summaryrefslogtreecommitdiff
path: root/svl/source/items/itempool.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svl/source/items/itempool.cxx')
-rw-r--r--svl/source/items/itempool.cxx1176
1 files changed, 1176 insertions, 0 deletions
diff --git a/svl/source/items/itempool.cxx b/svl/source/items/itempool.cxx
new file mode 100644
index 000000000000..5f34560e8471
--- /dev/null
+++ b/svl/source/items/itempool.cxx
@@ -0,0 +1,1176 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: itempool.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svl.hxx"
+
+#include <string.h>
+#include <stdio.h>
+#ifndef GCC
+#endif
+
+#include <svl/itempool.hxx>
+#include "whassert.hxx"
+#include <svl/brdcst.hxx>
+#include <svl/smplhint.hxx>
+#include "poolio.hxx"
+#include <algorithm>
+
+// 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 FASTBOOL SfxItemPool::IsItemFlag_Impl( USHORT nPos, USHORT nFlag ) const
+{
+ USHORT nItemFlag = pItemInfos[nPos]._nFlags;
+ return nFlag == (nItemFlag & nFlag);
+}
+
+// -----------------------------------------------------------------------
+
+FASTBOOL 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
+ 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 <SfxPoolItem> 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 <SfxSetItem>s enthalten soll, k"onnen im Konstruktor noch
+ keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich
+ mit <SfxItemPool::SetDefaults(SfxItemPool**)> geschehen.
+
+
+ [Querverweise]
+
+ <SfxItemPool::SetDefaults(SfxItemPool**)>
+ <SfxItemPool::ReleaseDefaults(SfxPoolItem**,USHORT,BOOL)>
+ <SfxItemPool::ReldaseDefaults(BOOL)>
+*/
+
+: 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]
+
+ <SfxItemPool::Clone()const>
+*/
+
+: 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) )
+ {
+ DBG_ERROR( "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: <SfxPoolItem>, dessen textuelle
+ Wert-Darstellung geliefert werden
+ soll */
+ SfxItemPresentation ePresent, /* IN: gew"unschte Art der Darstellung;
+ siehe <SfxItemPresentation> */
+ 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 <SfxPoolItem::GetPresentation()const>
+ 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 <Which-Id> 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 );
+ DBG_ERROR( "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;
+ }
+ DBG_ERROR( "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;
+}
+
+