summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/inc/swcrsr.hxx3
-rw-r--r--sw/source/core/crsr/crsrsh.cxx2
-rw-r--r--sw/source/core/crsr/findattr.cxx160
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 );