| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| #include <com/sun/star/lang/Locale.hpp> |
| #include <com/sun/star/util/SearchOptions.hpp> |
| #include <com/sun/star/util/SearchFlags.hpp> |
| #include <i18npool/mslangid.hxx> |
| #include <hintids.hxx> |
| #include <vcl/svapp.hxx> |
| #include <svl/itemiter.hxx> |
| #include <svl/whiter.hxx> |
| #include <editeng/brkitem.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <fmtpdsc.hxx> |
| #include <txatbase.hxx> |
| #include <fchrfmt.hxx> |
| #include <charfmt.hxx> |
| #include <doc.hxx> |
| #include <IDocumentUndoRedo.hxx> |
| #include <swcrsr.hxx> |
| #include <editsh.hxx> |
| #include <ndtxt.hxx> |
| #include <pamtyp.hxx> |
| #include <swundo.hxx> |
| #include <crsskip.hxx> |
| |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::util; |
| |
| SV_DECL_PTRARR_SORT( SwpFmts, SwFmt*, 0, 4 ) |
| SV_IMPL_PTRARR_SORT( SwpFmts, SwFmt* ) |
| |
| // Sonderbehandlung fuer SvxFontItem, nur den Namen vergleichen: |
| int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 ) |
| { |
| switch( rItem1.Which() ) |
| { |
| case RES_CHRATR_FONT: |
| return ((SvxFontItem&)rItem1).GetFamilyName() == |
| ((SvxFontItem&)rItem2).GetFamilyName(); |
| |
| case RES_CHRATR_COLOR: |
| return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual( |
| ((SvxColorItem&)rItem2).GetValue() ); |
| case RES_PAGEDESC: |
| return ((SwFmtPageDesc&)rItem1).GetNumOffset() == |
| ((SwFmtPageDesc&)rItem2).GetNumOffset() && |
| ((SwFmtPageDesc&)rItem1).GetPageDesc() == |
| ((SwFmtPageDesc&)rItem2).GetPageDesc(); |
| } |
| return rItem1 == rItem2; |
| } |
| |
| |
| const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos, |
| xub_StrLen nCntntPos ) |
| { |
| while( rPos < rHtsArr.Count() ) |
| { |
| const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ ); |
| // der Start vom Attribut muss innerhalb des Bereiches liegen !! |
| if( *pTxtHt->GetStart() >= nCntntPos ) |
| return pTxtHt; // gueltiges TextAttribut |
| } |
| return 0; // kein gueltiges TextAttribut |
| } |
| |
| |
| const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos, |
| xub_StrLen nCntntPos ) |
| { |
| while( rPos > 0 ) |
| { |
| //Hack mit cast fuer das Update |
| const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos ); |
| // der Start vom Attribut muss innerhalb des Bereiches liegen !! |
| if( *pTxtHt->GetStart() < nCntntPos ) |
| return pTxtHt; // gueltiges TextAttribut |
| } |
| return 0; // kein gueltiges TextAttribut |
| } |
| |
| |
| void lcl_SetAttrPam( SwPaM & rPam, xub_StrLen nStart, const xub_StrLen* pEnde, |
| const sal_Bool bSaveMark ) |
| { |
| xub_StrLen nCntntPos; |
| if( bSaveMark ) |
| nCntntPos = rPam.GetMark()->nContent.GetIndex(); |
| else |
| nCntntPos = rPam.GetPoint()->nContent.GetIndex(); |
| sal_Bool bTstEnde = rPam.GetPoint()->nNode == rPam.GetMark()->nNode; |
| |
| SwCntntNode* pCNd = rPam.GetCntntNode(); |
| rPam.GetPoint()->nContent.Assign( pCNd, nStart ); |
| rPam.SetMark(); // Point == GetMark |
| |
| // Point zeigt auf das Ende vom SuchBereich oder Ende vom Attribut |
| if( pEnde ) |
| { |
| if( bTstEnde && *pEnde > nCntntPos ) |
| rPam.GetPoint()->nContent = nCntntPos; |
| else |
| rPam.GetPoint()->nContent = *pEnde; |
| } |
| } |
| |
| //------------------ Suche nach einem Text Attribut ----------------------- |
| |
| // diese Funktion sucht in einem TextNode nach dem vorgegebenen Attribut. |
| // Wird es gefunden, dann hat der SwPaM den Bereich der das Attribut |
| // umspannt, unter Beachtung des Suchbereiches |
| |
| |
| sal_Bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam, |
| const SfxPoolItem& rCmpItem, |
| SwMoveFn fnMove, sal_Bool bValue ) |
| { |
| if ( !rTxtNd.HasHints() ) |
| return sal_False; |
| const SwTxtAttr *pTxtHt = 0; |
| sal_Bool bForward = fnMove == fnMoveForward; |
| sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count(); |
| xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex(); |
| |
| while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos))) |
| if( pTxtHt->Which() == rCmpItem.Which() && |
| ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem ))) |
| { |
| lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->End(), bForward ); |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| |
| //------------------ Suche nach mehren Text Attributen ------------------- |
| |
| struct _SwSrchChrAttr |
| { |
| sal_uInt16 nWhich; |
| xub_StrLen nStt, nEnd; |
| |
| _SwSrchChrAttr( const SfxPoolItem& rItem, |
| xub_StrLen nStart, xub_StrLen nAnyEnd ) |
| : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd ) |
| {} |
| }; |
| |
| class SwAttrCheckArr |
| { |
| _SwSrchChrAttr *pFndArr, *pStackArr; |
| xub_StrLen nNdStt, nNdEnd; |
| sal_uInt16 nArrStart, nArrLen; |
| sal_uInt16 nFound, nStackCnt; |
| SfxItemSet aCmpSet; |
| sal_Bool bNoColls; |
| sal_Bool bForward; |
| |
| public: |
| SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections ); |
| ~SwAttrCheckArr(); |
| |
| void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam ); |
| |
| // wieviele Attribute ueberhaupt ?? |
| sal_uInt16 Count() const { return aCmpSet.Count(); } |
| int Found() const { return nFound == aCmpSet.Count(); } |
| int CheckStack(); |
| |
| xub_StrLen Start() const; |
| xub_StrLen End() const; |
| |
| xub_StrLen GetNdStt() const { return nNdStt; } |
| xub_StrLen GetNdEnd() const { return nNdEnd; } |
| |
| int SetAttrFwd( const SwTxtAttr& rAttr ); |
| int SetAttrBwd( const SwTxtAttr& rAttr ); |
| }; |
| |
| |
| |
| SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd, |
| int bNoCollections ) |
| : aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 ) |
| { |
| aCmpSet.Put( rSet, sal_False ); |
| bNoColls = 0 != bNoCollections; |
| |
| bForward = 0 != bFwd; |
| |
| // Bestimmen den Bereich des Fnd/Stack-Arrays (Min/Max) |
| SfxItemIter aIter( aCmpSet ); |
| nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() ); |
| nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1; |
| |
| char* pFndChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ]; |
| char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ]; |
| |
| pFndArr = (_SwSrchChrAttr*)pFndChar; |
| pStackArr = (_SwSrchChrAttr*)pStackChar; |
| } |
| |
| SwAttrCheckArr::~SwAttrCheckArr() |
| { |
| delete[] (char*)pFndArr; |
| delete[] (char*)pStackArr; |
| } |
| |
| void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam ) |
| { |
| memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) ); |
| memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) ); |
| nFound = 0; |
| nStackCnt = 0; |
| |
| if( bForward ) |
| { |
| nNdStt = rPam.GetPoint()->nContent.GetIndex(); |
| nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode |
| ? rPam.GetMark()->nContent.GetIndex() |
| : rTxtNd.GetTxt().Len(); |
| } |
| else |
| { |
| nNdEnd = rPam.GetPoint()->nContent.GetIndex(); |
| nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode |
| ? rPam.GetMark()->nContent.GetIndex() |
| : 0; |
| } |
| |
| if( bNoColls && !rTxtNd.HasSwAttrSet() ) |
| return ; |
| |
| const SfxItemSet& rSet = rTxtNd.GetSwAttrSet(); |
| // if( !rSet.Count() ) |
| // return; |
| |
| SfxItemIter aIter( aCmpSet ); |
| const SfxPoolItem* pItem = aIter.GetCurItem(); |
| const SfxPoolItem* pFndItem; |
| sal_uInt16 nWhich; |
| |
| while( sal_True ) |
| { |
| // nur testen, ob vorhanden ist ? |
| if( IsInvalidItem( pItem ) ) |
| { |
| nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() ); |
| if( RES_TXTATR_END <= nWhich ) |
| break; // Ende der TextAttribute |
| |
| if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem ) |
| && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) )) |
| { |
| pFndArr[ nWhich - nArrStart ] = |
| _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd ); |
| nFound++; |
| } |
| } |
| else |
| { |
| if( RES_TXTATR_END <= (nWhich = pItem->Which() )) |
| break; // Ende der TextAttribute |
| |
| //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool |
| // runter |
| // if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem ) |
| // && *pFndItem == *pItem ) |
| if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) ) |
| { |
| pFndArr[ nWhich - nArrStart ] = |
| _SwSrchChrAttr( *pItem, nNdStt, nNdEnd ); |
| nFound++; |
| } |
| } |
| |
| if( aIter.IsAtEnd() ) |
| break; |
| pItem = aIter.NextItem(); |
| } |
| } |
| |
| static bool |
| lcl_IsAttributeIgnorable(xub_StrLen const nNdStart, xub_StrLen const nNdEnd, |
| _SwSrchChrAttr const& rTmp) |
| { |
| // #i115528#: if there is a paragraph attribute, it has been added by the |
| // SwAttrCheckArr ctor, and nFound is 1. |
| // if the paragraph is entirely covered by hints that override the paragraph |
| // attribute, then this function must find an attribute to decrement nFound! |
| // so check for an empty search range, let attributes that start/end there |
| // cover it, and hope for the best... |
| return ((nNdEnd == nNdStart) |
| ? ((rTmp.nEnd < nNdStart) || (nNdEnd < rTmp.nStt)) |
| : ((rTmp.nEnd <= nNdStart) || (nNdEnd <= rTmp.nStt))); |
| } |
| |
| int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr ) |
| { |
| _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() ); |
| |
| // ignore all attributes not in search range |
| if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp)) |
| { |
| return Found(); |
| } |
| |
| const SfxPoolItem* pItem; |
| // -------------------------------------------------------------- |
| // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht |
| // -------------------------------------------------------------- |
| sal_uInt16 nWhch = rAttr.Which(); |
| SfxWhichIter* pIter = NULL; |
| const SfxPoolItem* pTmpItem = NULL; |
| const SfxItemSet* pSet = NULL; |
| if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch ) |
| { |
| if( bNoColls && RES_TXTATR_CHARFMT == nWhch ) |
| return Found(); |
| pTmpItem = NULL; |
| pSet = CharFmt::GetItemSet( rAttr.GetAttr() ); |
| if ( pSet ) |
| { |
| pIter = new SfxWhichIter( *pSet ); |
| nWhch = pIter->FirstWhich(); |
| while( nWhch && |
| SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) ) |
| nWhch = pIter->NextWhich(); |
| if( !nWhch ) |
| pTmpItem = NULL; |
| } |
| } |
| else |
| pTmpItem = &rAttr.GetAttr(); |
| while( pTmpItem ) |
| { |
| SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem ); |
| if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState ) |
| { |
| sal_uInt16 n; |
| _SwSrchChrAttr* pCmp; |
| |
| // loesche erstmal alle, die bis zu der Start Position schon wieder |
| // ungueltig sind: |
| |
| _SwSrchChrAttr* pArrPtr; |
| if( nFound ) |
| for( pArrPtr = pFndArr, n = 0; n < nArrLen; |
| ++n, ++pArrPtr ) |
| if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt ) |
| { |
| pArrPtr->nWhich = 0; // geloescht |
| nFound--; |
| } |
| |
| // loesche erstmal alle, die bis zu der Start Position schon wieder |
| // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber |
| // die Start Position ragen, vom Stack in den FndSet |
| |
| if( nStackCnt ) |
| for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr ) |
| { |
| if( !pArrPtr->nWhich ) |
| continue; |
| |
| if( pArrPtr->nEnd <= aTmp.nStt ) |
| { |
| pArrPtr->nWhich = 0; // geloescht |
| if( !--nStackCnt ) |
| break; |
| } |
| else if( pArrPtr->nStt <= aTmp.nStt ) |
| { |
| if( ( pCmp = &pFndArr[ n ])->nWhich ) |
| { |
| if( pCmp->nEnd < pArrPtr->nEnd ) // erweitern |
| pCmp->nEnd = pArrPtr->nEnd; |
| } |
| else |
| { |
| *pCmp = *pArrPtr; |
| nFound++; |
| } |
| pArrPtr->nWhich = 0; |
| if( !--nStackCnt ) |
| break; |
| } |
| } |
| |
| sal_Bool bContinue = sal_False; |
| |
| if( SFX_ITEM_DONTCARE == eState ) |
| { |
| // wird Attribut gueltig ? |
| if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ), |
| *pTmpItem )) |
| { |
| // suche das Attribut und erweiter es gegebenenfalls |
| if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich ) |
| { |
| *pCmp = aTmp; // nicht gefunden, eintragen |
| nFound++; |
| } |
| else if( pCmp->nEnd < aTmp.nEnd ) // erweitern ? |
| pCmp->nEnd = aTmp.nEnd; |
| |
| bContinue = sal_True; |
| } |
| } |
| // wird Attribut gueltig ? |
| else if( CmpAttr( *pItem, *pTmpItem ) ) |
| { |
| pFndArr[ nWhch - nArrStart ] = aTmp; |
| ++nFound; |
| bContinue = sal_True; |
| } |
| |
| // tja, dann muss es auf den Stack |
| if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich ) |
| { |
| // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist |
| if( pCmp->nEnd > aTmp.nEnd ) |
| { |
| ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich, |
| "Stack-Platz ist noch belegt" ); |
| |
| // --------- |
| // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547 |
| // pCmp->nStt = aTmp.nEnd; |
| if( aTmp.nStt <= pCmp->nStt ) |
| pCmp->nStt = aTmp.nEnd; |
| else |
| pCmp->nEnd = aTmp.nStt; |
| // --------- |
| |
| pStackArr[ nWhch - nArrStart ] = *pCmp; |
| nStackCnt++; |
| } |
| pCmp->nWhich = 0; |
| nFound--; |
| } |
| } |
| if( pIter ) |
| { |
| nWhch = pIter->NextWhich(); |
| while( nWhch && |
| SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) ) |
| nWhch = pIter->NextWhich(); |
| if( !nWhch ) |
| break; |
| } |
| else |
| break; |
| } |
| return Found(); |
| } |
| |
| |
| int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr ) |
| { |
| _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() ); |
| |
| // ignore all attributes not in search range |
| if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp)) |
| { |
| return Found(); |
| } |
| |
| const SfxPoolItem* pItem; |
| // -------------------------------------------------------------- |
| // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht |
| // -------------------------------------------------------------- |
| sal_uInt16 nWhch = rAttr.Which(); |
| SfxWhichIter* pIter = NULL; |
| const SfxPoolItem* pTmpItem = NULL; |
| const SfxItemSet* pSet = NULL; |
| if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch ) |
| { |
| if( bNoColls && RES_TXTATR_CHARFMT == nWhch ) |
| return Found(); |
| |
| pSet = CharFmt::GetItemSet( rAttr.GetAttr() ); |
| if ( pSet ) |
| { |
| pIter = new SfxWhichIter( *pSet ); |
| nWhch = pIter->FirstWhich(); |
| while( nWhch && |
| SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) ) |
| nWhch = pIter->NextWhich(); |
| if( !nWhch ) |
| pTmpItem = NULL; |
| } |
| } |
| else |
| pTmpItem = &rAttr.GetAttr(); |
| while( pTmpItem ) |
| { |
| SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem ); |
| if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState ) |
| { |
| sal_uInt16 n; |
| _SwSrchChrAttr* pCmp; |
| |
| // loesche erstmal alle, die bis zu der Start Position schon wieder |
| // ungueltig sind: |
| |
| _SwSrchChrAttr* pArrPtr; |
| if( nFound ) |
| for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr ) |
| if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd ) |
| { |
| pArrPtr->nWhich = 0; // geloescht |
| nFound--; |
| } |
| |
| // loesche erstmal alle, die bis zu der Start Position schon wieder |
| // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber |
| // die Start Position ragen, vom Stack in den FndSet |
| |
| if( nStackCnt ) |
| for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr ) |
| { |
| if( !pArrPtr->nWhich ) |
| continue; |
| |
| if( pArrPtr->nStt >= aTmp.nEnd ) |
| { |
| pArrPtr->nWhich = 0; // geloescht |
| if( !--nStackCnt ) |
| break; |
| } |
| else if( pArrPtr->nEnd >= aTmp.nEnd ) |
| { |
| if( ( pCmp = &pFndArr[ n ])->nWhich ) |
| { |
| if( pCmp->nStt > pArrPtr->nStt ) // erweitern |
| pCmp->nStt = pArrPtr->nStt; |
| } |
| else |
| { |
| *pCmp = *pArrPtr; |
| nFound++; |
| } |
| pArrPtr->nWhich = 0; |
| if( !--nStackCnt ) |
| break; |
| } |
| } |
| |
| sal_Bool bContinue = sal_False; |
| if( SFX_ITEM_DONTCARE == eState ) |
| { |
| // wird Attribut gueltig ? |
| if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ), |
| *pTmpItem ) ) |
| { |
| // suche das Attribut und erweiter es gegebenenfalls |
| if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich ) |
| { |
| *pCmp = aTmp; // nicht gefunden, eintragen |
| nFound++; |
| } |
| else if( pCmp->nStt > aTmp.nStt ) // erweitern ? |
| pCmp->nStt = aTmp.nStt; |
| |
| bContinue = sal_True; |
| } |
| } |
| // wird Attribut gueltig ? |
| else if( CmpAttr( *pItem, *pTmpItem )) |
| { |
| pFndArr[ nWhch - nArrStart ] = aTmp; |
| ++nFound; |
| bContinue = sal_True; |
| } |
| |
| // tja, dann muss es auf den Stack |
| if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich ) |
| { |
| // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist |
| if( pCmp->nStt < aTmp.nStt ) |
| { |
| ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich, |
| "Stack-Platz ist noch belegt" ); |
| |
| // --------- |
| // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547 |
| // pCmp->nEnd = aTmp.nStt; |
| if( aTmp.nEnd <= pCmp->nEnd ) |
| pCmp->nEnd = aTmp.nStt; |
| else |
| pCmp->nStt = aTmp.nEnd; |
| // --------- |
| |
| pStackArr[ nWhch - nArrStart ] = *pCmp; |
| nStackCnt++; |
| } |
| pCmp->nWhich = 0; |
| nFound--; |
| } |
| } |
| if( pIter ) |
| { |
| nWhch = pIter->NextWhich(); |
| while( nWhch && |
| SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) ) |
| nWhch = pIter->NextWhich(); |
| if( !nWhch ) |
| break; |
| } |
| else |
| break; |
| } |
| return Found(); |
| } |
| |
| |
| xub_StrLen SwAttrCheckArr::Start() const |
| { |
| xub_StrLen nStart = nNdStt; |
| _SwSrchChrAttr* pArrPtr = pFndArr; |
| for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr ) |
| if( pArrPtr->nWhich && pArrPtr->nStt > nStart ) |
| nStart = pArrPtr->nStt; |
| |
| return nStart; |
| } |
| |
| |
| xub_StrLen SwAttrCheckArr::End() const |
| { |
| _SwSrchChrAttr* pArrPtr = pFndArr; |
| xub_StrLen nEnd = nNdEnd; |
| for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr ) |
| if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd ) |
| nEnd = pArrPtr->nEnd; |
| |
| return nEnd; |
| } |
| |
| |
| int SwAttrCheckArr::CheckStack() |
| { |
| if( !nStackCnt ) |
| return sal_False; |
| |
| sal_uInt16 n; |
| xub_StrLen nSttPos = Start(), nEndPos = End(); |
| _SwSrchChrAttr* pArrPtr; |
| for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr ) |
| { |
| if( !pArrPtr->nWhich ) |
| continue; |
| |
| if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos ) |
| { |
| pArrPtr->nWhich = 0; // geloescht |
| if( !--nStackCnt ) |
| return nFound == aCmpSet.Count(); |
| } |
| else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos ) |
| { |
| // alle die "offen" sind, heisst ueber die Start Position ragen, |
| // im FndSet setzen |
| ASSERT( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" ); |
| pFndArr[ n ] = *pArrPtr; |
| pArrPtr->nWhich = 0; |
| nFound++; |
| if( !--nStackCnt ) |
| return nFound == aCmpSet.Count(); |
| } |
| } |
| return nFound == aCmpSet.Count(); |
| } |
| |
| |
| |
| int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr, |
| SwPaM& rPam ) |
| { |
| xub_StrLen nEndPos, nSttPos; |
| rCmpArr.SetNewSet( rTxtNd, rPam ); |
| if( !rTxtNd.HasHints() ) |
| { |
| if( !rCmpArr.Found() ) |
| return sal_False; |
| nEndPos = rCmpArr.GetNdEnd(); |
| lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True ); |
| return sal_True; |
| } |
| |
| // dann gehe mal durch das nach "Start" sortierte Array |
| const SwpHints& rHtArr = rTxtNd.GetSwpHints(); |
| const SwTxtAttr* pAttr; |
| sal_uInt16 nPos = 0; |
| |
| // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem |
| // das wieder beendet wird. |
| if( rCmpArr.Found() ) |
| { |
| for( ; nPos < rHtArr.Count(); ++nPos ) |
| if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) ) |
| { |
| if( rCmpArr.GetNdStt() < *pAttr->GetStart() ) |
| { |
| // dann haben wir unser Ende: |
| lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), |
| pAttr->GetStart(), sal_True ); |
| return sal_True; |
| } |
| // ansonsten muessen wir weiter suchen |
| break; |
| } |
| |
| if( nPos == rHtArr.Count() && rCmpArr.Found() ) |
| { |
| // dann haben wir unseren Bereich |
| nEndPos = rCmpArr.GetNdEnd(); |
| lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True ); |
| return sal_True; |
| } |
| } |
| |
| for( ; nPos < rHtArr.Count(); ++nPos ) |
| if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) ) |
| { |
| // sollten noch mehr auf der gleichen Position anfangen ?? |
| // auch die noch mit testen !! |
| nSttPos = *pAttr->GetStart(); |
| while( ++nPos < rHtArr.Count() && nSttPos == |
| *( pAttr = rHtArr.GetStart( nPos ))->GetStart() && |
| rCmpArr.SetAttrFwd( *pAttr ) ) |
| ; |
| if( !rCmpArr.Found() ) |
| continue; |
| |
| // dann haben wir den Bereich zusammen |
| if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) ) |
| return sal_False; |
| lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True ); |
| return sal_True; |
| } |
| |
| if( !rCmpArr.CheckStack() || |
| (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) ) |
| return sal_False; |
| lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True ); |
| return sal_True; |
| } |
| |
| |
| int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr, |
| SwPaM& rPam ) |
| { |
| xub_StrLen nEndPos, nSttPos; |
| rCmpArr.SetNewSet( rTxtNd, rPam ); |
| if( !rTxtNd.HasHints() ) |
| { |
| if( !rCmpArr.Found() ) |
| return sal_False; |
| nEndPos = rCmpArr.GetNdEnd(); |
| lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False ); |
| return sal_True; |
| } |
| |
| // dann gehe mal durch das nach "Start" sortierte Array |
| const SwpHints& rHtArr = rTxtNd.GetSwpHints(); |
| const SwTxtAttr* pAttr; |
| sal_uInt16 nPos = rHtArr.Count(); |
| |
| // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem |
| // das wieder beendet wird. |
| if( rCmpArr.Found() ) |
| { |
| while( nPos ) |
| if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) ) |
| { |
| nSttPos = *pAttr->GetAnyEnd(); |
| if( nSttPos < rCmpArr.GetNdEnd() ) |
| { |
| // dann haben wir unser Ende: |
| nEndPos = rCmpArr.GetNdEnd(); |
| lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False ); |
| return sal_True; |
| } |
| |
| // ansonsten muessen wir weiter suchen |
| break; |
| } |
| |
| if( !nPos && rCmpArr.Found() ) |
| { |
| // dann haben wir unseren Bereich |
| nEndPos = rCmpArr.GetNdEnd(); |
| lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False ); |
| return sal_True; |
| } |
| } |
| |
| while( nPos ) |
| if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) ) |
| { |
| // sollten noch mehr auf der gleichen Position anfangen ?? |
| // auch die noch mit testen !! |
| if( nPos ) |
| { |
| nEndPos = *pAttr->GetAnyEnd(); |
| while( --nPos && nEndPos == |
| *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() && |
| rCmpArr.SetAttrBwd( *pAttr ) ) |
| ; |
| } |
| if( !rCmpArr.Found() ) |
| continue; |
| |
| |
| // dann haben wir den Bereich zusammen |
| if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) ) |
| return sal_False; |
| lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False ); |
| return sal_True; |
| } |
| |
| if( !rCmpArr.CheckStack() || |
| (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) ) |
| return sal_False; |
| lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False ); |
| return sal_True; |
| } |
| |
| |
| int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls ) |
| { |
| // nur die harte Attributierung suchen ? |
| if( bNoColls && !rCNd.HasSwAttrSet() ) |
| return sal_False; |
| |
| const SfxItemSet& rNdSet = rCNd.GetSwAttrSet(); |
| SfxItemIter aIter( rCmpSet ); |
| const SfxPoolItem* pItem = aIter.GetCurItem(); |
| const SfxPoolItem* pNdItem; |
| sal_uInt16 nWhich; |
| |
| while( sal_True ) |
| { |
| // nur testen, ob vorhanden ist ? |
| if( IsInvalidItem( pItem )) |
| { |
| nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() ); |
| if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem ) |
| || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) )) |
| return sal_False; |
| } |
| else |
| { |
| nWhich = pItem->Which(); |
| //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool |
| // runter |
| // if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem ) |
| // || *pNdItem != *pItem ) |
| if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem )) |
| return sal_False; |
| } |
| |
| if( aIter.IsAtEnd() ) |
| break; |
| pItem = aIter.NextItem(); |
| } |
| return sal_True; // wurde gefunden |
| } |
| |
| |
| sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove, |
| const SwPaM *pRegion, sal_Bool bInReadOnly ) |
| { |
| // stelle fest welches Attribut gesucht wird: |
| const sal_uInt16 nWhich = rAttr.Which(); |
| int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich); |
| |
| SwPaM* pPam = MakeRegion( fnMove, pRegion ); |
| |
| sal_Bool bFound = sal_False; |
| sal_Bool bFirst = sal_True; |
| sal_Bool bSrchForward = fnMove == fnMoveForward; |
| SwCntntNode * pNode; |
| const SfxPoolItem* pItem; |
| SwpFmts aFmtArr; |
| |
| // Wenn am Anfang/Ende, aus dem Node moven |
| if( bSrchForward |
| ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len() |
| : !pPam->GetPoint()->nContent.GetIndex() ) |
| { |
| if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False )) |
| { |
| delete pPam; |
| return sal_False; |
| } |
| SwCntntNode *pNd = pPam->GetCntntNode(); |
| xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len(); |
| pPam->GetPoint()->nContent.Assign( pNd, nTmpPos ); |
| } |
| |
| while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) ) |
| { |
| if( bCharAttr ) |
| { |
| if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes |
| continue; |
| |
| if( ((SwTxtNode*)pNode)->HasHints() && |
| lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove, bValue )) |
| { |
| // setze auf die Werte vom Attribut |
| SetMark(); |
| *GetPoint() = *pPam->GetPoint(); |
| *GetMark() = *pPam->GetMark(); |
| bFound = sal_True; |
| break; |
| } |
| else if (isTXTATR(nWhich)) |
| continue; // --> also weiter |
| } |
| |
| // keine harte Attributierung, dann pruefe, ob die Vorlage schon |
| // mal nach dem Attribut befragt wurde |
| if( !pNode->HasSwAttrSet() ) |
| { |
| const SwFmt* pTmpFmt = pNode->GetFmtColl(); |
| if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt )) |
| continue; // die Collection wurde schon mal befragt |
| aFmtArr.Insert( pTmpFmt ); |
| } |
| |
| if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich, |
| sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) ) |
| { |
| // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node |
| // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node |
| // und immer nach der Logik: inkl. Start, exkl. End !!! |
| *GetPoint() = *pPam->GetPoint(); |
| SetMark(); |
| pNode->MakeEndIndex( &GetPoint()->nContent ); |
| bFound = sal_True; |
| break; |
| } |
| } |
| |
| // beim rueckwaerts Suchen noch Point und Mark vertauschen |
| if( bFound && !bSrchForward ) |
| Exchange(); |
| |
| delete pPam; |
| return bFound; |
| } |
| |
| |
| typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& ); |
| |
| sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove, |
| const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst ) |
| { |
| SwPaM* pPam = MakeRegion( fnMove, pRegion ); |
| |
| sal_Bool bFound = sal_False; |
| sal_Bool bFirst = sal_True; |
| sal_Bool bSrchForward = fnMove == fnMoveForward; |
| SwCntntNode * pNode; |
| SwpFmts aFmtArr; |
| |
| // teste doch mal welche Text/Char-Attribute gesucht werden |
| SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls ); |
| SfxItemSet aOtherSet( GetDoc()->GetAttrPool(), |
| RES_PARATR_BEGIN, RES_GRFATR_END-1 ); |
| aOtherSet.Put( rSet, sal_False ); // alle Invalid-Items erhalten! |
| |
| FnSearchAttr fnSearch = bSrchForward |
| ? (&::lcl_SearchForward) |
| : (&::lcl_SearchBackward); |
| |
| // Wenn am Anfang/Ende, aus dem Node moven |
| // Wenn am Anfang/Ende, aus dem Node moven |
| if( bMoveFirst && |
| ( bSrchForward |
| ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len() |
| : !pPam->GetPoint()->nContent.GetIndex() ) ) |
| { |
| if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False )) |
| { |
| delete pPam; |
| return sal_False; |
| } |
| SwCntntNode *pNd = pPam->GetCntntNode(); |
| xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len(); |
| pPam->GetPoint()->nContent.Assign( pNd, nTmpPos ); |
| } |
| |
| |
| while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) ) |
| { |
| if( aCmpArr.Count() ) |
| { |
| if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes |
| continue; |
| |
| if( (!aOtherSet.Count() || |
| lcl_Search( *pNode, aOtherSet, bNoColls )) && |
| (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam )) |
| { |
| // setze auf die Werte vom Attribut |
| SetMark(); |
| *GetPoint() = *pPam->GetPoint(); |
| *GetMark() = *pPam->GetMark(); |
| bFound = sal_True; |
| break; |
| } |
| continue; // TextAttribute |
| } |
| |
| if( !aOtherSet.Count() ) |
| continue; |
| |
| // keine harte Attributierung, dann pruefe, ob die Vorlage schon |
| // mal nach dem Attribut befragt wurde |
| if( !pNode->HasSwAttrSet() ) |
| { |
| const SwFmt* pTmpFmt = pNode->GetFmtColl(); |
| if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt )) |
| continue; // die Collection wurde schon mal befragt |
| aFmtArr.Insert( pTmpFmt ); |
| } |
| |
| if( lcl_Search( *pNode, aOtherSet, bNoColls )) |
| { |
| // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node |
| // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node |
| // und immer nach der Logik: inkl. Start, exkl. End !!! |
| *GetPoint() = *pPam->GetPoint(); |
| SetMark(); |
| pNode->MakeEndIndex( &GetPoint()->nContent ); |
| bFound = sal_True; |
| break; |
| } |
| } |
| |
| // beim rueckwaerts Suchen noch Point und Mark vertauschen |
| if( bFound && !bSrchForward ) |
| Exchange(); |
| |
| delete pPam; |
| return bFound; |
| } |
| |
| //------------------ Methoden vom SwCursor --------------------------- |
| |
| // Parameter fuer das Suchen vom Attributen |
| struct SwFindParaAttr : public SwFindParas |
| { |
| sal_Bool bValue; |
| const SfxItemSet *pSet, *pReplSet; |
| const SearchOptions *pSearchOpt; |
| SwCursor& rCursor; |
| utl::TextSearch* pSTxt; |
| |
| SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection, |
| const SearchOptions* pOpt, const SfxItemSet* pRSet, |
| SwCursor& rCrsr ) |
| : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ), |
| pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {} |
| |
| virtual ~SwFindParaAttr() { delete pSTxt; } |
| |
| virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly ); |
| virtual int IsReplaceMode() const; |
| }; |
| |
| |
| int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion, |
| sal_Bool bInReadOnly ) |
| { |
| // String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert |
| // gesucht wird) |
| sal_Bool bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() || |
| !pSet->Count() ); |
| sal_Bool bReplaceAttr = pReplSet && pReplSet->Count(); |
| sal_Bool bMoveFirst = !bReplaceAttr; |
| if( bInReadOnly && (bReplaceAttr || bReplaceTxt )) |
| bInReadOnly = sal_False; |
| |
| // wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ? |
| { |
| SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() ); |
| SwPaM* pTextRegion = &aRegion; |
| SwPaM aSrchPam( *pCrsr->GetPoint() ); |
| |
| while( sal_True ) |
| { |
| if( pSet->Count() ) // gibts ueberhaupt Attributierung? |
| { |
| // zuerst die Attributierung |
| if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) ) |
| //JP 17.11.95: was ist mit Attributen in leeren Absaetzen !! |
| // || *pCrsr->GetMark() == *pCrsr->GetPoint() ) // kein Bereich ?? |
| return FIND_NOT_FOUND; |
| bMoveFirst = sal_True; |
| |
| if( !pSearchOpt ) |
| break; // ok, nur Attribute, also gefunden |
| |
| pTextRegion = &aSrchPam; |
| } |
| else if( !pSearchOpt ) |
| return FIND_NOT_FOUND; |
| |
| // dann darin den Text |
| if( !pSTxt ) |
| { |
| SearchOptions aTmp( *pSearchOpt ); |
| |
| // search in selection |
| aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE | |
| SearchFlags::REG_NOT_ENDOFLINE); |
| |
| MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale ); |
| |
| pSTxt = new utl::TextSearch( aTmp ); |
| } |
| |
| // todo/mba: searching for attributes in Outliner text?! |
| sal_Bool bSearchInNotes = sal_False; |
| |
| // Bug 24665: suche im richtigen Bereich weiter (pTextRegion!) |
| if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) && |
| *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) // gefunden ? |
| break; // also raus |
| else if( !pSet->Count() ) |
| return FIND_NOT_FOUND; // nur Text und nicht gefunden |
| |
| /* // --> FME 2007-4-12 #i74765 # Why should we move the position? |
| Moving the position results in bugs when there are two adjacent |
| portions which both have the requested attributes set. I suspect this |
| should be only be an optimization. Therefore I boldly remove it now! |
| |
| // JP: und wieder neu aufsetzen, aber eine Position weiter |
| //JP 04.11.97: Bug 44897 - aber den Mark wieder aufheben, damit |
| // weiterbewegt werden kann! |
| { |
| sal_Bool bCheckRegion = sal_True; |
| SwPosition* pPos = aSrchPam.GetPoint(); |
| if( !(*fnMove->fnNd)( &pPos->nNode.GetNode(), |
| &pPos->nContent, CRSR_SKIP_CHARS )) |
| { |
| if( (*fnMove->fnNds)( &pPos->nNode, sal_False )) |
| { |
| SwCntntNode *pNd = pPos->nNode.GetNode().GetCntntNode(); |
| xub_StrLen nCPos; |
| if( fnMove == fnMoveForward ) |
| nCPos = 0; |
| else |
| nCPos = pNd->Len(); |
| pPos->nContent.Assign( pNd, nCPos ); |
| } |
| else |
| bCheckRegion = sal_False; |
| } |
| if( !bCheckRegion || *aRegion.GetPoint() <= *pPos ) |
| return FIND_NOT_FOUND; // nicht gefunden |
| }*/ |
| *aRegion.GetMark() = *aSrchPam.GetPoint(); |
| } |
| |
| *pCrsr->GetPoint() = *aSrchPam.GetPoint(); |
| pCrsr->SetMark(); |
| *pCrsr->GetMark() = *aSrchPam.GetMark(); |
| } |
| |
| if( bReplaceTxt ) |
| { |
| const bool bRegExp( |
| SearchAlgorithms_REGEXP == pSearchOpt->algorithmType); |
| SwIndex& rSttCntIdx = pCrsr->Start()->nContent; |
| xub_StrLen nSttCnt = rSttCntIdx.GetIndex(); |
| |
| // damit die Region auch verschoben wird, in den Shell-Cursr-Ring |
| // mit aufnehmen !! |
| Ring *pPrevRing = 0; |
| if( bRegExp ) |
| { |
| pPrevRing = pRegion->GetPrev(); |
| ((Ring*)pRegion)->MoveRingTo( &rCursor ); |
| } |
| |
| ::std::auto_ptr<String> pRepl( (bRegExp) ? |
| ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 ); |
| rCursor.GetDoc()->ReplaceRange( *pCrsr, |
| (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString), |
| bRegExp ); |
| rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() ); |
| |
| if( bRegExp ) |
| { |
| // und die Region wieder herausnehmen: |
| Ring *p, *pNext = (Ring*)pRegion; |
| do { |
| p = pNext; |
| pNext = p->GetNext(); |
| p->MoveTo( (Ring*)pRegion ); |
| } while( p != pPrevRing ); |
| } |
| rSttCntIdx = nSttCnt; |
| } |
| |
| if( bReplaceAttr ) |
| { |
| // --- Ist die Selection noch da ?????? |
| |
| // und noch die Attribute setzen |
| #ifdef OLD |
| pCrsr->GetDoc()->Insert( *pCrsr, *pReplSet, 0 ); |
| #else |
| //JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im |
| // ReplaceSet angegeben, auf Default zurueck gesetzt |
| |
| if( !pSet->Count() ) |
| { |
| pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 ); |
| } |
| else |
| { |
| SfxItemPool* pPool = pReplSet->GetPool(); |
| SfxItemSet aSet( *pPool, pReplSet->GetRanges() ); |
| |
| SfxItemIter aIter( *pSet ); |
| const SfxPoolItem* pItem = aIter.GetCurItem(); |
| while( sal_True ) |
| { |
| // alle die nicht gesetzt sind mit Pool-Defaults aufuellen |
| if( !IsInvalidItem( pItem ) && SFX_ITEM_SET != |
| pReplSet->GetItemState( pItem->Which(), sal_False )) |
| aSet.Put( pPool->GetDefaultItem( pItem->Which() )); |
| |
| if( aIter.IsAtEnd() ) |
| break; |
| pItem = aIter.NextItem(); |
| } |
| aSet.Put( *pReplSet ); |
| pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 ); |
| } |
| #endif |
| return FIND_NO_RING; |
| } |
| |
| else |
| return FIND_FOUND; |
| } |
| |
| |
| int SwFindParaAttr::IsReplaceMode() const |
| { |
| return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) || |
| ( pReplSet && pReplSet->Count() ); |
| } |
| |
| // Suchen nach Attributen |
| |
| |
| sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections, |
| SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel, |
| FindRanges eFndRngs, |
| const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet ) |
| { |
| // OLE-Benachrichtigung abschalten !! |
| SwDoc* pDoc = GetDoc(); |
| Link aLnk( pDoc->GetOle2Link() ); |
| pDoc->SetOle2Link( Link() ); |
| |
| sal_Bool bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() || |
| !rSet.Count() ) ) || |
| (pReplSet && pReplSet->Count()); |
| bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace; |
| if (bStartUndo) |
| { |
| pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL ); |
| } |
| |
| SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt, |
| pReplSet, *this ); |
| |
| sal_uLong nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel ); |
| pDoc->SetOle2Link( aLnk ); |
| if( nRet && bReplace ) |
| pDoc->SetModified(); |
| |
| if (bStartUndo) |
| { |
| pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL ); |
| } |
| |
| return nRet; |
| } |
| |
| |
| |