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