/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svl.hxx" #include #include #include #include "whassert.hxx" #include #include #include "poolio.hxx" #include // STATIC DATA ----------------------------------------------------------- //======================================================================== SV_IMPL_PTRARR( SfxPoolVersionArr_Impl, SfxPoolVersion_Impl* ); //======================================================================== 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( USHORT 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 bool SfxItemPool::IsItemFlag_Impl( USHORT nPos, USHORT nFlag ) const { USHORT nItemFlag = pItemInfos[nPos]._nFlags; return nFlag == (nItemFlag & nFlag); } // ----------------------------------------------------------------------- bool SfxItemPool::IsItemFlag( USHORT nWhich, USHORT 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 FALSE; } // ----------------------------------------------------------------------- SfxBroadcaster& SfxItemPool::BC() { return pImp->aBC; } // ----------------------------------------------------------------------- SfxItemPool::SfxItemPool ( UniString const & rName, /* Name des Pools zur Idetifikation im File-Format */ USHORT nStartWhich, /* erste Which-Id des Pools */ USHORT 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 USHORT* pSlotIdArray, /* Zuordnung von Slot-Ids zu Which-Ids */ #endif bool 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 = FALSE; pImp->nLoadingVersion = 0; pImp->nInitRefCount = 1; pImp->nVerStart = nStart; pImp->nVerEnd = nEnd; pImp->bInSetItem = 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 BOOL bCloneStaticDefaults /* TRUE statische Defaults kopieren 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 = FALSE; pImp->nLoadingVersion = 0; pImp->nInitRefCount = 1; pImp->nVerStart = rPool.pImp->nVerStart; pImp->nVerEnd = rPool.pImp->nVerEnd; pImp->bInSetItem = 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 ( USHORT 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 ( USHORT n = 0; n <= nEnd - nStart; ++n ) if ( (*( rPool.ppPoolDefaults + n )) ) { (*( ppPoolDefaults + n )) = (*( rPool.ppPoolDefaults + n ))->Clone(this); (*( ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT ); } // Version-Map kopieren USHORT nVerCount = rPool.pImp->aVersions.Count(); for ( USHORT nVer = 0; nVer < nVerCount; ++nVer ) { const SfxPoolVersion_Impl *pOld = rPool.pImp->aVersions.GetObject(nVer); const SfxPoolVersion_Impl *pNew = new SfxPoolVersion_Impl( *pOld ); pImp->aVersions.Insert( pNew, nVer ); } // 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 ( USHORT 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 ( BOOL bDelete /* TRUE l"oscht sowohl das Array als auch die einzelnen statischen Defaults 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 == TRUE. if ( bDelete ) ppStaticDefaults = 0; } // ----------------------------------------------------------------------- void SfxItemPool::ReleaseDefaults ( SfxPoolItem** pDefaults, /* freizugebende statische Defaults */ USHORT nCount, /* Anzahl der statischen Defaults */ BOOL bDelete /* TRUE l"oscht sowohl das Array als auch die einzelnen statischen Defaults 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 ( USHORT 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? BOOL bHasSetItems = FALSE; for ( USHORT i = 0; !bHasSetItems && i < nEnd-nStart; ++i ) bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem); // abgehaengte Pools muessen leer sein BOOL bOK = bHasSetItems; for ( USHORT n = 0; bOK && n <= pSecondary->nEnd - pSecondary->nStart; ++n ) { SfxPoolItemArray_Impl** ppItemArr = pSecondary->pImp->ppPoolItems + n; if ( *ppItemArr ) { SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); for( USHORT i = (*ppItemArr)->Count(); i; ++ppHtArr, --i ) if ( !(*ppHtArr) ) { OSL_FAIL( "old secondary pool must be empty" ); bOK = 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( USHORT ) 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; USHORT 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 ) { SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); for ( USHORT n = (*ppItemArr)->Count(); 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 ) { SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); for ( USHORT n = (*ppItemArr)->Count(); 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; USHORT 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)) ) { SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); for ( USHORT n = (*ppItemArr)->Count(); n; --n, ++ppHtArr ) if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) { DELETEZ(*ppHtArr); } } } } ppItemArr = pImp->ppPoolItems; for ( nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr ) { if ( *ppItemArr ) { SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); for ( USHORT n = (*ppItemArr)->Count(); 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( USHORT 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, USHORT 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 BOOL bSID = nWhich > SFX_WHICH_MAX; if ( !bSID && !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->Put( rItem, nWhich ); OSL_FAIL( "unknown Which-Id - cannot put item" ); } // SID oder nicht poolable (neue Definition)? USHORT 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; SfxPoolItem **ppFree = 0; SfxPoolItem** ppHtArray = (SfxPoolItem**)(*ppItemArr)->GetData(); 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( USHORT n = (*ppItemArr)->Count(); n; ++ppHtArray, --n ) if( &rItem == (*ppHtArray) ) { AddRef( **ppHtArray ); return **ppHtArray; } } // 2. Schleife: dann muessen eben die Attribute verglichen werden USHORT n; for ( n = (*ppItemArr)->Count(), ppHtArray = (SfxPoolItem**)(*ppItemArr)->GetData(); n; ++ppHtArray, --n ) { if ( *ppHtArray ) { if( **ppHtArray == rItem ) { AddRef( **ppHtArray ); return **ppHtArray; } } else if ( !ppFree ) ppFree = ppHtArray; } } else { // freien Platz suchen SfxPoolItem** ppHtArr; USHORT n, nCount = (*ppItemArr)->Count(); for ( n = (*ppItemArr)->nFirstFree, ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData() + n; n < nCount; ++ppHtArr, ++n ) if ( !*ppHtArr ) { ppFree = ppHtArr; 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 ); const SfxPoolItem* pTemp = pNewItem; if ( !ppFree ) (*ppItemArr)->Insert( pTemp, (*ppItemArr)->Count() ); 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 USHORT nWhich = rItem.Which(); BOOL bSID = nWhich > SFX_WHICH_MAX; if ( !bSID && !IsInRange(nWhich) ) { if ( pSecondary ) { pSecondary->Remove( rItem ); return; } OSL_FAIL( "unknown Which-Id - cannot remove item" ); } // SID oder nicht poolable (neue Definition)? USHORT 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" ); SfxPoolItem** ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); for( USHORT n = (*ppItemArr)->Count(); 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 USHORT nPos = (*ppItemArr)->Count() - 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( USHORT 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" ); USHORT 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( USHORT*& pWhichRanges ) const { DBG_CHKTHIS(SfxItemPool, 0); DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" ); const SfxItemPool *pPool; USHORT nLevel = 0; for( pPool = this; pPool; pPool = pPool->pSecondary ) ++nLevel; pWhichRanges = new USHORT[ 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::GetItem(USHORT nWhich, USHORT nOfst) const { DBG_CHKTHIS(SfxItemPool, 0); if ( !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->GetItem( nWhich, nOfst ); SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); return 0; } // dflt-Attribut? if ( nOfst == SFX_ITEMS_STATICDEFAULT ) return *(ppStaticDefaults + GetIndex_Impl(nWhich)); SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); if( pItemArr && nOfst < pItemArr->Count() ) return (*pItemArr)[nOfst]; return 0; } // ----------------------------------------------------------------------- USHORT SfxItemPool::GetItemCount(USHORT nWhich) const { DBG_CHKTHIS(SfxItemPool, 0); if ( !IsInRange(nWhich) ) { if ( pSecondary ) return pSecondary->GetItemCount( 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->Count(); return 0; } // ----------------------------------------------------------------------- USHORT SfxItemPool::GetWhich( USHORT nSlotId, BOOL bDeep ) const { if ( !IsSlot(nSlotId) ) return nSlotId; #ifdef TF_POOLABLE USHORT nCount = nEnd - nStart + 1; for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs ) if ( pItemInfos[nOfs]._nSID == nSlotId ) return nOfs + nStart; #else if ( pSlotIds ) { USHORT nCount = nEnd - nStart + 1; for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs ) if ( pSlotIds[nOfs] == nSlotId ) return nOfs + nStart; } #endif if ( pSecondary && bDeep ) return pSecondary->GetWhich(nSlotId); return nSlotId; } // ----------------------------------------------------------------------- USHORT SfxItemPool::GetSlotId( USHORT nWhich, 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 USHORT nSID = pItemInfos[nWhich - nStart]._nSID; return nSID ? nSID : nWhich; #else else if ( pSlotIds ) return pSlotIds[nWhich - nStart]; return nWhich; #endif } // ----------------------------------------------------------------------- USHORT SfxItemPool::GetTrueWhich( USHORT nSlotId, BOOL bDeep ) const { if ( !IsSlot(nSlotId) ) return 0; #ifdef TF_POOLABLE USHORT nCount = nEnd - nStart + 1; for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs ) if ( pItemInfos[nOfs]._nSID == nSlotId ) return nOfs + nStart; #else if ( pSlotIds ) { USHORT nCount = nEnd - nStart + 1; for ( USHORT nOfs = 0; nOfs < nCount; ++nOfs ) if ( pSlotIds[nOfs] == nSlotId ) return nOfs + nStart; } #endif if ( pSecondary && bDeep ) return pSecondary->GetTrueWhich(nSlotId); return 0; } // ----------------------------------------------------------------------- USHORT SfxItemPool::GetTrueSlotId( USHORT nWhich, 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( USHORT 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; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */