SAL_UNUSED_PARAMETER (expanding to __attribute__ ((unused)) for GCC) is used to annotate legitimately unused parameters, so that static analysis tools can tell legitimately unused parameters from truly unnecessary ones. To that end, some patches for external modules are also added, that are only applied when compiling with GCC and add necessary __attribute__ ((unused)) in headers.
1293 lines
42 KiB
C++
1293 lines
42 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
|
|
#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 )
|
|
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->GetEnd(), 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 )
|
|
{
|
|
OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
|
|
"Stack-Platz ist noch belegt" );
|
|
|
|
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 )
|
|
{
|
|
OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
|
|
"Stack-Platz ist noch belegt" );
|
|
|
|
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
|
|
OSL_ENSURE( !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();
|
|
|
|
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:
|
|
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.isEmpty() ||
|
|
!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
|
|
|
|
*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 ??????
|
|
|
|
//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 );
|
|
}
|
|
|
|
return FIND_NO_RING;
|
|
}
|
|
|
|
else
|
|
return FIND_FOUND;
|
|
}
|
|
|
|
|
|
int SwFindParaAttr::IsReplaceMode() const
|
|
{
|
|
return ( pSearchOpt && !pSearchOpt->replaceString.isEmpty() ) ||
|
|
( 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.isEmpty() ||
|
|
!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;
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|