/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svl.hxx" #include #include #ifndef GCC #endif #include #include "whassert.hxx" #include #include #include "poolio.hxx" //======================================================================== void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser) { maSfxItemPoolUsers.push_back(&rNewUser); } void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser) { const SfxItemPoolUserVector::iterator aFindResult = ::std::find(maSfxItemPoolUsers.begin(), maSfxItemPoolUsers.end(), &rOldUser); if(aFindResult != maSfxItemPoolUsers.end()) { maSfxItemPoolUsers.erase(aFindResult); } } const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const { DBG_CHKTHIS(SfxItemPool, 0); const SfxPoolItem* pRet; if( IsInRange( nWhich ) ) pRet = *(ppPoolDefaults + GetIndex_Impl( nWhich )); else if( pSecondary ) pRet = pSecondary->GetPoolDefaultItem( nWhich ); else { SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get pool default" ); pRet = 0; } return pRet; } // ----------------------------------------------------------------------- inline FASTBOOL SfxItemPool::IsItemFlag_Impl( sal_uInt16 nPos, sal_uInt16 nFlag ) const { sal_uInt16 nItemFlag = pItemInfos[nPos]._nFlags; return nFlag == (nItemFlag & nFlag); } // ----------------------------------------------------------------------- FASTBOOL SfxItemPool::IsItemFlag( sal_uInt16 nWhich, sal_uInt16 nFlag ) const { for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary ) { if ( pPool->IsInRange(nWhich) ) return pPool->IsItemFlag_Impl( pPool->GetIndex_Impl(nWhich), nFlag); } DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" ); return sal_False; } // ----------------------------------------------------------------------- SfxBroadcaster& SfxItemPool::BC() { return pImp->aBC; } // ----------------------------------------------------------------------- SfxItemPool::SfxItemPool ( UniString const & rName, /* Name des Pools zur Idetifikation im File-Format */ sal_uInt16 nStartWhich, /* erste Which-Id des Pools */ sal_uInt16 nEndWhich, /* letzte Which-Id des Pools */ #ifdef TF_POOLABLE const SfxItemInfo* pInfos, /* SID-Map und Item-Flags */ #endif SfxPoolItem** pDefaults, /* Pointer auf statische Defaults, wird direkt vom Pool referenziert, jedoch kein Eigent"umer"ubergang */ #ifndef TF_POOLABLE sal_uInt16* pSlotIdArray, /* Zuordnung von Slot-Ids zu Which-Ids */ #endif FASTBOOL bLoadRefCounts /* Ref-Counts mitladen oder auf 1 setzen */ ) /* [Beschreibung] Der im Normalfall verwendete Konstruktor der Klasse SfxItemPool. Es wird eine SfxItemPool-Instanz initialisiert, die Items im b"undigen Which-Bereich von 'nStartWhich' bis 'nEndWhich' verwalten kann. F"ur jede dieser Which-Ids mu\s ein statischer Default im Array 'pDefaults' vorhanden sein, die dort beginnend mit einem mit der Which-Id 'nStartWhich' nach Which-Ids sortiert aufeinanderfolgend eingetragen sein m"ussen. 'pItemInfos' ist ein identisch angeordnetes Array von USHORTs, die Slot-Ids darstellen und Flags. Die Slot-Ids k"onnen 0 sein, wenn die betreffenden Items ausschlie\slich in der Core verwendet werden. "Uber die Flags kann z.B. bestimmt werden, ob Value-Sharing (SFX_ITEM_POOLABLE) stattfinden soll. [Anmerkung] Wenn der Pool s enthalten soll, k"onnen im Konstruktor noch keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich mit geschehen. [Querverweise] */ : aName(rName), nStart(nStartWhich), nEnd(nEndWhich), #ifdef TF_POOLABLE pItemInfos(pInfos), #else pSlotIds(pSlotIdArray), #endif pImp( new SfxItemPool_Impl( nStart, nEnd ) ), ppStaticDefaults(0), ppPoolDefaults(new SfxPoolItem* [ nEndWhich - nStartWhich + 1]), pSecondary(0), pMaster(this), _pPoolRanges( 0 ), bPersistentRefCounts(bLoadRefCounts), maSfxItemPoolUsers() { DBG_CTOR(SfxItemPool, 0); DBG_ASSERT(nStart, "Start-Which-Id must be greater 0" ); pImp->eDefMetric = SFX_MAPUNIT_TWIP; pImp->nVersion = 0; pImp->bStreaming = sal_False; pImp->nLoadingVersion = 0; pImp->nInitRefCount = 1; pImp->nVerStart = nStart; pImp->nVerEnd = nEnd; pImp->bInSetItem = sal_False; pImp->nStoringStart = nStartWhich; pImp->nStoringEnd = nEndWhich; memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1)); if ( pDefaults ) SetDefaults(pDefaults); } // ----------------------------------------------------------------------- SfxItemPool::SfxItemPool ( const SfxItemPool& rPool, // von dieser Instanz kopieren sal_Bool bCloneStaticDefaults /* sal_True statische Defaults kopieren sal_False statische Defaults "ubernehehmen */ ) /* [Beschreibung] Copy-Konstruktor der Klasse SfxItemPool. [Querverweise] */ : aName(rPool.aName), nStart(rPool.nStart), nEnd(rPool.nEnd), #ifdef TF_POOLABLE pItemInfos(rPool.pItemInfos), #else pSlotIds(rPool.pSlotIds), #endif pImp( new SfxItemPool_Impl( nStart, nEnd ) ), ppStaticDefaults(0), ppPoolDefaults(new SfxPoolItem* [ nEnd - nStart + 1]), pSecondary(0), pMaster(this), _pPoolRanges( 0 ), bPersistentRefCounts(rPool.bPersistentRefCounts ), maSfxItemPoolUsers() { DBG_CTOR(SfxItemPool, 0); pImp->eDefMetric = rPool.pImp->eDefMetric; pImp->nVersion = rPool.pImp->nVersion; pImp->bStreaming = sal_False; pImp->nLoadingVersion = 0; pImp->nInitRefCount = 1; pImp->nVerStart = rPool.pImp->nVerStart; pImp->nVerEnd = rPool.pImp->nVerEnd; pImp->bInSetItem = sal_False; pImp->nStoringStart = nStart; pImp->nStoringEnd = nEnd; memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1)); // Static Defaults "ubernehmen if ( bCloneStaticDefaults ) { SfxPoolItem **ppDefaults = new SfxPoolItem*[nEnd-nStart+1]; for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n ) { (*( ppDefaults + n )) = (*( rPool.ppStaticDefaults + n ))->Clone(this); (*( ppDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT ); } SetDefaults( ppDefaults ); } else SetDefaults( rPool.ppStaticDefaults ); // Pool Defaults kopieren for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n ) if ( (*( rPool.ppPoolDefaults + n )) ) { (*( ppPoolDefaults + n )) = (*( rPool.ppPoolDefaults + n ))->Clone(this); (*( ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT ); } // Copy Version-Map for ( size_t nVer = 0; nVer < rPool.pImp->aVersions.size(); ++nVer ) { const SfxPoolVersion_ImplPtr pOld = rPool.pImp->aVersions[nVer]; SfxPoolVersion_ImplPtr pNew = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl( *pOld ) ); pImp->aVersions.push_back( pNew ); } // Verkettung wiederherstellen if ( rPool.pSecondary ) SetSecondaryPool( rPool.pSecondary->Clone() ); } // ----------------------------------------------------------------------- void SfxItemPool::SetDefaults( SfxPoolItem **pDefaults ) { DBG_CHKTHIS(SfxItemPool, 0); DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." ); DBG_ASSERT( !ppStaticDefaults, "habe schon defaults" ); ppStaticDefaults = pDefaults; //! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT ) //! geht wohl nicht im Zshg mit SetItems, die hinten stehen { DBG_ASSERT( (*ppStaticDefaults)->GetRefCount() == 0 || IsDefaultItem( (*ppStaticDefaults) ), "das sind keine statics" ); for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n ) { SFX_ASSERT( (*( ppStaticDefaults + n ))->Which() == n + nStart, n + nStart, "static defaults not sorted" ); (*( ppStaticDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT ); DBG_ASSERT( !(pImp->ppPoolItems[n]), "defaults with setitems with items?!" ); } } } // ----------------------------------------------------------------------- void SfxItemPool::ReleaseDefaults ( sal_Bool bDelete /* sal_True l"oscht sowohl das Array als auch die einzelnen statischen Defaults sal_False l"oscht weder das Array noch die einzelnen statischen Defaults */ ) /* [Beschreibung] Gibt die statischen Defaults der betreffenden SfxItemPool-Instanz frei und l"oscht ggf. die statischen Defaults. Nach Aufruf dieser Methode darf die SfxItemPool-Instanz nicht mehr verwendet werden, einzig ist der Aufruf des Destruktors zu"lassig. */ { DBG_ASSERT( ppStaticDefaults, "keine Arme keine Kekse" ); ReleaseDefaults( ppStaticDefaults, nEnd - nStart + 1, bDelete ); // KSO (22.10.98): ppStaticDefaults zeigt auf geloeschten Speicher, // wenn bDelete == sal_True. if ( bDelete ) ppStaticDefaults = 0; } // ----------------------------------------------------------------------- void SfxItemPool::ReleaseDefaults ( SfxPoolItem** pDefaults, /* freizugebende statische Defaults */ sal_uInt16 nCount, /* Anzahl der statischen Defaults */ sal_Bool bDelete /* sal_True l"oscht sowohl das Array als auch die einzelnen statischen Defaults sal_False l"oscht weder das Array noch die einzelnen statischen Defaults */ ) /* [Beschreibung] Gibt die angegebenen statischen Defaults frei und l"oscht ggf. die statischen Defaults. Diese Methode darf erst nach Zerst"orung aller SfxItemPool-Instanzen, welche die angegebenen statischen Defaults 'pDefault' verwenden, aufgerufen werden. */ { DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." ); for ( sal_uInt16 n = 0; n < nCount; ++n ) { SFX_ASSERT( IsStaticDefaultItem( *(pDefaults+n) ), n, "das ist kein static-default" ); (*( pDefaults + n ))->SetRefCount( 0 ); if ( bDelete ) { delete *( pDefaults + n ); *(pDefaults + n) = 0; } } if ( bDelete ) { delete[] pDefaults; pDefaults = 0; } } // ----------------------------------------------------------------------- SfxItemPool::~SfxItemPool() { DBG_DTOR(SfxItemPool, 0); DBG_ASSERT( pMaster == this, "destroying active Secondary-Pool" ); if ( pImp->ppPoolItems && ppPoolDefaults ) Delete(); delete[] _pPoolRanges; delete pImp; } void SfxItemPool::Free(SfxItemPool* pPool) { if(pPool) { // tell all the registered SfxItemPoolUsers that the pool is in destruction SfxItemPoolUserVector aListCopy(pPool->maSfxItemPoolUsers.begin(), pPool->maSfxItemPoolUsers.end()); for(SfxItemPoolUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++) { SfxItemPoolUser* pSfxItemPoolUser = *aIterator; DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)"); pSfxItemPoolUser->ObjectInDestruction(*pPool); } // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser() // when they get called from ObjectInDestruction(). pPool->maSfxItemPoolUsers.clear(); // delete pool delete pPool; } } // ----------------------------------------------------------------------- void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool ) { // ggf. an abgeh"angten Pools den Master zur"ucksetzen if ( pSecondary ) { #ifdef DBG_UTIL HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) if ( ppStaticDefaults ) { // Delete() ist noch nicht gelaufen? if ( pImp->ppPoolItems && pSecondary->pImp->ppPoolItems ) { // hat der master SetItems? sal_Bool bHasSetItems = sal_False; for ( sal_uInt16 i = 0; !bHasSetItems && i < nEnd-nStart; ++i ) bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem); // abgehaengte Pools muessen leer sein sal_Bool bOK = bHasSetItems; for ( sal_uInt16 n = 0; bOK && n <= pSecondary->nEnd - pSecondary->nStart; ++n ) { SfxPoolItemArray_Impl** ppItemArr = pSecondary->pImp->ppPoolItems + n; if ( *ppItemArr ) { SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); for( size_t i = (*ppItemArr)->size(); i; ++ppHtArr, --i ) if ( !(*ppHtArr) ) { DBG_ERROR( "old secondary pool must be empty" ); bOK = sal_False; break; } } } } } #endif pSecondary->pMaster = pSecondary; for ( SfxItemPool *p = pSecondary->pSecondary; p; p = p->pSecondary ) p->pMaster = pSecondary; } // ggf. den Master der neuen Secondary-Pools setzen DBG_ASSERT( !pPool || pPool->pMaster == pPool, "Secondary tanzt auf zwei Hochzeiten " ); SfxItemPool *pNewMaster = pMaster ? pMaster : this; for ( SfxItemPool *p = pPool; p; p = p->pSecondary ) p->pMaster = pNewMaster; // neuen Secondary-Pool merken pSecondary = pPool; } // ----------------------------------------------------------------------- SfxMapUnit SfxItemPool::GetMetric( sal_uInt16 ) const { DBG_CHKTHIS(SfxItemPool, 0); return pImp->eDefMetric; } // ----------------------------------------------------------------------- void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric ) { DBG_CHKTHIS(SfxItemPool, 0); pImp->eDefMetric = eNewMetric; } // ----------------------------------------------------------------------- SfxItemPresentation SfxItemPool::GetPresentation ( const SfxPoolItem& rItem, /* IN: , dessen textuelle Wert-Darstellung geliefert werden soll */ SfxItemPresentation ePresent, /* IN: gew"unschte Art der Darstellung; siehe */ SfxMapUnit eMetric, /* IN: gew"unschte Ma\seinheit der Darstellung */ XubString& rText, /* OUT: textuelle Darstellung von 'rItem' */ const IntlWrapper * pIntlWrapper ) const /* [Beschreibung] "Uber diese virtuelle Methode k"onnen textuelle Darstellungen der von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems angefordert werden. In Ableitungen sollte diese Methode "uberladen werden und auf SfxPoolItems reagiert werden, die bei keine vollst"andige Information liefern k"onnen. Die Basisklasse liefert die unver"anderte Presentation von 'rItem'. */ { DBG_CHKTHIS(SfxItemPool, 0); return rItem.GetPresentation( ePresent, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper ); } // ----------------------------------------------------------------------- SfxItemPool* SfxItemPool::Clone() const { DBG_CHKTHIS(SfxItemPool, 0); SfxItemPool *pPool = new SfxItemPool( *this ); return pPool; } // ---------------------------------------------------------------------- void SfxItemPool::Delete() { DBG_CHKTHIS(SfxItemPool, 0); // schon deleted? if ( !pImp->ppPoolItems || !ppPoolDefaults ) return; // z.B. laufenden Requests bescheidsagen pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) ); //MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems. //Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt. SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; SfxPoolItem** ppDefaultItem = ppPoolDefaults; SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults; sal_uInt16 nArrCnt; //Erst die SetItems abraeumen HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) if ( ppStaticDefaults ) { for ( nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem ) { // KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer // von SfxItemPool abgeleiteten Klasse bereits geloescht worden // sein! -> CHAOS Itempool if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) ) { if ( *ppItemArr ) { SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) if (*ppHtArr) { #ifdef DBG_UTIL ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); #endif delete *ppHtArr; } DELETEZ( *ppItemArr ); } if ( *ppDefaultItem ) { #ifdef DBG_UTIL SetRefCount( **ppDefaultItem, 0 ); #endif DELETEZ( *ppDefaultItem ); } } } } ppItemArr = pImp->ppPoolItems; ppDefaultItem = ppPoolDefaults; //Jetzt die 'einfachen' Items for ( nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr, ++ppDefaultItem ) { if ( *ppItemArr ) { SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) if (*ppHtArr) { #ifdef DBG_UTIL ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); #endif delete *ppHtArr; } delete *ppItemArr; } if ( *ppDefaultItem ) { #ifdef DBG_UTIL SetRefCount( **ppDefaultItem, 0 ); #endif delete *ppDefaultItem; } } pImp->DeleteItems(); delete[] ppPoolDefaults; ppPoolDefaults = 0; } // ---------------------------------------------------------------------- void SfxItemPool::Cleanup() { DBG_CHKTHIS(SfxItemPool, 0); //MA 16. Apr. 97: siehe ::Delete() SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; SfxPoolItem** ppDefaultItem = ppPoolDefaults; SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults; sal_uInt16 nArrCnt; HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) if ( ppStaticDefaults ) //HACK fuer Image, dort gibt es keine Statics!! { for ( nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem ) { //Fuer jedes Item gibt es entweder ein Default oder ein static Default! if ( *ppItemArr && ((*ppDefaultItem && (*ppDefaultItem)->ISA(SfxSetItem)) || (*ppStaticDefaultItem)->ISA(SfxSetItem)) ) { SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) { DELETEZ(*ppHtArr); } } } } ppItemArr = pImp->ppPoolItems; for ( nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr ) { if ( *ppItemArr ) { SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) DELETEZ( *ppHtArr ); } } } // ---------------------------------------------------------------------- void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem) { DBG_CHKTHIS(SfxItemPool, 0); if ( IsInRange(rItem.Which()) ) { SfxPoolItem **ppOldDefault = ppPoolDefaults + GetIndex_Impl(rItem.Which()); SfxPoolItem *pNewDefault = rItem.Clone(this); pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT); if ( *ppOldDefault ) { (*ppOldDefault)->SetRefCount(0); DELETEZ( *ppOldDefault ); } *ppOldDefault = pNewDefault; } else if ( pSecondary ) pSecondary->SetPoolDefaultItem(rItem); else { SFX_ASSERT( 0, rItem.Which(), "unknown Which-Id - cannot set pool default" ); } } /* * Resets the default of the given back to the static default. * If a pool default exists it is removed. */ void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId ) { DBG_CHKTHIS(SfxItemPool, 0); if ( IsInRange(nWhichId) ) { SfxPoolItem **ppOldDefault = ppPoolDefaults + GetIndex_Impl( nWhichId ); if ( *ppOldDefault ) { (*ppOldDefault)->SetRefCount(0); DELETEZ( *ppOldDefault ); } } else if ( pSecondary ) pSecondary->ResetPoolDefaultItem(nWhichId); else { SFX_ASSERT( 0, nWhichId, "unknown Which-Id - cannot set pool default" ); } } // ----------------------------------------------------------------------- const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich ) { DBG_ASSERT( !rItem.ISA(SfxSetItem) || 0 != &((const SfxSetItem&)rItem).GetItemSet(), "SetItem without ItemSet" ); DBG_CHKTHIS(SfxItemPool, 0); if ( 0 == nWhich ) nWhich = rItem.Which(); // richtigen Secondary-Pool finden sal_Bool bSID = nWhich > SFX_WHICH_MAX; if ( !bSID && !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->Put( rItem, nWhich ); DBG_ERROR( "unknown Which-Id - cannot put item" ); } // SID oder nicht poolable (neue Definition)? sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich); if ( USHRT_MAX == nIndex || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) ) { SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich || !IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE, nWhich, "ein nicht Pool-Item ist Default?!" ); SfxPoolItem *pPoolItem = rItem.Clone(pMaster); pPoolItem->SetWhich(nWhich); AddRef( *pPoolItem ); return *pPoolItem; } SFX_ASSERT( rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich, "SFxItemPool: wrong item type in Put" ); SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems + nIndex; if( !*ppItemArr ) *ppItemArr = new SfxPoolItemArray_Impl; SfxPoolItemArrayBase_Impl::iterator ppFree; sal_Bool ppFreeIsSet = sal_False; SfxPoolItemArrayBase_Impl::iterator ppHtArray = (*ppItemArr)->begin(); if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) ) { // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein if ( IsPooledItem(&rItem) ) { // 1. Schleife: teste ob der Pointer vorhanden ist. for( size_t n = (*ppItemArr)->size(); n; ++ppHtArray, --n ) if( &rItem == (*ppHtArray) ) { AddRef( **ppHtArray ); return **ppHtArray; } } // 2. Schleife: dann muessen eben die Attribute verglichen werden size_t n; for ( n = (*ppItemArr)->size(), ppHtArray = (*ppItemArr)->begin(); n; ++ppHtArray, --n ) { if ( *ppHtArray ) { if( **ppHtArray == rItem ) { AddRef( **ppHtArray ); return **ppHtArray; } } else if ( ppFreeIsSet == sal_False ) { ppFree = ppHtArray; ppFreeIsSet = sal_True; } } } else { // freien Platz suchen SfxPoolItemArrayBase_Impl::iterator ppHtArr; size_t n, nCount = (*ppItemArr)->size(); for ( n = (*ppItemArr)->nFirstFree, ppHtArr = (*ppItemArr)->begin() + n; n < nCount; ++ppHtArr, ++n ) if ( !*ppHtArr ) { ppFree = ppHtArr; ppFreeIsSet = sal_True; break; } // naechstmoeglichen freien Platz merken (*ppItemArr)->nFirstFree = n; } // nicht vorhanden, also im PtrArray eintragen SfxPoolItem* pNewItem = rItem.Clone(pMaster); pNewItem->SetWhich(nWhich); #ifdef DBG_UTIL SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" ) #ifdef TF_POOLABLE if ( !rItem.ISA(SfxSetItem) ) { SFX_ASSERT( !IsItemFlag(nWhich, SFX_ITEM_POOLABLE) || rItem == *pNewItem, nWhich, "unequal items in Put(): no operator==?" ); SFX_ASSERT( !IsItemFlag(*pNewItem, SFX_ITEM_POOLABLE) || *pNewItem == rItem, nWhich, "unequal items in Put(): no operator==?" ); } #endif #endif AddRef( *pNewItem, pImp->nInitRefCount ); SfxPoolItem* pTemp = pNewItem; if ( ppFreeIsSet == sal_False ) (*ppItemArr)->push_back( pTemp ); else { DBG_ASSERT( *ppFree == 0, "using surrogate in use" ); *ppFree = pNewItem; } return *pNewItem; } // ----------------------------------------------------------------------- void SfxItemPool::Remove( const SfxPoolItem& rItem ) { DBG_CHKTHIS(SfxItemPool, 0); DBG_ASSERT( !rItem.ISA(SfxSetItem) || 0 != &((const SfxSetItem&)rItem).GetItemSet(), "SetItem without ItemSet" ); SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(), "wo kommt denn hier ein Pool-Default her" ); // richtigen Secondary-Pool finden const sal_uInt16 nWhich = rItem.Which(); sal_Bool bSID = nWhich > SFX_WHICH_MAX; if ( !bSID && !IsInRange(nWhich) ) { if ( pSecondary ) { pSecondary->Remove( rItem ); return; } DBG_ERROR( "unknown Which-Id - cannot remove item" ); } // SID oder nicht poolable (neue Definition)? sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich); if ( bSID || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) ) { SFX_ASSERT( USHRT_MAX != nIndex || !IsDefaultItem(&rItem), rItem.Which(), "ein nicht Pool-Item ist Default?!" ); if ( 0 == ReleaseRef(rItem) ) { SfxPoolItem *pItem = &(SfxPoolItem &)rItem; delete pItem; } return; } SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove unmoeglich" ); // statische Defaults sind eben einfach da if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT && &rItem == *( ppStaticDefaults + GetIndex_Impl(nWhich) ) ) return; // Item im eigenen Pool suchen SfxPoolItemArray_Impl** ppItemArr = (pImp->ppPoolItems + nIndex); SFX_ASSERT( *ppItemArr, rItem.Which(), "removing Item not in Pool" ); SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); for( size_t n = (*ppItemArr)->size(); n; ++ppHtArr, --n ) if( *ppHtArr == &rItem ) { if ( (*ppHtArr)->GetRefCount() ) //! ReleaseRef( **ppHtArr ); else { SFX_ASSERT( 0, rItem.Which(), "removing Item without ref" ); SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr ); } // ggf. kleinstmoegliche freie Position merken size_t nPos = (*ppItemArr)->size() - n; if ( (*ppItemArr)->nFirstFree > nPos ) (*ppItemArr)->nFirstFree = nPos; //! MI: Hack, solange wir das Problem mit dem Outliner haben //! siehe anderes MI-REF if ( 0 == (*ppHtArr)->GetRefCount() && nWhich < 4000 ) DELETEZ(*ppHtArr); return; } // nicht vorhanden SFX_ASSERT( 0, rItem.Which(), "removing Item not in Pool" ); SFX_TRACE( "to be removed, but not in pool: ", &rItem ); } // ----------------------------------------------------------------------- const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const { DBG_CHKTHIS(SfxItemPool, 0); if ( !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->GetDefaultItem( nWhich ); SFX_ASSERT( 0, nWhich, "unknown which - dont ask me for defaults" ); } DBG_ASSERT( ppStaticDefaults, "no defaults known - dont ask me for defaults" ); sal_uInt16 nPos = GetIndex_Impl(nWhich); SfxPoolItem *pDefault = *(ppPoolDefaults + nPos); if ( pDefault ) return *pDefault; return **(ppStaticDefaults + nPos); } // ----------------------------------------------------------------------- void SfxItemPool::FreezeIdRanges() /* [Beschreibung] This method should be called at the master pool, when all secondary pools are appended to it. It calculates the ranges of 'which-ids' for fast construction of item-sets, which contains all 'which-ids'. */ { FillItemIdRanges_Impl( _pPoolRanges ); } // ----------------------------------------------------------------------- void SfxItemPool::FillItemIdRanges_Impl( sal_uInt16*& pWhichRanges ) const { DBG_CHKTHIS(SfxItemPool, 0); DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" ); const SfxItemPool *pPool; sal_uInt16 nLevel = 0; for( pPool = this; pPool; pPool = pPool->pSecondary ) ++nLevel; pWhichRanges = new sal_uInt16[ 2*nLevel + 1 ]; nLevel = 0; for( pPool = this; pPool; pPool = pPool->pSecondary ) { *(pWhichRanges+(nLevel++)) = pPool->nStart; *(pWhichRanges+(nLevel++)) = pPool->nEnd; *(pWhichRanges+nLevel) = 0; } } // ----------------------------------------------------------------------- const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) const { DBG_CHKTHIS(SfxItemPool, 0); if ( !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->GetItem2( nWhich, nOfst ); SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); return 0; } // dflt-Attribut? if ( nOfst == SFX_ITEMS_DEFAULT ) return *(ppStaticDefaults + GetIndex_Impl(nWhich)); SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); if( pItemArr && nOfst < pItemArr->size() ) return (*pItemArr)[nOfst]; return 0; } // ----------------------------------------------------------------------- sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const { DBG_CHKTHIS(SfxItemPool, 0); if ( !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->GetItemCount2( nWhich ); SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); return 0; } SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); if ( pItemArr ) return pItemArr->size(); return 0; } // ----------------------------------------------------------------------- sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const { if ( !IsSlot(nSlotId) ) return nSlotId; #ifdef TF_POOLABLE sal_uInt16 nCount = nEnd - nStart + 1; for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) if ( pItemInfos[nOfs]._nSID == nSlotId ) return nOfs + nStart; #else if ( pSlotIds ) { sal_uInt16 nCount = nEnd - nStart + 1; for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) if ( pSlotIds[nOfs] == nSlotId ) return nOfs + nStart; } #endif if ( pSecondary && bDeep ) return pSecondary->GetWhich(nSlotId); return nSlotId; } // ----------------------------------------------------------------------- sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const { if ( !IsWhich(nWhich) ) return nWhich; if ( !IsInRange( nWhich ) ) { if ( pSecondary && bDeep ) return pSecondary->GetSlotId(nWhich); SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" ); return 0; } #ifdef TF_POOLABLE sal_uInt16 nSID = pItemInfos[nWhich - nStart]._nSID; return nSID ? nSID : nWhich; #else else if ( pSlotIds ) return pSlotIds[nWhich - nStart]; return nWhich; #endif } // ----------------------------------------------------------------------- sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const { if ( !IsSlot(nSlotId) ) return 0; #ifdef TF_POOLABLE sal_uInt16 nCount = nEnd - nStart + 1; for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) if ( pItemInfos[nOfs]._nSID == nSlotId ) return nOfs + nStart; #else if ( pSlotIds ) { sal_uInt16 nCount = nEnd - nStart + 1; for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) if ( pSlotIds[nOfs] == nSlotId ) return nOfs + nStart; } #endif if ( pSecondary && bDeep ) return pSecondary->GetTrueWhich(nSlotId); return 0; } // ----------------------------------------------------------------------- sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const { if ( !IsWhich(nWhich) ) return 0; if ( !IsInRange( nWhich ) ) { if ( pSecondary && bDeep ) return pSecondary->GetTrueSlotId(nWhich); SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" ); return 0; } #ifdef TF_POOLABLE return pItemInfos[nWhich - nStart]._nSID; #else else if ( pSlotIds ) return pSlotIds[nWhich - nStart]; else return 0; #endif } // ----------------------------------------------------------------------- void SfxItemPool::SetFileFormatVersion( sal_uInt16 nFileFormatVersion ) /* [Description] You must call this function to set the file format version after concatenating your secondary-pools but before you store any pool, itemset or item. Only set the version at the master pool, never at any secondary pool. */ { DBG_ASSERT( this == pMaster, "SfxItemPool::SetFileFormatVersion() but not a master pool" ); for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary ) pPool->_nFileFormatVersion = nFileFormatVersion; }