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

Generated by: LCOV version 1.10