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