Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <string.h>
22 :
23 : #include <cstdarg>
24 : #include <libxml/xmlwriter.h>
25 :
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"
33 :
34 : #include <tools/stream.hxx>
35 : #include <tools/solar.h>
36 : #include <rtl/string.hxx>
37 :
38 : // STATIC DATA
39 :
40 : static const sal_uInt16 nInitCount = 10; // Single USHORTs => 5 pairs without '0'
41 : #include "nranges.cxx"
42 : #include "poolio.hxx"
43 :
44 :
45 : #ifdef DBG_UTIL
46 :
47 :
48 : const sal_Char *DbgCheckItemSet( const void* pVoid )
49 : {
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 )
54 : {
55 : const SfxPoolItem *pItem = pSet->m_pItems[n];
56 : if ( pItem )
57 : {
58 : ++nCount;
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" );
67 : }
68 :
69 : }
70 : assert(pSet->m_nCount == nCount);
71 :
72 : return 0;
73 : }
74 :
75 : #endif
76 :
77 : /**
78 : * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
79 : * the supplied SfxItemPool.
80 : *
81 : * For Sfx programmers: an SfxItemSet constructed in this way cannot
82 : * contain any Items with SlotIds as Which values.
83 : */
84 23447 : SfxItemSet::SfxItemSet
85 : (
86 : SfxItemPool& rPool, /* Target Pool for the SfxPoolItems which are
87 : added to this SfxItemSet */
88 : bool bTotalRanges /* Take over complete pool ranges? */
89 : )
90 : : m_pPool( &rPool )
91 : , m_pParent(nullptr)
92 23447 : , m_nCount(0)
93 : {
94 : // DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
95 : // "please use suitable ranges" );
96 : #if defined DBG_UTIL && defined SFX_ITEMSET_NO_DEFAULT_CTOR
97 : if ( !bTotalRanges )
98 : *(int*)0 = 0; // GPF
99 : #else
100 : (void) bTotalRanges; // avoid warnings
101 : #endif
102 :
103 23447 : m_pWhichRanges = const_cast<sal_uInt16*>(m_pPool->GetFrozenIdRanges());
104 : assert( m_pWhichRanges && "don't create ItemSets with full range before FreezeIdRanges()" );
105 23447 : if (!m_pWhichRanges)
106 0 : m_pPool->FillItemIdRanges_Impl( m_pWhichRanges );
107 :
108 23447 : const sal_uInt16 nSize = TotalCount();
109 23447 : m_pItems = new const SfxPoolItem* [ nSize ];
110 23447 : memset(static_cast<void*>(m_pItems), 0, nSize * sizeof(SfxPoolItem*));
111 23447 : }
112 :
113 2516591 : SfxItemSet::SfxItemSet(SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2)
114 : : m_pPool( &rPool )
115 : , m_pParent(nullptr)
116 2516591 : , m_nCount(0)
117 : {
118 : assert(nWhich1 <= nWhich2);
119 :
120 2516591 : InitRanges_Impl(nWhich1, nWhich2);
121 2516591 : }
122 :
123 2516922 : void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2)
124 : {
125 2516922 : m_pWhichRanges = new sal_uInt16[ 3 ];
126 2516922 : *(m_pWhichRanges+0) = nWh1;
127 2516922 : *(m_pWhichRanges+1) = nWh2;
128 2516922 : *(m_pWhichRanges+2) = 0;
129 2516922 : const sal_uInt16 nRg = nWh2 - nWh1 + 1;
130 2516922 : m_pItems = new const SfxPoolItem* [ nRg ];
131 2516922 : memset(static_cast<void*>(m_pItems), 0, nRg * sizeof(SfxPoolItem*));
132 2516922 : }
133 :
134 464754 : void SfxItemSet::InitRanges_Impl(va_list pArgs, sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull)
135 : {
136 464754 : sal_uInt16 nSize = InitializeRanges_Impl(m_pWhichRanges, pArgs, nWh1, nWh2, nNull);
137 464754 : m_pItems = new const SfxPoolItem* [ nSize ];
138 464754 : memset(static_cast<void*>(m_pItems), 0, sizeof(SfxPoolItem*) * nSize);
139 464754 : }
140 :
141 465085 : SfxItemSet::SfxItemSet(SfxItemPool& rPool,
142 : USHORT_ARG nWh1, USHORT_ARG nWh2, USHORT_ARG nNull, ...)
143 : : m_pPool( &rPool )
144 : , m_pParent(nullptr)
145 : , m_pWhichRanges(nullptr)
146 465085 : , m_nCount(0)
147 : {
148 : assert(nWh1 <= nWh2);
149 :
150 465085 : if(!nNull)
151 : InitRanges_Impl(
152 331 : sal::static_int_cast< sal_uInt16 >(nWh1),
153 662 : sal::static_int_cast< sal_uInt16 >(nWh2));
154 : else {
155 : va_list pArgs;
156 464754 : va_start( pArgs, nNull );
157 : InitRanges_Impl(
158 464754 : pArgs, sal::static_int_cast< sal_uInt16 >(nWh1),
159 464754 : sal::static_int_cast< sal_uInt16 >(nWh2),
160 1394262 : sal::static_int_cast< sal_uInt16 >(nNull));
161 464754 : va_end(pArgs);
162 : }
163 465085 : }
164 :
165 8114662 : void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable)
166 : {
167 8114662 : sal_uInt16 nCnt = 0;
168 8114662 : const sal_uInt16* pPtr = pWhichPairTable;
169 43052654 : while( *pPtr )
170 : {
171 26823330 : nCnt += ( *(pPtr+1) - *pPtr ) + 1;
172 26823330 : pPtr += 2;
173 : }
174 :
175 8114662 : m_pItems = new const SfxPoolItem* [ nCnt ];
176 8114662 : memset(static_cast<void*>(m_pItems), 0, sizeof(SfxPoolItem*) * nCnt);
177 :
178 8114662 : std::ptrdiff_t cnt = pPtr - pWhichPairTable +1;
179 8114662 : m_pWhichRanges = new sal_uInt16[ cnt ];
180 8114662 : memcpy( m_pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt );
181 8114662 : }
182 :
183 8157297 : SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable )
184 : : m_pPool(&rPool)
185 : , m_pParent(nullptr)
186 : , m_pItems(nullptr)
187 : , m_pWhichRanges(nullptr)
188 8157297 : , m_nCount(0)
189 : {
190 : // pWhichPairTable == 0 is for the SfxAllEnumItemSet
191 8157297 : if ( pWhichPairTable )
192 8114662 : InitRanges_Impl(pWhichPairTable);
193 8157297 : }
194 :
195 5141298 : SfxItemSet::SfxItemSet( const SfxItemSet& rASet )
196 : : m_pPool( rASet.m_pPool )
197 : , m_pParent( rASet.m_pParent )
198 5141298 : , m_nCount( rASet.m_nCount )
199 : {
200 : // Calculate the attribute count
201 5141298 : sal_uInt16 nCnt = 0;
202 5141298 : sal_uInt16* pPtr = rASet.m_pWhichRanges;
203 40979673 : while( *pPtr )
204 : {
205 30697077 : nCnt += ( *(pPtr+1) - *pPtr ) + 1;
206 30697077 : pPtr += 2;
207 : }
208 :
209 5141298 : m_pItems = new const SfxPoolItem* [ nCnt ];
210 :
211 : // Copy attributes
212 5141298 : SfxItemArray ppDst = m_pItems, ppSrc = rASet.m_pItems;
213 370425816 : for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc )
214 747129646 : if ( 0 == *ppSrc || // Current Default?
215 381843754 : IsInvalidItem(*ppSrc) || // DontCare?
216 16559236 : IsStaticDefaultItem(*ppSrc) ) // Defaults that are not to be pooled?
217 : // Just copy the pointer
218 348769613 : *ppDst = *ppSrc;
219 16514905 : else if (m_pPool->IsItemFlag( **ppSrc, SfxItemPoolFlags::POOLABLE ))
220 : {
221 : // Just copy the pointer and increase RefCount
222 14695642 : *ppDst = *ppSrc;
223 14695642 : (*ppDst)->AddRef();
224 : }
225 1819263 : else if ( !(*ppSrc)->Which() )
226 0 : *ppDst = (*ppSrc)->Clone();
227 : else
228 : // !IsPoolable() => assign via Pool
229 1819263 : *ppDst = &m_pPool->Put( **ppSrc );
230 :
231 : // Copy the WhichRanges
232 5141298 : std::ptrdiff_t cnt = pPtr - rASet.m_pWhichRanges+1;
233 5141298 : m_pWhichRanges = new sal_uInt16[ cnt ];
234 5141298 : memcpy( m_pWhichRanges, rASet.m_pWhichRanges, sizeof( sal_uInt16 ) * cnt);
235 5141298 : }
236 :
237 17954663 : SfxItemSet::~SfxItemSet()
238 : {
239 16287298 : sal_uInt16 nCount = TotalCount();
240 16287298 : if( Count() )
241 : {
242 10208870 : SfxItemArray ppFnd = m_pItems;
243 1237758586 : for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd )
244 1227549716 : if( *ppFnd && !IsInvalidItem(*ppFnd) )
245 : {
246 42608119 : if( !(*ppFnd)->Which() )
247 18717 : delete *ppFnd;
248 : else {
249 : // Still multiple references present, so just alter the RefCount
250 42589402 : if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) )
251 37541680 : (*ppFnd)->ReleaseRef();
252 : else
253 5047722 : if ( !IsDefaultItem(*ppFnd) )
254 : // Delete from Pool
255 3562710 : m_pPool->Remove( **ppFnd );
256 : }
257 : }
258 : }
259 :
260 16287298 : delete[] m_pItems;
261 16287298 : if (m_pWhichRanges != m_pPool->GetFrozenIdRanges())
262 16263921 : delete[] m_pWhichRanges;
263 16287298 : m_pWhichRanges = nullptr; // for invariant-testing
264 17954663 : }
265 :
266 : /**
267 : * Delete single Items or all Items (nWhich == 0)
268 : */
269 7751374 : sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
270 : {
271 7751374 : if( !Count() )
272 3674815 : return 0;
273 :
274 4076559 : sal_uInt16 nDel = 0;
275 4076559 : SfxItemArray ppFnd = m_pItems;
276 :
277 4076559 : if( nWhich )
278 : {
279 3401975 : const sal_uInt16* pPtr = m_pWhichRanges;
280 10340791 : while( *pPtr )
281 : {
282 : // Within this range?
283 6830440 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
284 : {
285 : // Actually set?
286 3293599 : ppFnd += nWhich - *pPtr;
287 3293599 : if( *ppFnd )
288 : {
289 : // Due to the assertions in the sub calls, we need to do the following
290 205171 : --m_nCount;
291 205171 : const SfxPoolItem *pItemToClear = *ppFnd;
292 205171 : *ppFnd = 0;
293 :
294 205171 : if ( !IsInvalidItem(pItemToClear) )
295 : {
296 205171 : if ( nWhich <= SFX_WHICH_MAX )
297 : {
298 : const SfxPoolItem& rNew = m_pParent
299 77436 : ? m_pParent->Get( nWhich, true )
300 260113 : : m_pPool->GetDefaultItem( nWhich );
301 :
302 182677 : Changed( *pItemToClear, rNew );
303 : }
304 205171 : if ( pItemToClear->Which() )
305 205171 : m_pPool->Remove( *pItemToClear );
306 : }
307 205171 : ++nDel;
308 : }
309 :
310 : // found => break
311 3293599 : break;
312 : }
313 3536841 : ppFnd += *(pPtr+1) - *pPtr + 1;
314 3536841 : pPtr += 2;
315 : }
316 : }
317 : else
318 : {
319 674584 : nDel = m_nCount;
320 :
321 674584 : sal_uInt16* pPtr = m_pWhichRanges;
322 8706388 : while( *pPtr )
323 : {
324 81204291 : for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
325 73847071 : if( *ppFnd )
326 : {
327 : // Due to the assertions in the sub calls, we need to do this
328 2407618 : --m_nCount;
329 2407618 : const SfxPoolItem *pItemToClear = *ppFnd;
330 2407618 : *ppFnd = 0;
331 :
332 2407618 : if ( !IsInvalidItem(pItemToClear) )
333 : {
334 2407461 : if ( nWhich <= SFX_WHICH_MAX )
335 : {
336 : const SfxPoolItem& rNew = m_pParent
337 1134150 : ? m_pParent->Get( nWhich, true )
338 2984650 : : m_pPool->GetDefaultItem( nWhich );
339 :
340 1850500 : Changed( *pItemToClear, rNew );
341 : }
342 :
343 : // #i32448#
344 : // Take care of disabled items, too.
345 2407461 : if (!pItemToClear->m_nWhich)
346 : {
347 : // item is disabled, delete it
348 0 : delete pItemToClear;
349 : }
350 : else
351 : {
352 : // remove item from pool
353 2407461 : m_pPool->Remove( *pItemToClear );
354 : }
355 : }
356 : }
357 7357220 : pPtr += 2;
358 : }
359 : }
360 4076559 : return nDel;
361 : }
362 :
363 214821 : void SfxItemSet::ClearInvalidItems( bool bHardDefault )
364 : {
365 214821 : sal_uInt16* pPtr = m_pWhichRanges;
366 214821 : SfxItemArray ppFnd = m_pItems;
367 214821 : if ( bHardDefault )
368 0 : while( *pPtr )
369 : {
370 0 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
371 0 : if ( IsInvalidItem(*ppFnd) )
372 0 : *ppFnd = &m_pPool->Put( m_pPool->GetDefaultItem(nWhich) );
373 0 : pPtr += 2;
374 : }
375 : else
376 3827565 : while( *pPtr )
377 : {
378 33223399 : for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
379 29825476 : if( IsInvalidItem(*ppFnd) )
380 : {
381 759 : *ppFnd = 0;
382 759 : --m_nCount;
383 : }
384 3397923 : pPtr += 2;
385 : }
386 214821 : }
387 :
388 0 : void SfxItemSet::InvalidateDefaultItems()
389 : {
390 0 : sal_uInt16* pPtr = m_pWhichRanges;
391 0 : SfxItemArray ppFnd = m_pItems;
392 :
393 0 : while( *pPtr )
394 : {
395 0 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
396 0 : if (*ppFnd && *ppFnd != reinterpret_cast<SfxPoolItem *>(-1)
397 0 : && **ppFnd == m_pPool->GetDefaultItem(nWhich))
398 : {
399 0 : m_pPool->Remove( **ppFnd );
400 0 : *ppFnd = reinterpret_cast<SfxPoolItem*>(-1);
401 : }
402 0 : pPtr += 2;
403 : }
404 0 : }
405 :
406 0 : void SfxItemSet::InvalidateAllItems()
407 : {
408 : assert( !m_nCount && "There are still Items set" );
409 0 : m_nCount = TotalCount();
410 0 : memset(static_cast<void*>(m_pItems), -1, m_nCount * sizeof(SfxPoolItem*));
411 0 : }
412 :
413 176419523 : SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich,
414 : bool bSrchInParent,
415 : const SfxPoolItem **ppItem ) const
416 : {
417 : // Find the range in which the Which is located
418 176419523 : const SfxItemSet* pAktSet = this;
419 176419523 : SfxItemState eRet = SfxItemState::UNKNOWN;
420 142026535 : do
421 : {
422 200899285 : SfxItemArray ppFnd = pAktSet->m_pItems;
423 200899285 : const sal_uInt16* pPtr = pAktSet->m_pWhichRanges;
424 200899285 : if (pPtr)
425 : {
426 580258036 : while ( *pPtr )
427 : {
428 364251400 : if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
429 : {
430 : // Within this range
431 185791934 : ppFnd += nWhich - *pPtr;
432 185791934 : if ( !*ppFnd )
433 : {
434 155412085 : eRet = SfxItemState::DEFAULT;
435 155412085 : if( !bSrchInParent )
436 28492901 : return eRet; // Not present
437 126919184 : break; // Keep searching in the parents!
438 : }
439 :
440 30379849 : if ( reinterpret_cast<SfxPoolItem*>(-1) == *ppFnd )
441 : // Different ones are present
442 477 : return SfxItemState::DONTCARE;
443 :
444 30379372 : if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) )
445 24515 : return SfxItemState::DISABLED;
446 :
447 30354857 : if (ppItem)
448 : {
449 17463516 : *ppItem = *ppFnd;
450 : }
451 30354857 : return SfxItemState::SET;
452 : }
453 178459466 : ppFnd += *(pPtr+1) - *pPtr + 1;
454 178459466 : pPtr += 2;
455 : }
456 : }
457 142026535 : } while (bSrchInParent && nullptr != (pAktSet = pAktSet->m_pParent));
458 117546773 : return eRet;
459 : }
460 :
461 3686027 : bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const
462 : {
463 3686027 : bool bRet = SfxItemState::SET == GetItemState(nWhich, true, ppItem);
464 3686027 : if (!bRet && ppItem)
465 35976 : *ppItem = NULL;
466 3686027 : return bRet;
467 : }
468 :
469 37450958 : const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
470 : {
471 37450958 : if ( !nWhich )
472 112 : return 0; //FIXME: Only because of Outliner bug
473 :
474 37450846 : SfxItemArray ppFnd = m_pItems;
475 37450846 : const sal_uInt16* pPtr = m_pWhichRanges;
476 116313927 : while( *pPtr )
477 : {
478 74718988 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
479 : {
480 : // Within this range
481 33306753 : ppFnd += nWhich - *pPtr;
482 33306753 : if( *ppFnd ) // Already one present
483 : {
484 : // Same Item already present?
485 8082644 : if ( *ppFnd == &rItem )
486 5074561 : return 0;
487 :
488 : // Will 'dontcare' or 'disabled' be overwritten with some real value?
489 3008083 : if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) )
490 : {
491 9 : *ppFnd = &m_pPool->Put( rItem, nWhich );
492 9 : return *ppFnd;
493 : }
494 :
495 : // Turns into disabled?
496 3008074 : if( !rItem.Which() )
497 : {
498 1013 : *ppFnd = rItem.Clone(m_pPool);
499 1013 : return 0;
500 : }
501 : else
502 : {
503 : // Same value already present?
504 3007061 : if ( rItem == **ppFnd )
505 1974469 : return 0;
506 :
507 : // Add the new one, remove the old one
508 1032592 : const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich );
509 1032592 : const SfxPoolItem* pOld = *ppFnd;
510 1032592 : *ppFnd = &rNew;
511 1032592 : if(nWhich <= SFX_WHICH_MAX)
512 1021958 : Changed( *pOld, rNew );
513 1032592 : m_pPool->Remove( *pOld );
514 : }
515 : }
516 : else
517 : {
518 25224109 : ++m_nCount;
519 25224109 : if( !rItem.Which() )
520 18710 : *ppFnd = rItem.Clone(m_pPool);
521 : else {
522 25205399 : const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich );
523 25205399 : *ppFnd = &rNew;
524 25205399 : if (nWhich <= SFX_WHICH_MAX )
525 : {
526 : const SfxPoolItem& rOld = m_pParent
527 3182887 : ? m_pParent->Get( nWhich, true )
528 27512709 : : m_pPool->GetDefaultItem( nWhich );
529 24329822 : Changed( rOld, rNew );
530 : }
531 : }
532 : }
533 : SFX_ASSERT( !m_pPool->IsItemFlag(nWhich, SfxItemPoolFlags::POOLABLE) ||
534 : rItem.ISA(SfxSetItem) || **ppFnd == rItem,
535 : nWhich, "putted Item unequal" );
536 26256701 : return *ppFnd;
537 : }
538 41412235 : ppFnd += *(pPtr+1) - *pPtr + 1;
539 41412235 : pPtr += 2;
540 : }
541 4144093 : return 0;
542 : }
543 :
544 2049769 : bool SfxItemSet::Put( const SfxItemSet& rSet, bool bInvalidAsDefault )
545 : {
546 2049769 : bool bRet = false;
547 2049769 : if( rSet.Count() )
548 : {
549 1852328 : SfxItemArray ppFnd = rSet.m_pItems;
550 1852328 : const sal_uInt16* pPtr = rSet.m_pWhichRanges;
551 12931693 : while ( *pPtr )
552 : {
553 333971994 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
554 324744957 : if( *ppFnd )
555 : {
556 12095250 : if ( IsInvalidItem( *ppFnd ) )
557 : {
558 48 : if ( bInvalidAsDefault )
559 0 : bRet |= 0 != ClearItem( nWhich );
560 : // FIXME: Caused a SEGFAULT on non Windows-platforms:
561 : // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
562 : else
563 48 : InvalidateItem( nWhich );
564 : }
565 : else
566 12095202 : bRet |= 0 != Put( **ppFnd, nWhich );
567 : }
568 9227037 : pPtr += 2;
569 : }
570 : }
571 2049769 : return bRet;
572 : }
573 :
574 : /**
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.
578 : *
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':
582 : *
583 : * SfxItemState::SET: Hard set to the default of the Pool
584 : * SfxItemState::DEFAULT: Deleted (0 pointer)
585 : * SfxItemState::DONTCARE: Invalid (-1 pointer)
586 : *
587 : * NB: All other values for 'eDontCareAs' and 'eDefaultAs' are invalid
588 : */
589 1921 : void SfxItemSet::PutExtended
590 : (
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
594 : )
595 : {
596 : // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
597 1921 : SfxItemArray ppFnd = rSet.m_pItems;
598 1921 : const sal_uInt16* pPtr = rSet.m_pWhichRanges;
599 5779 : while ( *pPtr )
600 : {
601 109453 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
602 107516 : if( *ppFnd )
603 : {
604 1951 : if ( IsInvalidItem( *ppFnd ) )
605 : {
606 : // Item ist DontCare:
607 0 : switch ( eDontCareAs )
608 : {
609 : case SfxItemState::SET:
610 0 : Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
611 0 : break;
612 :
613 : case SfxItemState::DEFAULT:
614 0 : ClearItem( nWhich );
615 0 : break;
616 :
617 : case SfxItemState::DONTCARE:
618 0 : InvalidateItem( nWhich );
619 0 : break;
620 :
621 : default:
622 : assert(!"invalid Argument for eDontCareAs");
623 : }
624 : }
625 : else
626 : // Item is set:
627 1951 : Put( **ppFnd, nWhich );
628 : }
629 : else
630 : {
631 : // Item is default:
632 105565 : switch ( eDefaultAs )
633 : {
634 : case SfxItemState::SET:
635 104789 : Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
636 104789 : break;
637 :
638 : case SfxItemState::DEFAULT:
639 776 : ClearItem( nWhich );
640 776 : break;
641 :
642 : case SfxItemState::DONTCARE:
643 0 : InvalidateItem( nWhich );
644 0 : break;
645 :
646 : default:
647 : assert(!"invalid Argument for eDefaultAs");
648 : }
649 : }
650 1937 : pPtr += 2;
651 : }
652 1921 : }
653 :
654 : /**
655 : * Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
656 : * items which are new ranges too.
657 : */
658 37808 : void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
659 : {
660 : // special case: exactly one sal_uInt16 which is already included?
661 37808 : SfxItemState eItemState = GetItemState(nFrom, false);
662 37808 : if ( nFrom == nTo && ( eItemState == SfxItemState::DEFAULT || eItemState == SfxItemState::SET ) )
663 37808 : return;
664 :
665 : // merge new range
666 37808 : SfxUShortRanges aRanges( m_pWhichRanges );
667 37808 : aRanges += SfxUShortRanges( nFrom, nTo );
668 37808 : SetRanges( aRanges );
669 : }
670 :
671 : /**
672 : * Modifies the ranges of settable items. Keeps state of items which
673 : * are new ranges too.
674 : */
675 37808 : void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges )
676 : {
677 : // Identical Ranges?
678 37808 : if (m_pWhichRanges == pNewRanges)
679 0 : return;
680 37808 : const sal_uInt16* pOld = m_pWhichRanges;
681 37808 : const sal_uInt16* pNew = pNewRanges;
682 207944 : while ( *pOld == *pNew )
683 : {
684 132328 : if ( !*pOld && !*pNew )
685 0 : return;
686 132328 : ++pOld, ++pNew;
687 : }
688 :
689 : // create new item-array (by iterating through all new ranges)
690 37808 : sal_uLong nSize = Capacity_Impl(pNewRanges);
691 37808 : SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ];
692 37808 : sal_uInt16 nNewCount = 0;
693 37808 : if (m_nCount == 0)
694 37808 : memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) );
695 : else
696 : {
697 0 : sal_uInt16 n = 0;
698 0 : for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 )
699 : {
700 : // iterate through all ids in the range
701 0 : for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n )
702 : {
703 : // direct move of pointer (not via pool)
704 0 : SfxItemState eState = GetItemState( nWID, false, aNewItems+n );
705 0 : if ( SfxItemState::SET == eState )
706 : {
707 : // increment new item count and possibly increment ref count
708 0 : ++nNewCount;
709 0 : aNewItems[n]->AddRef();
710 : }
711 0 : else if ( SfxItemState::DISABLED == eState )
712 : {
713 : // put "disabled" item
714 0 : ++nNewCount;
715 0 : aNewItems[n] = new SfxVoidItem(0);
716 : }
717 0 : else if ( SfxItemState::DONTCARE == eState )
718 : {
719 0 : ++nNewCount;
720 0 : aNewItems[n] = reinterpret_cast<SfxPoolItem*>(-1);
721 : }
722 : else
723 : {
724 : // default
725 0 : aNewItems[n] = 0;
726 : }
727 : }
728 : }
729 : // free old items
730 0 : sal_uInt16 nOldTotalCount = TotalCount();
731 0 : for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem )
732 : {
733 0 : const SfxPoolItem *pItem = m_pItems[nItem];
734 0 : if ( pItem && !IsInvalidItem(pItem) && pItem->Which() )
735 0 : m_pPool->Remove(*pItem);
736 : }
737 : }
738 :
739 : // replace old items-array and ranges
740 37808 : delete[] m_pItems;
741 37808 : m_pItems = aNewItems;
742 37808 : m_nCount = nNewCount;
743 :
744 37808 : if( pNewRanges == GetPool()->GetFrozenIdRanges() )
745 : {
746 0 : delete[] m_pWhichRanges;
747 0 : m_pWhichRanges = const_cast<sal_uInt16*>(pNewRanges);
748 : }
749 : else
750 : {
751 37808 : sal_uInt16 nCount = Count_Impl(pNewRanges) + 1;
752 37808 : if (m_pWhichRanges != m_pPool->GetFrozenIdRanges())
753 37808 : delete[] m_pWhichRanges;
754 37808 : m_pWhichRanges = new sal_uInt16[ nCount ];
755 37808 : memcpy( m_pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount );
756 : }
757 : }
758 :
759 : /**
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
764 : * of *this.
765 : *
766 : * SfxPoolItems in rSet, for which holds 'IsInvalidItem() == true' are
767 : * taken over as invalid items.
768 : *
769 : * @return bool true
770 : * SfxPoolItems have been taken over
771 : *
772 : * false
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
776 : * set in rSet
777 : */
778 1423034 : bool SfxItemSet::Set
779 : (
780 : const SfxItemSet& rSet, /* The SfxItemSet, whose SfxPoolItems are
781 : to been taken over */
782 :
783 : bool bDeep /* true (default)
784 :
785 : The SfxPoolItems from the parents that may
786 : be present in rSet, are also taken over into
787 : this SfxPoolItemSet
788 :
789 : false
790 : The SfxPoolItems from the parents of
791 : rSet are not taken into account */
792 : )
793 : {
794 1423034 : bool bRet = false;
795 1423034 : if (m_nCount)
796 262263 : ClearItem();
797 1423034 : if ( bDeep )
798 : {
799 1414661 : SfxWhichIter aIter(*this);
800 1414661 : sal_uInt16 nWhich = aIter.FirstWhich();
801 69881826 : while ( nWhich )
802 : {
803 : const SfxPoolItem* pItem;
804 67052504 : if( SfxItemState::SET == rSet.GetItemState( nWhich, true, &pItem ) )
805 11335987 : bRet |= 0 != Put( *pItem, pItem->Which() );
806 67052504 : nWhich = aIter.NextWhich();
807 1414661 : }
808 : }
809 : else
810 8373 : bRet = Put(rSet, false);
811 :
812 1423034 : return bRet;
813 : }
814 :
815 : /**
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.
819 : *
820 : * The PRODUCT version returns 0, if the Item found is not of the
821 : * specified class.
822 : *
823 : * @returns 0 if the ItemSet does not contain an Item with the Id 'nWhich'
824 : */
825 660069 : const SfxPoolItem* SfxItemSet::GetItem
826 : (
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
830 : ) const
831 : {
832 : // Convert to WhichId
833 660069 : sal_uInt16 nWhich = GetPool()->GetWhich(nId);
834 :
835 : // Is the Item set or 'bDeep == true' available?
836 660069 : const SfxPoolItem *pItem = 0;
837 660069 : SfxItemState eState = GetItemState( nWhich, bSrchInParent, &pItem );
838 660069 : if ( bSrchInParent && SfxItemState::DEFAULT == eState &&
839 : nWhich <= SFX_WHICH_MAX )
840 : {
841 412909 : pItem = &m_pPool->GetDefaultItem(nWhich);
842 : }
843 :
844 660069 : if ( pItem )
845 : {
846 : // Does the type match?
847 570301 : if ( !aItemType || pItem->IsA(aItemType) )
848 570301 : return pItem;
849 :
850 : // Else report error
851 : assert(!"invalid argument type");
852 : }
853 :
854 : // No Item of wrong type found
855 89768 : return 0;
856 : }
857 :
858 270173723 : const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool bSrchInParent) const
859 : {
860 : // Search the Range in which the Which is located in:
861 270173723 : const SfxItemSet* pAktSet = this;
862 487285052 : do
863 : {
864 505172135 : if( pAktSet->Count() )
865 : {
866 278611111 : SfxItemArray ppFnd = pAktSet->m_pItems;
867 278611111 : const sal_uInt16* pPtr = pAktSet->m_pWhichRanges;
868 817437385 : while( *pPtr )
869 : {
870 538268741 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
871 : {
872 : // In this Range
873 278053578 : ppFnd += nWhich - *pPtr;
874 278053578 : if( *ppFnd )
875 : {
876 17887083 : 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);
880 : //!return aDefault;
881 510 : return m_pPool->GetDefaultItem( nWhich );
882 : }
883 : #ifdef DBG_UTIL
884 : const SfxPoolItem *pItem = *ppFnd;
885 : if ( pItem->ISA(SfxVoidItem) || !pItem->Which() )
886 : SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item");
887 : #endif
888 17886573 : return **ppFnd;
889 : }
890 260166495 : break; // Continue with Parent
891 : }
892 260215163 : ppFnd += *(pPtr+1) - *pPtr + 1;
893 260215163 : pPtr += 2;
894 : }
895 : }
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?
898 : // break;
899 487285052 : } while (bSrchInParent && nullptr != (pAktSet = pAktSet->m_pParent));
900 :
901 : // Get the Default from the Pool and return
902 : SFX_ASSERT(m_pPool, nWhich, "no Pool, but status is ambiguous");
903 252286640 : const SfxPoolItem *pItem = &m_pPool->GetDefaultItem( nWhich );
904 252286640 : return *pItem;
905 : }
906 :
907 : /**
908 : * Notification callback
909 : */
910 24991153 : void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& )
911 : {
912 24991153 : }
913 :
914 18699946 : sal_uInt16 SfxItemSet::TotalCount() const
915 : {
916 18699946 : sal_uInt16 nRet = 0;
917 18699946 : sal_uInt16* pPtr = m_pWhichRanges;
918 112788035 : while( *pPtr )
919 : {
920 75388143 : nRet += ( *(pPtr+1) - *pPtr ) + 1;
921 75388143 : pPtr += 2;
922 : }
923 18699946 : return nRet;
924 : }
925 :
926 : /**
927 : * Only retain the Items that are also present in rSet
928 : * (nevermind their value).
929 : */
930 43374 : void SfxItemSet::Intersect( const SfxItemSet& rSet )
931 : {
932 : assert(m_pPool && "Not implemented without Pool");
933 43374 : if( !Count() ) // None set?
934 11803 : return;
935 :
936 : // Delete all Items not contained in rSet
937 31571 : if( !rSet.Count() )
938 : {
939 0 : ClearItem(); // Delete everything
940 0 : return;
941 : }
942 :
943 : // Test whether the Which Ranges are different
944 31571 : bool bEqual = true;
945 31571 : sal_uInt16* pWh1 = m_pWhichRanges;
946 31571 : sal_uInt16* pWh2 = rSet.m_pWhichRanges;
947 31571 : sal_uInt16 nSize = 0;
948 :
949 222337 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
950 : {
951 190766 : if( *pWh1 != *pWh2 )
952 : {
953 0 : bEqual = false;
954 0 : break;
955 : }
956 190766 : if( n & 1 )
957 95383 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
958 : }
959 31571 : bEqual = *pWh1 == *pWh2; // Also check for 0
960 :
961 : // If the Ranges are identical, we can easily process it
962 31571 : if( bEqual )
963 : {
964 31571 : SfxItemArray ppFnd1 = m_pItems;
965 31571 : SfxItemArray ppFnd2 = rSet.m_pItems;
966 :
967 2073555 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
968 2041984 : if( *ppFnd1 && !*ppFnd2 )
969 : {
970 : // Delete from Pool
971 39510 : if( !IsInvalidItem( *ppFnd1 ) )
972 : {
973 39510 : sal_uInt16 nWhich = (*ppFnd1)->Which();
974 39510 : if(nWhich <= SFX_WHICH_MAX)
975 : {
976 : const SfxPoolItem& rNew = m_pParent
977 39510 : ? m_pParent->Get( nWhich, true )
978 79020 : : m_pPool->GetDefaultItem( nWhich );
979 :
980 39510 : Changed( **ppFnd1, rNew );
981 : }
982 39510 : m_pPool->Remove( **ppFnd1 );
983 : }
984 39510 : *ppFnd1 = 0;
985 39510 : --m_nCount;
986 : }
987 : }
988 : else
989 : {
990 0 : SfxItemIter aIter( *this );
991 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
992 : while( true )
993 : {
994 0 : sal_uInt16 nWhich = IsInvalidItem( pItem )
995 0 : ? GetWhichByPos( aIter.GetCurPos() )
996 0 : : pItem->Which();
997 0 : if( SfxItemState::UNKNOWN == rSet.GetItemState( nWhich, false ) )
998 0 : ClearItem( nWhich ); // Delete
999 0 : if( aIter.IsAtEnd() )
1000 0 : break;
1001 0 : pItem = aIter.NextItem();
1002 0 : }
1003 : }
1004 : }
1005 :
1006 993002 : void SfxItemSet::Differentiate( const SfxItemSet& rSet )
1007 : {
1008 993002 : if( !Count() || !rSet.Count() )// None set?
1009 1256762 : return;
1010 :
1011 : // Test whether the Which Ranges are different
1012 729242 : bool bEqual = true;
1013 729242 : sal_uInt16* pWh1 = m_pWhichRanges;
1014 729242 : sal_uInt16* pWh2 = rSet.m_pWhichRanges;
1015 729242 : sal_uInt16 nSize = 0;
1016 :
1017 1569210 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1018 : {
1019 1497012 : if( *pWh1 != *pWh2 )
1020 : {
1021 657044 : bEqual = false;
1022 657044 : break;
1023 : }
1024 839968 : if( n & 1 )
1025 419984 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1026 : }
1027 729242 : bEqual = *pWh1 == *pWh2; // Also test for 0
1028 :
1029 : // If the Ranges are identical, we can easily process it
1030 729242 : if( bEqual )
1031 : {
1032 72198 : SfxItemArray ppFnd1 = m_pItems;
1033 72198 : SfxItemArray ppFnd2 = rSet.m_pItems;
1034 :
1035 7324295 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1036 7252097 : if( *ppFnd1 && *ppFnd2 )
1037 : {
1038 : // Delete from Pool
1039 59564 : if( !IsInvalidItem( *ppFnd1 ) )
1040 : {
1041 59564 : sal_uInt16 nWhich = (*ppFnd1)->Which();
1042 59564 : if(nWhich <= SFX_WHICH_MAX)
1043 : {
1044 : const SfxPoolItem& rNew = m_pParent
1045 0 : ? m_pParent->Get( nWhich, true )
1046 59564 : : m_pPool->GetDefaultItem( nWhich );
1047 :
1048 59564 : Changed( **ppFnd1, rNew );
1049 : }
1050 59564 : m_pPool->Remove( **ppFnd1 );
1051 : }
1052 59564 : *ppFnd1 = 0;
1053 59564 : --m_nCount;
1054 : }
1055 : }
1056 : else
1057 : {
1058 657044 : SfxItemIter aIter( *this );
1059 657044 : const SfxPoolItem* pItem = aIter.GetCurItem();
1060 : while( true )
1061 : {
1062 690520 : sal_uInt16 nWhich = IsInvalidItem( pItem )
1063 0 : ? GetWhichByPos( aIter.GetCurPos() )
1064 690520 : : pItem->Which();
1065 690520 : if( SfxItemState::SET == rSet.GetItemState( nWhich, false ) )
1066 37757 : ClearItem( nWhich ); // Delete
1067 690520 : if( aIter.IsAtEnd() )
1068 657044 : break;
1069 33476 : pItem = aIter.NextItem();
1070 657044 : }
1071 :
1072 : }
1073 : }
1074 :
1075 : /**
1076 : * Decision table for MergeValue(s)
1077 : *
1078 : * Principles:
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
1082 : *
1083 : * 1st Item 2nd Item Values bIgnoreDefs Remove Assign Add
1084 : *
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 - - -
1101 : *
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 - - -
1118 : *
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 - - -
1135 : *
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 - - -
1152 : */
1153 423914 : static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount,
1154 : const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2,
1155 : bool bIgnoreDefaults )
1156 : {
1157 : assert(ppFnd1 != 0 && "Merging to 0-Item");
1158 :
1159 : // 1st Item is Default?
1160 423914 : if ( !*ppFnd1 )
1161 : {
1162 360165 : if ( IsInvalidItem(pFnd2) )
1163 : // Decision table: default, dontcare, doesn't matter, doesn't matter
1164 48 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1165 :
1166 360139 : else if ( pFnd2 && !bIgnoreDefaults &&
1167 22 : _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
1168 : // Decision table: default, set, !=, sal_False
1169 22 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1170 :
1171 360095 : else if ( pFnd2 && bIgnoreDefaults )
1172 : // Decision table: default, set, doesn't matter, sal_True
1173 4664 : *ppFnd1 = &_pPool->Put( *pFnd2 );
1174 :
1175 360165 : if ( *ppFnd1 )
1176 4734 : ++rCount;
1177 : }
1178 :
1179 : // 1st Item set?
1180 63749 : else if ( !IsInvalidItem(*ppFnd1) )
1181 : {
1182 49203 : if ( !pFnd2 )
1183 : {
1184 : // 2nd Item is Default
1185 1514 : if ( !bIgnoreDefaults &&
1186 757 : **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) )
1187 : {
1188 : // Decision table: set, default, !=, sal_False
1189 755 : _pPool->Remove( **ppFnd1 );
1190 755 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1191 : }
1192 : }
1193 48446 : else if ( IsInvalidItem(pFnd2) )
1194 : {
1195 : // 2nd Item is dontcare
1196 96 : if ( !bIgnoreDefaults ||
1197 0 : **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) )
1198 : {
1199 : // Decision table: set, dontcare, doesn't matter, sal_False
1200 : // or: set, dontcare, !=, sal_True
1201 96 : _pPool->Remove( **ppFnd1 );
1202 96 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1203 : }
1204 : }
1205 : else
1206 : {
1207 : // 2nd Item is set
1208 48350 : if ( **ppFnd1 != *pFnd2 )
1209 : {
1210 : // Decision table: set, set, !=, doesn't matter
1211 432 : _pPool->Remove( **ppFnd1 );
1212 432 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1213 : }
1214 : }
1215 : }
1216 423914 : }
1217 :
1218 8186 : void SfxItemSet::MergeValues( const SfxItemSet& rSet, bool bIgnoreDefaults )
1219 : {
1220 : // WARNING! When making changes/fixing bugs, always update the table above!!
1221 : assert( GetPool() == rSet.GetPool() && "MergeValues with different Pools" );
1222 :
1223 : // Test if the which Ranges are different
1224 8186 : bool bEqual = true;
1225 8186 : sal_uInt16* pWh1 = m_pWhichRanges;
1226 8186 : sal_uInt16* pWh2 = rSet.m_pWhichRanges;
1227 8186 : sal_uInt16 nSize = 0;
1228 :
1229 37022 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1230 : {
1231 28836 : if( *pWh1 != *pWh2 )
1232 : {
1233 0 : bEqual = false;
1234 0 : break;
1235 : }
1236 28836 : if( n & 1 )
1237 14418 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1238 : }
1239 8186 : bEqual = *pWh1 == *pWh2; // Also check for 0
1240 :
1241 : // If the Ranges match, they are easier to process!
1242 8186 : if( bEqual )
1243 : {
1244 8186 : SfxItemArray ppFnd1 = m_pItems;
1245 8186 : SfxItemArray ppFnd2 = rSet.m_pItems;
1246 :
1247 427436 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1248 419250 : MergeItem_Impl(m_pPool, m_nCount, ppFnd1, *ppFnd2, bIgnoreDefaults);
1249 : }
1250 : else
1251 : {
1252 0 : SfxWhichIter aIter( rSet );
1253 : sal_uInt16 nWhich;
1254 0 : while( 0 != ( nWhich = aIter.NextWhich() ) )
1255 : {
1256 0 : const SfxPoolItem* pItem = 0;
1257 0 : rSet.GetItemState( nWhich, true, &pItem );
1258 0 : if( !pItem )
1259 : {
1260 : // Not set, so default
1261 0 : if ( !bIgnoreDefaults )
1262 0 : MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ), bIgnoreDefaults );
1263 : }
1264 0 : else if( IsInvalidItem( pItem ) )
1265 : // dont care
1266 0 : InvalidateItem( nWhich );
1267 : else
1268 0 : MergeValue( *pItem, bIgnoreDefaults );
1269 0 : }
1270 : }
1271 8186 : }
1272 :
1273 4664 : void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, bool bIgnoreDefaults )
1274 : {
1275 4664 : SfxItemArray ppFnd = m_pItems;
1276 4664 : const sal_uInt16* pPtr = m_pWhichRanges;
1277 4664 : const sal_uInt16 nWhich = rAttr.Which();
1278 11088 : while( *pPtr )
1279 : {
1280 : // In this Range??
1281 6424 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1282 : {
1283 4664 : ppFnd += nWhich - *pPtr;
1284 4664 : MergeItem_Impl(m_pPool, m_nCount, ppFnd, &rAttr, bIgnoreDefaults);
1285 4664 : break;
1286 : }
1287 1760 : ppFnd += *(pPtr+1) - *pPtr + 1;
1288 1760 : pPtr += 2;
1289 : }
1290 4664 : }
1291 :
1292 6820 : void SfxItemSet::InvalidateItem( sal_uInt16 nWhich )
1293 : {
1294 6820 : SfxItemArray ppFnd = m_pItems;
1295 6820 : const sal_uInt16* pPtr = m_pWhichRanges;
1296 29430 : while( *pPtr )
1297 : {
1298 17742 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1299 : {
1300 : // In this Range?
1301 1952 : ppFnd += nWhich - *pPtr;
1302 :
1303 1952 : if( *ppFnd ) // Set for me
1304 : {
1305 1013 : if( reinterpret_cast<SfxPoolItem*>(-1) != *ppFnd ) // Not yet dontcare!
1306 : {
1307 503 : m_pPool->Remove( **ppFnd );
1308 503 : *ppFnd = reinterpret_cast<SfxPoolItem*>(-1);
1309 : }
1310 : }
1311 : else
1312 : {
1313 939 : *ppFnd = reinterpret_cast<SfxPoolItem*>(-1);
1314 939 : ++m_nCount;
1315 : }
1316 1952 : break;
1317 : }
1318 15790 : ppFnd += *(pPtr+1) - *pPtr + 1;
1319 15790 : pPtr += 2;
1320 : }
1321 6820 : }
1322 :
1323 220580 : sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const
1324 : {
1325 220580 : sal_uInt16 n = 0;
1326 220580 : sal_uInt16* pPtr = m_pWhichRanges;
1327 696393 : while( *pPtr )
1328 : {
1329 475813 : n = ( *(pPtr+1) - *pPtr ) + 1;
1330 475813 : if( nPos < n )
1331 220580 : return *(pPtr)+nPos;
1332 255233 : nPos = nPos - n;
1333 255233 : pPtr += 2;
1334 : }
1335 : assert(false);
1336 0 : return 0;
1337 : }
1338 :
1339 : /**
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:
1343 : *
1344 : * sal_uInt16 ... Count of the set Items
1345 : * Count* m_pPool->StoreItem()
1346 : *
1347 : * @see SfxItemPool::StoreItem() const
1348 : * @see SfxItemSet::Load(SvStream&,bool,const SfxItemPool*)
1349 : */
1350 6402 : SvStream &SfxItemSet::Store
1351 : (
1352 : SvStream& rStream, // Target stream for normal Items
1353 : bool bDirect /* true: Save Items directly
1354 : false: Surrogates */
1355 : ) const
1356 : {
1357 : assert(m_pPool);
1358 :
1359 : // Remember position of the count (to be able to correct it, if need be)
1360 6402 : sal_uLong nCountPos = rStream.Tell();
1361 6402 : rStream.WriteUInt16( m_nCount );
1362 :
1363 : // If there's nothing to save, don't construct an ItemIter
1364 6402 : if (m_nCount)
1365 : {
1366 : // Keep record of how many Items are really saved
1367 368 : sal_uInt16 nWrittenCount = 0; // Count of Items streamed in 'rStream'
1368 :
1369 : // Iterate over all set Items
1370 368 : SfxItemIter aIter(*this);
1371 10332 : for ( const SfxPoolItem *pItem = aIter.FirstItem();
1372 : pItem;
1373 : pItem = aIter.NextItem() )
1374 : {
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 19928 : if ( !IsInvalidItem(pItem) &&
1378 9964 : m_pPool->StoreItem( rStream, *pItem, bDirect ) )
1379 : // Item was streamed in 'rStream'
1380 9964 : ++nWrittenCount;
1381 : }
1382 :
1383 : // Fewer written than read (e.g. old format)
1384 368 : if (nWrittenCount != m_nCount)
1385 : {
1386 : // Store real count in the stream
1387 0 : sal_uLong nPos = rStream.Tell();
1388 0 : rStream.Seek( nCountPos );
1389 0 : rStream.WriteUInt16( nWrittenCount );
1390 0 : rStream.Seek( nPos );
1391 368 : }
1392 : }
1393 :
1394 6402 : return rStream;
1395 : }
1396 :
1397 : /**
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.
1402 : *
1403 : * @see SfxItemSet::Store(Stream&,bool) const
1404 : */
1405 0 : SvStream &SfxItemSet::Load
1406 : (
1407 : SvStream& rStream, // Stream we're loading from
1408 :
1409 : bool bDirect, /* true
1410 : Items are directly read form the stream
1411 : and not via Surrogates
1412 :
1413 : false (default)
1414 : Items are read via Surrogates */
1415 :
1416 : const SfxItemPool* pRefPool /* Pool that can resolve the Surrogates
1417 : (e.g. when inserting documents) */
1418 : )
1419 : {
1420 : assert(m_pPool);
1421 :
1422 : // No RefPool => Resolve Surrogates with ItemSet's Pool
1423 0 : if ( !pRefPool )
1424 0 : pRefPool = m_pPool;
1425 :
1426 : // Load Item count and as many Items
1427 0 : sal_uInt16 nCount = 0;
1428 0 : rStream.ReadUInt16( nCount );
1429 :
1430 0 : const size_t nMinRecordSize = sizeof(sal_uInt16) * 2;
1431 0 : const size_t nMaxRecords = rStream.remainingSize() / nMinRecordSize;
1432 0 : if (nCount > nMaxRecords)
1433 : {
1434 : SAL_WARN("svl", "Parsing error: " << nMaxRecords <<
1435 : " max possible entries, but " << nCount << " claimed, truncating");
1436 0 : nCount = nMaxRecords;
1437 : }
1438 :
1439 0 : for ( sal_uInt16 i = 0; i < nCount; ++i )
1440 : {
1441 : // Load Surrogate/Item and resolve Surrogate
1442 : const SfxPoolItem *pItem =
1443 0 : m_pPool->LoadItem( rStream, bDirect, pRefPool );
1444 :
1445 : // Did we load an Item or resolve a Surrogate?
1446 0 : if ( pItem )
1447 : {
1448 : // Find position for Item pointer in the set
1449 0 : sal_uInt16 nWhich = pItem->Which();
1450 0 : SfxItemArray ppFnd = m_pItems;
1451 0 : const sal_uInt16* pPtr = m_pWhichRanges;
1452 0 : while ( *pPtr )
1453 : {
1454 : // In this Range??
1455 0 : if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1456 : {
1457 : // Remember Item pointer in the set
1458 0 : ppFnd += nWhich - *pPtr;
1459 : SFX_ASSERT( !*ppFnd, nWhich, "Item is present twice");
1460 0 : *ppFnd = pItem;
1461 0 : ++m_nCount;
1462 0 : break;
1463 : }
1464 :
1465 : // In the range array and Item array to the next Which range
1466 0 : ppFnd += *(pPtr+1) - *pPtr + 1;
1467 0 : pPtr += 2;
1468 : }
1469 : }
1470 : }
1471 :
1472 0 : return rStream;
1473 : }
1474 :
1475 1104257 : bool SfxItemSet::operator==(const SfxItemSet &rCmp) const
1476 : {
1477 : // Values we can get quickly need to be the same
1478 3311085 : if ( m_pParent != rCmp.m_pParent ||
1479 1980705 : m_pPool != rCmp.m_pPool ||
1480 876448 : Count() != rCmp.Count() )
1481 562119 : return false;
1482 :
1483 : // Counting Ranges takes longer; they also need to be the same, however
1484 542138 : sal_uInt16 nCount1 = TotalCount();
1485 542138 : sal_uInt16 nCount2 = rCmp.TotalCount();
1486 542138 : if ( nCount1 != nCount2 )
1487 2202 : return false;
1488 :
1489 : // Are the Ranges themselves unequal?
1490 1147336 : for (sal_uInt16 nRange = 0; m_pWhichRanges[nRange]; nRange += 2)
1491 : {
1492 1214800 : if (m_pWhichRanges[nRange] != rCmp.m_pWhichRanges[nRange] ||
1493 607400 : m_pWhichRanges[nRange+1] != rCmp.m_pWhichRanges[nRange+1])
1494 : {
1495 : // We must use the slow method then
1496 0 : SfxWhichIter aIter( *this );
1497 0 : for ( sal_uInt16 nWh = aIter.FirstWhich();
1498 : nWh;
1499 : nWh = aIter.NextWhich() )
1500 : {
1501 : // If the pointer of the poolable Items are unequal, the Items must match
1502 0 : const SfxPoolItem *pItem1 = 0, *pItem2 = 0;
1503 0 : if ( GetItemState( nWh, false, &pItem1 ) !=
1504 0 : rCmp.GetItemState( nWh, false, &pItem2 ) ||
1505 0 : ( pItem1 != pItem2 &&
1506 0 : ( !pItem1 || IsInvalidItem(pItem1) ||
1507 0 : (m_pPool->IsItemFlag(*pItem1, SfxItemPoolFlags::POOLABLE) &&
1508 0 : *pItem1 != *pItem2 ) ) ) )
1509 0 : return false;
1510 : }
1511 :
1512 0 : return true;
1513 : }
1514 : }
1515 :
1516 : // Are all pointers the same?
1517 539936 : if (0 == memcmp( m_pItems, rCmp.m_pItems, nCount1 * sizeof(m_pItems[0]) ))
1518 524082 : return true;
1519 :
1520 : // We need to compare each one separately then
1521 15854 : const SfxPoolItem **ppItem1 = m_pItems;
1522 15854 : const SfxPoolItem **ppItem2 = rCmp.m_pItems;
1523 243918 : for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos )
1524 : {
1525 : // If the pointers of the poolable Items are not the same, the Items
1526 : // must match
1527 282952 : if ( *ppItem1 != *ppItem2 &&
1528 76195 : ( ( !*ppItem1 || !*ppItem2 ) ||
1529 74709 : ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) ||
1530 37183 : (m_pPool->IsItemFlag(**ppItem1, SfxItemPoolFlags::POOLABLE)) ||
1531 12280 : **ppItem1 != **ppItem2 ) )
1532 14531 : return false;
1533 :
1534 228064 : ++ppItem1;
1535 228064 : ++ppItem2;
1536 : }
1537 :
1538 1323 : return true;
1539 : }
1540 :
1541 730624 : SfxItemSet *SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
1542 : {
1543 730624 : if (pToPool && pToPool != m_pPool)
1544 : {
1545 13024 : SfxItemSet *pNewSet = new SfxItemSet(*pToPool, m_pWhichRanges);
1546 13024 : if ( bItems )
1547 : {
1548 327 : SfxWhichIter aIter(*pNewSet);
1549 327 : sal_uInt16 nWhich = aIter.FirstWhich();
1550 6324 : while ( nWhich )
1551 : {
1552 : const SfxPoolItem* pItem;
1553 5670 : if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
1554 9 : pNewSet->Put( *pItem, pItem->Which() );
1555 5670 : nWhich = aIter.NextWhich();
1556 327 : }
1557 : }
1558 13024 : return pNewSet;
1559 : }
1560 : else
1561 : return bItems
1562 706608 : ? new SfxItemSet(*this)
1563 1424208 : : new SfxItemSet(*m_pPool, m_pWhichRanges);
1564 : }
1565 :
1566 3586550 : void SfxItemSet::PutDirect(const SfxPoolItem &rItem)
1567 : {
1568 3586550 : SfxItemArray ppFnd = m_pItems;
1569 3586550 : const sal_uInt16* pPtr = m_pWhichRanges;
1570 3586550 : const sal_uInt16 nWhich = rItem.Which();
1571 : #ifdef DBG_UTIL
1572 : IsPoolDefaultItem(&rItem) || m_pPool->GetSurrogate(&rItem);
1573 : // Only cause assertion in the callees
1574 : #endif
1575 7962028 : while( *pPtr )
1576 : {
1577 4375478 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1578 : {
1579 : // In this Range?
1580 3586550 : ppFnd += nWhich - *pPtr;
1581 3586550 : const SfxPoolItem* pOld = *ppFnd;
1582 3586550 : if( pOld ) // One already present
1583 : {
1584 408 : if( rItem == **ppFnd )
1585 0 : return; // Already present!
1586 408 : m_pPool->Remove( *pOld );
1587 : }
1588 : else
1589 3586142 : ++m_nCount;
1590 :
1591 : // Add the new one
1592 3586550 : if( IsPoolDefaultItem(&rItem) )
1593 100898 : *ppFnd = &m_pPool->Put( rItem );
1594 : else
1595 : {
1596 3485652 : *ppFnd = &rItem;
1597 3485652 : if( !IsStaticDefaultItem( &rItem ) )
1598 2043283 : rItem.AddRef();
1599 : }
1600 :
1601 3586550 : return;
1602 : }
1603 788928 : ppFnd += *(pPtr+1) - *pPtr + 1;
1604 788928 : pPtr += 2;
1605 : }
1606 : }
1607 :
1608 0 : sal_Int32 SfxItemSet::getHash() const
1609 : {
1610 0 : return stringify().hashCode();
1611 : }
1612 :
1613 0 : OString SfxItemSet::stringify() const
1614 : {
1615 0 : SvMemoryStream aStream;
1616 0 : SfxItemSet aSet(*this);
1617 0 : aSet.InvalidateDefaultItems();
1618 0 : aSet.Store(aStream, true);
1619 0 : aStream.Flush();
1620 : return OString(
1621 0 : static_cast<char const *>(aStream.GetData()), aStream.GetEndOfData());
1622 : }
1623 :
1624 0 : void SfxItemSet::dumpAsXml(xmlTextWriterPtr pWriter) const
1625 : {
1626 0 : xmlTextWriterStartElement(pWriter, BAD_CAST("sfxItemSet"));
1627 0 : SfxItemIter aIter(*this);
1628 0 : for (const SfxPoolItem* pItem = aIter.FirstItem(); pItem; pItem = aIter.NextItem())
1629 0 : pItem->dumpAsXml(pWriter);
1630 0 : xmlTextWriterEndElement(pWriter);
1631 0 : }
1632 :
1633 :
1634 : // ----------------------------------------------- class SfxAllItemSet
1635 :
1636 42635 : SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool )
1637 : : SfxItemSet(rPool, nullptr),
1638 : aDefault(0),
1639 42635 : nFree(nInitCount)
1640 : {
1641 : // Initially no Items
1642 42635 : m_pItems = nullptr;
1643 :
1644 : // Allocate nInitCount pairs at USHORTs for Ranges
1645 42635 : m_pWhichRanges = new sal_uInt16[ nInitCount + 1 ];
1646 42635 : memset( m_pWhichRanges, 0, (nInitCount + 1) * sizeof(sal_uInt16) );
1647 42635 : }
1648 :
1649 727 : SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy)
1650 : : SfxItemSet(rCopy),
1651 : aDefault(0),
1652 727 : nFree(0)
1653 : {
1654 727 : }
1655 :
1656 : /**
1657 : * Explicitly define this ctor to avoid auto-generation by the compiler.
1658 : * The compiler does not take the ctor with the 'const SfxItemSet&'!
1659 : */
1660 4247 : SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy)
1661 : : SfxItemSet(rCopy),
1662 : aDefault(0),
1663 4247 : nFree(0)
1664 : {
1665 4247 : }
1666 :
1667 : /**
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
1670 : * of 'nIncr'.
1671 : * The terminating sal_uInt16 with the '0' is neither accounted for in 'nOldSize'
1672 : * nor in 'nIncr', but always explicitly added.
1673 : *
1674 : * @returns the new WhichRanges array (the old 'pUS' is freed)
1675 : */
1676 13208 : static sal_uInt16 *AddRanges_Impl(
1677 : sal_uInt16 *pUS, std::ptrdiff_t nOldSize, sal_uInt16 nIncr)
1678 : {
1679 : // Create new WhichRanges array
1680 13208 : sal_uInt16 *pNew = new sal_uInt16[ nOldSize + nIncr + 1 ];
1681 :
1682 : // Take over the old Ranges
1683 13208 : memcpy( pNew, pUS, nOldSize * sizeof(sal_uInt16) );
1684 :
1685 : // Initialize the new one to 0
1686 13208 : memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(sal_uInt16) );
1687 :
1688 : // Free the old array
1689 13208 : delete[] pUS;
1690 :
1691 13208 : return pNew;
1692 : }
1693 :
1694 : /**
1695 : * This internal function creates a new ItemArray, which is copied from 'pItems',
1696 : * but has room for a new ItemPointer at 'nPos'.
1697 : *
1698 : * @returns the new ItemArray (the old 'pItems' is freed)
1699 : */
1700 122667 : static SfxItemArray AddItem_Impl(SfxItemArray pItems, sal_uInt16 nOldSize, sal_uInt16 nPos)
1701 : {
1702 : // Create new ItemArray
1703 122667 : SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1];
1704 :
1705 : // Was there one before?
1706 122667 : if ( pItems )
1707 : {
1708 : // Copy all Items before nPos
1709 95813 : if ( nPos )
1710 95813 : memcpy( static_cast<void*>(pNew), pItems, nPos * sizeof(SfxPoolItem *) );
1711 :
1712 : // Copy all Items after nPos
1713 95813 : if ( nPos < nOldSize )
1714 2356 : memcpy( static_cast<void*>(pNew + nPos + 1), pItems + nPos,
1715 3534 : (nOldSize-nPos) * sizeof(SfxPoolItem *) );
1716 : }
1717 :
1718 : // Initialize new Item
1719 122667 : *(pNew + nPos) = 0;
1720 :
1721 : // Free old ItemArray
1722 122667 : delete[] pItems;
1723 :
1724 122667 : return pNew;
1725 : }
1726 :
1727 : /**
1728 : * Putting with automatic extension of the WhichId with the ID of the Item.
1729 : */
1730 160416 : const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
1731 : {
1732 160416 : sal_uInt16 nPos = 0; // Position for 'rItem' in 'm_pItems'
1733 160416 : const sal_uInt16 nItemCount = TotalCount();
1734 :
1735 : // Let's see first whether there's a suitable Range already
1736 160416 : sal_uInt16 *pPtr = m_pWhichRanges;
1737 816206 : while ( *pPtr )
1738 : {
1739 : // WhichId is within this Range?
1740 533123 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1741 : {
1742 : // Insert
1743 37749 : nPos += nWhich - *pPtr;
1744 37749 : break;
1745 : }
1746 :
1747 : // Carry over the position of the Item in m_pItems
1748 495374 : nPos += *(pPtr+1) - *pPtr + 1;
1749 :
1750 : // To the next Range
1751 495374 : pPtr += 2;
1752 : }
1753 :
1754 : // WhichId not yet present?
1755 160416 : if ( !*pPtr )
1756 : {
1757 : // Let's see if we can attach it somewhere
1758 122667 : pPtr = m_pWhichRanges;
1759 122667 : nPos = 0;
1760 594388 : while ( *pPtr )
1761 : {
1762 : // WhichId is right before this Range?
1763 350320 : if ( (nWhich+1) == *pPtr )
1764 : {
1765 : // Range grows downwards
1766 579 : (*pPtr)--;
1767 :
1768 : // Make room before first Item of this Range
1769 579 : m_pItems = AddItem_Impl(m_pItems, nItemCount, nPos);
1770 579 : break;
1771 : }
1772 :
1773 : // WhichId is right after this Range?
1774 349741 : else if ( (nWhich-1) == *(pPtr+1) )
1775 : {
1776 : // Range grows upwards?
1777 687 : (*(pPtr+1))++;
1778 :
1779 : // Make room after last Item of this Range
1780 687 : nPos += nWhich - *pPtr;
1781 687 : m_pItems = AddItem_Impl(m_pItems, nItemCount, nPos);
1782 687 : break;
1783 : }
1784 :
1785 : // Carry over position of the Item in m_pItems
1786 349054 : nPos += *(pPtr+1) - *pPtr + 1;
1787 :
1788 : // To the next Range
1789 349054 : pPtr += 2;
1790 : }
1791 : }
1792 :
1793 : // No extensible Range found?
1794 160416 : if ( !*pPtr )
1795 : {
1796 : // No room left in m_pWhichRanges? => Expand!
1797 121401 : std::ptrdiff_t nSize = pPtr - m_pWhichRanges;
1798 121401 : if( !nFree )
1799 : {
1800 13208 : m_pWhichRanges = AddRanges_Impl(m_pWhichRanges, nSize, nInitCount);
1801 13208 : nFree += nInitCount;
1802 : }
1803 :
1804 : // Attach new WhichRange
1805 121401 : pPtr = m_pWhichRanges + nSize;
1806 121401 : *pPtr++ = nWhich;
1807 121401 : *pPtr = nWhich;
1808 121401 : nFree -= 2;
1809 :
1810 : // Expand ItemArray
1811 121401 : nPos = nItemCount;
1812 121401 : m_pItems = AddItem_Impl(m_pItems, nItemCount, nPos);
1813 : }
1814 :
1815 : // Add new Item to Pool
1816 160416 : const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich );
1817 :
1818 : // Remember old Item
1819 160416 : bool bIncrementCount = false;
1820 160416 : const SfxPoolItem* pOld = *( m_pItems + nPos );
1821 160416 : if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld ) // state "dontcare"
1822 0 : pOld = NULL;
1823 160416 : if ( !pOld )
1824 : {
1825 122701 : bIncrementCount = true;
1826 : pOld = (m_pParent)
1827 0 : ? &m_pParent->Get( nWhich, true )
1828 : : ((nWhich <= SFX_WHICH_MAX)
1829 1 : ? &m_pPool->GetDefaultItem(nWhich)
1830 122702 : : nullptr);
1831 : }
1832 :
1833 : // Add new Item to ItemSet
1834 160416 : *(m_pItems + nPos) = &rNew;
1835 :
1836 : // Send Changed Notification
1837 160416 : if ( pOld )
1838 : {
1839 37716 : Changed( *pOld, rNew );
1840 37716 : if ( !IsDefaultItem(pOld) )
1841 37715 : m_pPool->Remove( *pOld );
1842 : }
1843 :
1844 160416 : if ( bIncrementCount )
1845 122701 : ++m_nCount;
1846 :
1847 160416 : return &rNew;
1848 : }
1849 :
1850 : /**
1851 : * Disable Item
1852 : * Using a VoidItem with Which value 0
1853 : */
1854 351078 : void SfxItemSet::DisableItem(sal_uInt16 nWhich)
1855 : {
1856 351078 : Put( SfxVoidItem(0), nWhich );
1857 351078 : }
1858 :
1859 0 : SfxItemSet *SfxAllItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
1860 : {
1861 0 : if (pToPool && pToPool != m_pPool)
1862 : {
1863 0 : SfxAllItemSet *pNewSet = new SfxAllItemSet( *pToPool );
1864 0 : if ( bItems )
1865 0 : pNewSet->Set( *this );
1866 0 : return pNewSet;
1867 : }
1868 : else
1869 0 : return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*m_pPool);
1870 : }
1871 :
1872 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|