Rebased ref, commits from common ancestor: commit 16eddb555444b4fb40319913b77455f3c741494f Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Dec 5 16:37:18 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:23:15 2018 +0100
temp? Change-Id: Ide2abf0c2ce054b75c917063a5d5aa8d13430426 diff --git a/sw/source/core/text/frmcrsr.cxx b/sw/source/core/text/frmcrsr.cxx index 7b6411163cb3..c756aedf4cd2 100644 --- a/sw/source/core/text/frmcrsr.cxx +++ b/sw/source/core/text/frmcrsr.cxx @@ -267,6 +267,7 @@ bool SwTextFrame::GetCharRect( SwRect& rOrig, const SwPosition &rPos, bool bGoOn = true; TextFrameIndex const nOffset = MapModelToViewPos(rPos); + assert(nOffset != TextFrameIndex(COMPLETE_STRING)); // not going to end well TextFrameIndex nNextOfst; do commit b6f42f452c964ce7f86a707273c5d800106087a3 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Dec 4 15:57:47 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:23:15 2018 +0100 sw_redlinehide_4b: FindText layout parameter Change-Id: I22c0adb40219bc53b5685e2e20bd55bfd65fd4a3 diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx index dd3b2720abf0..2a89054e02eb 100644 --- a/sw/inc/swcrsr.hxx +++ b/sw/inc/swcrsr.hxx @@ -116,7 +116,8 @@ public: SwDocPositions nStart, SwDocPositions nEnde, bool& bCancel, FindRanges, - bool bReplace = false ); + bool bReplace = false, + SwRootFrame const*const pLayout = nullptr); sal_uLong FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions nStart, SwDocPositions nEnde, bool& bCancel, diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 903902c50351..8c2f062611ab 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -3330,7 +3330,7 @@ sal_uLong SwCursorShell::FindText( const i18nutil::SearchOptions2& rSearchOpt, m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed sal_uLong nRet = m_pCurrentCursor->FindText(rSearchOpt, bSearchInNotes, eStart, eEnd, - bCancel, eRng, bReplace ); + bCancel, eRng, bReplace, GetLayout()); if( nRet || bCancel ) UpdateCursor(); return nRet; diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx index 62e42184fcae..5fe3a757e890 100644 --- a/sw/source/core/crsr/findtxt.cxx +++ b/sw/source/core/crsr/findtxt.cxx @@ -654,13 +654,19 @@ struct SwFindParaText : public SwFindParas { const i18nutil::SearchOptions2& m_rSearchOpt; SwCursor& m_rCursor; + SwRootFrame const* m_pLayout; utl::TextSearch m_aSText; bool const m_bReplace; bool const m_bSearchInNotes; - SwFindParaText( const i18nutil::SearchOptions2& rOpt, bool bSearchInNotes, bool bRepl, SwCursor& rCursor ) - : m_rSearchOpt( rOpt ), m_rCursor( rCursor ), m_aSText( utl::TextSearch::UpgradeToSearchOptions2( rOpt) ), - m_bReplace( bRepl ), m_bSearchInNotes( bSearchInNotes ) + SwFindParaText(const i18nutil::SearchOptions2& rOpt, bool bSearchInNotes, + bool bRepl, SwCursor& rCursor, SwRootFrame const*const pLayout) + : m_rSearchOpt( rOpt ) + , m_rCursor( rCursor ) + , m_pLayout(pLayout) + , m_aSText( utl::TextSearch::UpgradeToSearchOptions2(rOpt) ) + , m_bReplace( bRepl ) + , m_bSearchInNotes( bSearchInNotes ) {} virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly) override; virtual bool IsReplaceMode() const override; @@ -731,7 +737,8 @@ bool SwFindParaText::IsReplaceMode() const sal_uLong SwCursor::FindText( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions nStart, SwDocPositions nEnd, - bool& bCancel, FindRanges eFndRngs, bool bReplace ) + bool& bCancel, FindRanges eFndRngs, bool bReplace, + SwRootFrame const*const pLayout) { // switch off OLE-notifications SwDoc* pDoc = GetDoc(); @@ -747,7 +754,7 @@ sal_uLong SwCursor::FindText( const i18nutil::SearchOptions2& rSearchOpt, bool b bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE); if( bSearchSel ) eFndRngs = static_cast<FindRanges>(eFndRngs | FindRanges::InSel); - SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this ); + SwFindParaText aSwFindParaText(rSearchOpt, bSearchInNotes, bReplace, *this, pLayout); sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel ); pDoc->SetOle2Link( aLnk ); if( nRet && bReplace ) commit 8e8afe11b89400fdaf63152a6ccdbce13eb93464 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Dec 4 14:20:02 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:23:15 2018 +0100 sw: refactor a confusing thicket of overloads, all named Find() Also, some of these don't really make much sense as member functions of SwPaM, so make them plain functions instead. Also, some pointer parameters are never null, but there is code to handle that case in MakeRegion(); simplify that. Change-Id: I822e814b0cab14f7f31cfa33478ed15774405a61 diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx index 327674e3c547..84c83dd232a1 100644 --- a/sw/inc/crsrsh.hxx +++ b/sw/inc/crsrsh.hxx @@ -358,18 +358,18 @@ public: void MoveColumn( SwWhichColumn, SwPosColumn ); bool MoveRegion( SwWhichRegion, SwMoveFnCollection const & ); - sal_uLong Find( const i18nutil::SearchOptions2& rSearchOpt, + sal_uLong FindText( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, FindRanges eRng, bool bReplace = false ); - sal_uLong Find( const SwTextFormatColl& rFormatColl, + sal_uLong FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, FindRanges eRng, const SwTextFormatColl* pReplFormat ); - sal_uLong Find( const SfxItemSet& rSet, bool bNoCollections, + sal_uLong FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, FindRanges eRng, diff --git a/sw/inc/pam.hxx b/sw/inc/pam.hxx index c71667e30f50..c7bc752ff347 100644 --- a/sw/inc/pam.hxx +++ b/sw/inc/pam.hxx @@ -27,18 +27,9 @@ #include <iostream> -class SwFormat; -class SfxPoolItem; -class SfxItemSet; class SwDoc; class SwPaM; class Point; -namespace i18nutil { - struct SearchOptions2; -} -namespace utl { - class TextSearch; -} /// Marks a position in the document model. struct SAL_WARN_UNUSED SW_DLLPUBLIC SwPosition @@ -150,8 +141,6 @@ class SAL_WARN_UNUSED SW_DLLPUBLIC SwPaM : public sw::Ring<SwPaM> SwPosition * m_pMark; ///< points at either m_Bound1 or m_Bound2 bool m_bIsInFrontOfLabel; - std::unique_ptr<SwPaM> MakeRegion( SwMoveFnCollection const & fnMove, const SwPaM * pOrigRg ); - SwPaM(SwPaM const& rPaM) = delete; public: @@ -179,26 +168,6 @@ public: bool Move( SwMoveFnCollection const & fnMove = fnMoveForward, SwGoInDoc fnGo = GoInContent ); - /// Search. - bool Find( const i18nutil::SearchOptions2& rSearchOpt, - bool bSearchInNotes, - utl::TextSearch& rSText, - SwMoveFnCollection const & fnMove, - const SwPaM *pPam, bool bInReadOnly = false); - bool Find( const SwFormat& rFormat, - SwMoveFnCollection const & fnMove, - const SwPaM *pPam, bool bInReadOnly = false); - bool Find( const SfxPoolItem& rAttr, bool bValue, - SwMoveFnCollection const & fnMove, - const SwPaM *pPam, bool bInReadOnly = false ); - bool Find( const SfxItemSet& rAttr, bool bNoColls, - SwMoveFnCollection const & fnMove, - const SwPaM *pPam, bool bInReadOnly, bool bMoveFirst ); - - bool DoSearch( const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText, - SwMoveFnCollection const & fnMove, bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd, - sal_Int32 &nStart, sal_Int32 &nEnd, sal_Int32 nTextLen, SwNode* pNode, SwPaM* pPam); - bool IsInFrontOfLabel() const { return m_bIsInFrontOfLabel; } void SetInFrontOfLabel_( bool bNew ) { m_bIsInFrontOfLabel = bNew; } diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx index 5c9214dc2d00..dd3b2720abf0 100644 --- a/sw/inc/swcrsr.hxx +++ b/sw/inc/swcrsr.hxx @@ -23,6 +23,7 @@ #include "tblsel.hxx" #include "cshtyp.hxx" +class SfxItemSet; struct SwCursor_SavePos; namespace i18nutil { struct SearchOptions2; @@ -36,7 +37,7 @@ const int FIND_NO_RING = 2; struct SwFindParas { - virtual int Find( SwPaM*, SwMoveFnCollection const &, const SwPaM*, bool ) = 0; + virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM&, bool) = 0; virtual bool IsReplaceMode() const = 0; protected: @@ -75,8 +76,6 @@ class SW_DLLPUBLIC SwCursor : public SwPaM sal_uLong FindAll( SwFindParas& , SwDocPositions, SwDocPositions, FindRanges, bool& bCancel ); - using SwPaM::Find; - SwCursor(SwCursor const& rPaM) = delete; protected: @@ -112,18 +111,18 @@ public: SwMoveFnCollection const & MakeFindRange( SwDocPositions, SwDocPositions, SwPaM* ) const; - sal_uLong Find( const i18nutil::SearchOptions2& rSearchOpt, + sal_uLong FindText( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions nStart, SwDocPositions nEnde, bool& bCancel, FindRanges, bool bReplace = false ); - sal_uLong Find( const SwTextFormatColl& rFormatColl, + sal_uLong FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions nStart, SwDocPositions nEnde, bool& bCancel, FindRanges, const SwTextFormatColl* pReplFormat ); - sal_uLong Find( const SfxItemSet& rSet, bool bNoCollections, + sal_uLong FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions nStart, SwDocPositions nEnde, bool& bCancel, FindRanges, diff --git a/sw/qa/core/macros-test.cxx b/sw/qa/core/macros-test.cxx index 068001c7551b..82bdea2b4ca5 100644 --- a/sw/qa/core/macros-test.cxx +++ b/sw/qa/core/macros-test.cxx @@ -554,7 +554,7 @@ void SwMacrosTest::testFindReplace() '\\'); // find newline on 1st paragraph - bool bFound = pPaM->Find( + bool bFound = pPaM->FindText( opts, false, SwDocPositions::Curr, SwDocPositions::End, bCancel, FindRanges::InBody); CPPUNIT_ASSERT(bFound); CPPUNIT_ASSERT(pPaM->HasMark()); @@ -562,7 +562,7 @@ void SwMacrosTest::testFindReplace() // now do another Find, inside the selection from the first Find // opts.searchFlags = 71680; - bFound = pPaM->Find( + bFound = pPaM->FindText( opts, false, SwDocPositions::Curr, SwDocPositions::End, bCancel, FindRanges::InSel); CPPUNIT_ASSERT(bFound); CPPUNIT_ASSERT(pPaM->HasMark()); diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 7c59d0d70751..903902c50351 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -3317,7 +3317,7 @@ bool SwCursorShell::SelectHiddenRange() return bRet; } -sal_uLong SwCursorShell::Find( const i18nutil::SearchOptions2& rSearchOpt, +sal_uLong SwCursorShell::FindText( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, @@ -3329,14 +3329,14 @@ sal_uLong SwCursorShell::Find( const i18nutil::SearchOptions2& rSearchOpt, delete m_pTableCursor; m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - sal_uLong nRet = m_pCurrentCursor->Find( rSearchOpt, bSearchInNotes, eStart, eEnd, + sal_uLong nRet = m_pCurrentCursor->FindText(rSearchOpt, bSearchInNotes, eStart, eEnd, bCancel, eRng, bReplace ); if( nRet || bCancel ) UpdateCursor(); return nRet; } -sal_uLong SwCursorShell::Find( const SwTextFormatColl& rFormatColl, +sal_uLong SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, FindRanges eRng, @@ -3347,14 +3347,14 @@ sal_uLong SwCursorShell::Find( const SwTextFormatColl& rFormatColl, delete m_pTableCursor; m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - sal_uLong nRet = m_pCurrentCursor->Find( rFormatColl, eStart, eEnd, bCancel, eRng, + sal_uLong nRet = m_pCurrentCursor->FindFormat(rFormatColl, eStart, eEnd, bCancel, eRng, pReplFormat ); if( nRet ) UpdateCursor(); return nRet; } -sal_uLong SwCursorShell::Find( const SfxItemSet& rSet, +sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, @@ -3367,7 +3367,7 @@ sal_uLong SwCursorShell::Find( const SfxItemSet& rSet, delete m_pTableCursor; m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - sal_uLong nRet = m_pCurrentCursor->Find( rSet, bNoCollections, eStart, eEnd, + sal_uLong nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd, bCancel, eRng, pSearchOpt, rReplSet ); if( nRet ) UpdateCursor(); diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx index fa258e82ae53..4999c07d734b 100644 --- a/sw/source/core/crsr/findattr.cxx +++ b/sw/source/core/crsr/findattr.cxx @@ -887,14 +887,17 @@ static bool lcl_Search( const SwContentNode& rCNd, const SfxItemSet& rCmpSet, bo return true; // found } -bool SwPaM::Find( const SfxPoolItem& rAttr, bool bValue, SwMoveFnCollection const & fnMove, - const SwPaM *pRegion, bool bInReadOnly ) +namespace sw { + +bool FindAttrImpl(SwPaM & rSearchPam, + const SfxPoolItem& rAttr, bool bValue, SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly) { // determine which attribute is searched: const sal_uInt16 nWhich = rAttr.Which(); bool bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich); - std::unique_ptr<SwPaM> pPam(MakeRegion( fnMove, pRegion )); + std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion)); bool bFound = false; bool bFirst = true; @@ -927,9 +930,9 @@ bool SwPaM::Find( const SfxPoolItem& rAttr, bool bValue, SwMoveFnCollection cons lcl_Search( *pNode->GetTextNode(), *pPam, rAttr, fnMove, bValue )) { // set to the values of the attribute - SetMark(); - *GetPoint() = *pPam->GetPoint(); - *GetMark() = *pPam->GetMark(); + rSearchPam.SetMark(); + *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetMark() = *pPam->GetMark(); bFound = true; break; } @@ -952,9 +955,9 @@ bool SwPaM::Find( const SfxPoolItem& rAttr, bool bValue, SwMoveFnCollection cons // FORWARD: SPoint at the end, GetMark at the beginning of the node // BACKWARD: SPoint at the beginning, GetMark at the end of the node // always: incl. start and incl. end - *GetPoint() = *pPam->GetPoint(); - SetMark(); - pNode->MakeEndIndex( &GetPoint()->nContent ); + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.SetMark(); + pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); bFound = true; break; } @@ -962,17 +965,20 @@ bool SwPaM::Find( const SfxPoolItem& rAttr, bool bValue, SwMoveFnCollection cons // if backward search, switch point and mark if( bFound && !bSrchForward ) - Exchange(); + rSearchPam.Exchange(); return bFound; } +} // namespace sw + typedef bool (*FnSearchAttr)( const SwTextNode&, SwAttrCheckArr&, SwPaM& ); -bool SwPaM::Find( const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection const & fnMove, - const SwPaM *pRegion, bool bInReadOnly, bool bMoveFirst ) +static bool FindAttrsImpl(SwPaM & rSearchPam, + const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly, bool bMoveFirst) { - std::unique_ptr<SwPaM> pPam(MakeRegion( fnMove, pRegion )); + std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion)); bool bFound = false; bool bFirst = true; @@ -982,7 +988,7 @@ bool SwPaM::Find( const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection cons // check which text/char attributes are searched SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls ); - SfxItemSet aOtherSet( GetDoc()->GetAttrPool(), + SfxItemSet aOtherSet( rSearchPam.GetDoc()->GetAttrPool(), svl::Items<RES_PARATR_BEGIN, RES_GRFATR_END-1>{} ); aOtherSet.Put( rSet, false ); // got all invalid items @@ -1016,9 +1022,9 @@ bool SwPaM::Find( const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection cons (*fnSearch)( *pNode->GetTextNode(), aCmpArr, *pPam )) { // set to the values of the attribute - SetMark(); - *GetPoint() = *pPam->GetPoint(); - *GetMark() = *pPam->GetMark(); + rSearchPam.SetMark(); + *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetMark() = *pPam->GetMark(); bFound = true; break; } @@ -1042,9 +1048,9 @@ bool SwPaM::Find( const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection cons // FORWARD: SPoint at the end, GetMark at the beginning of the node // BACKWARD: SPoint at the beginning, GetMark at the end of the node // always: incl. start and incl. end - *GetPoint() = *pPam->GetPoint(); - SetMark(); - pNode->MakeEndIndex( &GetPoint()->nContent ); + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.SetMark(); + pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); bFound = true; break; } @@ -1052,7 +1058,7 @@ bool SwPaM::Find( const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection cons // if backward search, switch point and mark if( bFound && !bSrchForward ) - Exchange(); + rSearchPam.Exchange(); return bFound; } @@ -1074,12 +1080,12 @@ struct SwFindParaAttr : public SwFindParas virtual ~SwFindParaAttr() {} - virtual int Find( SwPaM* , SwMoveFnCollection const & , const SwPaM*, bool bInReadOnly ) override; + virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly) override; virtual bool IsReplaceMode() const override; }; -int SwFindParaAttr::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, const SwPaM* pRegion, - bool bInReadOnly ) +int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly) { // replace string (only if text given and search is not parameterized)? bool bReplaceText = pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() || @@ -1091,16 +1097,16 @@ int SwFindParaAttr::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, con // We search for attributes, should we search for text as well? { - SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() ); + SwPaM aRegion( *rRegion.GetMark(), *rRegion.GetPoint() ); SwPaM* pTextRegion = &aRegion; - SwPaM aSrchPam( *pCursor->GetPoint() ); + SwPaM aSrchPam( *rCursor.GetPoint() ); while( true ) { if( pSet->Count() ) // any attributes? { // first attributes - if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) ) + if (!FindAttrsImpl(aSrchPam, *pSet, bValue, fnMove, aRegion, bInReadOnly, bMoveFirst)) return FIND_NOT_FOUND; bMoveFirst = true; @@ -1129,7 +1135,7 @@ int SwFindParaAttr::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, con // TODO: searching for attributes in Outliner text?! // continue search in correct section (pTextRegion) - if( aSrchPam.Find( *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, pTextRegion, bInReadOnly ) && + if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly) && *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) break; // found else if( !pSet->Count() ) @@ -1138,41 +1144,41 @@ int SwFindParaAttr::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, con *aRegion.GetMark() = *aSrchPam.GetPoint(); } - *pCursor->GetPoint() = *aSrchPam.GetPoint(); - pCursor->SetMark(); - *pCursor->GetMark() = *aSrchPam.GetMark(); + *rCursor.GetPoint() = *aSrchPam.GetPoint(); + rCursor.SetMark(); + *rCursor.GetMark() = *aSrchPam.GetMark(); } if( bReplaceText ) { const bool bRegExp( SearchAlgorithms2::REGEXP == pSearchOpt->AlgorithmType2); - SwIndex& rSttCntIdx = pCursor->Start()->nContent; + SwIndex& rSttCntIdx = rCursor.Start()->nContent; const sal_Int32 nSttCnt = rSttCntIdx.GetIndex(); // add to shell-cursor-ring so that the regions will be moved eventually SwPaM* pPrevRing(nullptr); if( bRegExp ) { - pPrevRing = const_cast< SwPaM* >(pRegion)->GetPrev(); - const_cast< SwPaM* >(pRegion)->GetRingContainer().merge( m_rCursor.GetRingContainer() ); + pPrevRing = const_cast<SwPaM &>(rRegion).GetPrev(); + const_cast<SwPaM &>(rRegion).GetRingContainer().merge( m_rCursor.GetRingContainer() ); } std::unique_ptr<OUString> pRepl( bRegExp ? - ReplaceBackReferences( *pSearchOpt, pCursor ) : nullptr ); + ReplaceBackReferences(*pSearchOpt, &rCursor) : nullptr ); m_rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange( - *pCursor, pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp); - m_rCursor.SaveTableBoxContent( pCursor->GetPoint() ); + rCursor, pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp); + m_rCursor.SaveTableBoxContent( rCursor.GetPoint() ); if( bRegExp ) { // and remove region again SwPaM* p; - SwPaM* pNext = const_cast<SwPaM*>(pRegion); + SwPaM* pNext = const_cast<SwPaM*>(&rRegion); do { p = pNext; pNext = p->GetNext(); - p->MoveTo( const_cast<SwPaM*>(pRegion) ); + p->MoveTo(const_cast<SwPaM*>(&rRegion)); } while( p != pPrevRing ); } rSttCntIdx = nSttCnt; @@ -1185,7 +1191,7 @@ int SwFindParaAttr::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, con // they are not in ReplaceSet if( !pSet->Count() ) { - pCursor->GetDoc()->getIDocumentContentOperations().InsertItemSet( *pCursor, *pReplSet ); + rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(rCursor, *pReplSet); } else { @@ -1206,7 +1212,7 @@ int SwFindParaAttr::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, con pItem = aIter.NextItem(); } aSet.Put( *pReplSet ); - pCursor->GetDoc()->getIDocumentContentOperations().InsertItemSet( *pCursor, aSet ); + rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(rCursor, aSet); } return FIND_NO_RING; @@ -1222,7 +1228,7 @@ bool SwFindParaAttr::IsReplaceMode() const } /// search for attributes -sal_uLong SwCursor::Find( const SfxItemSet& rSet, bool bNoCollections, +sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, const i18nutil::SearchOptions2* pSearchOpt, diff --git a/sw/source/core/crsr/findcoll.cxx b/sw/source/core/crsr/findcoll.cxx index 6f59f3148750..b05fe2c5f742 100644 --- a/sw/source/core/crsr/findcoll.cxx +++ b/sw/source/core/crsr/findcoll.cxx @@ -34,22 +34,22 @@ struct SwFindParaFormatColl : public SwFindParas : pFormatColl( &rFormatColl ), pReplColl( pRpColl ) {} virtual ~SwFindParaFormatColl() {} - virtual int Find( SwPaM* , SwMoveFnCollection const & , const SwPaM*, bool bInReadOnly ) override; + virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly) override; virtual bool IsReplaceMode() const override; }; -int SwFindParaFormatColl::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, const SwPaM* pRegion, - bool bInReadOnly ) +int SwFindParaFormatColl::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly) { int nRet = FIND_FOUND; if( bInReadOnly && pReplColl ) bInReadOnly = false; - if( !pCursor->Find( *pFormatColl, fnMove, pRegion, bInReadOnly ) ) + if (!sw::FindFormatImpl(rCursor, *pFormatColl, fnMove, rRegion, bInReadOnly)) nRet = FIND_NOT_FOUND; else if( pReplColl ) { - pCursor->GetDoc()->SetTextFormatColl( *pCursor, const_cast<SwTextFormatColl*>(pReplColl) ); + rCursor.GetDoc()->SetTextFormatColl(rCursor, const_cast<SwTextFormatColl*>(pReplColl)); nRet = FIND_NO_RING; } return nRet; @@ -61,7 +61,7 @@ bool SwFindParaFormatColl::IsReplaceMode() const } /// search for Format-Collections -sal_uLong SwCursor::Find( const SwTextFormatColl& rFormatColl, SwDocPositions nStart, +sal_uLong SwCursor::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, const SwTextFormatColl* pReplFormatColl ) { diff --git a/sw/source/core/crsr/findfmt.cxx b/sw/source/core/crsr/findfmt.cxx index 2b16d0481ddd..f45759e5a0d6 100644 --- a/sw/source/core/crsr/findfmt.cxx +++ b/sw/source/core/crsr/findfmt.cxx @@ -22,12 +22,15 @@ #include <pam.hxx> #include <memory> -bool SwPaM::Find( const SwFormat& rFormat, SwMoveFnCollection const & fnMove, - const SwPaM *pRegion, bool bInReadOnly ) +namespace sw { + +bool FindFormatImpl(SwPaM & rSearchPam, + const SwFormat& rFormat, SwMoveFnCollection const & fnMove, + const SwPaM &rRegion, bool bInReadOnly) { bool bFound = false; const bool bSrchForward = &fnMove == &fnMoveForward; - std::unique_ptr<SwPaM> pPam(MakeRegion( fnMove, pRegion )); + std::unique_ptr<SwPaM> pPam(MakeRegion( fnMove, rRegion )); // if at beginning/end then move it out of the node if( bSrchForward @@ -53,14 +56,14 @@ bool SwPaM::Find( const SwFormat& rFormat, SwMoveFnCollection const & fnMove, // FORWARD: SPoint at the end, GetMark at the beginning of the node // BACKWARD: SPoint at the beginning, GetMark at the end of the node // always: incl. start and incl. end - *GetPoint() = *pPam->GetPoint(); - SetMark(); - pNode->MakeEndIndex( &GetPoint()->nContent ); - GetMark()->nContent = 0; + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.SetMark(); + pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); + rSearchPam.GetMark()->nContent = 0; // if backward search, switch point and mark if( !bSrchForward ) - Exchange(); + rSearchPam.Exchange(); bFound = true; break; @@ -69,4 +72,6 @@ bool SwPaM::Find( const SwFormat& rFormat, SwMoveFnCollection const & fnMove, return bFound; } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx index ad7ec024ef4a..62e42184fcae 100644 --- a/sw/source/core/crsr/findtxt.cxx +++ b/sw/source/core/crsr/findtxt.cxx @@ -226,14 +226,25 @@ static size_t GetPostIt(sal_Int32 aCount,const SwpHints *pHts) return aIndex; } -bool SwPaM::Find( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes , utl::TextSearch& rSText, - SwMoveFnCollection const & fnMove, const SwPaM * pRegion, - bool bInReadOnly ) +static bool DoSearch(SwPaM & rSearchPam, + const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText, + SwMoveFnCollection const & fnMove, + bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd, + sal_Int32 &nStart, sal_Int32 &nEnd, sal_Int32 nTextLen, SwNode* pNode, + SwPaM* pPam); + +namespace sw { + +bool FindTextImpl(SwPaM & rSearchPam, + const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, + utl::TextSearch& rSText, + SwMoveFnCollection const & fnMove, const SwPaM & rRegion, + bool bInReadOnly) { if( rSearchOpt.searchString.isEmpty() ) return false; - std::unique_ptr<SwPaM> pPam = MakeRegion( fnMove, pRegion ); + std::unique_ptr<SwPaM> pPam = sw::MakeRegion(fnMove, rRegion); const bool bSrchForward = &fnMove == &fnMoveForward; SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode; SwIndex& rContentIdx = pPam->GetPoint()->nContent; @@ -373,9 +384,9 @@ bool SwPaM::Find( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNote if (pPosition) { // Set search position to the shape's anchor point. - *GetPoint() = *pPosition; - GetPoint()->nContent.Assign(pPosition->nNode.GetNode().GetContentNode(), 0); - SetMark(); + *rSearchPam.GetPoint() = *pPosition; + rSearchPam.GetPoint()->nContent.Assign(pPosition->nNode.GetNode().GetContentNode(), 0); + rSearchPam.SetMark(); bFound = true; break; } @@ -433,7 +444,8 @@ bool SwPaM::Find( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNote nTextLen = nStartInside - nEndInside; } // search inside the text between a note - bFound = DoSearch( rSearchOpt, rSText, fnMove, bSrchForward, + bFound = DoSearch( rSearchPam, + rSearchOpt, rSText, fnMove, bSrchForward, bRegSearch, bChkEmptyPara, bChkParaEnd, nStartInside, nEndInside, nTextLen, pNode, pPam.get() ); @@ -462,7 +474,8 @@ bool SwPaM::Find( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNote { // if there is no SwPostItField inside or searching inside notes // is disabled, we search the whole length just like before - bFound = DoSearch( rSearchOpt, rSText, fnMove, bSrchForward, + bFound = DoSearch( rSearchPam, + rSearchOpt, rSText, fnMove, bSrchForward, bRegSearch, bChkEmptyPara, bChkParaEnd, nStart, nEnd, nTextLen, pNode, pPam.get() ); } @@ -473,7 +486,10 @@ bool SwPaM::Find( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNote return bFound; } -bool SwPaM::DoSearch( const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText, +} // namespace sw + +bool DoSearch(SwPaM & rSearchPam, + const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText, SwMoveFnCollection const & fnMove, bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd, sal_Int32 &nStart, sal_Int32 &nEnd, sal_Int32 nTextLen, @@ -564,8 +580,8 @@ bool SwPaM::DoSearch( const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearc nStart = nProxyStart; nEnd = nProxyEnd; // set section correctly - *GetPoint() = *pPam->GetPoint(); - SetMark(); + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.SetMark(); // adjust start and end if( !aFltArr.empty() ) @@ -590,12 +606,12 @@ bool SwPaM::DoSearch( const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearc // if backward search, switch positions temporarily if( !bSrchForward ) { std::swap(nStart, nEnd); } } - GetMark()->nContent = nStart; - GetPoint()->nContent = nEnd; + rSearchPam.GetMark()->nContent = nStart; + rSearchPam.GetPoint()->nContent = nEnd; // if backward search, switch point and mark if( !bSrchForward ) - Exchange(); + rSearchPam.Exchange(); bFound = true; break; } @@ -612,21 +628,21 @@ bool SwPaM::DoSearch( const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearc return true; else if( ( bChkEmptyPara && !nStart && !nTextLen ) || bChkParaEnd) { - *GetPoint() = *pPam->GetPoint(); - GetPoint()->nContent = bChkParaEnd ? nTextLen : 0; - SetMark(); + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.GetPoint()->nContent = bChkParaEnd ? nTextLen : 0; + rSearchPam.SetMark(); /* FIXME: this condition does not work for !bSrchForward backward * search, it probably never did. (pSttNd != &rNdIdx.GetNode()) * is never true in this case. */ if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) && - Move( fnMoveForward, GoInContent ) && - (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) && - 1 == std::abs( static_cast<int>( GetPoint()->nNode.GetIndex() - - GetMark()->nNode.GetIndex()) ) ) + rSearchPam.Move(fnMoveForward, GoInContent) && + (!bSrchForward || pSttNd != &rSearchPam.GetPoint()->nNode.GetNode()) && + 1 == std::abs(static_cast<int>(rSearchPam.GetPoint()->nNode.GetIndex() - + rSearchPam.GetMark()->nNode.GetIndex()))) { // if backward search, switch point and mark if( !bSrchForward ) - Exchange(); + rSearchPam.Exchange(); return true; } } @@ -646,7 +662,7 @@ struct SwFindParaText : public SwFindParas : m_rSearchOpt( rOpt ), m_rCursor( rCursor ), m_aSText( utl::TextSearch::UpgradeToSearchOptions2( rOpt) ), m_bReplace( bRepl ), m_bSearchInNotes( bSearchInNotes ) {} - virtual int Find( SwPaM* , SwMoveFnCollection const & , const SwPaM*, bool bInReadOnly ) override; + virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly) override; virtual bool IsReplaceMode() const override; virtual ~SwFindParaText(); }; @@ -655,54 +671,54 @@ SwFindParaText::~SwFindParaText() { } -int SwFindParaText::Find( SwPaM* pCursor, SwMoveFnCollection const & fnMove, - const SwPaM* pRegion, bool bInReadOnly ) +int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly) { if( bInReadOnly && m_bReplace ) bInReadOnly = false; - const bool bFnd = pCursor->Find( m_rSearchOpt, m_bSearchInNotes, m_aSText, fnMove, pRegion, bInReadOnly ); + const bool bFnd = sw::FindTextImpl(rCursor, m_rSearchOpt, m_bSearchInNotes, m_aSText, fnMove, rRegion, bInReadOnly); if( bFnd && m_bReplace ) // replace string { // use replace method in SwDoc const bool bRegExp(SearchAlgorithms2::REGEXP == m_rSearchOpt.AlgorithmType2); - SwIndex& rSttCntIdx = pCursor->Start()->nContent; + SwIndex& rSttCntIdx = rCursor.Start()->nContent; const sal_Int32 nSttCnt = rSttCntIdx.GetIndex(); // add to shell-cursor-ring so that the regions will be moved eventually SwPaM* pPrev(nullptr); if( bRegExp ) { - pPrev = const_cast<SwPaM*>(pRegion)->GetPrev(); - const_cast<SwPaM*>(pRegion)->GetRingContainer().merge( m_rCursor.GetRingContainer() ); + pPrev = const_cast<SwPaM&>(rRegion).GetPrev(); + const_cast<SwPaM&>(rRegion).GetRingContainer().merge( m_rCursor.GetRingContainer() ); } std::unique_ptr<OUString> pRepl( bRegExp - ? ReplaceBackReferences( m_rSearchOpt, pCursor ) : nullptr ); + ? ReplaceBackReferences(m_rSearchOpt, &rCursor) : nullptr ); bool const bReplaced = m_rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange( - *pCursor, pRepl ? *pRepl : m_rSearchOpt.replaceString, bRegExp); - m_rCursor.SaveTableBoxContent( pCursor->GetPoint() ); + rCursor, pRepl ? *pRepl : m_rSearchOpt.replaceString, bRegExp); + m_rCursor.SaveTableBoxContent( rCursor.GetPoint() ); if( bRegExp ) { // and remove region again SwPaM* p; - SwPaM* pNext(const_cast<SwPaM*>(pRegion)); + SwPaM* pNext(const_cast<SwPaM*>(&rRegion)); do { p = pNext; pNext = p->GetNext(); - p->MoveTo( const_cast<SwPaM*>(pRegion) ); + p->MoveTo(const_cast<SwPaM*>(&rRegion)); } while( p != pPrev ); } if (bRegExp && !bReplaced) { // fdo#80715 avoid infinite loop if join failed bool bRet = ((&fnMoveForward == &fnMove) ? &GoNextPara : &GoPrevPara) - (*pCursor, fnMove); + (rCursor, fnMove); (void) bRet; assert(bRet); // if join failed, next node must be SwTextNode } else - pCursor->Start()->nContent = nSttCnt; + rCursor.Start()->nContent = nSttCnt; return FIND_NO_RING; } return bFnd ? FIND_FOUND : FIND_NOT_FOUND; @@ -713,7 +729,7 @@ bool SwFindParaText::IsReplaceMode() const return m_bReplace; } -sal_uLong SwCursor::Find( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, +sal_uLong SwCursor::FindText( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, bool bReplace ) { diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx index 1c10bea10ac5..354adfbbfe37 100644 --- a/sw/source/core/crsr/pam.cxx +++ b/sw/source/core/crsr/pam.cxx @@ -481,6 +481,8 @@ bool SwPaM::Move( SwMoveFnCollection const & fnMove, SwGoInDoc fnGo ) return bRet; } +namespace sw { + /** make a new region Sets the first SwPaM onto the given SwPaM, or to the beginning or end of a @@ -491,21 +493,12 @@ bool SwPaM::Move( SwMoveFnCollection const & fnMove, SwGoInDoc fnGo ) @return Newly created range, in Ring with parameter pOrigRg. */ -std::unique_ptr<SwPaM> SwPaM::MakeRegion( SwMoveFnCollection const & fnMove, const SwPaM * pOrigRg ) +std::unique_ptr<SwPaM> MakeRegion(SwMoveFnCollection const & fnMove, + const SwPaM & rOrigRg) { std::unique_ptr<SwPaM> pPam; - if( pOrigRg == nullptr ) - { - pPam.reset(new SwPaM( *m_pPoint )); - pPam->SetMark(); // set beginning - pPam->Move( fnMove, GoInSection); // to beginning or end of a node - - // set SPoint onto its old position; set GetMark to the "end" - pPam->Exchange(); - } - else { - pPam.reset(new SwPaM(*pOrigRg, const_cast<SwPaM*>(pOrigRg))); // given search range + pPam.reset(new SwPaM(rOrigRg, const_cast<SwPaM*>(&rOrigRg))); // given search range // make sure that SPoint is on the "real" start position // FORWARD: SPoint always smaller than GetMark // BACKWARD: SPoint always bigger than GetMark @@ -515,6 +508,8 @@ std::unique_ptr<SwPaM> SwPaM::MakeRegion( SwMoveFnCollection const & fnMove, con return pPam; } +} // namespace sw + void SwPaM::Normalize(bool bPointFirst) { if (HasMark()) diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx index ad453fc2b8de..669a2d4f7f00 100644 --- a/sw/source/core/crsr/swcrsr.cxx +++ b/sw/source/core/crsr/swcrsr.cxx @@ -776,8 +776,8 @@ static sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurrentCurso // as long as found and not at same position while( *pSttPos <= *pEndPos && - 0 != ( nFndRet = rParas.Find( pCurrentCursor, fnMove, - &aRegion, bInReadOnly )) && + 0 != ( nFndRet = rParas.DoFind(*pCurrentCursor, fnMove, + aRegion, bInReadOnly)) && ( !pFndRing || *pFndRing->GetPoint() != *pCurrentCursor->GetPoint() || *pFndRing->GetMark() != *pCurrentCursor->GetMark() )) @@ -1063,9 +1063,8 @@ sal_uLong SwCursor::FindAll( SwFindParas& rParas, SwPosition aMarkPos( *GetMark() ); const bool bMarkPos = HasMark() && (eFndRngs == FindRanges::InBody); - if( 0 != (nFound = rParas.Find( this, fnMove, - &aRegion, bInReadOnly ) ? 1 : 0) - && bMarkPos ) + nFound = rParas.DoFind(*this, fnMove, aRegion, bInReadOnly) ? 1 : 0; + if (0 != nFound && bMarkPos) *GetMark() = aMarkPos; } diff --git a/sw/source/core/edit/edfld.cxx b/sw/source/core/edit/edfld.cxx index 57a4f77e43c1..da0a15e0199e 100644 --- a/sw/source/core/edit/edfld.cxx +++ b/sw/source/core/edit/edfld.cxx @@ -28,6 +28,7 @@ #include <docary.hxx> #include <fmtfld.hxx> #include <txtfld.hxx> +#include <pamtyp.hxx> #include <edimp.hxx> #include <dbfld.hxx> #include <expfld.hxx> @@ -260,9 +261,9 @@ void SwEditShell::UpdateFields( SwField &rField ) // Search for SwTextField ... while( bOkay && pCurStt->nContent != pCurEnd->nContent - && ( aPam.Find( aFieldHint, false, fnMoveForward, &aCurPam, true ) - || aPam.Find( aAnnotationFieldHint, false, fnMoveForward, &aCurPam ) - || aPam.Find( aInputFieldHint, false, fnMoveForward, &aCurPam ) ) ) + && (sw::FindAttrImpl(aPam, aFieldHint, false, fnMoveForward, aCurPam, true) + || sw::FindAttrImpl(aPam, aAnnotationFieldHint, false, fnMoveForward, aCurPam) + || sw::FindAttrImpl(aPam, aInputFieldHint, false, fnMoveForward, aCurPam))) { // if only one PaM has more than one field ... if( aPam.Start()->nContent != pCurStt->nContent ) diff --git a/sw/source/core/edit/edtox.cxx b/sw/source/core/edit/edtox.cxx index 2495fc8de524..762d33c25336 100644 --- a/sw/source/core/edit/edtox.cxx +++ b/sw/source/core/edit/edtox.cxx @@ -365,7 +365,7 @@ void SwEditShell::ApplyAutoMark() bool bCancel; // todo/mba: assuming that notes shouldn't be searched - sal_uLong nRet = Find( aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End, bCancel, + sal_uLong nRet = FindText(aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End, bCancel, FindRanges::InSelAll ); if(nRet) diff --git a/sw/source/core/inc/pamtyp.hxx b/sw/source/core/inc/pamtyp.hxx index 098d0941e38a..b8a81a090387 100644 --- a/sw/source/core/inc/pamtyp.hxx +++ b/sw/source/core/inc/pamtyp.hxx @@ -27,6 +27,15 @@ class SwpHints; struct SwPosition; class SwPaM; class SwTextAttr; +class SwFormat; +class SfxPoolItem; + +namespace i18nutil { + struct SearchOptions2; +} +namespace utl { + class TextSearch; +} // function prototypes for the move/find methods of SwPaM @@ -68,6 +77,29 @@ struct SwMoveFnCollection // function prototype for searching SwContentNode* GetNode( SwPaM&, bool&, SwMoveFnCollection const &, bool bInReadOnly = false ); +namespace sw { + + std::unique_ptr<SwPaM> MakeRegion(SwMoveFnCollection const & fnMove, + const SwPaM & rOrigRg); + + /// Search. + bool FindTextImpl(SwPaM & rSearchPam, + const i18nutil::SearchOptions2& rSearchOpt, + bool bSearchInNotes, + utl::TextSearch& rSText, + SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly = false); + bool FindFormatImpl(SwPaM & rSearchPam, + const SwFormat& rFormat, + SwMoveFnCollection const & fnMove, + const SwPaM & rRegion, bool bInReadOnly = false); + bool FindAttrImpl(SwPaM & rSearchPam, + const SfxPoolItem& rAttr, bool bValue, + SwMoveFnCollection const & fnMove, + const SwPaM & rPam, bool bInReadOnly = false); + +} // namespace sw + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/index/swuiidxmrk.cxx b/sw/source/ui/index/swuiidxmrk.cxx index e8240b7d2fc1..5c7c24131329 100644 --- a/sw/source/ui/index/swuiidxmrk.cxx +++ b/sw/source/ui/index/swuiidxmrk.cxx @@ -442,7 +442,7 @@ static void lcl_SelectSameStrings(SwWrtShell& rSh, bool bWordOnly, bool bCaseSen bool bCancel; //todo/mba: assuming that notes should not be searched - rSh.Find( aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End, bCancel, + rSh.FindText(aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End, bCancel, FindRanges::InSelAll | FindRanges::InBodyOnly ); } diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index 901cea6930a1..d1ac78b2392d 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -791,7 +791,7 @@ sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > pSearch->FillSearchItemSet(aSearch); pSearch->FillReplaceItemSet(aReplace); bool bCancel; - nResult = static_cast<sal_Int32>(pUnoCursor->Find( aSearch, !pSearch->m_bStyles, + nResult = static_cast<sal_Int32>(pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, eStart, eEnd, bCancel, static_cast<FindRanges>(eRanges), !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr, @@ -803,7 +803,7 @@ sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > SwTextFormatColl *pReplaceColl = lcl_GetParaStyle(pSearch->m_sReplaceText, pUnoCursor->GetDoc()); bool bCancel; - nResult = pUnoCursor->Find( *pSearchColl, + nResult = pUnoCursor->FindFormat(*pSearchColl, eStart, eEnd, bCancel, static_cast<FindRanges>(eRanges), pReplaceColl ); @@ -812,7 +812,7 @@ sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > { //todo/mba: assuming that notes should be omitted bool bCancel; - nResult = pUnoCursor->Find( aSearchOpt, false/*bSearchInNotes*/, + nResult = pUnoCursor->FindText(aSearchOpt, false/*bSearchInNotes*/, eStart, eEnd, bCancel, static_cast<FindRanges>(eRanges), true ); @@ -920,7 +920,7 @@ SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > RES_FRMATR_BEGIN, RES_FRMATR_END - 1>{}); pSearch->FillSearchItemSet(aSearch); bool bCancel; - nResult = static_cast<sal_Int32>(pUnoCursor->Find( aSearch, !pSearch->m_bStyles, + nResult = static_cast<sal_Int32>(pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, eStart, eEnd, bCancel, eRanges, !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr )); @@ -931,7 +931,7 @@ SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > //pSearch->sReplaceText SwTextFormatColl *pReplaceColl = nullptr; bool bCancel; - nResult = static_cast<sal_Int32>(pUnoCursor->Find( *pSearchColl, + nResult = static_cast<sal_Int32>(pUnoCursor->FindFormat(*pSearchColl, eStart, eEnd, bCancel, eRanges, pReplaceColl )); } @@ -939,7 +939,7 @@ SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > { //todo/mba: assuming that notes should be omitted bool bCancel; - nResult = static_cast<sal_Int32>(pUnoCursor->Find( aSearchOpt, false/*bSearchInNotes*/, + nResult = static_cast<sal_Int32>(pUnoCursor->FindText(aSearchOpt, false/*bSearchInNotes*/, eStart, eEnd, bCancel, eRanges )); } diff --git a/sw/source/uibase/wrtsh/select.cxx b/sw/source/uibase/wrtsh/select.cxx index 6459ef5284ff..4385627d7ac7 100644 --- a/sw/source/uibase/wrtsh/select.cxx +++ b/sw/source/uibase/wrtsh/select.cxx @@ -219,7 +219,7 @@ sal_uLong SwWrtShell::SearchPattern( const i18nutil::SearchOptions2& rSearchOpt, if(!(eFlags & FindRanges::InSel)) ClearMark(); bool bCancel = false; - sal_uLong nRet = Find( rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace ); + sal_uLong nRet = FindText(rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace); if(bCancel) { Undo(); @@ -243,7 +243,7 @@ sal_uLong SwWrtShell::SearchTempl( const OUString &rTempl, pReplaceColl = GetParaStyle(*pReplTempl, SwWrtShell::GETSTYLE_CREATESOME ); bool bCancel = false; - sal_uLong nRet = Find(pColl? *pColl: GetDfltTextFormatColl(), + sal_uLong nRet = FindFormat(pColl ? *pColl : GetDfltTextFormatColl(), eStt,eEnd, bCancel, eFlags, pReplaceColl); if(bCancel) { @@ -266,7 +266,7 @@ sal_uLong SwWrtShell::SearchAttr( const SfxItemSet& rFindSet, bool bNoColls, // Searching bool bCancel = false; - sal_uLong nRet = Find( rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet); + sal_uLong nRet = FindAttrs(rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet); if(bCancel) { commit 062b4762fcb410fe2c624de06975b673545407ab Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Dec 6 18:56:11 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:23:15 2018 +0100 sw_redlinehide_4b: fix CanSkipOverRedline() using wrong start position It must use the start position that GetNextRedln() returned, not the start of the end redline that GetNextRedln() returned, obviously. This triggers an assert in CanSkipOverRedline() in ooo31961-27.odt. Change-Id: I40b9647e0b8be9768e49047d309dd22470e658bd diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx index 8a3afaf5419c..298214fc9ea2 100644 --- a/sw/source/core/text/itratr.cxx +++ b/sw/source/core/text/itratr.cxx @@ -450,13 +450,14 @@ static void InsertCharAttrs(SfxPoolItem const** pAttrs, SfxItemSet const& rItems // if return false: portion ends at start of redline, indexes unchanged // if return true: portion end not known (past end of redline), indexes point to first hint past end of redline -static bool CanSkipOverRedline(SwRangeRedline const& rRedline, +static bool CanSkipOverRedline( + SwTextNode const& rStartNode, sal_Int32 const nStartRedline, + SwRangeRedline const& rRedline, size_t & rStartIndex, size_t & rEndIndex, bool const isTheAnswerYes) { size_t nStartIndex(rStartIndex); size_t nEndIndex(rEndIndex); - SwPosition const*const pRLStart(rRedline.Start()); SwPosition const*const pRLEnd(rRedline.End()); if (!pRLEnd->nNode.GetNode().IsTextNode() // if fully deleted... || pRLEnd->nContent == pRLEnd->nNode.GetNode().GetTextNode()->Len()) @@ -469,17 +470,16 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, // can't compare the SwFont that's stored somewhere, it doesn't have compare // operator, so try to recreate the situation with some temp arrays here SfxPoolItem const* activeCharAttrsStart[RES_CHRATR_END - RES_CHRATR_BEGIN + 1] = { nullptr, }; - if (pRLStart->nNode != pRLEnd->nNode) + if (&rStartNode != &pRLEnd->nNode.GetNode()) { // nodes' attributes are only needed if there are different nodes - InsertCharAttrs(activeCharAttrsStart, - pRLStart->nNode.GetNode().GetTextNode()->GetSwAttrSet()); + InsertCharAttrs(activeCharAttrsStart, rStartNode.GetSwAttrSet()); } - if (SwpHints *const pStartHints = pRLStart->nNode.GetNode().GetTextNode()->GetpSwpHints()) + if (SwpHints const*const pStartHints = rStartNode.GetpSwpHints()) { // check hint ends of hints that start before and end within - sal_Int32 const nRedlineEnd(pRLStart->nNode == pRLEnd->nNode + sal_Int32 const nRedlineEnd(&rStartNode == &pRLEnd->nNode.GetNode() ? pRLEnd->nContent.GetIndex() - : pRLStart->nNode.GetNode().GetTextNode()->Len()); + : rStartNode.Len()); for ( ; nEndIndex < pStartHints->Count(); ++nEndIndex) { SwTextAttr *const pAttr(pStartHints->GetSortedByEnd(nEndIndex)); @@ -491,7 +491,7 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, { break; } - if (pRLStart->nContent.GetIndex() <= pAttr->GetStart()) + if (nStartRedline <= pAttr->GetStart()) { continue; } @@ -542,7 +542,7 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, pRLEnd->nContent.GetIndex() < *pStartHints->GetSortedByEnd(nEndIndex)->GetAnyEnd()); } - if (pRLStart->nNode != pRLEnd->nNode) + if (&rStartNode != &pRLEnd->nNode.GetNode()) { nStartIndex = 0; nEndIndex = 0; @@ -554,7 +554,7 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, // ... and the charfmt must be *nominally* the same SfxPoolItem const* activeCharAttrsEnd[RES_CHRATR_END - RES_CHRATR_BEGIN + 1] = { nullptr, }; - if (pRLStart->nNode != pRLEnd->nNode) + if (&rStartNode != &pRLEnd->nNode.GetNode()) { // nodes' attributes are only needed if there are different nodes InsertCharAttrs(activeCharAttrsEnd, pRLEnd->nNode.GetNode().GetTextNode()->GetSwAttrSet()); @@ -564,8 +564,8 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, { // check hint starts of hints that start within and end after #ifndef NDEBUG - sal_Int32 const nRedlineStart(pRLStart->nNode == pRLEnd->nNode - ? pRLStart->nContent.GetIndex() + sal_Int32 const nRedlineStart(&rStartNode == &pRLEnd->nNode.GetNode() + ? nStartRedline : 0); #endif for ( ; nStartIndex < pEndHints->Count(); ++nStartIndex) @@ -629,7 +629,7 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, default: assert(false); } } - if (pRLStart->nNode != pRLEnd->nNode) + if (&rStartNode != &pRLEnd->nNode.GetNode()) { // need to iterate the nEndIndex forward too so the loop in the // caller can look for the right ends in the next iteration @@ -743,7 +743,7 @@ TextFrameIndex SwAttrIter::GetNextAttr() const assert(m_pMergedPara); assert(redline.second.first->End()->nNode.GetIndex() <= m_pMergedPara->pLastNode->GetIndex() || !redline.second.first->End()->nNode.GetNode().IsTextNode()); - if (CanSkipOverRedline(*redline.second.first, + if (CanSkipOverRedline(*pTextNode, redline.first, *redline.second.first, nStartIndex, nEndIndex, m_nPosition == redline.first)) { // if current position is start of the redline, must skip! nActRedline += redline.second.second; commit 4956318e4eed44f1f13ff1f1a242474fa6e8eb6f Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Dec 6 18:39:10 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:22:17 2018 +0100 sw_redlinehide_4b: fix pointer compares in SwRedlineItr::GetNextRedln() This is really stupid... Change-Id: I487ded0c0268ee9b7426e08109a9e8d447a0dfac diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx index 4f522ec3c171..96149b522c63 100644 --- a/sw/source/core/text/redlnitr.cxx +++ b/sw/source/core/text/redlnitr.cxx @@ -748,11 +748,11 @@ SwRedlineItr::GetNextRedln(sal_Int32 nNext, SwTextNode const*const pNode, { SwRangeRedline const*const pNext = m_rDoc.getIDocumentRedlineAccess().GetRedlineTable()[rAct + nSkipped]; - if (pRedline->End() < pNext->Start()) + if (*pRedline->End() < *pNext->Start()) { break; // done for now } - else if (pNext->Start() == pRedline->End() && + else if (*pNext->Start() == *pRedline->End() && pNext->GetType() == nsRedlineType_t::REDLINE_DELETE) { // consecutive delete - continue commit a696e85ca462b157033855e24db3f4ce912ebb7a Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Dec 6 12:32:20 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:04:15 2018 +0100 sw_redlinehide_4b: fix some problems with pathological table redlines As seen in ooo95711-1.odt, the ODF import may create a redline that starts on a SwTableNode - though i haven't been able to figure out how such an odd creature might arise from UI actions. Try to fix the obvious places so we don't crash easily; there might be more trouble elsewhere though with code that assumes that a redline starts on a SwTextNode. Change-Id: I8431c1416ac4503ff0209a946398656f1c28366d diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 71816cc7c20c..de795085681d 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -25,6 +25,7 @@ #include <fmtfld.hxx> #include <IDocumentUndoRedo.hxx> #include <IDocumentFieldsAccess.hxx> +#include <IDocumentLayoutAccess.hxx> #include <IDocumentState.hxx> #include <redline.hxx> #include <UndoRedline.hxx> @@ -143,28 +144,47 @@ void UpdateFramesForAddDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) // the AppendFootnote/RemoveFootnote will do it by itself! rDoc.GetFootnoteIdxs().UpdateFootnote(rPam.Start()->nNode); 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 (!pStartNode) { - if (pFrame->getRootFrame()->IsHideRedlines()) + SwTableNode *const pTableNode(rPam.Start()->nNode.GetNode().GetTableNode()); + assert(pTableNode); // known pathology + for (sal_uLong j = pTableNode->GetIndex(); j <= pTableNode->EndOfSectionIndex(); ++j) { - frames.push_back(pFrame); + pTableNode->GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::Hidden); + } + for (SwRootFrame const*const pLayout : rDoc.GetAllLayouts()) + { + if (pLayout->IsHideRedlines()) + { + pTableNode->DelFrames(pLayout); + } } } - for (SwTextFrame * pFrame : frames) + else { - 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)); - // 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); + 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)); + // 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); + } } // fields last - SwGetRefField::UpdateField requires up-to-date frames UpdateFieldsForRedline(rDoc.getIDocumentFieldsAccess()); // after footnotes @@ -178,55 +198,73 @@ void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) { rDoc.GetFootnoteIdxs().UpdateFootnote(rPam.Start()->nNode); 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 (!pStartNode) { - if (pFrame->getRootFrame()->IsHideRedlines()) + SwTableNode const*const pTableNode(rPam.Start()->nNode.GetNode().GetTableNode()); + assert(pTableNode); // known pathology + for (sal_uLong j = pTableNode->GetIndex(); j <= pTableNode->EndOfSectionIndex(); ++j) { - frames.push_back(pFrame); - layouts.insert(pFrame->getRootFrame()); + pTableNode->GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::None); + } + if (rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->IsHideRedlines()) + { + // note: this will also create frames for all currently hidden flys + // because it calls AppendAllObjs + ::MakeFrames(&rDoc, rPam.Start()->nNode, rPam.End()->nNode); } } - if (frames.empty()) - { - return; - } - if (rPam.GetPoint()->nNode != rPam.GetMark()->nNode) + else { - // first, call CheckParaRedlineMerge on the first paragraph, - // to init flag on new merge range (if any) + 1st node post the merge - for (SwTextFrame * pFrame : frames) + 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 (auto const pMergedPara = pFrame->GetMergedPara()) + if (pFrame->getRootFrame()->IsHideRedlines()) { - 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)); + frames.push_back(pFrame); + layouts.insert(pFrame->getRootFrame()); } } - // 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 - 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) + if (frames.empty()) + { + return; + } + if (rPam.GetPoint()->nNode != rPam.GetMark()->nNode) { - AppendAllObjs(rDoc.GetSpzFrameFormats(), pLayout); + // first, call CheckParaRedlineMerge on the first paragraph, + // to init flag on new merge range (if any) + 1st node post the merge + 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 + 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) + { + AppendAllObjs(rDoc.GetSpzFrameFormats(), pLayout); + } } } // fields last - SwGetRefField::UpdateField requires up-to-date frames diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx index 852cd0c8ff48..63be0e158b7d 100644 --- a/sw/source/core/doc/docnum.cxx +++ b/sw/source/core/doc/docnum.cxx @@ -1440,11 +1440,23 @@ namespace sw { void GotoPrevLayoutTextFrame(SwNodeIndex & rIndex, SwRootFrame const*const pLayout) { - if (pLayout && pLayout->IsHideRedlines() - && rIndex.GetNode().IsTextNode() - && rIndex.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None) + if (pLayout && pLayout->IsHideRedlines()) { - rIndex = *static_cast<SwTextFrame*>(rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))->GetMergedPara()->pFirstNode; + if (rIndex.GetNode().IsTextNode()) + { + if (rIndex.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None) + { + rIndex = *static_cast<SwTextFrame*>(rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))->GetMergedPara()->pFirstNode; + } + } + else if (rIndex.GetNode().IsEndNode()) + { + if (rIndex.GetNode().GetRedlineMergeFlag() == SwNode::Merge::Hidden) + { + rIndex = *rIndex.GetNode().StartOfSectionNode(); + assert(rIndex.GetNode().IsTableNode()); + } + } } --rIndex; if (pLayout && rIndex.GetNode().IsTextNode()) @@ -1456,11 +1468,22 @@ GotoPrevLayoutTextFrame(SwNodeIndex & rIndex, SwRootFrame const*const pLayout) void GotoNextLayoutTextFrame(SwNodeIndex & rIndex, SwRootFrame const*const pLayout) { - if (pLayout && pLayout->IsHideRedlines() - && rIndex.GetNode().IsTextNode() - && rIndex.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None) + if (pLayout && pLayout->IsHideRedlines()) { - rIndex = *static_cast<SwTextFrame*>(rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))->GetMergedPara()->pLastNode; + if (rIndex.GetNode().IsTextNode()) + { + if (rIndex.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None) + { + rIndex = *static_cast<SwTextFrame*>(rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))->GetMergedPara()->pLastNode; + } + } + else if (rIndex.GetNode().IsTableNode()) + { + if (rIndex.GetNode().GetRedlineMergeFlag() == SwNode::Merge::Hidden) + { + rIndex = *rIndex.GetNode().EndOfSectionNode(); + } + } } ++rIndex; if (pLayout && rIndex.GetNode().IsTextNode()) diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index f1c11bb23103..dda68bc72473 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -59,6 +59,7 @@ #include <laycache.hxx> #include <rootfrm.hxx> #include <paratr.hxx> +#include <redline.hxx> #include <sortedobjs.hxx> #include <objectformatter.hxx> #include <calbck.hxx> @@ -1446,6 +1447,31 @@ void InsertCnt_( SwLayoutFrame *pLay, SwDoc *pDoc, else if ( pNd->IsTableNode() ) { //Should we have encountered a table? SwTableNode *pTableNode = static_cast<SwTableNode*>(pNd); + if (pLayout->IsHideRedlines()) + { + // in the problematic case, there can be only 1 redline... + SwPosition const tmp(*pNd); + SwRangeRedline const*const pRedline( + pDoc->getIDocumentRedlineAccess().GetRedline(tmp, nullptr)); + // pathology: redline that starts on a TableNode; cannot + // be created in UI but by import filters... + if (pRedline + && pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE + && &pRedline->Start()->nNode.GetNode() == pNd) + { + SAL_WARN("sw.pageframe", "skipping table frame creation on bizarre redline"); + while (true) + { + pTableNode->GetNodes()[nIndex]->SetRedlineMergeFlag(SwNode::Merge::Hidden); + if (nIndex == pTableNode->EndOfSectionIndex()) + { + break; + } + ++nIndex; + } + continue; + } + } if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines()) { assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden); diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index aa2cd56249f6..9cebf22c8229 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4349,6 +4349,24 @@ static void UnHideRedlines(SwRootFrame & rLayout, rTextNode.NumRuleChgd(); } } + else if (rNode.IsTableNode() && rLayout.IsHideRedlines()) + { + SwPosition const tmp(rNode); + SwRangeRedline const*const pRedline( + rLayout.GetFormat()->GetDoc()->getIDocumentRedlineAccess().GetRedline(tmp, nullptr)); + // pathology: redline that starts on a TableNode; cannot + // be created in UI but by import filters... + if (pRedline + && pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE + && &pRedline->Start()->nNode.GetNode() == &rNode) + { + for (sal_uLong j = rNode.GetIndex(); j <= rNode.EndOfSectionIndex(); ++j) + { + rNode.GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::Hidden); + } + rNode.GetTableNode()->DelFrames(&rLayout); + } + } if (!rNode.IsCreateFrameWhenHidingRedlines()) { if (rLayout.IsHideRedlines()) diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx index 0b92335a7e97..4f522ec3c171 100644 --- a/sw/source/core/text/redlnitr.cxx +++ b/sw/source/core/text/redlnitr.cxx @@ -82,6 +82,11 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode, assert(IDocumentRedlineAccess::IsHideChanges(rIDRA.GetRedlineFlags())); continue; } + if (pStart->nNode.GetNode().IsTableNode()) + { + assert(&pEnd->nNode.GetNode() == &rTextNode && pEnd->nContent.GetIndex() == 0); + continue; // known pathology, ignore it + } bHaveRedlines = true; assert(pNode != &rTextNode || &pStart->nNode.GetNode() == &rTextNode); // detect calls with wrong start node if (pStart->nContent != nLastEnd) // not 0 so we eliminate adjacent deletes commit 4f37f275015ee0c433efc09d8615d997f91d8a92 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Dec 5 16:49:34 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:04:15 2018 +0100 sw_redlinehide_4b: fix crash in CanSkipOverRedline() This was another IsDelLastPara() redline in ooo27109-1.sxw. Change-Id: I1f4198a4bcbed7bdd52991af3cb3322ebacc65fe diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx index 827a29e8538f..8a3afaf5419c 100644 --- a/sw/source/core/text/itratr.cxx +++ b/sw/source/core/text/itratr.cxx @@ -458,7 +458,8 @@ static bool CanSkipOverRedline(SwRangeRedline const& rRedline, size_t nEndIndex(rEndIndex); SwPosition const*const pRLStart(rRedline.Start()); SwPosition const*const pRLEnd(rRedline.End()); - if (pRLEnd->nContent == pRLEnd->nNode.GetNode().GetTextNode()->Len()) + if (!pRLEnd->nNode.GetNode().IsTextNode() // if fully deleted... + || pRLEnd->nContent == pRLEnd->nNode.GetNode().GetTextNode()->Len()) { // shortcut: nothing follows redline // current state is end state commit a12d8a0a77ad3a6e99857b706e161f4d62c7cb39 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Dec 5 16:26:22 2018 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Thu Dec 6 19:03:19 2018 +0100 sw_redlinehide_4b: fix wrong handling of IsDelLastPara() redlines CheckParaRedlineMerge(): Fully deleted SwTextNode followed by a table, as seen in ooo81405-1.odt and ooo31961-16.sxw. Also avoid creating an extent for the node in which it starts, e.g. ooo31961-27.odt. Change-Id: I2a7d935a9cedcb66aeaa9dce418b1fab758f1784 diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx index 3bd7075cb9ed..827a29e8538f 100644 --- a/sw/source/core/text/itratr.cxx +++ b/sw/source/core/text/itratr.cxx @@ -740,6 +740,8 @@ TextFrameIndex SwAttrIter::GetNextAttr() const if (redline.second.first) { assert(m_pMergedPara); + assert(redline.second.first->End()->nNode.GetIndex() <= m_pMergedPara->pLastNode->GetIndex() + || !redline.second.first->End()->nNode.GetNode().IsTextNode()); if (CanSkipOverRedline(*redline.second.first, nStartIndex, nEndIndex, m_nPosition == redline.first)) { // if current position is start of the redline, must skip! diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx index e73a478ce737..0b92335a7e97 100644 --- a/sw/source/core/text/redlnitr.cxx +++ b/sw/source/core/text/redlnitr.cxx @@ -124,12 +124,32 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode, } pTmp->SetRedlineMergeFlag(SwNode::Merge::Hidden); } - pNode = pEnd->nNode.GetNode().GetTextNode(); - assert(pNode); - nodes.push_back(pNode); - pNode->SetRedlineMergeFlag(SwNode::Merge::NonFirst); + // note: in DelLastPara() case, the end node is not actually merged + // and is likely a SwTableNode! + if (!pEnd->nNode.GetNode().IsTextNode()) + { + assert(pEnd->nNode != pStart->nNode); + // must set pNode too because it will mark the last node + pNode = nodes.back(); + assert(pNode == pNode->GetNodes()[pEnd->nNode.GetIndex() - 1]); + if (pNode != &rTextNode) + { // something might depend on last merged one being NonFirst? + pNode->SetRedlineMergeFlag(SwNode::Merge::NonFirst); + } + nLastEnd = pNode->Len(); + } + else + { + pNode = pEnd->nNode.GetNode().GetTextNode(); + nodes.push_back(pNode); + pNode->SetRedlineMergeFlag(SwNode::Merge::NonFirst); + nLastEnd = pEnd->nContent.GetIndex(); + } + } + else + { + nLastEnd = pEnd->nContent.GetIndex(); } - nLastEnd = pEnd->nContent.GetIndex(); } if (pNode == &rTextNode) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits