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

Generated by: LCOV version 1.10