Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svl/itempool.hxx>
21 :
22 : #include <string.h>
23 :
24 : #include <osl/diagnose.h>
25 : #include <sal/log.hxx>
26 : #include "whassert.hxx"
27 : #include <svl/SfxBroadcaster.hxx>
28 : #include <svl/smplhint.hxx>
29 : #include "poolio.hxx"
30 :
31 : #include <vector>
32 :
33 :
34 : #if OSL_DEBUG_LEVEL > 0
35 : #include <map>
36 :
37 : static void
38 : lcl_CheckSlots2(std::map<sal_uInt16, sal_uInt16> & rSlotMap,
39 : SfxItemPool const& rPool, SfxItemInfo const* pInfos)
40 : {
41 : if (!pInfos)
42 : return; // may not be initialized yet
43 : if (rPool.GetName() == "EditEngineItemPool")
44 : return; // HACK: this one has loads of duplicates already, ignore it :(
45 : sal_uInt16 const nFirst(rPool.GetFirstWhich());
46 : sal_uInt16 const nCount(rPool.GetLastWhich() - rPool.GetFirstWhich() + 1);
47 : for (sal_uInt16 n = 0; n < nCount; ++n)
48 : {
49 : sal_uInt16 const nSlotId(pInfos[n]._nSID);
50 : if (nSlotId != 0
51 : && nSlotId != 10883 // preexisting duplicate SID_ATTR_GRAF_CROP
52 : && nSlotId != 10023 // preexisting duplicate SID_ATTR_BORDER_INNER
53 : && nSlotId != 10024 // preexisting duplicate SID_ATTR_BORDER_OUTER
54 : && nSlotId != 11013 // preexisting duplicate SID_ATTR_BORDER_DIAG_TLBR
55 : && nSlotId != 11014) // preexisting duplicate SID_ATTR_BORDER_DIAG_BLTR
56 : { // check for duplicate slot-id mapping
57 : std::map<sal_uInt16, sal_uInt16>::const_iterator const iter(
58 : rSlotMap.find(nSlotId));
59 : sal_uInt16 const nWhich(nFirst + n);
60 : if (iter != rSlotMap.end())
61 : {
62 : SAL_WARN("svl", "SfxItemPool: duplicate SlotId " << nSlotId
63 : << " mapped to " << iter->second << " and " << nWhich);
64 : assert(false);
65 : }
66 : rSlotMap.insert(std::make_pair(nSlotId, nWhich));
67 : }
68 : }
69 : }
70 :
71 : #define CHECK_SLOTS() \
72 : do { \
73 : std::map<sal_uInt16, sal_uInt16> slotmap; \
74 : for (SfxItemPool * p = pImp->mpMaster; p; p = p->pImp->mpSecondary) \
75 : { \
76 : lcl_CheckSlots2(slotmap, *p, p->pItemInfos); \
77 : } \
78 : } while (false)
79 :
80 : #else
81 : #define CHECK_SLOTS() do {} while (false)
82 : #endif
83 :
84 :
85 354146 : void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser)
86 : {
87 354146 : pImp->maSfxItemPoolUsers.push_back(&rNewUser);
88 354146 : }
89 :
90 352244 : void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser)
91 : {
92 : const std::vector<SfxItemPoolUser*>::iterator aFindResult = ::std::find(
93 352244 : pImp->maSfxItemPoolUsers.begin(), pImp->maSfxItemPoolUsers.end(), &rOldUser);
94 352244 : if(aFindResult != pImp->maSfxItemPoolUsers.end())
95 : {
96 352244 : pImp->maSfxItemPoolUsers.erase(aFindResult);
97 : }
98 352244 : }
99 :
100 340202 : const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const
101 : {
102 : const SfxPoolItem* pRet;
103 340202 : if( IsInRange( nWhich ) )
104 332398 : pRet = *(pImp->ppPoolDefaults + GetIndex_Impl( nWhich ));
105 7804 : else if( pImp->mpSecondary )
106 7804 : pRet = pImp->mpSecondary->GetPoolDefaultItem( nWhich );
107 : else
108 : {
109 : SFX_ASSERT( false, nWhich, "unknown WhichId - cannot get pool default" );
110 0 : pRet = 0;
111 : }
112 340202 : return pRet;
113 : }
114 :
115 :
116 :
117 78314216 : bool SfxItemPool::IsItemFlag_Impl( sal_uInt16 nPos, SfxItemPoolFlags nFlag ) const
118 : {
119 78314216 : return bool(pItemInfos[nPos]._nFlags & nFlag);
120 : }
121 :
122 :
123 :
124 17438119 : bool SfxItemPool::IsItemFlag( sal_uInt16 nWhich, SfxItemPoolFlags nFlag ) const
125 : {
126 28371663 : for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pImp->mpSecondary )
127 : {
128 26905991 : if ( pPool->IsInRange(nWhich) )
129 15972447 : return pPool->IsItemFlag_Impl( pPool->GetIndex_Impl(nWhich), nFlag);
130 : }
131 : DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" );
132 1465672 : return false;
133 : }
134 :
135 :
136 :
137 6455 : SfxBroadcaster& SfxItemPool::BC()
138 : {
139 6455 : return pImp->aBC;
140 : }
141 :
142 :
143 :
144 : /**
145 : * This is the regular ctor to be used for this class.
146 : * An SfxItemPool instance is initialized, which can manage Items in the
147 : * range from 'nStartWhich' to 'nEndWhich'.
148 : *
149 : * For every one of these WhichIds a static Default must be present in the
150 : * 'pDefaults' array. They start with an SfxPoolItem (with the WhichId
151 : * 'nStartWhich'), are sorted by WhichId and consecutively stored.
152 : *
153 : * 'pItemInfos' is a USHORT array arranged in the same way, which holds
154 : * SlotIds and Flags. These SlotIds can be 0, if the affected Items are
155 : * exclusively used in the Core.
156 : * The flags allow for e.g. enabling value sharing (SfxItemPoolFlags::POOLABLE).
157 : *
158 : * If the Pool is supposed to hold SfxSetItems, the ctor cannot yet contain
159 : * static Defaults. This needs to be done afterwards, using
160 : * @see SfxItemPool::SetDefaults(SfxItemPool**).
161 : *
162 : * @see SfxItemPool::SetDefaults(SfxItemPool**)
163 : * @see SfxItemPool::ReleaseDefaults(SfxPoolItem**,sal_uInt16,sal_Bool)
164 : * @see SfxItemPool::ReldaseDefaults(sal_Bool)
165 : */
166 65929 : SfxItemPool::SfxItemPool
167 : (
168 : const OUString& rName, /* Pool name to identify in the file format */
169 : sal_uInt16 nStartWhich, /* First WhichId of the Pool */
170 : sal_uInt16 nEndWhich, /* Last WhichId of the Pool */
171 : const SfxItemInfo* pInfos, /* SID Map and Item flags */
172 : SfxPoolItem** pDefaults, /* Pointer to static Defaults;
173 : is directly referenced by the Pool,
174 : but no transfer of ownership */
175 : bool bLoadRefCounts /* Load RefCounts or set to 1? */
176 : ) :
177 : pItemInfos(pInfos),
178 65929 : pImp( new SfxItemPool_Impl( this, rName, nStartWhich, nEndWhich ) )
179 : {
180 65929 : pImp->eDefMetric = SFX_MAPUNIT_TWIP;
181 65929 : pImp->nVersion = 0;
182 65929 : pImp->bStreaming = false;
183 65929 : pImp->nLoadingVersion = 0;
184 65929 : pImp->nInitRefCount = 1;
185 65929 : pImp->nVerStart = pImp->mnStart;
186 65929 : pImp->nVerEnd = pImp->mnEnd;
187 65929 : pImp->bInSetItem = false;
188 65929 : pImp->nStoringStart = nStartWhich;
189 65929 : pImp->nStoringEnd = nEndWhich;
190 65929 : pImp->mbPersistentRefCounts = bLoadRefCounts;
191 :
192 65929 : if ( pDefaults )
193 3021 : SetDefaults(pDefaults);
194 65929 : }
195 :
196 :
197 :
198 : /**
199 : * Copy ctor
200 : *
201 : * @see SfxItemPool::Clone() const
202 : */
203 37 : SfxItemPool::SfxItemPool
204 : (
205 : const SfxItemPool& rPool, // Copy from this instance
206 : bool bCloneStaticDefaults /* true
207 : Copy static Defaults
208 :
209 : false
210 : Take over static Defaults */
211 : ) :
212 : pItemInfos(rPool.pItemInfos),
213 37 : pImp( new SfxItemPool_Impl( this, rPool.pImp->aName, rPool.pImp->mnStart, rPool.pImp->mnEnd ) )
214 : {
215 37 : pImp->eDefMetric = rPool.pImp->eDefMetric;
216 37 : pImp->nVersion = rPool.pImp->nVersion;
217 37 : pImp->bStreaming = false;
218 37 : pImp->nLoadingVersion = 0;
219 37 : pImp->nInitRefCount = 1;
220 37 : pImp->nVerStart = rPool.pImp->nVerStart;
221 37 : pImp->nVerEnd = rPool.pImp->nVerEnd;
222 37 : pImp->bInSetItem = false;
223 37 : pImp->nStoringStart = pImp->mnStart;
224 37 : pImp->nStoringEnd = pImp->mnEnd;
225 37 : pImp->mbPersistentRefCounts = rPool.pImp->mbPersistentRefCounts;
226 :
227 : // Take over static Defaults
228 37 : if ( bCloneStaticDefaults )
229 : {
230 0 : SfxPoolItem **ppDefaults = new SfxPoolItem*[pImp->mnEnd-pImp->mnStart+1];
231 0 : for ( sal_uInt16 n = 0; n <= pImp->mnEnd - pImp->mnStart; ++n )
232 : {
233 0 : (*( ppDefaults + n )) = (*( rPool.pImp->ppStaticDefaults + n ))->Clone(this);
234 0 : (*( ppDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
235 : }
236 :
237 0 : SetDefaults( ppDefaults );
238 : }
239 : else
240 37 : SetDefaults( rPool.pImp->ppStaticDefaults );
241 :
242 : // Copy Pool Defaults
243 2072 : for ( sal_uInt16 n = 0; n <= pImp->mnEnd - pImp->mnStart; ++n )
244 2035 : if ( (*( rPool.pImp->ppPoolDefaults + n )) )
245 : {
246 0 : (*( pImp->ppPoolDefaults + n )) = (*( rPool.pImp->ppPoolDefaults + n ))->Clone(this);
247 0 : (*( pImp->ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT );
248 : }
249 :
250 : // Copy Version map
251 259 : for ( size_t nVer = 0; nVer < rPool.pImp->aVersions.size(); ++nVer )
252 : {
253 222 : const SfxPoolVersion_ImplPtr pOld = rPool.pImp->aVersions[nVer];
254 444 : SfxPoolVersion_ImplPtr pNew = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl( *pOld ) );
255 222 : pImp->aVersions.push_back( pNew );
256 222 : }
257 :
258 : // Repair linkage
259 37 : if ( rPool.pImp->mpSecondary )
260 0 : SetSecondaryPool( rPool.pImp->mpSecondary->Clone() );
261 37 : }
262 :
263 :
264 :
265 65965 : void SfxItemPool::SetDefaults( SfxPoolItem **pDefaults )
266 : {
267 : DBG_ASSERT( pDefaults, "first we ask for it, and then we don't give back..." );
268 : DBG_ASSERT( !pImp->ppStaticDefaults, "already have Defaults" );
269 :
270 65965 : pImp->ppStaticDefaults = pDefaults;
271 : //! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT )
272 : //! FIXME: Probably doesn't work with SetItems at the end
273 : {
274 : DBG_ASSERT( (*pImp->ppStaticDefaults)->GetRefCount() == 0 ||
275 : IsDefaultItem( (*pImp->ppStaticDefaults) ),
276 : "these are not static" );
277 4903003 : for ( sal_uInt16 n = 0; n <= pImp->mnEnd - pImp->mnStart; ++n )
278 : {
279 : SFX_ASSERT( (*( pImp->ppStaticDefaults + n ))->Which() == n + pImp->mnStart,
280 : n + pImp->mnStart, "static defaults not sorted" );
281 4837038 : (*( pImp->ppStaticDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT );
282 : DBG_ASSERT( !(pImp->maPoolItems[n]), "defaults with setitems with items?!" );
283 : }
284 : }
285 65965 : }
286 :
287 :
288 : /**
289 : * Frees the static Defaults of the corresponding SfxItemPool instance
290 : * and deletes them if specified.
291 : *
292 : * The SfxItemPool instance MUST NOT BE USED after this function has
293 : * been called; only the dtor must be called.
294 : */
295 119 : void SfxItemPool::ReleaseDefaults
296 : (
297 : bool bDelete /* true
298 : Deletes the array as well as the single static Defaults
299 :
300 : false
301 : Neither deletes the array not the single static Defaults */
302 : )
303 :
304 :
305 : {
306 : DBG_ASSERT( pImp->ppStaticDefaults, "requirements not met" );
307 119 : ReleaseDefaults( pImp->ppStaticDefaults, pImp->mnEnd - pImp->mnStart + 1, bDelete );
308 :
309 : // ppStaticDefaults points to deleted memory if bDelete == true.
310 119 : if ( bDelete )
311 0 : pImp->ppStaticDefaults = 0;
312 119 : }
313 :
314 :
315 : /**
316 : * Frees the specified static Defaults und also deletes them, if so
317 : * specified.
318 : *
319 : * This method MUST be called AFTER all SfxItemPool instances (which
320 : * use the specified static Defaults 'pDefault') have been destroyed.
321 : */
322 234 : void SfxItemPool::ReleaseDefaults
323 : (
324 : SfxPoolItem** pDefaults, /* Static Defaults that are to be freed */
325 :
326 : sal_uInt16 nCount, /* Count of static Defaults */
327 :
328 : bool bDelete /* true
329 : Deletes the array as well as the specified
330 : static Defaults
331 :
332 : false
333 : Neither deletes the array nor the single
334 : static Defaults */
335 : )
336 : {
337 : DBG_ASSERT( pDefaults, "we first ask for it and the return nothing ..." );
338 :
339 6678 : for ( sal_uInt16 n = 0; n < nCount; ++n )
340 : {
341 : SFX_ASSERT( IsStaticDefaultItem( *(pDefaults+n) ),
342 : n, "this is not a static Default" );
343 6444 : (*( pDefaults + n ))->SetRefCount( 0 );
344 6444 : if ( bDelete )
345 6325 : { delete *( pDefaults + n ); *(pDefaults + n) = 0; }
346 : }
347 :
348 234 : if ( bDelete )
349 115 : { delete[] pDefaults; pDefaults = 0; }
350 234 : }
351 :
352 :
353 :
354 57064 : SfxItemPool::~SfxItemPool()
355 : {
356 57027 : if ( !pImp->maPoolItems.empty() && pImp->ppPoolDefaults )
357 50714 : Delete();
358 :
359 57027 : if (pImp->mpMaster != NULL && pImp->mpMaster != this)
360 : {
361 : // This condition indicates an error.
362 : // A pImp->mpMaster->SetSecondaryPool(...) call should have been made
363 : // earlier to prevent this. At this point we can only try to
364 : // prevent a crash later on.
365 : DBG_ASSERT( pImp->mpMaster == this, "destroying active Secondary-Pool" );
366 0 : if (pImp->mpMaster->pImp->mpSecondary == this)
367 0 : pImp->mpMaster->pImp->mpSecondary = NULL;
368 : }
369 :
370 57027 : delete pImp;
371 57064 : }
372 :
373 60027 : void SfxItemPool::Free(SfxItemPool* pPool)
374 : {
375 60027 : if(pPool)
376 : {
377 : // tell all the registered SfxItemPoolUsers that the pool is in destruction
378 56908 : std::vector<SfxItemPoolUser*> aListCopy(pPool->pImp->maSfxItemPoolUsers.begin(), pPool->pImp->maSfxItemPoolUsers.end());
379 58507 : for(std::vector<SfxItemPoolUser*>::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); ++aIterator)
380 : {
381 1599 : SfxItemPoolUser* pSfxItemPoolUser = *aIterator;
382 : DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)");
383 1599 : pSfxItemPoolUser->ObjectInDestruction(*pPool);
384 : }
385 :
386 : // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser()
387 : // when they get called from ObjectInDestruction().
388 56908 : pPool->pImp->maSfxItemPoolUsers.clear();
389 :
390 : // delete pool
391 56908 : delete pPool;
392 : }
393 60027 : }
394 :
395 :
396 :
397 :
398 20314 : void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool )
399 : {
400 : // Reset Master in attached Pools
401 20314 : if ( pImp->mpSecondary )
402 : {
403 : #ifdef DBG_UTIL
404 : SAL_INFO( "svl.items", "for Image: there are not statics; this is a bug" );
405 : if ( pImp->ppStaticDefaults )
406 : {
407 : // Delete() did not yet run?
408 : if ( !pImp->maPoolItems.empty() && !pImp->mpSecondary->pImp->maPoolItems.empty() )
409 : {
410 : // Does the Master have SetItems?
411 : bool bHasSetItems = false;
412 : for ( sal_uInt16 i = 0; !bHasSetItems && i < pImp->mnEnd - pImp->mnStart; ++i )
413 : bHasSetItems = pImp->ppStaticDefaults[i]->ISA(SfxSetItem);
414 :
415 : // Detached Pools must be empty
416 : bool bOK = bHasSetItems;
417 : for ( sal_uInt16 n = 0;
418 : bOK && n <= pImp->mpSecondary->pImp->mnEnd - pImp->mpSecondary->pImp->mnStart;
419 : ++n )
420 : {
421 : SfxPoolItemArray_Impl* pItemArr = pImp->mpSecondary->pImp->maPoolItems[n];
422 : if ( pItemArr )
423 : {
424 : SfxPoolItemArrayBase_Impl::iterator ppHtArr = pItemArr->begin();
425 : for( size_t i = pItemArr->size(); i; ++ppHtArr, --i )
426 : if ( !(*ppHtArr) )
427 : {
428 : OSL_FAIL( "old secondary pool must be empty" );
429 : bOK = false;
430 : break;
431 : }
432 : }
433 : }
434 : }
435 : }
436 : #endif
437 :
438 8553 : pImp->mpSecondary->pImp->mpMaster = pImp->mpSecondary;
439 12101 : for ( SfxItemPool *p = pImp->mpSecondary->pImp->mpSecondary; p; p = p->pImp->mpSecondary )
440 3548 : p->pImp->mpMaster = pImp->mpSecondary;
441 : }
442 :
443 : // Set Master of new Secondary Pools
444 : DBG_ASSERT( !pPool || pPool->pImp->mpMaster == pPool, "Secondary is present in two Pools" );
445 20314 : SfxItemPool *pNewMaster = GetMasterPool() ? pImp->mpMaster : this;
446 29615 : for ( SfxItemPool *p = pPool; p; p = p->pImp->mpSecondary )
447 9301 : p->pImp->mpMaster = pNewMaster;
448 :
449 : // Remember new Secondary Pool
450 20314 : pImp->mpSecondary = pPool;
451 :
452 : CHECK_SLOTS();
453 20314 : }
454 :
455 5343 : void SfxItemPool::SetItemInfos(SfxItemInfo const*const pInfos)
456 : {
457 5343 : pItemInfos = pInfos;
458 : CHECK_SLOTS();
459 5343 : }
460 :
461 :
462 :
463 3383738 : SfxMapUnit SfxItemPool::GetMetric( sal_uInt16 ) const
464 : {
465 3383738 : return pImp->eDefMetric;
466 : }
467 :
468 :
469 :
470 51317 : void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric )
471 : {
472 51317 : pImp->eDefMetric = eNewMetric;
473 51317 : }
474 :
475 4597 : const OUString& SfxItemPool::GetName() const
476 : {
477 4597 : return pImp->aName;
478 : }
479 :
480 :
481 :
482 0 : bool SfxItemPool::GetPresentation
483 : (
484 : const SfxPoolItem& rItem,
485 : SfxMapUnit eMetric,
486 : OUString& rText,
487 : const IntlWrapper * pIntlWrapper
488 : ) const
489 : {
490 : return rItem.GetPresentation(
491 0 : SFX_ITEM_PRESENTATION_COMPLETE, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper );
492 : }
493 :
494 :
495 :
496 :
497 37 : SfxItemPool* SfxItemPool::Clone() const
498 : {
499 37 : SfxItemPool *pPool = new SfxItemPool( *this );
500 37 : return pPool;
501 : }
502 :
503 :
504 :
505 64718 : void SfxItemPool::Delete()
506 : {
507 : // Already deleted?
508 64718 : if ( pImp->maPoolItems.empty() || !pImp->ppPoolDefaults )
509 72409 : return;
510 :
511 : // Inform e.g. running Requests
512 57027 : pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) );
513 :
514 : // Iterate through twice: first for the SetItems.
515 : // We separate this into two loops (for clarity's sake)
516 57027 : std::vector<SfxPoolItemArray_Impl*>::iterator itrItemArr = pImp->maPoolItems.begin();
517 57027 : SfxPoolItem** ppDefaultItem = pImp->ppPoolDefaults;
518 57027 : SfxPoolItem** ppStaticDefaultItem = pImp->ppStaticDefaults;
519 : sal_uInt16 nArrCnt;
520 :
521 : // Collect the SetItems first
522 : SAL_INFO( "svl.items", "for Image: there are not statics there yet; this is a bug" );
523 57027 : if ( pImp->ppStaticDefaults )
524 : {
525 4381081 : for ( nArrCnt = GetSize_Impl();
526 : nArrCnt;
527 : --nArrCnt, ++itrItemArr, ++ppDefaultItem, ++ppStaticDefaultItem )
528 : {
529 : // *ppStaticDefaultItem could've already been deleted in a class derived
530 : // from SfxItemPool
531 : // This causes chaos in Itempool!
532 4324054 : if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) )
533 : {
534 13293 : if ( *itrItemArr )
535 : {
536 1639 : SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*itrItemArr)->begin();
537 10174 : for ( size_t n = (*itrItemArr)->size(); n; --n, ++ppHtArr )
538 8535 : if (*ppHtArr)
539 : {
540 : #ifdef DBG_UTIL
541 : ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
542 : #endif
543 2332 : delete *ppHtArr;
544 : }
545 1639 : DELETEZ( *itrItemArr );
546 : }
547 13293 : if ( *ppDefaultItem )
548 : {
549 : #ifdef DBG_UTIL
550 : SetRefCount( **ppDefaultItem, 0 );
551 : #endif
552 104 : DELETEZ( *ppDefaultItem );
553 : }
554 : }
555 : }
556 : }
557 :
558 57027 : itrItemArr = pImp->maPoolItems.begin();
559 57027 : ppDefaultItem = pImp->ppPoolDefaults;
560 :
561 : // Now for the easy Items
562 4381081 : for ( nArrCnt = GetSize_Impl();
563 : nArrCnt;
564 : --nArrCnt, ++itrItemArr, ++ppDefaultItem )
565 : {
566 4324054 : if ( *itrItemArr )
567 : {
568 514658 : SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*itrItemArr)->begin();
569 1372537 : for ( size_t n = (*itrItemArr)->size(); n; --n, ++ppHtArr )
570 857879 : if (*ppHtArr)
571 : {
572 : #ifdef DBG_UTIL
573 : ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() );
574 : #endif
575 340238 : delete *ppHtArr;
576 : }
577 514658 : DELETEZ( *itrItemArr );
578 : }
579 4324054 : if ( *ppDefaultItem )
580 : {
581 : #ifdef DBG_UTIL
582 : SetRefCount( **ppDefaultItem, 0 );
583 : #endif
584 144279 : delete *ppDefaultItem;
585 : }
586 : }
587 :
588 57027 : pImp->DeleteItems();
589 : }
590 :
591 :
592 :
593 390557 : void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem)
594 : {
595 390557 : if ( IsInRange(rItem.Which()) )
596 : {
597 : SfxPoolItem **ppOldDefault =
598 239605 : pImp->ppPoolDefaults + GetIndex_Impl(rItem.Which());
599 239605 : SfxPoolItem *pNewDefault = rItem.Clone(this);
600 239605 : pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT);
601 239605 : if ( *ppOldDefault )
602 : {
603 94118 : (*ppOldDefault)->SetRefCount(0);
604 94118 : DELETEZ( *ppOldDefault );
605 : }
606 239605 : *ppOldDefault = pNewDefault;
607 : }
608 150952 : else if ( pImp->mpSecondary )
609 150952 : pImp->mpSecondary->SetPoolDefaultItem(rItem);
610 : else
611 : {
612 : SFX_ASSERT( false, rItem.Which(), "unknown WhichId - cannot set pool default" );
613 : }
614 390557 : }
615 :
616 : /**
617 : * Resets the default of the given WhichId back to the static Default.
618 : * If a pool default exists, it is removed.
619 : */
620 338 : void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId )
621 : {
622 338 : if ( IsInRange(nWhichId) )
623 : {
624 : SfxPoolItem **ppOldDefault =
625 338 : pImp->ppPoolDefaults + GetIndex_Impl( nWhichId );
626 338 : if ( *ppOldDefault )
627 : {
628 152 : (*ppOldDefault)->SetRefCount(0);
629 152 : DELETEZ( *ppOldDefault );
630 : }
631 : }
632 0 : else if ( pImp->mpSecondary )
633 0 : pImp->mpSecondary->ResetPoolDefaultItem(nWhichId);
634 : else
635 : {
636 : SFX_ASSERT( false, nWhichId, "unknown WhichId - cannot set pool default" );
637 : }
638 338 : }
639 :
640 :
641 :
642 38466690 : const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
643 : {
644 38466690 : if ( 0 == nWhich )
645 2963444 : nWhich = rItem.Which();
646 :
647 : // Find correct Secondary Pool
648 38466690 : bool bSID = nWhich > SFX_WHICH_MAX;
649 38466690 : if ( !bSID && !IsInRange(nWhich) )
650 : {
651 9104830 : if ( pImp->mpSecondary )
652 9104830 : return pImp->mpSecondary->Put( rItem, nWhich );
653 : OSL_FAIL( "unknown WhichId - cannot put item" );
654 : }
655 :
656 : // SID or not poolable (new definition)?
657 29361860 : sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
658 56221350 : if ( USHRT_MAX == nIndex ||
659 26859490 : IsItemFlag_Impl( nIndex, SfxItemPoolFlags::NOT_POOLABLE ) )
660 : {
661 : SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich ||
662 : !IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE,
663 : nWhich, "a non Pool Item is Defaul?!" );
664 2502371 : SfxPoolItem *pPoolItem = rItem.Clone(pImp->mpMaster);
665 2502371 : pPoolItem->SetWhich(nWhich);
666 2502371 : AddRef( *pPoolItem );
667 2502371 : return *pPoolItem;
668 : }
669 :
670 : SFX_ASSERT( !pImp->ppStaticDefaults ||
671 : rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich,
672 : "SFxItemPool: wrong item type in Put" );
673 :
674 26859489 : SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[nIndex];
675 26859489 : if (!pItemArr)
676 : {
677 613733 : pImp->maPoolItems[nIndex] = new SfxPoolItemArray_Impl;
678 613733 : pItemArr = pImp->maPoolItems[nIndex];
679 : }
680 :
681 26859489 : SfxPoolItemArrayBase_Impl::iterator ppFree;
682 26859489 : bool ppFreeIsSet = false;
683 :
684 : // Is this a 'poolable' item - ie. should we re-use and return
685 : // the same underlying item for equivalent (==) SfxPoolItems?
686 26859489 : if ( IsItemFlag_Impl( nIndex, SfxItemPoolFlags::POOLABLE ) )
687 : {
688 : // if is already in a pool, then it is worth checking if it is in this one.
689 26325591 : if ( IsPooledItem(&rItem) )
690 : {
691 20754425 : SfxPoolItemArray_Impl::Hash::const_iterator it;
692 20754425 : it = pItemArr->maHash.find(const_cast<SfxPoolItem *>(&rItem));
693 :
694 : // 1. search for an identical pointer in the pool
695 20754425 : if (it != pItemArr->maHash.end())
696 : {
697 20075605 : AddRef(rItem);
698 20075605 : return rItem;
699 : }
700 : }
701 :
702 : // 2. search for an item with matching attributes.
703 6249986 : SfxPoolItemArrayBase_Impl::iterator itr = pItemArr->begin();
704 24010917 : for (; itr != pItemArr->end(); ++itr)
705 : {
706 22463327 : if (*itr)
707 : {
708 21440529 : if (**itr == rItem)
709 : {
710 4702396 : AddRef(**itr);
711 4702396 : return **itr;
712 : }
713 : }
714 : else
715 : {
716 1022798 : if (!ppFreeIsSet)
717 : {
718 749990 : ppFree = itr;
719 749990 : ppFreeIsSet = true;
720 : }
721 : }
722 : }
723 : }
724 : else
725 : {
726 : // Unconditionally insert; check for a recently freed place
727 533898 : if (pItemArr->maFree.size() > 0)
728 : {
729 420564 : SfxPoolItemArrayBase_Impl::iterator itr = pItemArr->begin();
730 420564 : sal_uInt32 nIdx = pItemArr->maFree.back();
731 420564 : pItemArr->maFree.pop_back();
732 :
733 : assert(nIdx < pItemArr->size());
734 420564 : std::advance(itr, nIdx);
735 420564 : ppFreeIsSet = true;
736 420564 : ppFree = itr;
737 : }
738 : }
739 :
740 : // 3. not found, so clone to insert into the pointer array.
741 2081488 : SfxPoolItem* pNewItem = rItem.Clone(pImp->mpMaster);
742 2081488 : pNewItem->SetWhich(nWhich);
743 : #ifdef DBG_UTIL
744 : SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" )
745 : if ( !rItem.ISA(SfxSetItem) )
746 : {
747 : SFX_ASSERT( !IsItemFlag(nWhich, SfxItemPoolFlags::POOLABLE) ||
748 : rItem == *pNewItem,
749 : nWhich, "unequal items in Put(): no operator==?" );
750 : SFX_ASSERT( !IsItemFlag(*pNewItem, SfxItemPoolFlags::POOLABLE) ||
751 : *pNewItem == rItem,
752 : nWhich, "unequal items in Put(): no operator==?" );
753 : }
754 : #endif
755 2081488 : AddRef( *pNewItem, pImp->nInitRefCount );
756 :
757 : // 4. finally insert into the pointer array
758 : assert( pItemArr->maHash.find(pNewItem) == pItemArr->maHash.end() );
759 2081488 : if ( !ppFreeIsSet )
760 : {
761 976500 : sal_uInt32 nOffset = pItemArr->size();
762 976500 : pItemArr->maHash.insert(std::make_pair(pNewItem, nOffset));
763 976500 : pItemArr->push_back( pNewItem );
764 : }
765 : else
766 : {
767 1104988 : sal_uInt32 nOffset = std::distance(pItemArr->begin(), ppFree);
768 1104988 : pItemArr->maHash.insert(std::make_pair(pNewItem, nOffset));
769 : assert(*ppFree == NULL);
770 1104988 : *ppFree = pNewItem;
771 : }
772 2081488 : return *pNewItem;
773 : }
774 :
775 : /// Re-build our free list and pointer hash.
776 2 : void SfxPoolItemArray_Impl::ReHash()
777 : {
778 2 : maFree.clear();
779 2 : maHash.clear();
780 :
781 5 : for (size_t nIdx = 0; nIdx < size(); ++nIdx)
782 : {
783 3 : SfxPoolItem *pItem = (*this)[nIdx];
784 3 : if (!pItem)
785 0 : maFree.push_back(nIdx);
786 : else
787 : {
788 3 : maHash.insert(std::make_pair(pItem,nIdx));
789 : assert(maHash.find(pItem) != maHash.end());
790 : }
791 : }
792 2 : }
793 :
794 12350211 : void SfxItemPool::Remove( const SfxPoolItem& rItem )
795 : {
796 : SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(),
797 : "where's the Pool Default coming from here?" );
798 :
799 : // Find correct Secondary Pool
800 12350211 : const sal_uInt16 nWhich = rItem.Which();
801 12350211 : bool bSID = nWhich > SFX_WHICH_MAX;
802 12350211 : if ( !bSID && !IsInRange(nWhich) )
803 : {
804 1225188 : if ( pImp->mpSecondary )
805 : {
806 1225188 : pImp->mpSecondary->Remove( rItem );
807 13575399 : return;
808 : }
809 : OSL_FAIL( "unknown WhichId - cannot remove item" );
810 : }
811 :
812 : // SID or not poolable (new definition)?
813 11125023 : sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich);
814 11125023 : if ( bSID || IsItemFlag_Impl( nIndex, SfxItemPoolFlags::NOT_POOLABLE ) )
815 : {
816 : SFX_ASSERT( USHRT_MAX != nIndex ||
817 : !IsDefaultItem(&rItem), rItem.Which(),
818 : "a non Pool Item is Default?!" );
819 2502233 : if ( 0 == ReleaseRef(rItem) )
820 : {
821 2502233 : SfxPoolItem *pItem = &(SfxPoolItem &)rItem;
822 2502233 : delete pItem;
823 : }
824 2502233 : return;
825 : }
826 :
827 : SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove impossible" );
828 :
829 : // Static Defaults are just there
830 11273195 : if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT &&
831 2650405 : &rItem == *( pImp->ppStaticDefaults + GetIndex_Impl(nWhich) ) )
832 2650405 : return;
833 :
834 : // Find Item in own Pool
835 5972385 : SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[nIndex];
836 : SFX_ASSERT( pItemArr, rItem.Which(), "removing Item not in Pool" );
837 :
838 5972385 : SfxPoolItemArray_Impl::Hash::iterator it;
839 5972385 : it = pItemArr->maHash.find(const_cast<SfxPoolItem *>(&rItem));
840 5972385 : if (it != pItemArr->maHash.end())
841 : {
842 5972385 : sal_uInt32 nIdx = it->second;
843 : assert(nIdx < pItemArr->size());
844 5972385 : SfxPoolItem*& p = (*pItemArr)[nIdx];
845 : assert(p == &rItem);
846 :
847 5972385 : if ( p->GetRefCount() ) //!
848 5972385 : ReleaseRef( *p );
849 : else
850 : {
851 : SFX_ASSERT( false, rItem.Which(), "removing Item without ref" );
852 : }
853 :
854 : // FIXME: Hack, for as long as we have problems with the Outliner
855 : // See other MI-REF
856 5972385 : if ( 0 == p->GetRefCount() && nWhich < 4000 )
857 : {
858 1631092 : DELETEZ(p);
859 :
860 : // remove ourselves from the hash
861 1631092 : pItemArr->maHash.erase(it);
862 :
863 : // record that this slot is free
864 1631092 : pItemArr->maFree.push_back( nIdx );
865 : }
866 :
867 5972385 : return;
868 : }
869 :
870 : // not found
871 : SFX_ASSERT( false, rItem.Which(), "removing Item not in Pool" );
872 : }
873 :
874 :
875 :
876 307269734 : const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const
877 : {
878 307269734 : if ( !IsInRange(nWhich) )
879 : {
880 28813235 : if ( pImp->mpSecondary )
881 28813235 : return pImp->mpSecondary->GetDefaultItem( nWhich );
882 : assert(!"unknown which - dont ask me for defaults");
883 : }
884 :
885 : DBG_ASSERT( pImp->ppStaticDefaults, "no defaults known - dont ask me for defaults" );
886 278456499 : sal_uInt16 nPos = GetIndex_Impl(nWhich);
887 278456499 : SfxPoolItem *pDefault = *(pImp->ppPoolDefaults + nPos);
888 278456499 : if ( pDefault )
889 199629219 : return *pDefault;
890 78827280 : return **(pImp->ppStaticDefaults + nPos);
891 : }
892 :
893 313820 : SfxItemPool* SfxItemPool::GetSecondaryPool() const
894 : {
895 313820 : return pImp->mpSecondary;
896 : }
897 :
898 20314 : SfxItemPool* SfxItemPool::GetMasterPool() const
899 : {
900 20314 : return pImp->mpMaster;
901 : }
902 :
903 : /**
904 : * This method should be called at the master pool, when all secondary
905 : * pools are appended to it.
906 : *
907 : * It calculates the ranges of 'which-ids' for fast construction of
908 : * item-sets, which contains all 'which-ids'.
909 : */
910 9666 : void SfxItemPool::FreezeIdRanges()
911 : {
912 9666 : FillItemIdRanges_Impl( pImp->mpPoolRanges );
913 9666 : }
914 :
915 :
916 :
917 :
918 9666 : void SfxItemPool::FillItemIdRanges_Impl( sal_uInt16*& pWhichRanges ) const
919 : {
920 : DBG_ASSERT( !pImp->mpPoolRanges, "GetFrozenRanges() would be faster!" );
921 :
922 : const SfxItemPool *pPool;
923 9666 : sal_uInt16 nLevel = 0;
924 27537 : for( pPool = this; pPool; pPool = pPool->pImp->mpSecondary )
925 17871 : ++nLevel;
926 :
927 9666 : pWhichRanges = new sal_uInt16[ 2*nLevel + 1 ];
928 :
929 9666 : nLevel = 0;
930 27537 : for( pPool = this; pPool; pPool = pPool->pImp->mpSecondary )
931 : {
932 17871 : *(pWhichRanges+(nLevel++)) = pPool->pImp->mnStart;
933 17871 : *(pWhichRanges+(nLevel++)) = pPool->pImp->mnEnd;
934 17871 : *(pWhichRanges+nLevel) = 0;
935 : }
936 9666 : }
937 :
938 16389378 : const sal_uInt16* SfxItemPool::GetFrozenIdRanges() const
939 : {
940 16389378 : return pImp->mpPoolRanges;
941 : }
942 :
943 0 : const SfxPoolItem *SfxItemPool::GetItem2Default(sal_uInt16 nWhich) const
944 : {
945 0 : return GetItem2(nWhich, SFX_ITEMS_DEFAULT);
946 : }
947 :
948 272419 : const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) const
949 : {
950 272419 : if ( !IsInRange(nWhich) )
951 : {
952 42798 : if ( pImp->mpSecondary )
953 42798 : return pImp->mpSecondary->GetItem2( nWhich, nOfst );
954 : SFX_ASSERT( false, nWhich, "unknown WhichId - cannot resolve surrogate" );
955 0 : return 0;
956 : }
957 :
958 : // default attribute?
959 229621 : if ( nOfst == SFX_ITEMS_DEFAULT )
960 0 : return *(pImp->ppStaticDefaults + GetIndex_Impl(nWhich));
961 :
962 229621 : SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[GetIndex_Impl(nWhich)];
963 229621 : if( pItemArr && nOfst < pItemArr->size() )
964 229621 : return (*pItemArr)[nOfst];
965 :
966 0 : return 0;
967 : }
968 :
969 119907 : sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const
970 : {
971 119907 : if ( !IsInRange(nWhich) )
972 : {
973 23794 : if ( pImp->mpSecondary )
974 23794 : return pImp->mpSecondary->GetItemCount2( nWhich );
975 : SFX_ASSERT( false, nWhich, "unknown WhichId - cannot resolve surrogate" );
976 0 : return 0;
977 : }
978 :
979 96113 : SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[GetIndex_Impl(nWhich)];
980 96113 : if ( pItemArr )
981 84533 : return pItemArr->size();
982 11580 : return 0;
983 : }
984 :
985 :
986 :
987 4784381 : sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, bool bDeep ) const
988 : {
989 4784381 : if ( !IsSlot(nSlotId) )
990 226905 : return nSlotId;
991 :
992 4557476 : sal_uInt16 nCount = pImp->mnEnd - pImp->mnStart + 1;
993 336679691 : for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
994 332720783 : if ( pItemInfos[nOfs]._nSID == nSlotId )
995 598568 : return nOfs + pImp->mnStart;
996 3958908 : if ( pImp->mpSecondary && bDeep )
997 1521840 : return pImp->mpSecondary->GetWhich(nSlotId);
998 2437068 : return nSlotId;
999 : }
1000 :
1001 :
1002 :
1003 124387 : sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich, bool bDeep ) const
1004 : {
1005 124387 : if ( !IsWhich(nWhich) )
1006 6 : return nWhich;
1007 :
1008 124381 : if ( !IsInRange( nWhich ) )
1009 : {
1010 1917 : if ( pImp->mpSecondary && bDeep )
1011 1917 : return pImp->mpSecondary->GetSlotId(nWhich);
1012 : SFX_ASSERT( false, nWhich, "unknown WhichId - cannot get slot-id" );
1013 0 : return 0;
1014 : }
1015 :
1016 122464 : sal_uInt16 nSID = pItemInfos[nWhich - pImp->mnStart]._nSID;
1017 122464 : return nSID ? nSID : nWhich;
1018 : }
1019 :
1020 :
1021 :
1022 692 : sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, bool bDeep ) const
1023 : {
1024 692 : if ( !IsSlot(nSlotId) )
1025 0 : return 0;
1026 :
1027 692 : sal_uInt16 nCount = pImp->mnEnd - pImp->mnStart + 1;
1028 24636 : for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs )
1029 24636 : if ( pItemInfos[nOfs]._nSID == nSlotId )
1030 692 : return nOfs + pImp->mnStart;
1031 0 : if ( pImp->mpSecondary && bDeep )
1032 0 : return pImp->mpSecondary->GetTrueWhich(nSlotId);
1033 0 : return 0;
1034 : }
1035 :
1036 :
1037 :
1038 204 : sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich, bool bDeep ) const
1039 : {
1040 204 : if ( !IsWhich(nWhich) )
1041 0 : return 0;
1042 :
1043 204 : if ( !IsInRange( nWhich ) )
1044 : {
1045 0 : if ( pImp->mpSecondary && bDeep )
1046 0 : return pImp->mpSecondary->GetTrueSlotId(nWhich);
1047 : SFX_ASSERT( false, nWhich, "unknown WhichId - cannot get slot-id" );
1048 0 : return 0;
1049 : }
1050 204 : return pItemInfos[nWhich - pImp->mnStart]._nSID;
1051 : }
1052 :
1053 : /**
1054 : * You must call this function to set the file format version after
1055 : * concatenating your secondary-pools but before you store any
1056 : * pool, itemset or item. Only set the version at the master pool,
1057 : * never at any secondary pool.
1058 : */
1059 7122 : void SfxItemPool::SetFileFormatVersion( sal_uInt16 nFileFormatVersion )
1060 : {
1061 : DBG_ASSERT( this == pImp->mpMaster,
1062 : "SfxItemPool::SetFileFormatVersion() but not a master pool" );
1063 14244 : for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pImp->mpSecondary )
1064 7122 : pPool->pImp->mnFileFormatVersion = nFileFormatVersion;
1065 7122 : }
1066 :
1067 : const SfxItemPool* SfxItemPool::pStoringPool_ = 0;
1068 :
1069 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|