LibreOffice Module svl (master) 1
itemset.cxx
Go to the documentation of this file.
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
23#include <algorithm>
24#include <cassert>
25#include <cstddef>
26
27#include <libxml/xmlwriter.h>
28
29#include <sal/log.hxx>
30#include <svl/itemset.hxx>
31#include <svl/itempool.hxx>
32#include <svl/itemiter.hxx>
33#include <svl/setitem.hxx>
34#include <svl/whiter.hxx>
35
36#include <items_helper.hxx>
37
48 : m_pPool(&rPool), m_pParent(nullptr),
49 m_ppItems(new SfxPoolItem const *[svl::detail::CountRanges(rPool.GetFrozenIdRanges())]{}),
50 m_pWhichRanges(rPool.GetFrozenIdRanges()),
51 m_nCount(0),
52 m_bItemsFixed(false)
53{
54 assert(svl::detail::validRanges2(m_pWhichRanges));
55}
56
58 : m_pPool(&rPool)
59 , m_pParent(nullptr)
60 , m_ppItems(nullptr)
61 , m_nCount(0)
62 , m_bItemsFixed(false)
63{
64}
65
68 : m_pPool(&rPool)
69 , m_pParent(nullptr)
70 , m_ppItems(ppItems)
71 , m_pWhichRanges(std::move(ranges))
72 , m_nCount(0)
73 , m_bItemsFixed(true)
74{
75 assert(ppItems);
76 assert(m_pWhichRanges.size() > 0);
78}
79
81 : m_pPool(&pool),
82 m_pParent(nullptr),
83 m_ppItems(new SfxPoolItem const *[svl::detail::CountRanges(wids)]{}),
84 m_pWhichRanges(std::move(wids)),
85 m_nCount(0),
86 m_bItemsFixed(false)
87{
88 assert(svl::detail::CountRanges(m_pWhichRanges) != 0);
89 assert(svl::detail::validRanges2(m_pWhichRanges));
90}
91
93 : m_pPool( rASet.m_pPool )
94 , m_pParent( rASet.m_pParent )
95 , m_pWhichRanges( rASet.m_pWhichRanges )
96 , m_nCount( rASet.m_nCount )
97 , m_bItemsFixed(false)
98{
99 if (rASet.m_pWhichRanges.empty())
100 {
101 m_ppItems = nullptr;
102 return;
103 }
104
106 m_ppItems = new const SfxPoolItem* [nCnt] {};
107
108 // Copy attributes
109 SfxPoolItem const** ppDst = m_ppItems;
110 SfxPoolItem const** ppSrc = rASet.m_ppItems;
111 for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc )
112 if ( nullptr == *ppSrc || // Current Default?
113 IsInvalidItem(*ppSrc) || // DontCare?
114 IsStaticDefaultItem(*ppSrc) ) // Defaults that are not to be pooled?
115 // Just copy the pointer
116 *ppDst = *ppSrc;
117 else if (m_pPool->IsItemPoolable( **ppSrc ))
118 {
119 // Just copy the pointer and increase RefCount
120 *ppDst = *ppSrc;
121 (*ppDst)->AddRef();
122 }
123 else if ( !(*ppSrc)->Which() )
124 *ppDst = (*ppSrc)->Clone();
125 else
126 // !IsPoolable() => assign via Pool
127 *ppDst = &m_pPool->Put( **ppSrc );
128
130}
131
133 : m_pPool( rASet.m_pPool )
134 , m_pParent( rASet.m_pParent )
135 , m_ppItems( rASet.m_ppItems )
136 , m_pWhichRanges( std::move(rASet.m_pWhichRanges) )
137 , m_nCount( rASet.m_nCount )
138 , m_bItemsFixed(false)
139{
140 if (rASet.m_bItemsFixed)
141 {
142 // have to make a copy
143 int noItems = svl::detail::CountRanges(m_pWhichRanges);
144 m_ppItems = new const SfxPoolItem* [noItems];
145 std::copy(rASet.m_ppItems, rASet.m_ppItems + noItems, m_ppItems);
146 }
147 else
148 // taking over ownership
149 rASet.m_ppItems = nullptr;
150 rASet.m_pPool = nullptr;
151 rASet.m_pParent = nullptr;
152 rASet.m_nCount = 0;
153 assert(svl::detail::validRanges2(m_pWhichRanges));
154}
155
157{
158 if (!m_pWhichRanges.empty()) // might be nullptr if we have been moved-from
159 {
160 if( Count() )
161 {
162 sal_uInt16 nCount = TotalCount();
163 SfxPoolItem const** ppFnd = m_ppItems;
164 for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd )
165 if( *ppFnd && !IsInvalidItem(*ppFnd) )
166 {
167 if( !(*ppFnd)->Which() )
168 delete *ppFnd;
169 else {
170 // Still multiple references present, so just alter the RefCount
171 if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) )
172 (*ppFnd)->ReleaseRef();
173 else
174 if ( !IsDefaultItem(*ppFnd) )
175 // Delete from Pool
176 m_pPool->Remove( **ppFnd );
177 }
178 }
179 }
180 }
181
182 if (!m_bItemsFixed)
183 delete[] m_ppItems;
184 m_pWhichRanges.reset(); // for invariant-testing
185}
186
190sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
191{
192 if( !Count() )
193 return 0;
194 if( nWhich )
195 return ClearSingleItemImpl(nWhich, std::nullopt);
196 else
197 return ClearAllItemsImpl();
198}
199
200sal_uInt16 SfxItemSet::ClearSingleItemImpl( sal_uInt16 nWhich, std::optional<sal_uInt16> oItemOffsetHint )
201{
202 sal_uInt16 nDel = 0;
203 SfxPoolItem const** pFoundOne = nullptr;
204
205 if (oItemOffsetHint)
206 {
207 pFoundOne = m_ppItems + *oItemOffsetHint;
208 assert(!*pFoundOne || IsInvalidItem(*pFoundOne) || (*pFoundOne)->IsVoidItem() || (*pFoundOne)->Which() == nWhich);
209 }
210 else
211 {
212 SfxPoolItem const** ppFnd = m_ppItems;
213 for (const WhichPair& rPair : m_pWhichRanges)
214 {
215 // Within this range?
216 if( rPair.first <= nWhich && nWhich <= rPair.second )
217 {
218 // Actually set?
219 ppFnd += nWhich - rPair.first;
220 pFoundOne = ppFnd;
221
222 // found => break
223 break;
224 }
225 ppFnd += rPair.second - rPair.first + 1;
226 }
227 }
228 if (pFoundOne && *pFoundOne)
229 {
230 // Due to the assertions in the sub calls, we need to do the following
231 --m_nCount;
232 const SfxPoolItem *pItemToClear = *pFoundOne;
233 *pFoundOne = nullptr;
234
235 if ( !IsInvalidItem(pItemToClear) )
236 {
237 if (SfxItemPool::IsWhich(nWhich))
238 {
239 const SfxPoolItem& rNew = m_pParent
240 ? m_pParent->Get( nWhich )
241 : m_pPool->GetDefaultItem( nWhich );
242
243 Changed( *pItemToClear, rNew );
244 }
245 if ( pItemToClear->Which() )
246 m_pPool->Remove( *pItemToClear );
247 }
248 ++nDel;
249 }
250 return nDel;
251}
252
253
255{
256 sal_uInt16 nDel = m_nCount;
257 SfxPoolItem const** ppFnd = m_ppItems;
258
259 for (const WhichPair& rPair : m_pWhichRanges)
260 {
261 for( sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; ++nWhich, ++ppFnd )
262 {
263 if( !*ppFnd )
264 continue;
265
266 // Due to the assertions in the sub calls, we need to do this
267 --m_nCount;
268 const SfxPoolItem *pItemToClear = *ppFnd;
269 *ppFnd = nullptr;
270
271 if ( IsInvalidItem(pItemToClear) )
272 continue;
273
274 if (SfxItemPool::IsWhich(nWhich))
275 {
276 const SfxPoolItem& rNew = m_pParent
277 ? m_pParent->Get( nWhich )
278 : m_pPool->GetDefaultItem( nWhich );
279
280 Changed( *pItemToClear, rNew );
281 }
282
283 // #i32448#
284 // Take care of disabled items, too.
285 if (!pItemToClear->m_nWhich)
286 {
287 // item is disabled, delete it
288 delete pItemToClear;
289 }
290 else
291 {
292 // remove item from pool
293 m_pPool->Remove( *pItemToClear );
294 }
295 }
296 }
297 return nDel;
298}
299
301{
302 SfxPoolItem const** ppFnd = m_ppItems;
303 for (const WhichPair& rPair : m_pWhichRanges)
304 {
305 for( sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; ++nWhich, ++ppFnd )
306 if( IsInvalidItem(*ppFnd) )
307 {
308 *ppFnd = nullptr;
309 --m_nCount;
310 }
311 }
312}
313
315{
316 assert( !m_nCount && "There are still Items set" );
318 memset(static_cast<void*>(m_ppItems), -1, m_nCount * sizeof(SfxPoolItem*));
319}
320
322 bool bSrchInParent,
323 const SfxPoolItem **ppItem ) const
324{
325 return GetItemStateImpl(nWhich, bSrchInParent, ppItem, std::nullopt);
326}
327
329 bool bSrchInParent,
330 const SfxPoolItem **ppItem,
331 std::optional<sal_uInt16> oItemsOffsetHint) const
332{
333 // Find the range in which the Which is located
334 const SfxItemSet* pCurrentSet = this;
336 do
337 {
338 SfxPoolItem const** pFoundOne = nullptr;
339 if (oItemsOffsetHint)
340 {
341 pFoundOne = pCurrentSet->m_ppItems + *oItemsOffsetHint;
342 assert(!*pFoundOne || IsInvalidItem(*pFoundOne) || (*pFoundOne)->IsVoidItem() || (*pFoundOne)->Which() == nWhich);
343 oItemsOffsetHint.reset(); // in case we need to search parent
344 }
345 else
346 {
347 SfxPoolItem const** ppFnd = pCurrentSet->m_ppItems;
348 for (const WhichPair& rPair : pCurrentSet->m_pWhichRanges)
349 {
350 if ( rPair.first <= nWhich && nWhich <= rPair.second )
351 {
352 // Within this range
353 pFoundOne = ppFnd + nWhich - rPair.first;
354 break;
355 }
356 ppFnd += rPair.second - rPair.first + 1;
357 }
358 }
359
360 if (pFoundOne)
361 {
362 if ( !*pFoundOne )
363 {
365 if( !bSrchInParent )
366 return eRet; // Not present
367 // Keep searching in the parents!
368 }
369 else
370 {
371 if ( IsInvalidItem(*pFoundOne) )
372 // Different ones are present
374
375 if ( (*pFoundOne)->IsVoidItem() )
377
378 if (ppItem)
379 {
380 *ppItem = *pFoundOne;
381 }
382 return SfxItemState::SET;
383 }
384 }
385 if (!bSrchInParent)
386 break;
387 pCurrentSet = pCurrentSet->m_pParent;
388 } while (nullptr != pCurrentSet);
389 return eRet;
390}
391
392bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const
393{
394 bool bRet = SfxItemState::SET == GetItemState(nWhich, true, ppItem);
395 if (!bRet && ppItem)
396 *ppItem = nullptr;
397 return bRet;
398}
399
400const SfxPoolItem* SfxItemSet::PutImpl( const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership )
401{
402 if ( !nWhich )
403 {
404 assert(!bPassingOwnership);
405 return nullptr; //FIXME: Only because of Outliner bug
406 }
407
408 SfxPoolItem const** ppFnd = m_ppItems;
409 for (const WhichPair& rPair : m_pWhichRanges)
410 {
411 if( rPair.first <= nWhich && nWhich <= rPair.second )
412 {
413 // Within this range
414 ppFnd += nWhich - rPair.first;
415 if( *ppFnd ) // Already one present
416 {
417 // Same Item already present?
418 if ( *ppFnd == &rItem )
419 {
420 assert(!bPassingOwnership);
421 return nullptr;
422 }
423
424 // Will 'dontcare' or 'disabled' be overwritten with some real value?
425 if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) )
426 {
427 auto const old = *ppFnd;
428 *ppFnd = &m_pPool->PutImpl( rItem, nWhich, bPassingOwnership );
429 if (!IsInvalidItem(old)) {
430 assert(old->Which() == 0);
431 delete old;
432 }
433 return *ppFnd;
434 }
435
436 // Turns into disabled?
437 if( !rItem.Which() )
438 {
439 if (IsInvalidItem(*ppFnd) || (*ppFnd)->Which() != 0) {
440 *ppFnd = rItem.Clone(m_pPool);
441 }
442 if (bPassingOwnership)
443 delete &rItem;
444 return nullptr;
445 }
446 else
447 {
448 // Same value already present?
449 if ( rItem == **ppFnd )
450 {
451 if (bPassingOwnership)
452 delete &rItem;
453 return nullptr;
454 }
455
456 // Add the new one, remove the old one
457 const SfxPoolItem& rNew = m_pPool->PutImpl( rItem, nWhich, bPassingOwnership );
458 const SfxPoolItem* pOld = *ppFnd;
459 *ppFnd = &rNew;
460 if (SfxItemPool::IsWhich(nWhich))
461 Changed( *pOld, rNew );
462 m_pPool->Remove( *pOld );
463 }
464 }
465 else
466 {
467 ++m_nCount;
468 if( !rItem.Which() )
469 {
470 *ppFnd = rItem.Clone(m_pPool);
471 if (bPassingOwnership)
472 delete &rItem;
473 }
474 else
475 {
476 const SfxPoolItem& rNew = m_pPool->PutImpl( rItem, nWhich, bPassingOwnership );
477 *ppFnd = &rNew;
478 if (SfxItemPool::IsWhich(nWhich))
479 {
480 const SfxPoolItem& rOld = m_pParent
481 ? m_pParent->Get( nWhich )
482 : m_pPool->GetDefaultItem( nWhich );
483 Changed( rOld, rNew );
484 }
485 }
486 }
487 SAL_WARN_IF(!bPassingOwnership && m_pPool->IsItemPoolable(nWhich) &&
488 dynamic_cast<const SfxSetItem*>( &rItem ) == nullptr &&
489 **ppFnd != rItem,
490 "svl.items", "putted Item unequal, with ID/pos " << nWhich );
491 return *ppFnd;
492 }
493 ppFnd += rPair.second - rPair.first + 1;
494 }
495 if (bPassingOwnership)
496 delete &rItem;
497 return nullptr;
498}
499
500bool SfxItemSet::Put( const SfxItemSet& rSet, bool bInvalidAsDefault )
501{
502 bool bRet = false;
503 if( rSet.Count() )
504 {
505 SfxPoolItem const** ppFnd = rSet.m_ppItems;
506 for (const WhichPair& rPair : rSet.m_pWhichRanges)
507 {
508 for ( sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; ++nWhich, ++ppFnd )
509 if( *ppFnd )
510 {
511 if ( IsInvalidItem( *ppFnd ) )
512 {
513 if ( bInvalidAsDefault )
514 bRet |= 0 != ClearItem( nWhich );
515 // FIXME: Caused a SEGFAULT on non Windows-platforms:
516 // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
517 else
518 InvalidateItem( nWhich );
519 }
520 else
521 bRet |= nullptr != Put( **ppFnd, nWhich );
522 }
523 }
524 }
525 return bRet;
526}
527
544(
545 const SfxItemSet& rSet, // Source of the Items to be put
546 SfxItemState eDontCareAs, // What will happen to the DontCare Items
547 SfxItemState eDefaultAs // What will happen to the Default Items
548)
549{
550 // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
551 SfxPoolItem const** ppFnd = rSet.m_ppItems;
552 for (const WhichPair& rPair : rSet.m_pWhichRanges)
553 {
554 for ( sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; ++nWhich, ++ppFnd )
555 if( *ppFnd )
556 {
557 if ( IsInvalidItem( *ppFnd ) )
558 {
559 // Item is DontCare:
560 switch ( eDontCareAs )
561 {
563 Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
564 break;
565
567 ClearItem( nWhich );
568 break;
569
571 InvalidateItem( nWhich );
572 break;
573
574 default:
575 assert(!"invalid Argument for eDontCareAs");
576 }
577 }
578 else
579 // Item is set:
580 Put( **ppFnd, nWhich );
581 }
582 else
583 {
584 // Item is default:
585 switch ( eDefaultAs )
586 {
588 Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
589 break;
590
592 ClearItem( nWhich );
593 break;
594
596 InvalidateItem( nWhich );
597 break;
598
599 default:
600 assert(!"invalid Argument for eDefaultAs");
601 }
602 }
603 }
604}
605
610void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
611{
612 // special case: exactly one sal_uInt16 which is already included?
613 if (nFrom == nTo)
614 if (SfxItemState eItemState = GetItemState(nFrom, false);
615 eItemState == SfxItemState::DEFAULT || eItemState == SfxItemState::SET)
616 return;
617
618 auto pNewRanges = m_pWhichRanges.MergeRange(nFrom, nTo);
619 RecreateRanges_Impl(pNewRanges);
620 m_pWhichRanges = std::move(pNewRanges);
621}
622
628{
629 // Identical Ranges?
630 if (m_pWhichRanges == pNewRanges)
631 return;
632 assert(svl::detail::validRanges2(pNewRanges));
633 RecreateRanges_Impl(pNewRanges);
634 m_pWhichRanges = pNewRanges;
635}
636
638{
639 // Identical Ranges?
640 if (m_pWhichRanges == pNewRanges)
641 return;
642 assert(svl::detail::validRanges2(pNewRanges));
643 RecreateRanges_Impl(pNewRanges);
644 m_pWhichRanges = std::move(pNewRanges);
645}
646
648{
649 // create new item-array (by iterating through all new ranges)
650 const auto nSize = svl::detail::CountRanges(pNewRanges);
651 SfxPoolItem const** aNewItems = new const SfxPoolItem* [ nSize ];
652 sal_uInt16 nNewCount = 0;
653 if (m_nCount == 0)
654 memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) );
655 else
656 {
657 sal_uInt16 n = 0;
658 for ( auto const & pRange : pNewRanges )
659 {
660 // iterate through all ids in the range
661 for ( sal_uInt16 nWID = pRange.first; nWID <= pRange.second; ++nWID, ++n )
662 {
663 // direct move of pointer (not via pool)
664 SfxItemState eState = GetItemState( nWID, false, aNewItems+n );
665 if ( SfxItemState::SET == eState )
666 {
667 // increment new item count and possibly increment ref count
668 ++nNewCount;
669 aNewItems[n]->AddRef();
670 }
671 else if ( SfxItemState::DISABLED == eState )
672 {
673 // put "disabled" item
674 ++nNewCount;
675 aNewItems[n] = new SfxVoidItem(0);
676 }
677 else if ( SfxItemState::DONTCARE == eState )
678 {
679 ++nNewCount;
680 aNewItems[n] = INVALID_POOL_ITEM;
681 }
682 else
683 {
684 // default
685 aNewItems[n] = nullptr;
686 }
687 }
688 }
689 // free old items
690 sal_uInt16 nOldTotalCount = TotalCount();
691 for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem )
692 {
693 const SfxPoolItem *pItem = m_ppItems[nItem];
694 if ( pItem && !IsInvalidItem(pItem) && pItem->Which() )
695 m_pPool->Remove(*pItem);
696 }
697 }
698
699 // replace old items-array and ranges
700 if (m_bItemsFixed)
701 m_bItemsFixed = false;
702 else
703 delete[] m_ppItems;
704 m_ppItems = aNewItems;
705 m_nCount = nNewCount;
706}
707
728(
729 const SfxItemSet& rSet, /* The SfxItemSet, whose SfxPoolItems are
730 to been taken over */
731
732 bool bDeep /* true (default)
733
734 The SfxPoolItems from the parents that may
735 be present in rSet, are also taken over into
736 this SfxPoolItemSet
737
738 false
739 The SfxPoolItems from the parents of
740 rSet are not taken into account */
741)
742{
743 bool bRet = false;
744 if (m_nCount)
745 ClearItem();
746 if ( bDeep )
747 {
748 SfxWhichIter aIter1(*this);
749 SfxWhichIter aIter2(rSet);
750 sal_uInt16 nWhich1 = aIter1.FirstWhich();
751 sal_uInt16 nWhich2 = aIter2.FirstWhich();
752 for (;;)
753 {
754 if (!nWhich1 || !nWhich2)
755 break;
756 if (nWhich1 > nWhich2)
757 {
758 nWhich2 = aIter2.NextWhich();
759 continue;
760 }
761 if (nWhich1 < nWhich2)
762 {
763 nWhich1 = aIter1.NextWhich();
764 continue;
765 }
766 const SfxPoolItem* pItem;
767 if( SfxItemState::SET == aIter2.GetItemState( true, &pItem ) )
768 bRet |= nullptr != Put( *pItem, pItem->Which() );
769 nWhich1 = aIter1.NextWhich();
770 nWhich2 = aIter2.NextWhich();
771 }
772 }
773 else
774 bRet = Put(rSet, false);
775
776 return bRet;
777}
778
779const SfxPoolItem* SfxItemSet::GetItem(sal_uInt16 nId, bool bSearchInParent) const
780{
781 // Convert to WhichId
782 sal_uInt16 nWhich = GetPool()->GetWhich(nId);
783
784 // Is the Item set or 'bDeep == true' available?
785 const SfxPoolItem *pItem = nullptr;
786 SfxItemState eState = GetItemState(nWhich, bSearchInParent, &pItem);
787 if (bSearchInParent && SfxItemState::DEFAULT == eState && SfxItemPool::IsWhich(nWhich))
788 {
789 pItem = &m_pPool->GetDefaultItem(nWhich);
790 }
791
792 return pItem;
793}
794
795const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool bSrchInParent) const
796{
797 // Search the Range in which the Which is located in:
798 const SfxItemSet* pCurrentSet = this;
799 do
800 {
801 if( pCurrentSet->Count() )
802 {
803 SfxPoolItem const** ppFnd = pCurrentSet->m_ppItems;
804 for (auto const & pPtr : pCurrentSet->m_pWhichRanges)
805 {
806 if( pPtr.first <= nWhich && nWhich <= pPtr.second )
807 {
808 // In this Range
809 ppFnd += nWhich - pPtr.first;
810 if( *ppFnd )
811 {
812 if( IsInvalidItem(*ppFnd) ) {
813 //FIXME: The following code is duplicated further down
814 assert(m_pPool);
817 return m_pPool->GetDefaultItem( nWhich );
818 }
819#ifdef DBG_UTIL
820 const SfxPoolItem *pItem = *ppFnd;
821 if ( pItem->IsVoidItem() || !pItem->Which() )
822 SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item");
823#endif
824 return **ppFnd;
825 }
826 break; // Continue with Parent
827 }
828 ppFnd += pPtr.second - pPtr.first + 1;
829 }
830 }
831//TODO: Search until end of Range: What are we supposed to do now? To the Parent or Default??
832// if( !*pPtr ) // Until the end of the search Range?
833// break;
834 if (!bSrchInParent)
835 break;
836 pCurrentSet = pCurrentSet->m_pParent;
837 } while (nullptr != pCurrentSet);
838
839 // Get the Default from the Pool and return
840 assert(m_pPool);
841 return m_pPool->GetDefaultItem( nWhich );
842}
843
848{
849}
850
851sal_uInt16 SfxItemSet::TotalCount() const
852{
854}
855
861{
862 assert(m_pPool && "Not implemented without Pool");
863 if( !Count() ) // None set?
864 return;
865
866 // Delete all Items not contained in rSet
867 if( !rSet.Count() )
868 {
869 ClearItem(); // Delete everything
870 return;
871 }
872
873 // If the Ranges are identical, we can easily process it
875 {
876 sal_uInt16 nSize = TotalCount();
877 SfxPoolItem const** ppFnd1 = m_ppItems;
878 SfxPoolItem const** ppFnd2 = rSet.m_ppItems;
879
880 for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
881 if( *ppFnd1 && !*ppFnd2 )
882 {
883 // Delete from Pool
884 if( !IsInvalidItem( *ppFnd1 ) )
885 {
886 sal_uInt16 nWhich = (*ppFnd1)->Which();
887 if (SfxItemPool::IsWhich(nWhich))
888 {
889 const SfxPoolItem& rNew = m_pParent
890 ? m_pParent->Get( nWhich )
891 : m_pPool->GetDefaultItem( nWhich );
892
893 Changed( **ppFnd1, rNew );
894 }
895 m_pPool->Remove( **ppFnd1 );
896 }
897 *ppFnd1 = nullptr;
898 --m_nCount;
899 }
900 }
901 else
902 {
903 SfxWhichIter aIter( *this );
904 sal_uInt16 nWhich = aIter.FirstWhich();
905 while ( nWhich )
906 {
907 if( SfxItemState::UNKNOWN == rSet.GetItemState( nWhich, false ) )
908 aIter.ClearItem(); // Delete
909 nWhich = aIter.NextWhich();
910 }
911 }
912}
913
915{
916 if( !Count() || !rSet.Count() )// None set?
917 return;
918
919 // If the Ranges are identical, we can easily process it
921 {
922 sal_uInt16 nSize = TotalCount();
923 SfxPoolItem const** ppFnd1 = m_ppItems;
924 SfxPoolItem const** ppFnd2 = rSet.m_ppItems;
925
926 for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
927 if( *ppFnd1 && *ppFnd2 )
928 {
929 // Delete from Pool
930 if( !IsInvalidItem( *ppFnd1 ) )
931 {
932 sal_uInt16 nWhich = (*ppFnd1)->Which();
933 if (SfxItemPool::IsWhich(nWhich))
934 {
935 const SfxPoolItem& rNew = m_pParent
936 ? m_pParent->Get( nWhich )
937 : m_pPool->GetDefaultItem( nWhich );
938
939 Changed( **ppFnd1, rNew );
940 }
941 m_pPool->Remove( **ppFnd1 );
942 }
943 *ppFnd1 = nullptr;
944 --m_nCount;
945 }
946 }
947 else
948 {
949 SfxWhichIter aIter( *this );
950 sal_uInt16 nWhich = aIter.FirstWhich();
951 while ( nWhich )
952 {
953 if( SfxItemState::SET == rSet.GetItemState( nWhich, false ) )
954 aIter.ClearItem(); // Delete
955 nWhich = aIter.NextWhich();
956 }
957 }
958}
959
1038static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount,
1039 const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2,
1040 bool bIgnoreDefaults )
1041{
1042 assert(ppFnd1 != nullptr && "Merging to 0-Item");
1043
1044 // 1st Item is Default?
1045 if ( !*ppFnd1 )
1046 {
1047 if ( IsInvalidItem(pFnd2) )
1048 // Decision table: default, dontcare, doesn't matter, doesn't matter
1049 *ppFnd1 = INVALID_POOL_ITEM;
1050
1051 else if ( pFnd2 && !bIgnoreDefaults &&
1052 _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
1053 // Decision table: default, set, !=, sal_False
1054 *ppFnd1 = INVALID_POOL_ITEM;
1055
1056 else if ( pFnd2 && bIgnoreDefaults )
1057 // Decision table: default, set, doesn't matter, sal_True
1058 *ppFnd1 = &_pPool->Put( *pFnd2 );
1059
1060 if ( *ppFnd1 )
1061 ++rCount;
1062 }
1063
1064 // 1st Item set?
1065 else if ( !IsInvalidItem(*ppFnd1) )
1066 {
1067 if ( !pFnd2 )
1068 {
1069 // 2nd Item is Default
1070 if ( !bIgnoreDefaults &&
1071 **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) )
1072 {
1073 // Decision table: set, default, !=, sal_False
1074 _pPool->Remove( **ppFnd1 );
1075 *ppFnd1 = INVALID_POOL_ITEM;
1076 }
1077 }
1078 else if ( IsInvalidItem(pFnd2) )
1079 {
1080 // 2nd Item is dontcare
1081 if ( !bIgnoreDefaults ||
1082 **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) )
1083 {
1084 // Decision table: set, dontcare, doesn't matter, sal_False
1085 // or: set, dontcare, !=, sal_True
1086 _pPool->Remove( **ppFnd1 );
1087 *ppFnd1 = INVALID_POOL_ITEM;
1088 }
1089 }
1090 else
1091 {
1092 // 2nd Item is set
1093 if ( **ppFnd1 != *pFnd2 )
1094 {
1095 // Decision table: set, set, !=, doesn't matter
1096 _pPool->Remove( **ppFnd1 );
1097 *ppFnd1 = INVALID_POOL_ITEM;
1098 }
1099 }
1100 }
1101}
1102
1104{
1105 // WARNING! When making changes/fixing bugs, always update the table above!!
1106 assert( GetPool() == rSet.GetPool() && "MergeValues with different Pools" );
1107
1108 // If the Ranges match, they are easier to process!
1110 {
1111 sal_uInt16 nSize = TotalCount();
1112 SfxPoolItem const** ppFnd1 = m_ppItems;
1113 SfxPoolItem const** ppFnd2 = rSet.m_ppItems;
1114
1115 for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1116 MergeItem_Impl(m_pPool, m_nCount, ppFnd1, *ppFnd2, false/*bIgnoreDefaults*/);
1117 }
1118 else
1119 {
1120 SfxWhichIter aIter( rSet );
1121 sal_uInt16 nWhich;
1122 while( 0 != ( nWhich = aIter.NextWhich() ) )
1123 {
1124 const SfxPoolItem* pItem = nullptr;
1125 (void)aIter.GetItemState( true, &pItem );
1126 if( !pItem )
1127 {
1128 // Not set, so default
1129 MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ) );
1130 }
1131 else if( IsInvalidItem( pItem ) )
1132 // don't care
1133 InvalidateItem( nWhich );
1134 else
1135 MergeValue( *pItem );
1136 }
1137 }
1138}
1139
1140void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, bool bIgnoreDefaults )
1141{
1142 SfxPoolItem const** ppFnd = m_ppItems;
1143 const sal_uInt16 nWhich = rAttr.Which();
1144 for( auto const & pPtr : m_pWhichRanges )
1145 {
1146 // In this Range??
1147 if( pPtr.first <= nWhich && nWhich <= pPtr.second )
1148 {
1149 ppFnd += nWhich - pPtr.first;
1150 MergeItem_Impl(m_pPool, m_nCount, ppFnd, &rAttr, bIgnoreDefaults);
1151 break;
1152 }
1153 ppFnd += pPtr.second - pPtr.first + 1;
1154 }
1155}
1156
1157void SfxItemSet::InvalidateItem( sal_uInt16 nWhich )
1158{
1159 SfxPoolItem const** ppFnd = m_ppItems;
1160 for( auto const & pPtr : m_pWhichRanges )
1161 {
1162 if( pPtr.first <= nWhich && nWhich <= pPtr.second )
1163 {
1164 // In this Range?
1165 ppFnd += nWhich - pPtr.first;
1166
1167 if( *ppFnd ) // Set for me
1168 {
1169 if( !IsInvalidItem(*ppFnd) )
1170 {
1171 m_pPool->Remove( **ppFnd );
1172 *ppFnd = INVALID_POOL_ITEM;
1173 }
1174 }
1175 else
1176 {
1177 *ppFnd = INVALID_POOL_ITEM;
1178 ++m_nCount;
1179 }
1180 break;
1181 }
1182 ppFnd += pPtr.second - pPtr.first + 1;
1183 }
1184}
1185
1186sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const
1187{
1188 sal_uInt16 n = 0;
1189 for( auto const & pPtr : m_pWhichRanges )
1190 {
1191 n = ( pPtr.second - pPtr.first ) + 1;
1192 if( nPos < n )
1193 return pPtr.first + nPos;
1194 nPos = nPos - n;
1195 }
1196 assert(false);
1197 return 0;
1198}
1199
1200bool SfxItemSet::operator==(const SfxItemSet &rCmp) const
1201{
1202 return Equals( rCmp, true);
1203}
1204
1205bool SfxItemSet::Equals(const SfxItemSet &rCmp, bool bComparePool) const
1206{
1207 // Values we can get quickly need to be the same
1208 const bool bDifferentPools = (m_pPool != rCmp.m_pPool);
1209 if ( (bComparePool && m_pParent != rCmp.m_pParent) ||
1210 (bComparePool && bDifferentPools) ||
1211 Count() != rCmp.Count() )
1212 return false;
1213
1214 // If we reach here and bDifferentPools==true that means bComparePool==false.
1215
1216 // Counting Ranges takes longer; they also need to be the same, however
1217 sal_uInt16 nCount1 = TotalCount();
1218 sal_uInt16 nCount2 = rCmp.TotalCount();
1219 if ( nCount1 != nCount2 )
1220 return false;
1221
1222 // Are the Ranges themselves unequal?
1223 for (sal_Int32 i = 0; i < m_pWhichRanges.size(); ++i)
1224 {
1225 if (m_pWhichRanges[i] != rCmp.m_pWhichRanges[i])
1226 {
1227 // We must use the slow method then
1228 SfxWhichIter aIter( *this );
1229 for ( sal_uInt16 nWh = aIter.FirstWhich();
1230 nWh;
1231 nWh = aIter.NextWhich() )
1232 {
1233 // If the pointer of the poolable Items are unequal, the Items must match
1234 const SfxPoolItem *pItem1 = nullptr, *pItem2 = nullptr;
1235 if ( GetItemState( nWh, false, &pItem1 ) !=
1236 rCmp.GetItemState( nWh, false, &pItem2 ) ||
1237 ( pItem1 != pItem2 &&
1238 ( !pItem1 || IsInvalidItem(pItem1) ||
1239 (m_pPool->IsItemPoolable(*pItem1) &&
1240 *pItem1 != *pItem2 ) ) ) )
1241 return false;
1242 }
1243
1244 return true;
1245 }
1246 }
1247
1248 // Are all pointers the same?
1249 if (0 == memcmp( m_ppItems, rCmp.m_ppItems, nCount1 * sizeof(m_ppItems[0]) ))
1250 return true;
1251
1252 // We need to compare each one separately then
1253 const SfxPoolItem **ppItem1 = m_ppItems;
1254 const SfxPoolItem **ppItem2 = rCmp.m_ppItems;
1255 for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos )
1256 {
1257 // If the pointers of the poolable Items are not the same, the Items
1258 // must match
1259 if ( *ppItem1 != *ppItem2 &&
1260 ( ( !*ppItem1 || !*ppItem2 ) ||
1261 ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) ||
1262 (!bDifferentPools && m_pPool->IsItemPoolable(**ppItem1)) ||
1263 **ppItem1 != **ppItem2 ) )
1264 return false;
1265
1266 ++ppItem1;
1267 ++ppItem2;
1268 }
1269
1270 return true;
1271}
1272
1273std::unique_ptr<SfxItemSet> SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
1274{
1275 if (pToPool && pToPool != m_pPool)
1276 {
1277 std::unique_ptr<SfxItemSet> pNewSet(new SfxItemSet(*pToPool, m_pWhichRanges));
1278 if ( bItems )
1279 {
1280 SfxWhichIter aIter(*pNewSet);
1281 sal_uInt16 nWhich = aIter.FirstWhich();
1282 while ( nWhich )
1283 {
1284 const SfxPoolItem* pItem;
1285 if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
1286 pNewSet->Put( *pItem, pItem->Which() );
1287 nWhich = aIter.NextWhich();
1288 }
1289 }
1290 return pNewSet;
1291 }
1292 else
1293 return std::unique_ptr<SfxItemSet>(bItems
1294 ? new SfxItemSet(*this)
1296}
1297
1299{
1300 // if you are trying to clone, then the thing you are cloning is polymorphic, which means
1301 // it cannot be cloned as a value
1302 assert((typeid(*this) == typeid(SfxItemSet)) && "cannot call this on a subclass of SfxItemSet");
1303
1304 if (pToPool && pToPool != m_pPool)
1305 {
1306 SfxItemSet aNewSet(*pToPool, m_pWhichRanges);
1307 if ( bItems )
1308 {
1309 SfxWhichIter aIter(aNewSet);
1310 sal_uInt16 nWhich = aIter.FirstWhich();
1311 while ( nWhich )
1312 {
1313 const SfxPoolItem* pItem;
1314 if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
1315 aNewSet.Put( *pItem, pItem->Which() );
1316 nWhich = aIter.NextWhich();
1317 }
1318 }
1319 return aNewSet;
1320 }
1321 else
1322 return bItems
1323 ? *this
1325}
1326
1328{
1329 SfxPoolItem const** ppFnd = m_ppItems;
1330 const sal_uInt16 nWhich = rItem.Which();
1331#ifdef DBG_UTIL
1332 IsPoolDefaultItem(&rItem) || m_pPool->CheckItemInPool(&rItem);
1333 // Only cause assertion in the callees
1334#endif
1335 for( auto const & pPtr : m_pWhichRanges)
1336 {
1337 if( pPtr.first <= nWhich && nWhich <= pPtr.second )
1338 {
1339 // In this Range?
1340 ppFnd += nWhich - pPtr.first;
1341 const SfxPoolItem* pOld = *ppFnd;
1342 if( pOld ) // One already present
1343 {
1344 if( rItem == **ppFnd )
1345 return; // Already present!
1346 m_pPool->Remove( *pOld );
1347 }
1348 else
1349 ++m_nCount;
1350
1351 // Add the new one
1352 if( IsPoolDefaultItem(&rItem) )
1353 *ppFnd = &m_pPool->Put( rItem );
1354 else
1355 {
1356 *ppFnd = &rItem;
1357 if( !IsStaticDefaultItem( &rItem ) )
1358 rItem.AddRef();
1359 }
1360
1361 return;
1362 }
1363 ppFnd += pPtr.second - pPtr.first + 1;
1364 }
1365}
1366
1368{
1369 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxItemSet"));
1370 SfxItemIter aIter(*this);
1371 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
1372 {
1373 if (IsInvalidItem(pItem))
1374 {
1375 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("invalid"));
1376 (void)xmlTextWriterEndElement(pWriter);
1377 }
1378 else
1379 {
1380 pItem->dumpAsXml(pWriter);
1381 }
1382 }
1383 (void)xmlTextWriterEndElement(pWriter);
1384}
1385
1386
1387// ----------------------------------------------- class SfxAllItemSet
1388
1390: SfxItemSet(rPool, SfxAllItemSetFlag::Flag)
1391{
1392}
1393
1395: SfxItemSet(rCopy)
1396{
1397}
1398
1404: SfxItemSet(rCopy)
1405{
1406}
1407
1411const SfxPoolItem* SfxAllItemSet::PutImpl( const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership )
1412{
1413 MergeRange(nWhich, nWhich);
1414 return SfxItemSet::PutImpl(rItem, nWhich, bPassingOwnership);
1415}
1416
1421void SfxItemSet::DisableItem(sal_uInt16 nWhich)
1422{
1423 Put( SfxVoidItem(0), nWhich );
1424}
1425
1426std::unique_ptr<SfxItemSet> SfxAllItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
1427{
1428 if (pToPool && pToPool != m_pPool)
1429 {
1430 std::unique_ptr<SfxAllItemSet> pNewSet(new SfxAllItemSet( *pToPool ));
1431 if ( bItems )
1432 pNewSet->Set( *this );
1433 return pNewSet;
1434 }
1435 else
1436 return std::unique_ptr<SfxItemSet>(bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*m_pPool));
1437}
1438
1439
1441{
1442 auto p = new WhichPair[nSize];
1443 for (int i=0; i<nSize; ++i)
1444 p[i] = wids[i];
1445 m_pairs = p;
1446 m_size = nSize;
1447 m_bOwnRanges = true;
1448}
1449
1450WhichRangesContainer::WhichRangesContainer(sal_uInt16 nWhichStart, sal_uInt16 nWhichEnd)
1451 : m_size(1), m_bOwnRanges(true)
1452{
1453 auto p = new WhichPair[1];
1454 p[0] = { nWhichStart, nWhichEnd };
1455 m_pairs = p;
1456}
1457
1459{
1460 std::swap(m_pairs, other.m_pairs);
1461 std::swap(m_size, other.m_size);
1462 std::swap(m_bOwnRanges, other.m_bOwnRanges);
1463}
1464
1466{
1467 std::swap(m_pairs, other.m_pairs);
1468 std::swap(m_size, other.m_size);
1469 std::swap(m_bOwnRanges, other.m_bOwnRanges);
1470 return *this;
1471}
1472
1474{
1475 reset();
1476 m_size = other.m_size;
1477 m_bOwnRanges = other.m_bOwnRanges;
1478 if (m_bOwnRanges)
1479 {
1480 auto p = new WhichPair[m_size];
1481 for (int i=0; i<m_size; ++i)
1482 p[i] = other.m_pairs[i];
1483 m_pairs = p;
1484 }
1485 else
1486 m_pairs = other.m_pairs;
1487 return *this;
1488}
1489
1491{
1492 reset();
1493}
1494
1496{
1497 if (m_size != other.m_size)
1498 return false;
1499 if (m_pairs == other.m_pairs)
1500 return true;
1501 return std::equal(m_pairs, m_pairs + m_size, other.m_pairs, other.m_pairs + m_size);
1502}
1503
1504
1506{
1507 if (m_bOwnRanges)
1508 {
1509 delete [] m_pairs;
1510 m_bOwnRanges = false;
1511 }
1512 m_pairs = nullptr;
1513 m_size = 0;
1514}
1515
1516// Adds a range to which ranges, keeping the ranges in valid state (sorted, non-overlapping)
1518 sal_uInt16 nTo) const
1519{
1520 assert(svl::detail::validRange(nFrom, nTo));
1521
1522 if (empty())
1523 return WhichRangesContainer(nFrom, nTo);
1524
1525 // create vector of ranges (sal_uInt16 pairs of lower and upper bound)
1526 const size_t nOldCount = size();
1527 // Allocate one item more than we already have.
1528 // In the worst case scenario we waste a little bit
1529 // of memory, but we avoid another allocation, which is more important.
1530 std::unique_ptr<WhichPair[]> aRangesTable(new WhichPair[nOldCount+1]);
1531 int aRangesTableSize = 0;
1532 bool bAdded = false;
1533 for (const auto& rPair : *this)
1534 {
1535 if (!bAdded && rPair.first >= nFrom)
1536 { // insert new range, keep ranges sorted
1537 aRangesTable[aRangesTableSize++] = { nFrom, nTo };
1538 bAdded = true;
1539 }
1540 // insert current range
1541 aRangesTable[aRangesTableSize++] = rPair;
1542 }
1543 if (!bAdded)
1544 aRangesTable[aRangesTableSize++] = { nFrom, nTo };
1545
1546 // true if ranges overlap or adjoin, false if ranges are separate
1547 auto needMerge = [](WhichPair lhs, WhichPair rhs) {
1548 return (lhs.first - 1) <= rhs.second && (rhs.first - 1) <= lhs.second;
1549 };
1550
1551 auto it = aRangesTable.get();
1552 auto endIt = aRangesTable.get() + aRangesTableSize;
1553 // we have at least one range at this point
1554 for (;;)
1555 {
1556 auto itNext = std::next(it);
1557 if (itNext == endIt)
1558 break;
1559 // check if neighbouring ranges overlap or adjoin
1560 if (needMerge(*it, *itNext))
1561 {
1562 // lower bounds are sorted, implies: it->first = min(it[0].first, it[1].first)
1563 it->second = std::max(it->second, itNext->second);
1564 // remove next element
1565 std::move(std::next(itNext), endIt, itNext);
1566 --aRangesTableSize;
1567 endIt = aRangesTable.get() + aRangesTableSize;
1568 }
1569 else
1570 ++it;
1571 }
1572
1573 return WhichRangesContainer(std::move(aRangesTable), aRangesTableSize);
1574}
1575
1576/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual const SfxPoolItem * PutImpl(const SfxPoolItem &, sal_uInt16 nWhich, bool bPassingOwnership) override
Putting with automatic extension of the WhichId with the ID of the Item.
Definition: itemset.cxx:1411
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const override
Definition: itemset.cxx:1426
const SfxPoolItem * GetCurItem() const
get item, or null if no items
Definition: itemiter.hxx:38
const SfxPoolItem * NextItem()
Definition: itemiter.hxx:42
Base class for providers of defaults of SfxPoolItems.
Definition: itempool.hxx:51
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
Definition: itempool.cxx:940
const SfxPoolItem & GetDefaultItem(sal_uInt16 nWhich) const
Definition: itempool.cxx:816
bool IsItemPoolable(sal_uInt16 nWhich) const
Definition: itempool.cxx:178
bool CheckItemInPool(const SfxPoolItem *) const
Definition: itempool.cxx:128
const T & Put(std::unique_ptr< T > xItem, sal_uInt16 nWhich=0)
Definition: itempool.hxx:138
static bool IsWhich(sal_uInt16 nId)
Definition: itempool.hxx:194
void Remove(const SfxPoolItem &)
Definition: itempool.cxx:751
virtual const SfxPoolItem & PutImpl(const SfxPoolItem &, sal_uInt16 nWhich=0, bool bPassingOwnership=false)
Definition: itempool.cxx:635
virtual void Changed(const SfxPoolItem &rOld, const SfxPoolItem &rNew)
Notification callback.
Definition: itemset.cxx:847
void MergeValues(const SfxItemSet &rSet)
Definition: itemset.cxx:1103
SfxItemPool * m_pPool
pool that stores the items
Definition: itemset.hxx:41
SfxItemSet(SfxItemPool &, SfxAllItemSetFlag)
Definition: itemset.cxx:57
SfxItemPool * GetPool() const
Definition: itemset.hxx:202
sal_uInt16 ClearAllItemsImpl()
Definition: itemset.cxx:254
sal_uInt16 Count() const
Definition: itemset.hxx:95
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: itemset.cxx:1367
bool m_bItemsFixed
true if this is a SfxItemSetFixed object
Definition: itemset.hxx:46
void PutExtended(const SfxItemSet &, SfxItemState eDontCareAs, SfxItemState eDefaultAs)
This method takes the Items from the 'rSet' and adds to '*this'.
Definition: itemset.cxx:544
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const
Definition: itemset.cxx:1273
bool operator==(const SfxItemSet &) const
Definition: itemset.cxx:1200
sal_uInt16 ClearSingleItemImpl(sal_uInt16 nWhich, std::optional< sal_uInt16 > oItemOffsetHint)
Definition: itemset.cxx:200
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
Delete single Items or all Items (nWhich == 0)
Definition: itemset.cxx:190
void InvalidateAllItems()
Definition: itemset.cxx:314
const SfxItemSet * m_pParent
derivation
Definition: itemset.hxx:42
void ClearInvalidItems()
Definition: itemset.cxx:300
bool HasItem(sal_uInt16 nWhich, const SfxPoolItem **ppItem=nullptr) const
Definition: itemset.cxx:392
void MergeValue(const SfxPoolItem &rItem, bool bOverwriteDefaults=false)
Definition: itemset.cxx:1140
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: itemset.cxx:321
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
This method eases accessing single Items in the SfxItemSet.
Definition: itemset.cxx:779
void PutDirect(const SfxPoolItem &rItem)
Definition: itemset.cxx:1327
sal_uInt16 TotalCount() const
Definition: itemset.cxx:851
SfxItemSet CloneAsValue(bool bItems=true, SfxItemPool *pToPool=nullptr) const
note that this only works if you know for sure that you are dealing with an SfxItemSet and not one of...
Definition: itemset.cxx:1298
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
Definition: itemset.hxx:181
SfxItemState GetItemStateImpl(sal_uInt16 nWhich, bool bSrchInParent, const SfxPoolItem **ppItem, std::optional< sal_uInt16 > oItemsOffsetHint) const
Definition: itemset.cxx:328
SfxAllItemSetFlag
special constructor for SfxAllItemSet
Definition: itemset.hxx:69
void Intersect(const SfxItemSet &rSet)
Only retain the Items that are also present in rSet (nevermind their value).
Definition: itemset.cxx:860
WhichRangesContainer m_pWhichRanges
array of Which Ranges
Definition: itemset.hxx:44
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
Definition: itemset.cxx:795
bool Set(const SfxItemSet &, bool bDeep=true)
The SfxItemSet takes over exactly those SfxPoolItems that are set in rSet and are in their own Which ...
Definition: itemset.cxx:728
void DisableItem(sal_uInt16 nWhich)
Disable Item Using a VoidItem with Which value 0.
Definition: itemset.cxx:1421
void SetRanges(const WhichRangesContainer &)
Modifies the ranges of settable items.
Definition: itemset.cxx:627
virtual ~SfxItemSet()
Definition: itemset.cxx:156
sal_uInt16 GetWhichByPos(sal_uInt16 nPos) const
Definition: itemset.cxx:1186
SfxPoolItem const ** m_ppItems
pointer to array of items, we allocate and free this unless m_bItemsFixed==true
Definition: itemset.hxx:43
virtual const SfxPoolItem * PutImpl(const SfxPoolItem &, sal_uInt16 nWhich, bool bPassingOwnership)
Definition: itemset.cxx:400
SVL_DLLPRIVATE void RecreateRanges_Impl(const WhichRangesContainer &pNewRanges)
Definition: itemset.cxx:647
friend class SfxAllItemSet
Definition: itemset.hxx:49
sal_uInt16 m_nCount
number of items
Definition: itemset.hxx:45
void Differentiate(const SfxItemSet &rSet)
Definition: itemset.cxx:914
void MergeRange(sal_uInt16 nFrom, sal_uInt16 nTo)
Expands the ranges of settable items by 'nFrom' to 'nTo'.
Definition: itemset.cxx:610
bool Equals(const SfxItemSet &, bool bComparePool) const
Compare possibly ignoring SfxItemPool pointer.
Definition: itemset.cxx:1205
void InvalidateItem(sal_uInt16 nWhich)
Definition: itemset.cxx:1157
void AddRef(sal_uInt32 n=1) const
Definition: poolitem.hxx:254
sal_uInt16 Which() const
Definition: poolitem.hxx:149
sal_uInt32 ReleaseRef(sal_uInt32 n=1) const
Definition: poolitem.hxx:261
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const =0
sal_uInt16 m_nWhich
Definition: poolitem.hxx:124
virtual bool IsVoidItem() const
Only SfxVoidItem shall and must return true for this.
Definition: poolitem.cxx:564
Iterates over the which ids and the pool items arrays together (which are stored in parallel arrays).
Definition: whiter.hxx:34
sal_uInt16 FirstWhich()
Definition: whiter.cxx:58
SfxItemState GetItemState(bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: whiter.cxx:66
void ClearItem()
Definition: whiter.cxx:73
sal_uInt16 NextWhich()
Definition: whiter.cxx:39
int nCount
struct _xmlTextWriter * xmlTextWriterPtr
static void MergeItem_Impl(SfxItemPool *_pPool, sal_uInt16 &rCount, const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2, bool bIgnoreDefaults)
Decision table for MergeValue(s)
Definition: itemset.cxx:1038
void * p
sal_Int64 n
sal_uInt16 nPos
sal_Int16 m_nCount
#define SAL_WARN_IF(condition, area, stream)
#define SAL_INFO(area, stream)
int i
constexpr bool validRange(sal_uInt16 wid1, sal_uInt16 wid2)
Definition: whichranges.hxx:24
sal_uInt16 CountRanges(const WhichRangesContainer &pRanges)
Determines the number of sal_uInt16s in a container of pairs of sal_uInt16s, each representing a rang...
bool validRanges2(const WhichRangesContainer &pRanges)
sal_Int16 nId
#define INVALID_POOL_ITEM
Definition: poolitem.hxx:109
bool IsPoolDefaultItem(const SfxPoolItem *pItem)
Definition: poolitem.hxx:269
SfxItemState
These values have to match the values in the css::frame::status::ItemState IDL to be found at offapi/...
Definition: poolitem.hxx:82
@ DISABLED
Specifies that the property is currently disabled.
@ DEFAULT
Specifies that the property is currently in a default state.
@ UNKNOWN
Specifies an unknown state.
@ SET
The property has been explicitly set to a given value hence we know we are not taking the default val...
@ DONTCARE
Specifies that the property is currently in a don't care state.
bool IsDefaultItem(const SfxPoolItem *pItem)
Definition: poolitem.hxx:279
bool IsInvalidItem(const SfxPoolItem *pItem)
Definition: poolitem.hxx:289
bool IsStaticDefaultItem(const SfxPoolItem *pItem)
Definition: poolitem.hxx:274
static SfxItemSet & rSet
Most of the time, the which ranges we point at are a compile-time literal.
Definition: whichranges.hxx:79
bool operator==(WhichRangesContainer const &other) const
Definition: itemset.cxx:1495
bool empty() const noexcept
sal_Int32 size() const noexcept
WhichRangesContainer & operator=(WhichRangesContainer &&other)
Definition: itemset.cxx:1465
WhichRangesContainer()=default
SAL_WARN_UNUSED_RESULT WhichRangesContainer MergeRange(sal_uInt16 nFrom, sal_uInt16 nTo) const
Definition: itemset.cxx:1517
WhichPair const * m_pairs
Definition: whichranges.hxx:82
bool m_bOwnRanges
if true, we allocated and need to delete the pairs, if not, we are pointing at a global const literal
Definition: whichranges.hxx:86
std::pair< sal_uInt16, sal_uInt16 > WhichPair
Definition: whichranges.hxx:18