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

Generated by: LCOV version 1.10