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