xref: /trunk/main/svl/source/items/itempool.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svl.hxx"
30 
31 #include <string.h>
32 #include <stdio.h>
33 #ifndef GCC
34 #endif
35 
36 #include <svl/itempool.hxx>
37 #include "whassert.hxx"
38 #include <svl/brdcst.hxx>
39 #include <svl/smplhint.hxx>
40 #include "poolio.hxx"
41 
42 //========================================================================
43 
44 
45 void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser)
46 {
47     maSfxItemPoolUsers.push_back(&rNewUser);
48 }
49 
50 void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser)
51 {
52     const SfxItemPoolUserVector::iterator aFindResult = ::std::find(maSfxItemPoolUsers.begin(), maSfxItemPoolUsers.end(), &rOldUser);
53     if(aFindResult != maSfxItemPoolUsers.end())
54     {
55         maSfxItemPoolUsers.erase(aFindResult);
56     }
57 }
58 
59 const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const
60 {
61     DBG_CHKTHIS(SfxItemPool, 0);
62     const SfxPoolItem* pRet;
63     if( IsInRange( nWhich ) )
64         pRet = *(ppPoolDefaults + GetIndex_Impl( nWhich ));
65     else if( pSecondary )
66         pRet = pSecondary->GetPoolDefaultItem( nWhich );
67     else
68     {
69         SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get pool default" );
70         pRet = 0;
71     }
72     return pRet;
73 }
74 
75 // -----------------------------------------------------------------------
76 
77 inline FASTBOOL SfxItemPool::IsItemFlag_Impl( sal_uInt16 nPos, sal_uInt16 nFlag ) const
78 {
79     sal_uInt16 nItemFlag = pItemInfos[nPos]._nFlags;
80     return nFlag == (nItemFlag & nFlag);
81 }
82 
83 // -----------------------------------------------------------------------
84 
85 FASTBOOL SfxItemPool::IsItemFlag( sal_uInt16 nWhich, sal_uInt16 nFlag ) const
86 {
87     for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary )
88     {
89         if ( pPool->IsInRange(nWhich) )
90             return pPool->IsItemFlag_Impl( pPool->GetIndex_Impl(nWhich), nFlag);
91     }
92     DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" );
93     return sal_False;
94 }
95 
96 // -----------------------------------------------------------------------
97 
98 SfxBroadcaster& SfxItemPool::BC()
99 {
100     return pImp->aBC;
101 }
102 
103 // -----------------------------------------------------------------------
104 
105 
106 SfxItemPool::SfxItemPool
107 (
108     UniString const &   rName,          /* Name des Pools zur Idetifikation
109                                            im File-Format */
110     sal_uInt16              nStartWhich,    /* erste Which-Id des Pools */
111     sal_uInt16              nEndWhich,      /* letzte Which-Id des Pools */
112 #ifdef TF_POOLABLE
113     const SfxItemInfo*  pInfos,         /* SID-Map und Item-Flags */
114 #endif
115     SfxPoolItem**       pDefaults,      /* Pointer auf statische Defaults,
116                                            wird direkt vom Pool referenziert,
117                                            jedoch kein Eigent"umer"ubergang */
118 #ifndef TF_POOLABLE
119     sal_uInt16*             pSlotIdArray,   /* Zuordnung von Slot-Ids zu Which-Ids */
120 #endif
121     FASTBOOL            bLoadRefCounts  /* Ref-Counts mitladen oder auf 1 setzen */
122 )
123 
124 /*  [Beschreibung]
125 
126     Der im Normalfall verwendete Konstruktor der Klasse SfxItemPool. Es
127     wird eine SfxItemPool-Instanz initialisiert, die Items im b"undigen
128     Which-Bereich von 'nStartWhich' bis 'nEndWhich' verwalten kann.
129 
130     F"ur jede dieser Which-Ids mu\s ein statischer Default im Array 'pDefaults'
131     vorhanden sein, die dort beginnend mit einem <SfxPoolItem> mit der
132     Which-Id 'nStartWhich' nach Which-Ids sortiert aufeinanderfolgend
133     eingetragen sein m"ussen.
134 
135     'pItemInfos' ist ein identisch angeordnetes Array von USHORTs, die
136     Slot-Ids darstellen und Flags. Die Slot-Ids k"onnen 0 sein, wenn die
137     betreffenden Items ausschlie\slich in der Core verwendet werden.
138     "Uber die Flags kann z.B. bestimmt werden, ob Value-Sharing
139     (SFX_ITEM_POOLABLE) stattfinden soll.
140 
141     [Anmerkung]
142 
143     Wenn der Pool <SfxSetItem>s enthalten soll, k"onnen im Konstruktor noch
144     keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich
145     mit <SfxItemPool::SetDefaults(SfxItemPool**)> geschehen.
146 
147 
148     [Querverweise]
149 
150     <SfxItemPool::SetDefaults(SfxItemPool**)>
151     <SfxItemPool::ReleaseDefaults(SfxPoolItem**,sal_uInt16,sal_Bool)>
152     <SfxItemPool::ReldaseDefaults(sal_Bool)>
153 */
154 
155 :   aName(rName),
156     nStart(nStartWhich),
157     nEnd(nEndWhich),
158 #ifdef TF_POOLABLE
159     pItemInfos(pInfos),
160 #else
161     pSlotIds(pSlotIdArray),
162 #endif
163     pImp( new SfxItemPool_Impl( nStart, nEnd ) ),
164     ppStaticDefaults(0),
165     ppPoolDefaults(new SfxPoolItem* [ nEndWhich - nStartWhich + 1]),
166     pSecondary(0),
167     pMaster(this),
168     _pPoolRanges( 0 ),
169     bPersistentRefCounts(bLoadRefCounts),
170     maSfxItemPoolUsers()
171 {
172     DBG_CTOR(SfxItemPool, 0);
173     DBG_ASSERT(nStart, "Start-Which-Id must be greater 0" );
174 
175     pImp->eDefMetric = SFX_MAPUNIT_TWIP;
176     pImp->nVersion = 0;
177     pImp->bStreaming = sal_False;
178     pImp->nLoadingVersion = 0;
179     pImp->nInitRefCount = 1;
180     pImp->nVerStart = nStart;
181     pImp->nVerEnd = nEnd;
182     pImp->bInSetItem = sal_False;
183     pImp->nStoringStart = nStartWhich;
184     pImp->nStoringEnd = nEndWhich;
185 
186     memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1));
187 
188     if ( pDefaults )
189         SetDefaults(pDefaults);
190 }
191 
192 // -----------------------------------------------------------------------
193 
194 
195 SfxItemPool::SfxItemPool
196 (
197     const SfxItemPool&  rPool,                  //  von dieser Instanz kopieren
198     sal_Bool                bCloneStaticDefaults    /*  sal_True
199                                                     statische Defaults kopieren
200 
201                                                     sal_False
202                                                     statische Defaults
203                                                     "ubernehehmen */
204 )
205 
206 /*  [Beschreibung]
207 
208     Copy-Konstruktor der Klasse SfxItemPool.
209 
210 
211     [Querverweise]
212 
213     <SfxItemPool::Clone()const>
214 */
215 
216 :   aName(rPool.aName),
217     nStart(rPool.nStart),
218     nEnd(rPool.nEnd),
219 #ifdef TF_POOLABLE
220     pItemInfos(rPool.pItemInfos),
221 #else
222     pSlotIds(rPool.pSlotIds),
223 #endif
224     pImp( new SfxItemPool_Impl( nStart, nEnd ) ),
225     ppStaticDefaults(0),
226     ppPoolDefaults(new SfxPoolItem* [ nEnd - nStart + 1]),
227     pSecondary(0),
228     pMaster(this),
229     _pPoolRanges( 0 ),
230     bPersistentRefCounts(rPool.bPersistentRefCounts ),
231     maSfxItemPoolUsers()
232 {
233     DBG_CTOR(SfxItemPool, 0);
234     pImp->eDefMetric = rPool.pImp->eDefMetric;
235     pImp->nVersion = rPool.pImp->nVersion;
236     pImp->bStreaming = sal_False;
237     pImp->nLoadingVersion = 0;
238     pImp->nInitRefCount = 1;
239     pImp->nVerStart = rPool.pImp->nVerStart;
240     pImp->nVerEnd = rPool.pImp->nVerEnd;
241     pImp->bInSetItem = sal_False;
242     pImp->nStoringStart = nStart;
243     pImp->nStoringEnd = nEnd;
244 
245     memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1));
246 
247     // Static Defaults "ubernehmen
248     if ( bCloneStaticDefaults )
249     {
250         SfxPoolItem **ppDefaults = new SfxPoolItem*[nEnd-nStart+1];
251         for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n )
252         {
253             (*( ppDefaults + n )) = (*( rPool.ppStaticDefaults + n ))->Clone(this);
254             (*( ppDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
255         }
256 
257         SetDefaults( ppDefaults );
258     }
259     else
260         SetDefaults( rPool.ppStaticDefaults );
261 
262     // Pool Defaults kopieren
263     for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n )
264         if ( (*( rPool.ppPoolDefaults + n )) )
265         {
266             (*( ppPoolDefaults + n )) = (*( rPool.ppPoolDefaults + n ))->Clone(this);
267             (*( ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT );
268         }
269 
270     // Copy Version-Map
271     for ( size_t nVer = 0; nVer < rPool.pImp->aVersions.size(); ++nVer )
272     {
273         const SfxPoolVersion_ImplPtr pOld = rPool.pImp->aVersions[nVer];
274         SfxPoolVersion_ImplPtr pNew = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl( *pOld ) );
275         pImp->aVersions.push_back( pNew );
276     }
277 
278     // Verkettung wiederherstellen
279     if ( rPool.pSecondary )
280         SetSecondaryPool( rPool.pSecondary->Clone() );
281 }
282 
283 // -----------------------------------------------------------------------
284 
285 void SfxItemPool::SetDefaults( SfxPoolItem **pDefaults )
286 {
287     DBG_CHKTHIS(SfxItemPool, 0);
288     DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." );
289     DBG_ASSERT( !ppStaticDefaults, "habe schon defaults" );
290 
291     ppStaticDefaults = pDefaults;
292     //! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT )
293     //! geht wohl nicht im Zshg mit SetItems, die hinten stehen
294     {
295         DBG_ASSERT( (*ppStaticDefaults)->GetRefCount() == 0 ||
296                     IsDefaultItem( (*ppStaticDefaults) ),
297                     "das sind keine statics" );
298         for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n )
299         {
300             SFX_ASSERT( (*( ppStaticDefaults + n ))->Which() == n + nStart,
301                         n + nStart, "static defaults not sorted" );
302             (*( ppStaticDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
303             DBG_ASSERT( !(pImp->ppPoolItems[n]), "defaults with setitems with items?!" );
304         }
305     }
306 }
307 
308 // -----------------------------------------------------------------------
309 
310 void SfxItemPool::ReleaseDefaults
311 (
312     sal_Bool    bDelete     /*  sal_True
313                             l"oscht sowohl das Array als auch die einzelnen
314                             statischen Defaults
315 
316                             sal_False
317                             l"oscht weder das Array noch die einzelnen
318                             statischen Defaults */
319 )
320 
321 /*  [Beschreibung]
322 
323     Gibt die statischen Defaults der betreffenden SfxItemPool-Instanz frei
324     und l"oscht ggf. die statischen Defaults.
325 
326     Nach Aufruf dieser Methode darf die SfxItemPool-Instanz nicht mehr
327     verwendet werden, einzig ist der Aufruf des Destruktors zu"lassig.
328 */
329 
330 {
331     DBG_ASSERT( ppStaticDefaults, "keine Arme keine Kekse" );
332     ReleaseDefaults( ppStaticDefaults, nEnd - nStart + 1, bDelete );
333 
334     // KSO (22.10.98): ppStaticDefaults zeigt auf geloeschten Speicher,
335     // wenn bDelete == sal_True.
336     if ( bDelete )
337         ppStaticDefaults = 0;
338 }
339 
340 // -----------------------------------------------------------------------
341 
342 void SfxItemPool::ReleaseDefaults
343 (
344     SfxPoolItem**   pDefaults,  /*  freizugebende statische Defaults */
345 
346     sal_uInt16          nCount,     /*  Anzahl der statischen Defaults */
347 
348     sal_Bool            bDelete     /*  sal_True
349                                     l"oscht sowohl das Array als auch die
350                                     einzelnen statischen Defaults
351 
352                                     sal_False
353                                     l"oscht weder das Array noch die
354                                     einzelnen statischen Defaults */
355 )
356 
357 /*  [Beschreibung]
358 
359     Gibt die angegebenen statischen Defaults frei und l"oscht ggf.
360     die statischen Defaults.
361 
362     Diese Methode darf erst nach Zerst"orung aller SfxItemPool-Instanzen,
363     welche die angegebenen statischen Defaults 'pDefault' verwenden,
364     aufgerufen werden.
365 */
366 
367 {
368     DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." );
369 
370     for ( sal_uInt16 n = 0; n < nCount; ++n )
371     {
372         SFX_ASSERT( IsStaticDefaultItem( *(pDefaults+n) ),
373                     n, "das ist kein static-default" );
374         (*( pDefaults + n ))->SetRefCount( 0 );
375         if ( bDelete )
376             { delete *( pDefaults + n ); *(pDefaults + n) = 0; }
377     }
378 
379     if ( bDelete )
380         { delete[] pDefaults; pDefaults = 0; }
381 }
382 
383 // -----------------------------------------------------------------------
384 
385 SfxItemPool::~SfxItemPool()
386 {
387     DBG_DTOR(SfxItemPool, 0);
388     DBG_ASSERT( pMaster == this, "destroying active Secondary-Pool" );
389 
390     if ( pImp->ppPoolItems && ppPoolDefaults )
391         Delete();
392     delete[] _pPoolRanges;
393     delete pImp;
394 }
395 
396 void SfxItemPool::Free(SfxItemPool* pPool)
397 {
398     if(pPool)
399     {
400         // tell all the registered SfxItemPoolUsers that the pool is in destruction
401         SfxItemPoolUserVector aListCopy(pPool->maSfxItemPoolUsers.begin(), pPool->maSfxItemPoolUsers.end());
402         for(SfxItemPoolUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++)
403         {
404             SfxItemPoolUser* pSfxItemPoolUser = *aIterator;
405             DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)");
406             pSfxItemPoolUser->ObjectInDestruction(*pPool);
407         }
408 
409         // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser()
410         // when they get called from ObjectInDestruction().
411         pPool->maSfxItemPoolUsers.clear();
412 
413         // delete pool
414         delete pPool;
415     }
416 }
417 
418 // -----------------------------------------------------------------------
419 
420 
421 void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool )
422 {
423     // ggf. an abgeh"angten Pools den Master zur"ucksetzen
424     if ( pSecondary )
425     {
426 #ifdef DBG_UTIL
427         HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
428         if ( ppStaticDefaults )
429         {
430             // Delete() ist noch nicht gelaufen?
431             if ( pImp->ppPoolItems && pSecondary->pImp->ppPoolItems )
432             {
433                 // hat der master SetItems?
434                 sal_Bool bHasSetItems = sal_False;
435                 for ( sal_uInt16 i = 0; !bHasSetItems && i < nEnd-nStart; ++i )
436                     bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem);
437 
438                 // abgehaengte Pools muessen leer sein
439                 sal_Bool bOK = bHasSetItems;
440                 for ( sal_uInt16 n = 0;
441                       bOK && n <= pSecondary->nEnd - pSecondary->nStart;
442                       ++n )
443                 {
444                     SfxPoolItemArray_Impl** ppItemArr =
445                                                 pSecondary->pImp->ppPoolItems + n;
446                     if ( *ppItemArr )
447                     {
448                         SfxPoolItemArrayBase_Impl::iterator ppHtArr =   (*ppItemArr)->begin();
449                         for( size_t i = (*ppItemArr)->size(); i; ++ppHtArr, --i )
450                             if ( !(*ppHtArr) )
451                             {
452                                 DBG_ERROR( "old secondary pool must be empty" );
453                                 bOK = sal_False;
454                                 break;
455                             }
456                     }
457                 }
458             }
459         }
460 #endif
461 
462         pSecondary->pMaster = pSecondary;
463         for ( SfxItemPool *p = pSecondary->pSecondary; p; p = p->pSecondary )
464             p->pMaster = pSecondary;
465     }
466 
467     // ggf. den Master der neuen Secondary-Pools setzen
468     DBG_ASSERT( !pPool || pPool->pMaster == pPool, "Secondary tanzt auf zwei Hochzeiten " );
469     SfxItemPool *pNewMaster = pMaster ? pMaster : this;
470     for ( SfxItemPool *p = pPool; p; p = p->pSecondary )
471         p->pMaster = pNewMaster;
472 
473     // neuen Secondary-Pool merken
474     pSecondary = pPool;
475 }
476 
477 // -----------------------------------------------------------------------
478 
479 SfxMapUnit SfxItemPool::GetMetric( sal_uInt16 ) const
480 {
481     DBG_CHKTHIS(SfxItemPool, 0);
482 
483     return pImp->eDefMetric;
484 }
485 
486 // -----------------------------------------------------------------------
487 
488 void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric )
489 {
490     DBG_CHKTHIS(SfxItemPool, 0);
491 
492     pImp->eDefMetric = eNewMetric;
493 }
494 
495 // -----------------------------------------------------------------------
496 
497 SfxItemPresentation SfxItemPool::GetPresentation
498 (
499     const SfxPoolItem&  rItem,      /*  IN: <SfxPoolItem>, dessen textuelle
500                                             Wert-Darstellung geliefert werden
501                                             soll */
502     SfxItemPresentation ePresent,   /*  IN: gew"unschte Art der Darstellung;
503                                             siehe <SfxItemPresentation> */
504     SfxMapUnit          eMetric,    /*  IN: gew"unschte Ma\seinheit der Darstellung */
505     XubString&           rText,      /*  OUT: textuelle Darstellung von 'rItem' */
506     const IntlWrapper * pIntlWrapper
507 )   const
508 
509 /*  [Beschreibung]
510 
511     "Uber diese virtuelle Methode k"onnen textuelle Darstellungen der
512     von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems
513     angefordert werden.
514 
515     In Ableitungen sollte diese Methode "uberladen werden und auf
516     SfxPoolItems reagiert werden, die bei <SfxPoolItem::GetPresentation()const>
517     keine vollst"andige Information liefern k"onnen.
518 
519     Die Basisklasse liefert die unver"anderte Presentation von 'rItem'.
520 */
521 
522 {
523     DBG_CHKTHIS(SfxItemPool, 0);
524     return rItem.GetPresentation(
525         ePresent, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper );
526 }
527 
528 
529 // -----------------------------------------------------------------------
530 
531 SfxItemPool* SfxItemPool::Clone() const
532 {
533     DBG_CHKTHIS(SfxItemPool, 0);
534 
535     SfxItemPool *pPool = new SfxItemPool( *this );
536     return pPool;
537 }
538 
539 // ----------------------------------------------------------------------
540 
541 void SfxItemPool::Delete()
542 {
543     DBG_CHKTHIS(SfxItemPool, 0);
544 
545     // schon deleted?
546     if ( !pImp->ppPoolItems || !ppPoolDefaults )
547         return;
548 
549     // z.B. laufenden Requests bescheidsagen
550     pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) );
551 
552     //MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems.
553     //Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt.
554 
555     SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
556     SfxPoolItem** ppDefaultItem = ppPoolDefaults;
557     SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults;
558     sal_uInt16 nArrCnt;
559 
560     //Erst die SetItems abraeumen
561     HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
562     if ( ppStaticDefaults )
563     {
564         for ( nArrCnt = GetSize_Impl();
565                 nArrCnt;
566                 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
567         {
568             // KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer
569             // von SfxItemPool abgeleiteten Klasse bereits geloescht worden
570             // sein! -> CHAOS Itempool
571             if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) )
572             {
573                 if ( *ppItemArr )
574                 {
575                     SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
576                     for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
577                         if (*ppHtArr)
578                         {
579 #ifdef DBG_UTIL
580                             ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
581 #endif
582                             delete *ppHtArr;
583                         }
584                     DELETEZ( *ppItemArr );
585                 }
586                 if ( *ppDefaultItem )
587                 {
588 #ifdef DBG_UTIL
589                     SetRefCount( **ppDefaultItem, 0 );
590 #endif
591                     DELETEZ( *ppDefaultItem );
592                 }
593             }
594         }
595     }
596 
597     ppItemArr = pImp->ppPoolItems;
598     ppDefaultItem = ppPoolDefaults;
599 
600     //Jetzt die 'einfachen' Items
601     for ( nArrCnt = GetSize_Impl();
602             nArrCnt;
603             --nArrCnt, ++ppItemArr, ++ppDefaultItem )
604     {
605         if ( *ppItemArr )
606         {
607             SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
608             for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
609                 if (*ppHtArr)
610                 {
611 #ifdef DBG_UTIL
612                     ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
613 #endif
614                     delete *ppHtArr;
615                 }
616             delete *ppItemArr;
617         }
618         if ( *ppDefaultItem )
619         {
620 #ifdef DBG_UTIL
621             SetRefCount( **ppDefaultItem, 0 );
622 #endif
623             delete *ppDefaultItem;
624         }
625     }
626 
627     pImp->DeleteItems();
628     delete[] ppPoolDefaults; ppPoolDefaults = 0;
629 }
630 
631 // ----------------------------------------------------------------------
632 
633 void SfxItemPool::Cleanup()
634 {
635     DBG_CHKTHIS(SfxItemPool, 0);
636 
637     //MA 16. Apr. 97: siehe ::Delete()
638 
639     SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
640     SfxPoolItem** ppDefaultItem = ppPoolDefaults;
641     SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults;
642     sal_uInt16 nArrCnt;
643 
644     HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" )
645     if ( ppStaticDefaults ) //HACK fuer Image, dort gibt es keine Statics!!
646     {
647         for ( nArrCnt = GetSize_Impl();
648                 nArrCnt;
649                 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
650         {
651             //Fuer jedes Item gibt es entweder ein Default oder ein static Default!
652             if ( *ppItemArr &&
653                  ((*ppDefaultItem && (*ppDefaultItem)->ISA(SfxSetItem)) ||
654                   (*ppStaticDefaultItem)->ISA(SfxSetItem)) )
655             {
656                 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
657                 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
658                     if ( *ppHtArr && !(*ppHtArr)->GetRefCount() )
659                     {
660                          DELETEZ(*ppHtArr);
661                     }
662             }
663         }
664     }
665 
666     ppItemArr = pImp->ppPoolItems;
667 
668     for ( nArrCnt = GetSize_Impl();
669           nArrCnt;
670           --nArrCnt, ++ppItemArr )
671     {
672         if ( *ppItemArr )
673         {
674             SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
675             for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
676                 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() )
677                     DELETEZ( *ppHtArr );
678         }
679     }
680 }
681 
682 // ----------------------------------------------------------------------
683 
684 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem)
685 {
686     DBG_CHKTHIS(SfxItemPool, 0);
687     if ( IsInRange(rItem.Which()) )
688     {
689         SfxPoolItem **ppOldDefault =
690             ppPoolDefaults + GetIndex_Impl(rItem.Which());
691         SfxPoolItem *pNewDefault = rItem.Clone(this);
692         pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT);
693         if ( *ppOldDefault )
694         {
695             (*ppOldDefault)->SetRefCount(0);
696             DELETEZ( *ppOldDefault );
697         }
698         *ppOldDefault = pNewDefault;
699     }
700     else if ( pSecondary )
701         pSecondary->SetPoolDefaultItem(rItem);
702     else
703     {
704         SFX_ASSERT( 0, rItem.Which(), "unknown Which-Id - cannot set pool default" );
705     }
706 }
707 
708 /*
709  * Resets the default of the given <Which-Id> back to the static default.
710  * If a pool default exists it is removed.
711  */
712 void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId )
713 {
714     DBG_CHKTHIS(SfxItemPool, 0);
715     if ( IsInRange(nWhichId) )
716     {
717         SfxPoolItem **ppOldDefault =
718             ppPoolDefaults + GetIndex_Impl( nWhichId );
719         if ( *ppOldDefault )
720         {
721             (*ppOldDefault)->SetRefCount(0);
722             DELETEZ( *ppOldDefault );
723         }
724     }
725     else if ( pSecondary )
726         pSecondary->ResetPoolDefaultItem(nWhichId);
727     else
728     {
729         SFX_ASSERT( 0, nWhichId, "unknown Which-Id - cannot set pool default" );
730     }
731 }
732 
733 // -----------------------------------------------------------------------
734 
735 const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
736 {
737     DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
738                 0 != &((const SfxSetItem&)rItem).GetItemSet(),
739                 "SetItem without ItemSet" );
740 
741     DBG_CHKTHIS(SfxItemPool, 0);
742     if ( 0 == nWhich )
743         nWhich = rItem.Which();
744 
745     // richtigen Secondary-Pool finden
746     sal_Bool bSID = nWhich > SFX_WHICH_MAX;
747     if ( !bSID && !IsInRange(nWhich) )
748     {
749         if ( pSecondary )
750             return pSecondary->Put( rItem, nWhich );
751         DBG_ERROR( "unknown Which-Id - cannot put item" );
752     }
753 
754     // SID oder nicht poolable (neue Definition)?
755     sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
756     if ( USHRT_MAX == nIndex ||
757          IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) )
758     {
759         SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich ||
760                     !IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE,
761                     nWhich, "ein nicht Pool-Item ist Default?!" );
762         SfxPoolItem *pPoolItem = rItem.Clone(pMaster);
763         pPoolItem->SetWhich(nWhich);
764         AddRef( *pPoolItem );
765         return *pPoolItem;
766     }
767 
768     SFX_ASSERT( rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich,
769                 "SFxItemPool: wrong item type in Put" );
770 
771     SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems + nIndex;
772     if( !*ppItemArr )
773         *ppItemArr = new SfxPoolItemArray_Impl;
774 
775     SfxPoolItemArrayBase_Impl::iterator ppFree;
776     sal_Bool ppFreeIsSet = sal_False;
777     SfxPoolItemArrayBase_Impl::iterator ppHtArray = (*ppItemArr)->begin();
778     if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) )
779     {
780         // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein
781         if ( IsPooledItem(&rItem) )
782         {
783             // 1. Schleife: teste ob der Pointer vorhanden ist.
784             for( size_t n = (*ppItemArr)->size(); n; ++ppHtArray, --n )
785                 if( &rItem == (*ppHtArray) )
786                 {
787                     AddRef( **ppHtArray );
788                     return **ppHtArray;
789                 }
790         }
791 
792         // 2. Schleife: dann muessen eben die Attribute verglichen werden
793         size_t n;
794         for ( n = (*ppItemArr)->size(), ppHtArray = (*ppItemArr)->begin();
795               n; ++ppHtArray, --n )
796         {
797             if ( *ppHtArray )
798             {
799                 if( **ppHtArray == rItem )
800                 {
801                     AddRef( **ppHtArray );
802                     return **ppHtArray;
803                 }
804             }
805             else
806                 if ( ppFreeIsSet == sal_False )
807                 {
808                     ppFree = ppHtArray;
809                     ppFreeIsSet = sal_True;
810                 }
811         }
812     }
813     else
814     {
815         // freien Platz suchen
816         SfxPoolItemArrayBase_Impl::iterator ppHtArr;
817         size_t n, nCount = (*ppItemArr)->size();
818         for ( n = (*ppItemArr)->nFirstFree,
819                   ppHtArr = (*ppItemArr)->begin() + n;
820               n < nCount;
821               ++ppHtArr, ++n )
822             if ( !*ppHtArr )
823             {
824                 ppFree = ppHtArr;
825                 ppFreeIsSet = sal_True;
826                 break;
827             }
828 
829         // naechstmoeglichen freien Platz merken
830         (*ppItemArr)->nFirstFree = n;
831     }
832 
833     // nicht vorhanden, also im PtrArray eintragen
834     SfxPoolItem* pNewItem = rItem.Clone(pMaster);
835     pNewItem->SetWhich(nWhich);
836 #ifdef DBG_UTIL
837     SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" )
838 #ifdef TF_POOLABLE
839     if ( !rItem.ISA(SfxSetItem) )
840     {
841         SFX_ASSERT( !IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
842                     rItem == *pNewItem,
843                     nWhich, "unequal items in Put(): no operator==?" );
844         SFX_ASSERT( !IsItemFlag(*pNewItem, SFX_ITEM_POOLABLE) ||
845                     *pNewItem == rItem,
846                     nWhich, "unequal items in Put(): no operator==?" );
847     }
848 #endif
849 #endif
850     AddRef( *pNewItem, pImp->nInitRefCount );
851     SfxPoolItem* pTemp = pNewItem;
852     if ( ppFreeIsSet == sal_False )
853         (*ppItemArr)->push_back( pTemp );
854     else
855     {
856         DBG_ASSERT( *ppFree == 0, "using surrogate in use" );
857         *ppFree = pNewItem;
858     }
859     return *pNewItem;
860 }
861 
862 // -----------------------------------------------------------------------
863 
864 void SfxItemPool::Remove( const SfxPoolItem& rItem )
865 {
866     DBG_CHKTHIS(SfxItemPool, 0);
867 
868     DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
869                 0 != &((const SfxSetItem&)rItem).GetItemSet(),
870                 "SetItem without ItemSet" );
871 
872     SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(),
873                 "wo kommt denn hier ein Pool-Default her" );
874 
875     // richtigen Secondary-Pool finden
876     const sal_uInt16 nWhich = rItem.Which();
877     sal_Bool bSID = nWhich > SFX_WHICH_MAX;
878     if ( !bSID && !IsInRange(nWhich) )
879     {
880         if ( pSecondary )
881         {
882             pSecondary->Remove( rItem );
883             return;
884         }
885         DBG_ERROR( "unknown Which-Id - cannot remove item" );
886     }
887 
888     // SID oder nicht poolable (neue Definition)?
889     sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
890     if ( bSID || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) )
891     {
892         SFX_ASSERT( USHRT_MAX != nIndex ||
893                     !IsDefaultItem(&rItem), rItem.Which(),
894                     "ein nicht Pool-Item ist Default?!" );
895         if ( 0 == ReleaseRef(rItem) )
896         {
897             SfxPoolItem *pItem = &(SfxPoolItem &)rItem;
898             delete pItem;
899         }
900         return;
901     }
902 
903     SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove unmoeglich" );
904 
905     // statische Defaults sind eben einfach da
906     if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT &&
907          &rItem == *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
908         return;
909 
910     // Item im eigenen Pool suchen
911     SfxPoolItemArray_Impl** ppItemArr = (pImp->ppPoolItems + nIndex);
912     SFX_ASSERT( *ppItemArr, rItem.Which(), "removing Item not in Pool" );
913     SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
914     for( size_t n = (*ppItemArr)->size(); n; ++ppHtArr, --n )
915         if( *ppHtArr == &rItem )
916         {
917             if ( (*ppHtArr)->GetRefCount() ) //!
918                 ReleaseRef( **ppHtArr );
919             else
920             {
921                 SFX_ASSERT( 0, rItem.Which(), "removing Item without ref" );
922                 SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr );
923             }
924 
925             // ggf. kleinstmoegliche freie Position merken
926             size_t nPos = (*ppItemArr)->size() - n;
927             if ( (*ppItemArr)->nFirstFree > nPos )
928                 (*ppItemArr)->nFirstFree = nPos;
929 
930             //! MI: Hack, solange wir das Problem mit dem Outliner haben
931             //! siehe anderes MI-REF
932             if ( 0 == (*ppHtArr)->GetRefCount() && nWhich < 4000 )
933                 DELETEZ(*ppHtArr);
934             return;
935         }
936 
937     // nicht vorhanden
938     SFX_ASSERT( 0, rItem.Which(), "removing Item not in Pool" );
939     SFX_TRACE( "to be removed, but not in pool: ", &rItem );
940 }
941 
942 // -----------------------------------------------------------------------
943 
944 const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const
945 {
946     DBG_CHKTHIS(SfxItemPool, 0);
947 
948     if ( !IsInRange(nWhich) )
949     {
950         if ( pSecondary )
951             return pSecondary->GetDefaultItem( nWhich );
952         SFX_ASSERT( 0, nWhich, "unknown which - dont ask me for defaults" );
953     }
954 
955     DBG_ASSERT( ppStaticDefaults, "no defaults known - dont ask me for defaults" );
956     sal_uInt16 nPos = GetIndex_Impl(nWhich);
957     SfxPoolItem *pDefault = *(ppPoolDefaults + nPos);
958     if ( pDefault )
959         return *pDefault;
960     return **(ppStaticDefaults + nPos);
961 }
962 
963 // -----------------------------------------------------------------------
964 
965 
966 void SfxItemPool::FreezeIdRanges()
967 
968 /*  [Beschreibung]
969 
970     This method should be called at the master pool, when all secondary
971     pools are appended to it.
972 
973     It calculates the ranges of 'which-ids' for fast construction of
974     item-sets, which contains all 'which-ids'.
975 */
976 
977 {
978     FillItemIdRanges_Impl( _pPoolRanges );
979 }
980 
981 
982 // -----------------------------------------------------------------------
983 
984 void SfxItemPool::FillItemIdRanges_Impl( sal_uInt16*& pWhichRanges ) const
985 {
986     DBG_CHKTHIS(SfxItemPool, 0);
987     DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" );
988 
989     const SfxItemPool *pPool;
990     sal_uInt16 nLevel = 0;
991     for( pPool = this; pPool; pPool = pPool->pSecondary )
992         ++nLevel;
993 
994     pWhichRanges = new sal_uInt16[ 2*nLevel + 1 ];
995 
996     nLevel = 0;
997     for( pPool = this; pPool; pPool = pPool->pSecondary )
998     {
999         *(pWhichRanges+(nLevel++)) = pPool->nStart;
1000         *(pWhichRanges+(nLevel++)) = pPool->nEnd;
1001         *(pWhichRanges+nLevel) = 0;
1002     }
1003 }
1004 
1005 // -----------------------------------------------------------------------
1006 
1007 const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) const
1008 {
1009     DBG_CHKTHIS(SfxItemPool, 0);
1010 
1011     if ( !IsInRange(nWhich) )
1012     {
1013         if ( pSecondary )
1014             return pSecondary->GetItem2( nWhich, nOfst );
1015         SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" );
1016         return 0;
1017     }
1018 
1019     // dflt-Attribut?
1020     if ( nOfst == SFX_ITEMS_DEFAULT )
1021         return *(ppStaticDefaults + GetIndex_Impl(nWhich));
1022 
1023     SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich));
1024     if( pItemArr && nOfst < pItemArr->size() )
1025         return (*pItemArr)[nOfst];
1026 
1027     return 0;
1028 }
1029 
1030 // -----------------------------------------------------------------------
1031 
1032 sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const
1033 {
1034     DBG_CHKTHIS(SfxItemPool, 0);
1035 
1036     if ( !IsInRange(nWhich) )
1037     {
1038         if ( pSecondary )
1039             return pSecondary->GetItemCount2( nWhich );
1040         SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" );
1041         return 0;
1042     }
1043 
1044     SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich));
1045     if  ( pItemArr )
1046         return pItemArr->size();
1047     return 0;
1048 }
1049 
1050 // -----------------------------------------------------------------------
1051 
1052 sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const
1053 {
1054     if ( !IsSlot(nSlotId) )
1055         return nSlotId;
1056 
1057 #ifdef TF_POOLABLE
1058     sal_uInt16 nCount = nEnd - nStart + 1;
1059     for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1060         if ( pItemInfos[nOfs]._nSID == nSlotId )
1061             return nOfs + nStart;
1062 #else
1063     if ( pSlotIds )
1064     {
1065         sal_uInt16 nCount = nEnd - nStart + 1;
1066         for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1067             if ( pSlotIds[nOfs] == nSlotId )
1068                 return nOfs + nStart;
1069     }
1070 #endif
1071     if ( pSecondary && bDeep )
1072         return pSecondary->GetWhich(nSlotId);
1073     return nSlotId;
1074 }
1075 
1076 // -----------------------------------------------------------------------
1077 
1078 sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const
1079 {
1080     if ( !IsWhich(nWhich) )
1081         return nWhich;
1082 
1083     if ( !IsInRange( nWhich ) )
1084     {
1085         if ( pSecondary && bDeep )
1086             return pSecondary->GetSlotId(nWhich);
1087         SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" );
1088         return 0;
1089     }
1090 #ifdef TF_POOLABLE
1091 
1092     sal_uInt16 nSID = pItemInfos[nWhich - nStart]._nSID;
1093     return nSID ? nSID : nWhich;
1094 #else
1095     else if ( pSlotIds )
1096         return pSlotIds[nWhich - nStart];
1097     return nWhich;
1098 #endif
1099 }
1100 
1101 // -----------------------------------------------------------------------
1102 
1103 sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const
1104 {
1105     if ( !IsSlot(nSlotId) )
1106         return 0;
1107 
1108 #ifdef TF_POOLABLE
1109     sal_uInt16 nCount = nEnd - nStart + 1;
1110     for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1111         if ( pItemInfos[nOfs]._nSID == nSlotId )
1112             return nOfs + nStart;
1113 #else
1114     if ( pSlotIds )
1115     {
1116         sal_uInt16 nCount = nEnd - nStart + 1;
1117         for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1118             if ( pSlotIds[nOfs] == nSlotId )
1119                 return nOfs + nStart;
1120     }
1121 #endif
1122     if ( pSecondary && bDeep )
1123         return pSecondary->GetTrueWhich(nSlotId);
1124     return 0;
1125 }
1126 
1127 // -----------------------------------------------------------------------
1128 
1129 sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const
1130 {
1131     if ( !IsWhich(nWhich) )
1132         return 0;
1133 
1134     if ( !IsInRange( nWhich ) )
1135     {
1136         if ( pSecondary && bDeep )
1137             return pSecondary->GetTrueSlotId(nWhich);
1138         SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" );
1139         return 0;
1140     }
1141 #ifdef TF_POOLABLE
1142     return pItemInfos[nWhich - nStart]._nSID;
1143 #else
1144     else if ( pSlotIds )
1145         return pSlotIds[nWhich - nStart];
1146     else
1147         return 0;
1148 #endif
1149 }
1150 // -----------------------------------------------------------------------
1151 void SfxItemPool::SetFileFormatVersion( sal_uInt16 nFileFormatVersion )
1152 
1153 /*  [Description]
1154 
1155     You must call this function to set the file format version after
1156     concatenating your secondary-pools but before you store any
1157     pool, itemset or item. Only set the version at the master pool,
1158     never at any secondary pool.
1159 */
1160 
1161 {
1162     DBG_ASSERT( this == pMaster,
1163                 "SfxItemPool::SetFileFormatVersion() but not a master pool" );
1164     for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary )
1165         pPool->_nFileFormatVersion = nFileFormatVersion;
1166 }
1167 
1168 
1169