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