xref: /aoo42x/main/svl/source/items/itemset.cxx (revision 05f023e4)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svl.hxx"
26 
27 #include <string.h>
28 
29 #if STLPORT_VERSION>=321
30 #include <cstdarg>
31 #endif
32 
33 #define _SVSTDARR_USHORTS
34 #define _SVSTDARR_ULONGS
35 
36 #include <svl/svstdarr.hxx>
37 #include <svl/itemset.hxx>
38 #include <svl/itempool.hxx>
39 #include <svl/itemiter.hxx>
40 #include <svl/whiter.hxx>
41 #include <svl/nranges.hxx>
42 #include "whassert.hxx"
43 
44 #include <tools/stream.hxx>
45 #include <tools/solar.h>
46 
47 // STATIC DATA -----------------------------------------------------------
48 
49 static const sal_uInt16 nInitCount = 10; // einzelne USHORTs => 5 Paare ohne '0'
50 #ifdef DBG_UTIL
51 static sal_uLong nRangesCopyCount = 0;	 // wie oft wurden Ranges kopiert
52 #endif
53 
54 DBG_NAME(SfxItemSet)
55 
56 //========================================================================
57 
58 #define NUMTYPE 		sal_uInt16
59 #define SvNums			SvUShorts
60 #define SfxNumRanges    SfxUShortRanges
61 #include "nranges.cxx"
62 #undef NUMTYPE
63 #undef SvNums
64 #undef SfxNumRanges
65 
66 #define NUMTYPE 		sal_uLong
67 #define SvNums			SvULongs
68 #define SfxNumRanges    SfxULongRanges
69 #include "nranges.cxx"
70 #undef NUMTYPE
71 #undef SvNums
72 #undef SfxNumRanges
73 
74 //========================================================================
75 
76 #ifdef DBG_UTIL
77 
78 
79 const sal_Char *DbgCheckItemSet( const void* pVoid )
80 {
81 	const SfxItemSet *pSet = (const SfxItemSet*) pVoid;
82 	SfxWhichIter aIter( *pSet );
83 	sal_uInt16 nCount = 0, n = 0;
84 	for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh; nWh = aIter.NextWhich(), ++n )
85 	{
86 		const SfxPoolItem *pItem = pSet->_aItems[n];
87 		if ( pItem )
88 		{
89 			++nCount;
90 			DBG_ASSERT( IsInvalidItem(pItem) ||
91 						pItem->Which() == 0 || pItem->Which() == nWh,
92 						"SfxItemSet: invalid which-id" );
93 			DBG_ASSERT( IsInvalidItem(pItem) || !pItem->Which() ||
94 					!SfxItemPool::IsWhich(pItem->Which()) ||
95 					pSet->GetPool()->IsItemFlag(nWh, SFX_ITEM_NOT_POOLABLE) ||
96 					SFX_ITEMS_NULL != pSet->GetPool()->GetSurrogate(pItem),
97 					"SfxItemSet: item in set which is not in pool" );
98 		}
99 
100 	}
101 	DBG_ASSERT( pSet->_nCount == nCount, "wrong SfxItemSet::nCount detected" );
102 
103 	return 0;
104 }
105 
106 #endif
107 // -----------------------------------------------------------------------
108 
109 SfxItemSet::SfxItemSet
110 (
111 	SfxItemPool&	rPool,  		/* der Pool, in dem die SfxPoolItems,
112 									   welche in dieses SfxItemSet gelangen,
113 									   aufgenommen werden sollen */
114 	sal_Bool
115 #ifdef DBG_UTIL
116 #ifdef SFX_ITEMSET_NO_DEFAULT_CTOR
117 
118                     bTotalRanges	/* komplette Pool-Ranges uebernehmen,
119                                        muss auf sal_True gesetzt werden */
120 #endif
121 #endif
122 )
123 /*	[Beschreibung]
124 
125     Konstruktor fuer ein SfxItemSet mit genau den Which-Bereichen, welche
126 	dem angegebenen <SfxItemPool> bekannt sind.
127 
128 
129 	[Anmerkung]
130 
131 	F"ur Sfx-Programmierer ein derart konstruiertes SfxItemSet kann
132 	keinerlei Items mit Slot-Ids als Which-Werte aufnehmen!
133 */
134 
135 :	_pPool( &rPool ),
136 	_pParent( 0 ),
137 	_nCount( 0 ),
138 	_aHashKey( 0 ) //i120575
139 {
140 	DBG_CTOR(SfxItemSet, DbgCheckItemSet);
141 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
142 	DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
143 //	DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
144 //				"please use suitable ranges" );
145 #ifdef DBG_UTIL
146 #ifdef SFX_ITEMSET_NO_DEFAULT_CTOR
147 	if ( !bTotalRanges )
148 		*(int*)0 = 0; // GPF
149 #endif
150 #endif
151 
152 	_pWhichRanges = (sal_uInt16*) _pPool->GetFrozenIdRanges();
153 	DBG_ASSERT( _pWhichRanges, "don't create ItemSets with full range before FreezeIdRanges()" );
154 	if ( !_pWhichRanges )
155 		_pPool->FillItemIdRanges_Impl( _pWhichRanges );
156 
157 	const sal_uInt16 nSize = TotalCount();
158 	_aItems = new const SfxPoolItem* [ nSize ];
159 	memset( (void*) _aItems, 0, nSize * sizeof( SfxPoolItem* ) );
160 }
161 
162 // -----------------------------------------------------------------------
163 
164 SfxItemSet::SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2 ):
165 	_pPool( &rPool ),
166 	_pParent( 0 ),
167 	_nCount( 0 ),
168 	_aHashKey( 0 ) //i120575
169 {
170 	DBG_CTOR(SfxItemSet, DbgCheckItemSet);
171 	DBG_ASSERT( nWhich1 <= nWhich2, "Ungueltiger Bereich" );
172 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
173 	DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
174 
175 	InitRanges_Impl(nWhich1, nWhich2);
176 }
177 
178 // -----------------------------------------------------------------------
179 
180 void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2)
181 {
182 	DBG_CHKTHIS(SfxItemSet, 0);
183 	_pWhichRanges = new sal_uInt16[ 3 ];
184 	*(_pWhichRanges+0) = nWh1;
185 	*(_pWhichRanges+1) = nWh2;
186 	*(_pWhichRanges+2) = 0;
187 	const sal_uInt16 nRg = nWh2 - nWh1 + 1;
188 	_aItems = new const SfxPoolItem* [ nRg ];
189 	memset( (void*) _aItems, 0, nRg * sizeof( SfxPoolItem* ) );
190 }
191 
192 // -----------------------------------------------------------------------
193 
194 void SfxItemSet::InitRanges_Impl(va_list pArgs, sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull)
195 {
196 	DBG_CHKTHIS(SfxItemSet, 0);
197 
198 	sal_uInt16 nSize = InitializeRanges_Impl( _pWhichRanges, pArgs, nWh1, nWh2, nNull );
199 	_aItems = new const SfxPoolItem* [ nSize ];
200 	memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nSize );
201 }
202 
203 // -----------------------------------------------------------------------
204 
205 SfxItemSet::SfxItemSet( SfxItemPool& rPool,
206 						USHORT_ARG nWh1, USHORT_ARG nWh2, USHORT_ARG nNull, ... ):
207 	_pPool( &rPool ),
208 	_pParent( 0 ),
209 	_pWhichRanges( 0 ),
210 	_nCount( 0 ),
211 	_aHashKey( 0 ) //i120575
212 {
213 	DBG_CTOR(SfxItemSet, DbgCheckItemSet);
214 	DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
215 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
216 	DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
217 
218 	if(!nNull)
219 		InitRanges_Impl(
220             sal::static_int_cast< sal_uInt16 >(nWh1),
221             sal::static_int_cast< sal_uInt16 >(nWh2));
222 	else {
223 		va_list pArgs;
224 		va_start( pArgs, nNull );
225 		InitRanges_Impl(
226             pArgs, sal::static_int_cast< sal_uInt16 >(nWh1),
227             sal::static_int_cast< sal_uInt16 >(nWh2),
228             sal::static_int_cast< sal_uInt16 >(nNull));
229 	}
230 }
231 
232 // -----------------------------------------------------------------------
233 
234 void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable)
235 {
236 	DBG_CHKTHIS(SfxItemSet, 0);
237 	DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
238 
239 	sal_uInt16 nCnt = 0;
240 	const sal_uInt16* pPtr = pWhichPairTable;
241 	while( *pPtr )
242 	{
243 		nCnt += ( *(pPtr+1) - *pPtr ) + 1;
244 		pPtr += 2;
245 	}
246 
247 	_aItems = new const SfxPoolItem* [ nCnt ];
248 	memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nCnt );
249 
250 	std::ptrdiff_t cnt = pPtr - pWhichPairTable +1;
251 	_pWhichRanges = new sal_uInt16[ cnt ];
252 	memcpy( _pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt );
253 }
254 
255 
256 // -----------------------------------------------------------------------
257 
258 SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ):
259 	_pPool( &rPool ),
260 	_pParent( 0 ),
261 	_pWhichRanges(0),
262 	_nCount( 0 ),
263 	_aHashKey( 0 ) //i120575
264 {
265 	DBG_CTOR(SfxItemSet, 0);
266 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
267 	DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
268 
269 	// pWhichPairTable == 0 ist f"ur das SfxAllEnumItemSet
270 	if ( pWhichPairTable )
271 		InitRanges_Impl(pWhichPairTable);
272 }
273 
274 // -----------------------------------------------------------------------
275 
276 SfxItemSet::SfxItemSet( const SfxItemSet& rASet ):
277 	_pPool( rASet._pPool ),
278 	_pParent( rASet._pParent ),
279 	_nCount( rASet._nCount ),
280 	_aHashKey( 0 ) //i120575
281 {
282 	DBG_CTOR(SfxItemSet, DbgCheckItemSet);
283 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
284 	DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
285 	DBG( ++*_pChildCount(_pParent) );
286 
287 	// errechne die Anzahl von Attributen
288 	sal_uInt16 nCnt = 0;
289 	sal_uInt16* pPtr = rASet._pWhichRanges;
290 	while( *pPtr )
291 	{
292 		nCnt += ( *(pPtr+1) - *pPtr ) + 1;
293 		pPtr += 2;
294 	}
295 
296 	_aItems = new const SfxPoolItem* [ nCnt ];
297 
298 	// Attribute kopieren
299 	SfxItemArray ppDst = _aItems, ppSrc = rASet._aItems;
300 	for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc )
301 		if ( 0 == *ppSrc || 				// aktueller Default?
302 			 IsInvalidItem(*ppSrc) ||		// Dont Care?
303 			 IsStaticDefaultItem(*ppSrc) )	// nicht zu poolende Defaults
304 			// einfach Pointer kopieren
305 			*ppDst = *ppSrc;
306 		else if ( _pPool->IsItemFlag( **ppSrc, SFX_ITEM_POOLABLE ) )
307 		{
308 			// einfach Pointer kopieren und Ref-Count erh"ohen
309 			*ppDst = *ppSrc;
310 			( (SfxPoolItem*) (*ppDst) )->AddRef();
311 		}
312 		else if ( !(*ppSrc)->Which() )
313 			*ppDst = (*ppSrc)->Clone();
314 		else
315 			// !IsPoolable() => via Pool zuweisen
316 			*ppDst = &_pPool->Put( **ppSrc );
317 
318 	// dann noch die Which Ranges kopieren
319 	DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
320 	std::ptrdiff_t cnt = pPtr - rASet._pWhichRanges+1;
321 	_pWhichRanges = new sal_uInt16[ cnt ];
322 	memcpy( _pWhichRanges, rASet._pWhichRanges, sizeof( sal_uInt16 ) * cnt);
323 }
324 
325 // -----------------------------------------------------------------------
326 
327 SfxItemSet::~SfxItemSet()
328 {
329 	DBG_DTOR(SfxItemSet, DbgCheckItemSet);
330 #ifdef DBG_UTIL
331 	DBG( DBG_ASSERT( 0 == *_pChildCount(this), "SfxItemSet: deleting parent-itemset" ) )
332 #endif
333 
334 	sal_uInt16 nCount = TotalCount();
335 	if( Count() )
336 	{
337 		SfxItemArray ppFnd = _aItems;
338 		for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd )
339 			if( *ppFnd && !IsInvalidItem(*ppFnd) )
340 			{
341 				if( !(*ppFnd)->Which() )
342 					delete (SfxPoolItem*) *ppFnd;
343 				else {
344 					// noch mehrer Referenzen vorhanden, also nur den
345 					// ReferenzCounter manipulieren
346 					if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) )
347 						(*ppFnd)->ReleaseRef();
348 					else
349 						if ( !IsDefaultItem(*ppFnd) )
350 							// aus dem Pool loeschen
351 							_pPool->Remove( **ppFnd );
352 				}
353 			}
354 	}
355 
356 	// FIXME: could be delete[] (SfxPoolItem **)_aItems;
357 	delete[] _aItems;
358 	if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
359 		delete[] _pWhichRanges;
360 	_pWhichRanges = 0; // for invariant-testing
361 
362 	DBG( --*_pChildCount(_pParent) );
363 	DBG( delete _pChildCount(this); _pChildCountDtor );
364 }
365 
366 // -----------------------------------------------------------------------
367 
368 sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
369 
370 // einzelnes Item oder alle Items (nWhich==0) l"oschen
371 
372 {
373 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
374 	if( !Count() )
375 		return 0;
376 
377 	sal_uInt16 nDel = 0;
378 	SfxItemArray ppFnd = _aItems;
379 
380 	if( nWhich )
381 	{
382 		const sal_uInt16* pPtr = _pWhichRanges;
383 		while( *pPtr )
384 		{
385 			// in diesem Bereich?
386 			if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
387 			{
388 				// "uberhaupt gesetzt?
389 				ppFnd += nWhich - *pPtr;
390 				if( *ppFnd )
391 				{
392 					// wegen der Assertions ins Sub-Calls mu\s das hier sein
393 					--_nCount;
394 					const SfxPoolItem *pItemToClear = *ppFnd;
395 					*ppFnd = 0;
396 
397 					if ( !IsInvalidItem(pItemToClear) )
398 					{
399 						if ( nWhich <= SFX_WHICH_MAX )
400 						{
401 							const SfxPoolItem& rNew = _pParent
402 									? _pParent->Get( nWhich, sal_True )
403 									: _pPool->GetDefaultItem( nWhich );
404 
405 							Changed( *pItemToClear, rNew );
406 						}
407 						if ( pItemToClear->Which() )
408 							_pPool->Remove( *pItemToClear );
409 					}
410 					++nDel;
411 				}
412 
413 				// gefunden => raus
414 				break;
415 			}
416 			ppFnd += *(pPtr+1) - *pPtr + 1;
417 			pPtr += 2;
418 		}
419 	}
420 	else
421 	{
422 		nDel = _nCount;
423 
424 		sal_uInt16* pPtr = _pWhichRanges;
425 		while( *pPtr )
426 		{
427 			for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
428 				if( *ppFnd )
429 				{
430 					// wegen der Assertions ins Sub-Calls mu\s das hier sein
431 					--_nCount;
432 					const SfxPoolItem *pItemToClear = *ppFnd;
433 					*ppFnd = 0;
434 
435 					if ( !IsInvalidItem(pItemToClear) )
436 					{
437 						if ( nWhich <= SFX_WHICH_MAX )
438 						{
439 							const SfxPoolItem& rNew = _pParent
440 									? _pParent->Get( nWhich, sal_True )
441 									: _pPool->GetDefaultItem( nWhich );
442 
443 							Changed( *pItemToClear, rNew );
444 						}
445 
446 						// #i32448#
447 						// Take care of disabled items, too.
448 						if(!pItemToClear->nWhich)
449 						{
450 							// item is disabled, delete it
451 							delete pItemToClear;
452 						}
453 						else
454 						{
455 							// remove item from pool
456 							_pPool->Remove( *pItemToClear );
457 						}
458 					}
459 				}
460 			pPtr += 2;
461 		}
462 	}
463 	InvalidateHashKey();	//i120575
464 	return nDel;
465 }
466 
467 // -----------------------------------------------------------------------
468 
469 void SfxItemSet::ClearInvalidItems( sal_Bool bHardDefault )
470 {
471 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
472 	sal_uInt16* pPtr = _pWhichRanges;
473 	SfxItemArray ppFnd = _aItems;
474 	if ( bHardDefault )
475 		while( *pPtr )
476 		{
477 			for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
478 				if ( IsInvalidItem(*ppFnd) )
479 					 *ppFnd = &_pPool->Put( _pPool->GetDefaultItem(nWhich) );
480 			pPtr += 2;
481 		}
482 	else
483 		while( *pPtr )
484 		{
485 			for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
486 				if( IsInvalidItem(*ppFnd) )
487 				{
488 					*ppFnd = 0;
489 					--_nCount;
490 				}
491 			pPtr += 2;
492 		}
493 	InvalidateHashKey();	//i120575
494 }
495 
496 //------------------------------------------------------------------------
497 
498 
499 void SfxItemSet::InvalidateAllItems()
500 {
501 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
502 	DBG_ASSERT( !_nCount, "Es sind noch Items gesetzt" );
503 
504 	memset( (void*)_aItems, -1, ( _nCount = TotalCount() ) * sizeof( SfxPoolItem*) );
505 	InvalidateHashKey();	//i120575
506 }
507 
508 // -----------------------------------------------------------------------
509 
510 SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich,
511 										sal_Bool bSrchInParent,
512 										const SfxPoolItem **ppItem ) const
513 {
514 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
515 	// suche den Bereich in dem das Which steht:
516 	const SfxItemSet* pAktSet = this;
517 	SfxItemState eRet = SFX_ITEM_UNKNOWN;
518 	do
519 	{
520 		SfxItemArray ppFnd = pAktSet->_aItems;
521 		const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
522 		if (pPtr)
523 		{
524 			while ( *pPtr )
525 			{
526 				if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
527 				{
528 					// in diesem Bereich
529 					ppFnd += nWhich - *pPtr;
530 					if ( !*ppFnd )
531 					{
532 						eRet = SFX_ITEM_DEFAULT;
533 						if( !bSrchInParent )
534 							return eRet;  // nicht vorhanden
535 						break; // JP: in den Parents weitersuchen !!!
536 					}
537 
538 					if ( (SfxPoolItem*) -1 == *ppFnd )
539 						// Unterschiedlich vorhanden
540 						return SFX_ITEM_DONTCARE;
541 
542 					if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) )
543 						return SFX_ITEM_DISABLED;
544 
545 					if (ppItem)
546 					{
547                         #ifdef DBG_UTIL
548 						const SfxPoolItem *pItem = *ppFnd;
549 						DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
550 								0 != &((const SfxSetItem*)pItem)->GetItemSet(),
551 								"SetItem without ItemSet" );
552                         #endif
553 						*ppItem = *ppFnd;
554 					}
555 					return SFX_ITEM_SET;
556 				}
557 				ppFnd += *(pPtr+1) - *pPtr + 1;
558 				pPtr += 2;
559 			}
560 		}
561 	} while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
562 	return eRet;
563 }
564 
565 // -----------------------------------------------------------------------
566 
567 const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
568 {
569 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
570 	DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
571 			0 != &((const SfxSetItem&)rItem).GetItemSet(),
572 			"SetItem without ItemSet" );
573 	if ( !nWhich )
574 		return 0; //! nur wegen Outliner-Bug
575 	SfxItemArray ppFnd = _aItems;
576 	const sal_uInt16* pPtr = _pWhichRanges;
577 	while( *pPtr )
578 	{
579 		if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
580 		{
581 			// in diesem Bereich
582 			ppFnd += nWhich - *pPtr;
583 			if( *ppFnd )		// schon einer vorhanden
584 			{
585 				// selbes Item bereits vorhanden?
586 				if ( *ppFnd == &rItem )
587 					return 0;
588 
589 				// wird dontcare oder disabled mit was echtem ueberschrieben?
590 				if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) )
591 				{
592 					*ppFnd = &_pPool->Put( rItem, nWhich );
593 					InvalidateHashKey();	//i120575
594 					return *ppFnd;
595 				}
596 
597 				// wird disabled?
598 				if( !rItem.Which() )
599 				{
600 					*ppFnd = rItem.Clone(_pPool);
601 					InvalidateHashKey();	//i120575
602 					return 0;
603 				}
604 				else
605 				{
606 					// selber Wert bereits vorhanden?
607 					if ( rItem == **ppFnd )
608 						return 0;
609 
610 					// den neuen eintragen, den alten austragen
611 					const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
612 					const SfxPoolItem* pOld = *ppFnd;
613 					*ppFnd = &rNew;
614 					if(nWhich <= SFX_WHICH_MAX)
615 						Changed( *pOld, rNew );
616 					_pPool->Remove( *pOld );
617 				}
618 			}
619 			else
620 			{
621 				++_nCount;
622 				if( !rItem.Which() )
623 					*ppFnd = rItem.Clone(_pPool);
624 				else {
625 					const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
626 					*ppFnd = &rNew;
627 					if (nWhich <= SFX_WHICH_MAX )
628 					{
629 						const SfxPoolItem& rOld = _pParent
630 							? _pParent->Get( nWhich, sal_True )
631 							: _pPool->GetDefaultItem( nWhich );
632 						Changed( rOld, rNew );
633 					}
634 				}
635 			}
636 			SFX_ASSERT( !_pPool->IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
637 						rItem.ISA(SfxSetItem) || **ppFnd == rItem,
638 						nWhich, "putted Item unequal" );
639 
640 			InvalidateHashKey();	//i120575
641 			return *ppFnd;
642 		}
643 		ppFnd += *(pPtr+1) - *pPtr + 1;
644 		pPtr += 2;
645 	}
646 	InvalidateHashKey();	//i120575
647 	return 0;
648 }
649 
650 // -----------------------------------------------------------------------
651 
652 int SfxItemSet::Put( const SfxItemSet& rSet, sal_Bool bInvalidAsDefault )
653 {
654 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
655 	sal_Bool bRet = sal_False;
656 	if( rSet.Count() )
657 	{
658 		SfxItemArray ppFnd = rSet._aItems;
659 		const sal_uInt16* pPtr = rSet._pWhichRanges;
660 		while ( *pPtr )
661 		{
662 			for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
663 				if( *ppFnd )
664 				{
665 					if ( IsInvalidItem( *ppFnd ) )
666 					{
667 						if ( bInvalidAsDefault )
668 							bRet |= 0 != ClearItem( nWhich );
669 							// gab GPF bei non.WIDs:
670 							// bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
671 						else
672 							InvalidateItem( nWhich );
673 					}
674 					else
675 						bRet |= 0 != Put( **ppFnd, nWhich );
676 				}
677 			pPtr += 2;
678 		}
679 	}
680 	return bRet;
681 }
682 
683 // -----------------------------------------------------------------------
684 
685 void SfxItemSet::PutExtended
686 (
687 	const SfxItemSet&	rSet,			// Quelle der zu puttenden Items
688 	SfxItemState		eDontCareAs,	// was mit DontCare-Items passiert
689 	SfxItemState		eDefaultAs		// was mit Default-Items passiert
690 )
691 
692 /*	[Beschreibung]
693 
694 	Diese Methode "ubernimmt die Items aus 'rSet' in '*this'. Die
695 	Which-Bereiche in '*this', die in 'rSet' nicht vorkommen bleiben unver-
696 	"andert. Der Which-Bereich von '*this' bleibt auch unver"andert.
697 
698 	In 'rSet' gesetzte Items werden auch in '*this*' gesetzt. Default-
699 	(0 Pointer) und Invalid- (-1 Pointer) Items werden je nach Parameter
700 	('eDontCareAs' und 'eDefaultAs' behandelt:
701 
702 	SFX_ITEM_SET:		hart auf Default des Pools gesetzt
703 	SFX_ITEM_DEFAULT:	gel"oscht (0 Pointer)
704 	SFX_ITEM_DONTCARE:	invalidiert (-1 Pointer)
705 
706 	Alle anderen Werte f"ur 'eDontCareAs' und 'eDefaultAs' sind ung"ultig.
707 */
708 
709 {
710 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
711 
712 	// don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
713 	SfxItemArray ppFnd = rSet._aItems;
714 	const sal_uInt16* pPtr = rSet._pWhichRanges;
715 	while ( *pPtr )
716 	{
717 		for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
718 			if( *ppFnd )
719 			{
720 				if ( IsInvalidItem( *ppFnd ) )
721 				{
722 					// Item ist DontCare:
723 					switch ( eDontCareAs )
724 					{
725 						case SFX_ITEM_SET:
726 							Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
727 							break;
728 
729 						case SFX_ITEM_DEFAULT:
730 							ClearItem( nWhich );
731 							break;
732 
733 						case SFX_ITEM_DONTCARE:
734 							InvalidateItem( nWhich );
735 							break;
736 
737 						default:
738 							DBG_ERROR( "invalid Argument for eDontCareAs" );
739 					}
740 				}
741 				else
742 					// Item ist gesetzt:
743 					Put( **ppFnd, nWhich );
744 			}
745 			else
746 			{
747 				// Item ist Default:
748 				switch ( eDefaultAs )
749 				{
750 					case SFX_ITEM_SET:
751 						Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
752 						break;
753 
754 					case SFX_ITEM_DEFAULT:
755 						ClearItem( nWhich );
756 						break;
757 
758 					case SFX_ITEM_DONTCARE:
759 						InvalidateItem( nWhich );
760 						break;
761 
762 					default:
763 						DBG_ERROR( "invalid Argument for eDefaultAs" );
764 				}
765 			}
766 		pPtr += 2;
767 	}
768 }
769 
770 // -----------------------------------------------------------------------
771 
772 void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
773 /**	<H3>Description</H3>
774 
775 	Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
776 	items which are new ranges too.
777 */
778 
779 {
780 	// special case: exactly one sal_uInt16 which is already included?
781 	if ( nFrom == nTo && SFX_ITEM_AVAILABLE <= GetItemState(nFrom, sal_False) )
782 		return;
783 
784 	// merge new range
785 	SfxUShortRanges aRanges( _pWhichRanges );
786 	aRanges += SfxUShortRanges( nFrom, nTo );
787 	SetRanges( aRanges );
788 }
789 
790 // -----------------------------------------------------------------------
791 
792 void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges )
793 
794 /**	<H3>Description</H3>
795 
796 	Modifies the ranges of settable items. Keeps state of items which
797 	are new ranges too.
798 */
799 
800 {
801 	// identische Ranges?
802 	if ( _pWhichRanges == pNewRanges )
803 		return;
804 	const sal_uInt16* pOld = _pWhichRanges;
805 	const sal_uInt16* pNew = pNewRanges;
806 	while ( *pOld == *pNew )
807 	{
808 		if ( !*pOld && !*pNew )
809 			return;
810 		++pOld, ++pNew;
811 	}
812 
813 	// create new item-array (by iterating through all new ranges)
814 	sal_uLong		 nSize = Capacity_Impl(pNewRanges);
815 	SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ];
816 	sal_uInt16		 n = 0, nNewCount = 0;
817 	if ( _nCount == 0 )
818 		memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) );
819 	else
820 	{
821 		for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 )
822 		{
823 			// iterate through all ids in the range
824 			for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n )
825 			{
826 				// direct move of pointer (not via pool)
827 				SfxItemState eState = GetItemState( nWID, sal_False, aNewItems+n );
828 				if ( SFX_ITEM_SET == eState )
829 				{
830 					// increment new item count and possibly increment ref count
831 					++nNewCount;
832 					aNewItems[n]->AddRef();
833 				}
834 				else if ( SFX_ITEM_DISABLED == eState )
835 				{
836 					// put "disabled" item
837 					++nNewCount;
838 					aNewItems[n] = new SfxVoidItem(0);
839 				}
840 				else if ( SFX_ITEM_DONTCARE == eState )
841 				{
842 					++nNewCount;
843 					aNewItems[n] = (SfxPoolItem*)-1;
844 				}
845 				else
846 				{
847 					// default
848 					aNewItems[n] = 0;
849 				}
850 			}
851 		}
852 		// free old items
853 		sal_uInt16 nOldTotalCount = TotalCount();
854 		for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem )
855 		{
856 			const SfxPoolItem *pItem = _aItems[nItem];
857 			if ( pItem && !IsInvalidItem(pItem) && pItem->Which() )
858 				_pPool->Remove(*pItem);
859 		}
860 	}
861 
862 	// replace old items-array and ranges
863 	delete[] _aItems;
864 	_aItems = aNewItems;
865 	_nCount = nNewCount;
866 
867 	if( pNewRanges == GetPool()->GetFrozenIdRanges() )
868 	{
869 		delete[] _pWhichRanges;
870 		_pWhichRanges = ( sal_uInt16* ) pNewRanges;
871 	}
872 	else
873 	{
874 		sal_uInt16 nCount = Count_Impl(pNewRanges) + 1;
875 		if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
876 			delete[] _pWhichRanges;
877 		_pWhichRanges = new sal_uInt16[ nCount ];
878 		memcpy( _pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount );
879 	}
880 	InvalidateHashKey();	//i120575
881 }
882 
883 // -----------------------------------------------------------------------
884 
885 int SfxItemSet::Set
886 (
887 	const SfxItemSet&	rSet,	/*	das SfxItemSet, dessen SfxPoolItems
888 									"ubernommen werden sollen */
889 
890 	sal_Bool				bDeep	/*	sal_True (default)
891 									auch die SfxPoolItems aus den ggf. an
892 									rSet vorhandenen Parents werden direkt
893 									in das SfxItemSet "ubernommen
894 
895 									sal_False
896 									die SfxPoolItems aus den Parents von
897 									rSet werden nicht ber"ucksichtigt */
898 )
899 
900 /*	[Beschreibung]
901 
902 	Das SfxItemSet nimmt genau die SfxPoolItems an, die auch in
903 	rSet gesetzt sind und im eigenen <Which-Bereich> liegen. Alle
904 	anderen werden entfernt. Der SfxItemPool wird dabei beibehalten,
905 	so da"s die "ubernommenen SfxPoolItems dabei ggf. vom SfxItemPool
906 	von rSet in den SfxItemPool von *this "ubernommen werden.
907 
908 	SfxPoolItems, f"ur die in rSet IsInvalidItem() == sal_True gilt,
909 	werden als Invalid-Item "ubernommen.
910 
911 
912 	[R"uckgabewert]
913 
914 	int 							sal_True
915 									es wurden SfxPoolItems "ubernommen
916 
917 									sal_False
918 									es wurden keine SfxPoolItems "ubernommen,
919 									da z.B. die Which-Bereiche der SfxItemSets
920 									keine Schnittmenge haben oder in der
921 									Schnittmenge keine SfxPoolItems in rSet
922 									gesetzt sind
923 
924 */
925 
926 {
927 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
928 	int bRet = sal_False;
929 	if ( _nCount )
930 		ClearItem();
931 	if ( bDeep )
932 	{
933 		SfxWhichIter aIter(*this);
934 		sal_uInt16 nWhich = aIter.FirstWhich();
935 		while ( nWhich )
936 		{
937 			const SfxPoolItem* pItem;
938 			if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_True, &pItem ) )
939 				bRet |= 0 != Put( *pItem, pItem->Which() );
940 			nWhich = aIter.NextWhich();
941 		}
942 	}
943 	else
944 		bRet = Put(rSet, sal_False);
945 
946 	return bRet;
947 }
948 
949 //------------------------------------------------------------------------
950 
951 const SfxPoolItem* SfxItemSet::GetItem
952 (
953 	sal_uInt16 				nId,   			// Slot-Id oder Which-Id des Items
954 	sal_Bool 				bSrchInParent,  // sal_True: auch in Parent-ItemSets suchen
955 	TypeId 				aItemType       // != 0 =>  RTTI Pruefung mit Assertion
956 )	const
957 
958 /*	[Beschreibung]
959 
960 	Mit dieser Methode wird der Zugriff auf einzelne Items im
961 	SfxItemSet wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
962 	(per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
963 	wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
964 	eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
965 	angegebenen Klasse ist. Ist kein Item mit der Id 'nWhich' in dem ItemSet,
966 	so wird 0 zurueckgegeben.
967 */
968 
969 {
970 	// ggf. in Which-Id umrechnen
971 	sal_uInt16 nWhich = GetPool()->GetWhich(nId);
972 
973 	// ist das Item gesetzt oder bei bDeep==sal_True verf"ugbar?
974 	const SfxPoolItem *pItem = 0;
975 	SfxItemState eState = GetItemState( nWhich, bSrchInParent, &pItem );
976 	if ( bSrchInParent && SFX_ITEM_AVAILABLE == eState &&
977 		 nWhich <= SFX_WHICH_MAX )
978 		pItem = &_pPool->GetDefaultItem(nWhich);
979 	if ( pItem )
980 	{
981 		// stimmt der Typ "uberein?
982 		if ( !aItemType || pItem->IsA(aItemType) )
983 			return pItem;
984 
985 		// sonst Fehler melden
986 		DBG_ERROR( "invalid argument type" );
987 	}
988 
989 	// kein Item gefunden oder falschen Typ gefunden
990 	return 0;
991 }
992 
993 
994 //------------------------------------------------------------------------
995 
996 
997 const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, sal_Bool bSrchInParent) const
998 {
999 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1000 	// suche den Bereich in dem das Which steht:
1001 	const SfxItemSet* pAktSet = this;
1002 	do
1003 	{
1004 		if( pAktSet->Count() )
1005 		{
1006 			SfxItemArray ppFnd = pAktSet->_aItems;
1007 			const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
1008 			while( *pPtr )
1009 			{
1010 				if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1011 				{
1012 					// in diesem Bereich
1013 					ppFnd += nWhich - *pPtr;
1014 					if( *ppFnd )
1015 					{
1016 						if( (SfxPoolItem*)-1 == *ppFnd ) {
1017 							//?MI: folgender code ist Doppelt (unten)
1018 							SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig");
1019 							//!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
1020 							//!return aDefault;
1021 							return _pPool->GetDefaultItem( nWhich );
1022 						}
1023 #ifdef DBG_UTIL
1024 						const SfxPoolItem *pItem = *ppFnd;
1025 						DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
1026 								0 != &((const SfxSetItem*)pItem)->GetItemSet(),
1027 								"SetItem without ItemSet" );
1028 						if ( pItem->ISA(SfxVoidItem) || !pItem->Which() )
1029 							DBG_WARNING( "SFX_WARNING: Getting disabled Item" );
1030 #endif
1031 						return **ppFnd;
1032 					}
1033 					break; 			// dann beim Parent suchen
1034 				}
1035 				ppFnd += *(pPtr+1) - *pPtr + 1;
1036 				pPtr += 2;
1037 			}
1038 		}
1039 // bis zum Ende vom Such-Bereich: was nun ? zum Parent, oder Default ??
1040 //		if( !*pPtr )			// bis zum Ende vom Such-Bereich ?
1041 //		break;
1042 	} while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
1043 
1044 	// dann das Default vom Pool holen und returnen
1045 	SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig");
1046 	const SfxPoolItem *pItem = &_pPool->GetDefaultItem( nWhich );
1047 	DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
1048 			0 != &((const SfxSetItem*)pItem)->GetItemSet(),
1049 			"SetItem without ItemSet" );
1050 	return *pItem;
1051 }
1052 
1053 	// Notification-Callback
1054 // -----------------------------------------------------------------------
1055 
1056 void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& )
1057 {
1058 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1059 }
1060 
1061 // -----------------------------------------------------------------------
1062 
1063 sal_uInt16 SfxItemSet::TotalCount() const
1064 {
1065 	DBG_CHKTHIS(SfxItemSet, 0); // wird im Ctor benutzt bevor vollst. init.
1066 	sal_uInt16 nRet = 0;
1067 	sal_uInt16* pPtr = _pWhichRanges;
1068 	while( *pPtr )
1069 	{
1070 		nRet += ( *(pPtr+1) - *pPtr ) + 1;
1071 		pPtr += 2;
1072 	}
1073 	return nRet;
1074 }
1075 // -----------------------------------------------------------------------
1076 
1077 // behalte nur die Items, die auch in rSet enthalten sein (Wert egal)
1078 
1079 void SfxItemSet::Intersect( const SfxItemSet& rSet )
1080 {
1081 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1082 	DBG_ASSERT(_pPool, "nicht implementiert ohne Pool");
1083 	if( !Count() )		 // gar keine gesetzt ?
1084 		return;
1085 
1086 	// loesche alle Items, die im rSet nicht mehr vorhanden sind
1087 	if( !rSet.Count() )
1088 	{
1089 		ClearItem();		// alles loeschen
1090 		return;
1091 	}
1092 
1093 	// teste mal, ob sich die Which-Bereiche unterscheiden.
1094 	sal_Bool bEqual = sal_True;
1095 	sal_uInt16* pWh1 = _pWhichRanges;
1096 	sal_uInt16* pWh2 = rSet._pWhichRanges;
1097 	sal_uInt16 nSize = 0;
1098 
1099 	for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1100 	{
1101 		if( *pWh1 != *pWh2 )
1102 		{
1103 			bEqual = sal_False;
1104 			break;
1105 		}
1106 		if( n & 1 )
1107 			nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1108 	}
1109 	bEqual = *pWh1 == *pWh2;		// auch die 0 abpruefen
1110 
1111 	// sind die Bereiche identisch, ist es einfacher zu handhaben !
1112 	if( bEqual )
1113 	{
1114 		SfxItemArray ppFnd1 = _aItems;
1115 		SfxItemArray ppFnd2 = rSet._aItems;
1116 
1117 		for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1118 			if( *ppFnd1 && !*ppFnd2 )
1119 			{
1120 				// aus dem Pool loeschen
1121 				if( !IsInvalidItem( *ppFnd1 ) )
1122 				{
1123 					sal_uInt16 nWhich = (*ppFnd1)->Which();
1124 					if(nWhich <= SFX_WHICH_MAX)
1125 					{
1126 						const SfxPoolItem& rNew = _pParent
1127 							? _pParent->Get( nWhich, sal_True )
1128 							: _pPool->GetDefaultItem( nWhich );
1129 
1130 						Changed( **ppFnd1, rNew );
1131 					}
1132 					_pPool->Remove( **ppFnd1 );
1133 				}
1134 				*ppFnd1 = 0;
1135 				--_nCount;
1136 			}
1137 	}
1138 	else
1139 	{
1140 		SfxItemIter aIter( *this );
1141 		const SfxPoolItem* pItem = aIter.GetCurItem();
1142 		while( sal_True )
1143 		{
1144 			sal_uInt16 nWhich = IsInvalidItem( pItem )
1145 								? GetWhichByPos( aIter.GetCurPos() )
1146 								: pItem->Which();
1147 			if( 0 == rSet.GetItemState( nWhich, sal_False ) )
1148 				ClearItem( nWhich );		// loeschen
1149 			if( aIter.IsAtEnd() )
1150 				break;
1151 			pItem = aIter.NextItem();
1152 		}
1153 	}
1154 	InvalidateHashKey();	//i120575
1155 }
1156 
1157 // -----------------------------------------------------------------------
1158 
1159 void SfxItemSet::Differentiate( const SfxItemSet& rSet )
1160 {
1161 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1162 	if( !Count() || !rSet.Count() )  // gar keine gesetzt ?
1163 		return;
1164 
1165 	// teste mal, ob sich die Which-Bereiche unterscheiden.
1166 	sal_Bool bEqual = sal_True;
1167 	sal_uInt16* pWh1 = _pWhichRanges;
1168 	sal_uInt16* pWh2 = rSet._pWhichRanges;
1169 	sal_uInt16 nSize = 0;
1170 
1171 	for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1172 	{
1173 		if( *pWh1 != *pWh2 )
1174 		{
1175 			bEqual = sal_False;
1176 			break;
1177 		}
1178 		if( n & 1 )
1179 			nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1180 	}
1181 	bEqual = *pWh1 == *pWh2;		// auch die 0 abpruefen
1182 
1183 	// sind die Bereiche identisch, ist es einfacher zu handhaben !
1184 	if( bEqual )
1185 	{
1186 		SfxItemArray ppFnd1 = _aItems;
1187 		SfxItemArray ppFnd2 = rSet._aItems;
1188 
1189 		for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1190 			if( *ppFnd1 && *ppFnd2 )
1191 			{
1192 				// aus dem Pool loeschen
1193 				if( !IsInvalidItem( *ppFnd1 ) )
1194 				{
1195 					sal_uInt16 nWhich = (*ppFnd1)->Which();
1196 					if(nWhich <= SFX_WHICH_MAX)
1197 					{
1198 						const SfxPoolItem& rNew = _pParent
1199 							? _pParent->Get( nWhich, sal_True )
1200 							: _pPool->GetDefaultItem( nWhich );
1201 
1202 						Changed( **ppFnd1, rNew );
1203 					}
1204 					_pPool->Remove( **ppFnd1 );
1205 				}
1206 				*ppFnd1 = 0;
1207 				--_nCount;
1208 			}
1209 	}
1210 	else
1211 	{
1212 		SfxItemIter aIter( *this );
1213 		const SfxPoolItem* pItem = aIter.GetCurItem();
1214 		while( sal_True )
1215 		{
1216 			sal_uInt16 nWhich = IsInvalidItem( pItem )
1217 								? GetWhichByPos( aIter.GetCurPos() )
1218 								: pItem->Which();
1219 			if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False ) )
1220 				ClearItem( nWhich );		// loeschen
1221 			if( aIter.IsAtEnd() )
1222 				break;
1223 			pItem = aIter.NextItem();
1224 		}
1225 
1226 	}
1227 	InvalidateHashKey();	//i120575
1228 }
1229 
1230 // -----------------------------------------------------------------------
1231 /* Entscheidungstabelle fuer MergeValue[s]
1232 
1233 Grundsaetze:
1234 	1. Ist der Which-Wert im 1.Set "unknown", dann folgt niemals eine Aktion.
1235 	2. Ist der Which-Wert im 2.Set "unknown", dann gilt er als "default".
1236 	3. Es gelten fuer Vergleiche die Werte der "default"-Items.
1237 
1238 1.-Item     2.-Item     Values  bIgnoreDefs     Remove      Assign      Add
1239 
1240 set         set         ==      sal_False           -           -           -
1241 default     set         ==      sal_False           -           -           -
1242 dontcare    set         ==      sal_False           -           -           -
1243 unknown     set         ==      sal_False           -           -           -
1244 set         default     ==      sal_False           -           -           -
1245 default     default     ==      sal_False           -           -           -
1246 dontcare    default     ==      sal_False           -           -           -
1247 unknown     default     ==      sal_False           -           -           -
1248 set         dontcare    ==      sal_False           1.-Item     -1          -
1249 default 	dontcare	==		sal_False			-			-1			-
1250 dontcare    dontcare    ==      sal_False           -           -           -
1251 unknown     dontcare    ==      sal_False           -           -           -
1252 set         unknown     ==      sal_False           1.-Item     -1          -
1253 default     unknown     ==      sal_False           -           -           -
1254 dontcare    unknown     ==      sal_False           -           -           -
1255 unknown     unknown     ==      sal_False           -           -           -
1256 
1257 set         set         !=      sal_False           1.-Item     -1          -
1258 default     set         !=      sal_False           -           -1          -
1259 dontcare    set         !=      sal_False           -           -           -
1260 unknown     set         !=      sal_False           -           -           -
1261 set         default     !=      sal_False           1.-Item     -1          -
1262 default     default     !=      sal_False           -           -           -
1263 dontcare    default     !=      sal_False           -           -           -
1264 unknown     default     !=      sal_False           -           -           -
1265 set         dontcare    !=      sal_False           1.-Item     -1          -
1266 default     dontcare    !=      sal_False           -           -1          -
1267 dontcare    dontcare    !=      sal_False           -           -           -
1268 unknown     dontcare    !=      sal_False           -           -           -
1269 set         unknown     !=      sal_False           1.-Item     -1          -
1270 default     unknown     !=      sal_False           -           -           -
1271 dontcare    unknown     !=      sal_False           -           -           -
1272 unknown     unknown     !=      sal_False           -           -           -
1273 
1274 set         set         ==      sal_True            -           -           -
1275 default 	set 		==		sal_True			-			2.-Item 	2.-Item
1276 dontcare    set         ==      sal_True            -           -           -
1277 unknown     set         ==      sal_True            -           -           -
1278 set         default     ==      sal_True            -           -           -
1279 default     default     ==      sal_True            -           -           -
1280 dontcare    default     ==      sal_True            -           -           -
1281 unknown     default     ==      sal_True            -           -           -
1282 set         dontcare    ==      sal_True            -           -           -
1283 default 	dontcare	==		sal_True			-			-1			-
1284 dontcare    dontcare    ==      sal_True            -           -           -
1285 unknown     dontcare    ==      sal_True            -           -           -
1286 set         unknown     ==      sal_True            -           -           -
1287 default     unknown     ==      sal_True            -           -           -
1288 dontcare    unknown     ==      sal_True            -           -           -
1289 unknown     unknown     ==      sal_True            -           -           -
1290 
1291 set         set         !=      sal_True            1.-Item     -1          -
1292 default     set         !=      sal_True            -           2.-Item     2.-Item
1293 dontcare	set 		!=		sal_True			-			-			-
1294 unknown     set         !=      sal_True            -           -           -
1295 set         default     !=      sal_True            -           -           -
1296 default     default     !=      sal_True            -           -           -
1297 dontcare    default     !=      sal_True            -           -           -
1298 unknown     default     !=      sal_True            -           -           -
1299 set         dontcare    !=      sal_True            1.-Item     -1          -
1300 default     dontcare    !=      sal_True            -           -1          -
1301 dontcare    dontcare    !=      sal_True            -           -           -
1302 unknown     dontcare    !=      sal_True            -           -           -
1303 set         unknown     !=      sal_True            -           -           -
1304 default     unknown     !=      sal_True            -           -           -
1305 dontcare    unknown     !=      sal_True            -           -           -
1306 unknown     unknown     !=      sal_True            -           -           -
1307 */
1308 
1309 
1310 static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount,
1311 							const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2,
1312 							sal_Bool bIgnoreDefaults )
1313 {
1314 	DBG_ASSERT( ppFnd1 != 0, "Merging to 0-Item" );
1315 
1316 	// 1. Item ist default?
1317 	if ( !*ppFnd1 )
1318 	{
1319 		if ( IsInvalidItem(pFnd2) )
1320 			// Entscheidungstabelle: default, dontcare, egal, egal
1321 			*ppFnd1 = (SfxPoolItem*) -1;
1322 
1323 		else if ( pFnd2 && !bIgnoreDefaults &&
1324 				  _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
1325 			// Entscheidungstabelle: default, set, !=, sal_False
1326 			*ppFnd1 = (SfxPoolItem*) -1;
1327 
1328 		else if ( pFnd2 && bIgnoreDefaults )
1329 			// Entscheidungstabelle: default, set, egal, sal_True
1330 			*ppFnd1 = &_pPool->Put( *pFnd2 );
1331 
1332 		if ( *ppFnd1 )
1333 			++rCount;
1334 	}
1335 
1336 	// 1. Item ist gesetzt?
1337 	else if ( !IsInvalidItem(*ppFnd1) )
1338 	{
1339 		if ( !pFnd2 )
1340 		{
1341 			// 2. Item ist default
1342 			if ( !bIgnoreDefaults &&
1343 				 **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) )
1344 			{
1345 				// Entscheidungstabelle: set, default, !=, sal_False
1346 				_pPool->Remove( **ppFnd1 );
1347 				*ppFnd1 = (SfxPoolItem*) -1;
1348 			}
1349 		}
1350 		else if ( IsInvalidItem(pFnd2) )
1351 		{
1352 			// 2. Item ist dontcare
1353 			if ( !bIgnoreDefaults ||
1354 				 **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) )
1355 			{
1356 				// Entscheidungstabelle: set, dontcare, egal, sal_False
1357 				// oder:				 set, dontcare, !=, sal_True
1358 				_pPool->Remove( **ppFnd1 );
1359 				*ppFnd1 = (SfxPoolItem*) -1;
1360 			}
1361 		}
1362 		else
1363 		{
1364 			// 2. Item ist gesetzt
1365 			if ( **ppFnd1 != *pFnd2 )
1366 			{
1367 				// Entscheidungstabelle: set, set, !=, egal
1368 				_pPool->Remove( **ppFnd1 );
1369 				*ppFnd1 = (SfxPoolItem*) -1;
1370 			}
1371 		}
1372 	}
1373 }
1374 
1375 // -----------------------------------------------------------------------
1376 
1377 void SfxItemSet::MergeValues( const SfxItemSet& rSet, sal_Bool bIgnoreDefaults )
1378 {
1379 	// Achtung!!! Bei Aenderungen/Bugfixes immer obenstehende Tabelle pflegen!
1380 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1381 	DBG_ASSERT( GetPool() == rSet.GetPool(), "MergeValues mit verschiedenen Pools" );
1382 
1383 	// teste mal, ob sich die Which-Bereiche unterscheiden.
1384 	sal_Bool bEqual = sal_True;
1385 	sal_uInt16* pWh1 = _pWhichRanges;
1386 	sal_uInt16* pWh2 = rSet._pWhichRanges;
1387 	sal_uInt16 nSize = 0;
1388 
1389 	for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1390 	{
1391 		if( *pWh1 != *pWh2 )
1392 		{
1393 			bEqual = sal_False;
1394 			break;
1395 		}
1396 		if( n & 1 )
1397 			nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1398 	}
1399 	bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen
1400 
1401 	// sind die Bereiche identisch, ist es effizieter zu handhaben !
1402 	if( bEqual )
1403 	{
1404 		SfxItemArray ppFnd1 = _aItems;
1405 		SfxItemArray ppFnd2 = rSet._aItems;
1406 
1407 		for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1408 			MergeItem_Impl( _pPool, _nCount, ppFnd1, *ppFnd2, bIgnoreDefaults );
1409 	}
1410 	else
1411 	{
1412 		SfxWhichIter aIter( rSet );
1413 		register sal_uInt16 nWhich;
1414 		while( 0 != ( nWhich = aIter.NextWhich() ) )
1415 		{
1416 			const SfxPoolItem* pItem = 0;
1417 			rSet.GetItemState( nWhich, sal_True, &pItem );
1418 			if( !pItem )
1419 			{
1420 				// nicht gesetzt, also default
1421 				if ( !bIgnoreDefaults )
1422 					MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ), bIgnoreDefaults );
1423 			}
1424 			else if( IsInvalidItem( pItem ) )
1425 				// dont care
1426 				InvalidateItem( nWhich );
1427 			else
1428 				MergeValue( *pItem, bIgnoreDefaults );
1429 		}
1430 	}
1431 	InvalidateHashKey();	//i120575
1432 }
1433 
1434 // -----------------------------------------------------------------------
1435 
1436 void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, sal_Bool bIgnoreDefaults )
1437 {
1438 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1439 	SfxItemArray ppFnd = _aItems;
1440 	const sal_uInt16* pPtr = _pWhichRanges;
1441 	const sal_uInt16 nWhich = rAttr.Which();
1442 	while( *pPtr )
1443 	{
1444 		// in diesem Bereich?
1445 		if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1446 		{
1447 			ppFnd += nWhich - *pPtr;
1448 			MergeItem_Impl( _pPool, _nCount, ppFnd, &rAttr, bIgnoreDefaults );
1449 			break;
1450 		}
1451 		ppFnd += *(pPtr+1) - *pPtr + 1;
1452 		pPtr += 2;
1453 	}
1454 	InvalidateHashKey();	//i120575
1455 }
1456 
1457 // -----------------------------------------------------------------------
1458 
1459 void SfxItemSet::InvalidateItem( sal_uInt16 nWhich )
1460 {
1461 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1462 	SfxItemArray ppFnd = _aItems;
1463 	const sal_uInt16* pPtr = _pWhichRanges;
1464 	while( *pPtr )
1465 	{
1466 		if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1467 		{
1468 			// in diesem Bereich
1469 			ppFnd += nWhich - *pPtr;
1470 
1471 			if( *ppFnd )   	// bei mir gesetzt
1472 			{
1473 				if( (SfxPoolItem*)-1 != *ppFnd )		// noch nicht dontcare !
1474 				{
1475 					_pPool->Remove( **ppFnd );
1476 					*ppFnd = (SfxPoolItem*)-1;
1477 				}
1478 			}
1479 			else
1480 			{
1481 				*ppFnd = (SfxPoolItem*)-1;
1482 				++_nCount;
1483 			}
1484 			break;
1485 		}
1486 		ppFnd += *(pPtr+1) - *pPtr + 1;
1487 		pPtr += 2;
1488 	}
1489 	InvalidateHashKey();	//i120575
1490 }
1491 
1492 // -----------------------------------------------------------------------
1493 
1494 sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const
1495 {
1496 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1497 	sal_uInt16 n = 0;
1498 	sal_uInt16* pPtr  = _pWhichRanges;
1499 	while( *pPtr )
1500 	{
1501 		n = ( *(pPtr+1) - *pPtr ) + 1;
1502 		if( nPos < n )
1503 			return *(pPtr)+nPos;
1504 		nPos = nPos - n;
1505 		pPtr += 2;
1506 	}
1507 	DBG_ASSERT( sal_False, "Hier sind wir falsch" );
1508 	return 0;
1509 }
1510 
1511 // -----------------------------------------------------------------------
1512 
1513 SvStream &SfxItemSet::Store
1514 (
1515 	SvStream&	rStream,		// Zielstream f"ur normale Items
1516 	FASTBOOL	bDirect 		// sal_True: Items direkt speicher, sal_False: Surrogate
1517 )	const
1518 
1519 /*	[Beschreibung]
1520 
1521 	Speichert die <SfxItemSet>-Instanz in den angegebenen Stream. Dabei
1522 	werden die Surrorage der gesetzten <SfxPoolItem>s bzw. ('bDirect==sal_True')
1523 	die gesetzten Items selbst wie folgt im Stream abgelegt:
1524 
1525 			sal_uInt16				(Count) Anzahl der gesetzten Items
1526 	Count*	_pPool->StoreItem()  siehe <SfxItemPool::StoreItem()const>
1527 
1528 
1529 	[Querverweise]
1530 
1531 	<SfxItemSet::Load(SvStream&,sal_Bool,const SfxItemPool*)>
1532 */
1533 
1534 {
1535 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1536 	DBG_ASSERT( _pPool, "Kein Pool" );
1537 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
1538 
1539 	// Position des Counts merken, um ggf. zu korrigieren
1540 	sal_uLong nCountPos = rStream.Tell();
1541 	rStream << _nCount;
1542 
1543 	// wenn nichts zu speichern ist, auch keinen ItemIter aufsetzen!
1544 	if ( _nCount )
1545 	{
1546 		// mitz"ahlen wieviel Items tats"achlich gespeichert werden
1547 		sal_uInt16 nWrittenCount = 0;  // Anzahl in 'rStream' gestreamter Items
1548 
1549 		// "uber alle gesetzten Items iterieren
1550 		SfxItemIter aIter(*this);
1551 		for ( const SfxPoolItem *pItem = aIter.FirstItem();
1552 			  pItem;
1553 			  pItem = aIter.NextItem() )
1554 		{
1555 			// Item (ggf. als Surrogat) via Pool speichern lassen
1556 			DBG_ASSERT( !IsInvalidItem(pItem), "can't store invalid items" );
1557 			if ( !IsInvalidItem(pItem) &&
1558 				 _pPool->StoreItem( rStream, *pItem, bDirect ) )
1559 				// Item wurde in 'rStream' gestreamt
1560 				++nWrittenCount;
1561 		};
1562 
1563 		// weniger geschrieben als enthalten (z.B. altes Format)
1564 		if ( nWrittenCount != _nCount )
1565 		{
1566 			// tats"achlichen Count im Stream ablegen
1567 			sal_uLong nPos = rStream.Tell();
1568 			rStream.Seek( nCountPos );
1569 			rStream << nWrittenCount;
1570 			rStream.Seek( nPos );
1571 		}
1572 	}
1573 
1574 	return rStream;
1575 }
1576 
1577 // -----------------------------------------------------------------------
1578 
1579 SvStream &SfxItemSet::Load
1580 (
1581 	SvStream&			rStream,	//	Stream, aus dem geladen werden soll
1582 
1583 	FASTBOOL			bDirect,	/*	sal_True
1584 										Items werden direkt aus dem Stream
1585 										gelesen, nicht "uber Surrogate
1586 
1587 										sal_False (default)
1588 										Items werden "uber Surrogate gelesen */
1589 
1590 	const SfxItemPool*	pRefPool 	/*	Pool, der die Surrogate aufl"osen kann
1591 										(z.B. zum Einf"ugen von Dokumenten) */
1592 )
1593 
1594 /*	[Beschreibung]
1595 
1596 	Diese Methode l"adt ein <SfxItemSet> aus einem Stream. Falls der
1597 	<SfxItemPool> ohne Ref-Counts geladen wurde, werden die geladenen
1598 	Item-Referenzen in den Items hochgez"ahlt, ansonsten wird vorausgesetzt,
1599 	da\s sie schon beim Laden des SfxItemPools ber"ucksichtigt waren.
1600 
1601 	[Querverweise]
1602 
1603 	<SfxItemSet::Store(Stream&,sal_Bool)const>
1604 */
1605 
1606 {
1607 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1608 	DBG_ASSERT( _pPool, "Kein Pool");
1609 	DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "Kein Master-Pool");
1610 
1611 	// kein Ref-Pool => Surrogate mit Pool des ItemSets aufl"osen
1612 	if ( !pRefPool )
1613 		pRefPool = _pPool;
1614 
1615 	// Anzahl der zu ladenden Items laden und dann ebensoviele Items
1616 	sal_uInt16 nCount = 0;
1617 	rStream >> nCount;
1618 	for ( sal_uInt16 i = 0; i < nCount; ++i )
1619 	{
1620 		// Surrogat/Item laden und (Surrogat) aufl"osen lassen
1621 		const SfxPoolItem *pItem =
1622 				_pPool->LoadItem( rStream, bDirect, pRefPool );
1623 
1624 		// konnte ein Item geladen oder via Surrogat aufgel"ost werden?
1625 		if ( pItem )
1626 		{
1627 			// Position f"ur Item-Pointer im Set suchen
1628 			sal_uInt16 nWhich = pItem->Which();
1629 			SfxItemArray ppFnd = _aItems;
1630 			const sal_uInt16* pPtr = _pWhichRanges;
1631 			while ( *pPtr )
1632 			{
1633 				// in diesem Bereich?
1634 				if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1635 				{
1636 					// Item-Pointer im Set merken
1637 					ppFnd += nWhich - *pPtr;
1638 					SFX_ASSERT( !*ppFnd, nWhich, "Item doppelt eingetragen");
1639 					*ppFnd = pItem;
1640 					++_nCount;
1641 					break;
1642 				}
1643 
1644 				// im Range-Array und Item-Array zum n"achsten Which-Range
1645 				ppFnd += *(pPtr+1) - *pPtr + 1;
1646 				pPtr += 2;
1647 			}
1648 		}
1649 	}
1650 
1651 
1652 	InvalidateHashKey();	//i120575
1653 	return rStream;
1654 }
1655 
1656 // -----------------------------------------------------------------------
1657 
1658 int	SfxItemSet::operator==(const SfxItemSet &rCmp) const
1659 {
1660 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1661 	DBG_CHKOBJ(&rCmp, SfxItemSet, DbgCheckItemSet);
1662 
1663 	// besonders schnell zu ermittelnde Werte muessen gleich sein
1664 	if ( _pParent != rCmp._pParent ||
1665 		 _pPool != rCmp._pPool ||
1666 		 Count() != rCmp.Count() )
1667 		return sal_False;
1668 
1669 	// Ranges durchzaehlen lassen dauert laenger, muss aber auch gleich sein
1670 	sal_uInt16 nCount1 = TotalCount();
1671 	sal_uInt16 nCount2 = rCmp.TotalCount();
1672 	if ( nCount1 != nCount2 )
1673 		return sal_False;
1674 
1675 	// sind die Ranges selbst ungleich?
1676 	for ( sal_uInt16 nRange = 0; _pWhichRanges[nRange]; nRange += 2 )
1677 		if ( _pWhichRanges[nRange] != rCmp._pWhichRanges[nRange] ||
1678 			 _pWhichRanges[nRange+1] != rCmp._pWhichRanges[nRange+1] )
1679 		{
1680 			// dann m"ussen wir die langsame Methode verwenden
1681 			SfxWhichIter aIter( *this );
1682 			for ( sal_uInt16 nWh = aIter.FirstWhich();
1683 				  nWh;
1684 				  nWh = aIter.NextWhich() )
1685 			{
1686 				// wenn die Pointer von poolable Items ungleich sind,
1687 				// muessen die Items gleich sein
1688 				const SfxPoolItem *pItem1 = 0, *pItem2 = 0;
1689 				if ( GetItemState( nWh, sal_False, &pItem1 ) !=
1690 						rCmp.GetItemState( nWh, sal_False, &pItem2 ) ||
1691 					 ( pItem1 != pItem2 &&
1692 						( !pItem1 || IsInvalidItem(pItem1) ||
1693 						  ( _pPool->IsItemFlag(*pItem1, SFX_ITEM_POOLABLE) &&
1694 							*pItem1 != *pItem2 ) ) ) )
1695 					return sal_False;
1696 			}
1697 
1698 			return sal_True;
1699 		}
1700 
1701 	// Pointer alle gleich?
1702 	if ( 0 == memcmp( _aItems, rCmp._aItems, nCount1 * sizeof(_aItems[0]) ) )
1703 		return sal_True;
1704 
1705 	// dann werden wir wohl alle einzeln vergleichen muessen
1706 	const SfxPoolItem **ppItem1 = (const SfxPoolItem**) _aItems;
1707 	const SfxPoolItem **ppItem2 = (const SfxPoolItem**) rCmp._aItems;
1708 	for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos )
1709 	{
1710 		// wenn die Pointer von poolable Items ungleich sind,
1711 		// muessen die Items gleich sein
1712 		if ( *ppItem1 != *ppItem2 &&
1713 			 ( ( !*ppItem1 || !*ppItem2 ) ||
1714 			   ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) ||
1715 			   ( _pPool->IsItemFlag(**ppItem1, SFX_ITEM_POOLABLE) ) ||
1716 				 **ppItem1 != **ppItem2 ) )
1717 			return sal_False;
1718 
1719 		++ppItem1;
1720 		++ppItem2;
1721 	}
1722 
1723 	return sal_True;
1724 }
1725 
1726 // -----------------------------------------------------------------------
1727 
1728 SfxItemSet *SfxItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const
1729 {
1730 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1731 	if ( pToPool && pToPool != _pPool )
1732 	{
1733 		SfxItemSet *pNewSet = new SfxItemSet( *pToPool, _pWhichRanges );
1734 		if ( bItems )
1735 		{
1736 			SfxWhichIter aIter(*pNewSet);
1737 			sal_uInt16 nWhich = aIter.FirstWhich();
1738 			while ( nWhich )
1739 			{
1740 				const SfxPoolItem* pItem;
1741 				if ( SFX_ITEM_SET == GetItemState( nWhich, sal_False, &pItem ) )
1742 					pNewSet->Put( *pItem, pItem->Which() );
1743 				nWhich = aIter.NextWhich();
1744 			}
1745 		}
1746 		return pNewSet;
1747 	}
1748 	else
1749 		return bItems
1750 				? new SfxItemSet(*this)
1751 				: new SfxItemSet(*_pPool, _pWhichRanges);
1752 }
1753 
1754 // -----------------------------------------------------------------------
1755 
1756 int	SfxItemSet::PutDirect(const SfxPoolItem &rItem)
1757 {
1758 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1759 	SfxItemArray ppFnd = _aItems;
1760 	const sal_uInt16* pPtr = _pWhichRanges;
1761 	const sal_uInt16 nWhich = rItem.Which();
1762 #ifdef DBG_UTIL
1763 	IsPoolDefaultItem(&rItem) || _pPool->GetSurrogate(&rItem);
1764 		// nur Assertion in den callees provozieren
1765 #endif
1766 	while( *pPtr )
1767 	{
1768 		if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1769 		{
1770 			// in diesem Bereich
1771 			ppFnd += nWhich - *pPtr;
1772 			const SfxPoolItem* pOld = *ppFnd;
1773 			if( pOld )		// schon einer vorhanden
1774 			{
1775 				if( rItem == **ppFnd )
1776 					return sal_False;		// schon vorhanden !
1777 				_pPool->Remove( *pOld );
1778 			}
1779 			else
1780 				++_nCount;
1781 
1782 			// den neuen eintragen
1783 			if( IsPoolDefaultItem(&rItem) )
1784 				*ppFnd = &_pPool->Put( rItem );
1785 			else
1786 			{
1787 				*ppFnd = &rItem;
1788 				if( !IsStaticDefaultItem( &rItem ) )
1789 					rItem.AddRef();
1790 			}
1791 
1792 			InvalidateHashKey();	//i120575
1793 			return sal_True;
1794 		}
1795 		ppFnd += *(pPtr+1) - *pPtr + 1;
1796 		pPtr += 2;
1797 	}
1798 	return sal_False;
1799 }
1800 
1801 // -----------------------------------------------------------------------
1802 
1803 SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool )
1804 :	SfxItemSet(rPool, (const sal_uInt16*) 0),
1805 	aDefault(0),
1806 	nFree(nInitCount)
1807 {
1808 	// initial keine Items
1809 	_aItems = 0;
1810 
1811 	// nInitCount Paare an USHORTs fuer Ranges allozieren
1812 	_pWhichRanges = new sal_uInt16[ nInitCount + 1 ];
1813 	memset( _pWhichRanges, 0, ( nInitCount + 1 ) * sizeof(sal_uInt16) );
1814 }
1815 
1816 
1817 // -----------------------------------------------------------------------
1818 
1819 
1820 SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy)
1821 :   SfxItemSet(rCopy),
1822 	aDefault(0),
1823 	nFree(0)
1824 {
1825 }
1826 
1827 // -----------------------------------------------------------------------
1828 
1829 
1830 
1831 SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy)
1832 :   SfxItemSet(rCopy),
1833 	aDefault(0),
1834 	nFree(0)
1835 /*	[Anmerkung]
1836 
1837 	Der mu\s sein, da sonst vom Compiler einer generiert wird, er nimmt
1838 	nicht den Ctor mit der 'const SfxItemSet&'!
1839 */
1840 {
1841 }
1842 
1843 // -----------------------------------------------------------------------
1844 
1845 static sal_uInt16 *AddRanges_Impl(
1846     sal_uInt16 *pUS, std::ptrdiff_t nOldSize, sal_uInt16 nIncr)
1847 
1848 /* 	Diese interne Funktion erzeugt ein neues Which-Range-Array, welches von
1849     dem 'nOldSize'-USHORTs langen 'pUS' kopiert wird und hinten an Platz
1850     f"ur 'nIncr' neue USHORTs hat. Das terminierende sal_uInt16 mit der '0'
1851     wird weder in 'nOldSize' noch in 'nIncr' mitgez"ahlt, sondern implizit
1852 	hinzugerechnet.
1853 
1854 	Das neue Which-Range-Array wird als Returnwert zur"uckgegeben, das alte
1855     'pUS' freigegeben.
1856 */
1857 
1858 {
1859 	// neues Which-Range-Array anlegen
1860 	sal_uInt16 *pNew = new sal_uInt16[ nOldSize + nIncr + 1 ];
1861 
1862 	// die alten Ranges "ubernehmen
1863 	memcpy( pNew, pUS, nOldSize * sizeof(sal_uInt16) );
1864 
1865 	// die neuen auf 0 initialisieren
1866 	memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(sal_uInt16) );
1867 
1868 	// das alte Array freigeben
1869 	delete[] pUS;
1870 
1871 	return pNew;
1872 }
1873 
1874 // -----------------------------------------------------------------------
1875 
1876 static SfxItemArray AddItem_Impl(SfxItemArray pItems, sal_uInt16 nOldSize, sal_uInt16 nPos)
1877 
1878 /*  Diese interne Funktion erzeugt ein neues ItemArray, welches von 'pItems'
1879     kopiert wird, an der Position 'nPos' jedoch Platz f"ur einen neuen
1880 	ItemPointer hat.
1881 
1882     Das neue ItemArray wird als Returnwert zur"uckgegeben, das alte 'pItems'
1883 	wird freigegeben.
1884 */
1885 
1886 {
1887 	// neues ItemArray anlegen
1888 	SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1];
1889 
1890 	// war schon vorher eins da?
1891 	if ( pItems )
1892 	{
1893 		// alte Items vor nPos kopieren
1894 		if ( nPos )
1895 			memcpy( (void*) pNew, pItems, nPos * sizeof(SfxPoolItem **) );
1896 
1897 		// alte Items hinter nPos kopieren
1898 		if ( nPos < nOldSize )
1899 			memcpy( (void*) (pNew + nPos + 1), pItems + nPos,
1900 					(nOldSize-nPos) * sizeof(SfxPoolItem **) );
1901 	}
1902 
1903 	// neues Item initialisieren
1904 	*(pNew + nPos) = 0;
1905 
1906 	// altes ItemArray freigeben
1907 	delete[] pItems;
1908 
1909 	return pNew;
1910 }
1911 
1912 // -----------------------------------------------------------------------
1913 
1914 const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
1915 
1916 // Putten mit automatischer Erweiterung der Whichs-Ids um die ID
1917 // des Items.
1918 
1919 {
1920     sal_uInt16 nPos = 0; // Position f"ur 'rItem' in '_aItems'
1921 	const sal_uInt16 nItemCount = TotalCount();
1922 
1923 	// erstmal sehen, ob es schon einen passenden Bereich gibt
1924 	sal_uInt16 *pPtr = _pWhichRanges;
1925 	while ( *pPtr )
1926 	{
1927 		// Which-Id liegt in diesem Bereich?
1928 		if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1929 		{
1930 			// Einfuegen
1931 			nPos += nWhich - *pPtr;
1932 			break;
1933 		}
1934 
1935 		// Position des Items in _aItems mitf"uhren
1936 		nPos += *(pPtr+1) - *pPtr + 1;
1937 
1938 		// zum n"achsten Bereich
1939 		pPtr += 2;
1940 	}
1941 
1942 	// Which-Id noch nicht vorhanden?
1943 	if ( !*pPtr )
1944 	{
1945 		// suchen, ob man sie irgendwo dranpacken kann
1946 		pPtr = _pWhichRanges;
1947 		nPos = 0;
1948 		while ( *pPtr )
1949 		{
1950 			// Which-Id liegt exakt vor diesem Bereich?
1951 			if ( (nWhich+1) == *pPtr )
1952 			{
1953 				// Bereich waechst nach unten
1954 				(*pPtr)--;
1955 
1956 				// vor erstem Item dieses Bereichs Platz schaffen
1957 				_aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1958 				break;
1959 			}
1960 
1961 			// Which-Id liegt exakt hinter diesem Bereich?
1962 			else if ( (nWhich-1) == *(pPtr+1) )
1963 			{
1964 				// Bereich waechst nach oben
1965 				(*(pPtr+1))++;
1966 
1967 				// hinter letztem Item dieses Bereichs Platz schaffen
1968 				nPos += nWhich - *pPtr;
1969 				_aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1970 				break;
1971 			}
1972 
1973 			// Position des Items in _aItems mitf"uhren
1974 			nPos += *(pPtr+1) - *pPtr + 1;
1975 
1976 			// zum n"achsten Bereich
1977 			pPtr += 2;
1978 		}
1979 	}
1980 
1981 	// keinen erweiterbaren Bereich gefunden?
1982 	if ( !*pPtr )
1983 	{
1984 		// kein Platz mehr in _pWhichRanges => erweitern
1985 		std::ptrdiff_t nSize = pPtr - _pWhichRanges;
1986 		if( !nFree )
1987 		{
1988 			_pWhichRanges = AddRanges_Impl(_pWhichRanges, nSize, nInitCount);
1989 			nFree += nInitCount;
1990 		}
1991 
1992 		// neuen Which-Range anh"angen
1993 		pPtr = _pWhichRanges + nSize;
1994 		*pPtr++ = nWhich;
1995 		*pPtr = nWhich;
1996 		nFree -= 2;
1997 
1998 		// Itemarray vergroessern
1999 		nPos = nItemCount;
2000 		_aItems = AddItem_Impl(_aItems, nItemCount, nPos);
2001 	}
2002 
2003 	// neues Item in Pool aufnehmen
2004 	const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
2005 
2006 	// altes Item merken
2007     sal_Bool bIncrementCount = sal_False;
2008 	const SfxPoolItem* pOld = *( _aItems + nPos );
2009     if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld )   // state "dontcare"
2010         pOld = NULL;
2011     if ( !pOld )
2012     {
2013         bIncrementCount = sal_True;
2014         pOld = _pParent ?
2015                 &_pParent->Get( nWhich, sal_True )
2016                 : nWhich <= SFX_WHICH_MAX ? &_pPool->GetDefaultItem( nWhich ) : 0;
2017     }
2018 
2019 	// neue Item in ItemSet aufnehmen
2020 	*(_aItems + nPos) = &rNew;
2021 
2022 	// Changed Notification versenden
2023 	if ( pOld )
2024 	{
2025 		Changed( *pOld, rNew );
2026 		if ( !IsDefaultItem(pOld) )
2027 			_pPool->Remove( *pOld );
2028 	}
2029 
2030     if ( bIncrementCount )
2031         ++_nCount;
2032 
2033 	InvalidateHashKey();	//i120575
2034 
2035 	return &rNew;
2036 }
2037 
2038 // -----------------------------------------------------------------------
2039 
2040 
2041 /*	Diese Methode wird forwarded, damit sie nicht durch die anderen
2042 	Put-Methoden dieser SubClass gehided wird.
2043 */
2044 
2045 int SfxAllItemSet::Put( const SfxItemSet& rSet, sal_Bool bInvalidAsDefault )
2046 {
2047 	//? pruefen, ob Which-Ranges erweitert werden
2048 	return SfxItemSet::Put( rSet, bInvalidAsDefault );
2049 }
2050 
2051 // -----------------------------------------------------------------------
2052 // Item disablen, wenn durch ein VoidItem mit dem Which-Wert 0 ausgedrueckt
2053 
2054 void SfxItemSet::DisableItem(sal_uInt16 nWhich)
2055 {
2056 	DBG_CHKTHIS(SfxItemSet, 0);
2057 	Put( SfxVoidItem(0), nWhich );
2058 }
2059 
2060 // -----------------------------------------------------------------------
2061 
2062 #if 0
2063 sal_Bool SfxAllItemSet::Remove(sal_uInt16 nWhich)
2064 {
2065 	DBG_CHKTHIS(SfxAllItemSet, 0);
2066 	sal_uInt16 *pPtr = _pWhichRanges;
2067 	sal_uInt16 nPos = 0;
2068 	while( *pPtr )
2069 	{
2070 		if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
2071 		{
2072 			sal_uInt16 *pTmp = pPtr;
2073 			sal_uInt16 nLeft = 0;
2074 			sal_uInt16 nRest = 0;
2075 			while(*++pTmp){
2076 				if( nLeft & 1 )
2077 					nRest = *pTmp - *(pTmp-1) + 1;
2078 				++nLeft;
2079 			}
2080 
2081 			// in diesem Bereich
2082 			nPos += nWhich - *pPtr;
2083 			nRest -= nWhich - *pPtr;
2084 			// 3,3
2085 			if(*pPtr == nWhich && *(pPtr+1) == nWhich) {
2086 				memmove(pPtr, pPtr + 2, nLeft * sizeof(sal_uInt16));
2087 				nFree += 2;
2088 			}
2089 				// Anfang
2090 			else if(*pPtr == nWhich)
2091 				(*pPtr)++;
2092 				// Ende
2093 			else if(*(pPtr+1) == nWhich)
2094 				(*(pPtr+1))--;
2095 			else {
2096 				if(nPos + nRest + 2 > nFree) {
2097 					sal_uInt16 nOf = pPtr - _pWhichRanges;
2098 					_pWhichRanges = IncrSize(_pWhichRanges, nPos + nRest, nInitCount);
2099 					nFree += nInitCount;
2100 					pPtr = _pWhichRanges + nOf;
2101 				}
2102 				memmove(pPtr +2, pPtr, (nLeft+2) * sizeof(sal_uInt16));
2103 				*++pPtr  = nWhich-1;
2104 				*++pPtr = nWhich+1;
2105 				nFree -= 2;
2106 			}
2107 			SfxPoolItem* pItem = *( _aItems + nPos );
2108 			if( pItem )
2109 			{
2110 				if(_pPool)
2111 					_pPool->Remove(*pItem );
2112 				else
2113 					delete pItem;
2114 				--_nCount;
2115 			}
2116 			memmove(_aItems + nPos +1, _aItems + nPos,
2117 					sizeof(SfxPoolItem *) * (nRest - 1));
2118 			break; 			// dann beim Parent suchen
2119 		}
2120 		nPos += *(pPtr+1) - *pPtr + 1;
2121 		pPtr += 2;
2122 	}
2123 	return *pPtr? sal_True: sal_False;
2124 }
2125 #endif
2126 
2127 // -----------------------------------------------------------------------
2128 
2129 SfxItemSet *SfxAllItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const
2130 {
2131 	DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
2132 	if ( pToPool && pToPool != _pPool )
2133 	{
2134 		SfxAllItemSet *pNewSet = new SfxAllItemSet( *pToPool );
2135 		if ( bItems )
2136 			pNewSet->Set( *this );
2137 		return pNewSet;
2138 	}
2139 	else
2140 		return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool);
2141 }
2142 
2143 //for i120575
2144 //align with the rtl_hash, return signed int result and input len limited to 2G.
2145 //can be replaced with other hash function in future for better performance, e.g. fnv hash.
2146 inline sal_Int32 myhash(void * buf, sal_Int32 buf_len)
2147 {
2148 	return rtl_str_hashCode_WithLength( reinterpret_cast<const sal_Char *>(buf), buf_len);
2149 }
2150 
2151 inline void SfxItemSet::UpdateHashKey()
2152 {
2153 	_aHashKey= myhash(_aItems,TotalCount()* sizeof(_aItems[0]));
2154 
2155 	//always treat '0' as invalidate hash key, not using addtional bool data field for saving space.
2156 	if (!IsValidateHashKey() )
2157 	{
2158 		_aHashKey = 1;
2159 	}
2160 }
2161 
2162 sal_Bool SfxItemSet::QuickCompare( SfxItemSet & rCmp)
2163 {
2164 	if ( _pParent != rCmp._pParent ||
2165 		 _pPool != rCmp._pPool ||
2166 		 Count() != rCmp.Count() )
2167 		return sal_False;
2168 
2169 	if ((0==Count())&&(0==rCmp.Count()))
2170 		return sal_True;
2171 
2172 	if (!IsValidateHashKey())
2173 	{
2174 		UpdateHashKey();
2175 	}
2176 	if (!rCmp.IsValidateHashKey())
2177 	{
2178 		rCmp.UpdateHashKey();
2179 	}
2180 
2181 	//improved performance here, in most cases, the hashkey is not equal.
2182 	if (GetHashKey() != rCmp.GetHashKey())
2183 		return sal_False;
2184 
2185 	if ( 0 == memcmp( _aItems, rCmp._aItems,  TotalCount() * sizeof(_aItems[0]) ) )
2186 		return sal_True;
2187 	else
2188 		return sal_False;
2189 }
2190 //end: i120575
2191