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