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 .
24 #include <libxml/xmlwriter.h>
26 #include <sal/log.hxx>
27 #include <svl/itemset.hxx>
28 #include <svl/itempool.hxx>
29 #include <svl/itemiter.hxx>
30 #include <svl/whiter.hxx>
31 #include <svl/nranges.hxx>
32 #include "whassert.hxx"
34 #include <tools/stream.hxx>
35 #include <tools/solar.h>
36 #include <rtl/string.hxx>
40 static const sal_uInt16 nInitCount
= 10; // Single USHORTs => 5 pairs without '0'
41 #include "nranges.cxx"
48 const sal_Char
*DbgCheckItemSet( const void* pVoid
)
50 const SfxItemSet
*pSet
= static_cast<const SfxItemSet
*>(pVoid
);
51 SfxWhichIter
aIter( *pSet
);
52 sal_uInt16 nCount
= 0, n
= 0;
53 for ( sal_uInt16 nWh
= aIter
.FirstWhich(); nWh
; nWh
= aIter
.NextWhich(), ++n
)
55 const SfxPoolItem
*pItem
= pSet
->m_pItems
[n
];
59 assert((IsInvalidItem(pItem
) ||
60 pItem
->Which() == 0 || pItem
->Which() == nWh
61 ) && "SfxItemSet: invalid which-id" );
62 assert((IsInvalidItem(pItem
) || !pItem
->Which() ||
63 !SfxItemPool::IsWhich(pItem
->Which()) ||
64 pSet
->GetPool()->IsItemFlag(nWh
, SfxItemPoolFlags::NOT_POOLABLE
) ||
65 SFX_ITEMS_NULL
!= pSet
->GetPool()->GetSurrogate(pItem
)
66 ) && "SfxItemSet: item in set which is not in pool" );
70 assert(pSet
->m_nCount
== nCount
);
78 * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
79 * the supplied SfxItemPool.
81 * For Sfx programmers: an SfxItemSet constructed in this way cannot
82 * contain any Items with SlotIds as Which values.
84 SfxItemSet::SfxItemSet
86 SfxItemPool
& rPool
, /* Target Pool for the SfxPoolItems which are
87 added to this SfxItemSet */
88 bool bTotalRanges
/* Take over complete pool ranges? */
94 // DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
95 // "please use suitable ranges" );
96 #if defined DBG_UTIL && defined SFX_ITEMSET_NO_DEFAULT_CTOR
100 (void) bTotalRanges
; // avoid warnings
103 m_pWhichRanges
= const_cast<sal_uInt16
*>(m_pPool
->GetFrozenIdRanges());
104 assert( m_pWhichRanges
&& "don't create ItemSets with full range before FreezeIdRanges()" );
106 m_pPool
->FillItemIdRanges_Impl( m_pWhichRanges
);
108 const sal_uInt16 nSize
= TotalCount();
109 m_pItems
= new const SfxPoolItem
* [ nSize
];
110 memset(static_cast<void*>(m_pItems
), 0, nSize
* sizeof(SfxPoolItem
*));
113 SfxItemSet::SfxItemSet(SfxItemPool
& rPool
, sal_uInt16 nWhich1
, sal_uInt16 nWhich2
)
118 assert(nWhich1
<= nWhich2
);
120 InitRanges_Impl(nWhich1
, nWhich2
);
123 void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1
, sal_uInt16 nWh2
)
125 m_pWhichRanges
= new sal_uInt16
[ 3 ];
126 *(m_pWhichRanges
+0) = nWh1
;
127 *(m_pWhichRanges
+1) = nWh2
;
128 *(m_pWhichRanges
+2) = 0;
129 const sal_uInt16 nRg
= nWh2
- nWh1
+ 1;
130 m_pItems
= new const SfxPoolItem
* [ nRg
];
131 memset(static_cast<void*>(m_pItems
), 0, nRg
* sizeof(SfxPoolItem
*));
134 void SfxItemSet::InitRanges_Impl(va_list pArgs
, sal_uInt16 nWh1
, sal_uInt16 nWh2
, sal_uInt16 nNull
)
136 sal_uInt16 nSize
= InitializeRanges_Impl(m_pWhichRanges
, pArgs
, nWh1
, nWh2
, nNull
);
137 m_pItems
= new const SfxPoolItem
* [ nSize
];
138 memset(static_cast<void*>(m_pItems
), 0, sizeof(SfxPoolItem
*) * nSize
);
141 SfxItemSet::SfxItemSet(SfxItemPool
& rPool
,
142 USHORT_ARG nWh1
, USHORT_ARG nWh2
, USHORT_ARG nNull
, ...)
145 , m_pWhichRanges(nullptr)
148 assert(nWh1
<= nWh2
);
152 sal::static_int_cast
< sal_uInt16
>(nWh1
),
153 sal::static_int_cast
< sal_uInt16
>(nWh2
));
156 va_start( pArgs
, nNull
);
158 pArgs
, sal::static_int_cast
< sal_uInt16
>(nWh1
),
159 sal::static_int_cast
< sal_uInt16
>(nWh2
),
160 sal::static_int_cast
< sal_uInt16
>(nNull
));
165 void SfxItemSet::InitRanges_Impl(const sal_uInt16
*pWhichPairTable
)
168 const sal_uInt16
* pPtr
= pWhichPairTable
;
171 nCnt
+= ( *(pPtr
+1) - *pPtr
) + 1;
175 m_pItems
= new const SfxPoolItem
* [ nCnt
];
176 memset(static_cast<void*>(m_pItems
), 0, sizeof(SfxPoolItem
*) * nCnt
);
178 std::ptrdiff_t cnt
= pPtr
- pWhichPairTable
+1;
179 m_pWhichRanges
= new sal_uInt16
[ cnt
];
180 memcpy( m_pWhichRanges
, pWhichPairTable
, sizeof( sal_uInt16
) * cnt
);
183 SfxItemSet::SfxItemSet( SfxItemPool
& rPool
, const sal_uInt16
* pWhichPairTable
)
187 , m_pWhichRanges(nullptr)
190 // pWhichPairTable == 0 is for the SfxAllEnumItemSet
191 if ( pWhichPairTable
)
192 InitRanges_Impl(pWhichPairTable
);
195 SfxItemSet::SfxItemSet( const SfxItemSet
& rASet
)
196 : m_pPool( rASet
.m_pPool
)
197 , m_pParent( rASet
.m_pParent
)
198 , m_nCount( rASet
.m_nCount
)
200 // Calculate the attribute count
202 sal_uInt16
* pPtr
= rASet
.m_pWhichRanges
;
205 nCnt
+= ( *(pPtr
+1) - *pPtr
) + 1;
209 m_pItems
= new const SfxPoolItem
* [ nCnt
];
212 SfxItemArray ppDst
= m_pItems
, ppSrc
= rASet
.m_pItems
;
213 for( sal_uInt16 n
= nCnt
; n
; --n
, ++ppDst
, ++ppSrc
)
214 if ( 0 == *ppSrc
|| // Current Default?
215 IsInvalidItem(*ppSrc
) || // DontCare?
216 IsStaticDefaultItem(*ppSrc
) ) // Defaults that are not to be pooled?
217 // Just copy the pointer
219 else if (m_pPool
->IsItemFlag( **ppSrc
, SfxItemPoolFlags::POOLABLE
))
221 // Just copy the pointer and increase RefCount
225 else if ( !(*ppSrc
)->Which() )
226 *ppDst
= (*ppSrc
)->Clone();
228 // !IsPoolable() => assign via Pool
229 *ppDst
= &m_pPool
->Put( **ppSrc
);
231 // Copy the WhichRanges
232 std::ptrdiff_t cnt
= pPtr
- rASet
.m_pWhichRanges
+1;
233 m_pWhichRanges
= new sal_uInt16
[ cnt
];
234 memcpy( m_pWhichRanges
, rASet
.m_pWhichRanges
, sizeof( sal_uInt16
) * cnt
);
237 SfxItemSet::~SfxItemSet()
239 sal_uInt16 nCount
= TotalCount();
242 SfxItemArray ppFnd
= m_pItems
;
243 for( sal_uInt16 nCnt
= nCount
; nCnt
; --nCnt
, ++ppFnd
)
244 if( *ppFnd
&& !IsInvalidItem(*ppFnd
) )
246 if( !(*ppFnd
)->Which() )
249 // Still multiple references present, so just alter the RefCount
250 if ( 1 < (*ppFnd
)->GetRefCount() && !IsDefaultItem(*ppFnd
) )
251 (*ppFnd
)->ReleaseRef();
253 if ( !IsDefaultItem(*ppFnd
) )
255 m_pPool
->Remove( **ppFnd
);
261 if (m_pWhichRanges
!= m_pPool
->GetFrozenIdRanges())
262 delete[] m_pWhichRanges
;
263 m_pWhichRanges
= nullptr; // for invariant-testing
267 * Delete single Items or all Items (nWhich == 0)
269 sal_uInt16
SfxItemSet::ClearItem( sal_uInt16 nWhich
)
275 SfxItemArray ppFnd
= m_pItems
;
279 const sal_uInt16
* pPtr
= m_pWhichRanges
;
282 // Within this range?
283 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
286 ppFnd
+= nWhich
- *pPtr
;
289 // Due to the assertions in the sub calls, we need to do the following
291 const SfxPoolItem
*pItemToClear
= *ppFnd
;
294 if ( !IsInvalidItem(pItemToClear
) )
296 if ( nWhich
<= SFX_WHICH_MAX
)
298 const SfxPoolItem
& rNew
= m_pParent
299 ? m_pParent
->Get( nWhich
, true )
300 : m_pPool
->GetDefaultItem( nWhich
);
302 Changed( *pItemToClear
, rNew
);
304 if ( pItemToClear
->Which() )
305 m_pPool
->Remove( *pItemToClear
);
313 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
321 sal_uInt16
* pPtr
= m_pWhichRanges
;
324 for( nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
327 // Due to the assertions in the sub calls, we need to do this
329 const SfxPoolItem
*pItemToClear
= *ppFnd
;
332 if ( !IsInvalidItem(pItemToClear
) )
334 if ( nWhich
<= SFX_WHICH_MAX
)
336 const SfxPoolItem
& rNew
= m_pParent
337 ? m_pParent
->Get( nWhich
, true )
338 : m_pPool
->GetDefaultItem( nWhich
);
340 Changed( *pItemToClear
, rNew
);
344 // Take care of disabled items, too.
345 if (!pItemToClear
->m_nWhich
)
347 // item is disabled, delete it
352 // remove item from pool
353 m_pPool
->Remove( *pItemToClear
);
363 void SfxItemSet::ClearInvalidItems( bool bHardDefault
)
365 sal_uInt16
* pPtr
= m_pWhichRanges
;
366 SfxItemArray ppFnd
= m_pItems
;
370 for ( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
371 if ( IsInvalidItem(*ppFnd
) )
372 *ppFnd
= &m_pPool
->Put( m_pPool
->GetDefaultItem(nWhich
) );
378 for( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
379 if( IsInvalidItem(*ppFnd
) )
388 void SfxItemSet::InvalidateDefaultItems()
390 sal_uInt16
* pPtr
= m_pWhichRanges
;
391 SfxItemArray ppFnd
= m_pItems
;
395 for ( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
396 if (*ppFnd
&& *ppFnd
!= reinterpret_cast<SfxPoolItem
*>(-1)
397 && **ppFnd
== m_pPool
->GetDefaultItem(nWhich
))
399 m_pPool
->Remove( **ppFnd
);
400 *ppFnd
= reinterpret_cast<SfxPoolItem
*>(-1);
406 void SfxItemSet::InvalidateAllItems()
408 assert( !m_nCount
&& "There are still Items set" );
409 m_nCount
= TotalCount();
410 memset(static_cast<void*>(m_pItems
), -1, m_nCount
* sizeof(SfxPoolItem
*));
413 SfxItemState
SfxItemSet::GetItemState( sal_uInt16 nWhich
,
415 const SfxPoolItem
**ppItem
) const
417 // Find the range in which the Which is located
418 const SfxItemSet
* pAktSet
= this;
419 SfxItemState eRet
= SfxItemState::UNKNOWN
;
422 SfxItemArray ppFnd
= pAktSet
->m_pItems
;
423 const sal_uInt16
* pPtr
= pAktSet
->m_pWhichRanges
;
428 if ( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
431 ppFnd
+= nWhich
- *pPtr
;
434 eRet
= SfxItemState::DEFAULT
;
436 return eRet
; // Not present
437 break; // Keep searching in the parents!
440 if ( reinterpret_cast<SfxPoolItem
*>(-1) == *ppFnd
)
441 // Different ones are present
442 return SfxItemState::DONTCARE
;
444 if ( (*ppFnd
)->Type() == TYPE(SfxVoidItem
) )
445 return SfxItemState::DISABLED
;
451 return SfxItemState::SET
;
453 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
457 } while (bSrchInParent
&& nullptr != (pAktSet
= pAktSet
->m_pParent
));
461 bool SfxItemSet::HasItem(sal_uInt16 nWhich
, const SfxPoolItem
** ppItem
) const
463 bool bRet
= SfxItemState::SET
== GetItemState(nWhich
, true, ppItem
);
469 const SfxPoolItem
* SfxItemSet::Put( const SfxPoolItem
& rItem
, sal_uInt16 nWhich
)
472 return 0; //FIXME: Only because of Outliner bug
474 SfxItemArray ppFnd
= m_pItems
;
475 const sal_uInt16
* pPtr
= m_pWhichRanges
;
478 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
481 ppFnd
+= nWhich
- *pPtr
;
482 if( *ppFnd
) // Already one present
484 // Same Item already present?
485 if ( *ppFnd
== &rItem
)
488 // Will 'dontcare' or 'disabled' be overwritten with some real value?
489 if ( rItem
.Which() && ( IsInvalidItem(*ppFnd
) || !(*ppFnd
)->Which() ) )
491 *ppFnd
= &m_pPool
->Put( rItem
, nWhich
);
495 // Turns into disabled?
498 *ppFnd
= rItem
.Clone(m_pPool
);
503 // Same value already present?
504 if ( rItem
== **ppFnd
)
507 // Add the new one, remove the old one
508 const SfxPoolItem
& rNew
= m_pPool
->Put( rItem
, nWhich
);
509 const SfxPoolItem
* pOld
= *ppFnd
;
511 if(nWhich
<= SFX_WHICH_MAX
)
512 Changed( *pOld
, rNew
);
513 m_pPool
->Remove( *pOld
);
520 *ppFnd
= rItem
.Clone(m_pPool
);
522 const SfxPoolItem
& rNew
= m_pPool
->Put( rItem
, nWhich
);
524 if (nWhich
<= SFX_WHICH_MAX
)
526 const SfxPoolItem
& rOld
= m_pParent
527 ? m_pParent
->Get( nWhich
, true )
528 : m_pPool
->GetDefaultItem( nWhich
);
529 Changed( rOld
, rNew
);
533 SFX_ASSERT( !m_pPool
->IsItemFlag(nWhich
, SfxItemPoolFlags::POOLABLE
) ||
534 rItem
.ISA(SfxSetItem
) || **ppFnd
== rItem
,
535 nWhich
, "putted Item unequal" );
538 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
544 bool SfxItemSet::Put( const SfxItemSet
& rSet
, bool bInvalidAsDefault
)
549 SfxItemArray ppFnd
= rSet
.m_pItems
;
550 const sal_uInt16
* pPtr
= rSet
.m_pWhichRanges
;
553 for ( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
556 if ( IsInvalidItem( *ppFnd
) )
558 if ( bInvalidAsDefault
)
559 bRet
|= 0 != ClearItem( nWhich
);
560 // FIXME: Caused a SEGFAULT on non Windows-platforms:
561 // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
563 InvalidateItem( nWhich
);
566 bRet
|= 0 != Put( **ppFnd
, nWhich
);
575 * This method takes the Items from the 'rSet' and adds to '*this'.
576 * Which ranges in '*this' that are non-existent in 'rSet' will not
577 * be altered. The Which range of '*this' is also not changed.
579 * Items set in 'rSet' are also set in '*this'.
580 * Default (0 pointer) and Invalid (-1 pointer) Items are processed
581 * according to their parameter 'eDontCareAs' and 'eDefaultAs':
583 * SfxItemState::SET: Hard set to the default of the Pool
584 * SfxItemState::DEFAULT: Deleted (0 pointer)
585 * SfxItemState::DONTCARE: Invalid (-1 pointer)
587 * NB: All other values for 'eDontCareAs' and 'eDefaultAs' are invalid
589 void SfxItemSet::PutExtended
591 const SfxItemSet
& rSet
, // Source of the Items to be put
592 SfxItemState eDontCareAs
, // What will happen to the DontCare Items
593 SfxItemState eDefaultAs
// What will happen to the Default Items
596 // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
597 SfxItemArray ppFnd
= rSet
.m_pItems
;
598 const sal_uInt16
* pPtr
= rSet
.m_pWhichRanges
;
601 for ( sal_uInt16 nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
604 if ( IsInvalidItem( *ppFnd
) )
606 // Item ist DontCare:
607 switch ( eDontCareAs
)
609 case SfxItemState::SET
:
610 Put( rSet
.GetPool()->GetDefaultItem(nWhich
), nWhich
);
613 case SfxItemState::DEFAULT
:
617 case SfxItemState::DONTCARE
:
618 InvalidateItem( nWhich
);
622 assert(!"invalid Argument for eDontCareAs");
627 Put( **ppFnd
, nWhich
);
632 switch ( eDefaultAs
)
634 case SfxItemState::SET
:
635 Put( rSet
.GetPool()->GetDefaultItem(nWhich
), nWhich
);
638 case SfxItemState::DEFAULT
:
642 case SfxItemState::DONTCARE
:
643 InvalidateItem( nWhich
);
647 assert(!"invalid Argument for eDefaultAs");
655 * Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
656 * items which are new ranges too.
658 void SfxItemSet::MergeRange( sal_uInt16 nFrom
, sal_uInt16 nTo
)
660 // special case: exactly one sal_uInt16 which is already included?
661 SfxItemState eItemState
= GetItemState(nFrom
, false);
662 if ( nFrom
== nTo
&& ( eItemState
== SfxItemState::DEFAULT
|| eItemState
== SfxItemState::SET
) )
666 SfxUShortRanges
aRanges( m_pWhichRanges
);
667 aRanges
+= SfxUShortRanges( nFrom
, nTo
);
668 SetRanges( aRanges
);
672 * Modifies the ranges of settable items. Keeps state of items which
673 * are new ranges too.
675 void SfxItemSet::SetRanges( const sal_uInt16
*pNewRanges
)
678 if (m_pWhichRanges
== pNewRanges
)
680 const sal_uInt16
* pOld
= m_pWhichRanges
;
681 const sal_uInt16
* pNew
= pNewRanges
;
682 while ( *pOld
== *pNew
)
684 if ( !*pOld
&& !*pNew
)
689 // create new item-array (by iterating through all new ranges)
690 sal_uLong nSize
= Capacity_Impl(pNewRanges
);
691 SfxItemArray aNewItems
= new const SfxPoolItem
* [ nSize
];
692 sal_uInt16 nNewCount
= 0;
694 memset( aNewItems
, 0, nSize
* sizeof( SfxPoolItem
* ) );
698 for ( const sal_uInt16
*pRange
= pNewRanges
; *pRange
; pRange
+= 2 )
700 // iterate through all ids in the range
701 for ( sal_uInt16 nWID
= *pRange
; nWID
<= pRange
[1]; ++nWID
, ++n
)
703 // direct move of pointer (not via pool)
704 SfxItemState eState
= GetItemState( nWID
, false, aNewItems
+n
);
705 if ( SfxItemState::SET
== eState
)
707 // increment new item count and possibly increment ref count
709 aNewItems
[n
]->AddRef();
711 else if ( SfxItemState::DISABLED
== eState
)
713 // put "disabled" item
715 aNewItems
[n
] = new SfxVoidItem(0);
717 else if ( SfxItemState::DONTCARE
== eState
)
720 aNewItems
[n
] = reinterpret_cast<SfxPoolItem
*>(-1);
730 sal_uInt16 nOldTotalCount
= TotalCount();
731 for ( sal_uInt16 nItem
= 0; nItem
< nOldTotalCount
; ++nItem
)
733 const SfxPoolItem
*pItem
= m_pItems
[nItem
];
734 if ( pItem
&& !IsInvalidItem(pItem
) && pItem
->Which() )
735 m_pPool
->Remove(*pItem
);
739 // replace old items-array and ranges
741 m_pItems
= aNewItems
;
742 m_nCount
= nNewCount
;
744 if( pNewRanges
== GetPool()->GetFrozenIdRanges() )
746 delete[] m_pWhichRanges
;
747 m_pWhichRanges
= const_cast<sal_uInt16
*>(pNewRanges
);
751 sal_uInt16 nCount
= Count_Impl(pNewRanges
) + 1;
752 if (m_pWhichRanges
!= m_pPool
->GetFrozenIdRanges())
753 delete[] m_pWhichRanges
;
754 m_pWhichRanges
= new sal_uInt16
[ nCount
];
755 memcpy( m_pWhichRanges
, pNewRanges
, sizeof( sal_uInt16
) * nCount
);
760 * The SfxItemSet takes over exactly those SfxPoolItems that are
761 * set in rSet and are in their own Which range. All others are removed.
762 * The SfxItemPool is retained, such that SfxPoolItems that have been
763 * taken over, are moved from the rSet's SfxItemPool to the SfxItemPool
766 * SfxPoolItems in rSet, for which holds 'IsInvalidItem() == true' are
767 * taken over as invalid items.
770 * SfxPoolItems have been taken over
773 * No SfxPoolItems have been taken over, because
774 * e.g. the Which ranges of SfxItemSets are not intersecting
775 * or the intersection does not contain SfxPoolItems that are
780 const SfxItemSet
& rSet
, /* The SfxItemSet, whose SfxPoolItems are
781 to been taken over */
783 bool bDeep
/* true (default)
785 The SfxPoolItems from the parents that may
786 be present in rSet, are also taken over into
790 The SfxPoolItems from the parents of
791 rSet are not taken into account */
799 SfxWhichIter
aIter(*this);
800 sal_uInt16 nWhich
= aIter
.FirstWhich();
803 const SfxPoolItem
* pItem
;
804 if( SfxItemState::SET
== rSet
.GetItemState( nWhich
, true, &pItem
) )
805 bRet
|= 0 != Put( *pItem
, pItem
->Which() );
806 nWhich
= aIter
.NextWhich();
810 bRet
= Put(rSet
, false);
816 * This method eases accessing single Items in the SfxItemSet.
817 * Type checking is done via assertion, which makes client code
818 * much more readable.
820 * The PRODUCT version returns 0, if the Item found is not of the
823 * @returns 0 if the ItemSet does not contain an Item with the Id 'nWhich'
825 const SfxPoolItem
* SfxItemSet::GetItem
827 sal_uInt16 nId
, // SlotId or the Item's WhichId
828 bool bSrchInParent
, // sal_True: also search in Parent ItemSets
829 TypeId aItemType
// != 0 => RTTI check using assertion
832 // Convert to WhichId
833 sal_uInt16 nWhich
= GetPool()->GetWhich(nId
);
835 // Is the Item set or 'bDeep == true' available?
836 const SfxPoolItem
*pItem
= 0;
837 SfxItemState eState
= GetItemState( nWhich
, bSrchInParent
, &pItem
);
838 if ( bSrchInParent
&& SfxItemState::DEFAULT
== eState
&&
839 nWhich
<= SFX_WHICH_MAX
)
841 pItem
= &m_pPool
->GetDefaultItem(nWhich
);
846 // Does the type match?
847 if ( !aItemType
|| pItem
->IsA(aItemType
) )
851 assert(!"invalid argument type");
854 // No Item of wrong type found
858 const SfxPoolItem
& SfxItemSet::Get( sal_uInt16 nWhich
, bool bSrchInParent
) const
860 // Search the Range in which the Which is located in:
861 const SfxItemSet
* pAktSet
= this;
864 if( pAktSet
->Count() )
866 SfxItemArray ppFnd
= pAktSet
->m_pItems
;
867 const sal_uInt16
* pPtr
= pAktSet
->m_pWhichRanges
;
870 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
873 ppFnd
+= nWhich
- *pPtr
;
876 if( reinterpret_cast<SfxPoolItem
*>(-1) == *ppFnd
) {
877 //FIXME: The following code is duplicated further down
878 SFX_ASSERT(m_pPool
, nWhich
, "no Pool, but status is ambiguous");
879 //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
881 return m_pPool
->GetDefaultItem( nWhich
);
884 const SfxPoolItem
*pItem
= *ppFnd
;
885 if ( pItem
->ISA(SfxVoidItem
) || !pItem
->Which() )
886 SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item");
890 break; // Continue with Parent
892 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
896 //TODO: Search until end of Range: What are we supposed to do now? To the Parent or Default??
897 // if( !*pPtr ) // Until the end of the search Range?
899 } while (bSrchInParent
&& nullptr != (pAktSet
= pAktSet
->m_pParent
));
901 // Get the Default from the Pool and return
902 SFX_ASSERT(m_pPool
, nWhich
, "no Pool, but status is ambiguous");
903 const SfxPoolItem
*pItem
= &m_pPool
->GetDefaultItem( nWhich
);
908 * Notification callback
910 void SfxItemSet::Changed( const SfxPoolItem
&, const SfxPoolItem
& )
914 sal_uInt16
SfxItemSet::TotalCount() const
917 sal_uInt16
* pPtr
= m_pWhichRanges
;
920 nRet
+= ( *(pPtr
+1) - *pPtr
) + 1;
927 * Only retain the Items that are also present in rSet
928 * (nevermind their value).
930 void SfxItemSet::Intersect( const SfxItemSet
& rSet
)
932 assert(m_pPool
&& "Not implemented without Pool");
933 if( !Count() ) // None set?
936 // Delete all Items not contained in rSet
939 ClearItem(); // Delete everything
943 // Test whether the Which Ranges are different
945 sal_uInt16
* pWh1
= m_pWhichRanges
;
946 sal_uInt16
* pWh2
= rSet
.m_pWhichRanges
;
947 sal_uInt16 nSize
= 0;
949 for( sal_uInt16 n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
957 nSize
+= ( *(pWh1
) - *(pWh1
-1) ) + 1;
959 bEqual
= *pWh1
== *pWh2
; // Also check for 0
961 // If the Ranges are identical, we can easily process it
964 SfxItemArray ppFnd1
= m_pItems
;
965 SfxItemArray ppFnd2
= rSet
.m_pItems
;
967 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
968 if( *ppFnd1
&& !*ppFnd2
)
971 if( !IsInvalidItem( *ppFnd1
) )
973 sal_uInt16 nWhich
= (*ppFnd1
)->Which();
974 if(nWhich
<= SFX_WHICH_MAX
)
976 const SfxPoolItem
& rNew
= m_pParent
977 ? m_pParent
->Get( nWhich
, true )
978 : m_pPool
->GetDefaultItem( nWhich
);
980 Changed( **ppFnd1
, rNew
);
982 m_pPool
->Remove( **ppFnd1
);
990 SfxItemIter
aIter( *this );
991 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
994 sal_uInt16 nWhich
= IsInvalidItem( pItem
)
995 ? GetWhichByPos( aIter
.GetCurPos() )
997 if( SfxItemState::UNKNOWN
== rSet
.GetItemState( nWhich
, false ) )
998 ClearItem( nWhich
); // Delete
999 if( aIter
.IsAtEnd() )
1001 pItem
= aIter
.NextItem();
1006 void SfxItemSet::Differentiate( const SfxItemSet
& rSet
)
1008 if( !Count() || !rSet
.Count() )// None set?
1011 // Test whether the Which Ranges are different
1013 sal_uInt16
* pWh1
= m_pWhichRanges
;
1014 sal_uInt16
* pWh2
= rSet
.m_pWhichRanges
;
1015 sal_uInt16 nSize
= 0;
1017 for( sal_uInt16 n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1019 if( *pWh1
!= *pWh2
)
1025 nSize
+= ( *(pWh1
) - *(pWh1
-1) ) + 1;
1027 bEqual
= *pWh1
== *pWh2
; // Also test for 0
1029 // If the Ranges are identical, we can easily process it
1032 SfxItemArray ppFnd1
= m_pItems
;
1033 SfxItemArray ppFnd2
= rSet
.m_pItems
;
1035 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1036 if( *ppFnd1
&& *ppFnd2
)
1039 if( !IsInvalidItem( *ppFnd1
) )
1041 sal_uInt16 nWhich
= (*ppFnd1
)->Which();
1042 if(nWhich
<= SFX_WHICH_MAX
)
1044 const SfxPoolItem
& rNew
= m_pParent
1045 ? m_pParent
->Get( nWhich
, true )
1046 : m_pPool
->GetDefaultItem( nWhich
);
1048 Changed( **ppFnd1
, rNew
);
1050 m_pPool
->Remove( **ppFnd1
);
1058 SfxItemIter
aIter( *this );
1059 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1062 sal_uInt16 nWhich
= IsInvalidItem( pItem
)
1063 ? GetWhichByPos( aIter
.GetCurPos() )
1065 if( SfxItemState::SET
== rSet
.GetItemState( nWhich
, false ) )
1066 ClearItem( nWhich
); // Delete
1067 if( aIter
.IsAtEnd() )
1069 pItem
= aIter
.NextItem();
1076 * Decision table for MergeValue(s)
1079 * 1. If the Which value in the 1st set is "unknown", there's never any action
1080 * 2. If the Which value in the 2nd set is "unknown", it's made the "default"
1081 * 3. For comparisons the values of the "default" Items are take into account
1083 * 1st Item 2nd Item Values bIgnoreDefs Remove Assign Add
1085 * set set == sal_False - - -
1086 * default set == sal_False - - -
1087 * dontcare set == sal_False - - -
1088 * unknown set == sal_False - - -
1089 * set default == sal_False - - -
1090 * default default == sal_False - - -
1091 * dontcare default == sal_False - - -
1092 * unknown default == sal_False - - -
1093 * set dontcare == sal_False 1st Item -1 -
1094 * default dontcare == sal_False - -1 -
1095 * dontcare dontcare == sal_False - - -
1096 * unknown dontcare == sal_False - - -
1097 * set unknown == sal_False 1st Item -1 -
1098 * default unknown == sal_False - - -
1099 * dontcare unknown == sal_False - - -
1100 * unknown unknown == sal_False - - -
1102 * set set != sal_False 1st Item -1 -
1103 * default set != sal_False - -1 -
1104 * dontcare set != sal_False - - -
1105 * unknown set != sal_False - - -
1106 * set default != sal_False 1st Item -1 -
1107 * default default != sal_False - - -
1108 * dontcare default != sal_False - - -
1109 * unknown default != sal_False - - -
1110 * set dontcare != sal_False 1st Item -1 -
1111 * default dontcare != sal_False - -1 -
1112 * dontcare dontcare != sal_False - - -
1113 * unknown dontcare != sal_False - - -
1114 * set unknown != sal_False 1st Item -1 -
1115 * default unknown != sal_False - - -
1116 * dontcare unknown != sal_False - - -
1117 * unknown unknown != sal_False - - -
1119 * set set == sal_True - - -
1120 * default set == sal_True - 2nd Item 2nd Item
1121 * dontcare set == sal_True - - -
1122 * unknown set == sal_True - - -
1123 * set default == sal_True - - -
1124 * default default == sal_True - - -
1125 * dontcare default == sal_True - - -
1126 * unknown default == sal_True - - -
1127 * set dontcare == sal_True - - -
1128 * default dontcare == sal_True - -1 -
1129 * dontcare dontcare == sal_True - - -
1130 * unknown dontcare == sal_True - - -
1131 * set unknown == sal_True - - -
1132 * default unknown == sal_True - - -
1133 * dontcare unknown == sal_True - - -
1134 * unknown unknown == sal_True - - -
1136 * set set != sal_True 1st Item -1 -
1137 * default set != sal_True - 2nd Item 2nd Item
1138 * dontcare set != sal_True - - -
1139 * unknown set != sal_True - - -
1140 * set default != sal_True - - -
1141 * default default != sal_True - - -
1142 * dontcare default != sal_True - - -
1143 * unknown default != sal_True - - -
1144 * set dontcare != sal_True 1st Item -1 -
1145 * default dontcare != sal_True - -1 -
1146 * dontcare dontcare != sal_True - - -
1147 * unknown dontcare != sal_True - - -
1148 * set unknown != sal_True - - -
1149 * default unknown != sal_True - - -
1150 * dontcare unknown != sal_True - - -
1151 * unknown unknown != sal_True - - -
1153 static void MergeItem_Impl( SfxItemPool
*_pPool
, sal_uInt16
&rCount
,
1154 const SfxPoolItem
**ppFnd1
, const SfxPoolItem
*pFnd2
,
1155 bool bIgnoreDefaults
)
1157 assert(ppFnd1
!= 0 && "Merging to 0-Item");
1159 // 1st Item is Default?
1162 if ( IsInvalidItem(pFnd2
) )
1163 // Decision table: default, dontcare, doesn't matter, doesn't matter
1164 *ppFnd1
= reinterpret_cast<SfxPoolItem
*>(-1);
1166 else if ( pFnd2
&& !bIgnoreDefaults
&&
1167 _pPool
->GetDefaultItem(pFnd2
->Which()) != *pFnd2
)
1168 // Decision table: default, set, !=, sal_False
1169 *ppFnd1
= reinterpret_cast<SfxPoolItem
*>(-1);
1171 else if ( pFnd2
&& bIgnoreDefaults
)
1172 // Decision table: default, set, doesn't matter, sal_True
1173 *ppFnd1
= &_pPool
->Put( *pFnd2
);
1180 else if ( !IsInvalidItem(*ppFnd1
) )
1184 // 2nd Item is Default
1185 if ( !bIgnoreDefaults
&&
1186 **ppFnd1
!= _pPool
->GetDefaultItem((*ppFnd1
)->Which()) )
1188 // Decision table: set, default, !=, sal_False
1189 _pPool
->Remove( **ppFnd1
);
1190 *ppFnd1
= reinterpret_cast<SfxPoolItem
*>(-1);
1193 else if ( IsInvalidItem(pFnd2
) )
1195 // 2nd Item is dontcare
1196 if ( !bIgnoreDefaults
||
1197 **ppFnd1
!= _pPool
->GetDefaultItem( (*ppFnd1
)->Which()) )
1199 // Decision table: set, dontcare, doesn't matter, sal_False
1200 // or: set, dontcare, !=, sal_True
1201 _pPool
->Remove( **ppFnd1
);
1202 *ppFnd1
= reinterpret_cast<SfxPoolItem
*>(-1);
1208 if ( **ppFnd1
!= *pFnd2
)
1210 // Decision table: set, set, !=, doesn't matter
1211 _pPool
->Remove( **ppFnd1
);
1212 *ppFnd1
= reinterpret_cast<SfxPoolItem
*>(-1);
1218 void SfxItemSet::MergeValues( const SfxItemSet
& rSet
, bool bIgnoreDefaults
)
1220 // WARNING! When making changes/fixing bugs, always update the table above!!
1221 assert( GetPool() == rSet
.GetPool() && "MergeValues with different Pools" );
1223 // Test if the which Ranges are different
1225 sal_uInt16
* pWh1
= m_pWhichRanges
;
1226 sal_uInt16
* pWh2
= rSet
.m_pWhichRanges
;
1227 sal_uInt16 nSize
= 0;
1229 for( sal_uInt16 n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1231 if( *pWh1
!= *pWh2
)
1237 nSize
+= ( *(pWh1
) - *(pWh1
-1) ) + 1;
1239 bEqual
= *pWh1
== *pWh2
; // Also check for 0
1241 // If the Ranges match, they are easier to process!
1244 SfxItemArray ppFnd1
= m_pItems
;
1245 SfxItemArray ppFnd2
= rSet
.m_pItems
;
1247 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1248 MergeItem_Impl(m_pPool
, m_nCount
, ppFnd1
, *ppFnd2
, bIgnoreDefaults
);
1252 SfxWhichIter
aIter( rSet
);
1254 while( 0 != ( nWhich
= aIter
.NextWhich() ) )
1256 const SfxPoolItem
* pItem
= 0;
1257 rSet
.GetItemState( nWhich
, true, &pItem
);
1260 // Not set, so default
1261 if ( !bIgnoreDefaults
)
1262 MergeValue( rSet
.GetPool()->GetDefaultItem( nWhich
), bIgnoreDefaults
);
1264 else if( IsInvalidItem( pItem
) )
1266 InvalidateItem( nWhich
);
1268 MergeValue( *pItem
, bIgnoreDefaults
);
1273 void SfxItemSet::MergeValue( const SfxPoolItem
& rAttr
, bool bIgnoreDefaults
)
1275 SfxItemArray ppFnd
= m_pItems
;
1276 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1277 const sal_uInt16 nWhich
= rAttr
.Which();
1281 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1283 ppFnd
+= nWhich
- *pPtr
;
1284 MergeItem_Impl(m_pPool
, m_nCount
, ppFnd
, &rAttr
, bIgnoreDefaults
);
1287 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1292 void SfxItemSet::InvalidateItem( sal_uInt16 nWhich
)
1294 SfxItemArray ppFnd
= m_pItems
;
1295 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1298 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1301 ppFnd
+= nWhich
- *pPtr
;
1303 if( *ppFnd
) // Set for me
1305 if( reinterpret_cast<SfxPoolItem
*>(-1) != *ppFnd
) // Not yet dontcare!
1307 m_pPool
->Remove( **ppFnd
);
1308 *ppFnd
= reinterpret_cast<SfxPoolItem
*>(-1);
1313 *ppFnd
= reinterpret_cast<SfxPoolItem
*>(-1);
1318 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1323 sal_uInt16
SfxItemSet::GetWhichByPos( sal_uInt16 nPos
) const
1326 sal_uInt16
* pPtr
= m_pWhichRanges
;
1329 n
= ( *(pPtr
+1) - *pPtr
) + 1;
1331 return *(pPtr
)+nPos
;
1340 * Saves the SfxItemSet instance to the supplied Stream.
1341 * The surrogates as well as the ones with 'bDirect == true' are saved
1342 * to the stream in the following way:
1344 * sal_uInt16 ... Count of the set Items
1345 * Count* m_pPool->StoreItem()
1347 * @see SfxItemPool::StoreItem() const
1348 * @see SfxItemSet::Load(SvStream&,bool,const SfxItemPool*)
1350 SvStream
&SfxItemSet::Store
1352 SvStream
& rStream
, // Target stream for normal Items
1353 bool bDirect
/* true: Save Items directly
1354 false: Surrogates */
1359 // Remember position of the count (to be able to correct it, if need be)
1360 sal_uLong nCountPos
= rStream
.Tell();
1361 rStream
.WriteUInt16( m_nCount
);
1363 // If there's nothing to save, don't construct an ItemIter
1366 // Keep record of how many Items are really saved
1367 sal_uInt16 nWrittenCount
= 0; // Count of Items streamed in 'rStream'
1369 // Iterate over all set Items
1370 SfxItemIter
aIter(*this);
1371 for ( const SfxPoolItem
*pItem
= aIter
.FirstItem();
1373 pItem
= aIter
.NextItem() )
1375 // Let Items (if need be as a Surrogate) be saved via Pool
1376 SAL_WARN_IF(IsInvalidItem(pItem
), "svl.items", "can't store invalid items");
1377 if ( !IsInvalidItem(pItem
) &&
1378 m_pPool
->StoreItem( rStream
, *pItem
, bDirect
) )
1379 // Item was streamed in 'rStream'
1383 // Fewer written than read (e.g. old format)
1384 if (nWrittenCount
!= m_nCount
)
1386 // Store real count in the stream
1387 sal_uLong nPos
= rStream
.Tell();
1388 rStream
.Seek( nCountPos
);
1389 rStream
.WriteUInt16( nWrittenCount
);
1390 rStream
.Seek( nPos
);
1398 * This method loads an SfxItemSet from a stream.
1399 * If the SfxItemPool was loaded without RefCounts the loaded Item
1400 * references are counted, else we assume the they were accounted for
1401 * when loadig the SfxItemPool.
1403 * @see SfxItemSet::Store(Stream&,bool) const
1405 SvStream
&SfxItemSet::Load
1407 SvStream
& rStream
, // Stream we're loading from
1409 bool bDirect
, /* true
1410 Items are directly read form the stream
1411 and not via Surrogates
1414 Items are read via Surrogates */
1416 const SfxItemPool
* pRefPool
/* Pool that can resolve the Surrogates
1417 (e.g. when inserting documents) */
1422 // No RefPool => Resolve Surrogates with ItemSet's Pool
1426 // Load Item count and as many Items
1427 sal_uInt16 nCount
= 0;
1428 rStream
.ReadUInt16( nCount
);
1430 const size_t nMinRecordSize
= sizeof(sal_uInt16
) * 2;
1431 const size_t nMaxRecords
= rStream
.remainingSize() / nMinRecordSize
;
1432 if (nCount
> nMaxRecords
)
1434 SAL_WARN("svl", "Parsing error: " << nMaxRecords
<<
1435 " max possible entries, but " << nCount
<< " claimed, truncating");
1436 nCount
= nMaxRecords
;
1439 for ( sal_uInt16 i
= 0; i
< nCount
; ++i
)
1441 // Load Surrogate/Item and resolve Surrogate
1442 const SfxPoolItem
*pItem
=
1443 m_pPool
->LoadItem( rStream
, bDirect
, pRefPool
);
1445 // Did we load an Item or resolve a Surrogate?
1448 // Find position for Item pointer in the set
1449 sal_uInt16 nWhich
= pItem
->Which();
1450 SfxItemArray ppFnd
= m_pItems
;
1451 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1455 if ( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1457 // Remember Item pointer in the set
1458 ppFnd
+= nWhich
- *pPtr
;
1459 SFX_ASSERT( !*ppFnd
, nWhich
, "Item is present twice");
1465 // In the range array and Item array to the next Which range
1466 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1475 bool SfxItemSet::operator==(const SfxItemSet
&rCmp
) const
1477 // Values we can get quickly need to be the same
1478 if ( m_pParent
!= rCmp
.m_pParent
||
1479 m_pPool
!= rCmp
.m_pPool
||
1480 Count() != rCmp
.Count() )
1483 // Counting Ranges takes longer; they also need to be the same, however
1484 sal_uInt16 nCount1
= TotalCount();
1485 sal_uInt16 nCount2
= rCmp
.TotalCount();
1486 if ( nCount1
!= nCount2
)
1489 // Are the Ranges themselves unequal?
1490 for (sal_uInt16 nRange
= 0; m_pWhichRanges
[nRange
]; nRange
+= 2)
1492 if (m_pWhichRanges
[nRange
] != rCmp
.m_pWhichRanges
[nRange
] ||
1493 m_pWhichRanges
[nRange
+1] != rCmp
.m_pWhichRanges
[nRange
+1])
1495 // We must use the slow method then
1496 SfxWhichIter
aIter( *this );
1497 for ( sal_uInt16 nWh
= aIter
.FirstWhich();
1499 nWh
= aIter
.NextWhich() )
1501 // If the pointer of the poolable Items are unequal, the Items must match
1502 const SfxPoolItem
*pItem1
= 0, *pItem2
= 0;
1503 if ( GetItemState( nWh
, false, &pItem1
) !=
1504 rCmp
.GetItemState( nWh
, false, &pItem2
) ||
1505 ( pItem1
!= pItem2
&&
1506 ( !pItem1
|| IsInvalidItem(pItem1
) ||
1507 (m_pPool
->IsItemFlag(*pItem1
, SfxItemPoolFlags::POOLABLE
) &&
1508 *pItem1
!= *pItem2
) ) ) )
1516 // Are all pointers the same?
1517 if (0 == memcmp( m_pItems
, rCmp
.m_pItems
, nCount1
* sizeof(m_pItems
[0]) ))
1520 // We need to compare each one separately then
1521 const SfxPoolItem
**ppItem1
= m_pItems
;
1522 const SfxPoolItem
**ppItem2
= rCmp
.m_pItems
;
1523 for ( sal_uInt16 nPos
= 0; nPos
< nCount1
; ++nPos
)
1525 // If the pointers of the poolable Items are not the same, the Items
1527 if ( *ppItem1
!= *ppItem2
&&
1528 ( ( !*ppItem1
|| !*ppItem2
) ||
1529 ( IsInvalidItem(*ppItem1
) || IsInvalidItem(*ppItem2
) ) ||
1530 (m_pPool
->IsItemFlag(**ppItem1
, SfxItemPoolFlags::POOLABLE
)) ||
1531 **ppItem1
!= **ppItem2
) )
1541 SfxItemSet
*SfxItemSet::Clone(bool bItems
, SfxItemPool
*pToPool
) const
1543 if (pToPool
&& pToPool
!= m_pPool
)
1545 SfxItemSet
*pNewSet
= new SfxItemSet(*pToPool
, m_pWhichRanges
);
1548 SfxWhichIter
aIter(*pNewSet
);
1549 sal_uInt16 nWhich
= aIter
.FirstWhich();
1552 const SfxPoolItem
* pItem
;
1553 if ( SfxItemState::SET
== GetItemState( nWhich
, false, &pItem
) )
1554 pNewSet
->Put( *pItem
, pItem
->Which() );
1555 nWhich
= aIter
.NextWhich();
1562 ? new SfxItemSet(*this)
1563 : new SfxItemSet(*m_pPool
, m_pWhichRanges
);
1566 void SfxItemSet::PutDirect(const SfxPoolItem
&rItem
)
1568 SfxItemArray ppFnd
= m_pItems
;
1569 const sal_uInt16
* pPtr
= m_pWhichRanges
;
1570 const sal_uInt16 nWhich
= rItem
.Which();
1572 IsPoolDefaultItem(&rItem
) || m_pPool
->GetSurrogate(&rItem
);
1573 // Only cause assertion in the callees
1577 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1580 ppFnd
+= nWhich
- *pPtr
;
1581 const SfxPoolItem
* pOld
= *ppFnd
;
1582 if( pOld
) // One already present
1584 if( rItem
== **ppFnd
)
1585 return; // Already present!
1586 m_pPool
->Remove( *pOld
);
1592 if( IsPoolDefaultItem(&rItem
) )
1593 *ppFnd
= &m_pPool
->Put( rItem
);
1597 if( !IsStaticDefaultItem( &rItem
) )
1603 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1608 sal_Int32
SfxItemSet::getHash() const
1610 return stringify().hashCode();
1613 OString
SfxItemSet::stringify() const
1615 SvMemoryStream aStream
;
1616 SfxItemSet
aSet(*this);
1617 aSet
.InvalidateDefaultItems();
1618 aSet
.Store(aStream
, true);
1621 static_cast<char const *>(aStream
.GetData()), aStream
.GetEndOfData());
1624 void SfxItemSet::dumpAsXml(xmlTextWriterPtr pWriter
) const
1626 xmlTextWriterStartElement(pWriter
, BAD_CAST("sfxItemSet"));
1627 SfxItemIter
aIter(*this);
1628 for (const SfxPoolItem
* pItem
= aIter
.FirstItem(); pItem
; pItem
= aIter
.NextItem())
1629 pItem
->dumpAsXml(pWriter
);
1630 xmlTextWriterEndElement(pWriter
);
1634 // ----------------------------------------------- class SfxAllItemSet
1636 SfxAllItemSet::SfxAllItemSet( SfxItemPool
&rPool
)
1637 : SfxItemSet(rPool
, (const sal_uInt16
*) 0),
1641 // Initially no Items
1644 // Allocate nInitCount pairs at USHORTs for Ranges
1645 m_pWhichRanges
= new sal_uInt16
[ nInitCount
+ 1 ];
1646 memset( m_pWhichRanges
, 0, (nInitCount
+ 1) * sizeof(sal_uInt16
) );
1649 SfxAllItemSet::SfxAllItemSet(const SfxItemSet
&rCopy
)
1650 : SfxItemSet(rCopy
),
1657 * Explicitly define this ctor to avoid auto-generation by the compiler.
1658 * The compiler does not take the ctor with the 'const SfxItemSet&'!
1660 SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet
&rCopy
)
1661 : SfxItemSet(rCopy
),
1668 * This internal function creates a new WhichRanges array, which is copied
1669 * from the 'nOldSize'-USHORTs long 'pUS'. It has new USHORTs at the end instead
1671 * The terminating sal_uInt16 with the '0' is neither accounted for in 'nOldSize'
1672 * nor in 'nIncr', but always explicitly added.
1674 * @returns the new WhichRanges array (the old 'pUS' is freed)
1676 static sal_uInt16
*AddRanges_Impl(
1677 sal_uInt16
*pUS
, std::ptrdiff_t nOldSize
, sal_uInt16 nIncr
)
1679 // Create new WhichRanges array
1680 sal_uInt16
*pNew
= new sal_uInt16
[ nOldSize
+ nIncr
+ 1 ];
1682 // Take over the old Ranges
1683 memcpy( pNew
, pUS
, nOldSize
* sizeof(sal_uInt16
) );
1685 // Initialize the new one to 0
1686 memset( pNew
+ nOldSize
, 0, ( nIncr
+ 1 ) * sizeof(sal_uInt16
) );
1688 // Free the old array
1695 * This internal function creates a new ItemArray, which is copied from 'pItems',
1696 * but has room for a new ItemPointer at 'nPos'.
1698 * @returns the new ItemArray (the old 'pItems' is freed)
1700 static SfxItemArray
AddItem_Impl(SfxItemArray pItems
, sal_uInt16 nOldSize
, sal_uInt16 nPos
)
1702 // Create new ItemArray
1703 SfxItemArray pNew
= new const SfxPoolItem
*[nOldSize
+1];
1705 // Was there one before?
1708 // Copy all Items before nPos
1710 memcpy( (void*) pNew
, pItems
, nPos
* sizeof(SfxPoolItem
*) );
1712 // Copy all Items after nPos
1713 if ( nPos
< nOldSize
)
1714 memcpy( (void*) (pNew
+ nPos
+ 1), pItems
+ nPos
,
1715 (nOldSize
-nPos
) * sizeof(SfxPoolItem
*) );
1718 // Initialize new Item
1721 // Free old ItemArray
1728 * Putting with automatic extension of the WhichId with the ID of the Item.
1730 const SfxPoolItem
* SfxAllItemSet::Put( const SfxPoolItem
& rItem
, sal_uInt16 nWhich
)
1732 sal_uInt16 nPos
= 0; // Position for 'rItem' in 'm_pItems'
1733 const sal_uInt16 nItemCount
= TotalCount();
1735 // Let's see first whether there's a suitable Range already
1736 sal_uInt16
*pPtr
= m_pWhichRanges
;
1739 // WhichId is within this Range?
1740 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1743 nPos
+= nWhich
- *pPtr
;
1747 // Carry over the position of the Item in m_pItems
1748 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
1750 // To the next Range
1754 // WhichId not yet present?
1757 // Let's see if we can attach it somewhere
1758 pPtr
= m_pWhichRanges
;
1762 // WhichId is right before this Range?
1763 if ( (nWhich
+1) == *pPtr
)
1765 // Range grows downwards
1768 // Make room before first Item of this Range
1769 m_pItems
= AddItem_Impl(m_pItems
, nItemCount
, nPos
);
1773 // WhichId is right after this Range?
1774 else if ( (nWhich
-1) == *(pPtr
+1) )
1776 // Range grows upwards?
1779 // Make room after last Item of this Range
1780 nPos
+= nWhich
- *pPtr
;
1781 m_pItems
= AddItem_Impl(m_pItems
, nItemCount
, nPos
);
1785 // Carry over position of the Item in m_pItems
1786 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
1788 // To the next Range
1793 // No extensible Range found?
1796 // No room left in m_pWhichRanges? => Expand!
1797 std::ptrdiff_t nSize
= pPtr
- m_pWhichRanges
;
1800 m_pWhichRanges
= AddRanges_Impl(m_pWhichRanges
, nSize
, nInitCount
);
1801 nFree
+= nInitCount
;
1804 // Attach new WhichRange
1805 pPtr
= m_pWhichRanges
+ nSize
;
1812 m_pItems
= AddItem_Impl(m_pItems
, nItemCount
, nPos
);
1815 // Add new Item to Pool
1816 const SfxPoolItem
& rNew
= m_pPool
->Put( rItem
, nWhich
);
1818 // Remember old Item
1819 bool bIncrementCount
= false;
1820 const SfxPoolItem
* pOld
= *( m_pItems
+ nPos
);
1821 if ( reinterpret_cast< SfxPoolItem
* >( -1 ) == pOld
) // state "dontcare"
1825 bIncrementCount
= true;
1827 ? &m_pParent
->Get( nWhich
, true )
1828 : ((nWhich
<= SFX_WHICH_MAX
)
1829 ? &m_pPool
->GetDefaultItem(nWhich
)
1833 // Add new Item to ItemSet
1834 *(m_pItems
+ nPos
) = &rNew
;
1836 // Send Changed Notification
1839 Changed( *pOld
, rNew
);
1840 if ( !IsDefaultItem(pOld
) )
1841 m_pPool
->Remove( *pOld
);
1844 if ( bIncrementCount
)
1852 * Using a VoidItem with Which value 0
1854 void SfxItemSet::DisableItem(sal_uInt16 nWhich
)
1856 Put( SfxVoidItem(0), nWhich
);
1859 SfxItemSet
*SfxAllItemSet::Clone(bool bItems
, SfxItemPool
*pToPool
) const
1861 if (pToPool
&& pToPool
!= m_pPool
)
1863 SfxAllItemSet
*pNewSet
= new SfxAllItemSet( *pToPool
);
1865 pNewSet
->Set( *this );
1869 return bItems
? new SfxAllItemSet(*this) : new SfxAllItemSet(*m_pPool
);
1872 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */