office-gobmx/svl/source/items/itempool.cxx
2011-08-03 01:54:39 +02:00

1117 lines
35 KiB
C++

/* -*- 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
* <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>
#include <svl/itempool.hxx>
#include "whassert.hxx"
#include <svl/brdcst.hxx>
#include <svl/smplhint.hxx>
#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 bool SfxItemPool::IsItemFlag_Impl( sal_uInt16 nPos, sal_uInt16 nFlag ) const
{
sal_uInt16 nItemFlag = pItemInfos[nPos]._nFlags;
return nFlag == (nItemFlag & nFlag);
}
// -----------------------------------------------------------------------
bool 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
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 <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**,sal_uInt16,sal_Bool)>
<SfxItemPool::ReldaseDefaults(sal_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 = sal_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
sal_Bool bCloneStaticDefaults /* sal_True
statische Defaults kopieren
sal_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 = sal_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 ( 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) )
{
OSL_FAIL( "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: <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;
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::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( 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 );
OSL_FAIL( "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;
}
OSL_FAIL( "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;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */