LCOV - code coverage report
Current view: top level - sw/source/core/crsr - findattr.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 593 0.2 %
Date: 2014-11-03 Functions: 2 32 6.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             : #include <com/sun/star/lang/Locale.hpp>
      21             : #include <com/sun/star/util/SearchOptions.hpp>
      22             : #include <com/sun/star/util/SearchFlags.hpp>
      23             : #include <i18nlangtag/languagetag.hxx>
      24             : #include <hintids.hxx>
      25             : #include <vcl/svapp.hxx>
      26             : #include <vcl/settings.hxx>
      27             : #include <svl/itemiter.hxx>
      28             : #include <svl/whiter.hxx>
      29             : #include <editeng/formatbreakitem.hxx>
      30             : #include <editeng/colritem.hxx>
      31             : #include <editeng/fontitem.hxx>
      32             : #include <fmtpdsc.hxx>
      33             : #include <txatbase.hxx>
      34             : #include <fchrfmt.hxx>
      35             : #include <charfmt.hxx>
      36             : #include <doc.hxx>
      37             : #include <IDocumentUndoRedo.hxx>
      38             : #include <IDocumentState.hxx>
      39             : #include <swcrsr.hxx>
      40             : #include <editsh.hxx>
      41             : #include <ndtxt.hxx>
      42             : #include <pamtyp.hxx>
      43             : #include <swundo.hxx>
      44             : #include <crsskip.hxx>
      45             : #include <boost/optional.hpp>
      46             : #include <boost/scoped_ptr.hpp>
      47             : 
      48             : using namespace ::com::sun::star;
      49             : using namespace ::com::sun::star::lang;
      50             : using namespace ::com::sun::star::util;
      51             : 
      52             : typedef std::set<SwFmt*> SwpFmts;
      53             : 
      54             : // Special case for SvxFontItem: only compare the name
      55           0 : bool CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
      56             : {
      57           0 :     switch( rItem1.Which() )
      58             :     {
      59             :     case RES_CHRATR_FONT:
      60           0 :         return ((SvxFontItem&)rItem1).GetFamilyName() ==
      61           0 :                 ((SvxFontItem&)rItem2).GetFamilyName();
      62             : 
      63             :     case RES_CHRATR_COLOR:
      64           0 :         return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
      65           0 :                                 ((SvxColorItem&)rItem2).GetValue() );
      66             :     case RES_PAGEDESC:
      67           0 :         bool bNumOffsetEqual = false;
      68           0 :         ::boost::optional<sal_uInt16> oNumOffset1 = ((SwFmtPageDesc&)rItem1).GetNumOffset();
      69           0 :         ::boost::optional<sal_uInt16> oNumOffset2 = ((SwFmtPageDesc&)rItem1).GetNumOffset();
      70           0 :         if (!oNumOffset1 && !oNumOffset2)
      71             :         {
      72           0 :             bNumOffsetEqual = true;
      73             :         }
      74           0 :         else if (oNumOffset1 && oNumOffset2)
      75             :         {
      76           0 :             bNumOffsetEqual = oNumOffset1.get() == oNumOffset2.get();
      77             :         }
      78             :         else
      79             :         {
      80           0 :             bNumOffsetEqual = false;
      81             :         }
      82             : 
      83           0 :         if (bNumOffsetEqual == false)
      84           0 :             return false;
      85             : 
      86           0 :         return ((SwFmtPageDesc&)rItem1).GetPageDesc() == ((SwFmtPageDesc&)rItem2).GetPageDesc();
      87             :     }
      88           0 :     return rItem1 == rItem2;
      89             : }
      90             : 
      91           0 : const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
      92             :                                     sal_Int32 nCntntPos )
      93             : {
      94           0 :     while( rPos < rHtsArr.Count() )
      95             :     {
      96           0 :         const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
      97             :         // the start of an attribute has to be in the section
      98           0 :         if( pTxtHt->GetStart() >= nCntntPos )
      99           0 :             return pTxtHt; // valid text attribute
     100             :     }
     101           0 :     return 0; // invalid text attribute
     102             : }
     103             : 
     104           0 : const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
     105             :                                   sal_Int32 nCntntPos )
     106             : {
     107           0 :     while( rPos > 0 )
     108             :     {
     109           0 :         const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
     110             :         // the start of an attribute has to be in the section
     111           0 :         if( pTxtHt->GetStart() < nCntntPos )
     112           0 :             return pTxtHt; // valid text attribute
     113             :     }
     114           0 :     return 0; // invalid text attribute
     115             : }
     116             : 
     117           0 : static void lcl_SetAttrPam( SwPaM& rPam, sal_Int32 nStart, const sal_Int32* pEnd,
     118             :                      const bool bSaveMark )
     119             : {
     120             :     sal_Int32 nCntntPos;
     121           0 :     if( bSaveMark )
     122           0 :         nCntntPos = rPam.GetMark()->nContent.GetIndex();
     123             :     else
     124           0 :         nCntntPos = rPam.GetPoint()->nContent.GetIndex();
     125           0 :     bool bTstEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
     126             : 
     127           0 :     SwCntntNode* pCNd = rPam.GetCntntNode();
     128           0 :     rPam.GetPoint()->nContent.Assign( pCNd, nStart );
     129           0 :     rPam.SetMark(); // Point == GetMark
     130             : 
     131             :     // Point points to end of search area or end of attribute
     132           0 :     if( pEnd )
     133             :     {
     134           0 :         if( bTstEnd && *pEnd > nCntntPos )
     135           0 :             rPam.GetPoint()->nContent = nCntntPos;
     136             :         else
     137           0 :             rPam.GetPoint()->nContent = *pEnd;
     138             :     }
     139           0 : }
     140             : 
     141             : // TODO: provide documentation
     142             : /** search for a text attribute
     143             : 
     144             :     This function searches in a text node for a given attribute.
     145             :     If that is found then the SwPaM contains the section that surrounds the
     146             :     attribute (w.r.t. the search area).
     147             : 
     148             :     @param rTxtNd   Text node to search in.
     149             :     @param rPam     ???
     150             :     @param rCmpItem ???
     151             :     @param fnMove   ???
     152             :     @param bValue   ???
     153             :     @return Returns <true> if found, <false> otherwise.
     154             : */
     155           0 : static bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
     156             :                     const SfxPoolItem& rCmpItem,
     157             :                     SwMoveFn fnMove, bool bValue )
     158             : {
     159           0 :     if ( !rTxtNd.HasHints() )
     160           0 :         return false;
     161             : 
     162           0 :     const SwTxtAttr *pTxtHt = 0;
     163           0 :     bool bForward = fnMove == fnMoveForward;
     164           0 :     sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
     165           0 :     sal_Int32 nCntntPos = rPam.GetPoint()->nContent.GetIndex();
     166             : 
     167           0 :     while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
     168           0 :         if( pTxtHt->Which() == rCmpItem.Which() &&
     169           0 :             ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
     170             :         {
     171           0 :             lcl_SetAttrPam( rPam, pTxtHt->GetStart(), pTxtHt->End(), bForward );
     172           0 :             return true;
     173             :         }
     174           0 :     return false;
     175             : }
     176             : 
     177             : /// search for multiple text attributes
     178             : struct _SwSrchChrAttr
     179             : {
     180             :     sal_uInt16 nWhich;
     181             :     sal_Int32 nStt;
     182             :     sal_Int32 nEnd;
     183             : 
     184           0 :     _SwSrchChrAttr( const SfxPoolItem& rItem,
     185             :                     sal_Int32 nStart, sal_Int32 nAnyEnd )
     186           0 :         : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
     187           0 :     {}
     188             : };
     189             : 
     190             : class SwAttrCheckArr
     191             : {
     192             :     _SwSrchChrAttr *pFndArr, *pStackArr;
     193             :     sal_Int32 nNdStt;
     194             :     sal_Int32 nNdEnd;
     195             :     sal_uInt16 nArrStart, nArrLen;
     196             :     sal_uInt16 nFound, nStackCnt;
     197             :     SfxItemSet aCmpSet;
     198             :     bool bNoColls;
     199             :     bool bForward;
     200             : 
     201             : public:
     202             :     SwAttrCheckArr( const SfxItemSet& rSet, bool bForward, bool bNoCollections );
     203             :     ~SwAttrCheckArr();
     204             : 
     205             :     void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
     206             : 
     207             :     /// how many attributes are there in total?
     208           0 :     sal_uInt16 Count() const    { return aCmpSet.Count(); }
     209           0 :     bool Found() const       { return nFound == aCmpSet.Count(); }
     210             :     bool CheckStack();
     211             : 
     212             :     sal_Int32 Start() const;
     213             :     sal_Int32 End() const;
     214             : 
     215           0 :     sal_Int32 GetNdStt() const { return nNdStt; }
     216           0 :     sal_Int32 GetNdEnd() const { return nNdEnd; }
     217             : 
     218             :     bool SetAttrFwd( const SwTxtAttr& rAttr );
     219             :     bool SetAttrBwd( const SwTxtAttr& rAttr );
     220             : };
     221             : 
     222           0 : SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, bool bFwd,
     223             :                                 bool bNoCollections )
     224             :     : nNdStt(0)
     225             :     , nNdEnd(0)
     226             :     , nFound(0)
     227             :     , nStackCnt(0)
     228           0 :     , aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
     229             :     , bNoColls(bNoCollections)
     230           0 :     , bForward(bFwd)
     231             : {
     232           0 :     aCmpSet.Put( rSet, false );
     233             : 
     234             :     // determine area of Fnd/Stack array (Min/Max)
     235           0 :     SfxItemIter aIter( aCmpSet );
     236           0 :     nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
     237           0 :     nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
     238             : 
     239           0 :     char* pFndChar  = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
     240           0 :     char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
     241             : 
     242           0 :     pFndArr = (_SwSrchChrAttr*)pFndChar;
     243           0 :     pStackArr = (_SwSrchChrAttr*)pStackChar;
     244           0 : }
     245             : 
     246           0 : SwAttrCheckArr::~SwAttrCheckArr()
     247             : {
     248           0 :     delete[] (char*)pFndArr;
     249           0 :     delete[] (char*)pStackArr;
     250           0 : }
     251             : 
     252           0 : void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
     253             : {
     254           0 :     memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
     255           0 :     memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
     256           0 :     nFound = 0;
     257           0 :     nStackCnt = 0;
     258             : 
     259           0 :     if( bForward )
     260             :     {
     261           0 :         nNdStt = rPam.GetPoint()->nContent.GetIndex();
     262           0 :         nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
     263           0 :                 ? rPam.GetMark()->nContent.GetIndex()
     264           0 :                 : rTxtNd.GetTxt().getLength();
     265             :     }
     266             :     else
     267             :     {
     268           0 :         nNdEnd = rPam.GetPoint()->nContent.GetIndex();
     269           0 :         nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
     270           0 :                 ? rPam.GetMark()->nContent.GetIndex()
     271           0 :                 : 0;
     272             :     }
     273             : 
     274           0 :     if( bNoColls && !rTxtNd.HasSwAttrSet() )
     275           0 :         return ;
     276             : 
     277           0 :     const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
     278             : 
     279           0 :     SfxItemIter aIter( aCmpSet );
     280           0 :     const SfxPoolItem* pItem = aIter.GetCurItem();
     281             :     const SfxPoolItem* pFndItem;
     282             :     sal_uInt16 nWhich;
     283             : 
     284             :     while( true )
     285             :     {
     286           0 :         if( IsInvalidItem( pItem ) )
     287             :         {
     288           0 :             nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
     289           0 :             if( RES_TXTATR_END <= nWhich )
     290           0 :                 break; // end of text attributes
     291             : 
     292           0 :             if( SfxItemState::SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
     293           0 :                 && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
     294             :             {
     295             :                 pFndArr[ nWhich - nArrStart ] =
     296           0 :                     _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
     297           0 :                 nFound++;
     298             :             }
     299             :         }
     300             :         else
     301             :         {
     302           0 :             if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
     303           0 :                 break; // end of text attributes
     304             : 
     305           0 :             if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
     306             :             {
     307             :                 pFndArr[ nWhich - nArrStart ] =
     308           0 :                     _SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
     309           0 :                 nFound++;
     310             :             }
     311             :         }
     312             : 
     313           0 :         if( aIter.IsAtEnd() )
     314           0 :             break;
     315           0 :         pItem = aIter.NextItem();
     316           0 :     }
     317             : }
     318             : 
     319             : static bool
     320           0 : lcl_IsAttributeIgnorable(sal_Int32 const nNdStart, sal_Int32 const nNdEnd,
     321             :         _SwSrchChrAttr const& rTmp)
     322             : {
     323             :     // #i115528#: if there is a paragraph attribute, it has been added by the
     324             :     // SwAttrCheckArr ctor, and nFound is 1.
     325             :     // if the paragraph is entirely covered by hints that override the paragraph
     326             :     // attribute, then this function must find an attribute to decrement nFound!
     327             :     // so check for an empty search range, let attributes that start/end there
     328             :     // cover it, and hope for the best...
     329             :     return ((nNdEnd == nNdStart)
     330           0 :             ? ((rTmp.nEnd <  nNdStart) || (nNdEnd <  rTmp.nStt))
     331           0 :             : ((rTmp.nEnd <= nNdStart) || (nNdEnd <= rTmp.nStt)));
     332             : }
     333             : 
     334           0 : bool SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
     335             : {
     336           0 :     _SwSrchChrAttr aTmp( rAttr.GetAttr(), rAttr.GetStart(), *rAttr.GetAnyEnd() );
     337             : 
     338             :     // ignore all attributes not in search range
     339           0 :     if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
     340             :     {
     341           0 :         return Found();
     342             :     }
     343             : 
     344             :     const SfxPoolItem* pItem;
     345             :     // here we explicitly also search in character templates
     346           0 :     sal_uInt16 nWhch = rAttr.Which();
     347           0 :     SfxWhichIter* pIter = NULL;
     348           0 :     const SfxPoolItem* pTmpItem = NULL;
     349           0 :     const SfxItemSet* pSet = NULL;
     350           0 :     if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
     351             :     {
     352           0 :         if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
     353           0 :             return Found();
     354           0 :         pTmpItem = NULL;
     355           0 :         pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
     356           0 :         if ( pSet )
     357             :         {
     358           0 :             pIter = new SfxWhichIter( *pSet );
     359           0 :             nWhch = pIter->FirstWhich();
     360           0 :             while( nWhch &&
     361           0 :                 SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) )
     362           0 :                 nWhch = pIter->NextWhich();
     363           0 :             if( !nWhch )
     364           0 :                 pTmpItem = NULL;
     365             :         }
     366             :     }
     367             :     else
     368           0 :         pTmpItem = &rAttr.GetAttr();
     369             : 
     370           0 :     while( pTmpItem )
     371             :     {
     372           0 :         SfxItemState eState = aCmpSet.GetItemState( nWhch, false, &pItem );
     373           0 :         if( SfxItemState::DONTCARE == eState || SfxItemState::SET == eState )
     374             :         {
     375             :             sal_uInt16 n;
     376             :             _SwSrchChrAttr* pCmp;
     377             : 
     378             :             // first delete all up to start position that are already invalid
     379             :             _SwSrchChrAttr* pArrPtr;
     380           0 :             if( nFound )
     381           0 :                 for( pArrPtr = pFndArr, n = 0; n < nArrLen;
     382             :                     ++n, ++pArrPtr )
     383           0 :                     if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
     384             :                     {
     385           0 :                         pArrPtr->nWhich = 0; // deleted
     386           0 :                         nFound--;
     387             :                     }
     388             : 
     389             :             // delete all up to start position that are already invalid and
     390             :             // move all "open" ones (= stick out over start position) from stack
     391             :             // into FndSet
     392           0 :             if( nStackCnt )
     393           0 :                 for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
     394             :                 {
     395           0 :                     if( !pArrPtr->nWhich )
     396           0 :                         continue;
     397             : 
     398           0 :                     if( pArrPtr->nEnd <= aTmp.nStt )
     399             :                     {
     400           0 :                         pArrPtr->nWhich = 0; // deleted
     401           0 :                         if( !--nStackCnt )
     402           0 :                             break;
     403             :                     }
     404           0 :                     else if( pArrPtr->nStt <= aTmp.nStt )
     405             :                     {
     406           0 :                         if( ( pCmp = &pFndArr[ n ])->nWhich )
     407             :                         {
     408           0 :                             if( pCmp->nEnd < pArrPtr->nEnd ) // extend
     409           0 :                                 pCmp->nEnd = pArrPtr->nEnd;
     410             :                         }
     411             :                         else
     412             :                         {
     413           0 :                             *pCmp = *pArrPtr;
     414           0 :                             nFound++;
     415             :                         }
     416           0 :                         pArrPtr->nWhich = 0;
     417           0 :                         if( !--nStackCnt )
     418           0 :                             break;
     419             :                     }
     420             :                 }
     421             : 
     422           0 :             bool bContinue = false;
     423             : 
     424           0 :             if( SfxItemState::DONTCARE == eState  )
     425             :             {
     426             :                 // Will the attribute become valid?
     427           0 :                 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
     428           0 :                     *pTmpItem ))
     429             :                 {
     430             :                     // search attribute and extend if needed
     431           0 :                     if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
     432             :                     {
     433           0 :                         *pCmp = aTmp; // not found, insert
     434           0 :                         nFound++;
     435             :                     }
     436           0 :                     else if( pCmp->nEnd < aTmp.nEnd ) // extend?
     437           0 :                         pCmp->nEnd = aTmp.nEnd;
     438             : 
     439           0 :                     bContinue = true;
     440             :                 }
     441             :             }
     442             :             // Will the attribute become valid?
     443           0 :             else if(  CmpAttr( *pItem, *pTmpItem ) )
     444             :             {
     445           0 :                 pFndArr[ nWhch - nArrStart ] = aTmp;
     446           0 :                 ++nFound;
     447           0 :                 bContinue = true;
     448             :             }
     449             : 
     450             :             // then is has to go on the stack
     451           0 :             if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
     452             :             {
     453             :                 // exists on stack, only if it is even bigger
     454           0 :                 if( pCmp->nEnd > aTmp.nEnd )
     455             :                 {
     456             :                     OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
     457             :                                     "slot on stack is still in use" );
     458             : 
     459           0 :                     if( aTmp.nStt <= pCmp->nStt )
     460           0 :                         pCmp->nStt = aTmp.nEnd;
     461             :                     else
     462           0 :                         pCmp->nEnd = aTmp.nStt;
     463             : 
     464           0 :                     pStackArr[ nWhch - nArrStart ] = *pCmp;
     465           0 :                     nStackCnt++;
     466             :                 }
     467           0 :                 pCmp->nWhich = 0;
     468           0 :                 nFound--;
     469             :             }
     470             :         }
     471           0 :         if( pIter )
     472             :         {
     473           0 :             nWhch = pIter->NextWhich();
     474           0 :             while( nWhch &&
     475           0 :                 SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) )
     476           0 :                 nWhch = pIter->NextWhich();
     477           0 :             if( !nWhch )
     478           0 :                 break;
     479             :         }
     480             :         else
     481           0 :             break;
     482             :     }
     483           0 :     delete pIter;
     484           0 :     return Found();
     485             : }
     486             : 
     487           0 : bool SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
     488             : {
     489           0 :     _SwSrchChrAttr aTmp( rAttr.GetAttr(), rAttr.GetStart(), *rAttr.GetAnyEnd() );
     490             : 
     491             :     // ignore all attributes not in search range
     492           0 :     if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
     493             :     {
     494           0 :         return Found();
     495             :     }
     496             : 
     497             :     const SfxPoolItem* pItem;
     498             :     // here we explicitly also search in character templates
     499           0 :     sal_uInt16 nWhch = rAttr.Which();
     500           0 :     SfxWhichIter* pIter = NULL;
     501           0 :     const SfxPoolItem* pTmpItem = NULL;
     502           0 :     const SfxItemSet* pSet = NULL;
     503           0 :     if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
     504             :     {
     505           0 :         if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
     506           0 :             return Found();
     507             : 
     508           0 :         pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
     509           0 :         if ( pSet )
     510             :         {
     511           0 :             pIter = new SfxWhichIter( *pSet );
     512           0 :             nWhch = pIter->FirstWhich();
     513           0 :             while( nWhch &&
     514           0 :                 SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) )
     515           0 :                 nWhch = pIter->NextWhich();
     516           0 :             if( !nWhch )
     517           0 :                 pTmpItem = NULL;
     518             :         }
     519             :     }
     520             :     else
     521           0 :         pTmpItem = &rAttr.GetAttr();
     522             : 
     523           0 :     while( pTmpItem )
     524             :     {
     525           0 :         SfxItemState eState = aCmpSet.GetItemState( nWhch, false, &pItem );
     526           0 :         if( SfxItemState::DONTCARE == eState || SfxItemState::SET == eState )
     527             :         {
     528             :             sal_uInt16 n;
     529             :             _SwSrchChrAttr* pCmp;
     530             : 
     531             :             // first delete all up to start position that are already invalid
     532             :             _SwSrchChrAttr* pArrPtr;
     533           0 :             if( nFound )
     534           0 :                 for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
     535           0 :                     if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
     536             :                     {
     537           0 :                         pArrPtr->nWhich = 0; // deleted
     538           0 :                         nFound--;
     539             :                     }
     540             : 
     541             :             // delete all up to start position that are already invalid and
     542             :             // move all "open" ones (= stick out over start position) from stack
     543             :             // into FndSet
     544           0 :             if( nStackCnt )
     545           0 :                 for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
     546             :                 {
     547           0 :                     if( !pArrPtr->nWhich )
     548           0 :                         continue;
     549             : 
     550           0 :                     if( pArrPtr->nStt >= aTmp.nEnd )
     551             :                     {
     552           0 :                         pArrPtr->nWhich = 0; // deleted
     553           0 :                         if( !--nStackCnt )
     554           0 :                             break;
     555             :                     }
     556           0 :                     else if( pArrPtr->nEnd >= aTmp.nEnd )
     557             :                     {
     558           0 :                         if( ( pCmp = &pFndArr[ n ])->nWhich )
     559             :                         {
     560           0 :                             if( pCmp->nStt > pArrPtr->nStt ) // extend
     561           0 :                                 pCmp->nStt = pArrPtr->nStt;
     562             :                         }
     563             :                         else
     564             :                         {
     565           0 :                             *pCmp = *pArrPtr;
     566           0 :                             nFound++;
     567             :                     }
     568           0 :                     pArrPtr->nWhich = 0;
     569           0 :                     if( !--nStackCnt )
     570           0 :                         break;
     571             :                 }
     572             :             }
     573             : 
     574           0 :             bool bContinue = false;
     575           0 :             if( SfxItemState::DONTCARE == eState  )
     576             :             {
     577             :                 // Will the attribute become valid?
     578           0 :                 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
     579           0 :                     *pTmpItem ) )
     580             :                 {
     581             :                     // search attribute and extend if needed
     582           0 :                     if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
     583             :                     {
     584           0 :                         *pCmp = aTmp; // not found, insert
     585           0 :                         nFound++;
     586             :                     }
     587           0 :                     else if( pCmp->nStt > aTmp.nStt ) // extend?
     588           0 :                         pCmp->nStt = aTmp.nStt;
     589             : 
     590           0 :                     bContinue = true;
     591             :                 }
     592             :             }
     593             :             // Will the attribute become valid?
     594           0 :             else if( CmpAttr( *pItem, *pTmpItem ))
     595             :             {
     596           0 :                 pFndArr[ nWhch - nArrStart ] = aTmp;
     597           0 :                 ++nFound;
     598           0 :                 bContinue = true;
     599             :             }
     600             : 
     601             :             // then is has to go on the stack
     602           0 :             if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
     603             :             {
     604             :                 // exists on stack, only if it is even bigger
     605           0 :                 if( pCmp->nStt < aTmp.nStt )
     606             :                 {
     607             :                     OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
     608             :                             "slot on stack is still in use" );
     609             : 
     610           0 :                     if( aTmp.nEnd <= pCmp->nEnd )
     611           0 :                         pCmp->nEnd = aTmp.nStt;
     612             :                     else
     613           0 :                         pCmp->nStt = aTmp.nEnd;
     614             : 
     615           0 :                     pStackArr[ nWhch - nArrStart ] = *pCmp;
     616           0 :                     nStackCnt++;
     617             :                 }
     618           0 :                 pCmp->nWhich = 0;
     619           0 :                 nFound--;
     620             :             }
     621             :         }
     622           0 :         if( pIter )
     623             :         {
     624           0 :             nWhch = pIter->NextWhich();
     625           0 :             while( nWhch &&
     626           0 :                 SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) )
     627           0 :                 nWhch = pIter->NextWhich();
     628           0 :             if( !nWhch )
     629           0 :                 break;
     630             :         }
     631             :         else
     632           0 :             break;
     633             :     }
     634           0 :     delete pIter;
     635           0 :     return Found();
     636             : }
     637             : 
     638           0 : sal_Int32 SwAttrCheckArr::Start() const
     639             : {
     640           0 :     sal_Int32 nStart = nNdStt;
     641           0 :     _SwSrchChrAttr* pArrPtr = pFndArr;
     642           0 :     for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
     643           0 :         if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
     644           0 :             nStart = pArrPtr->nStt;
     645             : 
     646           0 :     return nStart;
     647             : }
     648             : 
     649           0 : sal_Int32 SwAttrCheckArr::End() const
     650             : {
     651           0 :     _SwSrchChrAttr* pArrPtr = pFndArr;
     652           0 :     sal_Int32 nEnd = nNdEnd;
     653           0 :     for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
     654           0 :         if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
     655           0 :             nEnd = pArrPtr->nEnd;
     656             : 
     657           0 :     return nEnd;
     658             : }
     659             : 
     660           0 : bool SwAttrCheckArr::CheckStack()
     661             : {
     662           0 :     if( !nStackCnt )
     663           0 :         return false;
     664             : 
     665             :     sal_uInt16 n;
     666           0 :     const sal_Int32 nSttPos = Start();
     667           0 :     const sal_Int32 nEndPos = End();
     668             :     _SwSrchChrAttr* pArrPtr;
     669           0 :     for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
     670             :     {
     671           0 :         if( !pArrPtr->nWhich )
     672           0 :             continue;
     673             : 
     674           0 :         if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
     675             :         {
     676           0 :             pArrPtr->nWhich = 0; // deleted
     677           0 :             if( !--nStackCnt )
     678           0 :                 return nFound == aCmpSet.Count();
     679             :         }
     680           0 :         else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
     681             :         {
     682             :             // move all "open" ones (= stick out over start position) into FndSet
     683             :             OSL_ENSURE( !pFndArr[ n ].nWhich, "slot in array is already in use" );
     684           0 :             pFndArr[ n ] = *pArrPtr;
     685           0 :             pArrPtr->nWhich = 0;
     686           0 :             nFound++;
     687           0 :             if( !--nStackCnt )
     688           0 :                 return nFound == aCmpSet.Count();
     689             :         }
     690             :     }
     691           0 :     return nFound == aCmpSet.Count();
     692             : }
     693             : 
     694           0 : static int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
     695             :                             SwPaM& rPam )
     696             : {
     697             :     sal_Int32 nEndPos;
     698           0 :     rCmpArr.SetNewSet( rTxtNd, rPam );
     699           0 :     if( !rTxtNd.HasHints() )
     700             :     {
     701           0 :         if( !rCmpArr.Found() )
     702           0 :             return sal_False;
     703           0 :         nEndPos = rCmpArr.GetNdEnd();
     704           0 :         lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, true );
     705           0 :         return sal_True;
     706             :     }
     707             : 
     708           0 :     const SwpHints& rHtArr = rTxtNd.GetSwpHints();
     709             :     const SwTxtAttr* pAttr;
     710           0 :     size_t nPos = 0;
     711             : 
     712             :     // if everything is already there then check with which it will be ended
     713           0 :     if( rCmpArr.Found() )
     714             :     {
     715           0 :         for( ; nPos < rHtArr.Count(); ++nPos )
     716           0 :             if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
     717             :             {
     718           0 :                 if( rCmpArr.GetNdStt() < pAttr->GetStart() )
     719             :                 {
     720             :                     // found end
     721             :                     lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
     722           0 :                                 &pAttr->GetStart(), true );
     723           0 :                     return sal_True;
     724             :                 }
     725             :                 // continue search
     726           0 :                 break;
     727             :             }
     728             : 
     729           0 :         if( nPos == rHtArr.Count() && rCmpArr.Found() )
     730             :         {
     731             :             // found
     732           0 :             nEndPos = rCmpArr.GetNdEnd();
     733           0 :             lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, true );
     734           0 :             return sal_True;
     735             :         }
     736             :     }
     737             : 
     738             :     sal_Int32 nSttPos;
     739           0 :     for( ; nPos < rHtArr.Count(); ++nPos )
     740           0 :         if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
     741             :         {
     742             :             // Do multiple start at that position? Do also check those:
     743           0 :             nSttPos = pAttr->GetStart();
     744           0 :             while( ++nPos < rHtArr.Count() && nSttPos ==
     745           0 :                     ( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
     746           0 :                     rCmpArr.SetAttrFwd( *pAttr ) )
     747             :                 ;
     748             : 
     749           0 :             if( !rCmpArr.Found() )
     750           0 :                 continue;
     751             : 
     752             :             // then we have our search area
     753           0 :             if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
     754           0 :                 return sal_False;
     755             : 
     756           0 :             lcl_SetAttrPam( rPam, nSttPos, &nEndPos, true );
     757           0 :             return sal_True;
     758             :         }
     759             : 
     760           0 :     if( !rCmpArr.CheckStack() ||
     761           0 :         (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
     762           0 :         return sal_False;
     763             : 
     764           0 :     lcl_SetAttrPam( rPam, nSttPos, &nEndPos, true );
     765           0 :     return sal_True;
     766             : }
     767             : 
     768           0 : static int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
     769             :                             SwPaM& rPam )
     770             : {
     771             :     sal_Int32 nEndPos;
     772           0 :     rCmpArr.SetNewSet( rTxtNd, rPam );
     773           0 :     if( !rTxtNd.HasHints() )
     774             :     {
     775           0 :         if( !rCmpArr.Found() )
     776           0 :             return sal_False;
     777           0 :         nEndPos = rCmpArr.GetNdEnd();
     778           0 :         lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, false );
     779           0 :         return sal_True;
     780             :     }
     781             : 
     782           0 :     const SwpHints& rHtArr = rTxtNd.GetSwpHints();
     783             :     const SwTxtAttr* pAttr;
     784           0 :     size_t nPos = rHtArr.Count();
     785             :     sal_Int32 nSttPos;
     786             : 
     787             :     // if everything is already there then check with which it will be ended
     788           0 :     if( rCmpArr.Found() )
     789             :     {
     790           0 :         while( nPos )
     791           0 :             if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
     792             :             {
     793           0 :                 nSttPos = *pAttr->GetAnyEnd();
     794           0 :                 if( nSttPos < rCmpArr.GetNdEnd() )
     795             :                 {
     796             :                     // found end
     797           0 :                     nEndPos = rCmpArr.GetNdEnd();
     798           0 :                     lcl_SetAttrPam( rPam, nSttPos, &nEndPos, false );
     799           0 :                     return sal_True;
     800             :                 }
     801             : 
     802             :                 // continue search
     803           0 :                 break;
     804             :             }
     805             : 
     806           0 :         if( !nPos && rCmpArr.Found() )
     807             :         {
     808             :             // found
     809           0 :             nEndPos = rCmpArr.GetNdEnd();
     810           0 :             lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, false );
     811           0 :             return sal_True;
     812             :         }
     813             :     }
     814             : 
     815           0 :     while( nPos )
     816           0 :         if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
     817             :         {
     818             :             // Do multiple start at that position? Do also check those:
     819           0 :             if( nPos )
     820             :             {
     821           0 :                 nEndPos = *pAttr->GetAnyEnd();
     822           0 :                 while( --nPos && nEndPos ==
     823           0 :                         *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
     824           0 :                         rCmpArr.SetAttrBwd( *pAttr ) )
     825             :                     ;
     826             :             }
     827           0 :             if( !rCmpArr.Found() )
     828           0 :                 continue;
     829             : 
     830             :             // then we have our search area
     831           0 :             if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
     832           0 :                 return sal_False;
     833             : 
     834           0 :             lcl_SetAttrPam( rPam, nSttPos, &nEndPos, false );
     835           0 :             return sal_True;
     836             :         }
     837             : 
     838           0 :     if( !rCmpArr.CheckStack() ||
     839           0 :         (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
     840           0 :         return sal_False;
     841             : 
     842           0 :     lcl_SetAttrPam( rPam, nSttPos, &nEndPos, false );
     843           0 :     return sal_True;
     844             : }
     845             : 
     846           0 : static int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, bool bNoColls )
     847             : {
     848             :     // search only hard attribution?
     849           0 :     if( bNoColls && !rCNd.HasSwAttrSet() )
     850           0 :         return sal_False;
     851             : 
     852           0 :     const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
     853           0 :     SfxItemIter aIter( rCmpSet );
     854           0 :     const SfxPoolItem* pItem = aIter.GetCurItem();
     855             :     const SfxPoolItem* pNdItem;
     856             :     sal_uInt16 nWhich;
     857             : 
     858             :     while( true )
     859             :     {
     860           0 :         if( IsInvalidItem( pItem ))
     861             :         {
     862           0 :             nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
     863           0 :             if( SfxItemState::SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
     864           0 :                 || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
     865           0 :                 return sal_False;
     866             :         }
     867             :         else
     868             :         {
     869           0 :             nWhich = pItem->Which();
     870             : 
     871           0 :             if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
     872           0 :                 return sal_False;
     873             :         }
     874             : 
     875           0 :         if( aIter.IsAtEnd() )
     876           0 :             break;
     877           0 :         pItem = aIter.NextItem();
     878             :     }
     879           0 :     return sal_True; // found
     880             : }
     881             : 
     882           0 : bool SwPaM::Find( const SfxPoolItem& rAttr, bool bValue, SwMoveFn fnMove,
     883             :                   const SwPaM *pRegion, bool bInReadOnly )
     884             : {
     885             :     // determine which attribute is searched:
     886           0 :     const sal_uInt16 nWhich = rAttr.Which();
     887           0 :     bool bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
     888             : 
     889           0 :     boost::scoped_ptr<SwPaM> pPam(MakeRegion( fnMove, pRegion ));
     890             : 
     891           0 :     bool bFound = false;
     892           0 :     bool bFirst = true;
     893           0 :     const bool bSrchForward = fnMove == fnMoveForward;
     894             :     SwCntntNode * pNode;
     895             :     const SfxPoolItem* pItem;
     896           0 :     SwpFmts aFmtArr;
     897             : 
     898             :     // if at beginning/end then move it out of the node
     899           0 :     if( bSrchForward
     900           0 :         ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
     901           0 :         : !pPam->GetPoint()->nContent.GetIndex() )
     902             :     {
     903           0 :         if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, false ))
     904             :         {
     905           0 :             return false;
     906             :         }
     907           0 :         SwCntntNode *pNd = pPam->GetCntntNode();
     908           0 :         pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() );
     909             :     }
     910             : 
     911           0 :     while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
     912             :     {
     913           0 :         if( bCharAttr )
     914             :         {
     915           0 :             if( !pNode->IsTxtNode() ) // CharAttr are only in text nodes
     916           0 :                 continue;
     917             : 
     918           0 :             if( ((SwTxtNode*)pNode)->HasHints() &&
     919           0 :                 lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove,  bValue ))
     920             :             {
     921             :                 // set to the values of the attribute
     922           0 :                 SetMark();
     923           0 :                 *GetPoint() = *pPam->GetPoint();
     924           0 :                 *GetMark() = *pPam->GetMark();
     925           0 :                 bFound = true;
     926           0 :                 break;
     927             :             }
     928           0 :             else if (isTXTATR(nWhich))
     929           0 :                 continue;
     930             :         }
     931             : 
     932             :         // no hard attribution, so check if node was asked for this attr before
     933           0 :         if( !pNode->HasSwAttrSet() )
     934             :         {
     935           0 :             SwFmt* pTmpFmt = pNode->GetFmtColl();
     936           0 :             if( aFmtArr.find( pTmpFmt ) != aFmtArr.end() )
     937           0 :                 continue; // collection was requested earlier
     938           0 :             aFmtArr.insert( pTmpFmt );
     939             :         }
     940             : 
     941           0 :         if( SfxItemState::SET == pNode->GetSwAttrSet().GetItemState( nWhich,
     942           0 :             true, &pItem ) && ( !bValue || *pItem == rAttr ) )
     943             :         {
     944             :             // FORWARD:  SPoint at the end, GetMark at the beginning of the node
     945             :             // BACKWARD: SPoint at the beginning, GetMark at the end of the node
     946             :             // always: incl. start and incl. end
     947           0 :             *GetPoint() = *pPam->GetPoint();
     948           0 :             SetMark();
     949           0 :             pNode->MakeEndIndex( &GetPoint()->nContent );
     950           0 :             bFound = true;
     951           0 :             break;
     952             :         }
     953             :     }
     954             : 
     955             :     // if backward search, switch point and mark
     956           0 :     if( bFound && !bSrchForward )
     957           0 :         Exchange();
     958             : 
     959           0 :     return bFound;
     960             : }
     961             : 
     962             : typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
     963             : 
     964           0 : bool SwPaM::Find( const SfxItemSet& rSet, bool bNoColls, SwMoveFn fnMove,
     965             :                   const SwPaM *pRegion, bool bInReadOnly, bool bMoveFirst )
     966             : {
     967           0 :     boost::scoped_ptr<SwPaM> pPam(MakeRegion( fnMove, pRegion ));
     968             : 
     969           0 :     bool bFound = false;
     970           0 :     bool bFirst = true;
     971           0 :     const bool bSrchForward = fnMove == fnMoveForward;
     972             :     SwCntntNode * pNode;
     973           0 :     SwpFmts aFmtArr;
     974             : 
     975             :     // check which text/char attributes are searched
     976           0 :     SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
     977           0 :     SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
     978           0 :                             RES_PARATR_BEGIN, RES_GRFATR_END-1 );
     979           0 :     aOtherSet.Put( rSet, false );   // got all invalid items
     980             : 
     981             :     FnSearchAttr fnSearch = bSrchForward
     982             :                                 ? (&::lcl_SearchForward)
     983           0 :                                 : (&::lcl_SearchBackward);
     984             : 
     985             :     // if at beginning/end then move it out of the node
     986           0 :     if( bMoveFirst &&
     987             :         ( bSrchForward
     988           0 :         ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
     989           0 :         : !pPam->GetPoint()->nContent.GetIndex() ) )
     990             :     {
     991           0 :         if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, false ))
     992             :         {
     993           0 :             return false;
     994             :         }
     995           0 :         SwCntntNode *pNd = pPam->GetCntntNode();
     996           0 :         pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() );
     997             :     }
     998             : 
     999           0 :     while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
    1000             :     {
    1001           0 :         if( aCmpArr.Count() )
    1002             :         {
    1003           0 :             if( !pNode->IsTxtNode() ) // CharAttr are only in text nodes
    1004           0 :                 continue;
    1005             : 
    1006           0 :             if( (!aOtherSet.Count() ||
    1007           0 :                 lcl_Search( *pNode, aOtherSet, bNoColls )) &&
    1008           0 :                 (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
    1009             :             {
    1010             :                 // set to the values of the attribute
    1011           0 :                 SetMark();
    1012           0 :                 *GetPoint() = *pPam->GetPoint();
    1013           0 :                 *GetMark() = *pPam->GetMark();
    1014           0 :                 bFound = true;
    1015           0 :                 break;
    1016             :             }
    1017           0 :             continue; // text attribute
    1018             :         }
    1019             : 
    1020           0 :         if( !aOtherSet.Count() )
    1021           0 :             continue;
    1022             : 
    1023             :         // no hard attribution, so check if node was asked for this attr before
    1024           0 :         if( !pNode->HasSwAttrSet() )
    1025             :         {
    1026           0 :             SwFmt* pTmpFmt = pNode->GetFmtColl();
    1027           0 :             if( aFmtArr.find( pTmpFmt ) != aFmtArr.end() )
    1028           0 :                 continue; // collection was requested earlier
    1029           0 :             aFmtArr.insert( pTmpFmt );
    1030             :         }
    1031             : 
    1032           0 :         if( lcl_Search( *pNode, aOtherSet, bNoColls ))
    1033             :         {
    1034             :             // FORWARD:  SPoint at the end, GetMark at the beginning of the node
    1035             :             // BACKWARD: SPoint at the beginning, GetMark at the end of the node
    1036             :             // always: incl. start and incl. end
    1037           0 :             *GetPoint() = *pPam->GetPoint();
    1038           0 :             SetMark();
    1039           0 :             pNode->MakeEndIndex( &GetPoint()->nContent );
    1040           0 :             bFound = true;
    1041           0 :             break;
    1042             :         }
    1043             :     }
    1044             : 
    1045             :     // if backward search, switch point and mark
    1046           0 :     if( bFound && !bSrchForward )
    1047           0 :         Exchange();
    1048             : 
    1049           0 :     return bFound;
    1050             : }
    1051             : 
    1052             : /// parameters for search for attributes
    1053             : struct SwFindParaAttr : public SwFindParas
    1054             : {
    1055             :     bool bValue;
    1056             :     const SfxItemSet *pSet, *pReplSet;
    1057             :     const SearchOptions *pSearchOpt;
    1058             :     SwCursor& rCursor;
    1059             :     utl::TextSearch* pSTxt;
    1060             : 
    1061           0 :     SwFindParaAttr( const SfxItemSet& rSet, bool bNoCollection,
    1062             :                     const SearchOptions* pOpt, const SfxItemSet* pRSet,
    1063             :                     SwCursor& rCrsr )
    1064             :         : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
    1065           0 :           pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
    1066             : 
    1067           0 :     virtual ~SwFindParaAttr()   { delete pSTxt; }
    1068             : 
    1069             :     virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, bool bInReadOnly ) SAL_OVERRIDE;
    1070             :     virtual bool IsReplaceMode() const SAL_OVERRIDE;
    1071             : };
    1072             : 
    1073           0 : int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
    1074             :                           bool bInReadOnly )
    1075             : {
    1076             :     // replace string (only if text given and search is not parameterized)?
    1077           0 :     bool bReplaceTxt = pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() ||
    1078           0 :                                     !pSet->Count() );
    1079           0 :     bool bReplaceAttr = pReplSet && pReplSet->Count();
    1080           0 :     bool bMoveFirst = !bReplaceAttr;
    1081           0 :     if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
    1082           0 :         bInReadOnly = false;
    1083             : 
    1084             :     // We search for attributes, should we search for text as well?
    1085             :     {
    1086           0 :         SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
    1087           0 :         SwPaM* pTextRegion = &aRegion;
    1088           0 :         SwPaM aSrchPam( *pCrsr->GetPoint() );
    1089             : 
    1090             :         while( true )
    1091             :         {
    1092           0 :             if( pSet->Count() ) // any attributes?
    1093             :             {
    1094             :                 // first attributes
    1095           0 :                 if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
    1096           0 :                     return FIND_NOT_FOUND;
    1097           0 :                 bMoveFirst = true;
    1098             : 
    1099           0 :                 if( !pSearchOpt )
    1100           0 :                     break; // ok, only attributes, so found
    1101             : 
    1102           0 :                 pTextRegion = &aSrchPam;
    1103             :             }
    1104           0 :             else if( !pSearchOpt )
    1105           0 :                 return FIND_NOT_FOUND;
    1106             : 
    1107             :             // then search in text of it
    1108           0 :             if( !pSTxt )
    1109             :             {
    1110           0 :                 SearchOptions aTmp( *pSearchOpt );
    1111             : 
    1112             :                 // search in selection
    1113             :                 aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
    1114           0 :                                     SearchFlags::REG_NOT_ENDOFLINE);
    1115             : 
    1116           0 :                 aTmp.Locale = SvtSysLocale().GetLanguageTag().getLocale();
    1117             : 
    1118           0 :                 pSTxt = new utl::TextSearch( aTmp );
    1119             :             }
    1120             : 
    1121             :             // TODO: searching for attributes in Outliner text?!
    1122           0 :             bool bSearchInNotes = false;
    1123             : 
    1124             :             // continue search in correct section (pTextRegion)
    1125           0 :             if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
    1126           0 :                 *aSrchPam.GetMark() != *aSrchPam.GetPoint() )
    1127           0 :                 break; // found
    1128           0 :             else if( !pSet->Count() )
    1129           0 :                 return FIND_NOT_FOUND; // only text and nothing found
    1130             : 
    1131           0 :             *aRegion.GetMark() = *aSrchPam.GetPoint();
    1132             :         }
    1133             : 
    1134           0 :         *pCrsr->GetPoint() = *aSrchPam.GetPoint();
    1135           0 :         pCrsr->SetMark();
    1136           0 :         *pCrsr->GetMark() = *aSrchPam.GetMark();
    1137             :     }
    1138             : 
    1139           0 :     if( bReplaceTxt )
    1140             :     {
    1141             :         const bool bRegExp(
    1142           0 :                 SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
    1143           0 :         SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
    1144           0 :         const sal_Int32 nSttCnt = rSttCntIdx.GetIndex();
    1145             : 
    1146             :         // add to shell-cursor-ring so that the regions will be moved enventually
    1147           0 :         Ring *pPrevRing = 0;
    1148           0 :         if( bRegExp )
    1149             :         {
    1150           0 :             pPrevRing = pRegion->GetPrev();
    1151           0 :             ((Ring*)pRegion)->MoveRingTo( &rCursor );
    1152             :         }
    1153             : 
    1154             :         boost::scoped_ptr<OUString> pRepl( (bRegExp) ?
    1155           0 :                 ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
    1156           0 :         rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange( *pCrsr,
    1157           0 :             (pRepl.get()) ? *pRepl : pSearchOpt->replaceString,
    1158           0 :             bRegExp );
    1159           0 :         rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
    1160             : 
    1161           0 :         if( bRegExp )
    1162             :         {
    1163             :             // and remove region again
    1164           0 :             Ring *p, *pNext = (Ring*)pRegion;
    1165           0 :             do {
    1166           0 :                 p = pNext;
    1167           0 :                 pNext = p->GetNext();
    1168           0 :                 p->MoveTo( (Ring*)pRegion );
    1169             :             } while( p != pPrevRing );
    1170             :         }
    1171           0 :         rSttCntIdx = nSttCnt;
    1172             :     }
    1173             : 
    1174           0 :     if( bReplaceAttr )
    1175             :     {
    1176             :         // is the selection still existent?
    1177             :         // all searched attributes are reset to default if
    1178             :         // they are not in ReplaceSet
    1179           0 :         if( !pSet->Count() )
    1180             :         {
    1181           0 :             pCrsr->GetDoc()->getIDocumentContentOperations().InsertItemSet( *pCrsr, *pReplSet, 0 );
    1182             :         }
    1183             :         else
    1184             :         {
    1185           0 :             SfxItemPool* pPool = pReplSet->GetPool();
    1186           0 :             SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
    1187             : 
    1188           0 :             SfxItemIter aIter( *pSet );
    1189           0 :             const SfxPoolItem* pItem = aIter.GetCurItem();
    1190             :             while( true )
    1191             :             {
    1192             :                 // reset all that are not set with pool defaults
    1193           0 :                 if( !IsInvalidItem( pItem ) && SfxItemState::SET !=
    1194           0 :                     pReplSet->GetItemState( pItem->Which(), false ))
    1195           0 :                     aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
    1196             : 
    1197           0 :                 if( aIter.IsAtEnd() )
    1198           0 :                     break;
    1199           0 :                 pItem = aIter.NextItem();
    1200             :             }
    1201           0 :             aSet.Put( *pReplSet );
    1202           0 :             pCrsr->GetDoc()->getIDocumentContentOperations().InsertItemSet( *pCrsr, aSet, 0 );
    1203             :         }
    1204             : 
    1205           0 :         return FIND_NO_RING;
    1206             :     }
    1207             :     else
    1208           0 :         return FIND_FOUND;
    1209             : }
    1210             : 
    1211           0 : bool SwFindParaAttr::IsReplaceMode() const
    1212             : {
    1213           0 :     return ( pSearchOpt && !pSearchOpt->replaceString.isEmpty() ) ||
    1214           0 :            ( pReplSet && pReplSet->Count() );
    1215             : }
    1216             : 
    1217             : /// search for attributes
    1218           0 : sal_uLong SwCursor::Find( const SfxItemSet& rSet, bool bNoCollections,
    1219             :                           SwDocPositions nStart, SwDocPositions nEnd,
    1220             :                           bool& bCancel, FindRanges eFndRngs,
    1221             :                           const SearchOptions* pSearchOpt,
    1222             :                           const SfxItemSet* pReplSet )
    1223             : {
    1224             :     // switch off OLE-notifications
    1225           0 :     SwDoc* pDoc = GetDoc();
    1226           0 :     Link aLnk( pDoc->GetOle2Link() );
    1227           0 :     pDoc->SetOle2Link( Link() );
    1228             : 
    1229           0 :     bool bReplace = ( pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() ||
    1230           0 :                                     !rSet.Count() ) ) ||
    1231           0 :                     (pReplSet && pReplSet->Count());
    1232           0 :     bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
    1233           0 :     if (bStartUndo)
    1234             :     {
    1235           0 :         pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
    1236             :     }
    1237             : 
    1238             :     SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
    1239           0 :                                     pReplSet, *this );
    1240             : 
    1241           0 :     sal_uLong nRet = FindAll( aSwFindParaAttr, nStart, nEnd, eFndRngs, bCancel );
    1242           0 :     pDoc->SetOle2Link( aLnk );
    1243           0 :     if( nRet && bReplace )
    1244           0 :         pDoc->getIDocumentState().SetModified();
    1245             : 
    1246           0 :     if (bStartUndo)
    1247             :     {
    1248           0 :         pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
    1249             :     }
    1250             : 
    1251           0 :     return nRet;
    1252         270 : }
    1253             : 
    1254             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10