xref: /aoo41x/main/svl/source/items/itempool.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svl.hxx"
30 
31 #include <string.h>
32 #include <stdio.h>
33 #ifndef GCC
34 #endif
35 
36 #include <svl/itempool.hxx>
37 #include "whassert.hxx"
38 #include <svl/brdcst.hxx>
39 #include <svl/smplhint.hxx>
40 #include "poolio.hxx"
41 
42 //========================================================================
43 
44 
45 void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser)
46 {
47 	maSfxItemPoolUsers.push_back(&rNewUser);
48 }
49 
50 void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser)
51 {
52 	const SfxItemPoolUserVector::iterator aFindResult = ::std::find(maSfxItemPoolUsers.begin(), maSfxItemPoolUsers.end(), &rOldUser);
53 	if(aFindResult != maSfxItemPoolUsers.end())
54 	{
55 		maSfxItemPoolUsers.erase(aFindResult);
56 	}
57 }
58 
59 const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const
60 {
61 	DBG_CHKTHIS(SfxItemPool, 0);
62 	const SfxPoolItem* pRet;
63 	if( IsInRange( nWhich ) )
64 		pRet = *(ppPoolDefaults + GetIndex_Impl( nWhich ));
65 	else if( pSecondary )
66 		pRet = pSecondary->GetPoolDefaultItem( nWhich );
67 	else
68 	{
69 		SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get pool default" );
70 		pRet = 0;
71 	}
72 	return pRet;
73 }
74 
75 // -----------------------------------------------------------------------
76 
77 inline FASTBOOL SfxItemPool::IsItemFlag_Impl( sal_uInt16 nPos, sal_uInt16 nFlag ) const
78 {
79 	sal_uInt16 nItemFlag = pItemInfos[nPos]._nFlags;
80 	return nFlag == (nItemFlag & nFlag);
81 }
82 
83 // -----------------------------------------------------------------------
84 
85 FASTBOOL SfxItemPool::IsItemFlag( sal_uInt16 nWhich, sal_uInt16 nFlag ) const
86 {
87 	for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary )
88 	{
89 		if ( pPool->IsInRange(nWhich) )
90 			return pPool->IsItemFlag_Impl( pPool->GetIndex_Impl(nWhich), nFlag);
91 	}
92 	DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" );
93 	return sal_False;
94 }
95 
96 // -----------------------------------------------------------------------
97 
98 SfxBroadcaster& SfxItemPool::BC()
99 {
100 	return pImp->aBC;
101 }
102 
103 // -----------------------------------------------------------------------
104 
105 
106 SfxItemPool::SfxItemPool
107 (
108 	UniString const &	rName,          /* Name des Pools zur Idetifikation
109 										   im File-Format */
110 	sal_uInt16              nStartWhich,    /* erste Which-Id des Pools */
111 	sal_uInt16              nEndWhich,      /* letzte Which-Id des Pools */
112 #ifdef TF_POOLABLE
113 	const SfxItemInfo*  pInfos,         /* SID-Map und Item-Flags */
114 #endif
115 	SfxPoolItem**       pDefaults,      /* Pointer auf statische Defaults,
116 										   wird direkt vom Pool referenziert,
117 										   jedoch kein Eigent"umer"ubergang */
118 #ifndef TF_POOLABLE
119 	sal_uInt16*             pSlotIdArray,   /* Zuordnung von Slot-Ids zu Which-Ids */
120 #endif
121 	FASTBOOL            bLoadRefCounts  /* Ref-Counts mitladen oder auf 1 setzen */
122 )
123 
124 /*  [Beschreibung]
125 
126 	Der im Normalfall verwendete Konstruktor der Klasse SfxItemPool. Es
127 	wird eine SfxItemPool-Instanz initialisiert, die Items im b"undigen
128 	Which-Bereich von 'nStartWhich' bis 'nEndWhich' verwalten kann.
129 
130 	F"ur jede dieser Which-Ids mu\s ein statischer Default im Array 'pDefaults'
131 	vorhanden sein, die dort beginnend mit einem <SfxPoolItem> mit der
132 	Which-Id 'nStartWhich' nach Which-Ids sortiert aufeinanderfolgend
133 	eingetragen sein m"ussen.
134 
135 	'pItemInfos' ist ein identisch angeordnetes Array von USHORTs, die
136 	Slot-Ids darstellen und Flags. Die Slot-Ids k"onnen 0 sein, wenn die
137 	betreffenden Items ausschlie\slich in der Core verwendet werden.
138 	"Uber die Flags kann z.B. bestimmt werden, ob Value-Sharing
139 	(SFX_ITEM_POOLABLE) stattfinden soll.
140 
141 	[Anmerkung]
142 
143 	Wenn der Pool <SfxSetItem>s enthalten soll, k"onnen im Konstruktor noch
144 	keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich
145 	mit <SfxItemPool::SetDefaults(SfxItemPool**)> geschehen.
146 
147 
148 	[Querverweise]
149 
150 	<SfxItemPool::SetDefaults(SfxItemPool**)>
151 	<SfxItemPool::ReleaseDefaults(SfxPoolItem**,sal_uInt16,sal_Bool)>
152 	<SfxItemPool::ReldaseDefaults(sal_Bool)>
153 */
154 
155 :   aName(rName),
156 	nStart(nStartWhich),
157 	nEnd(nEndWhich),
158 #ifdef TF_POOLABLE
159 	pItemInfos(pInfos),
160 #else
161 	pSlotIds(pSlotIdArray),
162 #endif
163 	pImp( new SfxItemPool_Impl( nStart, nEnd ) ),
164 	ppStaticDefaults(0),
165 	ppPoolDefaults(new SfxPoolItem* [ nEndWhich - nStartWhich + 1]),
166 	pSecondary(0),
167 	pMaster(this),
168 	_pPoolRanges( 0 ),
169 	bPersistentRefCounts(bLoadRefCounts),
170     maSfxItemPoolUsers()
171 {
172 	DBG_CTOR(SfxItemPool, 0);
173 	DBG_ASSERT(nStart, "Start-Which-Id must be greater 0" );
174 
175 	pImp->eDefMetric = SFX_MAPUNIT_TWIP;
176 	pImp->nVersion = 0;
177 	pImp->bStreaming = sal_False;
178 	pImp->nLoadingVersion = 0;
179 	pImp->nInitRefCount = 1;
180 	pImp->nVerStart = nStart;
181 	pImp->nVerEnd = nEnd;
182 	pImp->bInSetItem = sal_False;
183 	pImp->nStoringStart = nStartWhich;
184 	pImp->nStoringEnd = nEndWhich;
185 
186 	memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1));
187 
188 	if ( pDefaults )
189 		SetDefaults(pDefaults);
190 }
191 
192 // -----------------------------------------------------------------------
193 
194 
195 SfxItemPool::SfxItemPool
196 (
197 	const SfxItemPool&  rPool,                  //  von dieser Instanz kopieren
198 	sal_Bool                bCloneStaticDefaults    /*  sal_True
199 													statische Defaults kopieren
200 
201 													sal_False
202 													statische Defaults
203 													"ubernehehmen */
204 )
205 
206 /*  [Beschreibung]
207 
208 	Copy-Konstruktor der Klasse SfxItemPool.
209 
210 
211 	[Querverweise]
212 
213 	<SfxItemPool::Clone()const>
214 */
215 
216 :   aName(rPool.aName),
217 	nStart(rPool.nStart),
218 	nEnd(rPool.nEnd),
219 #ifdef TF_POOLABLE
220 	pItemInfos(rPool.pItemInfos),
221 #else
222 	pSlotIds(rPool.pSlotIds),
223 #endif
224 	pImp( new SfxItemPool_Impl( nStart, nEnd ) ),
225 	ppStaticDefaults(0),
226 	ppPoolDefaults(new SfxPoolItem* [ nEnd - nStart + 1]),
227 	pSecondary(0),
228 	pMaster(this),
229 	_pPoolRanges( 0 ),
230 	bPersistentRefCounts(rPool.bPersistentRefCounts ),
231     maSfxItemPoolUsers()
232 {
233 	DBG_CTOR(SfxItemPool, 0);
234 	pImp->eDefMetric = rPool.pImp->eDefMetric;
235 	pImp->nVersion = rPool.pImp->nVersion;
236 	pImp->bStreaming = sal_False;
237 	pImp->nLoadingVersion = 0;
238 	pImp->nInitRefCount = 1;
239 	pImp->nVerStart = rPool.pImp->nVerStart;
240 	pImp->nVerEnd = rPool.pImp->nVerEnd;
241 	pImp->bInSetItem = sal_False;
242 	pImp->nStoringStart = nStart;
243 	pImp->nStoringEnd = nEnd;
244 
245 	memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1));
246 
247 	// Static Defaults "ubernehmen
248 	if ( bCloneStaticDefaults )
249 	{
250 		SfxPoolItem **ppDefaults = new SfxPoolItem*[nEnd-nStart+1];
251 		for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n )
252 		{
253 			(*( ppDefaults + n )) = (*( rPool.ppStaticDefaults + n ))->Clone(this);
254 			(*( ppDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
255 		}
256 
257 		SetDefaults( ppDefaults );
258 	}
259 	else
260 		SetDefaults( rPool.ppStaticDefaults );
261 
262 	// Pool Defaults kopieren
263 	for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n )
264 		if ( (*( rPool.ppPoolDefaults + n )) )
265 		{
266 			(*( ppPoolDefaults + n )) = (*( rPool.ppPoolDefaults + n ))->Clone(this);
267 			(*( ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT );
268 		}
269 
270 	// Copy Version-Map
271 	for ( size_t nVer = 0; nVer < rPool.pImp->aVersions.size(); ++nVer )
272 	{
273 		const SfxPoolVersion_ImplPtr pOld = rPool.pImp->aVersions[nVer];
274 		SfxPoolVersion_ImplPtr pNew = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl( *pOld ) );
275 		pImp->aVersions.push_back( pNew );
276 	}
277 
278 	// Verkettung wiederherstellen
279 	if ( rPool.pSecondary )
280 		SetSecondaryPool( rPool.pSecondary->Clone() );
281 }
282 
283 // -----------------------------------------------------------------------
284 
285 void SfxItemPool::SetDefaults( SfxPoolItem **pDefaults )
286 {
287 	DBG_CHKTHIS(SfxItemPool, 0);
288 	DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." );
289 	DBG_ASSERT( !ppStaticDefaults, "habe schon defaults" );
290 
291 	ppStaticDefaults = pDefaults;
292 	//! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT )
293 	//! geht wohl nicht im Zshg mit SetItems, die hinten stehen
294 	{
295 		DBG_ASSERT( (*ppStaticDefaults)->GetRefCount() == 0 ||
296 					IsDefaultItem( (*ppStaticDefaults) ),
297 					"das sind keine statics" );
298 		for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n )
299 		{
300 			SFX_ASSERT( (*( ppStaticDefaults + n ))->Which() == n + nStart,
301 						n + nStart, "static defaults not sorted" );
302 			(*( ppStaticDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
303 			DBG_ASSERT( !(pImp->ppPoolItems[n]), "defaults with setitems with items?!" );
304 		}
305 	}
306 }
307 
308 // -----------------------------------------------------------------------
309 
310 void SfxItemPool::ReleaseDefaults
311 (
312 	sal_Bool    bDelete     /*  sal_True
313 							l"oscht sowohl das Array als auch die einzelnen
314 							statischen Defaults
315 
316 							sal_False
317 							l"oscht weder das Array noch die einzelnen
318 							statischen Defaults */
319 )
320 
321 /*  [Beschreibung]
322 
323 	Gibt die statischen Defaults der betreffenden SfxItemPool-Instanz frei
324 	und l"oscht ggf. die statischen Defaults.
325 
326 	Nach Aufruf dieser Methode darf die SfxItemPool-Instanz nicht mehr
327 	verwendet werden, einzig ist der Aufruf des Destruktors zu"lassig.
328 */
329 
330 {
331 	DBG_ASSERT( ppStaticDefaults, "keine Arme keine Kekse" );
332 	ReleaseDefaults( ppStaticDefaults, nEnd - nStart + 1, bDelete );
333 
334 	// KSO (22.10.98): ppStaticDefaults zeigt auf geloeschten Speicher,
335 	// wenn bDelete == sal_True.
336 	if ( bDelete )
337 		ppStaticDefaults = 0;
338 }
339 
340 // -----------------------------------------------------------------------
341 
342 void SfxItemPool::ReleaseDefaults
343 (
344 	SfxPoolItem**   pDefaults,  /*  freizugebende statische Defaults */
345 
346 	sal_uInt16          nCount,     /*  Anzahl der statischen Defaults */
347 
348 	sal_Bool            bDelete     /*  sal_True
349 									l"oscht sowohl das Array als auch die
350 									einzelnen statischen Defaults
351 
352 									sal_False
353 									l"oscht weder das Array noch die
354 									einzelnen statischen Defaults */
355 )
356 
357 /*  [Beschreibung]
358 
359 	Gibt die angegebenen statischen Defaults frei und l"oscht ggf.
360 	die statischen Defaults.
361 
362 	Diese Methode darf erst nach Zerst"orung aller SfxItemPool-Instanzen,
363 	welche die angegebenen statischen Defaults 'pDefault' verwenden,
364 	aufgerufen werden.
365 */
366 
367 {
368 	DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." );
369 
370 	for ( sal_uInt16 n = 0; n < nCount; ++n )
371 	{
372 		SFX_ASSERT( IsStaticDefaultItem( *(pDefaults+n) ),
373 					n, "das ist kein static-default" );
374 		(*( pDefaults + n ))->SetRefCount( 0 );
375 		if ( bDelete )
376 			{ delete *( pDefaults + n ); *(pDefaults + n) = 0; }
377 	}
378 
379 	if ( bDelete )
380 		{ delete[] pDefaults; pDefaults = 0; }
381 }
382 
383 // -----------------------------------------------------------------------
384 
385 SfxItemPool::~SfxItemPool()
386 {
387 	DBG_DTOR(SfxItemPool, 0);
388 	DBG_ASSERT( pMaster == this, "destroying active Secondary-Pool" );
389 
390     if ( pImp->ppPoolItems && ppPoolDefaults )
391 		Delete();
392 	delete[] _pPoolRanges;
393 	delete pImp;
394 }
395 
396 void SfxItemPool::Free(SfxItemPool* pPool)
397 {
398     if(pPool)
399     {
400 	    // tell all the registered SfxItemPoolUsers that the pool is in destruction
401 	    SfxItemPoolUserVector aListCopy(pPool->maSfxItemPoolUsers.begin(), pPool->maSfxItemPoolUsers.end());
402 	    for(SfxItemPoolUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++)
403 	    {
404 		    SfxItemPoolUser* pSfxItemPoolUser = *aIterator;
405 		    DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)");
406 		    pSfxItemPoolUser->ObjectInDestruction(*pPool);
407 	    }
408 
409 	    // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser()
410 	    // when they get called from ObjectInDestruction().
411 	    pPool->maSfxItemPoolUsers.clear();
412 
413         // delete pool
414         delete pPool;
415     }
416 }
417 
418 // -----------------------------------------------------------------------
419 
420 
421 void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool )
422 {
423 	// ggf. an abgeh"angten Pools den Master zur"ucksetzen
424 	if ( pSecondary )
425 	{
426 #ifdef DBG_UTIL
427 		HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
428 		if ( ppStaticDefaults )
429 		{
430 			// Delete() ist noch nicht gelaufen?
431 			if ( pImp->ppPoolItems && pSecondary->pImp->ppPoolItems )
432 			{
433 				// hat der master SetItems?
434 				sal_Bool bHasSetItems = sal_False;
435 				for ( sal_uInt16 i = 0; !bHasSetItems && i < nEnd-nStart; ++i )
436 					bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem);
437 
438 				// abgehaengte Pools muessen leer sein
439 				sal_Bool bOK = bHasSetItems;
440 				for ( sal_uInt16 n = 0;
441 					  bOK && n <= pSecondary->nEnd - pSecondary->nStart;
442 					  ++n )
443 				{
444 					SfxPoolItemArray_Impl** ppItemArr =
445 												pSecondary->pImp->ppPoolItems + n;
446 					if ( *ppItemArr )
447 					{
448 						SfxPoolItemArrayBase_Impl::iterator ppHtArr =	(*ppItemArr)->begin();
449 						for( size_t i = (*ppItemArr)->size(); i; ++ppHtArr, --i )
450 							if ( !(*ppHtArr) )
451 							{
452 								DBG_ERROR( "old secondary pool must be empty" );
453 								bOK = sal_False;
454 								break;
455 							}
456 					}
457 				}
458 			}
459 		}
460 #endif
461 
462 		pSecondary->pMaster = pSecondary;
463 		for ( SfxItemPool *p = pSecondary->pSecondary; p; p = p->pSecondary )
464 			p->pMaster = pSecondary;
465 	}
466 
467 	// ggf. den Master der neuen Secondary-Pools setzen
468 	DBG_ASSERT( !pPool || pPool->pMaster == pPool, "Secondary tanzt auf zwei Hochzeiten " );
469 	SfxItemPool *pNewMaster = pMaster ? pMaster : this;
470 	for ( SfxItemPool *p = pPool; p; p = p->pSecondary )
471 		p->pMaster = pNewMaster;
472 
473 	// neuen Secondary-Pool merken
474 	pSecondary = pPool;
475 }
476 
477 // -----------------------------------------------------------------------
478 
479 SfxMapUnit SfxItemPool::GetMetric( sal_uInt16 ) const
480 {
481 	DBG_CHKTHIS(SfxItemPool, 0);
482 
483 	return pImp->eDefMetric;
484 }
485 
486 // -----------------------------------------------------------------------
487 
488 void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric )
489 {
490 	DBG_CHKTHIS(SfxItemPool, 0);
491 
492 	pImp->eDefMetric = eNewMetric;
493 }
494 
495 // -----------------------------------------------------------------------
496 
497 SfxItemPresentation SfxItemPool::GetPresentation
498 (
499 	const SfxPoolItem&  rItem,      /*  IN: <SfxPoolItem>, dessen textuelle
500 											Wert-Darstellung geliefert werden
501 											soll */
502 	SfxItemPresentation ePresent,   /*  IN: gew"unschte Art der Darstellung;
503 											siehe <SfxItemPresentation> */
504 	SfxMapUnit          eMetric,    /*  IN: gew"unschte Ma\seinheit der Darstellung */
505 	XubString&           rText,      /*  OUT: textuelle Darstellung von 'rItem' */
506     const IntlWrapper * pIntlWrapper
507 )   const
508 
509 /*  [Beschreibung]
510 
511 	"Uber diese virtuelle Methode k"onnen textuelle Darstellungen der
512 	von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems
513 	angefordert werden.
514 
515 	In Ableitungen sollte diese Methode "uberladen werden und auf
516 	SfxPoolItems reagiert werden, die bei <SfxPoolItem::GetPresentation()const>
517 	keine vollst"andige Information liefern k"onnen.
518 
519 	Die Basisklasse liefert die unver"anderte Presentation von 'rItem'.
520 */
521 
522 {
523 	DBG_CHKTHIS(SfxItemPool, 0);
524 	return rItem.GetPresentation(
525         ePresent, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper );
526 }
527 
528 
529 // -----------------------------------------------------------------------
530 
531 SfxItemPool* SfxItemPool::Clone() const
532 {
533 	DBG_CHKTHIS(SfxItemPool, 0);
534 
535 	SfxItemPool *pPool = new SfxItemPool( *this );
536 	return pPool;
537 }
538 
539 // ----------------------------------------------------------------------
540 
541 void SfxItemPool::Delete()
542 {
543 	DBG_CHKTHIS(SfxItemPool, 0);
544 
545 	// schon deleted?
546 	if ( !pImp->ppPoolItems || !ppPoolDefaults )
547 		return;
548 
549 	// z.B. laufenden Requests bescheidsagen
550 	pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) );
551 
552 	//MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems.
553 	//Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt.
554 
555 	SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
556 	SfxPoolItem** ppDefaultItem = ppPoolDefaults;
557 	SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults;
558 	sal_uInt16 nArrCnt;
559 
560 	//Erst die SetItems abraeumen
561 	HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
562 	if ( ppStaticDefaults )
563 	{
564 		for ( nArrCnt = GetSize_Impl();
565 				nArrCnt;
566 				--nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
567 		{
568 			// KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer
569 			// von SfxItemPool abgeleiteten Klasse bereits geloescht worden
570 			// sein! -> CHAOS Itempool
571 			if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) )
572 			{
573 				if ( *ppItemArr )
574 				{
575 					SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
576 					for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
577 						if (*ppHtArr)
578 						{
579 #ifdef DBG_UTIL
580 							ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
581 #endif
582 							delete *ppHtArr;
583 						}
584 					DELETEZ( *ppItemArr );
585 				}
586 				if ( *ppDefaultItem )
587 				{
588 #ifdef DBG_UTIL
589 					SetRefCount( **ppDefaultItem, 0 );
590 #endif
591 					DELETEZ( *ppDefaultItem );
592 				}
593 			}
594 		}
595 	}
596 
597 	ppItemArr = pImp->ppPoolItems;
598 	ppDefaultItem = ppPoolDefaults;
599 
600 	//Jetzt die 'einfachen' Items
601 	for ( nArrCnt = GetSize_Impl();
602 			nArrCnt;
603 			--nArrCnt, ++ppItemArr, ++ppDefaultItem )
604 	{
605 		if ( *ppItemArr )
606 		{
607 			SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
608 			for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
609 				if (*ppHtArr)
610 				{
611 #ifdef DBG_UTIL
612 					ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
613 #endif
614 					delete *ppHtArr;
615 				}
616 			delete *ppItemArr;
617 		}
618 		if ( *ppDefaultItem )
619 		{
620 #ifdef DBG_UTIL
621 			SetRefCount( **ppDefaultItem, 0 );
622 #endif
623 			delete *ppDefaultItem;
624 		}
625 	}
626 
627 	pImp->DeleteItems();
628 	delete[] ppPoolDefaults; ppPoolDefaults = 0;
629 }
630 
631 // ----------------------------------------------------------------------
632 
633 void SfxItemPool::Cleanup()
634 {
635 	DBG_CHKTHIS(SfxItemPool, 0);
636 
637 	//MA 16. Apr. 97: siehe ::Delete()
638 
639 	SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
640 	SfxPoolItem** ppDefaultItem = ppPoolDefaults;
641 	SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults;
642 	sal_uInt16 nArrCnt;
643 
644 	HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
645 	if ( ppStaticDefaults ) //HACK fuer Image, dort gibt es keine Statics!!
646 	{
647 		for ( nArrCnt = GetSize_Impl();
648 				nArrCnt;
649 				--nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
650 		{
651 			//Fuer jedes Item gibt es entweder ein Default oder ein static Default!
652 			if ( *ppItemArr &&
653 				 ((*ppDefaultItem && (*ppDefaultItem)->ISA(SfxSetItem)) ||
654 				  (*ppStaticDefaultItem)->ISA(SfxSetItem)) )
655 			{
656 				SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
657 				for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
658 					if ( *ppHtArr && !(*ppHtArr)->GetRefCount() )
659 					{
660 						 DELETEZ(*ppHtArr);
661 					}
662 			}
663 		}
664 	}
665 
666 	ppItemArr = pImp->ppPoolItems;
667 
668 	for ( nArrCnt = GetSize_Impl();
669 		  nArrCnt;
670 		  --nArrCnt, ++ppItemArr )
671 	{
672 		if ( *ppItemArr )
673 		{
674 			SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
675 			for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
676 				if ( *ppHtArr && !(*ppHtArr)->GetRefCount() )
677 					DELETEZ( *ppHtArr );
678 		}
679 	}
680 }
681 
682 // ----------------------------------------------------------------------
683 
684 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem)
685 {
686 	DBG_CHKTHIS(SfxItemPool, 0);
687 	if ( IsInRange(rItem.Which()) )
688 	{
689 		SfxPoolItem **ppOldDefault =
690 			ppPoolDefaults + GetIndex_Impl(rItem.Which());
691 		SfxPoolItem *pNewDefault = rItem.Clone(this);
692 		pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT);
693 		if ( *ppOldDefault )
694 		{
695 			(*ppOldDefault)->SetRefCount(0);
696 			DELETEZ( *ppOldDefault );
697 		}
698 		*ppOldDefault = pNewDefault;
699 	}
700 	else if ( pSecondary )
701 		pSecondary->SetPoolDefaultItem(rItem);
702 	else
703 	{
704 		SFX_ASSERT( 0, rItem.Which(), "unknown Which-Id - cannot set pool default" );
705 	}
706 }
707 
708 /*
709  * Resets the default of the given <Which-Id> back to the static default.
710  * If a pool default exists it is removed.
711  */
712 void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId )
713 {
714 	DBG_CHKTHIS(SfxItemPool, 0);
715 	if ( IsInRange(nWhichId) )
716 	{
717 		SfxPoolItem **ppOldDefault =
718 			ppPoolDefaults + GetIndex_Impl( nWhichId );
719 		if ( *ppOldDefault )
720 		{
721 			(*ppOldDefault)->SetRefCount(0);
722 			DELETEZ( *ppOldDefault );
723 		}
724 	}
725 	else if ( pSecondary )
726 		pSecondary->ResetPoolDefaultItem(nWhichId);
727 	else
728 	{
729 		SFX_ASSERT( 0, nWhichId, "unknown Which-Id - cannot set pool default" );
730 	}
731 }
732 
733 // -----------------------------------------------------------------------
734 
735 const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
736 {
737 	DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
738 				0 != &((const SfxSetItem&)rItem).GetItemSet(),
739 				"SetItem without ItemSet" );
740 
741 	DBG_CHKTHIS(SfxItemPool, 0);
742 	if ( 0 == nWhich )
743 		nWhich = rItem.Which();
744 
745 	// richtigen Secondary-Pool finden
746 	sal_Bool bSID = nWhich > SFX_WHICH_MAX;
747 	if ( !bSID && !IsInRange(nWhich) )
748 	{
749 		if ( pSecondary )
750 			return pSecondary->Put( rItem, nWhich );
751 		DBG_ERROR( "unknown Which-Id - cannot put item" );
752 	}
753 
754 	// SID oder nicht poolable (neue Definition)?
755 	sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
756 	if ( USHRT_MAX == nIndex ||
757 		 IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) )
758 	{
759 		SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich ||
760 					!IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE,
761 					nWhich, "ein nicht Pool-Item ist Default?!" );
762 		SfxPoolItem *pPoolItem = rItem.Clone(pMaster);
763 		pPoolItem->SetWhich(nWhich);
764 		AddRef( *pPoolItem );
765 		return *pPoolItem;
766 	}
767 
768 	SFX_ASSERT( rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich,
769 				"SFxItemPool: wrong item type in Put" );
770 
771 	SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems + nIndex;
772 	if( !*ppItemArr )
773 		*ppItemArr = new SfxPoolItemArray_Impl;
774 
775 	SfxPoolItemArrayBase_Impl::iterator ppFree;
776 	sal_Bool ppFreeIsSet = sal_False;
777 	SfxPoolItemArrayBase_Impl::iterator ppHtArray = (*ppItemArr)->begin();
778 	if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) )
779 	{
780 		// wenn es ueberhaupt gepoolt ist, koennte es schon drin sein
781 		if ( IsPooledItem(&rItem) )
782 		{
783 			// 1. Schleife: teste ob der Pointer vorhanden ist.
784 			for( size_t n = (*ppItemArr)->size(); n; ++ppHtArray, --n )
785 				if( &rItem == (*ppHtArray) )
786 				{
787 					AddRef( **ppHtArray );
788 					return **ppHtArray;
789 				}
790 		}
791 
792 		// 2. Schleife: dann muessen eben die Attribute verglichen werden
793 		size_t n;
794 		for ( n = (*ppItemArr)->size(), ppHtArray = (*ppItemArr)->begin();
795 			  n; ++ppHtArray, --n )
796 		{
797 			if ( *ppHtArray )
798 			{
799 				if( **ppHtArray == rItem )
800 				{
801 					AddRef( **ppHtArray );
802 					return **ppHtArray;
803 				}
804 			}
805 			else
806 				if ( ppFreeIsSet == sal_False )
807 				{
808 					ppFree = ppHtArray;
809 					ppFreeIsSet = sal_True;
810 				}
811 		}
812 	}
813 	else
814 	{
815 		// freien Platz suchen
816 		SfxPoolItemArrayBase_Impl::iterator ppHtArr;
817 		size_t n, nCount = (*ppItemArr)->size();
818 		for ( n = (*ppItemArr)->nFirstFree,
819 				  ppHtArr = (*ppItemArr)->begin() + n;
820 			  n < nCount;
821 			  ++ppHtArr, ++n )
822 			if ( !*ppHtArr )
823 			{
824 				ppFree = ppHtArr;
825 				ppFreeIsSet = sal_True;
826 				break;
827 			}
828 
829 		// naechstmoeglichen freien Platz merken
830 		(*ppItemArr)->nFirstFree = n;
831 	}
832 
833 	// nicht vorhanden, also im PtrArray eintragen
834 	SfxPoolItem* pNewItem = rItem.Clone(pMaster);
835 	pNewItem->SetWhich(nWhich);
836 #ifdef DBG_UTIL
837 	SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" )
838 #ifdef TF_POOLABLE
839 	if ( !rItem.ISA(SfxSetItem) )
840 	{
841 		SFX_ASSERT( !IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
842 					rItem == *pNewItem,
843 					nWhich, "unequal items in Put(): no operator==?" );
844 		SFX_ASSERT( !IsItemFlag(*pNewItem, SFX_ITEM_POOLABLE) ||
845 					*pNewItem == rItem,
846 					nWhich, "unequal items in Put(): no operator==?" );
847 	}
848 #endif
849 #endif
850 	AddRef( *pNewItem, pImp->nInitRefCount );
851 	SfxPoolItem* pTemp = pNewItem;
852 	if ( ppFreeIsSet == sal_False )
853 		(*ppItemArr)->push_back( pTemp );
854 	else
855 	{
856 		DBG_ASSERT( *ppFree == 0, "using surrogate in use" );
857 		*ppFree = pNewItem;
858 	}
859 	return *pNewItem;
860 }
861 
862 // -----------------------------------------------------------------------
863 
864 void SfxItemPool::Remove( const SfxPoolItem& rItem )
865 {
866 	DBG_CHKTHIS(SfxItemPool, 0);
867 
868 	DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
869 				0 != &((const SfxSetItem&)rItem).GetItemSet(),
870 				"SetItem without ItemSet" );
871 
872 	SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(),
873 				"wo kommt denn hier ein Pool-Default her" );
874 
875 	// richtigen Secondary-Pool finden
876 	const sal_uInt16 nWhich = rItem.Which();
877 	sal_Bool bSID = nWhich > SFX_WHICH_MAX;
878 	if ( !bSID && !IsInRange(nWhich) )
879 	{
880 		if ( pSecondary )
881 		{
882 			pSecondary->Remove( rItem );
883 			return;
884 		}
885 		DBG_ERROR( "unknown Which-Id - cannot remove item" );
886 	}
887 
888 	// SID oder nicht poolable (neue Definition)?
889 	sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
890 	if ( bSID || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) )
891 	{
892 		SFX_ASSERT( USHRT_MAX != nIndex ||
893 					!IsDefaultItem(&rItem), rItem.Which(),
894 					"ein nicht Pool-Item ist Default?!" );
895 		if ( 0 == ReleaseRef(rItem) )
896 		{
897 			SfxPoolItem *pItem = &(SfxPoolItem &)rItem;
898 			delete pItem;
899 		}
900 		return;
901 	}
902 
903 	SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove unmoeglich" );
904 
905 	// statische Defaults sind eben einfach da
906 	if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT &&
907 		 &rItem == *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
908 		return;
909 
910 	// Item im eigenen Pool suchen
911 	SfxPoolItemArray_Impl** ppItemArr = (pImp->ppPoolItems + nIndex);
912 	SFX_ASSERT( *ppItemArr, rItem.Which(), "removing Item not in Pool" );
913 	SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
914 	for( size_t n = (*ppItemArr)->size(); n; ++ppHtArr, --n )
915 		if( *ppHtArr == &rItem )
916 		{
917 			if ( (*ppHtArr)->GetRefCount() ) //!
918 				ReleaseRef( **ppHtArr );
919 			else
920 			{
921 				SFX_ASSERT( 0, rItem.Which(), "removing Item without ref" );
922 				SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr );
923 			}
924 
925 			// ggf. kleinstmoegliche freie Position merken
926 			size_t nPos = (*ppItemArr)->size() - n;
927 			if ( (*ppItemArr)->nFirstFree > nPos )
928 				(*ppItemArr)->nFirstFree = nPos;
929 
930 			//! MI: Hack, solange wir das Problem mit dem Outliner haben
931 			//! siehe anderes MI-REF
932 			if ( 0 == (*ppHtArr)->GetRefCount() && nWhich < 4000 )
933 				DELETEZ(*ppHtArr);
934 			return;
935 		}
936 
937 	// nicht vorhanden
938 	SFX_ASSERT( 0, rItem.Which(), "removing Item not in Pool" );
939 	SFX_TRACE( "to be removed, but not in pool: ", &rItem );
940 }
941 
942 // -----------------------------------------------------------------------
943 
944 const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const
945 {
946 	DBG_CHKTHIS(SfxItemPool, 0);
947 
948 	if ( !IsInRange(nWhich) )
949 	{
950 		if ( pSecondary )
951 			return pSecondary->GetDefaultItem( nWhich );
952 		SFX_ASSERT( 0, nWhich, "unknown which - dont ask me for defaults" );
953 	}
954 
955 	DBG_ASSERT( ppStaticDefaults, "no defaults known - dont ask me for defaults" );
956 	sal_uInt16 nPos = GetIndex_Impl(nWhich);
957 	SfxPoolItem *pDefault = *(ppPoolDefaults + nPos);
958 	if ( pDefault )
959 		return *pDefault;
960 	return **(ppStaticDefaults + nPos);
961 }
962 
963 // -----------------------------------------------------------------------
964 
965 
966 void SfxItemPool::FreezeIdRanges()
967 
968 /*	[Beschreibung]
969 
970 	This method should be called at the master pool, when all secondary
971 	pools are appended to it.
972 
973 	It calculates the ranges of 'which-ids' for fast construction of
974 	item-sets, which contains all 'which-ids'.
975 */
976 
977 {
978 	FillItemIdRanges_Impl( _pPoolRanges );
979 }
980 
981 
982 // -----------------------------------------------------------------------
983 
984 void SfxItemPool::FillItemIdRanges_Impl( sal_uInt16*& pWhichRanges ) const
985 {
986 	DBG_CHKTHIS(SfxItemPool, 0);
987 	DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" );
988 
989 	const SfxItemPool *pPool;
990 	sal_uInt16 nLevel = 0;
991 	for( pPool = this; pPool; pPool = pPool->pSecondary )
992 		++nLevel;
993 
994 	pWhichRanges = new sal_uInt16[ 2*nLevel + 1 ];
995 
996 	nLevel = 0;
997 	for( pPool = this; pPool; pPool = pPool->pSecondary )
998 	{
999 		*(pWhichRanges+(nLevel++)) = pPool->nStart;
1000 		*(pWhichRanges+(nLevel++)) = pPool->nEnd;
1001 		*(pWhichRanges+nLevel) = 0;
1002 	}
1003 }
1004 
1005 // -----------------------------------------------------------------------
1006 
1007 const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) const
1008 {
1009 	DBG_CHKTHIS(SfxItemPool, 0);
1010 
1011 	if ( !IsInRange(nWhich) )
1012 	{
1013 		if ( pSecondary )
1014 			return pSecondary->GetItem2( nWhich, nOfst );
1015 		SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" );
1016 		return 0;
1017 	}
1018 
1019 	// dflt-Attribut?
1020 	if ( nOfst == SFX_ITEMS_DEFAULT )
1021 		return *(ppStaticDefaults + GetIndex_Impl(nWhich));
1022 
1023 	SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich));
1024 	if( pItemArr && nOfst < pItemArr->size() )
1025 		return (*pItemArr)[nOfst];
1026 
1027 	return 0;
1028 }
1029 
1030 // -----------------------------------------------------------------------
1031 
1032 sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const
1033 {
1034 	DBG_CHKTHIS(SfxItemPool, 0);
1035 
1036 	if ( !IsInRange(nWhich) )
1037 	{
1038 		if ( pSecondary )
1039 			return pSecondary->GetItemCount2( nWhich );
1040 		SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" );
1041 		return 0;
1042 	}
1043 
1044 	SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich));
1045 	if  ( pItemArr )
1046 		return pItemArr->size();
1047 	return 0;
1048 }
1049 
1050 // -----------------------------------------------------------------------
1051 
1052 sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const
1053 {
1054 	if ( !IsSlot(nSlotId) )
1055 		return nSlotId;
1056 
1057 #ifdef TF_POOLABLE
1058 	sal_uInt16 nCount = nEnd - nStart + 1;
1059 	for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1060 		if ( pItemInfos[nOfs]._nSID == nSlotId )
1061 			return nOfs + nStart;
1062 #else
1063 	if ( pSlotIds )
1064 	{
1065 		sal_uInt16 nCount = nEnd - nStart + 1;
1066 		for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1067 			if ( pSlotIds[nOfs] == nSlotId )
1068 				return nOfs + nStart;
1069 	}
1070 #endif
1071 	if ( pSecondary && bDeep )
1072 		return pSecondary->GetWhich(nSlotId);
1073 	return nSlotId;
1074 }
1075 
1076 // -----------------------------------------------------------------------
1077 
1078 sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const
1079 {
1080 	if ( !IsWhich(nWhich) )
1081 		return nWhich;
1082 
1083 	if ( !IsInRange( nWhich ) )
1084 	{
1085 		if ( pSecondary && bDeep )
1086 			return pSecondary->GetSlotId(nWhich);
1087 		SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" );
1088 		return 0;
1089 	}
1090 #ifdef TF_POOLABLE
1091 
1092 	sal_uInt16 nSID = pItemInfos[nWhich - nStart]._nSID;
1093 	return nSID ? nSID : nWhich;
1094 #else
1095 	else if ( pSlotIds )
1096 		return pSlotIds[nWhich - nStart];
1097 	return nWhich;
1098 #endif
1099 }
1100 
1101 // -----------------------------------------------------------------------
1102 
1103 sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const
1104 {
1105 	if ( !IsSlot(nSlotId) )
1106 		return 0;
1107 
1108 #ifdef TF_POOLABLE
1109 	sal_uInt16 nCount = nEnd - nStart + 1;
1110 	for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1111 		if ( pItemInfos[nOfs]._nSID == nSlotId )
1112 			return nOfs + nStart;
1113 #else
1114 	if ( pSlotIds )
1115 	{
1116 		sal_uInt16 nCount = nEnd - nStart + 1;
1117 		for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1118 			if ( pSlotIds[nOfs] == nSlotId )
1119 				return nOfs + nStart;
1120 	}
1121 #endif
1122 	if ( pSecondary && bDeep )
1123 		return pSecondary->GetTrueWhich(nSlotId);
1124 	return 0;
1125 }
1126 
1127 // -----------------------------------------------------------------------
1128 
1129 sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const
1130 {
1131 	if ( !IsWhich(nWhich) )
1132 		return 0;
1133 
1134 	if ( !IsInRange( nWhich ) )
1135 	{
1136 		if ( pSecondary && bDeep )
1137 			return pSecondary->GetTrueSlotId(nWhich);
1138 		SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" );
1139 		return 0;
1140 	}
1141 #ifdef TF_POOLABLE
1142 	return pItemInfos[nWhich - nStart]._nSID;
1143 #else
1144 	else if ( pSlotIds )
1145 		return pSlotIds[nWhich - nStart];
1146 	else
1147 		return 0;
1148 #endif
1149 }
1150 // -----------------------------------------------------------------------
1151 void SfxItemPool::SetFileFormatVersion( sal_uInt16 nFileFormatVersion )
1152 
1153 /*  [Description]
1154 
1155 	You must call this function to set the file format version after
1156 	concatenating your secondary-pools but before you store any
1157 	pool, itemset or item. Only set the version at the master pool,
1158 	never at any secondary pool.
1159 */
1160 
1161 {
1162 	DBG_ASSERT( this == pMaster,
1163 				"SfxItemPool::SetFileFormatVersion() but not a master pool" );
1164 	for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary )
1165 		pPool->_nFileFormatVersion = nFileFormatVersion;
1166 }
1167 
1168 
1169