xref: /aoo41x/main/sw/source/core/crsr/findattr.cxx (revision 69a74367)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <com/sun/star/lang/Locale.hpp>
29cdf0e10cSrcweir #include <com/sun/star/util/SearchOptions.hpp>
30cdf0e10cSrcweir #include <com/sun/star/util/SearchFlags.hpp>
31cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
32cdf0e10cSrcweir #include <hintids.hxx>
33cdf0e10cSrcweir #include <vcl/svapp.hxx>
34cdf0e10cSrcweir #include <svl/itemiter.hxx>
35cdf0e10cSrcweir #include <svl/whiter.hxx>
36cdf0e10cSrcweir #include <editeng/brkitem.hxx>
37cdf0e10cSrcweir #include <editeng/colritem.hxx>
38cdf0e10cSrcweir #include <editeng/fontitem.hxx>
39cdf0e10cSrcweir #include <fmtpdsc.hxx>
40cdf0e10cSrcweir #include <txatbase.hxx>
41cdf0e10cSrcweir #include <fchrfmt.hxx>
42cdf0e10cSrcweir #include <charfmt.hxx>
43cdf0e10cSrcweir #include <doc.hxx>
44cdf0e10cSrcweir #include <IDocumentUndoRedo.hxx>
45cdf0e10cSrcweir #include <swcrsr.hxx>
46cdf0e10cSrcweir #include <editsh.hxx>
47cdf0e10cSrcweir #include <ndtxt.hxx>
48cdf0e10cSrcweir #include <pamtyp.hxx>
49cdf0e10cSrcweir #include <swundo.hxx>
50cdf0e10cSrcweir #include <crsskip.hxx>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir 
53cdf0e10cSrcweir using namespace ::com::sun::star;
54cdf0e10cSrcweir using namespace ::com::sun::star::lang;
55cdf0e10cSrcweir using namespace ::com::sun::star::util;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir SV_DECL_PTRARR_SORT( SwpFmts, SwFmt*, 0, 4 )
SV_IMPL_PTRARR_SORT(SwpFmts,SwFmt *)58cdf0e10cSrcweir SV_IMPL_PTRARR_SORT( SwpFmts, SwFmt* )
59cdf0e10cSrcweir 
60cdf0e10cSrcweir 	// Sonderbehandlung fuer SvxFontItem, nur den Namen vergleichen:
61cdf0e10cSrcweir int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir 	switch( rItem1.Which() )
64cdf0e10cSrcweir 	{
65cdf0e10cSrcweir 	case RES_CHRATR_FONT:
66cdf0e10cSrcweir 		return ((SvxFontItem&)rItem1).GetFamilyName() ==
67cdf0e10cSrcweir 				((SvxFontItem&)rItem2).GetFamilyName();
68cdf0e10cSrcweir 
69cdf0e10cSrcweir 	case RES_CHRATR_COLOR:
70cdf0e10cSrcweir 		return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
71cdf0e10cSrcweir 								((SvxColorItem&)rItem2).GetValue() );
72cdf0e10cSrcweir 	case RES_PAGEDESC:
73cdf0e10cSrcweir 		return ((SwFmtPageDesc&)rItem1).GetNumOffset() ==
74cdf0e10cSrcweir 						((SwFmtPageDesc&)rItem2).GetNumOffset() &&
75cdf0e10cSrcweir 				((SwFmtPageDesc&)rItem1).GetPageDesc() ==
76cdf0e10cSrcweir 						((SwFmtPageDesc&)rItem2).GetPageDesc();
77cdf0e10cSrcweir 	}
78cdf0e10cSrcweir 	return rItem1 == rItem2;
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 
GetFrwrdTxtHint(const SwpHints & rHtsArr,sal_uInt16 & rPos,xub_StrLen nCntntPos)82cdf0e10cSrcweir const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
83cdf0e10cSrcweir 									xub_StrLen nCntntPos )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir 	while( rPos < rHtsArr.Count() )
86cdf0e10cSrcweir 	{
87cdf0e10cSrcweir 		const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
88cdf0e10cSrcweir 		// der Start vom Attribut muss innerhalb des Bereiches liegen !!
89cdf0e10cSrcweir 		if( *pTxtHt->GetStart() >= nCntntPos )
90cdf0e10cSrcweir 			return pTxtHt; 		// gueltiges TextAttribut
91cdf0e10cSrcweir 	}
92cdf0e10cSrcweir 	return 0;			 		// kein gueltiges TextAttribut
93cdf0e10cSrcweir }
94cdf0e10cSrcweir 
95cdf0e10cSrcweir 
GetBkwrdTxtHint(const SwpHints & rHtsArr,sal_uInt16 & rPos,xub_StrLen nCntntPos)96cdf0e10cSrcweir const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
97cdf0e10cSrcweir 								  xub_StrLen nCntntPos )
98cdf0e10cSrcweir {
99cdf0e10cSrcweir 	while( rPos > 0 )
100cdf0e10cSrcweir 	{
101cdf0e10cSrcweir 		//Hack mit cast fuer das Update
102cdf0e10cSrcweir 		const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
103cdf0e10cSrcweir 		// der Start vom Attribut muss innerhalb des Bereiches liegen !!
104cdf0e10cSrcweir 		if( *pTxtHt->GetStart() < nCntntPos )
105cdf0e10cSrcweir 			return pTxtHt; 		// gueltiges TextAttribut
106cdf0e10cSrcweir 	}
107cdf0e10cSrcweir 	return 0; 					// kein gueltiges TextAttribut
108cdf0e10cSrcweir }
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 
lcl_SetAttrPam(SwPaM & rPam,xub_StrLen nStart,const xub_StrLen * pEnde,const sal_Bool bSaveMark)111cdf0e10cSrcweir void lcl_SetAttrPam( SwPaM & rPam, xub_StrLen nStart, const xub_StrLen* pEnde,
112cdf0e10cSrcweir 						const sal_Bool bSaveMark )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir 	xub_StrLen nCntntPos;
115cdf0e10cSrcweir 	if( bSaveMark )
116cdf0e10cSrcweir 		nCntntPos = rPam.GetMark()->nContent.GetIndex();
117cdf0e10cSrcweir 	else
118cdf0e10cSrcweir 		nCntntPos = rPam.GetPoint()->nContent.GetIndex();
119cdf0e10cSrcweir 	sal_Bool bTstEnde = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
120cdf0e10cSrcweir 
121cdf0e10cSrcweir 	SwCntntNode* pCNd = rPam.GetCntntNode();
122cdf0e10cSrcweir 	rPam.GetPoint()->nContent.Assign( pCNd, nStart );
123cdf0e10cSrcweir 	rPam.SetMark(); 	// Point == GetMark
124cdf0e10cSrcweir 
125cdf0e10cSrcweir 	// Point zeigt auf das Ende vom SuchBereich oder Ende vom Attribut
126cdf0e10cSrcweir 	if( pEnde )
127cdf0e10cSrcweir 	{
128cdf0e10cSrcweir 		if( bTstEnde && *pEnde > nCntntPos )
129cdf0e10cSrcweir 			rPam.GetPoint()->nContent = nCntntPos;
130cdf0e10cSrcweir 		else
131cdf0e10cSrcweir 			rPam.GetPoint()->nContent = *pEnde;
132cdf0e10cSrcweir 	}
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir //------------------ Suche nach einem Text Attribut -----------------------
136cdf0e10cSrcweir 
137cdf0e10cSrcweir // diese Funktion sucht in einem TextNode nach dem vorgegebenen Attribut.
138cdf0e10cSrcweir // Wird es gefunden, dann hat der SwPaM den Bereich der das Attribut
139cdf0e10cSrcweir // umspannt, unter Beachtung des Suchbereiches
140cdf0e10cSrcweir 
141cdf0e10cSrcweir 
lcl_Search(const SwTxtNode & rTxtNd,SwPaM & rPam,const SfxPoolItem & rCmpItem,SwMoveFn fnMove,sal_Bool bValue)142cdf0e10cSrcweir sal_Bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
143cdf0e10cSrcweir 					const SfxPoolItem& rCmpItem,
144cdf0e10cSrcweir 					SwMoveFn fnMove, sal_Bool bValue )
145cdf0e10cSrcweir {
146cdf0e10cSrcweir 	if ( !rTxtNd.HasHints() )
147cdf0e10cSrcweir 		return sal_False;
148cdf0e10cSrcweir 	const SwTxtAttr *pTxtHt = 0;
149cdf0e10cSrcweir 	sal_Bool bForward = fnMove == fnMoveForward;
150cdf0e10cSrcweir 	sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
151cdf0e10cSrcweir 	xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex();
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 	while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
154cdf0e10cSrcweir 		if( pTxtHt->Which() == rCmpItem.Which() &&
155cdf0e10cSrcweir 			( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
156cdf0e10cSrcweir 		{
157*69a74367SOliver-Rainer Wittmann 			lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->End(), bForward );
158cdf0e10cSrcweir 			return sal_True;
159cdf0e10cSrcweir 		}
160cdf0e10cSrcweir 	return sal_False;
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 
164cdf0e10cSrcweir //------------------ Suche nach mehren Text Attributen -------------------
165cdf0e10cSrcweir 
166cdf0e10cSrcweir struct _SwSrchChrAttr
167cdf0e10cSrcweir {
168cdf0e10cSrcweir 	sal_uInt16 nWhich;
169cdf0e10cSrcweir 	xub_StrLen nStt, nEnd;
170cdf0e10cSrcweir 
_SwSrchChrAttr_SwSrchChrAttr171cdf0e10cSrcweir 	_SwSrchChrAttr( const SfxPoolItem& rItem,
172cdf0e10cSrcweir 					xub_StrLen nStart, xub_StrLen nAnyEnd )
173cdf0e10cSrcweir 		: nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
174cdf0e10cSrcweir 	{}
175cdf0e10cSrcweir };
176cdf0e10cSrcweir 
177cdf0e10cSrcweir class SwAttrCheckArr
178cdf0e10cSrcweir {
179cdf0e10cSrcweir 	_SwSrchChrAttr *pFndArr, *pStackArr;
180cdf0e10cSrcweir 	xub_StrLen nNdStt, nNdEnd;
181cdf0e10cSrcweir 	sal_uInt16 nArrStart, nArrLen;
182cdf0e10cSrcweir 	sal_uInt16 nFound, nStackCnt;
183cdf0e10cSrcweir 	SfxItemSet aCmpSet;
184cdf0e10cSrcweir 	sal_Bool bNoColls;
185cdf0e10cSrcweir 	sal_Bool bForward;
186cdf0e10cSrcweir 
187cdf0e10cSrcweir public:
188cdf0e10cSrcweir 	SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections );
189cdf0e10cSrcweir 	~SwAttrCheckArr();
190cdf0e10cSrcweir 
191cdf0e10cSrcweir 	void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 	// wieviele Attribute ueberhaupt ??
Count() const194cdf0e10cSrcweir 	sal_uInt16 Count() const 	{ return aCmpSet.Count(); }
Found() const195cdf0e10cSrcweir 	int Found() const 		{ return nFound == aCmpSet.Count(); }
196cdf0e10cSrcweir 	int CheckStack();
197cdf0e10cSrcweir 
198cdf0e10cSrcweir 	xub_StrLen Start() const;
199cdf0e10cSrcweir 	xub_StrLen End() const;
200cdf0e10cSrcweir 
GetNdStt() const201cdf0e10cSrcweir 	xub_StrLen GetNdStt() const { return nNdStt; }
GetNdEnd() const202cdf0e10cSrcweir 	xub_StrLen GetNdEnd() const { return nNdEnd; }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 	int SetAttrFwd( const SwTxtAttr& rAttr );
205cdf0e10cSrcweir 	int SetAttrBwd( const SwTxtAttr& rAttr );
206cdf0e10cSrcweir };
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 
SwAttrCheckArr(const SfxItemSet & rSet,int bFwd,int bNoCollections)210cdf0e10cSrcweir SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd,
211cdf0e10cSrcweir 								int bNoCollections )
212cdf0e10cSrcweir 	: aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir 	aCmpSet.Put( rSet, sal_False );
215cdf0e10cSrcweir 	bNoColls = 0 != bNoCollections;
216cdf0e10cSrcweir 
217cdf0e10cSrcweir 	bForward = 0 != bFwd;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 	// Bestimmen den Bereich des Fnd/Stack-Arrays (Min/Max)
220cdf0e10cSrcweir 	SfxItemIter aIter( aCmpSet );
221cdf0e10cSrcweir 	nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
222cdf0e10cSrcweir 	nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
223cdf0e10cSrcweir 
224cdf0e10cSrcweir     char* pFndChar  = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
225cdf0e10cSrcweir     char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     pFndArr = (_SwSrchChrAttr*)pFndChar;
228cdf0e10cSrcweir     pStackArr = (_SwSrchChrAttr*)pStackChar;
229cdf0e10cSrcweir }
230cdf0e10cSrcweir 
~SwAttrCheckArr()231cdf0e10cSrcweir SwAttrCheckArr::~SwAttrCheckArr()
232cdf0e10cSrcweir {
233cdf0e10cSrcweir     delete[] (char*)pFndArr;
234cdf0e10cSrcweir     delete[] (char*)pStackArr;
235cdf0e10cSrcweir }
236cdf0e10cSrcweir 
SetNewSet(const SwTxtNode & rTxtNd,const SwPaM & rPam)237cdf0e10cSrcweir void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
238cdf0e10cSrcweir {
239cdf0e10cSrcweir 	memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
240cdf0e10cSrcweir 	memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
241cdf0e10cSrcweir 	nFound = 0;
242cdf0e10cSrcweir 	nStackCnt = 0;
243cdf0e10cSrcweir 
244cdf0e10cSrcweir 	if( bForward )
245cdf0e10cSrcweir 	{
246cdf0e10cSrcweir 		nNdStt = rPam.GetPoint()->nContent.GetIndex();
247cdf0e10cSrcweir 		nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
248cdf0e10cSrcweir 				? rPam.GetMark()->nContent.GetIndex()
249cdf0e10cSrcweir 				: rTxtNd.GetTxt().Len();
250cdf0e10cSrcweir 	}
251cdf0e10cSrcweir 	else
252cdf0e10cSrcweir 	{
253cdf0e10cSrcweir 		nNdEnd = rPam.GetPoint()->nContent.GetIndex();
254cdf0e10cSrcweir 		nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
255cdf0e10cSrcweir 				? rPam.GetMark()->nContent.GetIndex()
256cdf0e10cSrcweir 				: 0;
257cdf0e10cSrcweir 	}
258cdf0e10cSrcweir 
259cdf0e10cSrcweir     if( bNoColls && !rTxtNd.HasSwAttrSet() )
260cdf0e10cSrcweir 		return ;
261cdf0e10cSrcweir 
262cdf0e10cSrcweir 	const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
263cdf0e10cSrcweir //	if( !rSet.Count() )
264cdf0e10cSrcweir //		return;
265cdf0e10cSrcweir 
266cdf0e10cSrcweir 	SfxItemIter aIter( aCmpSet );
267cdf0e10cSrcweir 	const SfxPoolItem* pItem = aIter.GetCurItem();
268cdf0e10cSrcweir 	const SfxPoolItem* pFndItem;
269cdf0e10cSrcweir 	sal_uInt16 nWhich;
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 	while( sal_True )
272cdf0e10cSrcweir 	{
273cdf0e10cSrcweir 		// nur testen, ob vorhanden ist ?
274cdf0e10cSrcweir 		if( IsInvalidItem( pItem ) )
275cdf0e10cSrcweir 		{
276cdf0e10cSrcweir 			nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
277cdf0e10cSrcweir 			if( RES_TXTATR_END <= nWhich )
278cdf0e10cSrcweir 				break;				// Ende der TextAttribute
279cdf0e10cSrcweir 
280cdf0e10cSrcweir 			if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
281cdf0e10cSrcweir 				&& !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
282cdf0e10cSrcweir 			{
283cdf0e10cSrcweir 				pFndArr[ nWhich - nArrStart ] =
284cdf0e10cSrcweir 					_SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
285cdf0e10cSrcweir 				nFound++;
286cdf0e10cSrcweir 			}
287cdf0e10cSrcweir 		}
288cdf0e10cSrcweir 		else
289cdf0e10cSrcweir 		{
290cdf0e10cSrcweir 			if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
291cdf0e10cSrcweir 				break;				// Ende der TextAttribute
292cdf0e10cSrcweir 
293cdf0e10cSrcweir //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
294cdf0e10cSrcweir //				runter
295cdf0e10cSrcweir //			if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
296cdf0e10cSrcweir //                && *pFndItem == *pItem )
297cdf0e10cSrcweir 			if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
298cdf0e10cSrcweir 			{
299cdf0e10cSrcweir 				pFndArr[ nWhich - nArrStart ] =
300cdf0e10cSrcweir 					_SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
301cdf0e10cSrcweir 				nFound++;
302cdf0e10cSrcweir 			}
303cdf0e10cSrcweir 		}
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 		if( aIter.IsAtEnd() )
306cdf0e10cSrcweir 			break;
307cdf0e10cSrcweir 		pItem = aIter.NextItem();
308cdf0e10cSrcweir 	}
309cdf0e10cSrcweir }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir static bool
lcl_IsAttributeIgnorable(xub_StrLen const nNdStart,xub_StrLen const nNdEnd,_SwSrchChrAttr const & rTmp)312cdf0e10cSrcweir lcl_IsAttributeIgnorable(xub_StrLen const nNdStart, xub_StrLen const nNdEnd,
313cdf0e10cSrcweir         _SwSrchChrAttr const& rTmp)
314cdf0e10cSrcweir {
315cdf0e10cSrcweir     // #i115528#: if there is a paragraph attribute, it has been added by the
316cdf0e10cSrcweir     // SwAttrCheckArr ctor, and nFound is 1.
317cdf0e10cSrcweir     // if the paragraph is entirely covered by hints that override the paragraph
318cdf0e10cSrcweir     // attribute, then this function must find an attribute to decrement nFound!
319cdf0e10cSrcweir     // so check for an empty search range, let attributes that start/end there
320cdf0e10cSrcweir     // cover it, and hope for the best...
321cdf0e10cSrcweir     return ((nNdEnd == nNdStart)
322cdf0e10cSrcweir             ? ((rTmp.nEnd <  nNdStart) || (nNdEnd <  rTmp.nStt))
323cdf0e10cSrcweir             : ((rTmp.nEnd <= nNdStart) || (nNdEnd <= rTmp.nStt)));
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
SetAttrFwd(const SwTxtAttr & rAttr)326cdf0e10cSrcweir int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir 	_SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
329cdf0e10cSrcweir 
330cdf0e10cSrcweir     // ignore all attributes not in search range
331cdf0e10cSrcweir     if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
332cdf0e10cSrcweir     {
333cdf0e10cSrcweir         return Found();
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 	const SfxPoolItem* pItem;
337cdf0e10cSrcweir // --------------------------------------------------------------
338cdf0e10cSrcweir // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
339cdf0e10cSrcweir // --------------------------------------------------------------
340cdf0e10cSrcweir 	sal_uInt16 nWhch = rAttr.Which();
341cdf0e10cSrcweir 	SfxWhichIter* pIter = NULL;
342cdf0e10cSrcweir 	const SfxPoolItem* pTmpItem = NULL;
343cdf0e10cSrcweir     const SfxItemSet* pSet = NULL;
344cdf0e10cSrcweir 	if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
345cdf0e10cSrcweir 	{
346cdf0e10cSrcweir 		if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
347cdf0e10cSrcweir 			return Found();
348cdf0e10cSrcweir         pTmpItem = NULL;
349cdf0e10cSrcweir         pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
350cdf0e10cSrcweir         if ( pSet )
351cdf0e10cSrcweir         {
352cdf0e10cSrcweir 			pIter = new SfxWhichIter( *pSet );
353cdf0e10cSrcweir 			nWhch = pIter->FirstWhich();
354cdf0e10cSrcweir 			while( nWhch &&
355cdf0e10cSrcweir 				SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
356cdf0e10cSrcweir 				nWhch = pIter->NextWhich();
357cdf0e10cSrcweir 			if( !nWhch )
358cdf0e10cSrcweir 				pTmpItem = NULL;
359cdf0e10cSrcweir         }
360cdf0e10cSrcweir 	}
361cdf0e10cSrcweir 	else
362cdf0e10cSrcweir 		pTmpItem = &rAttr.GetAttr();
363cdf0e10cSrcweir 	while( pTmpItem )
364cdf0e10cSrcweir 	{
365cdf0e10cSrcweir 		SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
366cdf0e10cSrcweir 		if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
367cdf0e10cSrcweir 		{
368cdf0e10cSrcweir 			sal_uInt16 n;
369cdf0e10cSrcweir 			_SwSrchChrAttr* pCmp;
370cdf0e10cSrcweir 
371cdf0e10cSrcweir 			// loesche erstmal alle, die bis zu der Start Position schon wieder
372cdf0e10cSrcweir 			// ungueltig sind:
373cdf0e10cSrcweir 
374cdf0e10cSrcweir 			_SwSrchChrAttr* pArrPtr;
375cdf0e10cSrcweir 			if( nFound )
376cdf0e10cSrcweir 				for( pArrPtr = pFndArr, n = 0; n < nArrLen;
377cdf0e10cSrcweir 					++n, ++pArrPtr )
378cdf0e10cSrcweir 					if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
379cdf0e10cSrcweir 					{
380cdf0e10cSrcweir 						pArrPtr->nWhich = 0;		// geloescht
381cdf0e10cSrcweir 						nFound--;
382cdf0e10cSrcweir 					}
383cdf0e10cSrcweir 
384cdf0e10cSrcweir 			// loesche erstmal alle, die bis zu der Start Position schon wieder
385cdf0e10cSrcweir 			// ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
386cdf0e10cSrcweir 			// die Start Position ragen, vom Stack in den FndSet
387cdf0e10cSrcweir 
388cdf0e10cSrcweir 			if( nStackCnt )
389cdf0e10cSrcweir 				for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
390cdf0e10cSrcweir 				{
391cdf0e10cSrcweir 					if( !pArrPtr->nWhich )
392cdf0e10cSrcweir 						continue;
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 					if( pArrPtr->nEnd <= aTmp.nStt )
395cdf0e10cSrcweir 					{
396cdf0e10cSrcweir 						pArrPtr->nWhich = 0;		// geloescht
397cdf0e10cSrcweir 						if( !--nStackCnt )
398cdf0e10cSrcweir 							break;
399cdf0e10cSrcweir 					}
400cdf0e10cSrcweir 					else if( pArrPtr->nStt <= aTmp.nStt )
401cdf0e10cSrcweir 					{
402cdf0e10cSrcweir 						if( ( pCmp = &pFndArr[ n ])->nWhich )
403cdf0e10cSrcweir 						{
404cdf0e10cSrcweir 							if( pCmp->nEnd < pArrPtr->nEnd )		// erweitern
405cdf0e10cSrcweir 								pCmp->nEnd = pArrPtr->nEnd;
406cdf0e10cSrcweir 						}
407cdf0e10cSrcweir 						else
408cdf0e10cSrcweir 						{
409cdf0e10cSrcweir 							*pCmp = *pArrPtr;
410cdf0e10cSrcweir 							nFound++;
411cdf0e10cSrcweir 						}
412cdf0e10cSrcweir 						pArrPtr->nWhich = 0;
413cdf0e10cSrcweir 						if( !--nStackCnt )
414cdf0e10cSrcweir 							break;
415cdf0e10cSrcweir 					}
416cdf0e10cSrcweir 				}
417cdf0e10cSrcweir 
418cdf0e10cSrcweir 			sal_Bool bContinue = sal_False;
419cdf0e10cSrcweir 
420cdf0e10cSrcweir 			if( SFX_ITEM_DONTCARE == eState  )
421cdf0e10cSrcweir 			{
422cdf0e10cSrcweir 				// wird Attribut gueltig ?
423cdf0e10cSrcweir 				if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
424cdf0e10cSrcweir 					*pTmpItem ))
425cdf0e10cSrcweir 				{
426cdf0e10cSrcweir 					// suche das Attribut und erweiter es gegebenenfalls
427cdf0e10cSrcweir 					if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
428cdf0e10cSrcweir 					{
429cdf0e10cSrcweir 						*pCmp = aTmp;				// nicht gefunden, eintragen
430cdf0e10cSrcweir 						nFound++;
431cdf0e10cSrcweir 					}
432cdf0e10cSrcweir 					else if( pCmp->nEnd < aTmp.nEnd )		// erweitern ?
433cdf0e10cSrcweir 						pCmp->nEnd = aTmp.nEnd;
434cdf0e10cSrcweir 
435cdf0e10cSrcweir 					bContinue = sal_True;
436cdf0e10cSrcweir 				}
437cdf0e10cSrcweir 			}
438cdf0e10cSrcweir 			// wird Attribut gueltig ?
439cdf0e10cSrcweir 			else if(  CmpAttr( *pItem, *pTmpItem ) )
440cdf0e10cSrcweir 			{
441cdf0e10cSrcweir 				pFndArr[ nWhch - nArrStart ] = aTmp;
442cdf0e10cSrcweir 				++nFound;
443cdf0e10cSrcweir 				bContinue = sal_True;
444cdf0e10cSrcweir 			}
445cdf0e10cSrcweir 
446cdf0e10cSrcweir 			// tja, dann muss es auf den Stack
447cdf0e10cSrcweir 			if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
448cdf0e10cSrcweir 			{
449cdf0e10cSrcweir 				// vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
450cdf0e10cSrcweir 				if( pCmp->nEnd > aTmp.nEnd )
451cdf0e10cSrcweir 				{
452cdf0e10cSrcweir 					ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
453cdf0e10cSrcweir 									"Stack-Platz ist noch belegt" );
454cdf0e10cSrcweir 
455cdf0e10cSrcweir 		// ---------
456cdf0e10cSrcweir 		// JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
457cdf0e10cSrcweir 		//			pCmp->nStt = aTmp.nEnd;
458cdf0e10cSrcweir 					if( aTmp.nStt <= pCmp->nStt )
459cdf0e10cSrcweir 						pCmp->nStt = aTmp.nEnd;
460cdf0e10cSrcweir 					else
461cdf0e10cSrcweir 						pCmp->nEnd = aTmp.nStt;
462cdf0e10cSrcweir 		// ---------
463cdf0e10cSrcweir 
464cdf0e10cSrcweir 					pStackArr[ nWhch - nArrStart ] = *pCmp;
465cdf0e10cSrcweir 					nStackCnt++;
466cdf0e10cSrcweir 				}
467cdf0e10cSrcweir 				pCmp->nWhich = 0;
468cdf0e10cSrcweir 				nFound--;
469cdf0e10cSrcweir 			}
470cdf0e10cSrcweir 		}
471cdf0e10cSrcweir 		if( pIter )
472cdf0e10cSrcweir 		{
473cdf0e10cSrcweir 			nWhch = pIter->NextWhich();
474cdf0e10cSrcweir 			while( nWhch &&
475cdf0e10cSrcweir 				SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
476cdf0e10cSrcweir 				nWhch = pIter->NextWhich();
477cdf0e10cSrcweir 			if( !nWhch )
478cdf0e10cSrcweir 				break;
479cdf0e10cSrcweir 		}
480cdf0e10cSrcweir 		else
481cdf0e10cSrcweir 			break;
482cdf0e10cSrcweir 	}
483cdf0e10cSrcweir 	return Found();
484cdf0e10cSrcweir }
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 
SetAttrBwd(const SwTxtAttr & rAttr)487cdf0e10cSrcweir int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
488cdf0e10cSrcweir {
489cdf0e10cSrcweir 	_SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
490cdf0e10cSrcweir 
491cdf0e10cSrcweir     // ignore all attributes not in search range
492cdf0e10cSrcweir     if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
493cdf0e10cSrcweir     {
494cdf0e10cSrcweir         return Found();
495cdf0e10cSrcweir     }
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 	const SfxPoolItem* pItem;
498cdf0e10cSrcweir // --------------------------------------------------------------
499cdf0e10cSrcweir // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
500cdf0e10cSrcweir // --------------------------------------------------------------
501cdf0e10cSrcweir 	sal_uInt16 nWhch = rAttr.Which();
502cdf0e10cSrcweir 	SfxWhichIter* pIter = NULL;
503cdf0e10cSrcweir     const SfxPoolItem* pTmpItem = NULL;
504cdf0e10cSrcweir     const SfxItemSet* pSet = NULL;
505cdf0e10cSrcweir     if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
506cdf0e10cSrcweir 	{
507cdf0e10cSrcweir 		if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
508cdf0e10cSrcweir 			return Found();
509cdf0e10cSrcweir 
510cdf0e10cSrcweir         pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
511cdf0e10cSrcweir         if ( pSet )
512cdf0e10cSrcweir         {
513cdf0e10cSrcweir 			pIter = new SfxWhichIter( *pSet );
514cdf0e10cSrcweir 			nWhch = pIter->FirstWhich();
515cdf0e10cSrcweir 			while( nWhch &&
516cdf0e10cSrcweir 				SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
517cdf0e10cSrcweir 				nWhch = pIter->NextWhich();
518cdf0e10cSrcweir 			if( !nWhch )
519cdf0e10cSrcweir 				pTmpItem = NULL;
520cdf0e10cSrcweir         }
521cdf0e10cSrcweir 	}
522cdf0e10cSrcweir 	else
523cdf0e10cSrcweir 		pTmpItem = &rAttr.GetAttr();
524cdf0e10cSrcweir 	while( pTmpItem )
525cdf0e10cSrcweir 	{
526cdf0e10cSrcweir 		SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
527cdf0e10cSrcweir 		if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
528cdf0e10cSrcweir 		{
529cdf0e10cSrcweir 			sal_uInt16 n;
530cdf0e10cSrcweir 			_SwSrchChrAttr* pCmp;
531cdf0e10cSrcweir 
532cdf0e10cSrcweir 			// loesche erstmal alle, die bis zu der Start Position schon wieder
533cdf0e10cSrcweir 			// ungueltig sind:
534cdf0e10cSrcweir 
535cdf0e10cSrcweir 			_SwSrchChrAttr* pArrPtr;
536cdf0e10cSrcweir 			if( nFound )
537cdf0e10cSrcweir 				for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
538cdf0e10cSrcweir 					if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
539cdf0e10cSrcweir 					{
540cdf0e10cSrcweir 						pArrPtr->nWhich = 0;		// geloescht
541cdf0e10cSrcweir 						nFound--;
542cdf0e10cSrcweir 					}
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 			// loesche erstmal alle, die bis zu der Start Position schon wieder
545cdf0e10cSrcweir 			// ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
546cdf0e10cSrcweir 			// die Start Position ragen, vom Stack in den FndSet
547cdf0e10cSrcweir 
548cdf0e10cSrcweir 			if( nStackCnt )
549cdf0e10cSrcweir 				for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
550cdf0e10cSrcweir 				{
551cdf0e10cSrcweir 					if( !pArrPtr->nWhich )
552cdf0e10cSrcweir 						continue;
553cdf0e10cSrcweir 
554cdf0e10cSrcweir 					if( pArrPtr->nStt >= aTmp.nEnd )
555cdf0e10cSrcweir 					{
556cdf0e10cSrcweir 						pArrPtr->nWhich = 0;		// geloescht
557cdf0e10cSrcweir 						if( !--nStackCnt )
558cdf0e10cSrcweir 							break;
559cdf0e10cSrcweir 					}
560cdf0e10cSrcweir 					else if( pArrPtr->nEnd >= aTmp.nEnd )
561cdf0e10cSrcweir 					{
562cdf0e10cSrcweir 						if( ( pCmp = &pFndArr[ n ])->nWhich )
563cdf0e10cSrcweir 						{
564cdf0e10cSrcweir 							if( pCmp->nStt > pArrPtr->nStt )		// erweitern
565cdf0e10cSrcweir 								pCmp->nStt = pArrPtr->nStt;
566cdf0e10cSrcweir 						}
567cdf0e10cSrcweir 						else
568cdf0e10cSrcweir 						{
569cdf0e10cSrcweir 							*pCmp = *pArrPtr;
570cdf0e10cSrcweir 							nFound++;
571cdf0e10cSrcweir 					}
572cdf0e10cSrcweir 					pArrPtr->nWhich = 0;
573cdf0e10cSrcweir 					if( !--nStackCnt )
574cdf0e10cSrcweir 						break;
575cdf0e10cSrcweir 				}
576cdf0e10cSrcweir 			}
577cdf0e10cSrcweir 
578cdf0e10cSrcweir 			sal_Bool bContinue = sal_False;
579cdf0e10cSrcweir 			if( SFX_ITEM_DONTCARE == eState  )
580cdf0e10cSrcweir 			{
581cdf0e10cSrcweir 				// wird Attribut gueltig ?
582cdf0e10cSrcweir 				if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
583cdf0e10cSrcweir 					*pTmpItem ) )
584cdf0e10cSrcweir 				{
585cdf0e10cSrcweir 					// suche das Attribut und erweiter es gegebenenfalls
586cdf0e10cSrcweir 					if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
587cdf0e10cSrcweir 					{
588cdf0e10cSrcweir 						*pCmp = aTmp;				// nicht gefunden, eintragen
589cdf0e10cSrcweir 						nFound++;
590cdf0e10cSrcweir 					}
591cdf0e10cSrcweir 					else if( pCmp->nStt > aTmp.nStt )		// erweitern ?
592cdf0e10cSrcweir 						pCmp->nStt = aTmp.nStt;
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 					bContinue = sal_True;
595cdf0e10cSrcweir 				}
596cdf0e10cSrcweir 			}
597cdf0e10cSrcweir 			// wird Attribut gueltig ?
598cdf0e10cSrcweir 			else if( CmpAttr( *pItem, *pTmpItem ))
599cdf0e10cSrcweir 			{
600cdf0e10cSrcweir 				pFndArr[ nWhch - nArrStart ] = aTmp;
601cdf0e10cSrcweir 				++nFound;
602cdf0e10cSrcweir 				bContinue = sal_True;
603cdf0e10cSrcweir 			}
604cdf0e10cSrcweir 
605cdf0e10cSrcweir 			// tja, dann muss es auf den Stack
606cdf0e10cSrcweir 			if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
607cdf0e10cSrcweir 			{
608cdf0e10cSrcweir 				// vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
609cdf0e10cSrcweir 				if( pCmp->nStt < aTmp.nStt )
610cdf0e10cSrcweir 				{
611cdf0e10cSrcweir 					ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
612cdf0e10cSrcweir 							"Stack-Platz ist noch belegt" );
613cdf0e10cSrcweir 
614cdf0e10cSrcweir // ---------
615cdf0e10cSrcweir // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
616cdf0e10cSrcweir //			pCmp->nEnd = aTmp.nStt;
617cdf0e10cSrcweir 					if( aTmp.nEnd <= pCmp->nEnd )
618cdf0e10cSrcweir 						pCmp->nEnd = aTmp.nStt;
619cdf0e10cSrcweir 					else
620cdf0e10cSrcweir 						pCmp->nStt = aTmp.nEnd;
621cdf0e10cSrcweir // ---------
622cdf0e10cSrcweir 
623cdf0e10cSrcweir 					pStackArr[ nWhch - nArrStart ] = *pCmp;
624cdf0e10cSrcweir 					nStackCnt++;
625cdf0e10cSrcweir 				}
626cdf0e10cSrcweir 				pCmp->nWhich = 0;
627cdf0e10cSrcweir 				nFound--;
628cdf0e10cSrcweir 			}
629cdf0e10cSrcweir 		}
630cdf0e10cSrcweir 		if( pIter )
631cdf0e10cSrcweir 		{
632cdf0e10cSrcweir 			nWhch = pIter->NextWhich();
633cdf0e10cSrcweir 			while( nWhch &&
634cdf0e10cSrcweir 				SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
635cdf0e10cSrcweir 				nWhch = pIter->NextWhich();
636cdf0e10cSrcweir 			if( !nWhch )
637cdf0e10cSrcweir 				break;
638cdf0e10cSrcweir 		}
639cdf0e10cSrcweir 		else
640cdf0e10cSrcweir 			break;
641cdf0e10cSrcweir 	}
642cdf0e10cSrcweir 	return Found();
643cdf0e10cSrcweir }
644cdf0e10cSrcweir 
645cdf0e10cSrcweir 
Start() const646cdf0e10cSrcweir xub_StrLen SwAttrCheckArr::Start() const
647cdf0e10cSrcweir {
648cdf0e10cSrcweir 	xub_StrLen nStart = nNdStt;
649cdf0e10cSrcweir 	_SwSrchChrAttr* pArrPtr = pFndArr;
650cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
651cdf0e10cSrcweir 		if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
652cdf0e10cSrcweir 			nStart = pArrPtr->nStt;
653cdf0e10cSrcweir 
654cdf0e10cSrcweir 	return nStart;
655cdf0e10cSrcweir }
656cdf0e10cSrcweir 
657cdf0e10cSrcweir 
End() const658cdf0e10cSrcweir xub_StrLen SwAttrCheckArr::End() const
659cdf0e10cSrcweir {
660cdf0e10cSrcweir 	_SwSrchChrAttr* pArrPtr = pFndArr;
661cdf0e10cSrcweir 	xub_StrLen nEnd = nNdEnd;
662cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
663cdf0e10cSrcweir 		if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
664cdf0e10cSrcweir 			nEnd = pArrPtr->nEnd;
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 	return nEnd;
667cdf0e10cSrcweir }
668cdf0e10cSrcweir 
669cdf0e10cSrcweir 
CheckStack()670cdf0e10cSrcweir int SwAttrCheckArr::CheckStack()
671cdf0e10cSrcweir {
672cdf0e10cSrcweir 	if( !nStackCnt )
673cdf0e10cSrcweir 		return sal_False;
674cdf0e10cSrcweir 
675cdf0e10cSrcweir 	sal_uInt16 n;
676cdf0e10cSrcweir 	xub_StrLen nSttPos = Start(), nEndPos = End();
677cdf0e10cSrcweir 	_SwSrchChrAttr* pArrPtr;
678cdf0e10cSrcweir 	for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
679cdf0e10cSrcweir 	{
680cdf0e10cSrcweir 		if( !pArrPtr->nWhich )
681cdf0e10cSrcweir 			continue;
682cdf0e10cSrcweir 
683cdf0e10cSrcweir 		if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
684cdf0e10cSrcweir 		{
685cdf0e10cSrcweir 			pArrPtr->nWhich = 0;		// geloescht
686cdf0e10cSrcweir 			if( !--nStackCnt )
687cdf0e10cSrcweir 				return nFound == aCmpSet.Count();
688cdf0e10cSrcweir 		}
689cdf0e10cSrcweir 		else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
690cdf0e10cSrcweir 		{
691cdf0e10cSrcweir 			// alle die "offen" sind, heisst ueber die Start Position ragen,
692cdf0e10cSrcweir 			// im FndSet setzen
693cdf0e10cSrcweir 			ASSERT( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" );
694cdf0e10cSrcweir 			pFndArr[ n ] = *pArrPtr;
695cdf0e10cSrcweir 			pArrPtr->nWhich = 0;
696cdf0e10cSrcweir 			nFound++;
697cdf0e10cSrcweir 			if( !--nStackCnt )
698cdf0e10cSrcweir 				return nFound == aCmpSet.Count();
699cdf0e10cSrcweir 		}
700cdf0e10cSrcweir 	}
701cdf0e10cSrcweir 	return nFound == aCmpSet.Count();
702cdf0e10cSrcweir }
703cdf0e10cSrcweir 
704cdf0e10cSrcweir 
705cdf0e10cSrcweir 
lcl_SearchForward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)706cdf0e10cSrcweir int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
707cdf0e10cSrcweir 							SwPaM& rPam )
708cdf0e10cSrcweir {
709cdf0e10cSrcweir 	xub_StrLen nEndPos, nSttPos;
710cdf0e10cSrcweir 	rCmpArr.SetNewSet( rTxtNd, rPam );
711cdf0e10cSrcweir 	if( !rTxtNd.HasHints() )
712cdf0e10cSrcweir 	{
713cdf0e10cSrcweir 		if( !rCmpArr.Found() )
714cdf0e10cSrcweir 			return sal_False;
715cdf0e10cSrcweir 		nEndPos = rCmpArr.GetNdEnd();
716cdf0e10cSrcweir 		lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
717cdf0e10cSrcweir 		return sal_True;
718cdf0e10cSrcweir 	}
719cdf0e10cSrcweir 
720cdf0e10cSrcweir 	// dann gehe mal durch das nach "Start" sortierte Array
721cdf0e10cSrcweir 	const SwpHints& rHtArr = rTxtNd.GetSwpHints();
722cdf0e10cSrcweir 	const SwTxtAttr* pAttr;
723cdf0e10cSrcweir 	sal_uInt16 nPos = 0;
724cdf0e10cSrcweir 
725cdf0e10cSrcweir 	// sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
726cdf0e10cSrcweir 	// das wieder beendet wird.
727cdf0e10cSrcweir 	if( rCmpArr.Found() )
728cdf0e10cSrcweir 	{
729cdf0e10cSrcweir 		for( ; nPos < rHtArr.Count(); ++nPos )
730cdf0e10cSrcweir 			if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
731cdf0e10cSrcweir 			{
732cdf0e10cSrcweir 				if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
733cdf0e10cSrcweir 				{
734cdf0e10cSrcweir 					// dann haben wir unser Ende:
735cdf0e10cSrcweir 					lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
736cdf0e10cSrcweir 								pAttr->GetStart(), sal_True );
737cdf0e10cSrcweir 					return sal_True;
738cdf0e10cSrcweir 				}
739cdf0e10cSrcweir 				// ansonsten muessen wir weiter suchen
740cdf0e10cSrcweir 				break;
741cdf0e10cSrcweir 			}
742cdf0e10cSrcweir 
743cdf0e10cSrcweir 		if( nPos == rHtArr.Count() && rCmpArr.Found() )
744cdf0e10cSrcweir 		{
745cdf0e10cSrcweir 			// dann haben wir unseren Bereich
746cdf0e10cSrcweir 			nEndPos = rCmpArr.GetNdEnd();
747cdf0e10cSrcweir 			lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
748cdf0e10cSrcweir 			return sal_True;
749cdf0e10cSrcweir 		}
750cdf0e10cSrcweir 	}
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 	for( ; nPos < rHtArr.Count(); ++nPos )
753cdf0e10cSrcweir 		if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
754cdf0e10cSrcweir 		{
755cdf0e10cSrcweir 			// sollten noch mehr auf der gleichen Position anfangen ??
756cdf0e10cSrcweir 			// auch die noch mit testen !!
757cdf0e10cSrcweir 			nSttPos = *pAttr->GetStart();
758cdf0e10cSrcweir 			while( ++nPos < rHtArr.Count() && nSttPos ==
759cdf0e10cSrcweir 					*( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
760cdf0e10cSrcweir 					rCmpArr.SetAttrFwd( *pAttr ) )
761cdf0e10cSrcweir 				;
762cdf0e10cSrcweir 			if( !rCmpArr.Found() )
763cdf0e10cSrcweir 				continue;
764cdf0e10cSrcweir 
765cdf0e10cSrcweir 			// dann haben wir den Bereich zusammen
766cdf0e10cSrcweir 			if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
767cdf0e10cSrcweir 				return sal_False;
768cdf0e10cSrcweir 			lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
769cdf0e10cSrcweir 			return sal_True;
770cdf0e10cSrcweir 		}
771cdf0e10cSrcweir 
772cdf0e10cSrcweir 	if( !rCmpArr.CheckStack() ||
773cdf0e10cSrcweir 		(nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
774cdf0e10cSrcweir 		return sal_False;
775cdf0e10cSrcweir 	lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
776cdf0e10cSrcweir 	return sal_True;
777cdf0e10cSrcweir }
778cdf0e10cSrcweir 
779cdf0e10cSrcweir 
lcl_SearchBackward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)780cdf0e10cSrcweir int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
781cdf0e10cSrcweir 							SwPaM& rPam )
782cdf0e10cSrcweir {
783cdf0e10cSrcweir 	xub_StrLen nEndPos, nSttPos;
784cdf0e10cSrcweir 	rCmpArr.SetNewSet( rTxtNd, rPam );
785cdf0e10cSrcweir 	if( !rTxtNd.HasHints() )
786cdf0e10cSrcweir 	{
787cdf0e10cSrcweir 		if( !rCmpArr.Found() )
788cdf0e10cSrcweir 			return sal_False;
789cdf0e10cSrcweir 		nEndPos = rCmpArr.GetNdEnd();
790cdf0e10cSrcweir 		lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
791cdf0e10cSrcweir 		return sal_True;
792cdf0e10cSrcweir 	}
793cdf0e10cSrcweir 
794cdf0e10cSrcweir 	// dann gehe mal durch das nach "Start" sortierte Array
795cdf0e10cSrcweir 	const SwpHints& rHtArr = rTxtNd.GetSwpHints();
796cdf0e10cSrcweir 	const SwTxtAttr* pAttr;
797cdf0e10cSrcweir 	sal_uInt16 nPos = rHtArr.Count();
798cdf0e10cSrcweir 
799cdf0e10cSrcweir 	// sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
800cdf0e10cSrcweir 	// das wieder beendet wird.
801cdf0e10cSrcweir 	if( rCmpArr.Found() )
802cdf0e10cSrcweir 	{
803cdf0e10cSrcweir 		while( nPos )
804cdf0e10cSrcweir 			if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
805cdf0e10cSrcweir 			{
806cdf0e10cSrcweir 				nSttPos = *pAttr->GetAnyEnd();
807cdf0e10cSrcweir 				if( nSttPos < rCmpArr.GetNdEnd() )
808cdf0e10cSrcweir 				{
809cdf0e10cSrcweir 					// dann haben wir unser Ende:
810cdf0e10cSrcweir 					nEndPos = rCmpArr.GetNdEnd();
811cdf0e10cSrcweir 					lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
812cdf0e10cSrcweir 					return sal_True;
813cdf0e10cSrcweir 				}
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 				// ansonsten muessen wir weiter suchen
816cdf0e10cSrcweir 				break;
817cdf0e10cSrcweir 			}
818cdf0e10cSrcweir 
819cdf0e10cSrcweir 		if( !nPos && rCmpArr.Found() )
820cdf0e10cSrcweir 		{
821cdf0e10cSrcweir 			// dann haben wir unseren Bereich
822cdf0e10cSrcweir 			nEndPos = rCmpArr.GetNdEnd();
823cdf0e10cSrcweir 			lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
824cdf0e10cSrcweir 			return sal_True;
825cdf0e10cSrcweir 		}
826cdf0e10cSrcweir 	}
827cdf0e10cSrcweir 
828cdf0e10cSrcweir 	while( nPos )
829cdf0e10cSrcweir 		if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
830cdf0e10cSrcweir 		{
831cdf0e10cSrcweir 			// sollten noch mehr auf der gleichen Position anfangen ??
832cdf0e10cSrcweir 			// auch die noch mit testen !!
833cdf0e10cSrcweir 			if( nPos )
834cdf0e10cSrcweir 			{
835cdf0e10cSrcweir 				nEndPos = *pAttr->GetAnyEnd();
836cdf0e10cSrcweir 				while( --nPos && nEndPos ==
837cdf0e10cSrcweir 						*( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
838cdf0e10cSrcweir 						rCmpArr.SetAttrBwd( *pAttr ) )
839cdf0e10cSrcweir 					;
840cdf0e10cSrcweir 			}
841cdf0e10cSrcweir 			if( !rCmpArr.Found() )
842cdf0e10cSrcweir 				continue;
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 
845cdf0e10cSrcweir 			// dann haben wir den Bereich zusammen
846cdf0e10cSrcweir 			if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
847cdf0e10cSrcweir 				return sal_False;
848cdf0e10cSrcweir 			lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
849cdf0e10cSrcweir 			return sal_True;
850cdf0e10cSrcweir 		}
851cdf0e10cSrcweir 
852cdf0e10cSrcweir 	if( !rCmpArr.CheckStack() ||
853cdf0e10cSrcweir 		(nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
854cdf0e10cSrcweir 		return sal_False;
855cdf0e10cSrcweir 	lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
856cdf0e10cSrcweir 	return sal_True;
857cdf0e10cSrcweir }
858cdf0e10cSrcweir 
859cdf0e10cSrcweir 
lcl_Search(const SwCntntNode & rCNd,const SfxItemSet & rCmpSet,sal_Bool bNoColls)860cdf0e10cSrcweir int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls )
861cdf0e10cSrcweir {
862cdf0e10cSrcweir 	// nur die harte Attributierung suchen ?
863cdf0e10cSrcweir     if( bNoColls && !rCNd.HasSwAttrSet() )
864cdf0e10cSrcweir 		return sal_False;
865cdf0e10cSrcweir 
866cdf0e10cSrcweir 	const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
867cdf0e10cSrcweir 	SfxItemIter aIter( rCmpSet );
868cdf0e10cSrcweir 	const SfxPoolItem* pItem = aIter.GetCurItem();
869cdf0e10cSrcweir 	const SfxPoolItem* pNdItem;
870cdf0e10cSrcweir 	sal_uInt16 nWhich;
871cdf0e10cSrcweir 
872cdf0e10cSrcweir 	while( sal_True )
873cdf0e10cSrcweir 	{
874cdf0e10cSrcweir 		// nur testen, ob vorhanden ist ?
875cdf0e10cSrcweir 		if( IsInvalidItem( pItem ))
876cdf0e10cSrcweir 		{
877cdf0e10cSrcweir 			nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
878cdf0e10cSrcweir 			if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
879cdf0e10cSrcweir 				|| CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
880cdf0e10cSrcweir 				return sal_False;
881cdf0e10cSrcweir 		}
882cdf0e10cSrcweir 		else
883cdf0e10cSrcweir 		{
884cdf0e10cSrcweir 			nWhich = pItem->Which();
885cdf0e10cSrcweir //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
886cdf0e10cSrcweir //				runter
887cdf0e10cSrcweir //			if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
888cdf0e10cSrcweir //				|| *pNdItem != *pItem )
889cdf0e10cSrcweir 			if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
890cdf0e10cSrcweir 				return sal_False;
891cdf0e10cSrcweir 		}
892cdf0e10cSrcweir 
893cdf0e10cSrcweir 		if( aIter.IsAtEnd() )
894cdf0e10cSrcweir 			break;
895cdf0e10cSrcweir 		pItem = aIter.NextItem();
896cdf0e10cSrcweir 	}
897cdf0e10cSrcweir 	return sal_True;			// wurde gefunden
898cdf0e10cSrcweir }
899cdf0e10cSrcweir 
900cdf0e10cSrcweir 
Find(const SfxPoolItem & rAttr,sal_Bool bValue,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)901cdf0e10cSrcweir sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove,
902cdf0e10cSrcweir 					const SwPaM *pRegion, sal_Bool bInReadOnly )
903cdf0e10cSrcweir {
904cdf0e10cSrcweir 	// stelle fest welches Attribut gesucht wird:
905*69a74367SOliver-Rainer Wittmann 	const sal_uInt16 nWhich = rAttr.Which();
906cdf0e10cSrcweir     int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
907cdf0e10cSrcweir 
908cdf0e10cSrcweir 	SwPaM* pPam = MakeRegion( fnMove, pRegion );
909cdf0e10cSrcweir 
910cdf0e10cSrcweir 	sal_Bool bFound = sal_False;
911cdf0e10cSrcweir 	sal_Bool bFirst = sal_True;
912cdf0e10cSrcweir 	sal_Bool bSrchForward = fnMove == fnMoveForward;
913cdf0e10cSrcweir 	SwCntntNode * pNode;
914cdf0e10cSrcweir 	const SfxPoolItem* pItem;
915cdf0e10cSrcweir 	SwpFmts aFmtArr;
916cdf0e10cSrcweir 
917cdf0e10cSrcweir 	// Wenn am Anfang/Ende, aus dem Node moven
918cdf0e10cSrcweir 	if( bSrchForward
919cdf0e10cSrcweir 		? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
920cdf0e10cSrcweir 		: !pPam->GetPoint()->nContent.GetIndex() )
921cdf0e10cSrcweir 	{
922cdf0e10cSrcweir 		if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
923cdf0e10cSrcweir 		{
924cdf0e10cSrcweir 			delete pPam;
925cdf0e10cSrcweir 			return sal_False;
926cdf0e10cSrcweir 		}
927cdf0e10cSrcweir 		SwCntntNode *pNd = pPam->GetCntntNode();
928cdf0e10cSrcweir 		xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
929cdf0e10cSrcweir 		pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
930cdf0e10cSrcweir 	}
931cdf0e10cSrcweir 
932cdf0e10cSrcweir 	while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
933cdf0e10cSrcweir 	{
934cdf0e10cSrcweir 		if( bCharAttr )
935cdf0e10cSrcweir 		{
936cdf0e10cSrcweir 			if( !pNode->IsTxtNode() )       // CharAttr sind nur in TextNodes
937cdf0e10cSrcweir 				continue;
938cdf0e10cSrcweir 
939cdf0e10cSrcweir 			if( ((SwTxtNode*)pNode)->HasHints() &&
940cdf0e10cSrcweir 				lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove,  bValue ))
941cdf0e10cSrcweir 			{
942cdf0e10cSrcweir 				// setze auf die Werte vom Attribut
943cdf0e10cSrcweir 				SetMark();
944cdf0e10cSrcweir 				*GetPoint() = *pPam->GetPoint();
945cdf0e10cSrcweir 				*GetMark() = *pPam->GetMark();
946cdf0e10cSrcweir 				bFound = sal_True;
947cdf0e10cSrcweir 				break;
948cdf0e10cSrcweir 			}
949cdf0e10cSrcweir             else if (isTXTATR(nWhich))
950cdf0e10cSrcweir 				continue;               // --> also weiter
951cdf0e10cSrcweir 		}
952cdf0e10cSrcweir 
953cdf0e10cSrcweir 		// keine harte Attributierung, dann pruefe, ob die Vorlage schon
954cdf0e10cSrcweir 		// mal nach dem Attribut befragt wurde
955cdf0e10cSrcweir         if( !pNode->HasSwAttrSet() )
956cdf0e10cSrcweir 		{
957cdf0e10cSrcweir 			const SwFmt* pTmpFmt = pNode->GetFmtColl();
958cdf0e10cSrcweir 			if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
959cdf0e10cSrcweir 				continue; 	// die Collection wurde schon mal befragt
960cdf0e10cSrcweir 			aFmtArr.Insert( pTmpFmt );
961cdf0e10cSrcweir 		}
962cdf0e10cSrcweir 
963cdf0e10cSrcweir 		if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
964cdf0e10cSrcweir 			sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) )
965cdf0e10cSrcweir 		{
966cdf0e10cSrcweir 			// FORWARD:  Point an das Ende, GetMark zum Anfanf vom Node
967cdf0e10cSrcweir 			// BACKWARD: Point zum Anfang,	GetMark an das Ende vom Node
968cdf0e10cSrcweir 			// und immer nach der Logik: inkl. Start, exkl. End !!!
969cdf0e10cSrcweir 			*GetPoint() = *pPam->GetPoint();
970cdf0e10cSrcweir 			SetMark();
971cdf0e10cSrcweir 			pNode->MakeEndIndex( &GetPoint()->nContent );
972cdf0e10cSrcweir 			bFound = sal_True;
973cdf0e10cSrcweir 			break;
974cdf0e10cSrcweir 		}
975cdf0e10cSrcweir 	}
976cdf0e10cSrcweir 
977cdf0e10cSrcweir 	// beim rueckwaerts Suchen noch Point und Mark vertauschen
978cdf0e10cSrcweir 	if( bFound && !bSrchForward )
979cdf0e10cSrcweir 		Exchange();
980cdf0e10cSrcweir 
981cdf0e10cSrcweir 	delete pPam;
982cdf0e10cSrcweir 	return bFound;
983cdf0e10cSrcweir }
984cdf0e10cSrcweir 
985cdf0e10cSrcweir 
986cdf0e10cSrcweir typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
987cdf0e10cSrcweir 
Find(const SfxItemSet & rSet,sal_Bool bNoColls,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly,sal_Bool bMoveFirst)988cdf0e10cSrcweir sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove,
989cdf0e10cSrcweir 					const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst )
990cdf0e10cSrcweir {
991cdf0e10cSrcweir 	SwPaM* pPam = MakeRegion( fnMove, pRegion );
992cdf0e10cSrcweir 
993cdf0e10cSrcweir 	sal_Bool bFound = sal_False;
994cdf0e10cSrcweir 	sal_Bool bFirst = sal_True;
995cdf0e10cSrcweir 	sal_Bool bSrchForward = fnMove == fnMoveForward;
996cdf0e10cSrcweir 	SwCntntNode * pNode;
997cdf0e10cSrcweir 	SwpFmts aFmtArr;
998cdf0e10cSrcweir 
999cdf0e10cSrcweir 	// teste doch mal welche Text/Char-Attribute gesucht werden
1000cdf0e10cSrcweir 	SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
1001cdf0e10cSrcweir 	SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
1002cdf0e10cSrcweir 							RES_PARATR_BEGIN, RES_GRFATR_END-1 );
1003cdf0e10cSrcweir 	aOtherSet.Put( rSet, sal_False );	// alle Invalid-Items erhalten!
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 	FnSearchAttr fnSearch = bSrchForward
1006cdf0e10cSrcweir 								? (&::lcl_SearchForward)
1007cdf0e10cSrcweir 								: (&::lcl_SearchBackward);
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir 	// Wenn am Anfang/Ende, aus dem Node moven
1010cdf0e10cSrcweir 	// Wenn am Anfang/Ende, aus dem Node moven
1011cdf0e10cSrcweir 	if( bMoveFirst &&
1012cdf0e10cSrcweir         ( bSrchForward
1013cdf0e10cSrcweir 		? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
1014cdf0e10cSrcweir 		: !pPam->GetPoint()->nContent.GetIndex() ) )
1015cdf0e10cSrcweir 	{
1016cdf0e10cSrcweir 		if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
1017cdf0e10cSrcweir 		{
1018cdf0e10cSrcweir 			delete pPam;
1019cdf0e10cSrcweir 			return sal_False;
1020cdf0e10cSrcweir 		}
1021cdf0e10cSrcweir 		SwCntntNode *pNd = pPam->GetCntntNode();
1022cdf0e10cSrcweir 		xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
1023cdf0e10cSrcweir 		pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
1024cdf0e10cSrcweir 	}
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir 	while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
1028cdf0e10cSrcweir 	{
1029cdf0e10cSrcweir 		if( aCmpArr.Count() )
1030cdf0e10cSrcweir 		{
1031cdf0e10cSrcweir 			if( !pNode->IsTxtNode() )       // CharAttr sind nur in TextNodes
1032cdf0e10cSrcweir 				continue;
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir 			if( (!aOtherSet.Count() ||
1035cdf0e10cSrcweir                 lcl_Search( *pNode, aOtherSet, bNoColls )) &&
1036cdf0e10cSrcweir 				(*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
1037cdf0e10cSrcweir 			{
1038cdf0e10cSrcweir 				// setze auf die Werte vom Attribut
1039cdf0e10cSrcweir 				SetMark();
1040cdf0e10cSrcweir 				*GetPoint() = *pPam->GetPoint();
1041cdf0e10cSrcweir 				*GetMark() = *pPam->GetMark();
1042cdf0e10cSrcweir 				bFound = sal_True;
1043cdf0e10cSrcweir 				break;
1044cdf0e10cSrcweir 			}
1045cdf0e10cSrcweir 			continue;		// TextAttribute
1046cdf0e10cSrcweir 		}
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir 		if( !aOtherSet.Count() )
1049cdf0e10cSrcweir 			continue;
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir 		// keine harte Attributierung, dann pruefe, ob die Vorlage schon
1052cdf0e10cSrcweir 		// mal nach dem Attribut befragt wurde
1053cdf0e10cSrcweir         if( !pNode->HasSwAttrSet() )
1054cdf0e10cSrcweir 		{
1055cdf0e10cSrcweir 			const SwFmt* pTmpFmt = pNode->GetFmtColl();
1056cdf0e10cSrcweir 			if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
1057cdf0e10cSrcweir 				continue; 	// die Collection wurde schon mal befragt
1058cdf0e10cSrcweir 			aFmtArr.Insert( pTmpFmt );
1059cdf0e10cSrcweir 		}
1060cdf0e10cSrcweir 
1061cdf0e10cSrcweir         if( lcl_Search( *pNode, aOtherSet, bNoColls ))
1062cdf0e10cSrcweir 		{
1063cdf0e10cSrcweir 			// FORWARD:  Point an das Ende, GetMark zum Anfanf vom Node
1064cdf0e10cSrcweir 			// BACKWARD: Point zum Anfang,	GetMark an das Ende vom Node
1065cdf0e10cSrcweir 			// und immer nach der Logik: inkl. Start, exkl. End !!!
1066cdf0e10cSrcweir 			*GetPoint() = *pPam->GetPoint();
1067cdf0e10cSrcweir 			SetMark();
1068cdf0e10cSrcweir 			pNode->MakeEndIndex( &GetPoint()->nContent );
1069cdf0e10cSrcweir 			bFound = sal_True;
1070cdf0e10cSrcweir 			break;
1071cdf0e10cSrcweir 		}
1072cdf0e10cSrcweir 	}
1073cdf0e10cSrcweir 
1074cdf0e10cSrcweir 	// beim rueckwaerts Suchen noch Point und Mark vertauschen
1075cdf0e10cSrcweir 	if( bFound && !bSrchForward )
1076cdf0e10cSrcweir 		Exchange();
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir 	delete pPam;
1079cdf0e10cSrcweir 	return bFound;
1080cdf0e10cSrcweir }
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir //------------------ Methoden vom SwCursor ---------------------------
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir // Parameter fuer das Suchen vom Attributen
1085cdf0e10cSrcweir struct SwFindParaAttr : public SwFindParas
1086cdf0e10cSrcweir {
1087cdf0e10cSrcweir 	sal_Bool bValue;
1088cdf0e10cSrcweir 	const SfxItemSet *pSet, *pReplSet;
1089cdf0e10cSrcweir 	const SearchOptions *pSearchOpt;
1090cdf0e10cSrcweir 	SwCursor& rCursor;
1091cdf0e10cSrcweir 	utl::TextSearch* pSTxt;
1092cdf0e10cSrcweir 
SwFindParaAttrSwFindParaAttr1093cdf0e10cSrcweir 	SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection,
1094cdf0e10cSrcweir 					const SearchOptions* pOpt, const SfxItemSet* pRSet,
1095cdf0e10cSrcweir 					SwCursor& rCrsr )
1096cdf0e10cSrcweir         : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
1097cdf0e10cSrcweir           pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
1098cdf0e10cSrcweir 
~SwFindParaAttrSwFindParaAttr1099cdf0e10cSrcweir     virtual ~SwFindParaAttr()   { delete pSTxt; }
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir 	virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
1102cdf0e10cSrcweir 	virtual int IsReplaceMode() const;
1103cdf0e10cSrcweir };
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir 
Find(SwPaM * pCrsr,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)1106cdf0e10cSrcweir int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
1107cdf0e10cSrcweir 							sal_Bool bInReadOnly )
1108cdf0e10cSrcweir {
1109cdf0e10cSrcweir 	// String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert
1110cdf0e10cSrcweir 	// 						gesucht wird)
1111cdf0e10cSrcweir 	sal_Bool bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1112cdf0e10cSrcweir 									!pSet->Count() );
1113cdf0e10cSrcweir 	sal_Bool bReplaceAttr = pReplSet && pReplSet->Count();
1114cdf0e10cSrcweir     sal_Bool bMoveFirst = !bReplaceAttr;
1115cdf0e10cSrcweir 	if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
1116cdf0e10cSrcweir 		bInReadOnly = sal_False;
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir 	// wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ?
1119cdf0e10cSrcweir 	{
1120cdf0e10cSrcweir 		SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
1121cdf0e10cSrcweir 		SwPaM* pTextRegion = &aRegion;
1122cdf0e10cSrcweir 		SwPaM aSrchPam( *pCrsr->GetPoint() );
1123cdf0e10cSrcweir 
1124cdf0e10cSrcweir 		while( sal_True )
1125cdf0e10cSrcweir 		{
1126cdf0e10cSrcweir 			if( pSet->Count() )			// gibts ueberhaupt Attributierung?
1127cdf0e10cSrcweir 			{
1128cdf0e10cSrcweir 				// zuerst die Attributierung
1129cdf0e10cSrcweir 				if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
1130cdf0e10cSrcweir //JP 17.11.95: was ist mit Attributen in leeren Absaetzen !!
1131cdf0e10cSrcweir //					|| *pCrsr->GetMark() == *pCrsr->GetPoint() )	// kein Bereich ??
1132cdf0e10cSrcweir 					return FIND_NOT_FOUND;
1133cdf0e10cSrcweir                 bMoveFirst = sal_True;
1134cdf0e10cSrcweir 
1135cdf0e10cSrcweir 				if( !pSearchOpt )
1136cdf0e10cSrcweir 					break; 		// ok, nur Attribute, also gefunden
1137cdf0e10cSrcweir 
1138cdf0e10cSrcweir 				pTextRegion = &aSrchPam;
1139cdf0e10cSrcweir 			}
1140cdf0e10cSrcweir 			else if( !pSearchOpt )
1141cdf0e10cSrcweir 				return FIND_NOT_FOUND;
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir 			// dann darin den Text
1144cdf0e10cSrcweir 			if( !pSTxt )
1145cdf0e10cSrcweir 			{
1146cdf0e10cSrcweir 				SearchOptions aTmp( *pSearchOpt );
1147cdf0e10cSrcweir 
1148cdf0e10cSrcweir 				// search in selection
1149cdf0e10cSrcweir 				aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
1150cdf0e10cSrcweir 								    SearchFlags::REG_NOT_ENDOFLINE);
1151cdf0e10cSrcweir 
1152cdf0e10cSrcweir                 MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
1153cdf0e10cSrcweir 
1154cdf0e10cSrcweir 				pSTxt = new utl::TextSearch( aTmp );
1155cdf0e10cSrcweir 			}
1156cdf0e10cSrcweir 
1157cdf0e10cSrcweir 			// todo/mba: searching for attributes in Outliner text?!
1158cdf0e10cSrcweir 			sal_Bool bSearchInNotes = sal_False;
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir 			// Bug 24665: suche im richtigen Bereich weiter (pTextRegion!)
1161cdf0e10cSrcweir 			if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
1162cdf0e10cSrcweir 				*aSrchPam.GetMark() != *aSrchPam.GetPoint() )   // gefunden ?
1163cdf0e10cSrcweir 				break;										// also raus
1164cdf0e10cSrcweir 			else if( !pSet->Count() )
1165cdf0e10cSrcweir 				return FIND_NOT_FOUND;		// nur Text und nicht gefunden
1166cdf0e10cSrcweir 
1167cdf0e10cSrcweir /*          // --> FME 2007-4-12 #i74765 # Why should we move the position?
1168cdf0e10cSrcweir             Moving the position results in bugs when there are two adjacent
1169cdf0e10cSrcweir             portions which both have the requested attributes set. I suspect this
1170cdf0e10cSrcweir             should be only be an optimization. Therefore I boldly remove it now!
1171cdf0e10cSrcweir 
1172cdf0e10cSrcweir             // JP: und wieder neu aufsetzen, aber eine Position weiter
1173cdf0e10cSrcweir 			//JP 04.11.97: Bug 44897 - aber den Mark wieder aufheben, damit
1174cdf0e10cSrcweir 			//				weiterbewegt werden kann!
1175cdf0e10cSrcweir 			{
1176cdf0e10cSrcweir 				sal_Bool bCheckRegion = sal_True;
1177cdf0e10cSrcweir 				SwPosition* pPos = aSrchPam.GetPoint();
1178cdf0e10cSrcweir 				if( !(*fnMove->fnNd)( &pPos->nNode.GetNode(),
1179cdf0e10cSrcweir 										&pPos->nContent, CRSR_SKIP_CHARS ))
1180cdf0e10cSrcweir 				{
1181cdf0e10cSrcweir 					if( (*fnMove->fnNds)( &pPos->nNode, sal_False ))
1182cdf0e10cSrcweir 					{
1183cdf0e10cSrcweir 						SwCntntNode *pNd = pPos->nNode.GetNode().GetCntntNode();
1184cdf0e10cSrcweir 						xub_StrLen nCPos;
1185cdf0e10cSrcweir 						if( fnMove == fnMoveForward )
1186cdf0e10cSrcweir 							nCPos = 0;
1187cdf0e10cSrcweir 						else
1188cdf0e10cSrcweir 							nCPos = pNd->Len();
1189cdf0e10cSrcweir 						pPos->nContent.Assign( pNd, nCPos );
1190cdf0e10cSrcweir 					}
1191cdf0e10cSrcweir 					else
1192cdf0e10cSrcweir 						bCheckRegion = sal_False;
1193cdf0e10cSrcweir 				}
1194cdf0e10cSrcweir 				if( !bCheckRegion || *aRegion.GetPoint() <= *pPos )
1195cdf0e10cSrcweir 					return FIND_NOT_FOUND;		// nicht gefunden
1196cdf0e10cSrcweir 			}*/
1197cdf0e10cSrcweir 			*aRegion.GetMark() = *aSrchPam.GetPoint();
1198cdf0e10cSrcweir 		}
1199cdf0e10cSrcweir 
1200cdf0e10cSrcweir 		*pCrsr->GetPoint() = *aSrchPam.GetPoint();
1201cdf0e10cSrcweir 		pCrsr->SetMark();
1202cdf0e10cSrcweir 		*pCrsr->GetMark() = *aSrchPam.GetMark();
1203cdf0e10cSrcweir 	}
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir 	if( bReplaceTxt )
1206cdf0e10cSrcweir 	{
1207cdf0e10cSrcweir         const bool bRegExp(
1208cdf0e10cSrcweir                 SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
1209cdf0e10cSrcweir 		SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
1210cdf0e10cSrcweir 		xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
1211cdf0e10cSrcweir 
1212cdf0e10cSrcweir 		// damit die Region auch verschoben wird, in den Shell-Cursr-Ring
1213cdf0e10cSrcweir 		// mit aufnehmen !!
1214cdf0e10cSrcweir         Ring *pPrevRing = 0;
1215cdf0e10cSrcweir 		if( bRegExp )
1216cdf0e10cSrcweir 		{
1217cdf0e10cSrcweir             pPrevRing = pRegion->GetPrev();
1218cdf0e10cSrcweir 			((Ring*)pRegion)->MoveRingTo( &rCursor );
1219cdf0e10cSrcweir 		}
1220cdf0e10cSrcweir 
1221cdf0e10cSrcweir         ::std::auto_ptr<String> pRepl( (bRegExp) ?
1222cdf0e10cSrcweir                 ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
1223cdf0e10cSrcweir         rCursor.GetDoc()->ReplaceRange( *pCrsr,
1224cdf0e10cSrcweir             (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
1225cdf0e10cSrcweir             bRegExp );
1226cdf0e10cSrcweir 		rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
1227cdf0e10cSrcweir 
1228cdf0e10cSrcweir 		if( bRegExp )
1229cdf0e10cSrcweir 		{
1230cdf0e10cSrcweir 			// und die Region wieder herausnehmen:
1231cdf0e10cSrcweir 			Ring *p, *pNext = (Ring*)pRegion;
1232cdf0e10cSrcweir 			do {
1233cdf0e10cSrcweir 				p = pNext;
1234cdf0e10cSrcweir 				pNext = p->GetNext();
1235cdf0e10cSrcweir 				p->MoveTo( (Ring*)pRegion );
1236cdf0e10cSrcweir             } while( p != pPrevRing );
1237cdf0e10cSrcweir 		}
1238cdf0e10cSrcweir 		rSttCntIdx = nSttCnt;
1239cdf0e10cSrcweir 	}
1240cdf0e10cSrcweir 
1241cdf0e10cSrcweir 	if( bReplaceAttr )
1242cdf0e10cSrcweir 	{
1243cdf0e10cSrcweir 		// --- Ist die Selection noch da ??????
1244cdf0e10cSrcweir 
1245cdf0e10cSrcweir 		// und noch die Attribute setzen
1246cdf0e10cSrcweir #ifdef OLD
1247cdf0e10cSrcweir 		pCrsr->GetDoc()->Insert( *pCrsr, *pReplSet, 0 );
1248cdf0e10cSrcweir #else
1249cdf0e10cSrcweir 		//JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im
1250cdf0e10cSrcweir 		//				ReplaceSet angegeben, auf Default zurueck gesetzt
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir 		if( !pSet->Count() )
1253cdf0e10cSrcweir         {
1254cdf0e10cSrcweir             pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
1255cdf0e10cSrcweir         }
1256cdf0e10cSrcweir 		else
1257cdf0e10cSrcweir 		{
1258cdf0e10cSrcweir 			SfxItemPool* pPool = pReplSet->GetPool();
1259cdf0e10cSrcweir 			SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir 			SfxItemIter aIter( *pSet );
1262cdf0e10cSrcweir 			const SfxPoolItem* pItem = aIter.GetCurItem();
1263cdf0e10cSrcweir 			while( sal_True )
1264cdf0e10cSrcweir 			{
1265cdf0e10cSrcweir 				// alle die nicht gesetzt sind mit Pool-Defaults aufuellen
1266cdf0e10cSrcweir 				if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
1267cdf0e10cSrcweir 					pReplSet->GetItemState( pItem->Which(), sal_False ))
1268cdf0e10cSrcweir 					aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir 				if( aIter.IsAtEnd() )
1271cdf0e10cSrcweir 					break;
1272cdf0e10cSrcweir 				pItem = aIter.NextItem();
1273cdf0e10cSrcweir 			}
1274cdf0e10cSrcweir 			aSet.Put( *pReplSet );
1275cdf0e10cSrcweir             pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
1276cdf0e10cSrcweir         }
1277cdf0e10cSrcweir #endif
1278cdf0e10cSrcweir 		return FIND_NO_RING;
1279cdf0e10cSrcweir 	}
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir 	else
1282cdf0e10cSrcweir 		return FIND_FOUND;
1283cdf0e10cSrcweir }
1284cdf0e10cSrcweir 
1285cdf0e10cSrcweir 
IsReplaceMode() const1286cdf0e10cSrcweir int SwFindParaAttr::IsReplaceMode() const
1287cdf0e10cSrcweir {
1288cdf0e10cSrcweir 	return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) ||
1289cdf0e10cSrcweir 		   ( pReplSet && pReplSet->Count() );
1290cdf0e10cSrcweir }
1291cdf0e10cSrcweir 
1292cdf0e10cSrcweir // Suchen nach Attributen
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir 
Find(const SfxItemSet & rSet,sal_Bool bNoCollections,SwDocPositions nStart,SwDocPositions nEnde,sal_Bool & bCancel,FindRanges eFndRngs,const SearchOptions * pSearchOpt,const SfxItemSet * pReplSet)1295cdf0e10cSrcweir sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
1296cdf0e10cSrcweir 					SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel,
1297cdf0e10cSrcweir 					FindRanges eFndRngs,
1298cdf0e10cSrcweir 					const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet )
1299cdf0e10cSrcweir {
1300cdf0e10cSrcweir 	// OLE-Benachrichtigung abschalten !!
1301cdf0e10cSrcweir 	SwDoc* pDoc = GetDoc();
1302cdf0e10cSrcweir 	Link aLnk( pDoc->GetOle2Link() );
1303cdf0e10cSrcweir 	pDoc->SetOle2Link( Link() );
1304cdf0e10cSrcweir 
1305cdf0e10cSrcweir 	sal_Bool bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1306cdf0e10cSrcweir 									!rSet.Count() ) ) ||
1307cdf0e10cSrcweir 					(pReplSet && pReplSet->Count());
1308cdf0e10cSrcweir     bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
1309cdf0e10cSrcweir     if (bStartUndo)
1310cdf0e10cSrcweir     {
1311cdf0e10cSrcweir         pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
1312cdf0e10cSrcweir     }
1313cdf0e10cSrcweir 
1314cdf0e10cSrcweir 	SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
1315cdf0e10cSrcweir 									pReplSet, *this );
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir     sal_uLong nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel );
1318cdf0e10cSrcweir 	pDoc->SetOle2Link( aLnk );
1319cdf0e10cSrcweir 	if( nRet && bReplace )
1320cdf0e10cSrcweir 		pDoc->SetModified();
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir     if (bStartUndo)
1323cdf0e10cSrcweir     {
1324cdf0e10cSrcweir         pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
1325cdf0e10cSrcweir     }
1326cdf0e10cSrcweir 
1327cdf0e10cSrcweir 	return nRet;
1328cdf0e10cSrcweir }
1329cdf0e10cSrcweir 
1330cdf0e10cSrcweir 
1331cdf0e10cSrcweir 
1332