Update ooo320-m1
[ooovba.git] / svtools / source / items1 / itempool.cxx
blobddda204d132c60d22ed46e4312afc5f3846c1b9f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itempool.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <string.h>
35 #include <stdio.h>
36 #ifndef GCC
37 #endif
39 #include <svtools/itempool.hxx>
40 #include "whassert.hxx"
41 #include <svtools/brdcst.hxx>
42 #include <svtools/smplhint.hxx>
43 #include "poolio.hxx"
44 #include <algorithm>
46 // STATIC DATA -----------------------------------------------------------
49 //========================================================================
51 SV_IMPL_PTRARR( SfxPoolVersionArr_Impl, SfxPoolVersion_Impl* );
53 //========================================================================
56 void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser)
58 maSfxItemPoolUsers.push_back(&rNewUser);
61 void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser)
63 const SfxItemPoolUserVector::iterator aFindResult = ::std::find(maSfxItemPoolUsers.begin(), maSfxItemPoolUsers.end(), &rOldUser);
64 if(aFindResult != maSfxItemPoolUsers.end())
66 maSfxItemPoolUsers.erase(aFindResult);
70 const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( USHORT nWhich ) const
72 DBG_CHKTHIS(SfxItemPool, 0);
73 const SfxPoolItem* pRet;
74 if( IsInRange( nWhich ) )
75 pRet = *(ppPoolDefaults + GetIndex_Impl( nWhich ));
76 else if( pSecondary )
77 pRet = pSecondary->GetPoolDefaultItem( nWhich );
78 else
80 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get pool default" );
81 pRet = 0;
83 return pRet;
86 // -----------------------------------------------------------------------
88 inline FASTBOOL SfxItemPool::IsItemFlag_Impl( USHORT nPos, USHORT nFlag ) const
90 USHORT nItemFlag = pItemInfos[nPos]._nFlags;
91 return nFlag == (nItemFlag & nFlag);
94 // -----------------------------------------------------------------------
96 FASTBOOL SfxItemPool::IsItemFlag( USHORT nWhich, USHORT nFlag ) const
98 for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary )
100 if ( pPool->IsInRange(nWhich) )
101 return pPool->IsItemFlag_Impl( pPool->GetIndex_Impl(nWhich), nFlag);
103 DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" );
104 return FALSE;
107 // -----------------------------------------------------------------------
109 SfxBroadcaster& SfxItemPool::BC()
111 return pImp->aBC;
114 // -----------------------------------------------------------------------
117 SfxItemPool::SfxItemPool
119 UniString const & rName, /* Name des Pools zur Idetifikation
120 im File-Format */
121 USHORT nStartWhich, /* erste Which-Id des Pools */
122 USHORT nEndWhich, /* letzte Which-Id des Pools */
123 #ifdef TF_POOLABLE
124 const SfxItemInfo* pInfos, /* SID-Map und Item-Flags */
125 #endif
126 SfxPoolItem** pDefaults, /* Pointer auf statische Defaults,
127 wird direkt vom Pool referenziert,
128 jedoch kein Eigent"umer"ubergang */
129 #ifndef TF_POOLABLE
130 USHORT* pSlotIdArray, /* Zuordnung von Slot-Ids zu Which-Ids */
131 #endif
132 FASTBOOL bLoadRefCounts /* Ref-Counts mitladen oder auf 1 setzen */
135 /* [Beschreibung]
137 Der im Normalfall verwendete Konstruktor der Klasse SfxItemPool. Es
138 wird eine SfxItemPool-Instanz initialisiert, die Items im b"undigen
139 Which-Bereich von 'nStartWhich' bis 'nEndWhich' verwalten kann.
141 F"ur jede dieser Which-Ids mu\s ein statischer Default im Array 'pDefaults'
142 vorhanden sein, die dort beginnend mit einem <SfxPoolItem> mit der
143 Which-Id 'nStartWhich' nach Which-Ids sortiert aufeinanderfolgend
144 eingetragen sein m"ussen.
146 'pItemInfos' ist ein identisch angeordnetes Array von USHORTs, die
147 Slot-Ids darstellen und Flags. Die Slot-Ids k"onnen 0 sein, wenn die
148 betreffenden Items ausschlie\slich in der Core verwendet werden.
149 "Uber die Flags kann z.B. bestimmt werden, ob Value-Sharing
150 (SFX_ITEM_POOLABLE) stattfinden soll.
152 [Anmerkung]
154 Wenn der Pool <SfxSetItem>s enthalten soll, k"onnen im Konstruktor noch
155 keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich
156 mit <SfxItemPool::SetDefaults(SfxItemPool**)> geschehen.
159 [Querverweise]
161 <SfxItemPool::SetDefaults(SfxItemPool**)>
162 <SfxItemPool::ReleaseDefaults(SfxPoolItem**,USHORT,BOOL)>
163 <SfxItemPool::ReldaseDefaults(BOOL)>
166 : aName(rName),
167 nStart(nStartWhich),
168 nEnd(nEndWhich),
169 #ifdef TF_POOLABLE
170 pItemInfos(pInfos),
171 #else
172 pSlotIds(pSlotIdArray),
173 #endif
174 pImp( new SfxItemPool_Impl( nStart, nEnd ) ),
175 ppStaticDefaults(0),
176 ppPoolDefaults(new SfxPoolItem* [ nEndWhich - nStartWhich + 1]),
177 pSecondary(0),
178 pMaster(this),
179 _pPoolRanges( 0 ),
180 bPersistentRefCounts(bLoadRefCounts),
181 maSfxItemPoolUsers()
183 DBG_CTOR(SfxItemPool, 0);
184 DBG_ASSERT(nStart, "Start-Which-Id must be greater 0" );
186 pImp->eDefMetric = SFX_MAPUNIT_TWIP;
187 pImp->nVersion = 0;
188 pImp->bStreaming = FALSE;
189 pImp->nLoadingVersion = 0;
190 pImp->nInitRefCount = 1;
191 pImp->nVerStart = nStart;
192 pImp->nVerEnd = nEnd;
193 pImp->bInSetItem = FALSE;
194 pImp->nStoringStart = nStartWhich;
195 pImp->nStoringEnd = nEndWhich;
197 memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1));
199 if ( pDefaults )
200 SetDefaults(pDefaults);
203 // -----------------------------------------------------------------------
206 SfxItemPool::SfxItemPool
208 const SfxItemPool& rPool, // von dieser Instanz kopieren
209 BOOL bCloneStaticDefaults /* TRUE
210 statische Defaults kopieren
212 FALSE
213 statische Defaults
214 "ubernehehmen */
217 /* [Beschreibung]
219 Copy-Konstruktor der Klasse SfxItemPool.
222 [Querverweise]
224 <SfxItemPool::Clone()const>
227 : aName(rPool.aName),
228 nStart(rPool.nStart),
229 nEnd(rPool.nEnd),
230 #ifdef TF_POOLABLE
231 pItemInfos(rPool.pItemInfos),
232 #else
233 pSlotIds(rPool.pSlotIds),
234 #endif
235 pImp( new SfxItemPool_Impl( nStart, nEnd ) ),
236 ppStaticDefaults(0),
237 ppPoolDefaults(new SfxPoolItem* [ nEnd - nStart + 1]),
238 pSecondary(0),
239 pMaster(this),
240 _pPoolRanges( 0 ),
241 bPersistentRefCounts(rPool.bPersistentRefCounts ),
242 maSfxItemPoolUsers()
244 DBG_CTOR(SfxItemPool, 0);
245 pImp->eDefMetric = rPool.pImp->eDefMetric;
246 pImp->nVersion = rPool.pImp->nVersion;
247 pImp->bStreaming = FALSE;
248 pImp->nLoadingVersion = 0;
249 pImp->nInitRefCount = 1;
250 pImp->nVerStart = rPool.pImp->nVerStart;
251 pImp->nVerEnd = rPool.pImp->nVerEnd;
252 pImp->bInSetItem = FALSE;
253 pImp->nStoringStart = nStart;
254 pImp->nStoringEnd = nEnd;
256 memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1));
258 // Static Defaults "ubernehmen
259 if ( bCloneStaticDefaults )
261 SfxPoolItem **ppDefaults = new SfxPoolItem*[nEnd-nStart+1];
262 for ( USHORT n = 0; n <= nEnd - nStart; ++n )
264 (*( ppDefaults + n )) = (*( rPool.ppStaticDefaults + n ))->Clone(this);
265 (*( ppDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
268 SetDefaults( ppDefaults );
270 else
271 SetDefaults( rPool.ppStaticDefaults );
273 // Pool Defaults kopieren
274 for ( USHORT n = 0; n <= nEnd - nStart; ++n )
275 if ( (*( rPool.ppPoolDefaults + n )) )
277 (*( ppPoolDefaults + n )) = (*( rPool.ppPoolDefaults + n ))->Clone(this);
278 (*( ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT );
281 // Version-Map kopieren
282 USHORT nVerCount = rPool.pImp->aVersions.Count();
283 for ( USHORT nVer = 0; nVer < nVerCount; ++nVer )
285 const SfxPoolVersion_Impl *pOld = rPool.pImp->aVersions.GetObject(nVer);
286 const SfxPoolVersion_Impl *pNew = new SfxPoolVersion_Impl( *pOld );
287 pImp->aVersions.Insert( pNew, nVer );
290 // Verkettung wiederherstellen
291 if ( rPool.pSecondary )
292 SetSecondaryPool( rPool.pSecondary->Clone() );
295 // -----------------------------------------------------------------------
297 void SfxItemPool::SetDefaults( SfxPoolItem **pDefaults )
299 DBG_CHKTHIS(SfxItemPool, 0);
300 DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." );
301 DBG_ASSERT( !ppStaticDefaults, "habe schon defaults" );
303 ppStaticDefaults = pDefaults;
304 //! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT )
305 //! geht wohl nicht im Zshg mit SetItems, die hinten stehen
307 DBG_ASSERT( (*ppStaticDefaults)->GetRefCount() == 0 ||
308 IsDefaultItem( (*ppStaticDefaults) ),
309 "das sind keine statics" );
310 for ( USHORT n = 0; n <= nEnd - nStart; ++n )
312 SFX_ASSERT( (*( ppStaticDefaults + n ))->Which() == n + nStart,
313 n + nStart, "static defaults not sorted" );
314 (*( ppStaticDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
315 DBG_ASSERT( !(pImp->ppPoolItems[n]), "defaults with setitems with items?!" );
320 // -----------------------------------------------------------------------
322 void SfxItemPool::ReleaseDefaults
324 BOOL bDelete /* TRUE
325 l"oscht sowohl das Array als auch die einzelnen
326 statischen Defaults
328 FALSE
329 l"oscht weder das Array noch die einzelnen
330 statischen Defaults */
333 /* [Beschreibung]
335 Gibt die statischen Defaults der betreffenden SfxItemPool-Instanz frei
336 und l"oscht ggf. die statischen Defaults.
338 Nach Aufruf dieser Methode darf die SfxItemPool-Instanz nicht mehr
339 verwendet werden, einzig ist der Aufruf des Destruktors zu"lassig.
343 DBG_ASSERT( ppStaticDefaults, "keine Arme keine Kekse" );
344 ReleaseDefaults( ppStaticDefaults, nEnd - nStart + 1, bDelete );
346 // KSO (22.10.98): ppStaticDefaults zeigt auf geloeschten Speicher,
347 // wenn bDelete == TRUE.
348 if ( bDelete )
349 ppStaticDefaults = 0;
352 // -----------------------------------------------------------------------
354 void SfxItemPool::ReleaseDefaults
356 SfxPoolItem** pDefaults, /* freizugebende statische Defaults */
358 USHORT nCount, /* Anzahl der statischen Defaults */
360 BOOL bDelete /* TRUE
361 l"oscht sowohl das Array als auch die
362 einzelnen statischen Defaults
364 FALSE
365 l"oscht weder das Array noch die
366 einzelnen statischen Defaults */
369 /* [Beschreibung]
371 Gibt die angegebenen statischen Defaults frei und l"oscht ggf.
372 die statischen Defaults.
374 Diese Methode darf erst nach Zerst"orung aller SfxItemPool-Instanzen,
375 welche die angegebenen statischen Defaults 'pDefault' verwenden,
376 aufgerufen werden.
380 DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." );
382 for ( USHORT n = 0; n < nCount; ++n )
384 SFX_ASSERT( IsStaticDefaultItem( *(pDefaults+n) ),
385 n, "das ist kein static-default" );
386 (*( pDefaults + n ))->SetRefCount( 0 );
387 if ( bDelete )
388 { delete *( pDefaults + n ); *(pDefaults + n) = 0; }
391 if ( bDelete )
392 { delete[] pDefaults; pDefaults = 0; }
395 // -----------------------------------------------------------------------
397 SfxItemPool::~SfxItemPool()
399 DBG_DTOR(SfxItemPool, 0);
400 DBG_ASSERT( pMaster == this, "destroying active Secondary-Pool" );
402 if ( pImp->ppPoolItems && ppPoolDefaults )
403 Delete();
404 delete[] _pPoolRanges;
405 delete pImp;
408 void SfxItemPool::Free(SfxItemPool* pPool)
410 if(pPool)
412 // tell all the registered SfxItemPoolUsers that the pool is in destruction
413 SfxItemPoolUserVector aListCopy(pPool->maSfxItemPoolUsers.begin(), pPool->maSfxItemPoolUsers.end());
414 for(SfxItemPoolUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++)
416 SfxItemPoolUser* pSfxItemPoolUser = *aIterator;
417 DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)");
418 pSfxItemPoolUser->ObjectInDestruction(*pPool);
421 // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser()
422 // when they get called from ObjectInDestruction().
423 pPool->maSfxItemPoolUsers.clear();
425 // delete pool
426 delete pPool;
430 // -----------------------------------------------------------------------
433 void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool )
435 // ggf. an abgeh"angten Pools den Master zur"ucksetzen
436 if ( pSecondary )
438 #ifdef DBG_UTIL
439 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
440 if ( ppStaticDefaults )
442 // Delete() ist noch nicht gelaufen?
443 if ( pImp->ppPoolItems && pSecondary->pImp->ppPoolItems )
445 // hat der master SetItems?
446 BOOL bHasSetItems = FALSE;
447 for ( USHORT i = 0; !bHasSetItems && i < nEnd-nStart; ++i )
448 bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem);
450 // abgehaengte Pools muessen leer sein
451 BOOL bOK = bHasSetItems;
452 for ( USHORT n = 0;
453 bOK && n <= pSecondary->nEnd - pSecondary->nStart;
454 ++n )
456 SfxPoolItemArray_Impl** ppItemArr =
457 pSecondary->pImp->ppPoolItems + n;
458 if ( *ppItemArr )
460 SfxPoolItem** ppHtArr =
461 (SfxPoolItem**)(*ppItemArr)->GetData();
462 for( USHORT i = (*ppItemArr)->Count(); i; ++ppHtArr, --i )
463 if ( !(*ppHtArr) )
465 DBG_ERROR( "old secondary pool must be empty" );
466 bOK = FALSE;
467 break;
473 #endif
475 pSecondary->pMaster = pSecondary;
476 for ( SfxItemPool *p = pSecondary->pSecondary; p; p = p->pSecondary )
477 p->pMaster = pSecondary;
480 // ggf. den Master der neuen Secondary-Pools setzen
481 DBG_ASSERT( !pPool || pPool->pMaster == pPool, "Secondary tanzt auf zwei Hochzeiten " );
482 SfxItemPool *pNewMaster = pMaster ? pMaster : this;
483 for ( SfxItemPool *p = pPool; p; p = p->pSecondary )
484 p->pMaster = pNewMaster;
486 // neuen Secondary-Pool merken
487 pSecondary = pPool;
490 // -----------------------------------------------------------------------
492 SfxMapUnit SfxItemPool::GetMetric( USHORT ) const
494 DBG_CHKTHIS(SfxItemPool, 0);
496 return pImp->eDefMetric;
499 // -----------------------------------------------------------------------
501 void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric )
503 DBG_CHKTHIS(SfxItemPool, 0);
505 pImp->eDefMetric = eNewMetric;
508 // -----------------------------------------------------------------------
510 SfxItemPresentation SfxItemPool::GetPresentation
512 const SfxPoolItem& rItem, /* IN: <SfxPoolItem>, dessen textuelle
513 Wert-Darstellung geliefert werden
514 soll */
515 SfxItemPresentation ePresent, /* IN: gew"unschte Art der Darstellung;
516 siehe <SfxItemPresentation> */
517 SfxMapUnit eMetric, /* IN: gew"unschte Ma\seinheit der Darstellung */
518 XubString& rText, /* OUT: textuelle Darstellung von 'rItem' */
519 const IntlWrapper * pIntlWrapper
520 ) const
522 /* [Beschreibung]
524 "Uber diese virtuelle Methode k"onnen textuelle Darstellungen der
525 von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems
526 angefordert werden.
528 In Ableitungen sollte diese Methode "uberladen werden und auf
529 SfxPoolItems reagiert werden, die bei <SfxPoolItem::GetPresentation()const>
530 keine vollst"andige Information liefern k"onnen.
532 Die Basisklasse liefert die unver"anderte Presentation von 'rItem'.
536 DBG_CHKTHIS(SfxItemPool, 0);
537 return rItem.GetPresentation(
538 ePresent, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper );
542 // -----------------------------------------------------------------------
544 SfxItemPool* SfxItemPool::Clone() const
546 DBG_CHKTHIS(SfxItemPool, 0);
548 SfxItemPool *pPool = new SfxItemPool( *this );
549 return pPool;
552 // ----------------------------------------------------------------------
554 void SfxItemPool::Delete()
556 DBG_CHKTHIS(SfxItemPool, 0);
558 // schon deleted?
559 if ( !pImp->ppPoolItems || !ppPoolDefaults )
560 return;
562 // z.B. laufenden Requests bescheidsagen
563 pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) );
565 //MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems.
566 //Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt.
568 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
569 SfxPoolItem** ppDefaultItem = ppPoolDefaults;
570 SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults;
571 USHORT nArrCnt;
573 //Erst die SetItems abraeumen
574 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
575 if ( ppStaticDefaults )
577 for ( nArrCnt = GetSize_Impl();
578 nArrCnt;
579 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
581 // KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer
582 // von SfxItemPool abgeleiteten Klasse bereits geloescht worden
583 // sein! -> CHAOS Itempool
584 if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) )
586 if ( *ppItemArr )
588 SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData();
589 for ( USHORT n = (*ppItemArr)->Count(); n; --n, ++ppHtArr )
590 if (*ppHtArr)
592 #ifndef PRODUCT
593 ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
594 #endif
595 delete *ppHtArr;
597 DELETEZ( *ppItemArr );
599 if ( *ppDefaultItem )
601 #ifndef PRODUCT
602 SetRefCount( **ppDefaultItem, 0 );
603 #endif
604 DELETEZ( *ppDefaultItem );
610 ppItemArr = pImp->ppPoolItems;
611 ppDefaultItem = ppPoolDefaults;
613 //Jetzt die 'einfachen' Items
614 for ( nArrCnt = GetSize_Impl();
615 nArrCnt;
616 --nArrCnt, ++ppItemArr, ++ppDefaultItem )
618 if ( *ppItemArr )
620 SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData();
621 for ( USHORT n = (*ppItemArr)->Count(); n; --n, ++ppHtArr )
622 if (*ppHtArr)
624 #ifndef PRODUCT
625 ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
626 #endif
627 delete *ppHtArr;
629 delete *ppItemArr;
631 if ( *ppDefaultItem )
633 #ifndef PRODUCT
634 SetRefCount( **ppDefaultItem, 0 );
635 #endif
636 delete *ppDefaultItem;
640 pImp->DeleteItems();
641 delete[] ppPoolDefaults; ppPoolDefaults = 0;
644 // ----------------------------------------------------------------------
646 void SfxItemPool::Cleanup()
648 DBG_CHKTHIS(SfxItemPool, 0);
650 //MA 16. Apr. 97: siehe ::Delete()
652 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
653 SfxPoolItem** ppDefaultItem = ppPoolDefaults;
654 SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults;
655 USHORT nArrCnt;
657 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
658 if ( ppStaticDefaults ) //HACK fuer Image, dort gibt es keine Statics!!
660 for ( nArrCnt = GetSize_Impl();
661 nArrCnt;
662 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
664 //Fuer jedes Item gibt es entweder ein Default oder ein static Default!
665 if ( *ppItemArr &&
666 ((*ppDefaultItem && (*ppDefaultItem)->ISA(SfxSetItem)) ||
667 (*ppStaticDefaultItem)->ISA(SfxSetItem)) )
669 SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData();
670 for ( USHORT n = (*ppItemArr)->Count(); n; --n, ++ppHtArr )
671 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() )
673 DELETEZ(*ppHtArr);
679 ppItemArr = pImp->ppPoolItems;
681 for ( nArrCnt = GetSize_Impl();
682 nArrCnt;
683 --nArrCnt, ++ppItemArr )
685 if ( *ppItemArr )
687 SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData();
688 for ( USHORT n = (*ppItemArr)->Count(); n; --n, ++ppHtArr )
689 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() )
690 DELETEZ( *ppHtArr );
695 // ----------------------------------------------------------------------
697 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem)
699 DBG_CHKTHIS(SfxItemPool, 0);
700 if ( IsInRange(rItem.Which()) )
702 SfxPoolItem **ppOldDefault =
703 ppPoolDefaults + GetIndex_Impl(rItem.Which());
704 SfxPoolItem *pNewDefault = rItem.Clone(this);
705 pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT);
706 if ( *ppOldDefault )
708 (*ppOldDefault)->SetRefCount(0);
709 DELETEZ( *ppOldDefault );
711 *ppOldDefault = pNewDefault;
713 else if ( pSecondary )
714 pSecondary->SetPoolDefaultItem(rItem);
715 else
717 SFX_ASSERT( 0, rItem.Which(), "unknown Which-Id - cannot set pool default" );
722 * Resets the default of the given <Which-Id> back to the static default.
723 * If a pool default exists it is removed.
725 void SfxItemPool::ResetPoolDefaultItem( USHORT nWhichId )
727 DBG_CHKTHIS(SfxItemPool, 0);
728 if ( IsInRange(nWhichId) )
730 SfxPoolItem **ppOldDefault =
731 ppPoolDefaults + GetIndex_Impl( nWhichId );
732 if ( *ppOldDefault )
734 (*ppOldDefault)->SetRefCount(0);
735 DELETEZ( *ppOldDefault );
738 else if ( pSecondary )
739 pSecondary->ResetPoolDefaultItem(nWhichId);
740 else
742 SFX_ASSERT( 0, nWhichId, "unknown Which-Id - cannot set pool default" );
746 // -----------------------------------------------------------------------
748 const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, USHORT nWhich )
750 DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
751 0 != &((const SfxSetItem&)rItem).GetItemSet(),
752 "SetItem without ItemSet" );
754 DBG_CHKTHIS(SfxItemPool, 0);
755 if ( 0 == nWhich )
756 nWhich = rItem.Which();
758 // richtigen Secondary-Pool finden
759 BOOL bSID = nWhich > SFX_WHICH_MAX;
760 if ( !bSID && !IsInRange(nWhich) )
762 if ( pSecondary )
763 return pSecondary->Put( rItem, nWhich );
764 DBG_ERROR( "unknown Which-Id - cannot put item" );
767 // SID oder nicht poolable (neue Definition)?
768 USHORT nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
769 if ( USHRT_MAX == nIndex ||
770 IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) )
772 SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich ||
773 !IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE,
774 nWhich, "ein nicht Pool-Item ist Default?!" );
775 SfxPoolItem *pPoolItem = rItem.Clone(pMaster);
776 pPoolItem->SetWhich(nWhich);
777 AddRef( *pPoolItem );
778 return *pPoolItem;
781 SFX_ASSERT( rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich,
782 "SFxItemPool: wrong item type in Put" );
784 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems + nIndex;
785 if( !*ppItemArr )
786 *ppItemArr = new SfxPoolItemArray_Impl;
788 SfxPoolItem **ppFree = 0;
789 SfxPoolItem** ppHtArray = (SfxPoolItem**)(*ppItemArr)->GetData();
790 if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) )
792 // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein
793 if ( IsPooledItem(&rItem) )
795 // 1. Schleife: teste ob der Pointer vorhanden ist.
796 for( USHORT n = (*ppItemArr)->Count(); n; ++ppHtArray, --n )
797 if( &rItem == (*ppHtArray) )
799 AddRef( **ppHtArray );
800 return **ppHtArray;
804 // 2. Schleife: dann muessen eben die Attribute verglichen werden
805 USHORT n;
806 for ( n = (*ppItemArr)->Count(), ppHtArray = (SfxPoolItem**)(*ppItemArr)->GetData();
807 n; ++ppHtArray, --n )
809 if ( *ppHtArray )
811 if( **ppHtArray == rItem )
813 AddRef( **ppHtArray );
814 return **ppHtArray;
817 else
818 if ( !ppFree )
819 ppFree = ppHtArray;
822 else
824 // freien Platz suchen
825 SfxPoolItem** ppHtArr;
826 USHORT n, nCount = (*ppItemArr)->Count();
827 for ( n = (*ppItemArr)->nFirstFree,
828 ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData() + n;
829 n < nCount;
830 ++ppHtArr, ++n )
831 if ( !*ppHtArr )
833 ppFree = ppHtArr;
834 break;
837 // naechstmoeglichen freien Platz merken
838 (*ppItemArr)->nFirstFree = n;
841 // nicht vorhanden, also im PtrArray eintragen
842 SfxPoolItem* pNewItem = rItem.Clone(pMaster);
843 pNewItem->SetWhich(nWhich);
844 #ifdef DBG_UTIL
845 SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" )
846 #ifdef TF_POOLABLE
847 if ( !rItem.ISA(SfxSetItem) )
849 SFX_ASSERT( !IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
850 rItem == *pNewItem,
851 nWhich, "unequal items in Put(): no operator==?" );
852 SFX_ASSERT( !IsItemFlag(*pNewItem, SFX_ITEM_POOLABLE) ||
853 *pNewItem == rItem,
854 nWhich, "unequal items in Put(): no operator==?" );
856 #endif
857 #endif
858 AddRef( *pNewItem, pImp->nInitRefCount );
859 const SfxPoolItem* pTemp = pNewItem;
860 if ( !ppFree )
861 (*ppItemArr)->Insert( pTemp, (*ppItemArr)->Count() );
862 else
864 DBG_ASSERT( *ppFree == 0, "using surrogate in use" );
865 *ppFree = pNewItem;
867 return *pNewItem;
870 // -----------------------------------------------------------------------
872 void SfxItemPool::Remove( const SfxPoolItem& rItem )
874 DBG_CHKTHIS(SfxItemPool, 0);
876 DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
877 0 != &((const SfxSetItem&)rItem).GetItemSet(),
878 "SetItem without ItemSet" );
880 SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(),
881 "wo kommt denn hier ein Pool-Default her" );
883 // richtigen Secondary-Pool finden
884 const USHORT nWhich = rItem.Which();
885 BOOL bSID = nWhich > SFX_WHICH_MAX;
886 if ( !bSID && !IsInRange(nWhich) )
888 if ( pSecondary )
890 pSecondary->Remove( rItem );
891 return;
893 DBG_ERROR( "unknown Which-Id - cannot remove item" );
896 // SID oder nicht poolable (neue Definition)?
897 USHORT nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
898 if ( bSID || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) )
900 SFX_ASSERT( USHRT_MAX != nIndex ||
901 !IsDefaultItem(&rItem), rItem.Which(),
902 "ein nicht Pool-Item ist Default?!" );
903 if ( 0 == ReleaseRef(rItem) )
905 SfxPoolItem *pItem = &(SfxPoolItem &)rItem;
906 delete pItem;
908 return;
911 SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove unmoeglich" );
913 // statische Defaults sind eben einfach da
914 if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT &&
915 &rItem == *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
916 return;
918 // Item im eigenen Pool suchen
919 SfxPoolItemArray_Impl** ppItemArr = (pImp->ppPoolItems + nIndex);
920 SFX_ASSERT( *ppItemArr, rItem.Which(), "removing Item not in Pool" );
921 SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData();
922 for( USHORT n = (*ppItemArr)->Count(); n; ++ppHtArr, --n )
923 if( *ppHtArr == &rItem )
925 if ( (*ppHtArr)->GetRefCount() ) //!
926 ReleaseRef( **ppHtArr );
927 else
929 SFX_ASSERT( 0, rItem.Which(), "removing Item without ref" );
930 SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr );
933 // ggf. kleinstmoegliche freie Position merken
934 USHORT nPos = (*ppItemArr)->Count() - n;
935 if ( (*ppItemArr)->nFirstFree > nPos )
936 (*ppItemArr)->nFirstFree = nPos;
938 //! MI: Hack, solange wir das Problem mit dem Outliner haben
939 //! siehe anderes MI-REF
940 if ( 0 == (*ppHtArr)->GetRefCount() && nWhich < 4000 )
941 DELETEZ(*ppHtArr);
942 return;
945 // nicht vorhanden
946 SFX_ASSERT( 0, rItem.Which(), "removing Item not in Pool" );
947 SFX_TRACE( "to be removed, but not in pool: ", &rItem );
950 // -----------------------------------------------------------------------
952 const SfxPoolItem& SfxItemPool::GetDefaultItem( USHORT nWhich ) const
954 DBG_CHKTHIS(SfxItemPool, 0);
956 if ( !IsInRange(nWhich) )
958 if ( pSecondary )
959 return pSecondary->GetDefaultItem( nWhich );
960 SFX_ASSERT( 0, nWhich, "unknown which - dont ask me for defaults" );
963 DBG_ASSERT( ppStaticDefaults, "no defaults known - dont ask me for defaults" );
964 USHORT nPos = GetIndex_Impl(nWhich);
965 SfxPoolItem *pDefault = *(ppPoolDefaults + nPos);
966 if ( pDefault )
967 return *pDefault;
968 return **(ppStaticDefaults + nPos);
971 // -----------------------------------------------------------------------
974 void SfxItemPool::FreezeIdRanges()
976 /* [Beschreibung]
978 This method should be called at the master pool, when all secondary
979 pools are appended to it.
981 It calculates the ranges of 'which-ids' for fast construction of
982 item-sets, which contains all 'which-ids'.
986 FillItemIdRanges_Impl( _pPoolRanges );
990 // -----------------------------------------------------------------------
992 void SfxItemPool::FillItemIdRanges_Impl( USHORT*& pWhichRanges ) const
994 DBG_CHKTHIS(SfxItemPool, 0);
995 DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" );
997 const SfxItemPool *pPool;
998 USHORT nLevel = 0;
999 for( pPool = this; pPool; pPool = pPool->pSecondary )
1000 ++nLevel;
1002 pWhichRanges = new USHORT[ 2*nLevel + 1 ];
1004 nLevel = 0;
1005 for( pPool = this; pPool; pPool = pPool->pSecondary )
1007 *(pWhichRanges+(nLevel++)) = pPool->nStart;
1008 *(pWhichRanges+(nLevel++)) = pPool->nEnd;
1009 *(pWhichRanges+nLevel) = 0;
1013 // -----------------------------------------------------------------------
1015 const SfxPoolItem *SfxItemPool::GetItem(USHORT nWhich, USHORT nOfst) const
1017 DBG_CHKTHIS(SfxItemPool, 0);
1019 if ( !IsInRange(nWhich) )
1021 if ( pSecondary )
1022 return pSecondary->GetItem( nWhich, nOfst );
1023 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" );
1024 return 0;
1027 // dflt-Attribut?
1028 if ( nOfst == SFX_ITEMS_STATICDEFAULT )
1029 return *(ppStaticDefaults + GetIndex_Impl(nWhich));
1031 SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich));
1032 if( pItemArr && nOfst < pItemArr->Count() )
1033 return (*pItemArr)[nOfst];
1035 return 0;
1038 // -----------------------------------------------------------------------
1040 USHORT SfxItemPool::GetItemCount(USHORT nWhich) const
1042 DBG_CHKTHIS(SfxItemPool, 0);
1044 if ( !IsInRange(nWhich) )
1046 if ( pSecondary )
1047 return pSecondary->GetItemCount( nWhich );
1048 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" );
1049 return 0;
1052 SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich));
1053 if ( pItemArr )
1054 return pItemArr->Count();
1055 return 0;
1058 // -----------------------------------------------------------------------
1060 USHORT SfxItemPool::GetWhich( USHORT nSlotId, BOOL bDeep ) const
1062 if ( !IsSlot(nSlotId) )
1063 return nSlotId;
1065 #ifdef TF_POOLABLE
1066 USHORT nCount = nEnd - nStart + 1;
1067 for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs )
1068 if ( pItemInfos[nOfs]._nSID == nSlotId )
1069 return nOfs + nStart;
1070 #else
1071 if ( pSlotIds )
1073 USHORT nCount = nEnd - nStart + 1;
1074 for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs )
1075 if ( pSlotIds[nOfs] == nSlotId )
1076 return nOfs + nStart;
1078 #endif
1079 if ( pSecondary && bDeep )
1080 return pSecondary->GetWhich(nSlotId);
1081 return nSlotId;
1084 // -----------------------------------------------------------------------
1086 USHORT SfxItemPool::GetSlotId( USHORT nWhich, BOOL bDeep ) const
1088 if ( !IsWhich(nWhich) )
1089 return nWhich;
1091 if ( !IsInRange( nWhich ) )
1093 if ( pSecondary && bDeep )
1094 return pSecondary->GetSlotId(nWhich);
1095 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" );
1096 return 0;
1098 #ifdef TF_POOLABLE
1100 USHORT nSID = pItemInfos[nWhich - nStart]._nSID;
1101 return nSID ? nSID : nWhich;
1102 #else
1103 else if ( pSlotIds )
1104 return pSlotIds[nWhich - nStart];
1105 return nWhich;
1106 #endif
1109 // -----------------------------------------------------------------------
1111 USHORT SfxItemPool::GetTrueWhich( USHORT nSlotId, BOOL bDeep ) const
1113 if ( !IsSlot(nSlotId) )
1114 return 0;
1116 #ifdef TF_POOLABLE
1117 USHORT nCount = nEnd - nStart + 1;
1118 for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs )
1119 if ( pItemInfos[nOfs]._nSID == nSlotId )
1120 return nOfs + nStart;
1121 #else
1122 if ( pSlotIds )
1124 USHORT nCount = nEnd - nStart + 1;
1125 for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs )
1126 if ( pSlotIds[nOfs] == nSlotId )
1127 return nOfs + nStart;
1129 #endif
1130 if ( pSecondary && bDeep )
1131 return pSecondary->GetTrueWhich(nSlotId);
1132 return 0;
1135 // -----------------------------------------------------------------------
1137 USHORT SfxItemPool::GetTrueSlotId( USHORT nWhich, BOOL bDeep ) const
1139 if ( !IsWhich(nWhich) )
1140 return 0;
1142 if ( !IsInRange( nWhich ) )
1144 if ( pSecondary && bDeep )
1145 return pSecondary->GetTrueSlotId(nWhich);
1146 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" );
1147 return 0;
1149 #ifdef TF_POOLABLE
1150 return pItemInfos[nWhich - nStart]._nSID;
1151 #else
1152 else if ( pSlotIds )
1153 return pSlotIds[nWhich - nStart];
1154 else
1155 return 0;
1156 #endif
1158 // -----------------------------------------------------------------------
1159 void SfxItemPool::SetFileFormatVersion( USHORT nFileFormatVersion )
1161 /* [Description]
1163 You must call this function to set the file format version after
1164 concatenating your secondary-pools but before you store any
1165 pool, itemset or item. Only set the version at the master pool,
1166 never at any secondary pool.
1170 DBG_ASSERT( this == pMaster,
1171 "SfxItemPool::SetFileFormatVersion() but not a master pool" );
1172 for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary )
1173 pPool->_nFileFormatVersion = nFileFormatVersion;