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 .
27 #include <libxml/xmlwriter.h>
29 #include <sal/log.hxx>
30 #include <svl/itemset.hxx>
31 #include <svl/itempool.hxx>
32 #include <svl/itemiter.hxx>
33 #include <svl/whiter.hxx>
35 #include <tools/stream.hxx>
36 #include <tools/solar.h>
37 #include <rtl/string.hxx>
41 static const sal_uInt16 nInitCount
= 10; // Single USHORTs => 5 pairs without '0'
47 * Determines the number of sal_uInt16s in a 0-terminated array of pairs of
49 * The terminating 0 is not included in the count.
51 sal_uInt16
Count_Impl( const sal_uInt16
*pRanges
)
53 sal_uInt16 nCount
= 0;
63 * Determines the total number of sal_uInt16s described in a 0-terminated
64 * array of pairs of sal_uInt16s, each representing an range of sal_uInt16s.
66 sal_uInt16
Capacity_Impl( const sal_uInt16
*pRanges
)
68 sal_uInt16 nCount
= 0;
74 nCount
+= pRanges
[1] - pRanges
[0] + 1;
84 * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
85 * the supplied SfxItemPool.
87 * For Sfx programmers: an SfxItemSet constructed in this way cannot
88 * contain any Items with SlotIds as Which values.
90 SfxItemSet::SfxItemSet(SfxItemPool
& rPool
)
95 m_pWhichRanges
= const_cast<sal_uInt16
*>(m_pPool
->GetFrozenIdRanges());
96 assert( m_pWhichRanges
&& "don't create ItemSets with full range before FreezeIdRanges()" );
99 std::unique_ptr
<sal_uInt16
[]> tmp
;
100 m_pPool
->FillItemIdRanges_Impl(tmp
);
101 m_pWhichRanges
= tmp
.release();
104 const sal_uInt16 nSize
= TotalCount();
105 m_pItems
.reset(new const SfxPoolItem
*[nSize
]{});
108 void SfxItemSet::InitRanges_Impl(const sal_uInt16
*pWhichPairTable
)
111 const sal_uInt16
* pPtr
= pWhichPairTable
;
114 nCnt
+= ( *(pPtr
+1) - *pPtr
) + 1;
118 m_pItems
.reset( new const SfxPoolItem
*[nCnt
]{} );
120 std::ptrdiff_t cnt
= pPtr
- pWhichPairTable
+1;
121 m_pWhichRanges
= new sal_uInt16
[ cnt
];
122 memcpy( m_pWhichRanges
, pWhichPairTable
, sizeof( sal_uInt16
) * cnt
);
125 SfxItemSet::SfxItemSet(
126 SfxItemPool
& pool
, std::initializer_list
<sal_uInt16
> wids
,
128 m_pPool(&pool
), m_pParent(nullptr),
129 m_pItems(new SfxPoolItem
const *[items
]{}),
130 m_pWhichRanges(new sal_uInt16
[wids
.size() + 1]),
131 // cannot overflow, assuming std::size_t is no smaller than sal_uInt16,
132 // as wids.size() must be substantially smaller than
133 // std::numeric_limits<sal_uInt16>::max() by construction in
134 // SfxItemSet::create
137 assert(wids
.size() != 0);
138 assert(wids
.size() % 2 == 0);
139 std::copy(wids
.begin(), wids
.end(), m_pWhichRanges
);
140 m_pWhichRanges
[wids
.size()] = 0;
143 SfxItemSet::SfxItemSet(
144 SfxItemPool
& pool
, std::initializer_list
<Pair
> wids
):
145 m_pPool(&pool
), m_pParent(nullptr),
146 m_pWhichRanges(new sal_uInt16
[2 * wids
.size() + 1]), //TODO: overflow
149 assert(wids
.size() != 0);
151 std::size_t size
= 0;
153 //TODO: sal_uInt16 prev = 0;
155 for (auto const & p
: wids
) {
156 assert(svl::detail::validRange(p
.wid1
, p
.wid2
));
157 //TODO: assert(prev == 0 || svl::detail::validGap(prev, p.wid1));
158 m_pWhichRanges
[i
++] = p
.wid1
;
159 m_pWhichRanges
[i
++] = p
.wid2
;
160 size
+= svl::detail::rangeSize(p
.wid1
, p
.wid2
);
161 // cannot overflow, assuming std::size_t is no smaller than
164 //TODO: prev = p.wid2;
167 m_pWhichRanges
[i
] = 0;
168 m_pItems
.reset( new SfxPoolItem
const *[size
]{} );
171 SfxItemSet::SfxItemSet( SfxItemPool
& rPool
, const sal_uInt16
* pWhichPairTable
)
174 , m_pWhichRanges(nullptr)
177 // pWhichPairTable == 0 is for the SfxAllEnumItemSet
178 if ( pWhichPairTable
)
179 InitRanges_Impl(pWhichPairTable
);
182 SfxItemSet::SfxItemSet( const SfxItemSet
& rASet
)
183 : m_pPool( rASet
.m_pPool
)
184 , m_pParent( rASet
.m_pParent
)
185 , m_nCount( rASet
.m_nCount
)
187 // Calculate the attribute count
189 sal_uInt16
* pPtr
= rASet
.m_pWhichRanges
;
192 nCnt
+= ( *(pPtr
+1) - *pPtr
) + 1;
196 m_pItems
.reset( new const SfxPoolItem
* [ nCnt
] );
199 SfxPoolItem
const** ppDst
= m_pItems
.get();
200 SfxPoolItem
const** ppSrc
= rASet
.m_pItems
.get();
201 for( sal_uInt16 n
= nCnt
; n
; --n
, ++ppDst
, ++ppSrc
)
202 if ( nullptr == *ppSrc
|| // Current Default?
203 IsInvalidItem(*ppSrc
) || // DontCare?
204 IsStaticDefaultItem(*ppSrc
) ) // Defaults that are not to be pooled?
205 // Just copy the pointer
207 else if (m_pPool
->IsItemPoolable( **ppSrc
))
209 // Just copy the pointer and increase RefCount
213 else if ( !(*ppSrc
)->Which() )
214 *ppDst
= (*ppSrc
)->Clone();
216 // !IsPoolable() => assign via Pool
217 *ppDst
= &m_pPool
->Put( **ppSrc
);
219 // Copy the WhichRanges
220 std::ptrdiff_t cnt
= pPtr
- rASet
.m_pWhichRanges
+1;
221 m_pWhichRanges
= new sal_uInt16
[ cnt
];
222 memcpy( m_pWhichRanges
, rASet
.m_pWhichRanges
, sizeof( sal_uInt16
) * cnt
);
225 SfxItemSet::~SfxItemSet()
227 sal_uInt16 nCount
= TotalCount();
230 SfxPoolItem
const** ppFnd
= m_pItems
.get();
231 for( sal_uInt16 nCnt
= nCount
; nCnt
; --nCnt
, ++ppFnd
)
232 if( *ppFnd
&& !IsInvalidItem(*ppFnd
) )
234 if( !(*ppFnd
)->Which() )
237 // Still multiple references present, so just alter the RefCount
238 if ( 1 < (*ppFnd
)->GetRefCount() && !IsDefaultItem(*ppFnd
) )
239 (*ppFnd
)->ReleaseRef();
241 if ( !IsDefaultItem(*ppFnd
) )
243 m_pPool
->Remove( **ppFnd
);
249 if (m_pWhichRanges
!= m_pPool
->GetFrozenIdRanges())
250 delete[] m_pWhichRanges
;
251 m_pWhichRanges
= nullptr; // for invariant-testing
255 * Delete single Items or all Items (nWhich == 0)
257 sal_uInt16
SfxItemSet::ClearItem( sal_uInt16 nWhich
)
263 SfxPoolItem
const** ppFnd
= m_pItems
.get();
267 const sal_uInt16
* pPtr
= m_pWhichRanges
;
270 // Within this range?
271 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
274 ppFnd
+= nWhich
- *pPtr
;
277 // Due to the assertions in the sub calls, we need to do the following
279 const SfxPoolItem
*pItemToClear
= *ppFnd
;
282 if ( !IsInvalidItem(pItemToClear
) )
284 if (SfxItemPool::IsWhich(nWhich
))
286 const SfxPoolItem
& rNew
= m_pParent
287 ? m_pParent
->Get( nWhich
)
288 : m_pPool
->GetDefaultItem( nWhich
);
290 Changed( *pItemToClear
, rNew
);
292 if ( pItemToClear
->Which() )
293 m_pPool
->Remove( *pItemToClear
);
301 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
309 sal_uInt16
* pPtr
= m_pWhichRanges
;
312 for( nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
315 // Due to the assertions in the sub calls, we need to do this
317 const SfxPoolItem
*pItemToClear
= *ppFnd
;
320 if ( !IsInvalidItem(pItemToClear
) )
322 if (SfxItemPool::IsWhich(nWhich
))
324 const SfxPoolItem
& rNew
= m_pParent
325 ? m_pParent
->Get( nWhich
)
326 : m_pPool
->GetDefaultItem( nWhich
);
328 Changed( *pItemToClear
, rNew
);
332 // Take care of disabled items, too.
333 if (!pItemToClear
->m_nWhich
)
335 // item is disabled, delete it
340 // remove item from pool
341 m_pPool
->Remove( *pItemToClear
);
351 void SfxItemSet::ClearInvalidItems()
353 sal_uInt16
* pPtr
= m_pWhichRanges
;
354 SfxPoolItem
const** ppFnd
= m_pItems
.get();
357 for( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
358 if( IsInvalidItem(*ppFnd
) )
367 void SfxItemSet::InvalidateAllItems()
369 assert( !m_nCount
&& "There are still Items set" );
370 m_nCount
= TotalCount();
371 memset(static_cast<void*>(m_pItems
.get()), -1, m_nCount
* sizeof(SfxPoolItem
*));
374 SfxItemState
SfxItemSet::GetItemState( sal_uInt16 nWhich
,
376 const SfxPoolItem
**ppItem
) const
378 // Find the range in which the Which is located
379 const SfxItemSet
* pCurrentSet
= this;
380 SfxItemState eRet
= SfxItemState::UNKNOWN
;
383 SfxPoolItem
const** ppFnd
= pCurrentSet
->m_pItems
.get();
384 const sal_uInt16
* pPtr
= pCurrentSet
->m_pWhichRanges
;
389 if ( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
392 ppFnd
+= nWhich
- *pPtr
;
395 eRet
= SfxItemState::DEFAULT
;
397 return eRet
; // Not present
398 break; // Keep searching in the parents!
401 if ( IsInvalidItem(*ppFnd
) )
402 // Different ones are present
403 return SfxItemState::DONTCARE
;
405 if ( (*ppFnd
)->IsVoidItem() )
406 return SfxItemState::DISABLED
;
412 return SfxItemState::SET
;
414 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
418 } while (bSrchInParent
&& nullptr != (pCurrentSet
= pCurrentSet
->m_pParent
));
422 bool SfxItemSet::HasItem(sal_uInt16 nWhich
, const SfxPoolItem
** ppItem
) const
424 bool bRet
= SfxItemState::SET
== GetItemState(nWhich
, true, ppItem
);
430 const SfxPoolItem
* SfxItemSet::Put( const SfxPoolItem
& rItem
, sal_uInt16 nWhich
)
433 return nullptr; //FIXME: Only because of Outliner bug
435 SfxPoolItem
const** ppFnd
= m_pItems
.get();
436 const sal_uInt16
* pPtr
= m_pWhichRanges
;
439 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
442 ppFnd
+= nWhich
- *pPtr
;
443 if( *ppFnd
) // Already one present
445 // Same Item already present?
446 if ( *ppFnd
== &rItem
)
449 // Will 'dontcare' or 'disabled' be overwritten with some real value?
450 if ( rItem
.Which() && ( IsInvalidItem(*ppFnd
) || !(*ppFnd
)->Which() ) )
452 auto const old
= *ppFnd
;
453 *ppFnd
= &m_pPool
->Put( rItem
, nWhich
);
454 if (!IsInvalidItem(old
)) {
455 assert(old
->Which() == 0);
461 // Turns into disabled?
464 if (IsInvalidItem(*ppFnd
) || (*ppFnd
)->Which() != 0) {
465 *ppFnd
= rItem
.Clone(m_pPool
);
471 // Same value already present?
472 if ( rItem
== **ppFnd
)
475 // Add the new one, remove the old one
476 const SfxPoolItem
& rNew
= m_pPool
->Put( rItem
, nWhich
);
477 const SfxPoolItem
* pOld
= *ppFnd
;
479 if (SfxItemPool::IsWhich(nWhich
))
480 Changed( *pOld
, rNew
);
481 m_pPool
->Remove( *pOld
);
488 *ppFnd
= rItem
.Clone(m_pPool
);
490 const SfxPoolItem
& rNew
= m_pPool
->Put( rItem
, nWhich
);
492 if (SfxItemPool::IsWhich(nWhich
))
494 const SfxPoolItem
& rOld
= m_pParent
495 ? m_pParent
->Get( nWhich
)
496 : m_pPool
->GetDefaultItem( nWhich
);
497 Changed( rOld
, rNew
);
501 SAL_WARN_IF(m_pPool
->IsItemPoolable(nWhich
) &&
502 dynamic_cast<const SfxSetItem
*>( &rItem
) == nullptr &&
504 "svl.items", "putted Item unequal, with ID/pos " << nWhich
);
507 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
513 bool SfxItemSet::Put( const SfxItemSet
& rSet
, bool bInvalidAsDefault
)
518 SfxPoolItem
const** ppFnd
= rSet
.m_pItems
.get();
519 const sal_uInt16
* pPtr
= rSet
.m_pWhichRanges
;
522 for ( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
525 if ( IsInvalidItem( *ppFnd
) )
527 if ( bInvalidAsDefault
)
528 bRet
|= 0 != ClearItem( nWhich
);
529 // FIXME: Caused a SEGFAULT on non Windows-platforms:
530 // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
532 InvalidateItem( nWhich
);
535 bRet
|= nullptr != Put( **ppFnd
, nWhich
);
544 * This method takes the Items from the 'rSet' and adds to '*this'.
545 * Which ranges in '*this' that are non-existent in 'rSet' will not
546 * be altered. The Which range of '*this' is also not changed.
548 * Items set in 'rSet' are also set in '*this'.
549 * Default (0 pointer) and Invalid (-1 pointer) Items are processed
550 * according to their parameter 'eDontCareAs' and 'eDefaultAs':
552 * SfxItemState::SET: Hard set to the default of the Pool
553 * SfxItemState::DEFAULT: Deleted (0 pointer)
554 * SfxItemState::DONTCARE: Invalid (-1 pointer)
556 * NB: All other values for 'eDontCareAs' and 'eDefaultAs' are invalid
558 void SfxItemSet::PutExtended
560 const SfxItemSet
& rSet
, // Source of the Items to be put
561 SfxItemState eDontCareAs
, // What will happen to the DontCare Items
562 SfxItemState eDefaultAs
// What will happen to the Default Items
565 // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
566 SfxPoolItem
const** ppFnd
= rSet
.m_pItems
.get();
567 const sal_uInt16
* pPtr
= rSet
.m_pWhichRanges
;
570 for ( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
573 if ( IsInvalidItem( *ppFnd
) )
576 switch ( eDontCareAs
)
578 case SfxItemState::SET
:
579 Put( rSet
.GetPool()->GetDefaultItem(nWhich
), nWhich
);
582 case SfxItemState::DEFAULT
:
586 case SfxItemState::DONTCARE
:
587 InvalidateItem( nWhich
);
591 assert(!"invalid Argument for eDontCareAs");
596 Put( **ppFnd
, nWhich
);
601 switch ( eDefaultAs
)
603 case SfxItemState::SET
:
604 Put( rSet
.GetPool()->GetDefaultItem(nWhich
), nWhich
);
607 case SfxItemState::DEFAULT
:
611 case SfxItemState::DONTCARE
:
612 InvalidateItem( nWhich
);
616 assert(!"invalid Argument for eDefaultAs");
624 * Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
625 * items which are new ranges too.
627 void SfxItemSet::MergeRange( sal_uInt16 nFrom
, sal_uInt16 nTo
)
629 // special case: exactly one sal_uInt16 which is already included?
630 SfxItemState eItemState
= GetItemState(nFrom
, false);
631 if ( nFrom
== nTo
&& ( eItemState
== SfxItemState::DEFAULT
|| eItemState
== SfxItemState::SET
) )
635 assert(nFrom
<= nTo
);
636 for (const sal_uInt16
*pRange
= m_pWhichRanges
; *pRange
; pRange
+= 2)
638 assert(pRange
[0] <= pRange
[1]);
639 // ranges must be sorted and discrete
641 !pRange
[2] || (pRange
[2] > pRange
[1] && pRange
[2] - pRange
[1] > 1));
645 // create vector of ranges (sal_uInt16 pairs of lower and upper bound)
646 const size_t nOldCount
= Count_Impl(m_pWhichRanges
);
647 std::vector
<std::pair
<sal_uInt16
, sal_uInt16
>> aRangesTable
;
648 aRangesTable
.reserve(nOldCount
/2 + 1);
650 for (size_t i
= 0; i
< nOldCount
; i
+= 2)
652 if (!bAdded
&& m_pWhichRanges
[i
] >= nFrom
)
653 { // insert new range, keep ranges sorted
654 aRangesTable
.emplace_back(std::pair
<sal_uInt16
, sal_uInt16
>(nFrom
, nTo
));
657 // insert current range
658 aRangesTable
.emplace_back(std::pair
<sal_uInt16
, sal_uInt16
>(m_pWhichRanges
[i
], m_pWhichRanges
[i
+1]));
661 aRangesTable
.emplace_back(std::pair
<sal_uInt16
, sal_uInt16
>(nFrom
, nTo
));
663 // true if ranges overlap or adjoin, false if ranges are separate
664 auto needMerge
= [](std::pair
<sal_uInt16
, sal_uInt16
> lhs
, std::pair
<sal_uInt16
, sal_uInt16
> rhs
)
665 {return (lhs
.first
-1) <= rhs
.second
&& (rhs
.first
-1) <= lhs
.second
;};
667 std::vector
<std::pair
<sal_uInt16
, sal_uInt16
> >::iterator it
= aRangesTable
.begin();
668 std::vector
<std::pair
<sal_uInt16
, sal_uInt16
> >::iterator itNext
;
669 // we got at least one range
670 while ((itNext
= std::next(it
)) != aRangesTable
.end())
672 // check neighbouring ranges, find first range which overlaps or adjoins a previous range
673 if (needMerge(*it
, *itNext
))
675 // lower bounds are sorted, implies: it->first = min(it[0].first, it[1].first)
676 it
->second
= std::max(it
->second
, itNext
->second
);
677 aRangesTable
.erase(itNext
);
683 // construct range array
684 const size_t nNewSize
= 2 * aRangesTable
.size() + 1;
685 std::vector
<sal_uInt16
> aRanges(nNewSize
);
686 for (size_t i
= 0; i
< (nNewSize
- 1); i
+=2)
687 std::tie(aRanges
[i
], aRanges
[i
+1]) = aRangesTable
[i
/2];
689 // null terminate to be compatible with sal_uInt16* array pointers
692 SetRanges( aRanges
.data() );
696 * Modifies the ranges of settable items. Keeps state of items which
697 * are new ranges too.
699 void SfxItemSet::SetRanges( const sal_uInt16
*pNewRanges
)
702 if (m_pWhichRanges
== pNewRanges
)
704 const sal_uInt16
* pOld
= m_pWhichRanges
;
705 const sal_uInt16
* pNew
= pNewRanges
;
706 while ( *pOld
== *pNew
)
708 if ( !*pOld
&& !*pNew
)
714 // create new item-array (by iterating through all new ranges)
715 sal_uInt16 nSize
= Capacity_Impl(pNewRanges
);
716 SfxPoolItem
const** aNewItems
= new const SfxPoolItem
* [ nSize
];
717 sal_uInt16 nNewCount
= 0;
719 memset( aNewItems
, 0, nSize
* sizeof( SfxPoolItem
* ) );
723 for ( const sal_uInt16
*pRange
= pNewRanges
; *pRange
; pRange
+= 2 )
725 // iterate through all ids in the range
726 for ( sal_uInt16 nWID
= *pRange
; nWID
<= pRange
[1]; ++nWID
, ++n
)
728 // direct move of pointer (not via pool)
729 SfxItemState eState
= GetItemState( nWID
, false, aNewItems
+n
);
730 if ( SfxItemState::SET
== eState
)
732 // increment new item count and possibly increment ref count
734 aNewItems
[n
]->AddRef();
736 else if ( SfxItemState::DISABLED
== eState
)
738 // put "disabled" item
740 aNewItems
[n
] = new SfxVoidItem(0);
742 else if ( SfxItemState::DONTCARE
== eState
)
745 aNewItems
[n
] = INVALID_POOL_ITEM
;
750 aNewItems
[n
] = nullptr;
755 sal_uInt16 nOldTotalCount
= TotalCount();
756 for ( sal_uInt16 nItem
= 0; nItem
< nOldTotalCount
; ++nItem
)
758 const SfxPoolItem
*pItem
= m_pItems
[nItem
];
759 if ( pItem
&& !IsInvalidItem(pItem
) && pItem
->Which() )
760 m_pPool
->Remove(*pItem
);
764 // replace old items-array and ranges
765 m_pItems
.reset( aNewItems
);
766 m_nCount
= nNewCount
;
768 if( pNewRanges
== GetPool()->GetFrozenIdRanges() )
770 delete[] m_pWhichRanges
;
771 m_pWhichRanges
= const_cast<sal_uInt16
*>(pNewRanges
);
775 sal_uInt16 nCount
= Count_Impl(pNewRanges
) + 1;
776 if (m_pWhichRanges
!= m_pPool
->GetFrozenIdRanges())
777 delete[] m_pWhichRanges
;
778 m_pWhichRanges
= new sal_uInt16
[ nCount
];
779 memcpy( m_pWhichRanges
, pNewRanges
, sizeof( sal_uInt16
) * nCount
);
784 * The SfxItemSet takes over exactly those SfxPoolItems that are
785 * set in rSet and are in their own Which range. All others are removed.
786 * The SfxItemPool is retained, such that SfxPoolItems that have been
787 * taken over, are moved from the rSet's SfxItemPool to the SfxItemPool
790 * SfxPoolItems in rSet, for which holds 'IsInvalidItem() == true' are
791 * taken over as invalid items.
794 * SfxPoolItems have been taken over
797 * No SfxPoolItems have been taken over, because
798 * e.g. the Which ranges of SfxItemSets are not intersecting
799 * or the intersection does not contain SfxPoolItems that are
804 const SfxItemSet
& rSet
, /* The SfxItemSet, whose SfxPoolItems are
805 to been taken over */
807 bool bDeep
/* true (default)
809 The SfxPoolItems from the parents that may
810 be present in rSet, are also taken over into
814 The SfxPoolItems from the parents of
815 rSet are not taken into account */
823 SfxWhichIter
aIter(*this);
824 sal_uInt16 nWhich
= aIter
.FirstWhich();
827 const SfxPoolItem
* pItem
;
828 if( SfxItemState::SET
== rSet
.GetItemState( nWhich
, true, &pItem
) )
829 bRet
|= nullptr != Put( *pItem
, pItem
->Which() );
830 nWhich
= aIter
.NextWhich();
834 bRet
= Put(rSet
, false);
839 const SfxPoolItem
* SfxItemSet::GetItem(sal_uInt16 nId
, bool bSearchInParent
) const
841 // Convert to WhichId
842 sal_uInt16 nWhich
= GetPool()->GetWhich(nId
);
844 // Is the Item set or 'bDeep == true' available?
845 const SfxPoolItem
*pItem
= nullptr;
846 SfxItemState eState
= GetItemState(nWhich
, bSearchInParent
, &pItem
);
847 if (bSearchInParent
&& SfxItemState::DEFAULT
== eState
&& SfxItemPool::IsWhich(nWhich
))
849 pItem
= &m_pPool
->GetDefaultItem(nWhich
);
855 const SfxPoolItem
& SfxItemSet::Get( sal_uInt16 nWhich
, bool bSrchInParent
) const
857 // Search the Range in which the Which is located in:
858 const SfxItemSet
* pCurrentSet
= this;
861 if( pCurrentSet
->Count() )
863 SfxPoolItem
const** ppFnd
= pCurrentSet
->m_pItems
.get();
864 const sal_uInt16
* pPtr
= pCurrentSet
->m_pWhichRanges
;
867 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
870 ppFnd
+= nWhich
- *pPtr
;
873 if( IsInvalidItem(*ppFnd
) ) {
874 //FIXME: The following code is duplicated further down
875 SAL_WARN_IF(!m_pPool
, "svl.items", "no Pool, but status is ambiguous, with ID/pos " << nWhich
);
876 //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
878 return m_pPool
->GetDefaultItem( nWhich
);
881 const SfxPoolItem
*pItem
= *ppFnd
;
882 if ( pItem
->IsVoidItem() || !pItem
->Which() )
883 SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item");
887 break; // Continue with Parent
889 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
893 //TODO: Search until end of Range: What are we supposed to do now? To the Parent or Default??
894 // if( !*pPtr ) // Until the end of the search Range?
896 } while (bSrchInParent
&& nullptr != (pCurrentSet
= pCurrentSet
->m_pParent
));
898 // Get the Default from the Pool and return
899 SAL_WARN_IF(!m_pPool
, "svl.items", "no Pool, but status is ambiguous, with ID/pos " << nWhich
);
900 const SfxPoolItem
*pItem
= &m_pPool
->GetDefaultItem( nWhich
);
905 * Notification callback
907 void SfxItemSet::Changed( const SfxPoolItem
&, const SfxPoolItem
& )
911 sal_uInt16
SfxItemSet::TotalCount() const
914 sal_uInt16
* pPtr
= m_pWhichRanges
;
917 nRet
+= ( *(pPtr
+1) - *pPtr
) + 1;
924 * Only retain the Items that are also present in rSet
925 * (nevermind their value).
927 void SfxItemSet::Intersect( const SfxItemSet
& rSet
)
929 assert(m_pPool
&& "Not implemented without Pool");
930 if( !Count() ) // None set?
933 // Delete all Items not contained in rSet
936 ClearItem(); // Delete everything
940 // Test whether the Which Ranges are different
941 sal_uInt16
* pWh1
= m_pWhichRanges
;
942 sal_uInt16
* pWh2
= rSet
.m_pWhichRanges
;
943 sal_uInt16 nSize
= 0;
945 for( sal_uInt16 n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
952 nSize
+= ( *pWh1
- *(pWh1
-1) ) + 1;
954 bool bEqual
= *pWh1
== *pWh2
; // Also check for 0
956 // If the Ranges are identical, we can easily process it
959 SfxPoolItem
const** ppFnd1
= m_pItems
.get();
960 SfxPoolItem
const** ppFnd2
= rSet
.m_pItems
.get();
962 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
963 if( *ppFnd1
&& !*ppFnd2
)
966 if( !IsInvalidItem( *ppFnd1
) )
968 sal_uInt16 nWhich
= (*ppFnd1
)->Which();
969 if (SfxItemPool::IsWhich(nWhich
))
971 const SfxPoolItem
& rNew
= m_pParent
972 ? m_pParent
->Get( nWhich
)
973 : m_pPool
->GetDefaultItem( nWhich
);
975 Changed( **ppFnd1
, rNew
);
977 m_pPool
->Remove( **ppFnd1
);
985 SfxItemIter
aIter( *this );
986 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
989 sal_uInt16 nWhich
= IsInvalidItem( pItem
)
990 ? GetWhichByPos( aIter
.GetCurPos() )
992 if( SfxItemState::UNKNOWN
== rSet
.GetItemState( nWhich
, false ) )
993 ClearItem( nWhich
); // Delete
994 if( aIter
.IsAtEnd() )
996 pItem
= aIter
.NextItem();
1001 void SfxItemSet::Differentiate( const SfxItemSet
& rSet
)
1003 if( !Count() || !rSet
.Count() )// None set?
1006 // Test whether the Which Ranges are different
1007 sal_uInt16
* pWh1
= m_pWhichRanges
;
1008 sal_uInt16
* pWh2
= rSet
.m_pWhichRanges
;
1009 sal_uInt16 nSize
= 0;
1011 for( sal_uInt16 n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1013 if( *pWh1
!= *pWh2
)
1018 nSize
+= ( *pWh1
- *(pWh1
-1) ) + 1;
1020 bool bEqual
= *pWh1
== *pWh2
; // Also test for 0
1022 // If the Ranges are identical, we can easily process it
1025 SfxPoolItem
const** ppFnd1
= m_pItems
.get();
1026 SfxPoolItem
const** ppFnd2
= rSet
.m_pItems
.get();
1028 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1029 if( *ppFnd1
&& *ppFnd2
)
1032 if( !IsInvalidItem( *ppFnd1
) )
1034 sal_uInt16 nWhich
= (*ppFnd1
)->Which();
1035 if (SfxItemPool::IsWhich(nWhich
))
1037 const SfxPoolItem
& rNew
= m_pParent
1038 ? m_pParent
->Get( nWhich
)
1039 : m_pPool
->GetDefaultItem( nWhich
);
1041 Changed( **ppFnd1
, rNew
);
1043 m_pPool
->Remove( **ppFnd1
);
1051 SfxItemIter
aIter( *this );
1052 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1055 sal_uInt16 nWhich
= IsInvalidItem( pItem
)
1056 ? GetWhichByPos( aIter
.GetCurPos() )
1058 if( SfxItemState::SET
== rSet
.GetItemState( nWhich
, false ) )
1059 ClearItem( nWhich
); // Delete
1060 if( aIter
.IsAtEnd() )
1062 pItem
= aIter
.NextItem();
1069 * Decision table for MergeValue(s)
1072 * 1. If the Which value in the 1st set is "unknown", there's never any action
1073 * 2. If the Which value in the 2nd set is "unknown", it's made the "default"
1074 * 3. For comparisons the values of the "default" Items are take into account
1076 * 1st Item 2nd Item Values bIgnoreDefs Remove Assign Add
1078 * set set == sal_False - - -
1079 * default set == sal_False - - -
1080 * dontcare set == sal_False - - -
1081 * unknown set == sal_False - - -
1082 * set default == sal_False - - -
1083 * default default == sal_False - - -
1084 * dontcare default == sal_False - - -
1085 * unknown default == sal_False - - -
1086 * set dontcare == sal_False 1st Item -1 -
1087 * default dontcare == sal_False - -1 -
1088 * dontcare dontcare == sal_False - - -
1089 * unknown dontcare == sal_False - - -
1090 * set unknown == sal_False 1st Item -1 -
1091 * default unknown == sal_False - - -
1092 * dontcare unknown == sal_False - - -
1093 * unknown unknown == sal_False - - -
1095 * set set != sal_False 1st Item -1 -
1096 * default set != sal_False - -1 -
1097 * dontcare set != sal_False - - -
1098 * unknown set != sal_False - - -
1099 * set default != sal_False 1st Item -1 -
1100 * default default != sal_False - - -
1101 * dontcare default != sal_False - - -
1102 * unknown default != sal_False - - -
1103 * set dontcare != sal_False 1st Item -1 -
1104 * default dontcare != sal_False - -1 -
1105 * dontcare dontcare != sal_False - - -
1106 * unknown dontcare != sal_False - - -
1107 * set unknown != sal_False 1st Item -1 -
1108 * default unknown != sal_False - - -
1109 * dontcare unknown != sal_False - - -
1110 * unknown unknown != sal_False - - -
1112 * set set == sal_True - - -
1113 * default set == sal_True - 2nd Item 2nd Item
1114 * dontcare set == sal_True - - -
1115 * unknown set == sal_True - - -
1116 * set default == sal_True - - -
1117 * default default == sal_True - - -
1118 * dontcare default == sal_True - - -
1119 * unknown default == sal_True - - -
1120 * set dontcare == sal_True - - -
1121 * default dontcare == sal_True - -1 -
1122 * dontcare dontcare == sal_True - - -
1123 * unknown dontcare == sal_True - - -
1124 * set unknown == sal_True - - -
1125 * default unknown == sal_True - - -
1126 * dontcare unknown == sal_True - - -
1127 * unknown unknown == sal_True - - -
1129 * set set != sal_True 1st Item -1 -
1130 * default set != sal_True - 2nd Item 2nd Item
1131 * dontcare set != sal_True - - -
1132 * unknown set != sal_True - - -
1133 * set default != sal_True - - -
1134 * default default != sal_True - - -
1135 * dontcare default != sal_True - - -
1136 * unknown default != sal_True - - -
1137 * set dontcare != sal_True 1st Item -1 -
1138 * default dontcare != sal_True - -1 -
1139 * dontcare dontcare != sal_True - - -
1140 * unknown dontcare != sal_True - - -
1141 * set unknown != sal_True - - -
1142 * default unknown != sal_True - - -
1143 * dontcare unknown != sal_True - - -
1144 * unknown unknown != sal_True - - -
1146 static void MergeItem_Impl( SfxItemPool
*_pPool
, sal_uInt16
&rCount
,
1147 const SfxPoolItem
**ppFnd1
, const SfxPoolItem
*pFnd2
,
1148 bool bIgnoreDefaults
)
1150 assert(ppFnd1
!= nullptr && "Merging to 0-Item");
1152 // 1st Item is Default?
1155 if ( IsInvalidItem(pFnd2
) )
1156 // Decision table: default, dontcare, doesn't matter, doesn't matter
1157 *ppFnd1
= INVALID_POOL_ITEM
;
1159 else if ( pFnd2
&& !bIgnoreDefaults
&&
1160 _pPool
->GetDefaultItem(pFnd2
->Which()) != *pFnd2
)
1161 // Decision table: default, set, !=, sal_False
1162 *ppFnd1
= INVALID_POOL_ITEM
;
1164 else if ( pFnd2
&& bIgnoreDefaults
)
1165 // Decision table: default, set, doesn't matter, sal_True
1166 *ppFnd1
= &_pPool
->Put( *pFnd2
);
1173 else if ( !IsInvalidItem(*ppFnd1
) )
1177 // 2nd Item is Default
1178 if ( !bIgnoreDefaults
&&
1179 **ppFnd1
!= _pPool
->GetDefaultItem((*ppFnd1
)->Which()) )
1181 // Decision table: set, default, !=, sal_False
1182 _pPool
->Remove( **ppFnd1
);
1183 *ppFnd1
= INVALID_POOL_ITEM
;
1186 else if ( IsInvalidItem(pFnd2
) )
1188 // 2nd Item is dontcare
1189 if ( !bIgnoreDefaults
||
1190 **ppFnd1
!= _pPool
->GetDefaultItem( (*ppFnd1
)->Which()) )
1192 // Decision table: set, dontcare, doesn't matter, sal_False
1193 // or: set, dontcare, !=, sal_True
1194 _pPool
->Remove( **ppFnd1
);
1195 *ppFnd1
= INVALID_POOL_ITEM
;
1201 if ( **ppFnd1
!= *pFnd2
)
1203 // Decision table: set, set, !=, doesn't matter
1204 _pPool
->Remove( **ppFnd1
);
1205 *ppFnd1
= INVALID_POOL_ITEM
;
1211 void SfxItemSet::MergeValues( const SfxItemSet
& rSet
)
1213 // WARNING! When making changes/fixing bugs, always update the table above!!
1214 assert( GetPool() == rSet
.GetPool() && "MergeValues with different Pools" );
1216 // Test if the which Ranges are different
1217 sal_uInt16
* pWh1
= m_pWhichRanges
;
1218 sal_uInt16
* pWh2
= rSet
.m_pWhichRanges
;
1219 sal_uInt16 nSize
= 0;
1221 for( sal_uInt16 n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1223 if( *pWh1
!= *pWh2
)
1228 nSize
+= ( *pWh1
- *(pWh1
-1) ) + 1;
1230 bool bEqual
= *pWh1
== *pWh2
; // Also check for 0
1232 // If the Ranges match, they are easier to process!
1235 SfxPoolItem
const** ppFnd1
= m_pItems
.get();
1236 SfxPoolItem
const** ppFnd2
= rSet
.m_pItems
.get();
1238 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1239 MergeItem_Impl(m_pPool
, m_nCount
, ppFnd1
, *ppFnd2
, false/*bIgnoreDefaults*/);
1243 SfxWhichIter
aIter( rSet
);
1245 while( 0 != ( nWhich
= aIter
.NextWhich() ) )
1247 const SfxPoolItem
* pItem
= nullptr;
1248 (void)rSet
.GetItemState( nWhich
, true, &pItem
);
1251 // Not set, so default
1252 MergeValue( rSet
.GetPool()->GetDefaultItem( nWhich
) );
1254 else if( IsInvalidItem( pItem
) )
1256 InvalidateItem( nWhich
);
1258 MergeValue( *pItem
);
1263 void SfxItemSet::MergeValue( const SfxPoolItem
& rAttr
, bool bIgnoreDefaults
)
1265 SfxPoolItem
const** ppFnd
= m_pItems
.get();
1266 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1267 const sal_uInt16 nWhich
= rAttr
.Which();
1271 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1273 ppFnd
+= nWhich
- *pPtr
;
1274 MergeItem_Impl(m_pPool
, m_nCount
, ppFnd
, &rAttr
, bIgnoreDefaults
);
1277 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1282 void SfxItemSet::InvalidateItem( sal_uInt16 nWhich
)
1284 SfxPoolItem
const** ppFnd
= m_pItems
.get();
1285 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1288 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1291 ppFnd
+= nWhich
- *pPtr
;
1293 if( *ppFnd
) // Set for me
1295 if( !IsInvalidItem(*ppFnd
) )
1297 m_pPool
->Remove( **ppFnd
);
1298 *ppFnd
= INVALID_POOL_ITEM
;
1303 *ppFnd
= INVALID_POOL_ITEM
;
1308 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1313 sal_uInt16
SfxItemSet::GetWhichByPos( sal_uInt16 nPos
) const
1316 sal_uInt16
* pPtr
= m_pWhichRanges
;
1319 n
= ( *(pPtr
+1) - *pPtr
) + 1;
1321 return *pPtr
+ nPos
;
1329 bool SfxItemSet::operator==(const SfxItemSet
&rCmp
) const
1331 return Equals( rCmp
, true);
1334 bool SfxItemSet::Equals(const SfxItemSet
&rCmp
, bool bComparePool
) const
1336 // Values we can get quickly need to be the same
1337 const bool bDifferentPools
= (m_pPool
!= rCmp
.m_pPool
);
1338 if ( (bComparePool
&& m_pParent
!= rCmp
.m_pParent
) ||
1339 (bComparePool
&& bDifferentPools
) ||
1340 Count() != rCmp
.Count() )
1343 // If we reach here and bDifferentPools==true that means bComparePool==false.
1345 // Counting Ranges takes longer; they also need to be the same, however
1346 sal_uInt16 nCount1
= TotalCount();
1347 sal_uInt16 nCount2
= rCmp
.TotalCount();
1348 if ( nCount1
!= nCount2
)
1351 // Are the Ranges themselves unequal?
1352 for (sal_uInt16 nRange
= 0; m_pWhichRanges
[nRange
]; nRange
+= 2)
1354 if (m_pWhichRanges
[nRange
] != rCmp
.m_pWhichRanges
[nRange
] ||
1355 m_pWhichRanges
[nRange
+1] != rCmp
.m_pWhichRanges
[nRange
+1])
1357 // We must use the slow method then
1358 SfxWhichIter
aIter( *this );
1359 for ( sal_uInt16 nWh
= aIter
.FirstWhich();
1361 nWh
= aIter
.NextWhich() )
1363 // If the pointer of the poolable Items are unequal, the Items must match
1364 const SfxPoolItem
*pItem1
= nullptr, *pItem2
= nullptr;
1365 if ( GetItemState( nWh
, false, &pItem1
) !=
1366 rCmp
.GetItemState( nWh
, false, &pItem2
) ||
1367 ( pItem1
!= pItem2
&&
1368 ( !pItem1
|| IsInvalidItem(pItem1
) ||
1369 (m_pPool
->IsItemPoolable(*pItem1
) &&
1370 *pItem1
!= *pItem2
) ) ) )
1378 // Are all pointers the same?
1379 if (0 == memcmp( m_pItems
.get(), rCmp
.m_pItems
.get(), nCount1
* sizeof(m_pItems
[0]) ))
1382 // We need to compare each one separately then
1383 const SfxPoolItem
**ppItem1
= m_pItems
.get();
1384 const SfxPoolItem
**ppItem2
= rCmp
.m_pItems
.get();
1385 for ( sal_uInt16 nPos
= 0; nPos
< nCount1
; ++nPos
)
1387 // If the pointers of the poolable Items are not the same, the Items
1389 if ( *ppItem1
!= *ppItem2
&&
1390 ( ( !*ppItem1
|| !*ppItem2
) ||
1391 ( IsInvalidItem(*ppItem1
) || IsInvalidItem(*ppItem2
) ) ||
1392 (!bDifferentPools
&& m_pPool
->IsItemPoolable(**ppItem1
)) ||
1393 **ppItem1
!= **ppItem2
) )
1403 std::unique_ptr
<SfxItemSet
> SfxItemSet::Clone(bool bItems
, SfxItemPool
*pToPool
) const
1405 if (pToPool
&& pToPool
!= m_pPool
)
1407 std::unique_ptr
<SfxItemSet
> pNewSet(new SfxItemSet(*pToPool
, m_pWhichRanges
));
1410 SfxWhichIter
aIter(*pNewSet
);
1411 sal_uInt16 nWhich
= aIter
.FirstWhich();
1414 const SfxPoolItem
* pItem
;
1415 if ( SfxItemState::SET
== GetItemState( nWhich
, false, &pItem
) )
1416 pNewSet
->Put( *pItem
, pItem
->Which() );
1417 nWhich
= aIter
.NextWhich();
1423 return std::unique_ptr
<SfxItemSet
>(bItems
1424 ? new SfxItemSet(*this)
1425 : new SfxItemSet(*m_pPool
, m_pWhichRanges
));
1428 void SfxItemSet::PutDirect(const SfxPoolItem
&rItem
)
1430 SfxPoolItem
const** ppFnd
= m_pItems
.get();
1431 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1432 const sal_uInt16 nWhich
= rItem
.Which();
1434 IsPoolDefaultItem(&rItem
) || m_pPool
->CheckItemInPool(&rItem
);
1435 // Only cause assertion in the callees
1439 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1442 ppFnd
+= nWhich
- *pPtr
;
1443 const SfxPoolItem
* pOld
= *ppFnd
;
1444 if( pOld
) // One already present
1446 if( rItem
== **ppFnd
)
1447 return; // Already present!
1448 m_pPool
->Remove( *pOld
);
1454 if( IsPoolDefaultItem(&rItem
) )
1455 *ppFnd
= &m_pPool
->Put( rItem
);
1459 if( !IsStaticDefaultItem( &rItem
) )
1465 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1470 void SfxItemSet::dumpAsXml(xmlTextWriterPtr pWriter
) const
1472 xmlTextWriterStartElement(pWriter
, BAD_CAST("SfxItemSet"));
1473 SfxItemIter
aIter(*this);
1474 for (const SfxPoolItem
* pItem
= aIter
.FirstItem(); pItem
; pItem
= aIter
.NextItem())
1475 pItem
->dumpAsXml(pWriter
);
1476 xmlTextWriterEndElement(pWriter
);
1480 // ----------------------------------------------- class SfxAllItemSet
1482 SfxAllItemSet::SfxAllItemSet( SfxItemPool
&rPool
)
1483 : SfxItemSet(rPool
, nullptr),
1486 // Initially no Items
1489 // Allocate nInitCount pairs at USHORTs for Ranges
1490 m_pWhichRanges
= new sal_uInt16
[nInitCount
+ 1]{};
1493 SfxAllItemSet::SfxAllItemSet(const SfxItemSet
&rCopy
)
1494 : SfxItemSet(rCopy
),
1500 * Explicitly define this ctor to avoid auto-generation by the compiler.
1501 * The compiler does not take the ctor with the 'const SfxItemSet&'!
1503 SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet
&rCopy
)
1504 : SfxItemSet(rCopy
),
1510 * This internal function creates a new WhichRanges array, which is copied
1511 * from the 'nOldSize'-USHORTs long 'pUS'. It has new USHORTs at the end instead
1513 * The terminating sal_uInt16 with the '0' is neither accounted for in 'nOldSize'
1514 * nor in 'nIncr', but always explicitly added.
1516 * @returns the new WhichRanges array (the old 'pUS' is freed)
1518 static sal_uInt16
*AddRanges_Impl(
1519 sal_uInt16
*pUS
, std::ptrdiff_t nOldSize
, sal_uInt16 nIncr
)
1521 // Create new WhichRanges array
1522 sal_uInt16
*pNew
= new sal_uInt16
[ nOldSize
+ nIncr
+ 1 ];
1524 // Take over the old Ranges
1525 memcpy( pNew
, pUS
, nOldSize
* sizeof(sal_uInt16
) );
1527 // Initialize the new one to 0
1528 memset( pNew
+ nOldSize
, 0, ( nIncr
+ 1 ) * sizeof(sal_uInt16
) );
1530 // Free the old array
1537 * This internal function creates a new ItemArray, which is copied from 'pItems',
1538 * but has room for a new ItemPointer at 'nPos'.
1540 * @returns the new ItemArray (the old 'pItems' is freed)
1542 static void AddItem_Impl(std::unique_ptr
<SfxPoolItem
const*[]> & rpItems
, sal_uInt16 nOldSize
, sal_uInt16 nPos
)
1544 // Create new ItemArray
1545 SfxPoolItem
const** pNew
= new const SfxPoolItem
*[nOldSize
+1];
1547 // Was there one before?
1550 // Copy all Items before nPos
1552 memcpy( static_cast<void*>(pNew
), rpItems
.get(), nPos
* sizeof(SfxPoolItem
*) );
1554 // Copy all Items after nPos
1555 if ( nPos
< nOldSize
)
1556 memcpy( static_cast<void*>(pNew
+ nPos
+ 1), rpItems
.get() + nPos
,
1557 (nOldSize
-nPos
) * sizeof(SfxPoolItem
*) );
1560 // Initialize new Item
1561 *(pNew
+ nPos
) = nullptr;
1563 rpItems
.reset(pNew
);
1567 * Putting with automatic extension of the WhichId with the ID of the Item.
1569 const SfxPoolItem
* SfxAllItemSet::Put( const SfxPoolItem
& rItem
, sal_uInt16 nWhich
)
1571 sal_uInt16 nPos
= 0; // Position for 'rItem' in 'm_pItems'
1572 const sal_uInt16 nItemCount
= TotalCount();
1574 // Let's see first whether there's a suitable Range already
1575 sal_uInt16
*pPtr
= m_pWhichRanges
;
1578 // WhichId is within this Range?
1579 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1582 nPos
+= nWhich
- *pPtr
;
1586 // Carry over the position of the Item in m_pItems
1587 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
1589 // To the next Range
1593 // WhichId not yet present?
1596 // Let's see if we can attach it somewhere
1597 pPtr
= m_pWhichRanges
;
1601 // WhichId is right before this Range?
1602 if ( (nWhich
+1) == *pPtr
)
1604 // Range grows downwards
1607 // Make room before first Item of this Range
1608 AddItem_Impl(m_pItems
, nItemCount
, nPos
);
1612 // WhichId is right after this Range?
1613 else if ( (nWhich
-1) == *(pPtr
+1) )
1615 // Range grows upwards?
1618 // Make room after last Item of this Range
1619 nPos
+= nWhich
- *pPtr
;
1620 AddItem_Impl(m_pItems
, nItemCount
, nPos
);
1624 // Carry over position of the Item in m_pItems
1625 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
1627 // To the next Range
1632 // No extensible Range found?
1635 // No room left in m_pWhichRanges? => Expand!
1636 std::ptrdiff_t nSize
= pPtr
- m_pWhichRanges
;
1639 m_pWhichRanges
= AddRanges_Impl(m_pWhichRanges
, nSize
, nInitCount
);
1640 nFree
+= nInitCount
;
1643 // Attach new WhichRange
1644 pPtr
= m_pWhichRanges
+ nSize
;
1651 AddItem_Impl(m_pItems
, nItemCount
, nPos
);
1654 // Add new Item to Pool
1655 const SfxPoolItem
& rNew
= m_pPool
->Put( rItem
, nWhich
);
1657 // Remember old Item
1658 bool bIncrementCount
= false;
1659 const SfxPoolItem
* pOld
= m_pItems
[nPos
];
1660 if ( IsInvalidItem(pOld
) ) // state "dontcare"
1664 bIncrementCount
= true;
1666 ? &m_pParent
->Get( nWhich
)
1667 : (SfxItemPool::IsWhich(nWhich
)
1668 ? &m_pPool
->GetDefaultItem(nWhich
)
1672 // Add new Item to ItemSet
1673 m_pItems
[nPos
] = &rNew
;
1675 // Send Changed Notification
1678 Changed( *pOld
, rNew
);
1679 if ( !IsDefaultItem(pOld
) )
1680 m_pPool
->Remove( *pOld
);
1683 if ( bIncrementCount
)
1691 * Using a VoidItem with Which value 0
1693 void SfxItemSet::DisableItem(sal_uInt16 nWhich
)
1695 Put( SfxVoidItem(0), nWhich
);
1698 std::unique_ptr
<SfxItemSet
> SfxAllItemSet::Clone(bool bItems
, SfxItemPool
*pToPool
) const
1700 if (pToPool
&& pToPool
!= m_pPool
)
1702 std::unique_ptr
<SfxAllItemSet
> pNewSet(new SfxAllItemSet( *pToPool
));
1704 pNewSet
->Set( *this );
1705 return std::unique_ptr
<SfxItemSet
>(pNewSet
.release()); // clang3.8 does not seem to be able to upcast std::unique_ptr
1708 return std::unique_ptr
<SfxItemSet
>(bItems
? new SfxAllItemSet(*this) : new SfxAllItemSet(*m_pPool
));
1711 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */