diff --git a/svtools/source/items1/itempool.cxx b/svtools/source/items1/itempool.cxx new file mode 100644 index 000000000000..519fb53466aa --- /dev/null +++ b/svtools/source/items1/itempool.cxx @@ -0,0 +1,1167 @@ +/************************************************************************* + * + * $RCSfile: itempool.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: obo $ $Date: 2005-04-13 11:16:42 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include +#include +#ifndef GCC +#pragma hdrstop +#endif + +#include "itempool.hxx" +#include "whassert.hxx" +#include "brdcst.hxx" +#include "smplhint.hxx" +#include "poolio.hxx" + +// STATIC DATA ----------------------------------------------------------- + + +//======================================================================== + +SV_IMPL_PTRARR( SfxPoolVersionArr_Impl, SfxPoolVersion_Impl* ); + +//======================================================================== + + +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 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) +{ + 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 ) +{ + 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::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: , 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) + { +#ifndef PRODUCT + ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); +#endif + delete *ppHtArr; + } + DELETEZ( *ppItemArr ); + } + if ( *ppDefaultItem ) + { +#ifndef PRODUCT + 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) + { +#ifndef PRODUCT + ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); +#endif + delete *ppHtArr; + } + delete *ppItemArr; + } + if ( *ppDefaultItem ) + { +#ifndef PRODUCT + 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" ); +} + +// ---------------------------------------------------------------------- + +void SfxItemPool::ResetPoolDefaultItem( USHORT nWhichId ) + +/* [Beschreibung] + + Diese Methode setzt den Default f"ur die angegeben zur"uck + auf den statischen Default. Falls ein Pool-Default exisitiert, wird + dieser gel"oscht. +*/ + +{ + 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** ppHtArr = (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; ++ppHtArr, --n ) + if( &rItem == (*ppHtArr) ) + { + AddRef( **ppHtArr ); + return **ppHtArr; + } + } + + // 2. Schleife: dann muessen eben die Attribute verglichen werden + USHORT n; + for ( n = (*ppItemArr)->Count(), ppHtArr = (SfxPoolItem**)(*ppItemArr)->GetData(); + n; ++ppHtArr, --n ) + { + if ( *ppHtArr ) + { + if( **ppHtArr == rItem ) + { + AddRef( **ppHtArr ); + return **ppHtArr; + } + } + else + if ( !ppFree ) + ppFree = ppHtArr; + } + } + 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; +} + + diff --git a/svtools/source/items1/itemset.cxx b/svtools/source/items1/itemset.cxx new file mode 100644 index 000000000000..d9925ac58783 --- /dev/null +++ b/svtools/source/items1/itemset.cxx @@ -0,0 +1,2149 @@ +/************************************************************************* + * + * $RCSfile: itemset.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: obo $ $Date: 2005-04-13 11:17:07 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include + +#if STLPORT_VERSION>=321 +#include +#endif + +#ifndef GCC +#pragma hdrstop +#endif + +#define _SVSTDARR_USHORTS +#define _SVSTDARR_ULONGS + +#include "svstdarr.hxx" +#include "itemset.hxx" +#include "itempool.hxx" +#include "itemiter.hxx" +#include "whiter.hxx" +#include "nranges.hxx" +#include "whassert.hxx" + +#include +#include + +// STATIC DATA ----------------------------------------------------------- + +static const USHORT nInitCount = 10; // einzelne USHORTs => 5 Paare ohne '0' +static ULONG nRangesCopyCount = 0; // wie oft wurden Ranges kopiert + +DBG_NAME(SfxItemSet); + +//======================================================================== + +#define NUMTYPE USHORT +#define SvNums SvUShorts +#define SfxNumRanges SfxUShortRanges +#include "nranges.cxx" +#undef NUMTYPE +#undef SvNums +#undef SfxNumRanges + +#define NUMTYPE ULONG +#define SvNums SvULongs +#define SfxNumRanges SfxULongRanges +#include "nranges.cxx" +#undef NUMTYPE +#undef SvNums +#undef SfxNumRanges + +//======================================================================== + +#ifdef DBG_UTIL + + +const sal_Char *DbgCheckItemSet( const void* pVoid ) +{ + const SfxItemSet *pSet = (const SfxItemSet*) pVoid; + SfxWhichIter aIter( *pSet ); + USHORT nCount = 0, n = 0; + for ( USHORT nWh = aIter.FirstWhich(); nWh; nWh = aIter.NextWhich(), ++n ) + { + const SfxPoolItem *pItem = pSet->_aItems[n]; + if ( pItem ) + { + ++nCount; + DBG_ASSERT( IsInvalidItem(pItem) || + pItem->Which() == 0 || pItem->Which() == nWh, + "SfxItemSet: invalid which-id" ); + DBG_ASSERT( IsInvalidItem(pItem) || !pItem->Which() || + !SfxItemPool::IsWhich(pItem->Which()) || + pSet->GetPool()->IsItemFlag(nWh, SFX_ITEM_NOT_POOLABLE) || + SFX_ITEMS_NULL != pSet->GetPool()->GetSurrogate(pItem), + "SfxItemSet: item in set which is not in pool" ); + } + + } + DBG_ASSERT( pSet->_nCount == nCount, "wrong SfxItemSet::nCount detected" ); + + return 0; +} + +#endif +// ----------------------------------------------------------------------- + +SfxItemSet::SfxItemSet +( + SfxItemPool& rPool, /* der Pool, in dem die SfxPoolItems, + welche in dieses SfxItemSet gelangen, + aufgenommen werden sollen */ + BOOL bTotalRanges /* komplette Pool-Ranges uebernehmen, + muss auf TRUE gesetzt werden */ +) +/* [Beschreibung] + + Konstruktor fuer ein SfxItemSet mit genau den Which-Bereichen, welche + dem angegebenen bekannt sind. + + + [Anmerkung] + + F"ur Sfx-Programmierer ein derart konstruiertes SfxItemSet kann + keinerlei Items mit Slot-Ids als Which-Werte aufnehmen! +*/ + +: _pPool( &rPool ), + _pParent( 0 ), + _nCount( 0 ) +{ + DBG_CTOR(SfxItemSet, DbgCheckItemSet); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); + DBG( _pChildCountCtor; *_pChildCount(this) = 0 ); +// DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000, +// "please use suitable ranges" ); +#if DBG_UTIL +#ifdef SFX_ITEMSET_NO_DEFAULT_CTOR + if ( !bTotalRanges ) + *(int*)0 = 0; // GPF +#endif +#endif + + _pWhichRanges = (USHORT*) _pPool->GetFrozenIdRanges(); + DBG_ASSERT( _pWhichRanges, "don't create ItemSets with full range before FreezeIdRanges()" ); + if ( !_pWhichRanges ) + _pPool->FillItemIdRanges_Impl( _pWhichRanges ); + + const USHORT nSize = TotalCount(); + _aItems = new const SfxPoolItem* [ nSize ]; + memset( (void*) _aItems, 0, nSize * sizeof( SfxPoolItem* ) ); +} + +// ----------------------------------------------------------------------- + +SfxItemSet::SfxItemSet( SfxItemPool& rPool, USHORT nWhich1, USHORT nWhich2 ): + _pPool( &rPool ), + _pParent( 0 ), + _nCount( 0 ) +{ + DBG_CTOR(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( nWhich1 <= nWhich2, "Ungueltiger Bereich" ); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); + DBG( _pChildCountCtor; *_pChildCount(this) = 0 ); + +#ifndef PRODUCT + if( nWhich1 > nWhich2 ) // falls der Bereich + nWhich1 ^= nWhich2 ^= nWhich1 ^= nWhich2; // ungueltig ist swappen +#endif + InitRanges_Impl(nWhich1, nWhich2); +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::InitRanges_Impl(USHORT nWh1, USHORT nWh2) +{ + DBG_CHKTHIS(SfxItemSet, 0); + _pWhichRanges = new USHORT[ 3 ]; + *(_pWhichRanges+0) = nWh1; + *(_pWhichRanges+1) = nWh2; + *(_pWhichRanges+2) = 0; + const USHORT nRg = nWh2 - nWh1 + 1; + _aItems = new const SfxPoolItem* [ nRg ]; + memset( (void*) _aItems, 0, nRg * sizeof( SfxPoolItem* ) ); +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::InitRanges_Impl(va_list pArgs, USHORT nWh1, USHORT nWh2, USHORT nNull) +{ + DBG_CHKTHIS(SfxItemSet, 0); + + USHORT nSize = InitializeRanges_Impl( _pWhichRanges, pArgs, nWh1, nWh2, nNull ); + _aItems = new const SfxPoolItem* [ nSize ]; + memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nSize ); +} + +// ----------------------------------------------------------------------- + +SfxItemSet::SfxItemSet( SfxItemPool& rPool, + USHORT_ARG nWh1, USHORT_ARG nWh2, USHORT_ARG nNull, ... ): + _pPool( &rPool ), + _pParent( 0 ), + _pWhichRanges( 0 ), + _nCount( 0 ) +{ + DBG_CTOR(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" ); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); + DBG( _pChildCountCtor; *_pChildCount(this) = 0 ); + +#ifndef PRODUCT + if( nWh1 > nWh2 ) // falls der Bereich ungueltig ist + nWh1 ^= nWh2 ^= nWh1 ^= nWh2; // swappen +#endif + if(!nNull) + InitRanges_Impl(nWh1, nWh2); + else { + va_list pArgs; + va_start( pArgs, nNull ); + InitRanges_Impl(pArgs, nWh1, nWh2, nNull); + } +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::InitRanges_Impl(const USHORT *pWhichPairTable) +{ + DBG_CHKTHIS(SfxItemSet, 0); + DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount); + + USHORT nCnt = 0; + const USHORT* pPtr = pWhichPairTable; + while( *pPtr ) + { + nCnt += ( *(pPtr+1) - *pPtr ) + 1; + pPtr += 2; + } + + _aItems = new const SfxPoolItem* [ nCnt ]; + memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nCnt ); + + nCnt = pPtr - pWhichPairTable +1; + _pWhichRanges = new USHORT[ nCnt ]; + memcpy( _pWhichRanges, pWhichPairTable, sizeof( USHORT ) * nCnt ); +} + + +// ----------------------------------------------------------------------- + +SfxItemSet::SfxItemSet( SfxItemPool& rPool, const USHORT* pWhichPairTable ): + _pPool( &rPool ), + _pParent( 0 ), + _pWhichRanges(0), + _nCount( 0 ) +{ + DBG_CTOR(SfxItemSet, 0); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); + DBG( _pChildCountCtor; *_pChildCount(this) = 0 ); + + // pWhichPairTable == 0 ist f"ur das SfxAllEnumItemSet + if ( pWhichPairTable ) + InitRanges_Impl(pWhichPairTable); +} + +// ----------------------------------------------------------------------- + +SfxItemSet::SfxItemSet( const SfxItemSet& rASet ): + _pPool( rASet._pPool ), + _pParent( rASet._pParent ), + _nCount( rASet._nCount ) +{ + DBG_CTOR(SfxItemSet, DbgCheckItemSet); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); + DBG( _pChildCountCtor; *_pChildCount(this) = 0 ); + DBG( ++*_pChildCount(_pParent) ); + + // errechne die Anzahl von Attributen + USHORT nCnt = 0; + USHORT* pPtr = rASet._pWhichRanges; + while( *pPtr ) + { + nCnt += ( *(pPtr+1) - *pPtr ) + 1; + pPtr += 2; + } + + _aItems = new const SfxPoolItem* [ nCnt ]; + + // Attribute kopieren + SfxItemArray ppDst = _aItems, ppSrc = rASet._aItems; + for( USHORT n = nCnt; n; --n, ++ppDst, ++ppSrc ) + if ( 0 == *ppSrc || // aktueller Default? + IsInvalidItem(*ppSrc) || // Dont Care? + IsStaticDefaultItem(*ppSrc) ) // nicht zu poolende Defaults + // einfach Pointer kopieren + *ppDst = *ppSrc; + else if ( _pPool->IsItemFlag( **ppSrc, SFX_ITEM_POOLABLE ) ) + { + // einfach Pointer kopieren und Ref-Count erh"ohen + *ppDst = *ppSrc; + ( (SfxPoolItem*) (*ppDst) )->AddRef(); + } + else if ( !(*ppSrc)->Which() ) + *ppDst = (*ppSrc)->Clone(); + else + // !IsPoolable() => via Pool zuweisen + *ppDst = &_pPool->Put( **ppSrc ); + + // dann noch die Which Ranges kopieren + DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount); + nCnt = pPtr - rASet._pWhichRanges+1; + _pWhichRanges = new USHORT[ nCnt ]; + memcpy( _pWhichRanges, rASet._pWhichRanges, sizeof( USHORT ) * nCnt ); +} + +// ----------------------------------------------------------------------- + +SfxItemSet::~SfxItemSet() +{ + DBG_DTOR(SfxItemSet, DbgCheckItemSet); +#ifdef DBG_UTIL + DBG( DBG_ASSERT( 0 == *_pChildCount(this), "SfxItemSet: deleting parent-itemset" ) ) +#endif + + USHORT nCount = TotalCount(); + if( Count() ) + { + SfxItemArray ppFnd = _aItems; + for( USHORT nCnt = nCount; nCnt; --nCnt, ++ppFnd ) + if( *ppFnd && !IsInvalidItem(*ppFnd) ) + { + if( !(*ppFnd)->Which() ) + delete (SfxPoolItem*) *ppFnd; + else { + // noch mehrer Referenzen vorhanden, also nur den + // ReferenzCounter manipulieren + if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) ) + (*ppFnd)->ReleaseRef(); + else + if ( !IsDefaultItem(*ppFnd) ) + // aus dem Pool loeschen + _pPool->Remove( **ppFnd ); + } + } + } + + // FIXME: could be delete[] (SfxPoolItem **)_aItems; + delete[] _aItems; + if ( _pWhichRanges != _pPool->GetFrozenIdRanges() ) + delete[] _pWhichRanges; + _pWhichRanges = 0; // for invariant-testing + + DBG( --*_pChildCount(_pParent) ); + DBG( delete _pChildCount(this); _pChildCountDtor ); +} + +// ----------------------------------------------------------------------- + +USHORT SfxItemSet::ClearItem( USHORT nWhich ) + +// einzelnes Item oder alle Items (nWhich==0) l"oschen + +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + if( !Count() ) + return 0; + + USHORT nDel = 0; + SfxItemArray ppFnd = _aItems; + + if( nWhich ) + { + const USHORT* pPtr = _pWhichRanges; + while( *pPtr ) + { + // in diesem Bereich? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // "uberhaupt gesetzt? + ppFnd += nWhich - *pPtr; + if( *ppFnd ) + { + // wegen der Assertions ins Sub-Calls mu\s das hier sein + --_nCount; + const SfxPoolItem *pItemToClear = *ppFnd; + *ppFnd = 0; + + if ( !IsInvalidItem(pItemToClear) ) + { + if ( nWhich <= SFX_WHICH_MAX ) + { + const SfxPoolItem& rNew = _pParent + ? _pParent->Get( nWhich, TRUE ) + : _pPool->GetDefaultItem( nWhich ); + + Changed( *pItemToClear, rNew ); + } + if ( pItemToClear->Which() ) + _pPool->Remove( *pItemToClear ); + } + ++nDel; + } + + // gefunden => raus + break; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } + else + { + nDel = _nCount; + + USHORT* pPtr = _pWhichRanges; + while( *pPtr ) + { + for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + // wegen der Assertions ins Sub-Calls mu\s das hier sein + --_nCount; + const SfxPoolItem *pItemToClear = *ppFnd; + *ppFnd = 0; + + if ( !IsInvalidItem(pItemToClear) ) + { + if ( nWhich <= SFX_WHICH_MAX ) + { + const SfxPoolItem& rNew = _pParent + ? _pParent->Get( nWhich, TRUE ) + : _pPool->GetDefaultItem( nWhich ); + + Changed( *pItemToClear, rNew ); + } + + // #i32448# + // Take care of disabled items, too. + if(!pItemToClear->nWhich) + { + // item is disabled, delete it + delete pItemToClear; + } + else + { + // remove item from pool + _pPool->Remove( *pItemToClear ); + } + } + } + pPtr += 2; + } + } + return nDel; +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::ClearInvalidItems( BOOL bHardDefault ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + USHORT* pPtr = _pWhichRanges; + SfxItemArray ppFnd = _aItems; + if ( bHardDefault ) + while( *pPtr ) + { + for ( USHORT nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if ( IsInvalidItem(*ppFnd) ) + *ppFnd = &_pPool->Put( _pPool->GetDefaultItem(nWhich) ); + pPtr += 2; + } + else + while( *pPtr ) + { + for( USHORT nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( IsInvalidItem(*ppFnd) ) + { + *ppFnd = 0; + --_nCount; + } + pPtr += 2; + } +} + +//------------------------------------------------------------------------ + + +void SfxItemSet::InvalidateAllItems() +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( !_nCount, "Es sind noch Items gesetzt" ); + + memset( (void*)_aItems, -1, ( _nCount = TotalCount() ) * sizeof( SfxPoolItem*) ); +} + +// ----------------------------------------------------------------------- + +SfxItemState SfxItemSet::GetItemState( USHORT nWhich, + BOOL bSrchInParent, + const SfxPoolItem **ppItem ) const +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + // suche den Bereich in dem das Which steht: + const SfxItemSet* pAktSet = this; + SfxItemState eRet = SFX_ITEM_UNKNOWN; + do + { + SfxItemArray ppFnd = pAktSet->_aItems; + const USHORT* pPtr = pAktSet->_pWhichRanges; + if (pPtr) + { + while ( *pPtr ) + { + if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // in diesem Bereich + ppFnd += nWhich - *pPtr; + if ( !*ppFnd ) + { + eRet = SFX_ITEM_DEFAULT; + if( !bSrchInParent ) + return eRet; // nicht vorhanden + break; // JP: in den Parents weitersuchen !!! + } + + if ( (SfxPoolItem*) -1 == *ppFnd ) + // Unterschiedlich vorhanden + return SFX_ITEM_DONTCARE; + + if ( (*ppFnd)->IsA(TYPE(SfxVoidItem)) ) + return SFX_ITEM_DISABLED; + + if (ppItem) + { + const SfxPoolItem *pItem = *ppFnd; + DBG_ASSERT( !pItem->ISA(SfxSetItem) || + 0 != &((const SfxSetItem*)pItem)->GetItemSet(), + "SetItem without ItemSet" ); + *ppItem = *ppFnd; + } + return SFX_ITEM_SET; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } + } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent )); + return eRet; +} + +// ----------------------------------------------------------------------- + +const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, USHORT nWhich ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( !rItem.ISA(SfxSetItem) || + 0 != &((const SfxSetItem&)rItem).GetItemSet(), + "SetItem without ItemSet" ); + if ( !nWhich ) + return 0; //! nur wegen Outliner-Bug + SfxItemArray ppFnd = _aItems; + const USHORT* pPtr = _pWhichRanges; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // in diesem Bereich + ppFnd += nWhich - *pPtr; + if( *ppFnd ) // schon einer vorhanden + { + // selbes Item bereits vorhanden? + if ( *ppFnd == &rItem ) + return 0; + + // wird dontcare oder disabled mit was echtem ueberschrieben? + if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) ) + { + *ppFnd = &_pPool->Put( rItem, nWhich ); + return *ppFnd; + } + + // wird disabled? + if( !rItem.Which() ) + { + *ppFnd = rItem.Clone(_pPool); + return 0; + } + else + { + // selber Wert bereits vorhanden? + if ( rItem == **ppFnd ) + return 0; + + // den neuen eintragen, den alten austragen + const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich ); + const SfxPoolItem* pOld = *ppFnd; + *ppFnd = &rNew; + if(nWhich <= SFX_WHICH_MAX) + Changed( *pOld, rNew ); + _pPool->Remove( *pOld ); + } + } + else + { + ++_nCount; + if( !rItem.Which() ) + *ppFnd = rItem.Clone(_pPool); + else { + const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich ); + *ppFnd = &rNew; + if (nWhich <= SFX_WHICH_MAX ) + { + const SfxPoolItem& rOld = _pParent + ? _pParent->Get( nWhich, TRUE ) + : _pPool->GetDefaultItem( nWhich ); + Changed( rOld, rNew ); + } + } + } + SFX_ASSERT( !_pPool->IsItemFlag(nWhich, SFX_ITEM_POOLABLE) || + rItem.ISA(SfxSetItem) || **ppFnd == rItem, + nWhich, "putted Item unequal" ); + return *ppFnd; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + return 0; +} + +// ----------------------------------------------------------------------- + +int SfxItemSet::Put( const SfxItemSet& rSet, BOOL bInvalidAsDefault ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + BOOL bRet = FALSE; + if( rSet.Count() ) + { + SfxItemArray ppFnd = rSet._aItems; + const USHORT* pPtr = rSet._pWhichRanges; + while ( *pPtr ) + { + for ( USHORT nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + if ( IsInvalidItem( *ppFnd ) ) + { + if ( bInvalidAsDefault ) + bRet |= 0 != ClearItem( nWhich ); + // gab GPF bei non.WIDs: + // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + else + InvalidateItem( nWhich ); + } + else + bRet |= 0 != Put( **ppFnd, nWhich ); + } + pPtr += 2; + } + } + return bRet; +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::PutExtended +( + const SfxItemSet& rSet, // Quelle der zu puttenden Items + SfxItemState eDontCareAs, // was mit DontCare-Items passiert + SfxItemState eDefaultAs // was mit Default-Items passiert +) + +/* [Beschreibung] + + Diese Methode "ubernimmt die Items aus 'rSet' in '*this'. Die + Which-Bereiche in '*this', die in 'rSet' nicht vorkommen bleiben unver- + "andert. Der Which-Bereich von '*this' bleibt auch unver"andert. + + In 'rSet' gesetzte Items werden auch in '*this*' gesetzt. Default- + (0 Pointer) und Invalid- (-1 Pointer) Items werden je nach Parameter + ('eDontCareAs' und 'eDefaultAs' behandelt: + + SFX_ITEM_SET: hart auf Default des Pools gesetzt + SFX_ITEM_DEFAULT: gel"oscht (0 Pointer) + SFX_ITEM_DONTCARE: invalidiert (-1 Pointer) + + Alle anderen Werte f"ur 'eDontCareAs' und 'eDefaultAs' sind ung"ultig. +*/ + +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + + // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults + SfxItemArray ppFnd = rSet._aItems; + const USHORT* pPtr = rSet._pWhichRanges; + while ( *pPtr ) + { + for ( USHORT nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + if ( IsInvalidItem( *ppFnd ) ) + { + // Item ist DontCare: + switch ( eDontCareAs ) + { + case SFX_ITEM_SET: + Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + break; + + case SFX_ITEM_DEFAULT: + ClearItem( nWhich ); + break; + + case SFX_ITEM_DONTCARE: + InvalidateItem( nWhich ); + break; + + default: + DBG_ERROR( "invalid Argument for eDontCareAs" ); + } + } + else + // Item ist gesetzt: + Put( **ppFnd, nWhich ); + } + else + { + // Item ist Default: + switch ( eDefaultAs ) + { + case SFX_ITEM_SET: + Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + break; + + case SFX_ITEM_DEFAULT: + ClearItem( nWhich ); + break; + + case SFX_ITEM_DONTCARE: + InvalidateItem( nWhich ); + break; + + default: + DBG_ERROR( "invalid Argument for eDefaultAs" ); + } + } + pPtr += 2; + } +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::MergeRange( USHORT nFrom, USHORT nTo ) +/**

Description

+ + Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of + items which are new ranges too. +*/ + +{ + // special case: exactly one USHORT which is already included? + if ( nFrom == nTo && SFX_ITEM_AVAILABLE <= GetItemState(nFrom, FALSE) ) + return; + + // merge new range + SfxUShortRanges aRanges( _pWhichRanges ); + aRanges += SfxUShortRanges( nFrom, nTo ); + SetRanges( aRanges ); +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::SetRanges( const USHORT *pNewRanges ) + +/**

Description

+ + Modifies the ranges of settable items. Keeps state of items which + are new ranges too. +*/ + +{ + // identische Ranges? + if ( _pWhichRanges == pNewRanges ) + return; + const USHORT* pOld = _pWhichRanges; + const USHORT* pNew = pNewRanges; + while ( *pOld == *pNew ) + { + if ( !*pOld && !*pNew ) + return; + ++pOld, ++pNew; + } + + // create new item-array (by iterating through all new ranges) + ULONG nSize = Capacity_Impl(pNewRanges); + SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ]; + USHORT n = 0, nNewCount = 0; + if ( _nCount == 0 ) + memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) ); + else + { + for ( const USHORT *pRange = pNewRanges; *pRange; pRange += 2 ) + { + // iterate through all ids in the range + for ( USHORT nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n ) + { + // direct move of pointer (not via pool) + SfxItemState eState = GetItemState( nWID, FALSE, aNewItems+n ); + if ( SFX_ITEM_SET == eState ) + { + // increment new item count and possibly increment ref count + ++nNewCount; + aNewItems[n]->AddRef(); + } + else if ( SFX_ITEM_DISABLED == eState ) + { + // put "disabled" item + ++nNewCount; + aNewItems[n] = new SfxVoidItem(0); + } + else if ( SFX_ITEM_DONTCARE == eState ) + { + ++nNewCount; + aNewItems[n] = (SfxPoolItem*)-1; + } + else + { + // default + aNewItems[n] = 0; + } + } + } + // free old items + USHORT nOldTotalCount = TotalCount(); + for ( USHORT nItem = 0; nItem < nOldTotalCount; ++nItem ) + { + const SfxPoolItem *pItem = _aItems[nItem]; + if ( pItem && !IsInvalidItem(pItem) && pItem->Which() ) + _pPool->Remove(*pItem); + } + } + + // replace old items-array and ranges + delete[] _aItems; + _aItems = aNewItems; + _nCount = nNewCount; + + if( pNewRanges == GetPool()->GetFrozenIdRanges() ) + { + delete[] _pWhichRanges; + _pWhichRanges = ( USHORT* ) pNewRanges; + } + else + { + USHORT nCount = Count_Impl(pNewRanges) + 1; + if ( _pWhichRanges != _pPool->GetFrozenIdRanges() ) + delete[] _pWhichRanges; + _pWhichRanges = new USHORT[ nCount ]; + memcpy( _pWhichRanges, pNewRanges, sizeof( USHORT ) * nCount ); + } +} + +// ----------------------------------------------------------------------- + +int SfxItemSet::Set +( + const SfxItemSet& rSet, /* das SfxItemSet, dessen SfxPoolItems + "ubernommen werden sollen */ + + BOOL bDeep /* TRUE (default) + auch die SfxPoolItems aus den ggf. an + rSet vorhandenen Parents werden direkt + in das SfxItemSet "ubernommen + + FALSE + die SfxPoolItems aus den Parents von + rSet werden nicht ber"ucksichtigt */ +) + +/* [Beschreibung] + + Das SfxItemSet nimmt genau die SfxPoolItems an, die auch in + rSet gesetzt sind und im eigenen liegen. Alle + anderen werden entfernt. Der SfxItemPool wird dabei beibehalten, + so da"s die "ubernommenen SfxPoolItems dabei ggf. vom SfxItemPool + von rSet in den SfxItemPool von *this "ubernommen werden. + + SfxPoolItems, f"ur die in rSet IsInvalidItem() == TRUE gilt, + werden als Invalid-Item "ubernommen. + + + [R"uckgabewert] + + int TRUE + es wurden SfxPoolItems "ubernommen + + FALSE + es wurden keine SfxPoolItems "ubernommen, + da z.B. die Which-Bereiche der SfxItemSets + keine Schnittmenge haben oder in der + Schnittmenge keine SfxPoolItems in rSet + gesetzt sind + +*/ + +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + int bRet = FALSE; + if ( _nCount ) + ClearItem(); + if ( bDeep ) + { + SfxWhichIter aIter(*this); + USHORT nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == rSet.GetItemState( nWhich, TRUE, &pItem ) ) + bRet |= 0 != Put( *pItem, pItem->Which() ); + nWhich = aIter.NextWhich(); + } + } + else + bRet = Put(rSet, FALSE); + + return bRet; +} + +//------------------------------------------------------------------------ + +const SfxPoolItem* SfxItemSet::GetItem +( + USHORT nId, // Slot-Id oder Which-Id des Items + BOOL bSrchInParent, // TRUE: auch in Parent-ItemSets suchen + TypeId aItemType // != 0 => RTTI Pruefung mit Assertion +) const + +/* [Beschreibung] + + Mit dieser Methode wird der Zugriff auf einzelne Items im + SfxItemSet wesentlich vereinfacht. Insbesondere wird die Typpr"ufung + (per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen + wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird + eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der + angegebenen Klasse ist. Ist kein Item mit der Id 'nWhich' in dem ItemSet, + so wird 0 zurueckgegeben. +*/ + +{ + // ggf. in Which-Id umrechnen + USHORT nWhich = GetPool()->GetWhich(nId); + + // ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar? + const SfxPoolItem *pItem = 0; + SfxItemState eState = GetItemState( nWhich, bSrchInParent, &pItem ); + if ( bSrchInParent && SFX_ITEM_AVAILABLE == eState && + nWhich <= SFX_WHICH_MAX ) + pItem = &_pPool->GetDefaultItem(nWhich); + if ( pItem ) + { + // stimmt der Typ "uberein? + if ( !aItemType || pItem->IsA(aItemType) ) + return pItem; + + // sonst Fehler melden + DBG_ERROR( "invalid argument type" ); + } + + // kein Item gefunden oder falschen Typ gefunden + return 0; +} + + +//------------------------------------------------------------------------ + + +const SfxPoolItem& SfxItemSet::Get( USHORT nWhich, BOOL bSrchInParent) const +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + // suche den Bereich in dem das Which steht: + const SfxItemSet* pAktSet = this; + do + { + if( pAktSet->Count() ) + { + SfxItemArray ppFnd = pAktSet->_aItems; + const USHORT* pPtr = pAktSet->_pWhichRanges; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // in diesem Bereich + ppFnd += nWhich - *pPtr; + if( *ppFnd ) + { + if( (SfxPoolItem*)-1 == *ppFnd ) { + //?MI: folgender code ist Doppelt (unten) + SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig"); + //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich); + //!return aDefault; + return _pPool->GetDefaultItem( nWhich ); + } + const SfxPoolItem *pItem = *ppFnd; + DBG_ASSERT( !pItem->ISA(SfxSetItem) || + 0 != &((const SfxSetItem*)pItem)->GetItemSet(), + "SetItem without ItemSet" ); +#ifdef DBG_UTIL + if ( pItem->ISA(SfxVoidItem) || !pItem->Which() ) + DBG_WARNING( "SFX_WARNING: Getting disabled Item" ); +#endif + return **ppFnd; + } + break; // dann beim Parent suchen + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } +// bis zum Ende vom Such-Bereich: was nun ? zum Parent, oder Default ?? +// if( !*pPtr ) // bis zum Ende vom Such-Bereich ? +// break; + } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent )); + + // dann das Default vom Pool holen und returnen + SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig"); + const SfxPoolItem *pItem = &_pPool->GetDefaultItem( nWhich ); + DBG_ASSERT( !pItem->ISA(SfxSetItem) || + 0 != &((const SfxSetItem*)pItem)->GetItemSet(), + "SetItem without ItemSet" ); + return *pItem; +} + + // Notification-Callback +// ----------------------------------------------------------------------- + +void SfxItemSet::Changed( const SfxPoolItem& rOld, const SfxPoolItem& rNew ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); +} + +// ----------------------------------------------------------------------- + +USHORT SfxItemSet::TotalCount() const +{ + DBG_CHKTHIS(SfxItemSet, 0); // wird im Ctor benutzt bevor vollst. init. + USHORT nRet = 0; + USHORT* pPtr = _pWhichRanges; + while( *pPtr ) + { + nRet += ( *(pPtr+1) - *pPtr ) + 1; + pPtr += 2; + } + return nRet; +} +// ----------------------------------------------------------------------- + +// behalte nur die Items, die auch in rSet enthalten sein (Wert egal) + +void SfxItemSet::Intersect( const SfxItemSet& rSet ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT(_pPool, "nicht implementiert ohne Pool"); + if( !Count() ) // gar keine gesetzt ? + return; + + // loesche alle Items, die im rSet nicht mehr vorhanden sind + if( !rSet.Count() ) + { + ClearItem(); // alles loeschen + return; + } + + // teste mal, ob sich die Which-Bereiche unterscheiden. + BOOL bEqual = TRUE; + USHORT* pWh1 = _pWhichRanges; + USHORT* pWh2 = rSet._pWhichRanges; + USHORT nSize = 0, nWhich; + + for( USHORT n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + bEqual = FALSE; + break; + } + if( n & 1 ) + nSize += ( *(pWh1) - *(pWh1-1) ) + 1; + } + bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen + + // sind die Bereiche identisch, ist es einfacher zu handhaben ! + if( bEqual ) + { + SfxItemArray ppFnd1 = _aItems; + SfxItemArray ppFnd2 = rSet._aItems; + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + if( *ppFnd1 && !*ppFnd2 ) + { + // aus dem Pool loeschen + if( !IsInvalidItem( *ppFnd1 ) ) + { + nWhich = (*ppFnd1)->Which(); + if(nWhich <= SFX_WHICH_MAX) + { + const SfxPoolItem& rNew = _pParent + ? _pParent->Get( nWhich, TRUE ) + : _pPool->GetDefaultItem( nWhich ); + + Changed( **ppFnd1, rNew ); + } + _pPool->Remove( **ppFnd1 ); + } + *ppFnd1 = 0; + --_nCount; + } + } + else + { + SfxItemIter aIter( *this ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + while( TRUE ) + { + USHORT nWhich = IsInvalidItem( pItem ) + ? GetWhichByPos( aIter.GetCurPos() ) + : pItem->Which(); + if( 0 == rSet.GetItemState( nWhich, FALSE ) ) + ClearItem( nWhich ); // loeschen + if( aIter.IsAtEnd() ) + break; + pItem = aIter.NextItem(); + } + } +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::Differentiate( const SfxItemSet& rSet ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + if( !Count() || !rSet.Count() ) // gar keine gesetzt ? + return; + + // teste mal, ob sich die Which-Bereiche unterscheiden. + BOOL bEqual = TRUE; + USHORT* pWh1 = _pWhichRanges; + USHORT* pWh2 = rSet._pWhichRanges; + USHORT nSize = 0, nWhich; + + for( USHORT n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + bEqual = FALSE; + break; + } + if( n & 1 ) + nSize += ( *(pWh1) - *(pWh1-1) ) + 1; + } + bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen + + // sind die Bereiche identisch, ist es einfacher zu handhaben ! + if( bEqual ) + { + SfxItemArray ppFnd1 = _aItems; + SfxItemArray ppFnd2 = rSet._aItems; + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + if( *ppFnd1 && *ppFnd2 ) + { + // aus dem Pool loeschen + if( !IsInvalidItem( *ppFnd1 ) ) + { + nWhich = (*ppFnd1)->Which(); + if(nWhich <= SFX_WHICH_MAX) + { + const SfxPoolItem& rNew = _pParent + ? _pParent->Get( nWhich, TRUE ) + : _pPool->GetDefaultItem( nWhich ); + + Changed( **ppFnd1, rNew ); + } + _pPool->Remove( **ppFnd1 ); + } + *ppFnd1 = 0; + --_nCount; + } + } + else + { + SfxItemIter aIter( *this ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + while( TRUE ) + { + USHORT nWhich = IsInvalidItem( pItem ) + ? GetWhichByPos( aIter.GetCurPos() ) + : pItem->Which(); + if( SFX_ITEM_SET == rSet.GetItemState( nWhich, FALSE ) ) + ClearItem( nWhich ); // loeschen + if( aIter.IsAtEnd() ) + break; + pItem = aIter.NextItem(); + } + + } +} + +// ----------------------------------------------------------------------- +/* Entscheidungstabelle fuer MergeValue[s] + +Grundsaetze: + 1. Ist der Which-Wert im 1.Set "unknown", dann folgt niemals eine Aktion. + 2. Ist der Which-Wert im 2.Set "unknown", dann gilt er als "default". + 3. Es gelten fuer Vergleiche die Werte der "default"-Items. + +1.-Item 2.-Item Values bIgnoreDefs Remove Assign Add + +set set == FALSE - - - +default set == FALSE - - - +dontcare set == FALSE - - - +unknown set == FALSE - - - +set default == FALSE - - - +default default == FALSE - - - +dontcare default == FALSE - - - +unknown default == FALSE - - - +set dontcare == FALSE 1.-Item -1 - +default dontcare == FALSE - -1 - +dontcare dontcare == FALSE - - - +unknown dontcare == FALSE - - - +set unknown == FALSE 1.-Item -1 - +default unknown == FALSE - - - +dontcare unknown == FALSE - - - +unknown unknown == FALSE - - - + +set set != FALSE 1.-Item -1 - +default set != FALSE - -1 - +dontcare set != FALSE - - - +unknown set != FALSE - - - +set default != FALSE 1.-Item -1 - +default default != FALSE - - - +dontcare default != FALSE - - - +unknown default != FALSE - - - +set dontcare != FALSE 1.-Item -1 - +default dontcare != FALSE - -1 - +dontcare dontcare != FALSE - - - +unknown dontcare != FALSE - - - +set unknown != FALSE 1.-Item -1 - +default unknown != FALSE - - - +dontcare unknown != FALSE - - - +unknown unknown != FALSE - - - + +set set == TRUE - - - +default set == TRUE - 2.-Item 2.-Item +dontcare set == TRUE - - - +unknown set == TRUE - - - +set default == TRUE - - - +default default == TRUE - - - +dontcare default == TRUE - - - +unknown default == TRUE - - - +set dontcare == TRUE - - - +default dontcare == TRUE - -1 - +dontcare dontcare == TRUE - - - +unknown dontcare == TRUE - - - +set unknown == TRUE - - - +default unknown == TRUE - - - +dontcare unknown == TRUE - - - +unknown unknown == TRUE - - - + +set set != TRUE 1.-Item -1 - +default set != TRUE - 2.-Item 2.-Item +dontcare set != TRUE - - - +unknown set != TRUE - - - +set default != TRUE - - - +default default != TRUE - - - +dontcare default != TRUE - - - +unknown default != TRUE - - - +set dontcare != TRUE 1.-Item -1 - +default dontcare != TRUE - -1 - +dontcare dontcare != TRUE - - - +unknown dontcare != TRUE - - - +set unknown != TRUE - - - +default unknown != TRUE - - - +dontcare unknown != TRUE - - - +unknown unknown != TRUE - - - +*/ + + +static void MergeItem_Impl( SfxItemPool *_pPool, USHORT &rCount, + const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2, + BOOL bIgnoreDefaults ) +{ + DBG_ASSERT( ppFnd1 != 0, "Merging to 0-Item" ); + + // 1. Item ist default? + if ( !*ppFnd1 ) + { + if ( IsInvalidItem(pFnd2) ) + // Entscheidungstabelle: default, dontcare, egal, egal + *ppFnd1 = (SfxPoolItem*) -1; + + else if ( pFnd2 && !bIgnoreDefaults && + _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 ) + // Entscheidungstabelle: default, set, !=, FALSE + *ppFnd1 = (SfxPoolItem*) -1; + + else if ( pFnd2 && bIgnoreDefaults ) + // Entscheidungstabelle: default, set, egal, TRUE + *ppFnd1 = &_pPool->Put( *pFnd2 ); + + if ( *ppFnd1 ) + ++rCount; + } + + // 1. Item ist gesetzt? + else if ( !IsInvalidItem(*ppFnd1) ) + { + if ( !pFnd2 ) + { + // 2. Item ist default + if ( !bIgnoreDefaults && + **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) ) + { + // Entscheidungstabelle: set, default, !=, FALSE + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = (SfxPoolItem*) -1; + } + } + else if ( IsInvalidItem(pFnd2) ) + { + // 2. Item ist dontcare + if ( !bIgnoreDefaults || + **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) ) + { + // Entscheidungstabelle: set, dontcare, egal, FALSE + // oder: set, dontcare, !=, TRUE + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = (SfxPoolItem*) -1; + } + } + else + { + // 2. Item ist gesetzt + if ( **ppFnd1 != *pFnd2 ) + { + // Entscheidungstabelle: set, set, !=, egal + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = (SfxPoolItem*) -1; + } + } + } +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::MergeValues( const SfxItemSet& rSet, BOOL bIgnoreDefaults ) +{ + // Achtung!!! Bei Aenderungen/Bugfixes immer obenstehende Tabelle pflegen! + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( GetPool() == rSet.GetPool(), "MergeValues mit verschiedenen Pools" ); + + // teste mal, ob sich die Which-Bereiche unterscheiden. + BOOL bEqual = TRUE; + USHORT* pWh1 = _pWhichRanges; + USHORT* pWh2 = rSet._pWhichRanges; + USHORT nSize = 0; + + for( USHORT n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + bEqual = FALSE; + break; + } + if( n & 1 ) + nSize += ( *(pWh1) - *(pWh1-1) ) + 1; + } + bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen + + // sind die Bereiche identisch, ist es effizieter zu handhaben ! + if( bEqual ) + { + SfxItemArray ppFnd1 = _aItems; + SfxItemArray ppFnd2 = rSet._aItems; + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + MergeItem_Impl( _pPool, _nCount, ppFnd1, *ppFnd2, bIgnoreDefaults ); + } + else + { + SfxWhichIter aIter( rSet ); + register USHORT nWhich; + while( 0 != ( nWhich = aIter.NextWhich() ) ) + { + const SfxPoolItem* pItem = 0; + rSet.GetItemState( nWhich, TRUE, &pItem ); + if( !pItem ) + { + // nicht gesetzt, also default + if ( !bIgnoreDefaults ) + MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ), bIgnoreDefaults ); + } + else if( IsInvalidItem( pItem ) ) + // dont care + InvalidateItem( nWhich ); + else + MergeValue( *pItem, bIgnoreDefaults ); + } + } +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, BOOL bIgnoreDefaults ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + SfxItemArray ppFnd = _aItems; + const USHORT* pPtr = _pWhichRanges; + const USHORT nWhich = rAttr.Which(); + while( *pPtr ) + { + // in diesem Bereich? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + ppFnd += nWhich - *pPtr; + MergeItem_Impl( _pPool, _nCount, ppFnd, &rAttr, bIgnoreDefaults ); + break; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } +} + +// ----------------------------------------------------------------------- + +void SfxItemSet::InvalidateItem( USHORT nWhich ) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + SfxItemArray ppFnd = _aItems; + const USHORT* pPtr = _pWhichRanges; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // in diesem Bereich + ppFnd += nWhich - *pPtr; + + if( *ppFnd ) // bei mir gesetzt + { + if( (SfxPoolItem*)-1 != *ppFnd ) // noch nicht dontcare ! + { + _pPool->Remove( **ppFnd ); + *ppFnd = (SfxPoolItem*)-1; + } + } + else + { + *ppFnd = (SfxPoolItem*)-1; + ++_nCount; + } + break; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } +} + +// ----------------------------------------------------------------------- + +USHORT SfxItemSet::GetWhichByPos( USHORT nPos ) const +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + USHORT n = 0; + USHORT* pPtr = _pWhichRanges; + while( *pPtr ) + { + n = ( *(pPtr+1) - *pPtr ) + 1; + if( nPos < n ) + return *(pPtr)+nPos; + nPos -= n; + pPtr += 2; + } + DBG_ASSERT( FALSE, "Hier sind wir falsch" ); + return 0; +} + +// ----------------------------------------------------------------------- + +SvStream &SfxItemSet::Store +( + SvStream& rStream, // Zielstream f"ur normale Items + FASTBOOL bDirect // TRUE: Items direkt speicher, FALSE: Surrogate +) const + +/* [Beschreibung] + + Speichert die -Instanz in den angegebenen Stream. Dabei + werden die Surrorage der gesetzten s bzw. ('bDirect==TRUE') + die gesetzten Items selbst wie folgt im Stream abgelegt: + + USHORT (Count) Anzahl der gesetzten Items + Count* _pPool->StoreItem() siehe + + + [Querverweise] + + +*/ + +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( _pPool, "Kein Pool" ); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); + + // Position des Counts merken, um ggf. zu korrigieren + ULONG nCountPos = rStream.Tell(); + rStream << _nCount; + + // wenn nichts zu speichern ist, auch keinen ItemIter aufsetzen! + if ( _nCount ) + { + // mitz"ahlen wieviel Items tats"achlich gespeichert werden + USHORT nWrittenCount = 0; // Anzahl in 'rStream' gestreamter Items + + // "uber alle gesetzten Items iterieren + SfxItemIter aIter(*this); + for ( const SfxPoolItem *pItem = aIter.FirstItem(); + pItem; + pItem = aIter.NextItem() ) + { + // Item (ggf. als Surrogat) via Pool speichern lassen + DBG_ASSERT( !IsInvalidItem(pItem), "can't store invalid items" ); + if ( !IsInvalidItem(pItem) && + _pPool->StoreItem( rStream, *pItem, bDirect ) ) + // Item wurde in 'rStream' gestreamt + ++nWrittenCount; + }; + + // weniger geschrieben als enthalten (z.B. altes Format) + if ( nWrittenCount != _nCount ) + { + // tats"achlichen Count im Stream ablegen + ULONG nPos = rStream.Tell(); + rStream.Seek( nCountPos ); + rStream << nWrittenCount; + rStream.Seek( nPos ); + } + } + + return rStream; +} + +// ----------------------------------------------------------------------- + +SvStream &SfxItemSet::Load +( + SvStream& rStream, // Stream, aus dem geladen werden soll + + FASTBOOL bDirect, /* TRUE + Items werden direkt aus dem Stream + gelesen, nicht "uber Surrogate + + FALSE (default) + Items werden "uber Surrogate gelesen */ + + const SfxItemPool* pRefPool /* Pool, der die Surrogate aufl"osen kann + (z.B. zum Einf"ugen von Dokumenten) */ +) + +/* [Beschreibung] + + Diese Methode l"adt ein aus einem Stream. Falls der + ohne Ref-Counts geladen wurde, werden die geladenen + Item-Referenzen in den Items hochgez"ahlt, ansonsten wird vorausgesetzt, + da\s sie schon beim Laden des SfxItemPools ber"ucksichtigt waren. + + [Querverweise] + + +*/ + +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_ASSERT( _pPool, "Kein Pool"); + DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "Kein Master-Pool"); + + // kein Ref-Pool => Surrogate mit Pool des ItemSets aufl"osen + if ( !pRefPool ) + pRefPool = _pPool; + + // Anzahl der zu ladenden Items laden und dann ebensoviele Items + USHORT nCount = 0; + rStream >> nCount; + for ( USHORT i = 0; i < nCount; ++i ) + { + // Surrogat/Item laden und (Surrogat) aufl"osen lassen + const SfxPoolItem *pItem = + _pPool->LoadItem( rStream, bDirect, pRefPool ); + + // konnte ein Item geladen oder via Surrogat aufgel"ost werden? + if ( pItem ) + { + // Position f"ur Item-Pointer im Set suchen + USHORT nWhich = pItem->Which(); + SfxItemArray ppFnd = _aItems; + const USHORT* pPtr = _pWhichRanges; + while ( *pPtr ) + { + // in diesem Bereich? + if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Item-Pointer im Set merken + ppFnd += nWhich - *pPtr; + SFX_ASSERT( !*ppFnd, nWhich, "Item doppelt eingetragen"); + *ppFnd = pItem; + ++_nCount; + break; + } + + // im Range-Array und Item-Array zum n"achsten Which-Range + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + } + } + + return rStream; +} + +// ----------------------------------------------------------------------- + +int SfxItemSet::operator==(const SfxItemSet &rCmp) const +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + DBG_CHKOBJ(&rCmp, SfxItemSet, DbgCheckItemSet); + + // besonders schnell zu ermittelnde Werte muessen gleich sein + if ( _pParent != rCmp._pParent || + _pPool != rCmp._pPool || + Count() != rCmp.Count() ) + return FALSE; + + // Ranges durchzaehlen lassen dauert laenger, muss aber auch gleich sein + USHORT nCount1 = TotalCount(); + USHORT nCount2 = rCmp.TotalCount(); + if ( nCount1 != nCount2 ) + return FALSE; + + // sind die Ranges selbst ungleich? + for ( USHORT nRange = 0; _pWhichRanges[nRange]; nRange += 2 ) + if ( _pWhichRanges[nRange] != rCmp._pWhichRanges[nRange] || + _pWhichRanges[nRange+1] != rCmp._pWhichRanges[nRange+1] ) + { + // dann m"ussen wir die langsame Methode verwenden + SfxWhichIter aIter( *this ); + for ( USHORT nWh = aIter.FirstWhich(); + nWh; + nWh = aIter.NextWhich() ) + { + // wenn die Pointer von poolable Items ungleich sind, + // muessen die Items gleich sein + const SfxPoolItem *pItem1 = 0, *pItem2 = 0; + if ( GetItemState( nWh, FALSE, &pItem1 ) != + rCmp.GetItemState( nWh, FALSE, &pItem2 ) || + ( pItem1 != pItem2 && + ( !pItem1 || IsInvalidItem(pItem1) || + ( _pPool->IsItemFlag(*pItem1, SFX_ITEM_POOLABLE) && + *pItem1 != *pItem2 ) ) ) ) + return FALSE; + } + + return TRUE; + } + + // Pointer alle gleich? + if ( 0 == memcmp( _aItems, rCmp._aItems, nCount1 * sizeof(_aItems[0]) ) ) + return TRUE; + + // dann werden wir wohl alle einzeln vergleichen muessen + const SfxPoolItem **ppItem1 = (const SfxPoolItem**) _aItems; + const SfxPoolItem **ppItem2 = (const SfxPoolItem**) rCmp._aItems; + for ( USHORT nPos = 0; nPos < nCount1; ++nPos ) + { + // wenn die Pointer von poolable Items ungleich sind, + // muessen die Items gleich sein + if ( *ppItem1 != *ppItem2 && + ( ( !*ppItem1 || !*ppItem2 ) || + ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) || + ( _pPool->IsItemFlag(**ppItem1, SFX_ITEM_POOLABLE) ) || + **ppItem1 != **ppItem2 ) ) + return FALSE; + + ++ppItem1; + ++ppItem2; + } + + return TRUE; +} + +// ----------------------------------------------------------------------- + +SfxItemSet *SfxItemSet::Clone(BOOL bItems, SfxItemPool *pToPool ) const +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + if ( pToPool && pToPool != _pPool ) + { + SfxItemSet *pNewSet = new SfxItemSet( *pToPool, _pWhichRanges ); + if ( bItems ) + { + SfxWhichIter aIter(*pNewSet); + USHORT nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + const SfxPoolItem* pItem; + if ( SFX_ITEM_SET == GetItemState( nWhich, FALSE, &pItem ) ) + pNewSet->Put( *pItem, pItem->Which() ); + nWhich = aIter.NextWhich(); + } + } + return pNewSet; + } + else + return bItems + ? new SfxItemSet(*this) + : new SfxItemSet(*_pPool, _pWhichRanges); +} + +// ----------------------------------------------------------------------- + +int SfxItemSet::PutDirect(const SfxPoolItem &rItem) +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + SfxItemArray ppFnd = _aItems; + const USHORT* pPtr = _pWhichRanges; + const USHORT nWhich = rItem.Which(); +#ifdef DBG_UTIL + IsPoolDefaultItem(&rItem) || _pPool->GetSurrogate(&rItem); + // nur Assertion in den callees provozieren +#endif + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // in diesem Bereich + ppFnd += nWhich - *pPtr; + const SfxPoolItem* pOld = *ppFnd; + if( pOld ) // schon einer vorhanden + { + if( rItem == **ppFnd ) + return FALSE; // schon vorhanden ! + _pPool->Remove( *pOld ); + } + else + ++_nCount; + + // den neuen eintragen + if( IsPoolDefaultItem(&rItem) ) + *ppFnd = &_pPool->Put( rItem ); + else + { + *ppFnd = &rItem; + if( !IsStaticDefaultItem( &rItem ) ) + rItem.AddRef(); + } + + return TRUE; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + return FALSE; +} + +// ----------------------------------------------------------------------- + +SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool ) +: SfxItemSet(rPool, (const USHORT*) 0), + aDefault(0), + nFree(nInitCount) +{ + // initial keine Items + _aItems = 0; + + // nInitCount Paare an USHORTs fuer Ranges allozieren + _pWhichRanges = new USHORT[ nInitCount + 1 ]; + memset( _pWhichRanges, 0, ( nInitCount + 1 ) * sizeof(USHORT) ); +} + + +// ----------------------------------------------------------------------- + + +SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy) +: SfxItemSet(rCopy), + aDefault(0), + nFree(0) +{ +} + +// ----------------------------------------------------------------------- + + + +SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy) +: SfxItemSet(rCopy), + aDefault(0), + nFree(0) +/* [Anmerkung] + + Der mu\s sein, da sonst vom Compiler einer generiert wird, er nimmt + nicht den Ctor mit der 'const SfxItemSet&'! +*/ +{ +} + +// ----------------------------------------------------------------------- + +static USHORT *AddRanges_Impl(USHORT *pUS, USHORT nOldSize, USHORT nIncr) + +/* Diese interne Funktion erzeugt ein neues Which-Range-Array, welches von + dem 'nOldSize'-USHORTs langen 'pUS' kopiert wird und hinten an Platz + f"ur 'nIncr' neue USHORTs hat. Das terminierende USHORT mit der '0' + wird weder in 'nOldSize' noch in 'nIncr' mitgez"ahlt, sondern implizit + hinzugerechnet. + + Das neue Which-Range-Array wird als Returnwert zur"uckgegeben, das alte + 'pUS' freigegeben. +*/ + +{ + // neues Which-Range-Array anlegen + USHORT *pNew = new USHORT[ nOldSize + nIncr + 1 ]; + + // die alten Ranges "ubernehmen + memcpy( pNew, pUS, nOldSize * sizeof(USHORT) ); + + // die neuen auf 0 initialisieren + memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(USHORT) ); + + // das alte Array freigeben + delete[] pUS; + + return pNew; +} + +// ----------------------------------------------------------------------- + +static SfxItemArray AddItem_Impl(SfxItemArray pItems, USHORT nOldSize, USHORT nPos) + +/* Diese interne Funktion erzeugt ein neues ItemArray, welches von 'pItems' + kopiert wird, an der Position 'nPos' jedoch Platz f"ur einen neuen + ItemPointer hat. + + Das neue ItemArray wird als Returnwert zur"uckgegeben, das alte 'pItems' + wird freigegeben. +*/ + +{ + // neues ItemArray anlegen + SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1]; + + // war schon vorher eins da? + if ( pItems ) + { + // alte Items vor nPos kopieren + if ( nPos ) + memcpy( (void*) pNew, pItems, nPos * sizeof(SfxPoolItem **) ); + + // alte Items hinter nPos kopieren + if ( nPos < nOldSize ) + memcpy( (void*) (pNew + nPos + 1), pItems + nPos, + (nOldSize-nPos) * sizeof(SfxPoolItem **) ); + } + + // neues Item initialisieren + *(pNew + nPos) = 0; + + // altes ItemArray freigeben + delete[] pItems; + + return pNew; +} + +// ----------------------------------------------------------------------- + +const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, USHORT nWhich ) + +// Putten mit automatischer Erweiterung der Whichs-Ids um die ID +// des Items. + +{ + USHORT nPos = 0; // Position f"ur 'rItem' in '_aItems' + const USHORT nItemCount = TotalCount(); + + // erstmal sehen, ob es schon einen passenden Bereich gibt + USHORT *pPtr = _pWhichRanges; + while ( *pPtr ) + { + // Which-Id liegt in diesem Bereich? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Einfuegen + nPos += nWhich - *pPtr; + break; + } + + // Position des Items in _aItems mitf"uhren + nPos += *(pPtr+1) - *pPtr + 1; + + // zum n"achsten Bereich + pPtr += 2; + } + + // Which-Id noch nicht vorhanden? + if ( !*pPtr ) + { + // suchen, ob man sie irgendwo dranpacken kann + pPtr = _pWhichRanges; + nPos = 0; + while ( *pPtr ) + { + // Which-Id liegt exakt vor diesem Bereich? + if ( (nWhich+1) == *pPtr ) + { + // Bereich waechst nach unten + (*pPtr)--; + + // vor erstem Item dieses Bereichs Platz schaffen + _aItems = AddItem_Impl(_aItems, nItemCount, nPos); + break; + } + + // Which-Id liegt exakt hinter diesem Bereich? + else if ( (nWhich-1) == *(pPtr+1) ) + { + // Bereich waechst nach oben + (*(pPtr+1))++; + + // hinter letztem Item dieses Bereichs Platz schaffen + nPos += nWhich - *pPtr; + _aItems = AddItem_Impl(_aItems, nItemCount, nPos); + break; + } + + // Position des Items in _aItems mitf"uhren + nPos += *(pPtr+1) - *pPtr + 1; + + // zum n"achsten Bereich + pPtr += 2; + } + } + + // keinen erweiterbaren Bereich gefunden? + if ( !*pPtr ) + { + // kein Platz mehr in _pWhichRanges => erweitern + USHORT nSize = pPtr - _pWhichRanges; + if( !nFree ) + { + _pWhichRanges = AddRanges_Impl(_pWhichRanges, nSize, nInitCount); + nFree += nInitCount; + } + + // neuen Which-Range anh"angen + pPtr = _pWhichRanges + nSize; + *pPtr++ = nWhich; + *pPtr = nWhich; + nFree -= 2; + + // Itemarray vergroessern + nPos = nItemCount; + _aItems = AddItem_Impl(_aItems, nItemCount, nPos); + } + + // neues Item in Pool aufnehmen + const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich ); + + // altes Item merken + BOOL bIncrementCount = FALSE; + const SfxPoolItem* pOld = *( _aItems + nPos ); + if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld ) // state "dontcare" + pOld = NULL; + if ( !pOld ) + { + bIncrementCount = TRUE; + pOld = _pParent ? + &_pParent->Get( nWhich, TRUE ) + : nWhich <= SFX_WHICH_MAX ? &_pPool->GetDefaultItem( nWhich ) : 0; + } + + // neue Item in ItemSet aufnehmen + *(_aItems + nPos) = &rNew; + + // Changed Notification versenden + if ( pOld ) + { + Changed( *pOld, rNew ); + if ( !IsDefaultItem(pOld) ) + _pPool->Remove( *pOld ); + } + + if ( bIncrementCount ) + ++_nCount; + + return &rNew; +} + +// ----------------------------------------------------------------------- + + +/* Diese Methode wird forwarded, damit sie nicht durch die anderen + Put-Methoden dieser SubClass gehided wird. +*/ + +int SfxAllItemSet::Put( const SfxItemSet& rSet, BOOL bInvalidAsDefault ) +{ + //? pruefen, ob Which-Ranges erweitert werden + return SfxItemSet::Put( rSet, bInvalidAsDefault ); +} + +// ----------------------------------------------------------------------- +// Item disablen, wenn durch ein VoidItem mit dem Which-Wert 0 ausgedrueckt + +void SfxItemSet::DisableItem(USHORT nWhich) +{ + DBG_CHKTHIS(SfxItemSet, 0); + Put( SfxVoidItem(0), nWhich ); +} + +// ----------------------------------------------------------------------- + +#if 0 +BOOL SfxAllItemSet::Remove(USHORT nWhich) +{ + DBG_CHKTHIS(SfxAllItemSet, 0); + USHORT *pPtr = _pWhichRanges; + USHORT nPos = 0; + while( *pPtr ) + { + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + USHORT *pTmp = pPtr; + USHORT nLeft = 0; + USHORT nRest = 0; + while(*++pTmp){ + if( nLeft & 1 ) + nRest = *pTmp - *(pTmp-1) + 1; + ++nLeft; + } + + // in diesem Bereich + nPos += nWhich - *pPtr; + nRest -= nWhich - *pPtr; + // 3,3 + if(*pPtr == nWhich && *(pPtr+1) == nWhich) { + memmove(pPtr, pPtr + 2, nLeft * sizeof(USHORT)); + nFree += 2; + } + // Anfang + else if(*pPtr == nWhich) + (*pPtr)++; + // Ende + else if(*(pPtr+1) == nWhich) + (*(pPtr+1))--; + else { + if(nPos + nRest + 2 > nFree) { + USHORT nOf = pPtr - _pWhichRanges; + _pWhichRanges = IncrSize(_pWhichRanges, nPos + nRest, nInitCount); + nFree += nInitCount; + pPtr = _pWhichRanges + nOf; + } + memmove(pPtr +2, pPtr, (nLeft+2) * sizeof(USHORT)); + *++pPtr = nWhich-1; + *++pPtr = nWhich+1; + nFree -= 2; + } + SfxPoolItem* pItem = *( _aItems + nPos ); + if( pItem ) + { + if(_pPool) + _pPool->Remove(*pItem ); + else + delete pItem; + --_nCount; + } + memmove(_aItems + nPos +1, _aItems + nPos, + sizeof(SfxPoolItem *) * (nRest - 1)); + break; // dann beim Parent suchen + } + nPos += *(pPtr+1) - *pPtr + 1; + pPtr += 2; + } + return *pPtr? TRUE: FALSE; +} +#endif + +// ----------------------------------------------------------------------- + +SfxItemSet *SfxAllItemSet::Clone(BOOL bItems, SfxItemPool *pToPool ) const +{ + DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); + if ( pToPool && pToPool != _pPool ) + { + SfxAllItemSet *pNewSet = new SfxAllItemSet( *pToPool ); + if ( bItems ) + pNewSet->Set( *this ); + return pNewSet; + } + else + return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool); +} +