LCOV - code coverage report
Current view: top level - sw/source/core/crsr - findattr.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 593 0.2 %
Date: 2015-06-13 12:38:46 Functions: 2 32 6.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11