summaryrefslogtreecommitdiff
path: root/sw/source/core/crsr/findtxt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/crsr/findtxt.cxx')
-rw-r--r--sw/source/core/crsr/findtxt.cxx705
1 files changed, 705 insertions, 0 deletions
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
new file mode 100644
index 000000000000..9fd6dd0516e9
--- /dev/null
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -0,0 +1,705 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+
+
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#include <vcl/svapp.hxx>
+#include <txatritr.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <txtatr.hxx>
+#include <txtfld.hxx>
+#include <swcrsr.hxx>
+#include <doc.hxx>
+#include <pamtyp.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx>
+#include <breakit.hxx>
+
+#include <docsh.hxx>
+#include <PostItMgr.hxx>
+#include <viewsh.hxx>
+#include <vcl/window.hxx>
+
+#define POSTITMGR ((ViewShell*)pNode->GetDoc()->GetDocShell()->GetWrtShell())->GetPostItMgr()
+
+using namespace ::com::sun::star;
+using namespace util;
+
+String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam );
+
+String& lcl_CleanStr( const SwTxtNode& rNd, xub_StrLen nStart,
+ xub_StrLen& rEnde, SvULongs& rArr, String& rRet,
+ bool bRemoveSoftHyphen )
+{
+ rRet = rNd.GetTxt();
+ if( rArr.Count() )
+ rArr.Remove( 0, rArr.Count() );
+
+ const SwpHints *pHts = rNd.GetpSwpHints();
+
+ USHORT n = 0;
+ xub_StrLen nSoftHyphen = nStart;
+ xub_StrLen nHintStart = STRING_LEN;
+ bool bNewHint = true;
+ bool bNewSoftHyphen = true;
+ const xub_StrLen nEnd = rEnde;
+ SvUShorts aReplaced;
+
+ do
+ {
+ if ( bNewHint )
+ nHintStart = pHts && n < pHts->Count() ?
+ *(*pHts)[n]->GetStart() :
+ STRING_LEN;
+
+ if ( bNewSoftHyphen )
+ nSoftHyphen = bRemoveSoftHyphen ?
+ rNd.GetTxt().Search( CHAR_SOFTHYPHEN, nSoftHyphen ) :
+ STRING_LEN;
+
+ bNewHint = false;
+ bNewSoftHyphen = false;
+
+ xub_StrLen nStt = 0;
+
+ // Check if next stop is a hint.
+ if ( STRING_LEN != nHintStart && nHintStart < nSoftHyphen && nHintStart < nEnd )
+ {
+ nStt = nHintStart;
+ bNewHint = true;
+ }
+ // Check if next stop is a soft hyphen.
+ else if ( STRING_LEN != nSoftHyphen && nSoftHyphen < nHintStart && nSoftHyphen < nEnd )
+ {
+ nStt = nSoftHyphen;
+ bNewSoftHyphen = true;
+ }
+ // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
+ else if ( STRING_LEN != nSoftHyphen && nSoftHyphen == nHintStart )
+ {
+ nStt = nSoftHyphen;
+ bNewHint = true;
+ bNewSoftHyphen = true;
+ }
+ else
+ break;
+
+ const xub_StrLen nAkt = nStt - rArr.Count();
+
+ if ( bNewHint )
+ {
+ const SwTxtAttr* pHt = (*pHts)[n];
+ if ( pHt->HasDummyChar() && (nStt >= nStart) )
+ {
+ //JP 17.05.00: Task 75806 ask for ">=" and not for ">"
+ switch( pHt->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ {
+ // JP 06.05.98: mit Bug 50100 werden sie als Trenner erwuenscht und nicht
+ // mehr zum Wort dazu gehoerend.
+ // MA 23.06.98: mit Bug 51215 sollen sie konsequenterweise auch am
+ // Satzanfang und -ende ignoriert werden wenn sie Leer sind.
+ // Dazu werden sie schlicht entfernt. Fuer den Anfang entfernen
+ // wir sie einfach.
+ // Fuer das Ende merken wir uns die Ersetzungen und entferenen
+ // hinterher alle am Stringende (koenten ja 'normale' 0x7f drinstehen
+ BOOL bEmpty = RES_TXTATR_FIELD != pHt->Which() ||
+ !(static_cast<SwTxtFld const*>(pHt)
+ ->GetFld().GetFld()->ExpandField(
+ rNd.GetDoc()->IsClipBoard()).Len());
+ if ( bEmpty && nStart == nAkt )
+ {
+ rArr.Insert( nAkt, rArr.Count() );
+ --rEnde;
+ rRet.Erase( nAkt, 1 );
+ }
+ else
+ {
+ if ( bEmpty )
+ aReplaced.Insert( nAkt, aReplaced.Count() );
+ rRet.SetChar( nAkt, '\x7f' );
+ }
+ }
+ break;
+ default:
+ ASSERT( false, "unknown case in lcl_CleanStr" )
+ break;
+ }
+ }
+ ++n;
+ }
+
+ if ( bNewSoftHyphen )
+ {
+ rArr.Insert( nAkt, rArr.Count() );
+ --rEnde;
+ rRet.Erase( nAkt, 1 );
+ ++nSoftHyphen;
+ }
+ }
+ while ( true );
+
+ for( USHORT i = aReplaced.Count(); i; )
+ {
+ const xub_StrLen nTmp = aReplaced[ --i ];
+ if( nTmp == rRet.Len() - 1 )
+ {
+ rRet.Erase( nTmp );
+ rArr.Insert( nTmp, rArr.Count() );
+ --rEnde;
+ }
+ }
+
+ return rRet;
+}
+
+// skip all non SwPostIts inside the array
+xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts)
+{
+ xub_StrLen aIndex = 0;
+ while (aCount)
+ {
+ for (xub_StrLen i = 0; i <pHts->Count();i++)
+ {
+ aIndex++;
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ {
+ aCount--;
+ if (!aCount)
+ break;
+ }
+ }
+ }
+ // throw away all following non postits
+ for (xub_StrLen i = aIndex; i <pHts->Count();i++)
+ {
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ break;
+ else
+ aIndex++;
+ }
+ return aIndex;
+}
+
+BYTE SwPaM::Find( const SearchOptions& rSearchOpt, BOOL bSearchInNotes , utl::TextSearch& rSTxt,
+ SwMoveFn fnMove, const SwPaM * pRegion,
+ BOOL bInReadOnly )
+{
+ if( !rSearchOpt.searchString.getLength() )
+ return FALSE;
+
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+ BOOL bSrchForward = fnMove == fnMoveForward;
+ SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
+ SwIndex& rCntntIdx = pPam->GetPoint()->nContent;
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ // beim leeren Node nicht weiter
+ if( bSrchForward
+ ? ( rCntntIdx.GetIndex() == pPam->GetCntntNode()->Len() &&
+ rCntntIdx.GetIndex() )
+ : !rCntntIdx.GetIndex() && pPam->GetCntntNode()->Len() )
+ {
+ if( !(*fnMove->fnNds)( &rNdIdx, FALSE ))
+ {
+ delete pPam;
+ return FALSE;
+ }
+ SwCntntNode *pNd = rNdIdx.GetNode().GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ rCntntIdx.Assign( pNd, nTmpPos );
+ }
+
+ /*
+ * Ist bFound == TRUE, dann wurde der String gefunden und in
+ * nStart und nEnde steht der gefundenen String
+ */
+ BOOL bFound = FALSE;
+ /*
+ * StartPostion im Text oder Anfangsposition
+ */
+ BOOL bFirst = TRUE;
+ SwCntntNode * pNode;
+ //testarea
+ //String sCleanStr;
+ //SvULongs aFltArr;
+ //const SwNode* pSttNd = &rNdIdx.GetNode();
+
+ xub_StrLen nStart, nEnde, nTxtLen;
+
+ BOOL bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType;
+ BOOL bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
+ ( !rSearchOpt.searchString.compareToAscii( "^$" ) ||
+ !rSearchOpt.searchString.compareToAscii( "$^" ) );
+ BOOL bChkParaEnd = bRegSearch && 1 == rSearchOpt.searchString.getLength() &&
+ !rSearchOpt.searchString.compareToAscii( "$" );
+
+// LanguageType eLastLang = 0;
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
+ {
+ if( pNode->IsTxtNode() )
+ {
+ nTxtLen = ((SwTxtNode*)pNode)->GetTxt().Len();
+ if( rNdIdx == pPam->GetMark()->nNode )
+ nEnde = pPam->GetMark()->nContent.GetIndex();
+ else
+ nEnde = bSrchForward ? nTxtLen : 0;
+ nStart = rCntntIdx.GetIndex();
+
+ /* #i80135# */
+ // if there are SwPostItFields inside our current node text, we split the text into seperate pieces
+ // and search for text inside the pieces as well as inside the fields
+ const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints();
+
+ // count postitfields by looping over all fields
+ xub_StrLen aNumberPostits = 0;
+ xub_StrLen aIgnore = 0;
+ if (pHts && bSearchInNotes)
+ {
+ if (!bSrchForward)
+ {
+ xub_StrLen swap = nEnde;
+ nEnde = nStart;
+ nStart = swap;
+ }
+
+ for (xub_StrLen i = 0; i <pHts->Count();i++)
+ {
+ xub_StrLen aPos = *(*pHts)[i]->GetStart();
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ {
+ if ( (aPos >= nStart) && (aPos <= nEnde) )
+ aNumberPostits++;
+ else
+ {
+ if (bSrchForward)
+ aIgnore++;
+ }
+ }
+ }
+
+ if (!bSrchForward)
+ {
+ xub_StrLen swap = nEnde;
+ nEnde = nStart;
+ nStart = swap;
+ }
+
+ }
+
+ xub_StrLen aStart = 0;
+ // do we need to finish a note?
+ if (POSTITMGR->HasActiveSidebarWin())
+ {
+ if (bSearchInNotes)
+ {
+ if (bSrchForward)
+ aStart++;
+ else
+ {
+ if (aNumberPostits)
+ --aNumberPostits;
+ }
+ //search inside and finsih and put focus back into the doc
+ if (POSTITMGR->FinishSearchReplace(rSearchOpt,bSrchForward))
+ {
+ bFound = true ;
+ break;
+ }
+ }
+ else
+ {
+ POSTITMGR->SetActiveSidebarWin(0);
+ }
+ }
+
+ if (aNumberPostits)
+ {
+ // now we have to split
+ xub_StrLen nStartInside = 0;
+ xub_StrLen nEndeInside = 0;
+ sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits;
+
+ while ( (aLoop>=0) && (aLoop<=aNumberPostits))
+ {
+ if (bSrchForward)
+ {
+ nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
+ nEndeInside = aLoop==aNumberPostits? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
+ nTxtLen = nEndeInside-nStartInside;
+ }
+ else
+ {
+ nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
+ nEndeInside = aLoop==0 ? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
+ nTxtLen = nStartInside-nEndeInside;
+ }
+ // search inside the text between a note
+ bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
+ nStartInside,nEndeInside,nTxtLen, pNode,pPam);
+ 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) ))
+ {
+ const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)];
+ if ( POSTITMGR->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFld(),rSearchOpt,bSrchForward) )
+ {
+ bFound = true ;
+ break;
+ }
+ }
+ }
+ aLoop = bSrchForward ? aLoop+1 : aLoop-1;
+ }
+ }
+ else
+ {
+ // if there is no SwPostItField inside or searching inside notes is disabled, we search the whole length just like before
+ bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
+ nStart,nEnde,nTxtLen, pNode,pPam);
+ }
+ if (bFound)
+ break;
+ }
+ }
+ delete pPam;
+ return bFound;
+}
+
+bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt,
+ SwMoveFn fnMove,
+ BOOL bSrchForward, BOOL bRegSearch, BOOL bChkEmptyPara, BOOL bChkParaEnd,
+ xub_StrLen &nStart, xub_StrLen &nEnde, xub_StrLen nTxtLen,SwNode* pNode, SwPaM* pPam)
+{
+ bool bFound = false;
+ SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
+ const SwNode* pSttNd = &rNdIdx.GetNode();
+ String sCleanStr;
+ SvULongs aFltArr;
+ LanguageType eLastLang = 0;
+ // if the search string contains a soft hypen, we don't strip them from the text:
+ bool bRemoveSoftHyphens = true;
+ if ( bRegSearch )
+ {
+ const rtl::OUString a00AD( rtl::OUString::createFromAscii( "\\x00AD" ) );
+ if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) )
+ bRemoveSoftHyphens = false;
+ }
+ else
+ {
+ if ( 1 == rSearchOpt.searchString.getLength() &&
+ CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
+ bRemoveSoftHyphens = false;
+ }
+
+ if( bSrchForward )
+ lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnde,
+ aFltArr, sCleanStr, bRemoveSoftHyphens );
+ else
+ lcl_CleanStr( *(SwTxtNode*)pNode, nEnde, nStart,
+ aFltArr, sCleanStr, bRemoveSoftHyphens );
+
+ SwScriptIterator* pScriptIter = 0;
+ USHORT nSearchScript = 0;
+ USHORT nCurrScript = 0;
+
+ if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType &&
+ pBreakIt->GetBreakIter().is() )
+ {
+ pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward );
+ nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
+ }
+
+ xub_StrLen nStringEnd = nEnde;
+ while ( (bSrchForward && nStart < nStringEnd) ||
+ (! bSrchForward && nStart > nStringEnd) )
+ {
+ // SearchAlgorithms_APPROXIMATE works on a per word base
+ // so we have to provide the text searcher with the correct
+ // locale, because it uses the breakiterator
+ if ( pScriptIter )
+ {
+ nEnde = pScriptIter->GetScriptChgPos();
+ nCurrScript = pScriptIter->GetCurrScript();
+ if ( nSearchScript == nCurrScript )
+ {
+ const LanguageType eCurrLang =
+ ((SwTxtNode*)pNode)->GetLang( bSrchForward ?
+ nStart :
+ nEnde );
+
+ if ( eCurrLang != eLastLang )
+ {
+ const lang::Locale aLocale(
+ pBreakIt->GetLocale( eCurrLang ) );
+ rSTxt.SetLocale( rSearchOpt, aLocale );
+ eLastLang = eCurrLang;
+ }
+ }
+ pScriptIter->Next();
+ }
+
+ if( nSearchScript == nCurrScript &&
+ (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnde, 0 ))
+ {
+ // setze den Bereich richtig
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+
+ // Start und Ende wieder korrigieren !!
+ if( aFltArr.Count() )
+ {
+ xub_StrLen n, nNew;
+ // bei Rueckwaertssuche die Positionen temp. vertauschen
+ if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
+
+ for( n = 0, nNew = nStart;
+ n < aFltArr.Count() && aFltArr[ n ] <= nStart;
+ ++n, ++nNew )
+ ;
+ nStart = nNew;
+ for( n = 0, nNew = nEnde;
+ n < aFltArr.Count() && aFltArr[ n ] < nEnde;
+ ++n, ++nNew )
+ ;
+ nEnde = nNew;
+
+ // bei Rueckwaertssuche die Positionen temp. vertauschen
+ if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
+ }
+ GetMark()->nContent = nStart; // Startposition setzen
+ GetPoint()->nContent = nEnde;
+
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // Point und Mark tauschen
+ bFound = TRUE;
+ break;
+ }
+
+ nStart = nEnde;
+ } // end of script while
+
+ delete pScriptIter;
+
+ if ( bFound )
+ return true;
+ else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd )
+ {
+ *GetPoint() = *pPam->GetPoint();
+ GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0;
+ SetMark();
+ if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) &&
+ Move( fnMoveForward, fnGoCntnt ) &&
+ (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) &&
+ 1 == Abs( (int)( GetPoint()->nNode.GetIndex() -
+ GetMark()->nNode.GetIndex()) ) )
+ {
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // Point und Mark tauschen
+ //bFound = TRUE;
+ //break;
+ return true;
+ }
+ }
+ return bFound;
+}
+
+// Parameter fuers Suchen und Ersetzen von Text
+struct SwFindParaText : public SwFindParas
+{
+ const SearchOptions& rSearchOpt;
+ SwCursor& rCursor;
+ utl::TextSearch aSTxt;
+ BOOL bReplace;
+ BOOL bSearchInNotes;
+
+ SwFindParaText( const SearchOptions& rOpt, BOOL bSearchNotes, int bRepl, SwCursor& rCrsr )
+ : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes )
+ {}
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, BOOL bInReadOnly );
+ virtual int IsReplaceMode() const;
+ virtual ~SwFindParaText();
+};
+
+SwFindParaText::~SwFindParaText()
+{
+}
+
+int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
+ const SwPaM* pRegion, BOOL bInReadOnly )
+{
+ if( bInReadOnly && bReplace )
+ bInReadOnly = FALSE;
+
+ BOOL bFnd = (BOOL)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly );
+
+ /* #i80135# if we found something in a note, Mark and Point is the same
+ if( bFnd && *pCrsr->GetMark() == *pCrsr->GetPoint() )
+ return FIND_NOT_FOUND;
+ */
+
+ if( bFnd && bReplace ) // String ersetzen ??
+ {
+ // Replace-Methode vom SwDoc benutzen
+ const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType);
+ SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
+ xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
+ // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
+ // mit aufnehmen !!
+ Ring *pPrev(0);
+ if( bRegExp )
+ {
+ pPrev = pRegion->GetPrev();
+ ((Ring*)pRegion)->MoveRingTo( &rCursor );
+ }
+
+ ::std::auto_ptr<String> pRepl( (bRegExp)
+ ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
+ rCursor.GetDoc()->ReplaceRange( *pCrsr,
+ (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString),
+ bRegExp );
+ rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
+
+ if( bRegExp )
+ {
+ // und die Region wieder herausnehmen:
+ Ring *p, *pNext = (Ring*)pRegion;
+ do {
+ p = pNext;
+ pNext = p->GetNext();
+ p->MoveTo( (Ring*)pRegion );
+ } while( p != pPrev );
+ }
+ pCrsr->Start()->nContent = nSttCnt;
+ return FIND_NO_RING;
+ }
+ return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
+}
+
+
+int SwFindParaText::IsReplaceMode() const
+{
+ return bReplace;
+}
+
+
+ULONG SwCursor::Find( const SearchOptions& rSearchOpt, BOOL bSearchInNotes,
+ SwDocPositions nStart, SwDocPositions nEnde,
+ BOOL& bCancel,
+ FindRanges eFndRngs, int bReplace )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ BOOL bSttUndo = pDoc->DoesUndo() && bReplace;
+ if( bSttUndo )
+ pDoc->StartUndo( UNDO_REPLACE, NULL );
+
+ BOOL bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
+ if( bSearchSel )
+ eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL);
+ SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this );
+ ULONG nRet = FindAll( aSwFindParaText, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+ if( nRet && bReplace )
+ pDoc->SetModified();
+
+ if( bSttUndo )
+ pDoc->EndUndo( UNDO_REPLACE, NULL );
+ return nRet;
+}
+
+String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam )
+{
+ String *pRet = 0;
+ if( pPam && pPam->HasMark() &&
+ SearchAlgorithms_REGEXP == rSearchOpt.algorithmType )
+ {
+ const SwCntntNode* pTxtNode = pPam->GetCntntNode( TRUE );
+ if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( FALSE ) )
+ {
+ utl::TextSearch aSTxt( rSearchOpt );
+ String aStr( pPam->GetTxt() );
+ String aSearchStr( rSearchOpt.searchString );
+ String aReplaceStr( rSearchOpt.replaceString );
+ aStr.EraseAllChars( CH_TXTATR_BREAKWORD );
+ aStr.EraseAllChars( CH_TXTATR_INWORD );
+ xub_StrLen nStart = 0;
+ String sX( 'x' );
+ if( pPam->Start()->nContent > 0 )
+ {
+ aStr.Insert( sX, 0 );
+ ++nStart;
+ }
+ xub_StrLen nEnd = aStr.Len();
+ bool bDeleteLastX = false;
+ if( pPam->End()->nContent < (static_cast<const SwTxtNode*>(pTxtNode))->GetTxt().Len() )
+ {
+ aStr.Insert( sX );
+ bDeleteLastX = true;
+ }
+ SearchResult aResult;
+ if( aSTxt.SearchFrwrd( aStr, &nStart, &nEnd, &aResult ) )
+ {
+ if( bDeleteLastX )
+ aStr.Erase( aStr.Len() - 1 );
+ aSTxt.ReplaceBackReferences( aReplaceStr, aStr, aResult );
+ pRet = new String( aReplaceStr );
+ }
+ }
+ }
+ return pRet;
+}
+
+