diff options
-rw-r--r-- | sw/inc/swcrsr.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/crsr/crsrsh.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/crsr/findattr.cxx | 160 |
3 files changed, 137 insertions, 28 deletions
diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx index cd07cafdf46a..1a5a65bf0661 100644 --- a/sw/inc/swcrsr.hxx +++ b/sw/inc/swcrsr.hxx @@ -129,7 +129,8 @@ public: bool& bCancel, FindRanges, const i18nutil::SearchOptions2* pSearchOpt, - const SfxItemSet* rReplSet = nullptr ); + const SfxItemSet* rReplSet = nullptr, + SwRootFrame const*const pLayout = nullptr); // UI versions bool IsStartEndSentence(bool bEnd, SwRootFrame const* pLayout) const; diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index f8e3bdd8a997..7324992e1702 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -3368,7 +3368,7 @@ sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet, m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed sal_uLong nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd, - bCancel, eRng, pSearchOpt, rReplSet ); + bCancel, eRng, pSearchOpt, rReplSet, GetLayout()); if( nRet ) UpdateCursor(); return nRet; diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx index 500d4628ad27..d50e0c41d496 100644 --- a/sw/source/core/crsr/findattr.cxx +++ b/sw/source/core/crsr/findattr.cxx @@ -41,6 +41,7 @@ #include <editsh.hxx> #include <ndtxt.hxx> #include <pamtyp.hxx> +#include <txtfrm.hxx> #include <swundo.hxx> #include <boost/optional.hpp> @@ -976,7 +977,8 @@ typedef bool (*FnSearchAttr)( const SwTextNode&, SwAttrCheckArr&, SwPaM& ); static bool FindAttrsImpl(SwPaM & rSearchPam, const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection const & fnMove, - const SwPaM & rRegion, bool bInReadOnly, bool bMoveFirst) + const SwPaM & rRegion, bool bInReadOnly, bool bMoveFirst, + SwRootFrame const*const pLayout) { std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion)); @@ -1010,22 +1012,100 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() ); } - while( nullptr != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) ) + while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout))) { + SwTextFrame const*const pFrame(pLayout && pNode->IsTextNode() + ? static_cast<SwTextFrame const*>(pNode->getLayoutFrame(pLayout)) + : nullptr); + assert(!pLayout || !pNode->IsTextNode() || pFrame); + // sw_redlinehide: it's apparently not possible to find break items + // with the UI, so checking one node is enough + SwContentNode const& rPropsNode(*(pFrame + ? pFrame->GetTextNodeForParaProps() + : pNode)); + if( aCmpArr.Count() ) { if( !pNode->IsTextNode() ) // CharAttr are only in text nodes continue; - if( (!aOtherSet.Count() || - lcl_Search( *pNode, aOtherSet, bNoColls )) && - (*fnSearch)( *pNode->GetTextNode(), aCmpArr, *pPam )) + if (aOtherSet.Count() && + !lcl_Search(rPropsNode, aOtherSet, bNoColls)) + { + continue; + } + sw::MergedPara const*const pMergedPara(pFrame ? pFrame->GetMergedPara() : nullptr); + if (pMergedPara) + { + SwPosition const& rStart(*pPam->Start()); + SwPosition const& rEnd(*pPam->End()); + // no extents? fall back to searching index 0 of propsnode + // to find its node items + if (pMergedPara->extents.empty()) + { + if (rStart.nNode.GetIndex() <= rPropsNode.GetIndex() + && rPropsNode.GetIndex() <= rEnd.nNode.GetIndex()) + { + SwPaM tmp(rPropsNode, 0, rPropsNode, 0); + bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, tmp); + if (bFound) + { + *pPam = tmp; + } + } + } + else + { + // iterate the extents, and intersect with input pPam: + // the found ranges should never include delete redlines + // so that subsequent Replace will not affect them + for (size_t i = 0; i < pMergedPara->extents.size(); ++i) + { + auto const rExtent(pMergedPara->extents[bSrchForward + ? i + : pMergedPara->extents.size() - i - 1]); + if (rExtent.pNode->GetIndex() < rStart.nNode.GetIndex() + || rEnd.nNode.GetIndex() < rExtent.pNode->GetIndex()) + { + continue; + } + sal_Int32 const nStart(rExtent.pNode == &rStart.nNode.GetNode() + ? rStart.nContent.GetIndex() + : 0); + if (rExtent.nEnd <= nStart) + { + continue; + } + sal_Int32 const nEnd(rExtent.pNode == &rEnd.nNode.GetNode() + ? rEnd.nContent.GetIndex() + : rExtent.pNode->Len()); + if (nEnd < rExtent.nStart + || (nStart != nEnd && nEnd == rExtent.nStart)) + { + continue; + } + SwPaM tmp(*rExtent.pNode, std::max(nStart, rExtent.nStart), + *rExtent.pNode, std::min(nEnd, rExtent.nEnd)); + tmp.Normalize(bSrchForward); + bFound = (*fnSearch)(*rExtent.pNode, aCmpArr, tmp); + if (bFound) + { + *pPam = tmp; + break; + } + } + } + } + else + { + bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, *pPam); + } + if (bFound) { // set to the values of the attribute rSearchPam.SetMark(); *rSearchPam.GetPoint() = *pPam->GetPoint(); *rSearchPam.GetMark() = *pPam->GetMark(); - bFound = true; break; } continue; // text attribute @@ -1035,22 +1115,39 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, continue; // no hard attribution, so check if node was asked for this attr before - if( !pNode->HasSwAttrSet() ) + // (as an optimisation) + if (!rPropsNode.HasSwAttrSet()) { - SwFormat* pTmpFormat = pNode->GetFormatColl(); + SwFormat* pTmpFormat = rPropsNode.GetFormatColl(); if( aFormatArr.find( pTmpFormat ) != aFormatArr.end() ) continue; // collection was requested earlier aFormatArr.insert( pTmpFormat ); } - if( lcl_Search( *pNode, aOtherSet, bNoColls )) + if (lcl_Search(rPropsNode, aOtherSet, bNoColls)) { // 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 - *rSearchPam.GetPoint() = *pPam->GetPoint(); - rSearchPam.SetMark(); - pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); + if (pFrame) + { + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.SetMark(); + *rSearchPam.GetMark() = pFrame->MapViewToModelPos( + TextFrameIndex(bSrchForward ? pFrame->GetText().getLength() : 0)); + } + else + { + *rSearchPam.GetPoint() = *pPam->GetPoint(); + rSearchPam.SetMark(); + if (bSrchForward) + { + pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); + } + else + { + pNode->MakeStartIndex( &rSearchPam.GetPoint()->nContent ); + } + } bFound = true; break; } @@ -1066,17 +1163,23 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, /// parameters for search for attributes struct SwFindParaAttr : public SwFindParas { - bool const bValue; + bool const m_bNoCollection; const SfxItemSet *pSet, *pReplSet; const i18nutil::SearchOptions2 *pSearchOpt; SwCursor& m_rCursor; + SwRootFrame const* m_pLayout; std::unique_ptr<utl::TextSearch> pSText; SwFindParaAttr( const SfxItemSet& rSet, bool bNoCollection, const i18nutil::SearchOptions2* pOpt, const SfxItemSet* pRSet, - SwCursor& rCursor ) - : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ), - pSearchOpt( pOpt ), m_rCursor( rCursor ) {} + SwCursor& rCursor, SwRootFrame const*const pLayout) + : m_bNoCollection(bNoCollection) + , pSet( &rSet ) + , pReplSet( pRSet ) + , pSearchOpt( pOpt ) + , m_rCursor(rCursor) + , m_pLayout(pLayout) + {} virtual ~SwFindParaAttr() {} @@ -1106,7 +1209,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, if( pSet->Count() ) // any attributes? { // first attributes - if (!FindAttrsImpl(aSrchPam, *pSet, bValue, fnMove, aRegion, bInReadOnly, bMoveFirst)) + if (!FindAttrsImpl(aSrchPam, *pSet, m_bNoCollection, fnMove, aRegion, bInReadOnly, bMoveFirst, m_pLayout)) return FIND_NOT_FOUND; bMoveFirst = true; @@ -1135,7 +1238,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, // TODO: searching for attributes in Outliner text?! // continue search in correct section (pTextRegion) - if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly, nullptr/*FIXME*/) && + if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly, m_pLayout) && *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) break; // found else if( !pSet->Count() ) @@ -1165,10 +1268,12 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, } std::unique_ptr<OUString> pRepl(bRegExp - ? sw::ReplaceBackReferences(*pSearchOpt, &rCursor, nullptr/*FIXME*/) + ? sw::ReplaceBackReferences(*pSearchOpt, &rCursor, m_pLayout) : nullptr); - m_rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange( - rCursor, pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp); + sw::ReplaceImpl(rCursor, + pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp, + *m_rCursor.GetDoc(), m_pLayout); + m_rCursor.SaveTableBoxContent( rCursor.GetPoint() ); if( bRegExp ) @@ -1192,7 +1297,8 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, // they are not in ReplaceSet if( !pSet->Count() ) { - rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(rCursor, *pReplSet); + rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet( + rCursor, *pReplSet, SetAttrMode::DEFAULT, m_pLayout); } else { @@ -1213,7 +1319,8 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, pItem = aIter.NextItem(); } aSet.Put( *pReplSet ); - rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(rCursor, aSet); + rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet( + rCursor, aSet, SetAttrMode::DEFAULT, m_pLayout); } return FIND_NO_RING; @@ -1233,7 +1340,8 @@ sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, const i18nutil::SearchOptions2* pSearchOpt, - const SfxItemSet* pReplSet ) + const SfxItemSet* pReplSet, + SwRootFrame const*const pLayout) { // switch off OLE-notifications SwDoc* pDoc = GetDoc(); @@ -1250,7 +1358,7 @@ sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, } SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt, - pReplSet, *this ); + pReplSet, *this, pLayout ); sal_uLong nRet = FindAll( aSwFindParaAttr, nStart, nEnd, eFndRngs, bCancel ); pDoc->SetOle2Link( aLnk ); |