1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itempool.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
39 #include <svtools/itempool.hxx>
40 #include "whassert.hxx"
41 #include <svtools/brdcst.hxx>
42 #include <svtools/smplhint.hxx>
46 // STATIC DATA -----------------------------------------------------------
49 //========================================================================
51 SV_IMPL_PTRARR( SfxPoolVersionArr_Impl
, SfxPoolVersion_Impl
* );
53 //========================================================================
56 void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser
& rNewUser
)
58 maSfxItemPoolUsers
.push_back(&rNewUser
);
61 void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser
& rOldUser
)
63 const SfxItemPoolUserVector::iterator aFindResult
= ::std::find(maSfxItemPoolUsers
.begin(), maSfxItemPoolUsers
.end(), &rOldUser
);
64 if(aFindResult
!= maSfxItemPoolUsers
.end())
66 maSfxItemPoolUsers
.erase(aFindResult
);
70 const SfxPoolItem
* SfxItemPool::GetPoolDefaultItem( USHORT nWhich
) const
72 DBG_CHKTHIS(SfxItemPool
, 0);
73 const SfxPoolItem
* pRet
;
74 if( IsInRange( nWhich
) )
75 pRet
= *(ppPoolDefaults
+ GetIndex_Impl( nWhich
));
77 pRet
= pSecondary
->GetPoolDefaultItem( nWhich
);
80 SFX_ASSERT( 0, nWhich
, "unknown Which-Id - cannot get pool default" );
86 // -----------------------------------------------------------------------
88 inline FASTBOOL
SfxItemPool::IsItemFlag_Impl( USHORT nPos
, USHORT nFlag
) const
90 USHORT nItemFlag
= pItemInfos
[nPos
]._nFlags
;
91 return nFlag
== (nItemFlag
& nFlag
);
94 // -----------------------------------------------------------------------
96 FASTBOOL
SfxItemPool::IsItemFlag( USHORT nWhich
, USHORT nFlag
) const
98 for ( const SfxItemPool
*pPool
= this; pPool
; pPool
= pPool
->pSecondary
)
100 if ( pPool
->IsInRange(nWhich
) )
101 return pPool
->IsItemFlag_Impl( pPool
->GetIndex_Impl(nWhich
), nFlag
);
103 DBG_ASSERT( !IsWhich(nWhich
), "unknown which-id" );
107 // -----------------------------------------------------------------------
109 SfxBroadcaster
& SfxItemPool::BC()
114 // -----------------------------------------------------------------------
117 SfxItemPool::SfxItemPool
119 UniString
const & rName
, /* Name des Pools zur Idetifikation
121 USHORT nStartWhich
, /* erste Which-Id des Pools */
122 USHORT nEndWhich
, /* letzte Which-Id des Pools */
124 const SfxItemInfo
* pInfos
, /* SID-Map und Item-Flags */
126 SfxPoolItem
** pDefaults
, /* Pointer auf statische Defaults,
127 wird direkt vom Pool referenziert,
128 jedoch kein Eigent"umer"ubergang */
130 USHORT
* pSlotIdArray
, /* Zuordnung von Slot-Ids zu Which-Ids */
132 FASTBOOL bLoadRefCounts
/* Ref-Counts mitladen oder auf 1 setzen */
137 Der im Normalfall verwendete Konstruktor der Klasse SfxItemPool. Es
138 wird eine SfxItemPool-Instanz initialisiert, die Items im b"undigen
139 Which-Bereich von 'nStartWhich' bis 'nEndWhich' verwalten kann.
141 F"ur jede dieser Which-Ids mu\s ein statischer Default im Array 'pDefaults'
142 vorhanden sein, die dort beginnend mit einem <SfxPoolItem> mit der
143 Which-Id 'nStartWhich' nach Which-Ids sortiert aufeinanderfolgend
144 eingetragen sein m"ussen.
146 'pItemInfos' ist ein identisch angeordnetes Array von USHORTs, die
147 Slot-Ids darstellen und Flags. Die Slot-Ids k"onnen 0 sein, wenn die
148 betreffenden Items ausschlie\slich in der Core verwendet werden.
149 "Uber die Flags kann z.B. bestimmt werden, ob Value-Sharing
150 (SFX_ITEM_POOLABLE) stattfinden soll.
154 Wenn der Pool <SfxSetItem>s enthalten soll, k"onnen im Konstruktor noch
155 keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich
156 mit <SfxItemPool::SetDefaults(SfxItemPool**)> geschehen.
161 <SfxItemPool::SetDefaults(SfxItemPool**)>
162 <SfxItemPool::ReleaseDefaults(SfxPoolItem**,USHORT,BOOL)>
163 <SfxItemPool::ReldaseDefaults(BOOL)>
172 pSlotIds(pSlotIdArray
),
174 pImp( new SfxItemPool_Impl( nStart
, nEnd
) ),
176 ppPoolDefaults(new SfxPoolItem
* [ nEndWhich
- nStartWhich
+ 1]),
180 bPersistentRefCounts(bLoadRefCounts
),
183 DBG_CTOR(SfxItemPool
, 0);
184 DBG_ASSERT(nStart
, "Start-Which-Id must be greater 0" );
186 pImp
->eDefMetric
= SFX_MAPUNIT_TWIP
;
188 pImp
->bStreaming
= FALSE
;
189 pImp
->nLoadingVersion
= 0;
190 pImp
->nInitRefCount
= 1;
191 pImp
->nVerStart
= nStart
;
192 pImp
->nVerEnd
= nEnd
;
193 pImp
->bInSetItem
= FALSE
;
194 pImp
->nStoringStart
= nStartWhich
;
195 pImp
->nStoringEnd
= nEndWhich
;
197 memset( ppPoolDefaults
, 0, sizeof( SfxPoolItem
* ) * (nEnd
- nStart
+ 1));
200 SetDefaults(pDefaults
);
203 // -----------------------------------------------------------------------
206 SfxItemPool::SfxItemPool
208 const SfxItemPool
& rPool
, // von dieser Instanz kopieren
209 BOOL bCloneStaticDefaults
/* TRUE
210 statische Defaults kopieren
219 Copy-Konstruktor der Klasse SfxItemPool.
224 <SfxItemPool::Clone()const>
227 : aName(rPool
.aName
),
228 nStart(rPool
.nStart
),
231 pItemInfos(rPool
.pItemInfos
),
233 pSlotIds(rPool
.pSlotIds
),
235 pImp( new SfxItemPool_Impl( nStart
, nEnd
) ),
237 ppPoolDefaults(new SfxPoolItem
* [ nEnd
- nStart
+ 1]),
241 bPersistentRefCounts(rPool
.bPersistentRefCounts
),
244 DBG_CTOR(SfxItemPool
, 0);
245 pImp
->eDefMetric
= rPool
.pImp
->eDefMetric
;
246 pImp
->nVersion
= rPool
.pImp
->nVersion
;
247 pImp
->bStreaming
= FALSE
;
248 pImp
->nLoadingVersion
= 0;
249 pImp
->nInitRefCount
= 1;
250 pImp
->nVerStart
= rPool
.pImp
->nVerStart
;
251 pImp
->nVerEnd
= rPool
.pImp
->nVerEnd
;
252 pImp
->bInSetItem
= FALSE
;
253 pImp
->nStoringStart
= nStart
;
254 pImp
->nStoringEnd
= nEnd
;
256 memset( ppPoolDefaults
, 0, sizeof( SfxPoolItem
* ) * (nEnd
- nStart
+ 1));
258 // Static Defaults "ubernehmen
259 if ( bCloneStaticDefaults
)
261 SfxPoolItem
**ppDefaults
= new SfxPoolItem
*[nEnd
-nStart
+1];
262 for ( USHORT n
= 0; n
<= nEnd
- nStart
; ++n
)
264 (*( ppDefaults
+ n
)) = (*( rPool
.ppStaticDefaults
+ n
))->Clone(this);
265 (*( ppDefaults
+ n
))->SetKind( SFX_ITEMS_STATICDEFAULT
);
268 SetDefaults( ppDefaults
);
271 SetDefaults( rPool
.ppStaticDefaults
);
273 // Pool Defaults kopieren
274 for ( USHORT n
= 0; n
<= nEnd
- nStart
; ++n
)
275 if ( (*( rPool
.ppPoolDefaults
+ n
)) )
277 (*( ppPoolDefaults
+ n
)) = (*( rPool
.ppPoolDefaults
+ n
))->Clone(this);
278 (*( ppPoolDefaults
+ n
))->SetKind( SFX_ITEMS_POOLDEFAULT
);
281 // Version-Map kopieren
282 USHORT nVerCount
= rPool
.pImp
->aVersions
.Count();
283 for ( USHORT nVer
= 0; nVer
< nVerCount
; ++nVer
)
285 const SfxPoolVersion_Impl
*pOld
= rPool
.pImp
->aVersions
.GetObject(nVer
);
286 const SfxPoolVersion_Impl
*pNew
= new SfxPoolVersion_Impl( *pOld
);
287 pImp
->aVersions
.Insert( pNew
, nVer
);
290 // Verkettung wiederherstellen
291 if ( rPool
.pSecondary
)
292 SetSecondaryPool( rPool
.pSecondary
->Clone() );
295 // -----------------------------------------------------------------------
297 void SfxItemPool::SetDefaults( SfxPoolItem
**pDefaults
)
299 DBG_CHKTHIS(SfxItemPool
, 0);
300 DBG_ASSERT( pDefaults
, "erst wollen, dann nichts geben..." );
301 DBG_ASSERT( !ppStaticDefaults
, "habe schon defaults" );
303 ppStaticDefaults
= pDefaults
;
304 //! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT )
305 //! geht wohl nicht im Zshg mit SetItems, die hinten stehen
307 DBG_ASSERT( (*ppStaticDefaults
)->GetRefCount() == 0 ||
308 IsDefaultItem( (*ppStaticDefaults
) ),
309 "das sind keine statics" );
310 for ( USHORT n
= 0; n
<= nEnd
- nStart
; ++n
)
312 SFX_ASSERT( (*( ppStaticDefaults
+ n
))->Which() == n
+ nStart
,
313 n
+ nStart
, "static defaults not sorted" );
314 (*( ppStaticDefaults
+ n
))->SetKind( SFX_ITEMS_STATICDEFAULT
);
315 DBG_ASSERT( !(pImp
->ppPoolItems
[n
]), "defaults with setitems with items?!" );
320 // -----------------------------------------------------------------------
322 void SfxItemPool::ReleaseDefaults
325 l"oscht sowohl das Array als auch die einzelnen
329 l"oscht weder das Array noch die einzelnen
330 statischen Defaults */
335 Gibt die statischen Defaults der betreffenden SfxItemPool-Instanz frei
336 und l"oscht ggf. die statischen Defaults.
338 Nach Aufruf dieser Methode darf die SfxItemPool-Instanz nicht mehr
339 verwendet werden, einzig ist der Aufruf des Destruktors zu"lassig.
343 DBG_ASSERT( ppStaticDefaults
, "keine Arme keine Kekse" );
344 ReleaseDefaults( ppStaticDefaults
, nEnd
- nStart
+ 1, bDelete
);
346 // KSO (22.10.98): ppStaticDefaults zeigt auf geloeschten Speicher,
347 // wenn bDelete == TRUE.
349 ppStaticDefaults
= 0;
352 // -----------------------------------------------------------------------
354 void SfxItemPool::ReleaseDefaults
356 SfxPoolItem
** pDefaults
, /* freizugebende statische Defaults */
358 USHORT nCount
, /* Anzahl der statischen Defaults */
361 l"oscht sowohl das Array als auch die
362 einzelnen statischen Defaults
365 l"oscht weder das Array noch die
366 einzelnen statischen Defaults */
371 Gibt die angegebenen statischen Defaults frei und l"oscht ggf.
372 die statischen Defaults.
374 Diese Methode darf erst nach Zerst"orung aller SfxItemPool-Instanzen,
375 welche die angegebenen statischen Defaults 'pDefault' verwenden,
380 DBG_ASSERT( pDefaults
, "erst wollen, dann nichts geben..." );
382 for ( USHORT n
= 0; n
< nCount
; ++n
)
384 SFX_ASSERT( IsStaticDefaultItem( *(pDefaults
+n
) ),
385 n
, "das ist kein static-default" );
386 (*( pDefaults
+ n
))->SetRefCount( 0 );
388 { delete *( pDefaults
+ n
); *(pDefaults
+ n
) = 0; }
392 { delete[] pDefaults
; pDefaults
= 0; }
395 // -----------------------------------------------------------------------
397 SfxItemPool::~SfxItemPool()
399 DBG_DTOR(SfxItemPool
, 0);
400 DBG_ASSERT( pMaster
== this, "destroying active Secondary-Pool" );
402 if ( pImp
->ppPoolItems
&& ppPoolDefaults
)
404 delete[] _pPoolRanges
;
408 void SfxItemPool::Free(SfxItemPool
* pPool
)
412 // tell all the registered SfxItemPoolUsers that the pool is in destruction
413 SfxItemPoolUserVector
aListCopy(pPool
->maSfxItemPoolUsers
.begin(), pPool
->maSfxItemPoolUsers
.end());
414 for(SfxItemPoolUserVector::iterator aIterator
= aListCopy
.begin(); aIterator
!= aListCopy
.end(); aIterator
++)
416 SfxItemPoolUser
* pSfxItemPoolUser
= *aIterator
;
417 DBG_ASSERT(pSfxItemPoolUser
, "corrupt SfxItemPoolUser list (!)");
418 pSfxItemPoolUser
->ObjectInDestruction(*pPool
);
421 // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser()
422 // when they get called from ObjectInDestruction().
423 pPool
->maSfxItemPoolUsers
.clear();
430 // -----------------------------------------------------------------------
433 void SfxItemPool::SetSecondaryPool( SfxItemPool
*pPool
)
435 // ggf. an abgeh"angten Pools den Master zur"ucksetzen
439 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
440 if ( ppStaticDefaults
)
442 // Delete() ist noch nicht gelaufen?
443 if ( pImp
->ppPoolItems
&& pSecondary
->pImp
->ppPoolItems
)
445 // hat der master SetItems?
446 BOOL bHasSetItems
= FALSE
;
447 for ( USHORT i
= 0; !bHasSetItems
&& i
< nEnd
-nStart
; ++i
)
448 bHasSetItems
= ppStaticDefaults
[i
]->ISA(SfxSetItem
);
450 // abgehaengte Pools muessen leer sein
451 BOOL bOK
= bHasSetItems
;
453 bOK
&& n
<= pSecondary
->nEnd
- pSecondary
->nStart
;
456 SfxPoolItemArray_Impl
** ppItemArr
=
457 pSecondary
->pImp
->ppPoolItems
+ n
;
460 SfxPoolItem
** ppHtArr
=
461 (SfxPoolItem
**)(*ppItemArr
)->GetData();
462 for( USHORT i
= (*ppItemArr
)->Count(); i
; ++ppHtArr
, --i
)
465 DBG_ERROR( "old secondary pool must be empty" );
475 pSecondary
->pMaster
= pSecondary
;
476 for ( SfxItemPool
*p
= pSecondary
->pSecondary
; p
; p
= p
->pSecondary
)
477 p
->pMaster
= pSecondary
;
480 // ggf. den Master der neuen Secondary-Pools setzen
481 DBG_ASSERT( !pPool
|| pPool
->pMaster
== pPool
, "Secondary tanzt auf zwei Hochzeiten " );
482 SfxItemPool
*pNewMaster
= pMaster
? pMaster
: this;
483 for ( SfxItemPool
*p
= pPool
; p
; p
= p
->pSecondary
)
484 p
->pMaster
= pNewMaster
;
486 // neuen Secondary-Pool merken
490 // -----------------------------------------------------------------------
492 SfxMapUnit
SfxItemPool::GetMetric( USHORT
) const
494 DBG_CHKTHIS(SfxItemPool
, 0);
496 return pImp
->eDefMetric
;
499 // -----------------------------------------------------------------------
501 void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric
)
503 DBG_CHKTHIS(SfxItemPool
, 0);
505 pImp
->eDefMetric
= eNewMetric
;
508 // -----------------------------------------------------------------------
510 SfxItemPresentation
SfxItemPool::GetPresentation
512 const SfxPoolItem
& rItem
, /* IN: <SfxPoolItem>, dessen textuelle
513 Wert-Darstellung geliefert werden
515 SfxItemPresentation ePresent
, /* IN: gew"unschte Art der Darstellung;
516 siehe <SfxItemPresentation> */
517 SfxMapUnit eMetric
, /* IN: gew"unschte Ma\seinheit der Darstellung */
518 XubString
& rText
, /* OUT: textuelle Darstellung von 'rItem' */
519 const IntlWrapper
* pIntlWrapper
524 "Uber diese virtuelle Methode k"onnen textuelle Darstellungen der
525 von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems
528 In Ableitungen sollte diese Methode "uberladen werden und auf
529 SfxPoolItems reagiert werden, die bei <SfxPoolItem::GetPresentation()const>
530 keine vollst"andige Information liefern k"onnen.
532 Die Basisklasse liefert die unver"anderte Presentation von 'rItem'.
536 DBG_CHKTHIS(SfxItemPool
, 0);
537 return rItem
.GetPresentation(
538 ePresent
, GetMetric(rItem
.Which()), eMetric
, rText
, pIntlWrapper
);
542 // -----------------------------------------------------------------------
544 SfxItemPool
* SfxItemPool::Clone() const
546 DBG_CHKTHIS(SfxItemPool
, 0);
548 SfxItemPool
*pPool
= new SfxItemPool( *this );
552 // ----------------------------------------------------------------------
554 void SfxItemPool::Delete()
556 DBG_CHKTHIS(SfxItemPool
, 0);
559 if ( !pImp
->ppPoolItems
|| !ppPoolDefaults
)
562 // z.B. laufenden Requests bescheidsagen
563 pImp
->aBC
.Broadcast( SfxSimpleHint( SFX_HINT_DYING
) );
565 //MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems.
566 //Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt.
568 SfxPoolItemArray_Impl
** ppItemArr
= pImp
->ppPoolItems
;
569 SfxPoolItem
** ppDefaultItem
= ppPoolDefaults
;
570 SfxPoolItem
** ppStaticDefaultItem
= ppStaticDefaults
;
573 //Erst die SetItems abraeumen
574 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
575 if ( ppStaticDefaults
)
577 for ( nArrCnt
= GetSize_Impl();
579 --nArrCnt
, ++ppItemArr
, ++ppDefaultItem
, ++ppStaticDefaultItem
)
581 // KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer
582 // von SfxItemPool abgeleiteten Klasse bereits geloescht worden
583 // sein! -> CHAOS Itempool
584 if ( *ppStaticDefaultItem
&& (*ppStaticDefaultItem
)->ISA(SfxSetItem
) )
588 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
589 for ( USHORT n
= (*ppItemArr
)->Count(); n
; --n
, ++ppHtArr
)
593 ReleaseRef( **ppHtArr
, (*ppHtArr
)->GetRefCount() );
597 DELETEZ( *ppItemArr
);
599 if ( *ppDefaultItem
)
602 SetRefCount( **ppDefaultItem
, 0 );
604 DELETEZ( *ppDefaultItem
);
610 ppItemArr
= pImp
->ppPoolItems
;
611 ppDefaultItem
= ppPoolDefaults
;
613 //Jetzt die 'einfachen' Items
614 for ( nArrCnt
= GetSize_Impl();
616 --nArrCnt
, ++ppItemArr
, ++ppDefaultItem
)
620 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
621 for ( USHORT n
= (*ppItemArr
)->Count(); n
; --n
, ++ppHtArr
)
625 ReleaseRef( **ppHtArr
, (*ppHtArr
)->GetRefCount() );
631 if ( *ppDefaultItem
)
634 SetRefCount( **ppDefaultItem
, 0 );
636 delete *ppDefaultItem
;
641 delete[] ppPoolDefaults
; ppPoolDefaults
= 0;
644 // ----------------------------------------------------------------------
646 void SfxItemPool::Cleanup()
648 DBG_CHKTHIS(SfxItemPool
, 0);
650 //MA 16. Apr. 97: siehe ::Delete()
652 SfxPoolItemArray_Impl
** ppItemArr
= pImp
->ppPoolItems
;
653 SfxPoolItem
** ppDefaultItem
= ppPoolDefaults
;
654 SfxPoolItem
** ppStaticDefaultItem
= ppStaticDefaults
;
657 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
658 if ( ppStaticDefaults
) //HACK fuer Image, dort gibt es keine Statics!!
660 for ( nArrCnt
= GetSize_Impl();
662 --nArrCnt
, ++ppItemArr
, ++ppDefaultItem
, ++ppStaticDefaultItem
)
664 //Fuer jedes Item gibt es entweder ein Default oder ein static Default!
666 ((*ppDefaultItem
&& (*ppDefaultItem
)->ISA(SfxSetItem
)) ||
667 (*ppStaticDefaultItem
)->ISA(SfxSetItem
)) )
669 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
670 for ( USHORT n
= (*ppItemArr
)->Count(); n
; --n
, ++ppHtArr
)
671 if ( *ppHtArr
&& !(*ppHtArr
)->GetRefCount() )
679 ppItemArr
= pImp
->ppPoolItems
;
681 for ( nArrCnt
= GetSize_Impl();
683 --nArrCnt
, ++ppItemArr
)
687 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
688 for ( USHORT n
= (*ppItemArr
)->Count(); n
; --n
, ++ppHtArr
)
689 if ( *ppHtArr
&& !(*ppHtArr
)->GetRefCount() )
695 // ----------------------------------------------------------------------
697 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem
&rItem
)
699 DBG_CHKTHIS(SfxItemPool
, 0);
700 if ( IsInRange(rItem
.Which()) )
702 SfxPoolItem
**ppOldDefault
=
703 ppPoolDefaults
+ GetIndex_Impl(rItem
.Which());
704 SfxPoolItem
*pNewDefault
= rItem
.Clone(this);
705 pNewDefault
->SetKind(SFX_ITEMS_POOLDEFAULT
);
708 (*ppOldDefault
)->SetRefCount(0);
709 DELETEZ( *ppOldDefault
);
711 *ppOldDefault
= pNewDefault
;
713 else if ( pSecondary
)
714 pSecondary
->SetPoolDefaultItem(rItem
);
717 SFX_ASSERT( 0, rItem
.Which(), "unknown Which-Id - cannot set pool default" );
722 * Resets the default of the given <Which-Id> back to the static default.
723 * If a pool default exists it is removed.
725 void SfxItemPool::ResetPoolDefaultItem( USHORT nWhichId
)
727 DBG_CHKTHIS(SfxItemPool
, 0);
728 if ( IsInRange(nWhichId
) )
730 SfxPoolItem
**ppOldDefault
=
731 ppPoolDefaults
+ GetIndex_Impl( nWhichId
);
734 (*ppOldDefault
)->SetRefCount(0);
735 DELETEZ( *ppOldDefault
);
738 else if ( pSecondary
)
739 pSecondary
->ResetPoolDefaultItem(nWhichId
);
742 SFX_ASSERT( 0, nWhichId
, "unknown Which-Id - cannot set pool default" );
746 // -----------------------------------------------------------------------
748 const SfxPoolItem
& SfxItemPool::Put( const SfxPoolItem
& rItem
, USHORT nWhich
)
750 DBG_ASSERT( !rItem
.ISA(SfxSetItem
) ||
751 0 != &((const SfxSetItem
&)rItem
).GetItemSet(),
752 "SetItem without ItemSet" );
754 DBG_CHKTHIS(SfxItemPool
, 0);
756 nWhich
= rItem
.Which();
758 // richtigen Secondary-Pool finden
759 BOOL bSID
= nWhich
> SFX_WHICH_MAX
;
760 if ( !bSID
&& !IsInRange(nWhich
) )
763 return pSecondary
->Put( rItem
, nWhich
);
764 DBG_ERROR( "unknown Which-Id - cannot put item" );
767 // SID oder nicht poolable (neue Definition)?
768 USHORT nIndex
= bSID
? USHRT_MAX
: GetIndex_Impl(nWhich
);
769 if ( USHRT_MAX
== nIndex
||
770 IsItemFlag_Impl( nIndex
, SFX_ITEM_NOT_POOLABLE
) )
772 SFX_ASSERT( USHRT_MAX
!= nIndex
|| rItem
.Which() != nWhich
||
773 !IsDefaultItem(&rItem
) || rItem
.GetKind() == SFX_ITEMS_DELETEONIDLE
,
774 nWhich
, "ein nicht Pool-Item ist Default?!" );
775 SfxPoolItem
*pPoolItem
= rItem
.Clone(pMaster
);
776 pPoolItem
->SetWhich(nWhich
);
777 AddRef( *pPoolItem
);
781 SFX_ASSERT( rItem
.IsA(GetDefaultItem(nWhich
).Type()), nWhich
,
782 "SFxItemPool: wrong item type in Put" );
784 SfxPoolItemArray_Impl
** ppItemArr
= pImp
->ppPoolItems
+ nIndex
;
786 *ppItemArr
= new SfxPoolItemArray_Impl
;
788 SfxPoolItem
**ppFree
= 0;
789 SfxPoolItem
** ppHtArray
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
790 if ( IsItemFlag_Impl( nIndex
, SFX_ITEM_POOLABLE
) )
792 // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein
793 if ( IsPooledItem(&rItem
) )
795 // 1. Schleife: teste ob der Pointer vorhanden ist.
796 for( USHORT n
= (*ppItemArr
)->Count(); n
; ++ppHtArray
, --n
)
797 if( &rItem
== (*ppHtArray
) )
799 AddRef( **ppHtArray
);
804 // 2. Schleife: dann muessen eben die Attribute verglichen werden
806 for ( n
= (*ppItemArr
)->Count(), ppHtArray
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
807 n
; ++ppHtArray
, --n
)
811 if( **ppHtArray
== rItem
)
813 AddRef( **ppHtArray
);
824 // freien Platz suchen
825 SfxPoolItem
** ppHtArr
;
826 USHORT n
, nCount
= (*ppItemArr
)->Count();
827 for ( n
= (*ppItemArr
)->nFirstFree
,
828 ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData() + n
;
837 // naechstmoeglichen freien Platz merken
838 (*ppItemArr
)->nFirstFree
= n
;
841 // nicht vorhanden, also im PtrArray eintragen
842 SfxPoolItem
* pNewItem
= rItem
.Clone(pMaster
);
843 pNewItem
->SetWhich(nWhich
);
845 SFX_ASSERT( rItem
.Type() == pNewItem
->Type(), nWhich
, "unequal types in Put(): no Clone()?" )
847 if ( !rItem
.ISA(SfxSetItem
) )
849 SFX_ASSERT( !IsItemFlag(nWhich
, SFX_ITEM_POOLABLE
) ||
851 nWhich
, "unequal items in Put(): no operator==?" );
852 SFX_ASSERT( !IsItemFlag(*pNewItem
, SFX_ITEM_POOLABLE
) ||
854 nWhich
, "unequal items in Put(): no operator==?" );
858 AddRef( *pNewItem
, pImp
->nInitRefCount
);
859 const SfxPoolItem
* pTemp
= pNewItem
;
861 (*ppItemArr
)->Insert( pTemp
, (*ppItemArr
)->Count() );
864 DBG_ASSERT( *ppFree
== 0, "using surrogate in use" );
870 // -----------------------------------------------------------------------
872 void SfxItemPool::Remove( const SfxPoolItem
& rItem
)
874 DBG_CHKTHIS(SfxItemPool
, 0);
876 DBG_ASSERT( !rItem
.ISA(SfxSetItem
) ||
877 0 != &((const SfxSetItem
&)rItem
).GetItemSet(),
878 "SetItem without ItemSet" );
880 SFX_ASSERT( !IsPoolDefaultItem(&rItem
), rItem
.Which(),
881 "wo kommt denn hier ein Pool-Default her" );
883 // richtigen Secondary-Pool finden
884 const USHORT nWhich
= rItem
.Which();
885 BOOL bSID
= nWhich
> SFX_WHICH_MAX
;
886 if ( !bSID
&& !IsInRange(nWhich
) )
890 pSecondary
->Remove( rItem
);
893 DBG_ERROR( "unknown Which-Id - cannot remove item" );
896 // SID oder nicht poolable (neue Definition)?
897 USHORT nIndex
= bSID
? USHRT_MAX
: GetIndex_Impl(nWhich
);
898 if ( bSID
|| IsItemFlag_Impl( nIndex
, SFX_ITEM_NOT_POOLABLE
) )
900 SFX_ASSERT( USHRT_MAX
!= nIndex
||
901 !IsDefaultItem(&rItem
), rItem
.Which(),
902 "ein nicht Pool-Item ist Default?!" );
903 if ( 0 == ReleaseRef(rItem
) )
905 SfxPoolItem
*pItem
= &(SfxPoolItem
&)rItem
;
911 SFX_ASSERT( rItem
.GetRefCount(), rItem
.Which(), "RefCount == 0, Remove unmoeglich" );
913 // statische Defaults sind eben einfach da
914 if ( rItem
.GetKind() == SFX_ITEMS_STATICDEFAULT
&&
915 &rItem
== *( ppStaticDefaults
+ GetIndex_Impl(nWhich
) ) )
918 // Item im eigenen Pool suchen
919 SfxPoolItemArray_Impl
** ppItemArr
= (pImp
->ppPoolItems
+ nIndex
);
920 SFX_ASSERT( *ppItemArr
, rItem
.Which(), "removing Item not in Pool" );
921 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
922 for( USHORT n
= (*ppItemArr
)->Count(); n
; ++ppHtArr
, --n
)
923 if( *ppHtArr
== &rItem
)
925 if ( (*ppHtArr
)->GetRefCount() ) //!
926 ReleaseRef( **ppHtArr
);
929 SFX_ASSERT( 0, rItem
.Which(), "removing Item without ref" );
930 SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr
);
933 // ggf. kleinstmoegliche freie Position merken
934 USHORT nPos
= (*ppItemArr
)->Count() - n
;
935 if ( (*ppItemArr
)->nFirstFree
> nPos
)
936 (*ppItemArr
)->nFirstFree
= nPos
;
938 //! MI: Hack, solange wir das Problem mit dem Outliner haben
939 //! siehe anderes MI-REF
940 if ( 0 == (*ppHtArr
)->GetRefCount() && nWhich
< 4000 )
946 SFX_ASSERT( 0, rItem
.Which(), "removing Item not in Pool" );
947 SFX_TRACE( "to be removed, but not in pool: ", &rItem
);
950 // -----------------------------------------------------------------------
952 const SfxPoolItem
& SfxItemPool::GetDefaultItem( USHORT nWhich
) const
954 DBG_CHKTHIS(SfxItemPool
, 0);
956 if ( !IsInRange(nWhich
) )
959 return pSecondary
->GetDefaultItem( nWhich
);
960 SFX_ASSERT( 0, nWhich
, "unknown which - dont ask me for defaults" );
963 DBG_ASSERT( ppStaticDefaults
, "no defaults known - dont ask me for defaults" );
964 USHORT nPos
= GetIndex_Impl(nWhich
);
965 SfxPoolItem
*pDefault
= *(ppPoolDefaults
+ nPos
);
968 return **(ppStaticDefaults
+ nPos
);
971 // -----------------------------------------------------------------------
974 void SfxItemPool::FreezeIdRanges()
978 This method should be called at the master pool, when all secondary
979 pools are appended to it.
981 It calculates the ranges of 'which-ids' for fast construction of
982 item-sets, which contains all 'which-ids'.
986 FillItemIdRanges_Impl( _pPoolRanges
);
990 // -----------------------------------------------------------------------
992 void SfxItemPool::FillItemIdRanges_Impl( USHORT
*& pWhichRanges
) const
994 DBG_CHKTHIS(SfxItemPool
, 0);
995 DBG_ASSERT( !_pPoolRanges
, "GetFrozenRanges() would be faster!" );
997 const SfxItemPool
*pPool
;
999 for( pPool
= this; pPool
; pPool
= pPool
->pSecondary
)
1002 pWhichRanges
= new USHORT
[ 2*nLevel
+ 1 ];
1005 for( pPool
= this; pPool
; pPool
= pPool
->pSecondary
)
1007 *(pWhichRanges
+(nLevel
++)) = pPool
->nStart
;
1008 *(pWhichRanges
+(nLevel
++)) = pPool
->nEnd
;
1009 *(pWhichRanges
+nLevel
) = 0;
1013 // -----------------------------------------------------------------------
1015 const SfxPoolItem
*SfxItemPool::GetItem(USHORT nWhich
, USHORT nOfst
) const
1017 DBG_CHKTHIS(SfxItemPool
, 0);
1019 if ( !IsInRange(nWhich
) )
1022 return pSecondary
->GetItem( nWhich
, nOfst
);
1023 SFX_ASSERT( 0, nWhich
, "unknown Which-Id - cannot resolve surrogate" );
1028 if ( nOfst
== SFX_ITEMS_STATICDEFAULT
)
1029 return *(ppStaticDefaults
+ GetIndex_Impl(nWhich
));
1031 SfxPoolItemArray_Impl
* pItemArr
= *(pImp
->ppPoolItems
+ GetIndex_Impl(nWhich
));
1032 if( pItemArr
&& nOfst
< pItemArr
->Count() )
1033 return (*pItemArr
)[nOfst
];
1038 // -----------------------------------------------------------------------
1040 USHORT
SfxItemPool::GetItemCount(USHORT nWhich
) const
1042 DBG_CHKTHIS(SfxItemPool
, 0);
1044 if ( !IsInRange(nWhich
) )
1047 return pSecondary
->GetItemCount( nWhich
);
1048 SFX_ASSERT( 0, nWhich
, "unknown Which-Id - cannot resolve surrogate" );
1052 SfxPoolItemArray_Impl
* pItemArr
= *(pImp
->ppPoolItems
+ GetIndex_Impl(nWhich
));
1054 return pItemArr
->Count();
1058 // -----------------------------------------------------------------------
1060 USHORT
SfxItemPool::GetWhich( USHORT nSlotId
, BOOL bDeep
) const
1062 if ( !IsSlot(nSlotId
) )
1066 USHORT nCount
= nEnd
- nStart
+ 1;
1067 for ( USHORT nOfs
= 0; nOfs
< nCount
; ++nOfs
)
1068 if ( pItemInfos
[nOfs
]._nSID
== nSlotId
)
1069 return nOfs
+ nStart
;
1073 USHORT nCount
= nEnd
- nStart
+ 1;
1074 for ( USHORT nOfs
= 0; nOfs
< nCount
; ++nOfs
)
1075 if ( pSlotIds
[nOfs
] == nSlotId
)
1076 return nOfs
+ nStart
;
1079 if ( pSecondary
&& bDeep
)
1080 return pSecondary
->GetWhich(nSlotId
);
1084 // -----------------------------------------------------------------------
1086 USHORT
SfxItemPool::GetSlotId( USHORT nWhich
, BOOL bDeep
) const
1088 if ( !IsWhich(nWhich
) )
1091 if ( !IsInRange( nWhich
) )
1093 if ( pSecondary
&& bDeep
)
1094 return pSecondary
->GetSlotId(nWhich
);
1095 SFX_ASSERT( 0, nWhich
, "unknown Which-Id - cannot get slot-id" );
1100 USHORT nSID
= pItemInfos
[nWhich
- nStart
]._nSID
;
1101 return nSID
? nSID
: nWhich
;
1103 else if ( pSlotIds
)
1104 return pSlotIds
[nWhich
- nStart
];
1109 // -----------------------------------------------------------------------
1111 USHORT
SfxItemPool::GetTrueWhich( USHORT nSlotId
, BOOL bDeep
) const
1113 if ( !IsSlot(nSlotId
) )
1117 USHORT nCount
= nEnd
- nStart
+ 1;
1118 for ( USHORT nOfs
= 0; nOfs
< nCount
; ++nOfs
)
1119 if ( pItemInfos
[nOfs
]._nSID
== nSlotId
)
1120 return nOfs
+ nStart
;
1124 USHORT nCount
= nEnd
- nStart
+ 1;
1125 for ( USHORT nOfs
= 0; nOfs
< nCount
; ++nOfs
)
1126 if ( pSlotIds
[nOfs
] == nSlotId
)
1127 return nOfs
+ nStart
;
1130 if ( pSecondary
&& bDeep
)
1131 return pSecondary
->GetTrueWhich(nSlotId
);
1135 // -----------------------------------------------------------------------
1137 USHORT
SfxItemPool::GetTrueSlotId( USHORT nWhich
, BOOL bDeep
) const
1139 if ( !IsWhich(nWhich
) )
1142 if ( !IsInRange( nWhich
) )
1144 if ( pSecondary
&& bDeep
)
1145 return pSecondary
->GetTrueSlotId(nWhich
);
1146 SFX_ASSERT( 0, nWhich
, "unknown Which-Id - cannot get slot-id" );
1150 return pItemInfos
[nWhich
- nStart
]._nSID
;
1152 else if ( pSlotIds
)
1153 return pSlotIds
[nWhich
- nStart
];
1158 // -----------------------------------------------------------------------
1159 void SfxItemPool::SetFileFormatVersion( USHORT nFileFormatVersion
)
1163 You must call this function to set the file format version after
1164 concatenating your secondary-pools but before you store any
1165 pool, itemset or item. Only set the version at the master pool,
1166 never at any secondary pool.
1170 DBG_ASSERT( this == pMaster
,
1171 "SfxItemPool::SetFileFormatVersion() but not a master pool" );
1172 for ( SfxItemPool
*pPool
= this; pPool
; pPool
= pPool
->pSecondary
)
1173 pPool
->_nFileFormatVersion
= nFileFormatVersion
;