LCOV - code coverage report
Current view: top level - sw/source/core/crsr - findtxt.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 167 316 52.8 %
Date: 2014-04-11 Functions: 7 11 63.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/util/SearchOptions.hpp>
      21             : #include <com/sun/star/util/SearchFlags.hpp>
      22             : #include <comphelper/string.hxx>
      23             : #include <vcl/svapp.hxx>
      24             : #include <vcl/window.hxx>
      25             : 
      26             : #include <txatritr.hxx>
      27             : #include <fldbas.hxx>
      28             : #include <fmtfld.hxx>
      29             : #include <txtatr.hxx>
      30             : #include <txtfld.hxx>
      31             : #include <swcrsr.hxx>
      32             : #include <doc.hxx>
      33             : #include <IDocumentUndoRedo.hxx>
      34             : #include <pamtyp.hxx>
      35             : #include <ndtxt.hxx>
      36             : #include <swundo.hxx>
      37             : #include <UndoInsert.hxx>
      38             : #include <breakit.hxx>
      39             : #include <docsh.hxx>
      40             : #include <PostItMgr.hxx>
      41             : #include <viewsh.hxx>
      42             : 
      43             : using namespace ::com::sun::star;
      44             : using namespace util;
      45             : 
      46             : OUString *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam );
      47             : 
      48             : static OUString
      49         296 : lcl_CleanStr(const SwTxtNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
      50             :              std::vector<sal_Int32> &rArr, bool const bRemoveSoftHyphen)
      51             : {
      52         296 :     OUStringBuffer buf(rNd.GetTxt());
      53         296 :     rArr.clear();
      54             : 
      55         296 :     const SwpHints *pHts = rNd.GetpSwpHints();
      56             : 
      57         296 :     sal_uInt16 n = 0;
      58         296 :     sal_Int32 nSoftHyphen = nStart;
      59         296 :     sal_Int32 nHintStart = -1;
      60         296 :     bool bNewHint       = true;
      61         296 :     bool bNewSoftHyphen = true;
      62         296 :     const sal_Int32 nEnd = rEnd;
      63         592 :     std::vector<sal_Int32> aReplaced;
      64             : 
      65             :     do
      66             :     {
      67         304 :         if ( bNewHint )
      68          12 :             nHintStart = pHts && n < pHts->Count() ?
      69           8 :                          *(*pHts)[n]->GetStart() :
      70         312 :                          -1;
      71             : 
      72         304 :         if ( bNewSoftHyphen )
      73             :         {
      74             :             nSoftHyphen = (bRemoveSoftHyphen)
      75         296 :                     ?  rNd.GetTxt().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen)
      76         592 :                     : -1;
      77             :         }
      78             : 
      79         304 :         bNewHint       = false;
      80         304 :         bNewSoftHyphen = false;
      81         304 :         sal_Int32 nStt = 0;
      82             : 
      83             :         // Check if next stop is a hint.
      84         304 :         if ( nHintStart>=0
      85           8 :             && (-1 == nSoftHyphen || nHintStart < nSoftHyphen)
      86           8 :             && nHintStart < nEnd )
      87             :         {
      88           8 :             nStt = nHintStart;
      89           8 :             bNewHint = true;
      90             :         }
      91             :         // Check if next stop is a soft hyphen.
      92         296 :         else if (   -1 != nSoftHyphen
      93           0 :                  && (-1 == nHintStart || nSoftHyphen < nHintStart)
      94           0 :                  && nSoftHyphen < nEnd)
      95             :         {
      96           0 :             nStt = nSoftHyphen;
      97           0 :             bNewSoftHyphen = true;
      98             :         }
      99             :         // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
     100         296 :         else if (-1 != nSoftHyphen && nSoftHyphen == nHintStart)
     101             :         {
     102           0 :             nStt = nSoftHyphen;
     103           0 :             bNewHint = true;
     104           0 :             bNewSoftHyphen = true;
     105             :         }
     106             :         else
     107             :             break;
     108             : 
     109           8 :         const sal_Int32 nAkt = nStt - rArr.size();
     110             : 
     111           8 :         if ( bNewHint )
     112             :         {
     113           8 :             const SwTxtAttr* pHt = (*pHts)[n];
     114           8 :             if ( pHt->HasDummyChar() && (nStt >= nStart) )
     115             :             {
     116           8 :                 switch( pHt->Which() )
     117             :                 {
     118             :                 case RES_TXTATR_FLYCNT:
     119             :                 case RES_TXTATR_FTN:
     120             :                 case RES_TXTATR_FIELD:
     121             :                 case RES_TXTATR_ANNOTATION:
     122             :                 case RES_TXTATR_REFMARK:
     123             :                 case RES_TXTATR_TOXMARK:
     124             :                 case RES_TXTATR_META:
     125             :                 case RES_TXTATR_METAFIELD:
     126             :                     {
     127             :                         // (1998) they are desired as separators and
     128             :                         // belong not any longer to a word.
     129             :                         // they should also be ignored at a
     130             :                         // beginning/end of a sentence if blank. Those are
     131             :                         // simply removed if first. If at the end, we keep the
     132             :                         // replacement and remove afterwards all at a string's
     133             :                         // end (might be normal 0x7f).
     134             :                         const bool bEmpty =
     135           8 :                             ( pHt->Which() != RES_TXTATR_FIELD
     136           8 :                               && pHt->Which() != RES_TXTATR_ANNOTATION )
     137          16 :                             || (static_cast<SwTxtFld const*>(pHt)->GetFmtFld().GetField()->ExpandField(true).isEmpty());;
     138           8 :                         if ( bEmpty && nStart == nAkt )
     139             :                         {
     140           8 :                             rArr.push_back( nAkt );
     141           8 :                             --rEnd;
     142           8 :                             buf.remove(nAkt, 1);
     143             :                         }
     144             :                         else
     145             :                         {
     146           0 :                             if ( bEmpty )
     147           0 :                                 aReplaced.push_back( nAkt );
     148           0 :                             buf[nAkt] = '\x7f';
     149             :                            }
     150             :                     }
     151           8 :                     break;
     152             :                     default:
     153             :                         OSL_FAIL( "unknown case in lcl_CleanStr" );
     154           0 :                         break;
     155             :                 }
     156             :             }
     157           8 :             ++n;
     158             :         }
     159             : 
     160           8 :         if ( bNewSoftHyphen )
     161             :         {
     162           0 :             rArr.push_back( nAkt );
     163           0 :             --rEnd;
     164           0 :             buf.remove(nAkt, 1);
     165           0 :             ++nSoftHyphen;
     166             :         }
     167             :     }
     168             :     while ( true );
     169             : 
     170         592 :     for( sal_uInt16 i = aReplaced.size(); i; )
     171             :     {
     172           0 :         const sal_Int32 nTmp = aReplaced[ --i ];
     173           0 :         if (nTmp == buf.getLength() - 1)
     174             :         {
     175           0 :             buf.truncate(nTmp);
     176           0 :             rArr.push_back( nTmp );
     177           0 :             --rEnd;
     178             :         }
     179             :     }
     180             : 
     181         592 :     return buf.makeStringAndClear();
     182             : }
     183             : 
     184             : // skip all non SwPostIts inside the array
     185           0 : sal_Int32 GetPostIt(sal_Int32 aCount,const SwpHints *pHts)
     186             : {
     187           0 :     sal_Int32 aIndex = 0;
     188           0 :     while (aCount)
     189             :     {
     190           0 :         for (sal_Int32 i = 0; i < pHts->Count(); i++ )
     191             :         {
     192           0 :             aIndex++;
     193           0 :             const SwTxtAttr* pTxtAttr = (*pHts)[i];
     194           0 :             if ( pTxtAttr->Which() == RES_TXTATR_ANNOTATION )
     195             :             {
     196           0 :                 aCount--;
     197           0 :                 if (!aCount)
     198           0 :                     break;
     199             :             }
     200             :         }
     201             :     }
     202             :     // throw away all following non postits
     203           0 :     for( sal_Int32 i = aIndex; i < pHts->Count(); i++ )
     204             :     {
     205           0 :         const SwTxtAttr* pTxtAttr = (*pHts)[i];
     206           0 :         if ( pTxtAttr->Which() == RES_TXTATR_ANNOTATION )
     207           0 :             break;
     208             :         else
     209           0 :             aIndex++;
     210             :     }
     211           0 :     return aIndex;
     212             : }
     213             : 
     214          90 : bool SwPaM::Find( const SearchOptions& rSearchOpt, bool bSearchInNotes , utl::TextSearch& rSTxt,
     215             :                   SwMoveFn fnMove, const SwPaM * pRegion,
     216             :                   bool bInReadOnly )
     217             : {
     218          90 :     if( rSearchOpt.searchString.isEmpty() )
     219           0 :         return false;
     220             : 
     221          90 :     SwPaM* pPam = MakeRegion( fnMove, pRegion );
     222          90 :     const bool bSrchForward = fnMove == fnMoveForward;
     223          90 :     SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
     224          90 :     SwIndex& rCntntIdx = pPam->GetPoint()->nContent;
     225             : 
     226             :     // If bFound is true then the string was found and is between nStart and nEnd
     227          90 :     bool bFound = false;
     228             :     // start position in text or initial position
     229          90 :     sal_Bool bFirst = sal_True;
     230             :     SwCntntNode * pNode;
     231             : 
     232          90 :     const bool bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType;
     233          90 :     const bool bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
     234           0 :                         ( rSearchOpt.searchString.equalsAscii( "^$" ) ||
     235          90 :                           rSearchOpt.searchString.equalsAscii( "$^" ) );
     236          90 :     const bool bChkParaEnd = bRegSearch && rSearchOpt.searchString.equalsAscii( "$" );
     237             : 
     238             :     // LanguageType eLastLang = 0;
     239         396 :     while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
     240             :     {
     241         300 :         if( pNode->IsTxtNode() )
     242             :         {
     243         296 :             sal_Int32 nTxtLen = static_cast<SwTxtNode*>(pNode)->GetTxt().getLength();
     244             :             sal_Int32 nEnd;
     245         296 :             if( rNdIdx == pPam->GetMark()->nNode )
     246           0 :                 nEnd = pPam->GetMark()->nContent.GetIndex();
     247             :             else
     248         296 :                 nEnd = bSrchForward ? nTxtLen : 0;
     249         296 :             sal_Int32 nStart = rCntntIdx.GetIndex();
     250             : 
     251             :             /* #i80135# */
     252             :             // if there are SwPostItFields inside our current node text, we
     253             :             // split the text into separate pieces and search for text inside
     254             :             // the pieces as well as inside the fields
     255         296 :             const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints();
     256             : 
     257             :             // count PostItFields by looping over all fields
     258         296 :             sal_Int32 aNumberPostits = 0;
     259         296 :             sal_Int32 aIgnore = 0;
     260         296 :             if (pHts && bSearchInNotes)
     261             :             {
     262           0 :                 if (!bSrchForward)
     263             :                 {
     264           0 :                     std::swap(nStart, nEnd);
     265             :                 }
     266             : 
     267           0 :                 for( sal_Int32 i = 0; i < pHts->Count(); i++ )
     268             :                 {
     269           0 :                     const SwTxtAttr* pTxtAttr = (*pHts)[i];
     270           0 :                     if ( pTxtAttr->Which()==RES_TXTATR_ANNOTATION )
     271             :                     {
     272           0 :                         const sal_Int32 aPos = *pTxtAttr->GetStart();
     273           0 :                         if ( (aPos >= nStart) && (aPos <= nEnd) )
     274           0 :                             aNumberPostits++;
     275             :                         else
     276             :                         {
     277           0 :                             if (bSrchForward)
     278           0 :                                 aIgnore++;
     279             :                         }
     280             :                     }
     281             :                 }
     282             : 
     283           0 :                 if (!bSrchForward)
     284             :                 {
     285           0 :                     std::swap(nStart, nEnd);
     286             :                 }
     287             : 
     288             :             }
     289             : 
     290         296 :             SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell();
     291         296 :             SwViewShell *const pWrtShell = (pDocShell) ? (SwViewShell*)(pDocShell->GetWrtShell()) : 0;
     292         296 :             SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0;
     293             : 
     294         296 :             sal_Int32 aStart = 0;
     295             :             // do we need to finish a note?
     296         296 :             if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
     297             :             {
     298           0 :                 if (bSearchInNotes)
     299             :                 {
     300           0 :                     if (bSrchForward)
     301           0 :                         aStart++;
     302             :                     else
     303             :                     {
     304           0 :                         if (aNumberPostits)
     305           0 :                             --aNumberPostits;
     306             :                     }
     307             :                     //search inside and finsih and put focus back into the doc
     308           0 :                     if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
     309             :                     {
     310           0 :                         bFound = true ;
     311          84 :                         break;
     312             :                     }
     313             :                 }
     314             :                 else
     315             :                 {
     316           0 :                     pPostItMgr->SetActiveSidebarWin(0);
     317             :                 }
     318             :             }
     319             : 
     320         296 :             if (aNumberPostits)
     321             :             {
     322             :                 // now we have to split
     323           0 :                 sal_Int32 nStartInside = 0;
     324           0 :                 sal_Int32 nEndInside = 0;
     325           0 :                 sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits;
     326             : 
     327           0 :                 while ( (aLoop>=0) && (aLoop<=aNumberPostits))
     328             :                 {
     329           0 :                     if (bSrchForward)
     330             :                     {
     331           0 :                         nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
     332           0 :                         nEndInside = aLoop==aNumberPostits ? nEnd : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
     333           0 :                         nTxtLen = nEndInside - nStartInside;
     334             :                     }
     335             :                     else
     336             :                     {
     337           0 :                         nStartInside =  aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
     338           0 :                         nEndInside = aLoop==0 ? nEnd : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
     339           0 :                         nTxtLen = nStartInside - nEndInside;
     340             :                     }
     341             :                     // search inside the text between a note
     342             :                     bFound = DoSearch( rSearchOpt, rSTxt, fnMove, bSrchForward,
     343             :                                        bRegSearch, bChkEmptyPara, bChkParaEnd,
     344             :                                        nStartInside, nEndInside, nTxtLen, pNode,
     345           0 :                                        pPam );
     346           0 :                     if ( bFound )
     347           0 :                         break;
     348             :                     else
     349             :                     {
     350             :                         // we should now be right in front of a note, search inside
     351           0 :                         if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) ))
     352             :                         {
     353           0 :                             const SwTxtAttr* pTxtAttr = bSrchForward ?  (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)];
     354           0 :                             if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFmtFld(),rSearchOpt,bSrchForward) )
     355             :                             {
     356           0 :                                 bFound = true ;
     357           0 :                                 break;
     358             :                             }
     359             :                         }
     360             :                     }
     361           0 :                     aLoop = bSrchForward ? aLoop+1 : aLoop-1;
     362             :                 }
     363             :             }
     364             :             else
     365             :             {
     366             :                 // if there is no SwPostItField inside or searching inside notes
     367             :                 // is disabled, we search the whole length just like before
     368             :                 bFound = DoSearch( rSearchOpt, rSTxt, fnMove, bSrchForward,
     369             :                                    bRegSearch, bChkEmptyPara, bChkParaEnd,
     370         296 :                                    nStart, nEnd, nTxtLen, pNode, pPam );
     371             :             }
     372         296 :             if (bFound)
     373          84 :                 break;
     374             :         }
     375             :     }
     376          90 :     delete pPam;
     377          90 :     return bFound;
     378             : }
     379             : 
     380         296 : bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt,
     381             :                       SwMoveFn fnMove, bool bSrchForward, bool bRegSearch,
     382             :                       bool bChkEmptyPara, bool bChkParaEnd,
     383             :                       sal_Int32 &nStart, sal_Int32 &nEnd, sal_Int32 nTxtLen,
     384             :                       SwNode* pNode, SwPaM* pPam)
     385             : {
     386         296 :     bool bFound = false;
     387         296 :     SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
     388         296 :     const SwNode* pSttNd = &rNdIdx.GetNode();
     389         296 :     OUString sCleanStr;
     390         592 :     std::vector<sal_Int32> aFltArr;
     391         296 :     LanguageType eLastLang = 0;
     392             :     // if the search string contains a soft hypen,
     393             :     // we don't strip them from the text:
     394         296 :     bool bRemoveSoftHyphens = true;
     395             : 
     396         296 :     if ( bRegSearch )
     397             :     {
     398           0 :         if (   -1 != rSearchOpt.searchString.indexOf("\\xAD")
     399           0 :             || -1 != rSearchOpt.searchString.indexOf("\\x{00AD}")
     400           0 :             || -1 != rSearchOpt.searchString.indexOf("\\u00AD")
     401           0 :             || -1 != rSearchOpt.searchString.indexOf("\\U000000AD")
     402           0 :             || -1 != rSearchOpt.searchString.indexOf("\\N{SOFT HYPHEN}"))
     403             :         {
     404           0 :              bRemoveSoftHyphens = false;
     405             :         }
     406             :     }
     407             :     else
     408             :     {
     409         296 :         if ( 1 == rSearchOpt.searchString.getLength() &&
     410           0 :              CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
     411           0 :              bRemoveSoftHyphens = false;
     412             :     }
     413             : 
     414         296 :     if( bSrchForward )
     415         592 :         sCleanStr = lcl_CleanStr(*static_cast<SwTxtNode*>(pNode), nStart, nEnd,
     416         296 :                         aFltArr, bRemoveSoftHyphens);
     417             :     else
     418           0 :         sCleanStr = lcl_CleanStr(*static_cast<SwTxtNode*>(pNode), nEnd, nStart,
     419           0 :                         aFltArr, bRemoveSoftHyphens);
     420             : 
     421         296 :     SwScriptIterator* pScriptIter = 0;
     422         296 :     sal_uInt16 nSearchScript = 0;
     423         296 :     sal_uInt16 nCurrScript = 0;
     424             : 
     425         888 :     if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType &&
     426         296 :          g_pBreakIt->GetBreakIter().is() )
     427             :     {
     428           0 :         pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward );
     429           0 :         nSearchScript = g_pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
     430             :     }
     431             : 
     432         296 :     const sal_Int32 nStringEnd = nEnd;
     433         296 :     bool bZeroMatch = false;    // zero-length match, i.e. only $ anchor as regex
     434         856 :     while ( ((bSrchForward && nStart < nStringEnd) ||
     435         212 :             (! bSrchForward && nStart > nStringEnd)) && !bZeroMatch )
     436             :     {
     437             :         // SearchAlgorithms_APPROXIMATE works on a per word base so we have to
     438             :         // provide the text searcher with the correct locale, because it uses
     439             :         // the break-iterator
     440         136 :         if ( pScriptIter )
     441             :         {
     442           0 :             nEnd = pScriptIter->GetScriptChgPos();
     443           0 :             nCurrScript = pScriptIter->GetCurrScript();
     444           0 :             if ( nSearchScript == nCurrScript )
     445             :             {
     446             :                 const LanguageType eCurrLang =
     447             :                         ((SwTxtNode*)pNode)->GetLang( bSrchForward ?
     448             :                                                       nStart :
     449           0 :                                                       nEnd );
     450             : 
     451           0 :                 if ( eCurrLang != eLastLang )
     452             :                 {
     453             :                     const lang::Locale aLocale(
     454           0 :                             g_pBreakIt->GetLocale( eCurrLang ) );
     455           0 :                     rSTxt.SetLocale( rSearchOpt, aLocale );
     456           0 :                     eLastLang = eCurrLang;
     457             :                 }
     458             :             }
     459           0 :             pScriptIter->Next();
     460             :         }
     461         136 :         sal_Int32 nProxyStart = nStart;
     462         136 :         sal_Int32 nProxyEnd = nEnd;
     463         272 :         if( nSearchScript == nCurrScript &&
     464         304 :                 (rSTxt.*fnMove->fnSearch)( sCleanStr, &nProxyStart, &nProxyEnd, 0 ) &&
     465         168 :                 !(bZeroMatch = (nProxyStart == nProxyEnd)))
     466             :         {
     467          84 :             nStart = nProxyStart;
     468          84 :             nEnd = nProxyEnd;
     469             :             // set section correctly
     470          84 :             *GetPoint() = *pPam->GetPoint();
     471          84 :             SetMark();
     472             : 
     473             :             // adjust start and end
     474          84 :             if( !aFltArr.empty() )
     475             :             {
     476             :                 // if backward search, switch positions temporarily
     477           0 :                 if( !bSrchForward ) { std::swap(nStart, nEnd); }
     478             : 
     479           0 :                 sal_Int32 nNew = nStart;
     480           0 :                 for (size_t n = 0; n < aFltArr.size() && aFltArr[ n ] <= nStart; ++n )
     481             :                 {
     482           0 :                     ++nNew;
     483             :                 }
     484             : 
     485           0 :                 nStart = nNew;
     486           0 :                 nNew = nEnd;
     487           0 :                 for( size_t n = 0; n < aFltArr.size() && aFltArr[ n ] < nEnd; ++n )
     488             :                 {
     489           0 :                     ++nNew;
     490             :                 }
     491             : 
     492           0 :                 nEnd = nNew;
     493             :                 // if backward search, switch positions temporarily
     494           0 :                 if( !bSrchForward ) { std::swap(nStart, nEnd); }
     495             :             }
     496          84 :             GetMark()->nContent = nStart;
     497          84 :             GetPoint()->nContent = nEnd;
     498             : 
     499             :             // if backward search, switch point and mark
     500          84 :             if( !bSrchForward )
     501           0 :                 Exchange();
     502          84 :             bFound = true;
     503         168 :             break;
     504             :         }
     505             :         else
     506             :         {
     507          52 :             nStart = (sal_uInt16)nProxyStart;
     508          52 :             nEnd = (sal_uInt16)nProxyEnd;
     509             :         }
     510          52 :         nStart = nEnd;
     511             :     }
     512             : 
     513         296 :     delete pScriptIter;
     514             : 
     515         296 :     if ( bFound )
     516          84 :         return true;
     517         212 :     else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd)
     518             :     {
     519           0 :         *GetPoint() = *pPam->GetPoint();
     520           0 :         GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0;
     521           0 :         SetMark();
     522             :         /* FIXME: this condition does not work for !bSrchForward backward
     523             :          * search, it probably never did. (pSttNd != &rNdIdx.GetNode())
     524             :          * is never true in this case. */
     525           0 :         if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) &&
     526           0 :             Move( fnMoveForward, fnGoCntnt ) &&
     527           0 :             (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) &&
     528           0 :             1 == std::abs( (int)( GetPoint()->nNode.GetIndex() -
     529           0 :                              GetMark()->nNode.GetIndex()) ) )
     530             :         {
     531             :             // if backward search, switch point and mark
     532           0 :             if( !bSrchForward )
     533           0 :                 Exchange();
     534           0 :             return true;
     535             :         }
     536             :     }
     537         508 :     return bFound;
     538             : }
     539             : 
     540             : /// parameters for search and replace in text
     541             : struct SwFindParaText : public SwFindParas
     542             : {
     543             :     const SearchOptions& rSearchOpt;
     544             :     SwCursor& rCursor;
     545             :     utl::TextSearch aSTxt;
     546             :     sal_Bool bReplace;
     547             :     sal_Bool bSearchInNotes;
     548             : 
     549           9 :     SwFindParaText( const SearchOptions& rOpt, sal_Bool bSearchNotes, int bRepl, SwCursor& rCrsr )
     550           9 :         : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes )
     551           9 :     {}
     552             :     virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly ) SAL_OVERRIDE;
     553             :     virtual bool IsReplaceMode() const SAL_OVERRIDE;
     554             :     virtual ~SwFindParaText();
     555             : };
     556             : 
     557           9 : SwFindParaText::~SwFindParaText()
     558             : {
     559           9 : }
     560             : 
     561          90 : int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
     562             :                             const SwPaM* pRegion, sal_Bool bInReadOnly )
     563             : {
     564          90 :     if( bInReadOnly && bReplace )
     565          46 :         bInReadOnly = sal_False;
     566             : 
     567          90 :     const bool bFnd = pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly );
     568             : 
     569          90 :     if( bFnd && bReplace ) // replace string
     570             :     {
     571             :         // use replace method in SwDoc
     572          44 :         const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType);
     573          44 :         SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
     574          44 :         const sal_Int32 nSttCnt = rSttCntIdx.GetIndex();
     575             :         // add to shell-cursor-ring so that the regions will be moved enventually
     576          44 :         Ring *pPrev(0);
     577          44 :         if( bRegExp )
     578             :         {
     579           0 :             pPrev = pRegion->GetPrev();
     580           0 :             ((Ring*)pRegion)->MoveRingTo( &rCursor );
     581             :         }
     582             : 
     583             :         boost::scoped_ptr<OUString> pRepl( (bRegExp)
     584          44 :                 ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
     585          44 :         rCursor.GetDoc()->ReplaceRange( *pCrsr,
     586          44 :             (pRepl.get()) ? *pRepl : rSearchOpt.replaceString,
     587          88 :             bRegExp );
     588          44 :         rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
     589             : 
     590          44 :         if( bRegExp )
     591             :         {
     592             :             // and remove region again
     593           0 :             Ring *p, *pNext = (Ring*)pRegion;
     594           0 :             do {
     595           0 :                 p = pNext;
     596           0 :                 pNext = p->GetNext();
     597           0 :                 p->MoveTo( (Ring*)pRegion );
     598             :             } while( p != pPrev );
     599             :         }
     600          44 :         pCrsr->Start()->nContent = nSttCnt;
     601          44 :         return FIND_NO_RING;
     602             :     }
     603          46 :     return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
     604             : }
     605             : 
     606           0 : bool SwFindParaText::IsReplaceMode() const
     607             : {
     608           0 :     return bReplace;
     609             : }
     610             : 
     611           9 : sal_uLong SwCursor::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
     612             :                           SwDocPositions nStart, SwDocPositions nEnd,
     613             :                           sal_Bool& bCancel, FindRanges eFndRngs, int bReplace )
     614             : {
     615             :     // switch off OLE-notifications
     616           9 :     SwDoc* pDoc = GetDoc();
     617           9 :     Link aLnk( pDoc->GetOle2Link() );
     618           9 :     pDoc->SetOle2Link( Link() );
     619             : 
     620           9 :     bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
     621           9 :     if (bStartUndo)
     622             :     {
     623           2 :         pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
     624             :     }
     625             : 
     626           9 :     bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
     627           9 :     if( bSearchSel )
     628           0 :         eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL);
     629           9 :     SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this );
     630           9 :     sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel );
     631           9 :     pDoc->SetOle2Link( aLnk );
     632           9 :     if( nRet && bReplace )
     633           2 :         pDoc->SetModified();
     634             : 
     635           9 :     if (bStartUndo)
     636             :     {
     637             :         SwRewriter rewriter(MakeUndoReplaceRewriter(
     638           2 :                 nRet, rSearchOpt.searchString, rSearchOpt.replaceString));
     639           2 :         pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, & rewriter );
     640             :     }
     641           9 :     return nRet;
     642             : }
     643             : 
     644           0 : OUString *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam )
     645             : {
     646           0 :     OUString *pRet = 0;
     647           0 :     if( pPam && pPam->HasMark() &&
     648           0 :         SearchAlgorithms_REGEXP == rSearchOpt.algorithmType )
     649             :     {
     650           0 :         const SwCntntNode* pTxtNode = pPam->GetCntntNode( true );
     651           0 :         if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( false ) )
     652             :         {
     653           0 :             utl::TextSearch aSTxt( rSearchOpt );
     654           0 :             const OUString& rStr = static_cast<const SwTxtNode*>(pTxtNode)->GetTxt();
     655           0 :             sal_Int32 nStart = pPam->Start()->nContent.GetIndex();
     656           0 :             sal_Int32 nEnd = pPam->End()->nContent.GetIndex();
     657           0 :             SearchResult aResult;
     658           0 :             if( aSTxt.SearchForward( rStr, &nStart, &nEnd, &aResult ) )
     659             :             {
     660           0 :                 OUString aReplaceStr( rSearchOpt.replaceString );
     661           0 :                 aSTxt.ReplaceBackReferences( aReplaceStr, rStr, aResult );
     662           0 :                 pRet = new OUString( aReplaceStr );
     663           0 :             }
     664             :         }
     665             :     }
     666           0 :     return pRet;
     667             : }
     668             : 
     669             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10