1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svl/itempool.hxx>
23 #include <libxml/xmlwriter.h>
25 #include <tools/solar.h>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <svl/SfxBroadcaster.hxx>
29 #include <svl/hint.hxx>
30 #include <svl/itemset.hxx>
38 #if OSL_DEBUG_LEVEL > 0
42 lcl_CheckSlots2(std::map
<sal_uInt16
, sal_uInt16
> & rSlotMap
,
43 SfxItemPool
const& rPool
, SfxItemInfo
const* pInfo
)
46 return; // may not be initialized yet
47 if (rPool
.GetName() == "EditEngineItemPool")
48 return; // HACK: this one has loads of duplicates already, ignore it :(
49 sal_uInt16
const nFirst(rPool
.GetFirstWhich());
50 sal_uInt16
const nCount(rPool
.GetLastWhich() - rPool
.GetFirstWhich() + 1);
51 for (sal_uInt16 n
= 0; n
< nCount
; ++n
)
53 sal_uInt16
const nSlotId(pInfo
[n
]._nSID
);
55 && nSlotId
!= 10883 // preexisting duplicate SID_ATTR_GRAF_CROP
56 && nSlotId
!= 10023 // preexisting duplicate SID_ATTR_BORDER_INNER
57 && nSlotId
!= 10024 // preexisting duplicate SID_ATTR_BORDER_OUTER
58 && nSlotId
!= 11013 // preexisting duplicate SID_ATTR_BORDER_DIAG_TLBR
59 && nSlotId
!= 11014) // preexisting duplicate SID_ATTR_BORDER_DIAG_BLTR
60 { // check for duplicate slot-id mapping
61 std::map
<sal_uInt16
, sal_uInt16
>::const_iterator
const iter(
62 rSlotMap
.find(nSlotId
));
63 sal_uInt16
const nWhich(nFirst
+ n
);
64 if (iter
!= rSlotMap
.end())
66 SAL_WARN("svl", "SfxItemPool: duplicate SlotId " << nSlotId
67 << " mapped to " << iter
->second
<< " and " << nWhich
);
70 rSlotMap
.insert(std::make_pair(nSlotId
, nWhich
));
75 #define CHECK_SLOTS() \
77 std::map<sal_uInt16, sal_uInt16> slotmap; \
78 for (SfxItemPool * p = pImpl->mpMaster; p; p = p->pImpl->mpSecondary) \
80 lcl_CheckSlots2(slotmap, *p, p->pItemInfos); \
85 #define CHECK_SLOTS() do {} while (false)
89 void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser
& rNewUser
)
91 // maintain sorted to reduce cost of remove
92 const auto insertIt
= ::std::lower_bound(
93 pImpl
->maSfxItemPoolUsers
.begin(), pImpl
->maSfxItemPoolUsers
.end(), &rNewUser
);
94 pImpl
->maSfxItemPoolUsers
.insert(insertIt
, &rNewUser
);
97 void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser
& rOldUser
)
99 const auto aFindResult
= ::std::lower_bound(
100 pImpl
->maSfxItemPoolUsers
.begin(), pImpl
->maSfxItemPoolUsers
.end(), &rOldUser
);
101 if(aFindResult
!= pImpl
->maSfxItemPoolUsers
.end() && *aFindResult
== &rOldUser
)
103 pImpl
->maSfxItemPoolUsers
.erase(aFindResult
);
107 const SfxPoolItem
* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich
) const
109 const SfxPoolItem
* pRet
;
110 if( IsInRange( nWhich
) )
111 pRet
= pImpl
->maPoolDefaults
[GetIndex_Impl(nWhich
)];
112 else if( pImpl
->mpSecondary
)
113 pRet
= pImpl
->mpSecondary
->GetPoolDefaultItem( nWhich
);
116 assert(false && "unknown WhichId - cannot get pool default");
123 bool SfxItemPool::IsItemPoolable_Impl( sal_uInt16 nPos
) const
125 return pItemInfos
[nPos
]._bPoolable
;
129 bool SfxItemPool::IsItemPoolable( sal_uInt16 nWhich
) const
131 for ( const SfxItemPool
*pPool
= this; pPool
; pPool
= pPool
->pImpl
->mpSecondary
)
133 if ( pPool
->IsInRange(nWhich
) )
134 return pPool
->IsItemPoolable_Impl( pPool
->GetIndex_Impl(nWhich
));
136 DBG_ASSERT( !IsWhich(nWhich
), "unknown which-id" );
141 SfxBroadcaster
& SfxItemPool::BC()
148 * This is the regular ctor to be used for this class.
149 * An SfxItemPool instance is initialized, which can manage Items in the
150 * range from 'nStartWhich' to 'nEndWhich'.
152 * For every one of these WhichIds a static Default must be present in the
153 * 'pDefaults' array. They start with an SfxPoolItem (with the WhichId
154 * 'nStartWhich'), are sorted by WhichId and consecutively stored.
156 * 'pItemInfos' is a USHORT array arranged in the same way, which holds
157 * SlotIds and Flags. These SlotIds can be 0, if the affected Items are
158 * exclusively used in the Core.
159 * The flags allow for e.g. enabling value sharing (poolable).
161 * If the Pool is supposed to hold SfxSetItems, the ctor cannot yet contain
162 * static Defaults. This needs to be done afterwards, using
163 * @see SfxItemPool::SetDefaults(std::vector<SfxPoolItem*>*).
165 * @see SfxItemPool::SetDefaults(std::vector<SfxPoolItem*>*)
166 * @see SfxItemPool::ReleaseDefaults(std::vector<SfxPoolItem*>*,sal_uInt16,sal_Bool)
167 * @see SfxItemPool::ReldaseDefaults(sal_Bool)
169 SfxItemPool::SfxItemPool
171 const OUString
& rName
, /* Pool name to identify in the file format */
172 sal_uInt16 nStartWhich
, /* First WhichId of the Pool (must be > 0) */
173 sal_uInt16 nEndWhich
, /* Last WhichId of the Pool */
174 const SfxItemInfo
* pInfo
, /* SID Map and Item flags */
175 std::vector
<SfxPoolItem
*>*
176 pDefaults
/* Pointer to static Defaults;
177 is directly referenced by the Pool,
178 but no transfer of ownership */
181 pImpl( new SfxItemPool_Impl( this, rName
, nStartWhich
, nEndWhich
) )
183 pImpl
->eDefMetric
= MapUnit::MapTwip
;
186 SetDefaults(pDefaults
);
193 * @see SfxItemPool::Clone() const
195 SfxItemPool::SfxItemPool
197 const SfxItemPool
& rPool
, // Copy from this instance
198 bool bCloneStaticDefaults
/* true
202 Take over static Defaults */
204 pItemInfos(rPool
.pItemInfos
),
205 pImpl( new SfxItemPool_Impl( this, rPool
.pImpl
->aName
, rPool
.pImpl
->mnStart
, rPool
.pImpl
->mnEnd
) )
207 pImpl
->eDefMetric
= rPool
.pImpl
->eDefMetric
;
209 // Take over static Defaults
210 if ( bCloneStaticDefaults
)
212 std::vector
<SfxPoolItem
*>* ppDefaults
= new std::vector
<SfxPoolItem
*>(pImpl
->mnEnd
-pImpl
->mnStart
+1);
213 for ( sal_uInt16 n
= 0; n
<= pImpl
->mnEnd
- pImpl
->mnStart
; ++n
)
215 (*ppDefaults
)[n
] = (*rPool
.pImpl
->mpStaticDefaults
)[n
]->Clone(this);
216 (*ppDefaults
)[n
]->SetKind(SfxItemKind::StaticDefault
);
219 SetDefaults( ppDefaults
);
222 SetDefaults( rPool
.pImpl
->mpStaticDefaults
);
224 // Copy Pool Defaults
225 for (size_t n
= 0; n
< pImpl
->maPoolDefaults
.size(); ++n
)
226 if (rPool
.pImpl
->maPoolDefaults
[n
])
228 pImpl
->maPoolDefaults
[n
] = rPool
.pImpl
->maPoolDefaults
[n
]->Clone(this); //resets kind
229 pImpl
->maPoolDefaults
[n
]->SetKind(SfxItemKind::PoolDefault
);
233 if ( rPool
.pImpl
->mpSecondary
)
234 SetSecondaryPool( rPool
.pImpl
->mpSecondary
->Clone() );
237 void SfxItemPool::SetDefaults( std::vector
<SfxPoolItem
*>* pDefaults
)
239 DBG_ASSERT( pDefaults
, "first we ask for it, and then we don't give back..." );
240 DBG_ASSERT( !pImpl
->mpStaticDefaults
, "already have Defaults" );
242 pImpl
->mpStaticDefaults
= pDefaults
;
243 //! if ((*mpStaticDefaults)->GetKind() != SfxItemKind::StaticDefault)
244 //! FIXME: Probably doesn't work with SetItems at the end
246 DBG_ASSERT( (*pImpl
->mpStaticDefaults
)[0]->GetRefCount() == 0 ||
247 IsDefaultItem( (*pImpl
->mpStaticDefaults
)[0] ),
248 "these are not static" );
249 for ( sal_uInt16 n
= 0; n
<= pImpl
->mnEnd
- pImpl
->mnStart
; ++n
)
251 assert( ((*pImpl
->mpStaticDefaults
)[n
]->Which() == n
+ pImpl
->mnStart
)
252 && "static defaults not sorted" );
253 (*pImpl
->mpStaticDefaults
)[n
]->SetKind(SfxItemKind::StaticDefault
);
254 DBG_ASSERT( pImpl
->maPoolItemArrays
[n
].empty(), "defaults with setitems with items?!" );
259 void SfxItemPool::ClearDefaults()
261 pImpl
->mpStaticDefaults
= nullptr;
265 * Frees the static Defaults of the corresponding SfxItemPool instance
266 * and deletes them if specified.
268 * The SfxItemPool instance MUST NOT BE USED after this function has
269 * been called; only the dtor must be called.
271 void SfxItemPool::ReleaseDefaults
274 Deletes the array as well as the single static Defaults
277 Neither deletes the array not the single static Defaults */
282 DBG_ASSERT( pImpl
->mpStaticDefaults
, "requirements not met" );
283 ReleaseDefaults( pImpl
->mpStaticDefaults
, bDelete
);
285 // mpStaticDefaults points to deleted memory if bDelete == true.
287 pImpl
->mpStaticDefaults
= nullptr;
292 * Frees the specified static Defaults and also deletes them, if so
295 * This method MUST be called AFTER all SfxItemPool instances (which
296 * use the specified static Defaults 'pDefault') have been destroyed.
298 void SfxItemPool::ReleaseDefaults
300 std::vector
<SfxPoolItem
*>*
301 pDefaults
, /* Static Defaults that are to be freed */
304 Deletes the array as well as the specified
308 Neither deletes the array nor the single
312 DBG_ASSERT( pDefaults
, "we first ask for it and the return nothing ..." );
314 for ( auto & rpItem
: *pDefaults
)
316 assert(IsStaticDefaultItem(rpItem
));
317 rpItem
->SetRefCount(0);
333 SfxItemPool::~SfxItemPool()
335 if ( !pImpl
->maPoolItemArrays
.empty() && !pImpl
->maPoolDefaults
.empty() )
338 if (pImpl
->mpMaster
!= nullptr && pImpl
->mpMaster
!= this)
340 // This condition indicates an error.
341 // A pImpl->mpMaster->SetSecondaryPool(...) call should have been made
342 // earlier to prevent this. At this point we can only try to
343 // prevent a crash later on.
344 DBG_ASSERT( pImpl
->mpMaster
== this, "destroying active Secondary-Pool" );
345 if (pImpl
->mpMaster
->pImpl
->mpSecondary
== this)
346 pImpl
->mpMaster
->pImpl
->mpSecondary
= nullptr;
350 void SfxItemPool::Free(SfxItemPool
* pPool
)
355 // tell all the registered SfxItemPoolUsers that the pool is in destruction
356 std::vector
<SfxItemPoolUser
*> aListCopy(pPool
->pImpl
->maSfxItemPoolUsers
);
357 for(SfxItemPoolUser
* pSfxItemPoolUser
: aListCopy
)
359 DBG_ASSERT(pSfxItemPoolUser
, "corrupt SfxItemPoolUser list (!)");
360 pSfxItemPoolUser
->ObjectInDestruction(*pPool
);
363 // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser()
364 // when they get called from ObjectInDestruction().
365 pPool
->pImpl
->maSfxItemPoolUsers
.clear();
372 void SfxItemPool::SetSecondaryPool( SfxItemPool
*pPool
)
374 // Reset Master in attached Pools
375 if ( pImpl
->mpSecondary
)
378 if (pImpl
->mpStaticDefaults
!= nullptr && !pImpl
->maPoolItemArrays
.empty()
379 && !pImpl
->mpSecondary
->pImpl
->maPoolItemArrays
.empty())
380 // Delete() did not yet run?
382 // Does the Master have SetItems?
383 bool bHasSetItems
= false;
384 for ( sal_uInt16 i
= 0; !bHasSetItems
&& i
< pImpl
->mnEnd
- pImpl
->mnStart
; ++i
)
385 bHasSetItems
= dynamic_cast<const SfxSetItem
*>((*pImpl
->mpStaticDefaults
)[i
]) != nullptr;
387 // Detached Pools must be empty
388 bool bOK
= bHasSetItems
;
389 for (auto const& rSecArray
: pImpl
->mpSecondary
->pImpl
->maPoolItemArrays
)
393 if (rSecArray
.size()>0)
395 SAL_WARN("svl.items", "old secondary pool: " << pImpl
->mpSecondary
->pImpl
->aName
396 << " of pool: " << pImpl
->aName
<< " must be empty.");
403 pImpl
->mpSecondary
->pImpl
->mpMaster
= pImpl
->mpSecondary
;
404 for ( SfxItemPool
*p
= pImpl
->mpSecondary
->pImpl
->mpSecondary
; p
; p
= p
->pImpl
->mpSecondary
)
405 p
->pImpl
->mpMaster
= pImpl
->mpSecondary
;
408 // Set Master of new Secondary Pools
409 DBG_ASSERT( !pPool
|| pPool
->pImpl
->mpMaster
== pPool
, "Secondary is present in two Pools" );
410 SfxItemPool
*pNewMaster
= GetMasterPool() ? pImpl
->mpMaster
: this;
411 for ( SfxItemPool
*p
= pPool
; p
; p
= p
->pImpl
->mpSecondary
)
412 p
->pImpl
->mpMaster
= pNewMaster
;
414 // Remember new Secondary Pool
415 pImpl
->mpSecondary
= pPool
;
420 void SfxItemPool::SetItemInfos(SfxItemInfo
const*const pInfo
)
427 MapUnit
SfxItemPool::GetMetric( sal_uInt16
) const
429 return pImpl
->eDefMetric
;
433 void SfxItemPool::SetDefaultMetric( MapUnit eNewMetric
)
435 pImpl
->eDefMetric
= eNewMetric
;
438 const OUString
& SfxItemPool::GetName() const
444 bool SfxItemPool::GetPresentation
446 const SfxPoolItem
& rItem
,
449 const IntlWrapper
& rIntlWrapper
452 return rItem
.GetPresentation(
453 SfxItemPresentation::Complete
, GetMetric(rItem
.Which()), eMetric
, rText
, rIntlWrapper
);
457 SfxItemPool
* SfxItemPool::Clone() const
459 SfxItemPool
*pPool
= new SfxItemPool( *this );
464 void SfxItemPool::Delete()
467 if (pImpl
->maPoolItemArrays
.empty() || pImpl
->maPoolDefaults
.empty())
470 // Inform e.g. running Requests
471 pImpl
->aBC
.Broadcast( SfxHint( SfxHintId::Dying
) );
473 // Iterate through twice: first for the SetItems.
474 if (pImpl
->mpStaticDefaults
!= nullptr) {
475 for (size_t n
= 0; n
< GetSize_Impl(); ++n
)
477 // *mpStaticDefaultItem could've already been deleted in a class derived
479 // This causes chaos in Itempool!
480 const SfxPoolItem
* pStaticDefaultItem
= (*pImpl
->mpStaticDefaults
)[n
];
481 if (dynamic_cast<const SfxSetItem
*>(pStaticDefaultItem
))
483 // SfxSetItem found, remove PoolItems (and defaults) with same ID
484 auto& rArray
= pImpl
->maPoolItemArrays
[n
];
485 for (auto& rItemPtr
: rArray
)
487 ReleaseRef(*rItemPtr
, rItemPtr
->GetRefCount()); // for RefCount check in dtor
491 // let pImpl->DeleteItems() delete item arrays in maPoolItems
492 auto& rItemPtr
= pImpl
->maPoolDefaults
[n
];
496 ClearRefCount(*rItemPtr
);
505 // now remove remaining PoolItems (and defaults) who didn't have SetItems
506 for (auto& rArray
: pImpl
->maPoolItemArrays
)
508 for (auto& rItemPtr
: rArray
)
510 ReleaseRef(*rItemPtr
, rItemPtr
->GetRefCount()); // for RefCount check in dtor
514 // let pImpl->DeleteItems() delete item arrays in maPoolItems
516 pImpl
->maPoolItemArrays
.clear();
518 for (auto rItemPtr
: pImpl
->maPoolDefaults
)
523 ClearRefCount(*rItemPtr
);
530 pImpl
->DeleteItems();
534 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem
&rItem
)
536 if ( IsInRange(rItem
.Which()) )
539 pImpl
->maPoolDefaults
[GetIndex_Impl(rItem
.Which())];
540 SfxPoolItem
*pNewDefault
= rItem
.Clone(this);
541 pNewDefault
->SetKind(SfxItemKind::PoolDefault
);
544 rOldDefault
->SetRefCount(0);
545 DELETEZ(rOldDefault
);
547 rOldDefault
= pNewDefault
;
549 else if ( pImpl
->mpSecondary
)
550 pImpl
->mpSecondary
->SetPoolDefaultItem(rItem
);
553 assert(false && "unknown WhichId - cannot set pool default");
558 * Resets the default of the given WhichId back to the static Default.
559 * If a pool default exists, it is removed.
561 void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId
)
563 if ( IsInRange(nWhichId
) )
566 pImpl
->maPoolDefaults
[GetIndex_Impl(nWhichId
)];
569 rOldDefault
->SetRefCount(0);
570 DELETEZ(rOldDefault
);
573 else if ( pImpl
->mpSecondary
)
574 pImpl
->mpSecondary
->ResetPoolDefaultItem(nWhichId
);
577 assert(false && "unknown WhichId - cannot reset pool default");
582 const SfxPoolItem
& SfxItemPool::PutImpl( const SfxPoolItem
& rItem
, sal_uInt16 nWhich
, bool bPassingOwnership
)
585 nWhich
= rItem
.Which();
587 // Find correct Secondary Pool
588 bool bSID
= IsSlot(nWhich
);
589 if ( !bSID
&& !IsInRange(nWhich
) )
591 if ( pImpl
->mpSecondary
)
592 return pImpl
->mpSecondary
->PutImpl( rItem
, nWhich
, bPassingOwnership
);
593 OSL_FAIL( "unknown WhichId - cannot put item" );
599 assert((rItem
.Which() != nWhich
||
600 !IsDefaultItem(&rItem
) || rItem
.GetKind() == SfxItemKind::DeleteOnIdle
)
601 && "a non Pool Item is Default?!");
602 SfxPoolItem
*pPoolItem
= rItem
.Clone(pImpl
->mpMaster
);
603 pPoolItem
->SetWhich(nWhich
);
604 AddRef( *pPoolItem
);
605 if (bPassingOwnership
)
610 assert(!pImpl
->mpStaticDefaults
||
611 typeid(rItem
) == typeid(GetDefaultItem(nWhich
)));
613 const sal_uInt16 nIndex
= GetIndex_Impl(nWhich
);
614 SfxPoolItemArray_Impl
& rItemArr
= pImpl
->maPoolItemArrays
[nIndex
];
616 // Is this a 'poolable' item - ie. should we re-use and return
617 // the same underlying item for equivalent (==) SfxPoolItems?
618 if ( IsItemPoolable_Impl( nIndex
) )
620 // if is already in a pool, then it is worth checking if it is in this one.
621 if ( IsPooledItem(&rItem
) )
623 // 1. search for an identical pointer in the pool
624 auto it
= rItemArr
.find(const_cast<SfxPoolItem
*>(&rItem
));
625 if (it
!= rItemArr
.end())
628 assert(!bPassingOwnership
&& "can't be passing ownership and have the item already in the pool");
633 const SfxPoolItem
* pFoundItem
= nullptr;
634 // 2. search for an item with matching attributes.
635 if (rItem
.IsSortable())
637 pFoundItem
= rItemArr
.findByLessThan(&rItem
);
639 assert(*pFoundItem
== rItem
);
643 for (auto itr
= rItemArr
.begin(); itr
!= rItemArr
.end(); ++itr
)
654 assert((!bPassingOwnership
|| (&rItem
!= pFoundItem
)) && "can't be passing ownership and have the item already in the pool");
656 if (bPassingOwnership
)
662 // 3. not found, so clone to insert into the pointer array.
663 SfxPoolItem
* pNewItem
;
664 if (bPassingOwnership
)
666 assert(!dynamic_cast<const SfxItemSet
*>(&rItem
) && "can't pass ownership of SfxItem, they need to be cloned to the master pool");
667 pNewItem
= const_cast<SfxPoolItem
*>(&rItem
);
670 pNewItem
= rItem
.Clone(pImpl
->mpMaster
);
671 pNewItem
->SetWhich(nWhich
);
672 assert(typeid(rItem
) == typeid(*pNewItem
) && "SfxItemPool::Put(): unequal types, no Clone() override?");
673 if (dynamic_cast<const SfxSetItem
*>(&rItem
) == nullptr)
675 assert((!IsItemPoolable(nWhich
) || rItem
== *pNewItem
)
676 && "SfxItemPool::Put(): unequal items: no operator== override?");
677 assert((!IsItemPoolable(*pNewItem
) || *pNewItem
== rItem
)
678 && "SfxItemPool::Put(): unequal items: no operator== override?");
682 // 4. finally insert into the pointer array
683 assert( rItemArr
.find(pNewItem
) == rItemArr
.end() );
684 rItemArr
.insert( pNewItem
);
688 void SfxItemPool::Remove( const SfxPoolItem
& rItem
)
690 assert(!IsPoolDefaultItem(&rItem
) && "cannot remove Pool Default");
692 // Find correct Secondary Pool
693 const sal_uInt16 nWhich
= rItem
.Which();
694 bool bSID
= IsSlot(nWhich
);
695 if ( !bSID
&& !IsInRange(nWhich
) )
697 if ( pImpl
->mpSecondary
)
699 pImpl
->mpSecondary
->Remove( rItem
);
702 OSL_FAIL( "unknown WhichId - cannot remove item" );
708 assert(!IsDefaultItem(&rItem
) && "a non Pool Item is Default?!");
709 if ( 0 == ReleaseRef(rItem
) )
716 assert(rItem
.GetRefCount() && "RefCount == 0, Remove impossible");
718 const sal_uInt16 nIndex
= GetIndex_Impl(nWhich
);
719 // Static Defaults are just there
720 if ( IsStaticDefaultItem(&rItem
) &&
721 &rItem
== (*pImpl
->mpStaticDefaults
)[nIndex
])
724 // Find Item in own Pool
725 SfxPoolItemArray_Impl
& rItemArr
= pImpl
->maPoolItemArrays
[nIndex
];
727 auto it
= rItemArr
.find(const_cast<SfxPoolItem
*>(&rItem
));
728 if (it
!= rItemArr
.end())
730 if ( rItem
.GetRefCount() ) //!
734 assert(false && "removing Item without ref");
737 // FIXME: Hack, for as long as we have problems with the Outliner
739 if ( 0 == rItem
.GetRefCount() && nWhich
< 4000 )
749 assert(false && "removing Item not in Pool");
753 const SfxPoolItem
& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich
) const
755 if ( !IsInRange(nWhich
) )
757 if ( pImpl
->mpSecondary
)
758 return pImpl
->mpSecondary
->GetDefaultItem( nWhich
);
759 assert(!"unknown which - don't ask me for defaults");
762 DBG_ASSERT( pImpl
->mpStaticDefaults
, "no defaults known - don't ask me for defaults" );
763 sal_uInt16 nPos
= GetIndex_Impl(nWhich
);
764 SfxPoolItem
* pDefault
= pImpl
->maPoolDefaults
[nPos
];
767 return *(*pImpl
->mpStaticDefaults
)[nPos
];
770 SfxItemPool
* SfxItemPool::GetSecondaryPool() const
772 return pImpl
->mpSecondary
;
775 SfxItemPool
* SfxItemPool::GetMasterPool() const
777 return pImpl
->mpMaster
;
781 * This method should be called at the master pool, when all secondary
782 * pools are appended to it.
784 * It calculates the ranges of 'which-ids' for fast construction of
785 * item-sets, which contains all 'which-ids'.
787 void SfxItemPool::FreezeIdRanges()
789 FillItemIdRanges_Impl( pImpl
->mpPoolRanges
);
793 void SfxItemPool::FillItemIdRanges_Impl( std::unique_ptr
<sal_uInt16
[]>& pWhichRanges
) const
795 DBG_ASSERT( !pImpl
->mpPoolRanges
, "GetFrozenRanges() would be faster!" );
797 const SfxItemPool
*pPool
;
798 sal_uInt16 nLevel
= 0;
799 for( pPool
= this; pPool
; pPool
= pPool
->pImpl
->mpSecondary
)
802 pWhichRanges
.reset(new sal_uInt16
[ 2*nLevel
+ 1 ]);
805 for( pPool
= this; pPool
; pPool
= pPool
->pImpl
->mpSecondary
)
807 pWhichRanges
[nLevel
++] = pPool
->pImpl
->mnStart
;
808 pWhichRanges
[nLevel
++] = pPool
->pImpl
->mnEnd
;
809 pWhichRanges
[nLevel
] = 0;
813 const sal_uInt16
* SfxItemPool::GetFrozenIdRanges() const
815 return pImpl
->mpPoolRanges
.get();
818 const SfxPoolItem
*SfxItemPool::GetItem2Default(sal_uInt16 nWhich
) const
820 if ( !IsInRange(nWhich
) )
822 if ( pImpl
->mpSecondary
)
823 return pImpl
->mpSecondary
->GetItem2Default( nWhich
);
824 assert(false && "unknown WhichId - cannot resolve surrogate");
827 return (*pImpl
->mpStaticDefaults
)[ GetIndex_Impl(nWhich
) ];
830 SfxItemPool::Item2Range
SfxItemPool::GetItemSurrogates(sal_uInt16 nWhich
) const
832 static const o3tl::sorted_vector
<SfxPoolItem
*> EMPTY
;
834 if ( !IsInRange(nWhich
) )
836 if ( pImpl
->mpSecondary
)
837 return pImpl
->mpSecondary
->GetItemSurrogates( nWhich
);
838 assert(false && "unknown WhichId - cannot resolve surrogate");
839 return { EMPTY
.end(), EMPTY
.end() };
842 SfxPoolItemArray_Impl
& rItemArr
= pImpl
->maPoolItemArrays
[GetIndex_Impl(nWhich
)];
843 return { rItemArr
.begin(), rItemArr
.end() };
846 /* This is only valid for SfxPoolItem that override IsSortable and operator< */
847 std::vector
<const SfxPoolItem
*> SfxItemPool::FindItemSurrogate(sal_uInt16 nWhich
, SfxPoolItem
const & rSample
) const
849 if ( !IsInRange(nWhich
) )
851 if ( pImpl
->mpSecondary
)
852 return pImpl
->mpSecondary
->FindItemSurrogate( nWhich
, rSample
);
853 assert(false && "unknown WhichId - cannot resolve surrogate");
854 return std::vector
<const SfxPoolItem
*>();
857 SfxPoolItemArray_Impl
& rItemArr
= pImpl
->maPoolItemArrays
[GetIndex_Impl(nWhich
)];
858 return rItemArr
.findSurrogateRange(&rSample
);
861 sal_uInt32
SfxItemPool::GetItemCount2(sal_uInt16 nWhich
) const
863 if ( !IsInRange(nWhich
) )
865 if ( pImpl
->mpSecondary
)
866 return pImpl
->mpSecondary
->GetItemCount2( nWhich
);
867 assert(false && "unknown WhichId - cannot resolve surrogate");
871 SfxPoolItemArray_Impl
& rItemArr
= pImpl
->maPoolItemArrays
[GetIndex_Impl(nWhich
)];
872 return rItemArr
.size();
876 sal_uInt16
SfxItemPool::GetWhich( sal_uInt16 nSlotId
, bool bDeep
) const
878 if ( !IsSlot(nSlotId
) )
881 sal_uInt16 nCount
= pImpl
->mnEnd
- pImpl
->mnStart
+ 1;
882 for ( sal_uInt16 nOfs
= 0; nOfs
< nCount
; ++nOfs
)
883 if ( pItemInfos
[nOfs
]._nSID
== nSlotId
)
884 return nOfs
+ pImpl
->mnStart
;
885 if ( pImpl
->mpSecondary
&& bDeep
)
886 return pImpl
->mpSecondary
->GetWhich(nSlotId
);
891 sal_uInt16
SfxItemPool::GetSlotId( sal_uInt16 nWhich
) const
893 if ( !IsWhich(nWhich
) )
896 if ( !IsInRange( nWhich
) )
898 if ( pImpl
->mpSecondary
)
899 return pImpl
->mpSecondary
->GetSlotId(nWhich
);
900 assert(false && "unknown WhichId - cannot get slot-id");
904 sal_uInt16 nSID
= pItemInfos
[nWhich
- pImpl
->mnStart
]._nSID
;
905 return nSID
? nSID
: nWhich
;
909 sal_uInt16
SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId
, bool bDeep
) const
911 if ( !IsSlot(nSlotId
) )
914 sal_uInt16 nCount
= pImpl
->mnEnd
- pImpl
->mnStart
+ 1;
915 for ( sal_uInt16 nOfs
= 0; nOfs
< nCount
; ++nOfs
)
916 if ( pItemInfos
[nOfs
]._nSID
== nSlotId
)
917 return nOfs
+ pImpl
->mnStart
;
918 if ( pImpl
->mpSecondary
&& bDeep
)
919 return pImpl
->mpSecondary
->GetTrueWhich(nSlotId
);
924 sal_uInt16
SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich
) const
926 if ( !IsWhich(nWhich
) )
929 if ( !IsInRange( nWhich
) )
931 if ( pImpl
->mpSecondary
)
932 return pImpl
->mpSecondary
->GetTrueSlotId(nWhich
);
933 assert(false && "unknown WhichId - cannot get slot-id");
936 return pItemInfos
[nWhich
- pImpl
->mnStart
]._nSID
;
939 void SfxItemPool::dumpAsXml(xmlTextWriterPtr pWriter
) const
941 xmlTextWriterStartElement(pWriter
, BAD_CAST("SfxItemPool"));
942 for (auto const & rArray
: pImpl
->maPoolItemArrays
)
943 for (auto const & rItem
: rArray
)
944 rItem
->dumpAsXml(pWriter
);
945 xmlTextWriterEndElement(pWriter
);
948 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */