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.cxx2
-rw-r--r--sw/source/core/crsr/findtxt.cxx544
-rw-r--r--sw/source/core/crsr/pam.cxx21
-rw-r--r--sw/source/core/inc/pamtyp.hxx7
6 files changed, 419 insertions, 160 deletions
diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index 2ae2f58924d2..cd07cafdf46a 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -117,7 +117,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 eb5b21b84669..f8e3bdd8a997 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -3330,7 +3330,7 @@ sal_uLong SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt,
m_pTableCursor = nullptr;
SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
sal_uLong nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd,
- bCancel, eRng, bReplace );
+ bCancel, eRng, bReplace, GetLayout());
if( nRet || bCancel )
UpdateCursor();
return nRet;
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
index 4999c07d734b..9da44ada4dfe 100644
--- a/sw/source/core/crsr/findattr.cxx
+++ b/sw/source/core/crsr/findattr.cxx
@@ -1135,7 +1135,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) &&
+ if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly, nullptr/*FIXME*/) &&
*aSrchPam.GetMark() != *aSrchPam.GetPoint() )
break; // found
else if( !pSet->Count() )
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
index b70a2219d0b3..c37df0a1fd69 100644
--- a/sw/source/core/crsr/findtxt.cxx
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -34,6 +34,7 @@
#include <fmtfld.hxx>
#include <txtatr.hxx>
#include <txtfld.hxx>
+#include <txtfrm.hxx>
#include <swcrsr.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
@@ -53,59 +54,198 @@
using namespace ::com::sun::star;
using namespace util;
+/// because the Find may be called on the View or the Model, we need an index
+/// afflicted by multiple personality disorder
+struct AmbiguousIndex
+{
+private:
+ sal_Int32 m_value;
+
+#ifndef NDEBUG
+ enum class tags : char { Any, Frame, Model };
+ tags m_tag;
+#endif
+
+public:
+ AmbiguousIndex() : m_value(-1)
+#ifndef NDEBUG
+ , m_tag(tags::Any)
+#endif
+ {}
+ explicit AmbiguousIndex(sal_Int32 const value
+#ifndef NDEBUG
+ , tags const tag
+#endif
+ ) : m_value(value)
+#ifndef NDEBUG
+ , m_tag(tag)
+#endif
+ {}
+
+ sal_Int32 & GetAnyIndex() { return m_value; } ///< for arithmetic
+ sal_Int32 const& GetAnyIndex() const { return m_value; } ///< for arithmetic
+ TextFrameIndex GetFrameIndex() const
+ {
+ assert(m_tag != tags::Model);
+ return TextFrameIndex(m_value);
+ }
+ sal_Int32 GetModelIndex() const
+ {
+ assert(m_tag != tags::Frame);
+ return m_value;
+ }
+ void SetFrameIndex(TextFrameIndex const value)
+ {
+#ifndef NDEBUG
+ m_tag = tags::Frame;
+#endif
+ m_value = sal_Int32(value);
+ }
+ void SetModelIndex(sal_Int32 const value)
+ {
+#ifndef NDEBUG
+ m_tag = tags::Model;
+#endif
+ m_value = value;
+ }
+
+ bool operator ==(AmbiguousIndex const& rOther) const
+ {
+ assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+ return m_value == rOther.m_value;
+ }
+ bool operator <=(AmbiguousIndex const& rOther) const
+ {
+ assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+ return m_value <= rOther.m_value;
+ }
+ bool operator < (AmbiguousIndex const& rOther) const
+ {
+ assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+ return m_value < rOther.m_value;
+ }
+ AmbiguousIndex operator - (AmbiguousIndex const& rOther) const
+ {
+ assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+ return AmbiguousIndex(m_value - rOther.m_value
+#ifndef NDEBUG
+ , std::max(m_tag, rOther.m_tag)
+#endif
+ );
+ }
+};
+
+class MaybeMergedIter
+{
+ boost::optional<sw::MergedAttrIter> m_oMergedIter;
+ SwTextNode const*const m_pNode;
+ size_t m_HintIndex;
+
+public:
+ MaybeMergedIter(SwTextFrame const*const pFrame, SwTextNode const*const pNode)
+ : m_pNode(pNode)
+ , m_HintIndex(0)
+ {
+ if (pFrame)
+ {
+ m_oMergedIter.emplace(*pFrame);
+ }
+ }
+
+ SwTextAttr const* NextAttr(SwTextNode const*& rpNode)
+ {
+ if (m_oMergedIter)
+ {
+ return m_oMergedIter->NextAttr(&rpNode);
+ }
+ if (SwpHints const*const pHints = m_pNode->GetpSwpHints())
+ {
+ if (m_HintIndex < pHints->Count())
+ {
+ rpNode = m_pNode;
+ return pHints->Get(m_HintIndex++);
+ }
+ }
+ return nullptr;
+ }
+};
+
static OUString
-lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
- std::vector<sal_Int32> &rArr, bool const bRemoveSoftHyphen, bool const bRemoveCommentAnchors)
+lcl_CleanStr(const SwTextNode& rNd,
+ SwTextFrame const*const pFrame,
+ SwRootFrame const*const pLayout,
+ AmbiguousIndex const nStart, AmbiguousIndex & rEnd,
+ std::vector<AmbiguousIndex> &rArr,
+ bool const bRemoveSoftHyphen, bool const bRemoveCommentAnchors)
{
- OUStringBuffer buf(rNd.GetText());
+ OUStringBuffer buf(pLayout ? pFrame->GetText() : rNd.GetText());
rArr.clear();
- const SwpHints *pHts = rNd.GetpSwpHints();
+ MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rNd);
- size_t n = 0;
- sal_Int32 nSoftHyphen = nStart;
- sal_Int32 nHintStart = -1;
+ AmbiguousIndex nSoftHyphen = nStart;
+ AmbiguousIndex nHintStart;
bool bNewHint = true;
bool bNewSoftHyphen = true;
- const sal_Int32 nEnd = rEnd;
- std::vector<sal_Int32> aReplaced;
+ const AmbiguousIndex nEnd = rEnd;
+ std::vector<AmbiguousIndex> aReplaced;
+ SwTextNode const* pNextHintNode(nullptr);
+ SwTextAttr const* pNextHint(iter.NextAttr(pNextHintNode));
do
{
if ( bNewHint )
- nHintStart = pHts && n < pHts->Count() ?
- pHts->Get(n)->GetStart() :
- -1;
+ {
+ if (pLayout)
+ {
+ nHintStart.SetFrameIndex(pNextHint
+ ? pFrame->MapModelToView(pNextHintNode, pNextHint->GetStart())
+ : TextFrameIndex(-1));
+ }
+ else
+ {
+ nHintStart.SetModelIndex(pNextHint ? pNextHint->GetStart() : -1);
+ }
+ }
if ( bNewSoftHyphen )
{
- nSoftHyphen = bRemoveSoftHyphen
- ? rNd.GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen)
- : -1;
+ if (pLayout)
+ {
+ nSoftHyphen.SetFrameIndex(TextFrameIndex(bRemoveSoftHyphen
+ ? pFrame->GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen.GetAnyIndex())
+ : -1));
+ }
+ else
+ {
+ nSoftHyphen.SetModelIndex(bRemoveSoftHyphen
+ ? rNd.GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen.GetAnyIndex())
+ : -1);
+ }
}
bNewHint = false;
bNewSoftHyphen = false;
- sal_Int32 nStt = 0;
+ AmbiguousIndex nStt;
// Check if next stop is a hint.
- if ( nHintStart>=0
- && (-1 == nSoftHyphen || nHintStart < nSoftHyphen)
+ if (0 <= nHintStart.GetAnyIndex()
+ && (-1 == nSoftHyphen.GetAnyIndex() || nHintStart < nSoftHyphen)
&& nHintStart < nEnd )
{
nStt = nHintStart;
bNewHint = true;
}
// Check if next stop is a soft hyphen.
- else if ( -1 != nSoftHyphen
- && (-1 == nHintStart || nSoftHyphen < nHintStart)
+ else if ( -1 != nSoftHyphen.GetAnyIndex()
+ && (-1 == nHintStart.GetAnyIndex() || nSoftHyphen < nHintStart)
&& nSoftHyphen < nEnd)
{
nStt = nSoftHyphen;
bNewSoftHyphen = true;
}
// If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
- else if (-1 != nSoftHyphen && nSoftHyphen == nHintStart)
+ else if (-1 != nSoftHyphen.GetAnyIndex() && nSoftHyphen == nHintStart)
{
nStt = nSoftHyphen;
bNewHint = true;
@@ -114,14 +254,14 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
else
break;
- const sal_Int32 nCurrent = nStt - rArr.size();
+ AmbiguousIndex nCurrent(nStt);
+ nCurrent.GetAnyIndex() -= rArr.size();
if ( bNewHint )
{
- const SwTextAttr* pHt = pHts->Get(n);
- if ( pHt->HasDummyChar() && (nStt >= nStart) )
+ if (pNextHint->HasDummyChar() && (nStart <= nStt))
{
- switch( pHt->Which() )
+ switch (pNextHint->Which())
{
case RES_TXTATR_FLYCNT:
case RES_TXTATR_FTN:
@@ -138,19 +278,19 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
// simply removed if first. If at the end, we keep the
// replacement and remove afterwards all at a string's
// end (might be normal 0x7f).
- const bool bEmpty = pHt->Which() != RES_TXTATR_FIELD
- || (static_txtattr_cast<SwTextField const*>(pHt)->GetFormatField().GetField()->ExpandField(true, nullptr).isEmpty());
+ const bool bEmpty = pNextHint->Which() != RES_TXTATR_FIELD
+ || (static_txtattr_cast<SwTextField const*>(pNextHint)->GetFormatField().GetField()->ExpandField(true, pLayout).isEmpty());
if ( bEmpty && nStart == nCurrent )
{
rArr.push_back( nCurrent );
- --rEnd;
- buf.remove(nCurrent, 1);
+ --rEnd.GetAnyIndex();
+ buf.remove(nCurrent.GetAnyIndex(), 1);
}
else
{
if ( bEmpty )
aReplaced.push_back( nCurrent );
- buf[nCurrent] = '\x7f';
+ buf[nCurrent.GetAnyIndex()] = '\x7f';
}
}
break;
@@ -159,8 +299,8 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
if( bRemoveCommentAnchors )
{
rArr.push_back( nCurrent );
- --rEnd;
- buf.remove( nCurrent, 1 );
+ --rEnd.GetAnyIndex();
+ buf.remove( nCurrent.GetAnyIndex(), 1 );
}
}
break;
@@ -169,69 +309,40 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
break;
}
}
- ++n;
+ pNextHint = iter.NextAttr(pNextHintNode);
}
if ( bNewSoftHyphen )
{
rArr.push_back( nCurrent );
- --rEnd;
- buf.remove(nCurrent, 1);
- ++nSoftHyphen;
+ --rEnd.GetAnyIndex();
+ buf.remove(nCurrent.GetAnyIndex(), 1);
+ ++nSoftHyphen.GetAnyIndex();
}
}
while ( true );
- for( std::vector<sal_Int32>::size_type i = aReplaced.size(); i; )
+ for (auto i = aReplaced.size(); i; )
{
- const sal_Int32 nTmp = aReplaced[ --i ];
- if (nTmp == buf.getLength() - 1)
+ const AmbiguousIndex nTmp = aReplaced[ --i ];
+ if (nTmp.GetAnyIndex() == buf.getLength() - 1)
{
- buf.truncate(nTmp);
+ buf.truncate(nTmp.GetAnyIndex());
rArr.push_back( nTmp );
- --rEnd;
+ --rEnd.GetAnyIndex();
}
}
return buf.makeStringAndClear();
}
-// skip all non SwPostIts inside the array
-static size_t GetPostIt(sal_Int32 aCount,const SwpHints *pHts)
-{
- size_t aIndex = 0;
- while (aCount)
- {
- for (size_t i = 0; i < pHts->Count(); ++i )
- {
- aIndex++;
- const SwTextAttr* pTextAttr = pHts->Get(i);
- if ( pTextAttr->Which() == RES_TXTATR_ANNOTATION )
- {
- aCount--;
- if (!aCount)
- break;
- }
- }
- }
- // throw away all following non postits
- for( size_t i = aIndex; i < pHts->Count(); ++i )
- {
- const SwTextAttr* pTextAttr = pHts->Get(i);
- if ( pTextAttr->Which() == RES_TXTATR_ANNOTATION )
- break;
- else
- aIndex++;
- }
- return aIndex;
-}
-
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);
+ AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex nTextLen,
+ SwTextNode const* pNode, SwTextFrame const* pTextFrame,
+ SwRootFrame const* pLayout, SwPaM* pPam);
namespace sw {
@@ -239,7 +350,7 @@ bool FindTextImpl(SwPaM & rSearchPam,
const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
utl::TextSearch& rSText,
SwMoveFnCollection const & fnMove, const SwPaM & rRegion,
- bool bInReadOnly)
+ bool bInReadOnly, SwRootFrame const*const pLayout)
{
if( rSearchOpt.searchString.isEmpty() )
return false;
@@ -266,47 +377,95 @@ bool FindTextImpl(SwPaM & rSearchPam,
aSearchItem.SetBackward(!bSrchForward);
// LanguageType eLastLang = 0;
- while( nullptr != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
+ while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout)))
{
if( pNode->IsTextNode() )
{
SwTextNode& rTextNode = *pNode->GetTextNode();
- sal_Int32 nTextLen = rTextNode.GetText().getLength();
- sal_Int32 nEnd;
- if( rNdIdx == pPam->GetMark()->nNode )
- nEnd = pPam->GetMark()->nContent.GetIndex();
+ SwTextFrame const*const pFrame(pLayout
+ ? static_cast<SwTextFrame const*>(rTextNode.getLayoutFrame(pLayout))
+ : nullptr);
+ assert(!pLayout || pFrame);
+ AmbiguousIndex nTextLen;
+ if (pLayout)
+ {
+ nTextLen.SetFrameIndex(TextFrameIndex(pFrame->GetText().getLength()));
+ }
else
- nEnd = bSrchForward ? nTextLen : 0;
- sal_Int32 nStart = rContentIdx.GetIndex();
+ {
+ nTextLen.SetModelIndex(rTextNode.GetText().getLength());
+ }
+ AmbiguousIndex nEnd;
+ if (pLayout
+ ? FrameContainsNode(*pFrame, pPam->GetMark()->nNode.GetIndex())
+ : rNdIdx == pPam->GetMark()->nNode)
+ {
+ if (pLayout)
+ {
+ nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->GetMark()));
+ }
+ else
+ {
+ nEnd.SetModelIndex(pPam->GetMark()->nContent.GetIndex());
+ }
+ }
+ else
+ {
+ if (bSrchForward)
+ {
+ nEnd = nTextLen;
+ }
+ else
+ {
+ if (pLayout)
+ {
+ nEnd.SetFrameIndex(TextFrameIndex(0));
+ }
+ else
+ {
+ nEnd.SetModelIndex(0);
+ }
+ }
+ }
+ AmbiguousIndex nStart;
+ if (pLayout)
+ {
+ nStart.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->GetPoint()));
+ }
+ else
+ {
+ nStart.SetModelIndex(rContentIdx.GetIndex());
+ }
/* #i80135# */
// if there are SwPostItFields inside our current node text, we
// split the text into separate pieces and search for text inside
// the pieces as well as inside the fields
- const SwpHints *pHts = rTextNode.GetpSwpHints();
+ MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rTextNode);
// count PostItFields by looping over all fields
- sal_Int32 aNumberPostits = 0;
- sal_Int32 aIgnore = 0;
- if (pHts && bSearchInNotes)
+ std::vector<std::pair<SwTextAttr const*, AmbiguousIndex>> postits;
+ if (bSearchInNotes)
{
if (!bSrchForward)
{
std::swap(nStart, nEnd);
}
- for( size_t i = 0; i < pHts->Count(); ++i )
+ SwTextNode const* pTemp(nullptr);
+ while (SwTextAttr const*const pTextAttr = iter.NextAttr(pTemp))
{
- const SwTextAttr* pTextAttr = pHts->Get(i);
if ( pTextAttr->Which()==RES_TXTATR_ANNOTATION )
{
- const sal_Int32 aPos = pTextAttr->GetStart();
- if ( (aPos >= nStart) && (aPos <= nEnd) )
- aNumberPostits++;
- else
+ AmbiguousIndex aPos;
+ aPos.SetModelIndex(pTextAttr->GetStart());
+ if (pLayout)
+ {
+ aPos.SetFrameIndex(pFrame->MapModelToView(pTemp, aPos.GetModelIndex()));
+ }
+ if ((nStart <= aPos) && (aPos <= nEnd))
{
- if (bSrchForward)
- aIgnore++;
+ postits.emplace_back(pTextAttr, aPos);
}
}
}
@@ -334,7 +493,9 @@ bool FindTextImpl(SwPaM & rSearchPam,
if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject))
{
const SwPosition* pPosition = pFrameFormat->GetAnchor().GetContentAnchor();
- if (!pPosition || pPosition->nNode.GetIndex() != pNode->GetIndex())
+ if (!pPosition || (pLayout
+ ? !FrameContainsNode(*pFrame, pPosition->nNode.GetIndex())
+ : pPosition->nNode.GetIndex() != pNode->GetIndex()))
pObject = nullptr;
}
}
@@ -369,10 +530,29 @@ bool FindTextImpl(SwPaM & rSearchPam,
{
// If there are any shapes anchored to this node, search there.
SwPaM aPaM(pNode->GetDoc()->GetNodes().GetEndOfContent());
- aPaM.GetPoint()->nNode = rTextNode;
- aPaM.GetPoint()->nContent.Assign(aPaM.GetPoint()->nNode.GetNode().GetTextNode(), nStart);
+ if (pLayout)
+ {
+ *aPaM.GetPoint() = pFrame->MapViewToModelPos(nStart.GetFrameIndex());
+ }
+ else
+ {
+ aPaM.GetPoint()->nNode = rTextNode;
+ aPaM.GetPoint()->nContent.Assign(
+ aPaM.GetPoint()->nNode.GetNode().GetTextNode(),
+ nStart.GetModelIndex());
+ }
aPaM.SetMark();
- aPaM.GetMark()->nNode = rTextNode.GetIndex() + 1;
+ if (pLayout)
+ {
+ aPaM.GetMark()->nNode = (pFrame->GetMergedPara()
+ ? *pFrame->GetMergedPara()->pLastNode
+ : rTextNode)
+ .GetIndex() + 1;
+ }
+ else
+ {
+ aPaM.GetMark()->nNode = rTextNode.GetIndex() + 1;
+ }
aPaM.GetMark()->nContent.Assign(aPaM.GetMark()->nNode.GetNode().GetTextNode(), 0);
if (pNode->GetDoc()->getIDocumentDrawModelAccess().Search(aPaM, aSearchItem) && pSdrView)
{
@@ -396,18 +576,21 @@ bool FindTextImpl(SwPaM & rSearchPam,
}
}
- sal_Int32 aStart = 0;
// do we need to finish a note?
if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
{
if (bSearchInNotes)
{
- if (bSrchForward)
- aStart++;
- else
+ if (!postits.empty())
{
- if (aNumberPostits)
- --aNumberPostits;
+ if (bSrchForward)
+ {
+ postits.erase(postits.begin());
+ }
+ else
+ {
+ postits.pop_back(); // hope that's the right one?
+ }
}
//search inside, finish and put focus back into the doc
if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
@@ -422,43 +605,72 @@ bool FindTextImpl(SwPaM & rSearchPam,
}
}
- if (aNumberPostits)
+ if (!postits.empty())
{
// now we have to split
- sal_Int32 nStartInside = 0;
- sal_Int32 nEndInside = 0;
- sal_Int32 aLoop= bSrchForward ? aStart : aNumberPostits;
+ AmbiguousIndex nStartInside;
+ AmbiguousIndex nEndInside;
+ sal_Int32 aLoop = bSrchForward ? 0 : postits.size();
- while ( (aLoop>=0) && (aLoop<=aNumberPostits))
+ while ((0 <= aLoop) && (static_cast<size_t>(aLoop) <= postits.size()))
{
if (bSrchForward)
{
- nStartInside = aLoop==0 ? nStart : pHts->Get(GetPostIt(aLoop+aIgnore-1,pHts))->GetStart()+1;
- nEndInside = aLoop==aNumberPostits ? nEnd : pHts->Get(GetPostIt(aLoop+aIgnore,pHts))->GetStart();
+ if (aLoop == 0)
+ {
+ nStartInside = nStart;
+ }
+ else if (pLayout)
+ {
+ nStartInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + TextFrameIndex(1));
+ }
+ else
+ {
+ nStartInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1);
+ }
+ nEndInside = static_cast<size_t>(aLoop) == postits.size()
+ ? nEnd
+ : postits[aLoop].second;
nTextLen = nEndInside - nStartInside;
}
else
{
- nStartInside = aLoop==aNumberPostits ? nStart : pHts->Get(GetPostIt(aLoop+aIgnore,pHts))->GetStart();
- nEndInside = aLoop==0 ? nEnd : pHts->Get(GetPostIt(aLoop+aIgnore-1,pHts))->GetStart()+1;
+ nStartInside = static_cast<size_t>(aLoop) == postits.size()
+ ? nStart
+ : postits[aLoop].second;
+ if (aLoop == 0)
+ {
+ nEndInside = nEnd;
+ }
+ else if (pLayout)
+ {
+ nEndInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + TextFrameIndex(1));
+ }
+ else
+ {
+ nEndInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1);
+ }
nTextLen = nStartInside - nEndInside;
}
// search inside the text between a note
bFound = DoSearch( rSearchPam,
rSearchOpt, rSText, fnMove, bSrchForward,
bRegSearch, bChkEmptyPara, bChkParaEnd,
- nStartInside, nEndInside, nTextLen, pNode,
+ nStartInside, nEndInside, nTextLen,
+ pNode->GetTextNode(), pFrame, pLayout,
pPam.get() );
if ( bFound )
break;
else
{
// we should now be right in front of a note, search inside
- if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) ))
+ if (bSrchForward
+ ? (static_cast<size_t>(aLoop) != postits.size())
+ : (aLoop != 0))
{
- const SwTextAttr* pTextAttr = bSrchForward
- ? pHts->Get(GetPostIt(aLoop+aIgnore,pHts))
- : pHts->Get(GetPostIt(aLoop+aIgnore-1,pHts));
+ const SwTextAttr *const pTextAttr = bSrchForward
+ ? postits[aLoop].first
+ : postits[aLoop - 1].first;
if (pPostItMgr && pPostItMgr->SearchReplace(
static_txtattr_cast<SwTextField const*>(pTextAttr)->GetFormatField(),rSearchOpt,bSrchForward))
{
@@ -477,7 +689,9 @@ bool FindTextImpl(SwPaM & rSearchPam,
bFound = DoSearch( rSearchPam,
rSearchOpt, rSText, fnMove, bSrchForward,
bRegSearch, bChkEmptyPara, bChkParaEnd,
- nStart, nEnd, nTextLen, pNode, pPam.get() );
+ nStart, nEnd, nTextLen,
+ pNode->GetTextNode(), pFrame, pLayout,
+ pPam.get() );
}
if (bFound)
break;
@@ -492,14 +706,14 @@ 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)
+ AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex const nTextLen,
+ SwTextNode const*const pNode, SwTextFrame const*const pFrame,
+ SwRootFrame const*const pLayout, SwPaM* pPam)
{
bool bFound = false;
SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
- const SwNode* pSttNd = &rNdIdx.GetNode();
OUString sCleanStr;
- std::vector<sal_Int32> aFltArr;
+ std::vector<AmbiguousIndex> aFltArr;
LanguageType eLastLang = LANGUAGE_SYSTEM;
// if the search string contains a soft hyphen,
// we don't strip them from the text:
@@ -526,10 +740,10 @@ bool DoSearch(SwPaM & rSearchPam,
}
if( bSrchForward )
- sCleanStr = lcl_CleanStr(*pNode->GetTextNode(), nStart, nEnd,
+ sCleanStr = lcl_CleanStr(*pNode, pFrame, pLayout, nStart, nEnd,
aFltArr, bRemoveSoftHyphens, bRemoveCommentAnchors);
else
- sCleanStr = lcl_CleanStr(*pNode->GetTextNode(), nEnd, nStart,
+ sCleanStr = lcl_CleanStr(*pNode, pFrame, pLayout, nEnd, nStart,
aFltArr, bRemoveSoftHyphens, bRemoveCommentAnchors);
std::unique_ptr<SwScriptIterator> pScriptIter;
@@ -538,28 +752,32 @@ bool DoSearch(SwPaM & rSearchPam,
if (SearchAlgorithms2::APPROXIMATE == rSearchOpt.AlgorithmType2)
{
- pScriptIter.reset(new SwScriptIterator( sCleanStr, nStart, bSrchForward ));
+ pScriptIter.reset(new SwScriptIterator(sCleanStr, nStart.GetAnyIndex(), bSrchForward));
nSearchScript = g_pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
}
- const sal_Int32 nStringEnd = nEnd;
+ const AmbiguousIndex nStringEnd = nEnd;
bool bZeroMatch = false; // zero-length match, i.e. only $ anchor as regex
while ( ((bSrchForward && nStart < nStringEnd) ||
- (! bSrchForward && nStart > nStringEnd)) && !bZeroMatch )
+ (!bSrchForward && nStringEnd < nStart)) && !bZeroMatch )
{
// SearchAlgorithms_APPROXIMATE works on a per word base so we have to
// provide the text searcher with the correct locale, because it uses
// the break-iterator
if ( pScriptIter )
{
- nEnd = pScriptIter->GetScriptChgPos();
+ nEnd.GetAnyIndex() = pScriptIter->GetScriptChgPos();
nCurrScript = pScriptIter->GetCurrScript();
if ( nSearchScript == nCurrScript )
{
- const LanguageType eCurrLang =
- pNode->GetTextNode()->GetLang( bSrchForward ?
- nStart :
- nEnd );
+ const LanguageType eCurrLang = pLayout
+ ? pFrame->GetLangOfChar(bSrchForward
+ ? nStart.GetFrameIndex()
+ : nEnd.GetFrameIndex(),
+ 0, true)
+ : pNode->GetLang(bSrchForward
+ ? nStart.GetModelIndex()
+ : nEnd.GetModelIndex());
if ( eCurrLang != eLastLang )
{
@@ -571,10 +789,10 @@ bool DoSearch(SwPaM & rSearchPam,
}
pScriptIter->Next();
}
- sal_Int32 nProxyStart = nStart;
- sal_Int32 nProxyEnd = nEnd;
+ AmbiguousIndex nProxyStart = nStart;
+ AmbiguousIndex nProxyEnd = nEnd;
if( nSearchScript == nCurrScript &&
- (rSText.*fnMove.fnSearch)( sCleanStr, &nProxyStart, &nProxyEnd, nullptr ) &&
+ (rSText.*fnMove.fnSearch)( sCleanStr, &nProxyStart.GetAnyIndex(), &nProxyEnd.GetAnyIndex(), nullptr) &&
!(bZeroMatch = (nProxyStart == nProxyEnd)))
{
nStart = nProxyStart;
@@ -587,27 +805,35 @@ bool DoSearch(SwPaM & rSearchPam,
if( !aFltArr.empty() )
{
// if backward search, switch positions temporarily
- if( !bSrchForward ) { std::swap(nStart, nEnd); }
+ if (!bSrchForward) { std::swap(nStart, nEnd); }
- sal_Int32 nNew = nStart;
+ AmbiguousIndex nNew = nStart;
for (size_t n = 0; n < aFltArr.size() && aFltArr[ n ] <= nStart; ++n )
{
- ++nNew;
+ ++nNew.GetAnyIndex();
}
nStart = nNew;
nNew = nEnd;
for( size_t n = 0; n < aFltArr.size() && aFltArr[ n ] < nEnd; ++n )
{
- ++nNew;
+ ++nNew.GetAnyIndex();
}
nEnd = nNew;
// if backward search, switch positions temporarily
if( !bSrchForward ) { std::swap(nStart, nEnd); }
}
- rSearchPam.GetMark()->nContent = nStart;
- rSearchPam.GetPoint()->nContent = nEnd;
+ if (pLayout)
+ {
+ *rSearchPam.GetMark() = pFrame->MapViewToModelPos(nStart.GetFrameIndex());
+ *rSearchPam.GetPoint() = pFrame->MapViewToModelPos(nEnd.GetFrameIndex());
+ }
+ else
+ {
+ rSearchPam.GetMark()->nContent = nStart.GetModelIndex();
+ rSearchPam.GetPoint()->nContent = nEnd.GetModelIndex();
+ }
// if backward search, switch point and mark
if( !bSrchForward )
@@ -626,11 +852,23 @@ bool DoSearch(SwPaM & rSearchPam,
if ( bFound )
return true;
- else if( ( bChkEmptyPara && !nStart && !nTextLen ) || bChkParaEnd)
+ else if ((bChkEmptyPara && !nStart.GetAnyIndex() && !nTextLen.GetAnyIndex())
+ || bChkParaEnd)
{
*rSearchPam.GetPoint() = *pPam->GetPoint();
- rSearchPam.GetPoint()->nContent = bChkParaEnd ? nTextLen : 0;
+ if (pLayout)
+ {
+ *rSearchPam.GetPoint() = pFrame->MapViewToModelPos(
+ bChkParaEnd ? nTextLen.GetFrameIndex() : TextFrameIndex(0));
+ }
+ else
+ {
+ rSearchPam.GetPoint()->nContent = bChkParaEnd ? nTextLen.GetModelIndex() : 0;
+ }
rSearchPam.SetMark();
+ const SwNode *const pSttNd = bSrchForward
+ ? &rSearchPam.GetPoint()->nNode.GetNode() // end of the frame
+ : &rNdIdx.GetNode(); // keep the bug as-is for now...
/* FIXME: this condition does not work for !bSrchForward backward
* search, it probably never did. (pSttNd != &rNdIdx.GetNode())
* is never true in this case. */
@@ -654,13 +892,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;
@@ -677,7 +921,8 @@ int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
if( bInReadOnly && m_bReplace )
bInReadOnly = false;
- const bool bFnd = sw::FindTextImpl(rCursor, m_rSearchOpt, m_bSearchInNotes, m_aSText, fnMove, rRegion, bInReadOnly);
+ const bool bFnd = sw::FindTextImpl(rCursor, m_rSearchOpt, m_bSearchInNotes,
+ m_aSText, fnMove, rRegion, bInReadOnly, m_pLayout);
if( bFnd && m_bReplace ) // replace string
{
@@ -731,7 +976,8 @@ bool SwFindParaText::IsReplaceMode() const
sal_uLong SwCursor::Find_Text( 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 +993,7 @@ sal_uLong SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool
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 )
diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx
index 354adfbbfe37..3583e0d2794c 100644
--- a/sw/source/core/crsr/pam.cxx
+++ b/sw/source/core/crsr/pam.cxx
@@ -735,24 +735,26 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const
/// @param rbFirst If <true> then first time request. If so than the position of
/// the PaM must not be changed!
SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & fnMove,
- bool bInReadOnly )
+ bool const bInReadOnly, SwRootFrame const*const i_pLayout)
{
+ SwRootFrame const*const pLayout(i_pLayout ? i_pLayout :
+ rPam.GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
SwContentNode * pNd = nullptr;
if( ((*rPam.GetPoint()).*fnMove.fnCmpOp)( *rPam.GetMark() ) ||
( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
{
- SwContentFrame* pFrame;
if( rbFirst )
{
rbFirst = false;
pNd = rPam.GetContentNode();
if( pNd )
{
+ SwContentFrame const*const pFrame(pNd->getLayoutFrame(pLayout));
if(
(
- nullptr == ( pFrame = pNd->getLayoutFrame( pNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() ) ) ||
+ nullptr == pFrame ||
( !bInReadOnly && pFrame->IsProtected() ) ||
- (pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow())
+ (pFrame->IsTextFrame() && static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
) ||
( !bInReadOnly && pNd->FindSectionNode() &&
pNd->FindSectionNode()->GetSection().IsProtect()
@@ -773,6 +775,12 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const &
// go to next/previous ContentNode
while( true )
{
+ if (i_pLayout && aPos.nNode.GetNode().IsTextNode())
+ {
+ auto const fal(sw::GetFirstAndLastNode(*pLayout, aPos.nNode));
+ aPos.nNode = bSrchForward ? *fal.second : *fal.first;
+ }
+
pNd = bSrchForward
? rNodes.GoNextSection( &aPos.nNode, true, !bInReadOnly )
: SwNodes::GoPrevSection( &aPos.nNode, true, !bInReadOnly );
@@ -783,10 +791,11 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const &
if( (aPos.*fnMove.fnCmpOp)( *rPam.GetMark() ) )
{
// only in AutoTextSection can be nodes that are hidden
- if( nullptr == ( pFrame = pNd->getLayoutFrame( pNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() ) ) ||
+ SwContentFrame const*const pFrame(pNd->getLayoutFrame(pLayout));
+ if (nullptr == pFrame ||
( !bInReadOnly && pFrame->IsProtected() ) ||
( pFrame->IsTextFrame() &&
- static_cast<SwTextFrame*>(pFrame)->IsHiddenNow() ) )
+ static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow()))
{
pNd = nullptr;
continue;
diff --git a/sw/source/core/inc/pamtyp.hxx b/sw/source/core/inc/pamtyp.hxx
index b8a81a090387..a0ebf2bea708 100644
--- a/sw/source/core/inc/pamtyp.hxx
+++ b/sw/source/core/inc/pamtyp.hxx
@@ -29,6 +29,7 @@ class SwPaM;
class SwTextAttr;
class SwFormat;
class SfxPoolItem;
+class SwRootFrame;
namespace i18nutil {
struct SearchOptions2;
@@ -75,7 +76,8 @@ struct SwMoveFnCollection
};
// function prototype for searching
-SwContentNode* GetNode( SwPaM&, bool&, SwMoveFnCollection const &, bool bInReadOnly = false );
+SwContentNode* GetNode(SwPaM&, bool&, SwMoveFnCollection const &,
+ bool bInReadOnly = false, SwRootFrame const* pLayout = nullptr);
namespace sw {
@@ -88,7 +90,8 @@ namespace sw {
bool bSearchInNotes,
utl::TextSearch& rSText,
SwMoveFnCollection const & fnMove,
- const SwPaM & rRegion, bool bInReadOnly = false);
+ const SwPaM & rRegion, bool bInReadOnly,
+ SwRootFrame const* pLayout);
bool FindFormatImpl(SwPaM & rSearchPam,
const SwFormat& rFormat,
SwMoveFnCollection const & fnMove,