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 :
25 : #include <svl/itemset.hxx>
26 : #include <svl/itempool.hxx>
27 : #include <svl/itemiter.hxx>
28 : #include <svl/whiter.hxx>
29 : #include <svl/nranges.hxx>
30 : #include "whassert.hxx"
31 :
32 : #include <tools/stream.hxx>
33 : #include <tools/solar.h>
34 : #include <rtl/string.hxx>
35 :
36 : // STATIC DATA
37 :
38 : static const sal_uInt16 nInitCount = 10; // Single USHORTs => 5 pairs without '0'
39 : #if OSL_DEBUG_LEVEL > 1
40 : static sal_uLong nRangesCopyCount = 0; // How often have ranges been copied?
41 : #endif
42 :
43 : #include "nranges.cxx"
44 : #include "poolio.hxx"
45 :
46 :
47 : #ifdef DBG_UTIL
48 :
49 :
50 : const sal_Char *DbgCheckItemSet( const void* pVoid )
51 : {
52 : const SfxItemSet *pSet = (const SfxItemSet*) pVoid;
53 : SfxWhichIter aIter( *pSet );
54 : sal_uInt16 nCount = 0, n = 0;
55 : for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh; nWh = aIter.NextWhich(), ++n )
56 : {
57 : const SfxPoolItem *pItem = pSet->_aItems[n];
58 : if ( pItem )
59 : {
60 : ++nCount;
61 : DBG_ASSERT( IsInvalidItem(pItem) ||
62 : pItem->Which() == 0 || pItem->Which() == nWh,
63 : "SfxItemSet: invalid which-id" );
64 : DBG_ASSERT( IsInvalidItem(pItem) || !pItem->Which() ||
65 : !SfxItemPool::IsWhich(pItem->Which()) ||
66 : pSet->GetPool()->IsItemFlag(nWh, SFX_ITEM_NOT_POOLABLE) ||
67 : SFX_ITEMS_NULL != pSet->GetPool()->GetSurrogate(pItem),
68 : "SfxItemSet: item in set which is not in pool" );
69 : }
70 :
71 : }
72 : DBG_ASSERT( pSet->_nCount == nCount, "wrong SfxItemSet::nCount detected" );
73 :
74 : return 0;
75 : }
76 :
77 : #endif
78 :
79 : /**
80 : * Ctor for a SfxItemSet with exactly the Which Ranges, which are known to
81 : * the supplied SfxItemPool.
82 : *
83 : * For Sfx programmers: an SfxItemSet constructed in this way cannot
84 : * contain any Items with SlotIds as Which values.
85 : */
86 34505 : SfxItemSet::SfxItemSet
87 : (
88 : SfxItemPool& rPool, /* Target Pool for the SfxPoolItems which are
89 : added to this SfxItemSet */
90 : bool bTotalRanges /* Take over complete pool ranges? */
91 : )
92 : : _pPool( &rPool ),
93 : _pParent( 0 ),
94 34505 : _nCount( 0 )
95 : {
96 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "no Master Pool" );
97 : // DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
98 : // "please use suitable ranges" );
99 : #if defined DBG_UTIL && defined SFX_ITEMSET_NO_DEFAULT_CTOR
100 : if ( !bTotalRanges )
101 : *(int*)0 = 0; // GPF
102 : #else
103 : (void) bTotalRanges; // avoid warnings
104 : #endif
105 :
106 34505 : _pWhichRanges = (sal_uInt16*) _pPool->GetFrozenIdRanges();
107 : DBG_ASSERT( _pWhichRanges, "don't create ItemSets with full range before FreezeIdRanges()" );
108 34505 : if ( !_pWhichRanges )
109 0 : _pPool->FillItemIdRanges_Impl( _pWhichRanges );
110 :
111 34505 : const sal_uInt16 nSize = TotalCount();
112 34505 : _aItems = new const SfxPoolItem* [ nSize ];
113 34505 : memset( (void*) _aItems, 0, nSize * sizeof( SfxPoolItem* ) );
114 34505 : }
115 :
116 :
117 :
118 2965664 : SfxItemSet::SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2 ):
119 : _pPool( &rPool ),
120 : _pParent( 0 ),
121 2965664 : _nCount( 0 )
122 : {
123 : DBG_ASSERT( nWhich1 <= nWhich2, "Invalid range" );
124 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "no Master Pool" );
125 :
126 2965664 : InitRanges_Impl(nWhich1, nWhich2);
127 2965664 : }
128 :
129 :
130 :
131 2966022 : void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2)
132 : {
133 2966022 : _pWhichRanges = new sal_uInt16[ 3 ];
134 2966022 : *(_pWhichRanges+0) = nWh1;
135 2966022 : *(_pWhichRanges+1) = nWh2;
136 2966022 : *(_pWhichRanges+2) = 0;
137 2966022 : const sal_uInt16 nRg = nWh2 - nWh1 + 1;
138 2966022 : _aItems = new const SfxPoolItem* [ nRg ];
139 2966022 : memset( (void*) _aItems, 0, nRg * sizeof( SfxPoolItem* ) );
140 2966022 : }
141 :
142 :
143 :
144 667597 : void SfxItemSet::InitRanges_Impl(va_list pArgs, sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull)
145 : {
146 667597 : sal_uInt16 nSize = InitializeRanges_Impl( _pWhichRanges, pArgs, nWh1, nWh2, nNull );
147 667597 : _aItems = new const SfxPoolItem* [ nSize ];
148 667597 : memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nSize );
149 667597 : }
150 :
151 :
152 :
153 667955 : SfxItemSet::SfxItemSet( SfxItemPool& rPool,
154 : USHORT_ARG nWh1, USHORT_ARG nWh2, USHORT_ARG nNull, ... ):
155 : _pPool( &rPool ),
156 : _pParent( 0 ),
157 : _pWhichRanges( 0 ),
158 667955 : _nCount( 0 )
159 : {
160 : DBG_ASSERT( nWh1 <= nWh2, "Invalid range" );
161 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "no Master Pool" );
162 :
163 667955 : if(!nNull)
164 : InitRanges_Impl(
165 358 : sal::static_int_cast< sal_uInt16 >(nWh1),
166 716 : sal::static_int_cast< sal_uInt16 >(nWh2));
167 : else {
168 : va_list pArgs;
169 667597 : va_start( pArgs, nNull );
170 : InitRanges_Impl(
171 667597 : pArgs, sal::static_int_cast< sal_uInt16 >(nWh1),
172 667597 : sal::static_int_cast< sal_uInt16 >(nWh2),
173 2002791 : sal::static_int_cast< sal_uInt16 >(nNull));
174 667597 : va_end(pArgs);
175 : }
176 667955 : }
177 :
178 :
179 :
180 8726034 : void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable)
181 : {
182 : #if OSL_DEBUG_LEVEL > 1
183 : OSL_TRACE("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
184 : #endif
185 :
186 8726034 : sal_uInt16 nCnt = 0;
187 8726034 : const sal_uInt16* pPtr = pWhichPairTable;
188 47855238 : while( *pPtr )
189 : {
190 30403170 : nCnt += ( *(pPtr+1) - *pPtr ) + 1;
191 30403170 : pPtr += 2;
192 : }
193 :
194 8726034 : _aItems = new const SfxPoolItem* [ nCnt ];
195 8726034 : memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nCnt );
196 :
197 8726034 : std::ptrdiff_t cnt = pPtr - pWhichPairTable +1;
198 8726034 : _pWhichRanges = new sal_uInt16[ cnt ];
199 8726034 : memcpy( _pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt );
200 8726034 : }
201 :
202 :
203 :
204 :
205 8786185 : SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable )
206 : : _pPool(&rPool)
207 : , _pParent(0)
208 : , _aItems(0)
209 : , _pWhichRanges(0)
210 8786185 : , _nCount(0)
211 : {
212 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "no Master Pool" );
213 :
214 : // pWhichPairTable == 0 ist f"ur das SfxAllEnumItemSet
215 8786185 : if ( pWhichPairTable )
216 8726034 : InitRanges_Impl(pWhichPairTable);
217 8786185 : }
218 :
219 7409380 : SfxItemSet::SfxItemSet( const SfxItemSet& rASet ):
220 : _pPool( rASet._pPool ),
221 : _pParent( rASet._pParent ),
222 7409380 : _nCount( rASet._nCount )
223 : {
224 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "no Master Pool" );
225 :
226 : // Calculate the attribute count
227 7409380 : sal_uInt16 nCnt = 0;
228 7409380 : sal_uInt16* pPtr = rASet._pWhichRanges;
229 66934649 : while( *pPtr )
230 : {
231 52115889 : nCnt += ( *(pPtr+1) - *pPtr ) + 1;
232 52115889 : pPtr += 2;
233 : }
234 :
235 7409380 : _aItems = new const SfxPoolItem* [ nCnt ];
236 :
237 : // Copy attributes
238 7409380 : SfxItemArray ppDst = _aItems, ppSrc = rASet._aItems;
239 560289918 : for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc )
240 1128951821 : if ( 0 == *ppSrc || // Current Default?
241 576068971 : IsInvalidItem(*ppSrc) || // DontCare?
242 23188433 : IsStaticDefaultItem(*ppSrc) ) // Defaults that are not to be pooled?
243 : // Just copy the pointer
244 529768125 : *ppDst = *ppSrc;
245 23112413 : else if ( _pPool->IsItemFlag( **ppSrc, SFX_ITEM_POOLABLE ) )
246 : {
247 : // Just copy the pointer and increase RefCount
248 20077530 : *ppDst = *ppSrc;
249 20077530 : ( (SfxPoolItem*) (*ppDst) )->AddRef();
250 : }
251 3034883 : else if ( !(*ppSrc)->Which() )
252 0 : *ppDst = (*ppSrc)->Clone();
253 : else
254 : // !IsPoolable() => assign via Pool
255 3034883 : *ppDst = &_pPool->Put( **ppSrc );
256 :
257 : // Copy the WhichRanges
258 : #if OSL_DEBUG_LEVEL > 1
259 : OSL_TRACE("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
260 : #endif
261 7409380 : std::ptrdiff_t cnt = pPtr - rASet._pWhichRanges+1;
262 7409380 : _pWhichRanges = new sal_uInt16[ cnt ];
263 7409380 : memcpy( _pWhichRanges, rASet._pWhichRanges, sizeof( sal_uInt16 ) * cnt);
264 7409380 : }
265 :
266 :
267 :
268 22195095 : SfxItemSet::~SfxItemSet()
269 : {
270 19858972 : sal_uInt16 nCount = TotalCount();
271 19858972 : if( Count() )
272 : {
273 11017897 : SfxItemArray ppFnd = _aItems;
274 1248175208 : for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd )
275 1237157311 : if( *ppFnd && !IsInvalidItem(*ppFnd) )
276 : {
277 45531845 : if( !(*ppFnd)->Which() )
278 13081 : delete (SfxPoolItem*) *ppFnd;
279 : else {
280 : // Still multiple references present, so just alter the RefCount
281 45518764 : if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) )
282 39225506 : (*ppFnd)->ReleaseRef();
283 : else
284 6293258 : if ( !IsDefaultItem(*ppFnd) )
285 : // Delete from Pool
286 5602586 : _pPool->Remove( **ppFnd );
287 : }
288 : }
289 : }
290 :
291 : // FIXME: could be delete[] (SfxPoolItem **)_aItems;
292 19858972 : delete[] _aItems;
293 19858972 : if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
294 19824543 : delete[] _pWhichRanges;
295 19858972 : _pWhichRanges = 0; // for invariant-testing
296 22195095 : }
297 :
298 :
299 : /**
300 : * Delete single Items or all Items (nWhich == 0)
301 : */
302 9190982 : sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
303 : {
304 9190982 : if( !Count() )
305 3448442 : return 0;
306 :
307 5742540 : sal_uInt16 nDel = 0;
308 5742540 : SfxItemArray ppFnd = _aItems;
309 :
310 5742540 : if( nWhich )
311 : {
312 4833870 : const sal_uInt16* pPtr = _pWhichRanges;
313 15055708 : while( *pPtr )
314 : {
315 : // Within this range?
316 10087457 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
317 : {
318 : // Actually set?
319 4699489 : ppFnd += nWhich - *pPtr;
320 4699489 : if( *ppFnd )
321 : {
322 : // Due to the assertions in the sub calls, we need to do the following
323 295279 : --_nCount;
324 295279 : const SfxPoolItem *pItemToClear = *ppFnd;
325 295279 : *ppFnd = 0;
326 :
327 295279 : if ( !IsInvalidItem(pItemToClear) )
328 : {
329 295279 : if ( nWhich <= SFX_WHICH_MAX )
330 : {
331 : const SfxPoolItem& rNew = _pParent
332 107380 : ? _pParent->Get( nWhich, true )
333 373072 : : _pPool->GetDefaultItem( nWhich );
334 :
335 265692 : Changed( *pItemToClear, rNew );
336 : }
337 295279 : if ( pItemToClear->Which() )
338 295279 : _pPool->Remove( *pItemToClear );
339 : }
340 295279 : ++nDel;
341 : }
342 :
343 : // found => break
344 4699489 : break;
345 : }
346 5387968 : ppFnd += *(pPtr+1) - *pPtr + 1;
347 5387968 : pPtr += 2;
348 : }
349 : }
350 : else
351 : {
352 908670 : nDel = _nCount;
353 :
354 908670 : sal_uInt16* pPtr = _pWhichRanges;
355 13899650 : while( *pPtr )
356 : {
357 124371378 : for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
358 112289068 : if( *ppFnd )
359 : {
360 : // Due to the assertions in the sub calls, we need to do this
361 3290068 : --_nCount;
362 3290068 : const SfxPoolItem *pItemToClear = *ppFnd;
363 3290068 : *ppFnd = 0;
364 :
365 3290068 : if ( !IsInvalidItem(pItemToClear) )
366 : {
367 3289762 : if ( nWhich <= SFX_WHICH_MAX )
368 : {
369 : const SfxPoolItem& rNew = _pParent
370 1500082 : ? _pParent->Get( nWhich, true )
371 3912952 : : _pPool->GetDefaultItem( nWhich );
372 :
373 2412870 : Changed( *pItemToClear, rNew );
374 : }
375 :
376 : // #i32448#
377 : // Take care of disabled items, too.
378 3289762 : if (!pItemToClear->m_nWhich)
379 : {
380 : // item is disabled, delete it
381 0 : delete pItemToClear;
382 : }
383 : else
384 : {
385 : // remove item from pool
386 3289762 : _pPool->Remove( *pItemToClear );
387 : }
388 : }
389 : }
390 12082310 : pPtr += 2;
391 : }
392 : }
393 5742540 : return nDel;
394 : }
395 :
396 :
397 :
398 355583 : void SfxItemSet::ClearInvalidItems( bool bHardDefault )
399 : {
400 355583 : sal_uInt16* pPtr = _pWhichRanges;
401 355583 : SfxItemArray ppFnd = _aItems;
402 355583 : if ( bHardDefault )
403 0 : while( *pPtr )
404 : {
405 0 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
406 0 : if ( IsInvalidItem(*ppFnd) )
407 0 : *ppFnd = &_pPool->Put( _pPool->GetDefaultItem(nWhich) );
408 0 : pPtr += 2;
409 : }
410 : else
411 6582561 : while( *pPtr )
412 : {
413 56682694 : for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
414 50811299 : if( IsInvalidItem(*ppFnd) )
415 : {
416 1214 : *ppFnd = 0;
417 1214 : --_nCount;
418 : }
419 5871395 : pPtr += 2;
420 : }
421 355583 : }
422 :
423 0 : void SfxItemSet::InvalidateDefaultItems()
424 : {
425 0 : sal_uInt16* pPtr = _pWhichRanges;
426 0 : SfxItemArray ppFnd = _aItems;
427 :
428 0 : while( *pPtr )
429 : {
430 0 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
431 0 : if ( *ppFnd && *ppFnd != reinterpret_cast<SfxPoolItem *>(-1) && **ppFnd == _pPool->GetDefaultItem( nWhich ) )
432 : {
433 0 : _pPool->Remove( **ppFnd );
434 0 : *ppFnd = reinterpret_cast<SfxPoolItem*>(-1);
435 : }
436 0 : pPtr += 2;
437 : }
438 0 : }
439 :
440 0 : void SfxItemSet::InvalidateAllItems()
441 : {
442 : DBG_ASSERT( !_nCount, "There are still Items set" );
443 :
444 0 : memset( (void*)_aItems, -1, ( _nCount = TotalCount() ) * sizeof( SfxPoolItem*) );
445 0 : }
446 :
447 :
448 :
449 197655943 : SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich,
450 : bool bSrchInParent,
451 : const SfxPoolItem **ppItem ) const
452 : {
453 : // Find the range in which the Which is located
454 197655943 : const SfxItemSet* pAktSet = this;
455 197655943 : SfxItemState eRet = SfxItemState::UNKNOWN;
456 177105948 : do
457 : {
458 235308370 : SfxItemArray ppFnd = pAktSet->_aItems;
459 235308370 : const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
460 235308370 : if (pPtr)
461 : {
462 699934533 : while ( *pPtr )
463 : {
464 444875787 : if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
465 : {
466 : // Within this range
467 215557994 : ppFnd += nWhich - *pPtr;
468 215557994 : if ( !*ppFnd )
469 : {
470 187319731 : eRet = SfxItemState::DEFAULT;
471 187319731 : if( !bSrchInParent )
472 29964159 : return eRet; // Not present
473 157355572 : break; // Keep searching in the parents!
474 : }
475 :
476 28238263 : if ( reinterpret_cast<SfxPoolItem*>(-1) == *ppFnd )
477 : // Different ones are present
478 694 : return SfxItemState::DONTCARE;
479 :
480 28237569 : if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) )
481 20222 : return SfxItemState::DISABLED;
482 :
483 28217347 : if (ppItem)
484 : {
485 15621293 : *ppItem = *ppFnd;
486 : }
487 28217347 : return SfxItemState::SET;
488 : }
489 229317793 : ppFnd += *(pPtr+1) - *pPtr + 1;
490 229317793 : pPtr += 2;
491 : }
492 : }
493 177105948 : } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
494 139453521 : return eRet;
495 : }
496 :
497 6928274 : bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const
498 : {
499 6928274 : bool bRet = SfxItemState::SET == GetItemState(nWhich, true, ppItem);
500 6928274 : if (!bRet && ppItem)
501 54739 : *ppItem = NULL;
502 6928274 : return bRet;
503 : }
504 :
505 :
506 :
507 37642088 : const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
508 : {
509 37642088 : if ( !nWhich )
510 122 : return 0; //FIXME: Only because of Outliner bug
511 :
512 37641966 : SfxItemArray ppFnd = _aItems;
513 37641966 : const sal_uInt16* pPtr = _pWhichRanges;
514 124532308 : while( *pPtr )
515 : {
516 81155799 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
517 : {
518 : // Within this range
519 31907423 : ppFnd += nWhich - *pPtr;
520 31907423 : if( *ppFnd ) // Already one present
521 : {
522 : // Same Item already present?
523 8399849 : if ( *ppFnd == &rItem )
524 5332089 : return 0;
525 :
526 : // Will 'dontcare' or 'disabled' be overwritten with some real value?
527 3067760 : if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) )
528 : {
529 18 : *ppFnd = &_pPool->Put( rItem, nWhich );
530 18 : return *ppFnd;
531 : }
532 :
533 : // Turns into disabled?
534 3067742 : if( !rItem.Which() )
535 : {
536 14 : *ppFnd = rItem.Clone(_pPool);
537 14 : return 0;
538 : }
539 : else
540 : {
541 : // Same value already present?
542 3067728 : if ( rItem == **ppFnd )
543 1721681 : return 0;
544 :
545 : // Add the new one, remove the old one
546 1346047 : const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
547 1346047 : const SfxPoolItem* pOld = *ppFnd;
548 1346047 : *ppFnd = &rNew;
549 1346047 : if(nWhich <= SFX_WHICH_MAX)
550 1329422 : Changed( *pOld, rNew );
551 1346047 : _pPool->Remove( *pOld );
552 : }
553 : }
554 : else
555 : {
556 23507574 : ++_nCount;
557 23507574 : if( !rItem.Which() )
558 13067 : *ppFnd = rItem.Clone(_pPool);
559 : else {
560 23494507 : const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
561 23494507 : *ppFnd = &rNew;
562 23494507 : if (nWhich <= SFX_WHICH_MAX )
563 : {
564 : const SfxPoolItem& rOld = _pParent
565 2902569 : ? _pParent->Get( nWhich, true )
566 25102134 : : _pPool->GetDefaultItem( nWhich );
567 22199565 : Changed( rOld, rNew );
568 : }
569 : }
570 : }
571 : SFX_ASSERT( !_pPool->IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
572 : rItem.ISA(SfxSetItem) || **ppFnd == rItem,
573 : nWhich, "putted Item unequal" );
574 24853621 : return *ppFnd;
575 : }
576 49248376 : ppFnd += *(pPtr+1) - *pPtr + 1;
577 49248376 : pPtr += 2;
578 : }
579 5734543 : return 0;
580 : }
581 :
582 :
583 :
584 3088331 : bool SfxItemSet::Put( const SfxItemSet& rSet, bool bInvalidAsDefault )
585 : {
586 3088331 : bool bRet = false;
587 3088331 : if( rSet.Count() )
588 : {
589 2775242 : SfxItemArray ppFnd = rSet._aItems;
590 2775242 : const sal_uInt16* pPtr = rSet._pWhichRanges;
591 20528426 : while ( *pPtr )
592 : {
593 340915316 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
594 325937374 : if( *ppFnd )
595 : {
596 14519761 : if ( IsInvalidItem( *ppFnd ) )
597 : {
598 48 : if ( bInvalidAsDefault )
599 0 : bRet |= 0 != ClearItem( nWhich );
600 : // FIXME: Caused a SEGFAULT on non Windows-platforms:
601 : // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
602 : else
603 48 : InvalidateItem( nWhich );
604 : }
605 : else
606 14519713 : bRet |= 0 != Put( **ppFnd, nWhich );
607 : }
608 14977942 : pPtr += 2;
609 : }
610 : }
611 3088331 : return bRet;
612 : }
613 :
614 :
615 : /**
616 : * This method takes the Items from the 'rSet' and adds to '*this'.
617 : * Which ranges in '*this' that are non-existent in 'rSet' will not
618 : * be altered. The Which range of '*this' is also not changed.
619 : *
620 : * Items set in 'rSet' are also set in '*this'.
621 : * Default (0 pointer) and Invalid (-1 pointer) Items are processed
622 : * according to their parameter 'eDontCareAs' and 'eDefaultAs':
623 : *
624 : * SfxItemState::SET: Hard set to the default of the Pool
625 : * SfxItemState::DEFAULT: Deleted (0 pointer)
626 : * SfxItemState::DONTCARE: Invalid (-1 pointer)
627 : *
628 : * NB: All other values for 'eDontCareAs' and 'eDefaultAs' are invalid
629 : */
630 1252 : void SfxItemSet::PutExtended
631 : (
632 : const SfxItemSet& rSet, // Source of the Items to be put
633 : SfxItemState eDontCareAs, // What will happen to the DontCare Items
634 : SfxItemState eDefaultAs // What will happen to the Default Items
635 : )
636 : {
637 : // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
638 1252 : SfxItemArray ppFnd = rSet._aItems;
639 1252 : const sal_uInt16* pPtr = rSet._pWhichRanges;
640 3788 : while ( *pPtr )
641 : {
642 71276 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
643 69992 : if( *ppFnd )
644 : {
645 190 : if ( IsInvalidItem( *ppFnd ) )
646 : {
647 : // Item ist DontCare:
648 0 : switch ( eDontCareAs )
649 : {
650 : case SfxItemState::SET:
651 0 : Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
652 0 : break;
653 :
654 : case SfxItemState::DEFAULT:
655 0 : ClearItem( nWhich );
656 0 : break;
657 :
658 : case SfxItemState::DONTCARE:
659 0 : InvalidateItem( nWhich );
660 0 : break;
661 :
662 : default:
663 : OSL_FAIL( "invalid Argument for eDontCareAs" );
664 : }
665 : }
666 : else
667 : // Item is set:
668 190 : Put( **ppFnd, nWhich );
669 : }
670 : else
671 : {
672 : // Item is default:
673 69802 : switch ( eDefaultAs )
674 : {
675 : case SfxItemState::SET:
676 68250 : Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
677 68250 : break;
678 :
679 : case SfxItemState::DEFAULT:
680 1552 : ClearItem( nWhich );
681 1552 : break;
682 :
683 : case SfxItemState::DONTCARE:
684 0 : InvalidateItem( nWhich );
685 0 : break;
686 :
687 : default:
688 : OSL_FAIL( "invalid Argument for eDefaultAs" );
689 : }
690 : }
691 1284 : pPtr += 2;
692 : }
693 1252 : }
694 :
695 :
696 : /**
697 : * Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
698 : * items which are new ranges too.
699 : */
700 51040 : void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
701 : {
702 : // special case: exactly one sal_uInt16 which is already included?
703 51040 : SfxItemState eItemState = GetItemState(nFrom, false);
704 51040 : if ( nFrom == nTo && ( eItemState == SfxItemState::DEFAULT || eItemState == SfxItemState::SET ) )
705 51040 : return;
706 :
707 : // merge new range
708 51040 : SfxUShortRanges aRanges( _pWhichRanges );
709 51040 : aRanges += SfxUShortRanges( nFrom, nTo );
710 51040 : SetRanges( aRanges );
711 : }
712 :
713 :
714 : /**
715 : * Modifies the ranges of settable items. Keeps state of items which
716 : * are new ranges too.
717 : */
718 51040 : void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges )
719 : {
720 : // Identical Ranges?
721 51040 : if ( _pWhichRanges == pNewRanges )
722 0 : return;
723 51040 : const sal_uInt16* pOld = _pWhichRanges;
724 51040 : const sal_uInt16* pNew = pNewRanges;
725 280720 : while ( *pOld == *pNew )
726 : {
727 178640 : if ( !*pOld && !*pNew )
728 0 : return;
729 178640 : ++pOld, ++pNew;
730 : }
731 :
732 : // create new item-array (by iterating through all new ranges)
733 51040 : sal_uLong nSize = Capacity_Impl(pNewRanges);
734 51040 : SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ];
735 51040 : sal_uInt16 nNewCount = 0;
736 51040 : if ( _nCount == 0 )
737 51040 : memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) );
738 : else
739 : {
740 0 : sal_uInt16 n = 0;
741 0 : for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 )
742 : {
743 : // iterate through all ids in the range
744 0 : for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n )
745 : {
746 : // direct move of pointer (not via pool)
747 0 : SfxItemState eState = GetItemState( nWID, false, aNewItems+n );
748 0 : if ( SfxItemState::SET == eState )
749 : {
750 : // increment new item count and possibly increment ref count
751 0 : ++nNewCount;
752 0 : aNewItems[n]->AddRef();
753 : }
754 0 : else if ( SfxItemState::DISABLED == eState )
755 : {
756 : // put "disabled" item
757 0 : ++nNewCount;
758 0 : aNewItems[n] = new SfxVoidItem(0);
759 : }
760 0 : else if ( SfxItemState::DONTCARE == eState )
761 : {
762 0 : ++nNewCount;
763 0 : aNewItems[n] = reinterpret_cast<SfxPoolItem*>(-1);
764 : }
765 : else
766 : {
767 : // default
768 0 : aNewItems[n] = 0;
769 : }
770 : }
771 : }
772 : // free old items
773 0 : sal_uInt16 nOldTotalCount = TotalCount();
774 0 : for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem )
775 : {
776 0 : const SfxPoolItem *pItem = _aItems[nItem];
777 0 : if ( pItem && !IsInvalidItem(pItem) && pItem->Which() )
778 0 : _pPool->Remove(*pItem);
779 : }
780 : }
781 :
782 : // replace old items-array and ranges
783 51040 : delete[] _aItems;
784 51040 : _aItems = aNewItems;
785 51040 : _nCount = nNewCount;
786 :
787 51040 : if( pNewRanges == GetPool()->GetFrozenIdRanges() )
788 : {
789 0 : delete[] _pWhichRanges;
790 0 : _pWhichRanges = ( sal_uInt16* ) pNewRanges;
791 : }
792 : else
793 : {
794 51040 : sal_uInt16 nCount = Count_Impl(pNewRanges) + 1;
795 51040 : if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
796 51040 : delete[] _pWhichRanges;
797 51040 : _pWhichRanges = new sal_uInt16[ nCount ];
798 51040 : memcpy( _pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount );
799 : }
800 : }
801 :
802 :
803 : /**
804 : * The SfxItemSet takes over exactly those SfxPoolItems that are
805 : * set in rSet and are in their own Which range. All others are removed.
806 : * The SfxItemPool is retained, such that SfxPoolItems that have been
807 : * taken over, are moved from the rSet's SfxItemPool to the SfxItemPool
808 : * of *this.
809 : *
810 : * SfxPoolItems in rSet, for which holds 'IsInvalidItem() == true' are
811 : * taken over as invalid items.
812 : *
813 : * @return bool true
814 : * SfxPoolItems have been taken over
815 : *
816 : * false
817 : * No SfxPoolItems have been taken over, because
818 : * e.g. the Which ranges of SfxItemSets are not intersecting
819 : * or the intersection does not contain SfxPoolItems that are
820 : * set in rSet
821 : */
822 1477958 : bool SfxItemSet::Set
823 : (
824 : const SfxItemSet& rSet, /* The SfxItemSet, whose SfxPoolItems are
825 : to been taken over */
826 :
827 : bool bDeep /* true (default)
828 :
829 : The SfxPoolItems from the parents that may
830 : be present in rSet, are also taken over into
831 : this SfxPoolItemSet
832 :
833 : false
834 : The SfxPoolItems from the parents of
835 : rSet are not taken into account */
836 : )
837 : {
838 1477958 : bool bRet = false;
839 1477958 : if ( _nCount )
840 227840 : ClearItem();
841 1477958 : if ( bDeep )
842 : {
843 1464246 : SfxWhichIter aIter(*this);
844 1464246 : sal_uInt16 nWhich = aIter.FirstWhich();
845 68462936 : while ( nWhich )
846 : {
847 : const SfxPoolItem* pItem;
848 65534444 : if( SfxItemState::SET == rSet.GetItemState( nWhich, true, &pItem ) )
849 8967567 : bRet |= 0 != Put( *pItem, pItem->Which() );
850 65534444 : nWhich = aIter.NextWhich();
851 1464246 : }
852 : }
853 : else
854 13712 : bRet = Put(rSet, false);
855 :
856 1477958 : return bRet;
857 : }
858 :
859 : /**
860 : * This method eases accessing single Items in the SfxItemSet.
861 : * Type checking is done via assertion, which makes client code
862 : * much more readable.
863 : *
864 : * The PRODUCT version returns 0, if the Item found is not of the
865 : * specified class.
866 : *
867 : * @returns 0 if the ItemSet does not contain an Item with the Id 'nWhich'
868 : */
869 255822 : const SfxPoolItem* SfxItemSet::GetItem
870 : (
871 : sal_uInt16 nId, // SlotId or the Item's WhichId
872 : bool bSrchInParent, // sal_True: also search in Parent ItemSets
873 : TypeId aItemType // != 0 => RTTI check using assertion
874 : ) const
875 : {
876 : // Convert to WhichId
877 255822 : sal_uInt16 nWhich = GetPool()->GetWhich(nId);
878 :
879 : // Is the Item set or 'bDeep == true' available?
880 255822 : const SfxPoolItem *pItem = 0;
881 255822 : SfxItemState eState = GetItemState( nWhich, bSrchInParent, &pItem );
882 255822 : if ( bSrchInParent && SfxItemState::DEFAULT == eState &&
883 : nWhich <= SFX_WHICH_MAX )
884 36662 : pItem = &_pPool->GetDefaultItem(nWhich);
885 :
886 255822 : if ( pItem )
887 : {
888 : // Does the type match?
889 107504 : if ( !aItemType || pItem->IsA(aItemType) )
890 107504 : return pItem;
891 :
892 : // Else report error
893 : OSL_FAIL( "invalid argument type" );
894 : }
895 :
896 : // No Item of wrong type found
897 148318 : return 0;
898 : }
899 :
900 :
901 :
902 :
903 127273018 : const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool bSrchInParent) const
904 : {
905 : // Search the Range in which the Which is located in:
906 127273018 : const SfxItemSet* pAktSet = this;
907 192742590 : do
908 : {
909 218714389 : if( pAktSet->Count() )
910 : {
911 103611978 : SfxItemArray ppFnd = pAktSet->_aItems;
912 103611978 : const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
913 299538198 : while( *pPtr )
914 : {
915 195192286 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
916 : {
917 : // In this Range
918 102878044 : ppFnd += nWhich - *pPtr;
919 102878044 : if( *ppFnd )
920 : {
921 25971799 : if( reinterpret_cast<SfxPoolItem*>(-1) == *ppFnd ) {
922 : //FIXME: The following code is duplicated further down
923 : SFX_ASSERT(_pPool, nWhich, "no Pool, but status is ambiguous");
924 : //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
925 : //!return aDefault;
926 810 : return _pPool->GetDefaultItem( nWhich );
927 : }
928 : #ifdef DBG_UTIL
929 : const SfxPoolItem *pItem = *ppFnd;
930 : if ( pItem->ISA(SfxVoidItem) || !pItem->Which() )
931 : DBG_WARNING( "SFX_WARNING: Getting disabled Item" );
932 : #endif
933 25970989 : return **ppFnd;
934 : }
935 76906245 : break; // Continue with Parent
936 : }
937 92314242 : ppFnd += *(pPtr+1) - *pPtr + 1;
938 92314242 : pPtr += 2;
939 : }
940 : }
941 : //TODO: Search until end of Range: What are we supposed to do now? To the Parent or Default??
942 : // if( !*pPtr ) // Until the end of the search Range?
943 : // break;
944 192742590 : } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
945 :
946 : // Get the Default from the Pool and return
947 : SFX_ASSERT(_pPool, nWhich, "no Pool, but status is ambiguous");
948 101301219 : const SfxPoolItem *pItem = &_pPool->GetDefaultItem( nWhich );
949 101301219 : return *pItem;
950 : }
951 :
952 : /**
953 : * Notification callback
954 : */
955 24045623 : void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& )
956 : {
957 24045623 : }
958 :
959 :
960 :
961 23026100 : sal_uInt16 SfxItemSet::TotalCount() const
962 : {
963 23026100 : sal_uInt16 nRet = 0;
964 23026100 : sal_uInt16* pPtr = _pWhichRanges;
965 156228547 : while( *pPtr )
966 : {
967 110176347 : nRet += ( *(pPtr+1) - *pPtr ) + 1;
968 110176347 : pPtr += 2;
969 : }
970 23026100 : return nRet;
971 : }
972 :
973 :
974 : /**
975 : * Only retain the Items that are also present in rSet
976 : * (nevermind their value).
977 : */
978 66052 : void SfxItemSet::Intersect( const SfxItemSet& rSet )
979 : {
980 : DBG_ASSERT(_pPool, "Not implemented without Pool");
981 66052 : if( !Count() ) // None set?
982 21090 : return;
983 :
984 : // Delete all Items not contained in rSet
985 44962 : if( !rSet.Count() )
986 : {
987 0 : ClearItem(); // Delete everything
988 0 : return;
989 : }
990 :
991 : // Test whether the Which Ranges are different
992 44962 : bool bEqual = true;
993 44962 : sal_uInt16* pWh1 = _pWhichRanges;
994 44962 : sal_uInt16* pWh2 = rSet._pWhichRanges;
995 44962 : sal_uInt16 nSize = 0;
996 :
997 315414 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
998 : {
999 270452 : if( *pWh1 != *pWh2 )
1000 : {
1001 0 : bEqual = false;
1002 0 : break;
1003 : }
1004 270452 : if( n & 1 )
1005 135226 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1006 : }
1007 44962 : bEqual = *pWh1 == *pWh2; // Also check for 0
1008 :
1009 : // If the Ranges are identical, we can easily process it
1010 44962 : if( bEqual )
1011 : {
1012 44962 : SfxItemArray ppFnd1 = _aItems;
1013 44962 : SfxItemArray ppFnd2 = rSet._aItems;
1014 :
1015 2933410 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1016 2888448 : if( *ppFnd1 && !*ppFnd2 )
1017 : {
1018 : // Delete from Pool
1019 49122 : if( !IsInvalidItem( *ppFnd1 ) )
1020 : {
1021 49122 : sal_uInt16 nWhich = (*ppFnd1)->Which();
1022 49122 : if(nWhich <= SFX_WHICH_MAX)
1023 : {
1024 : const SfxPoolItem& rNew = _pParent
1025 49122 : ? _pParent->Get( nWhich, true )
1026 98244 : : _pPool->GetDefaultItem( nWhich );
1027 :
1028 49122 : Changed( **ppFnd1, rNew );
1029 : }
1030 49122 : _pPool->Remove( **ppFnd1 );
1031 : }
1032 49122 : *ppFnd1 = 0;
1033 49122 : --_nCount;
1034 : }
1035 : }
1036 : else
1037 : {
1038 0 : SfxItemIter aIter( *this );
1039 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
1040 : while( true )
1041 : {
1042 0 : sal_uInt16 nWhich = IsInvalidItem( pItem )
1043 0 : ? GetWhichByPos( aIter.GetCurPos() )
1044 0 : : pItem->Which();
1045 0 : if( SfxItemState::UNKNOWN == rSet.GetItemState( nWhich, false ) )
1046 0 : ClearItem( nWhich ); // Delete
1047 0 : if( aIter.IsAtEnd() )
1048 0 : break;
1049 0 : pItem = aIter.NextItem();
1050 0 : }
1051 : }
1052 : }
1053 :
1054 :
1055 :
1056 1703450 : void SfxItemSet::Differentiate( const SfxItemSet& rSet )
1057 : {
1058 1703450 : if( !Count() || !rSet.Count() )// None set?
1059 2151119 : return;
1060 :
1061 : // Test whether the Which Ranges are different
1062 1255781 : bool bEqual = true;
1063 1255781 : sal_uInt16* pWh1 = _pWhichRanges;
1064 1255781 : sal_uInt16* pWh2 = rSet._pWhichRanges;
1065 1255781 : sal_uInt16 nSize = 0;
1066 :
1067 2697231 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1068 : {
1069 2574678 : if( *pWh1 != *pWh2 )
1070 : {
1071 1133228 : bEqual = false;
1072 1133228 : break;
1073 : }
1074 1441450 : if( n & 1 )
1075 720725 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1076 : }
1077 1255781 : bEqual = *pWh1 == *pWh2; // Also test for 0
1078 :
1079 : // If the Ranges are identical, we can easily process it
1080 1255781 : if( bEqual )
1081 : {
1082 122553 : SfxItemArray ppFnd1 = _aItems;
1083 122553 : SfxItemArray ppFnd2 = rSet._aItems;
1084 :
1085 11955961 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1086 11833408 : if( *ppFnd1 && *ppFnd2 )
1087 : {
1088 : // Delete from Pool
1089 105003 : if( !IsInvalidItem( *ppFnd1 ) )
1090 : {
1091 105003 : sal_uInt16 nWhich = (*ppFnd1)->Which();
1092 105003 : if(nWhich <= SFX_WHICH_MAX)
1093 : {
1094 : const SfxPoolItem& rNew = _pParent
1095 0 : ? _pParent->Get( nWhich, true )
1096 105003 : : _pPool->GetDefaultItem( nWhich );
1097 :
1098 105003 : Changed( **ppFnd1, rNew );
1099 : }
1100 105003 : _pPool->Remove( **ppFnd1 );
1101 : }
1102 105003 : *ppFnd1 = 0;
1103 105003 : --_nCount;
1104 : }
1105 : }
1106 : else
1107 : {
1108 1133228 : SfxItemIter aIter( *this );
1109 1133228 : const SfxPoolItem* pItem = aIter.GetCurItem();
1110 : while( true )
1111 : {
1112 1186390 : sal_uInt16 nWhich = IsInvalidItem( pItem )
1113 0 : ? GetWhichByPos( aIter.GetCurPos() )
1114 1186390 : : pItem->Which();
1115 1186390 : if( SfxItemState::SET == rSet.GetItemState( nWhich, false ) )
1116 50492 : ClearItem( nWhich ); // Delete
1117 1186390 : if( aIter.IsAtEnd() )
1118 1133228 : break;
1119 53162 : pItem = aIter.NextItem();
1120 1133228 : }
1121 :
1122 : }
1123 : }
1124 :
1125 :
1126 : /**
1127 : * Decision table for MergeValue(s)
1128 : *
1129 : * Principles:
1130 : * 1. If the Which value in the 1st set is "unknown", there's never any action
1131 : * 2. If the Which value in the 2nd set is "unknown", it's made the "default"
1132 : * 3. For comparisons the values of the "default" Items are take into account
1133 : *
1134 : * 1st Item 2nd Item Values bIgnoreDefs Remove Assign Add
1135 : *
1136 : * set set == sal_False - - -
1137 : * default set == sal_False - - -
1138 : * dontcare set == sal_False - - -
1139 : * unknown set == sal_False - - -
1140 : * set default == sal_False - - -
1141 : * default default == sal_False - - -
1142 : * dontcare default == sal_False - - -
1143 : * unknown default == sal_False - - -
1144 : * set dontcare == sal_False 1st Item -1 -
1145 : * default dontcare == sal_False - -1 -
1146 : * dontcare dontcare == sal_False - - -
1147 : * unknown dontcare == sal_False - - -
1148 : * set unknown == sal_False 1st Item -1 -
1149 : * default unknown == sal_False - - -
1150 : * dontcare unknown == sal_False - - -
1151 : * unknown unknown == sal_False - - -
1152 : *
1153 : * set set != sal_False 1st Item -1 -
1154 : * default set != sal_False - -1 -
1155 : * dontcare set != sal_False - - -
1156 : * unknown set != sal_False - - -
1157 : * set default != sal_False 1st Item -1 -
1158 : * default default != sal_False - - -
1159 : * dontcare default != sal_False - - -
1160 : * unknown default != sal_False - - -
1161 : * set dontcare != sal_False 1st Item -1 -
1162 : * default dontcare != sal_False - -1 -
1163 : * dontcare dontcare != sal_False - - -
1164 : * unknown dontcare != sal_False - - -
1165 : * set unknown != sal_False 1st Item -1 -
1166 : * default unknown != sal_False - - -
1167 : * dontcare unknown != sal_False - - -
1168 : * unknown unknown != sal_False - - -
1169 : *
1170 : * set set == sal_True - - -
1171 : * default set == sal_True - 2nd Item 2nd Item
1172 : * dontcare set == sal_True - - -
1173 : * unknown set == sal_True - - -
1174 : * set default == sal_True - - -
1175 : * default default == sal_True - - -
1176 : * dontcare default == sal_True - - -
1177 : * unknown default == sal_True - - -
1178 : * set dontcare == sal_True - - -
1179 : * default dontcare == sal_True - -1 -
1180 : * dontcare dontcare == sal_True - - -
1181 : * unknown dontcare == sal_True - - -
1182 : * set unknown == sal_True - - -
1183 : * default unknown == sal_True - - -
1184 : * dontcare unknown == sal_True - - -
1185 : * unknown unknown == sal_True - - -
1186 : *
1187 : * set set != sal_True 1st Item -1 -
1188 : * default set != sal_True - 2nd Item 2nd Item
1189 : * dontcare set != sal_True - - -
1190 : * unknown set != sal_True - - -
1191 : * set default != sal_True - - -
1192 : * default default != sal_True - - -
1193 : * dontcare default != sal_True - - -
1194 : * unknown default != sal_True - - -
1195 : * set dontcare != sal_True 1st Item -1 -
1196 : * default dontcare != sal_True - -1 -
1197 : * dontcare dontcare != sal_True - - -
1198 : * unknown dontcare != sal_True - - -
1199 : * set unknown != sal_True - - -
1200 : * default unknown != sal_True - - -
1201 : * dontcare unknown != sal_True - - -
1202 : * unknown unknown != sal_True - - -
1203 : */
1204 810648 : static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount,
1205 : const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2,
1206 : bool bIgnoreDefaults )
1207 : {
1208 : assert(ppFnd1 != 0 && "Merging to 0-Item");
1209 :
1210 : // 1st Item is Default?
1211 810648 : if ( !*ppFnd1 )
1212 : {
1213 683600 : if ( IsInvalidItem(pFnd2) )
1214 : // Decision table: default, dontcare, doesn't matter, doesn't matter
1215 96 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1216 :
1217 683544 : else if ( pFnd2 && !bIgnoreDefaults &&
1218 40 : _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
1219 : // Decision table: default, set, !=, sal_False
1220 40 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1221 :
1222 683464 : else if ( pFnd2 && bIgnoreDefaults )
1223 : // Decision table: default, set, doesn't matter, sal_True
1224 1656 : *ppFnd1 = &_pPool->Put( *pFnd2 );
1225 :
1226 683600 : if ( *ppFnd1 )
1227 1792 : ++rCount;
1228 : }
1229 :
1230 : // 1st Item set?
1231 127048 : else if ( !IsInvalidItem(*ppFnd1) )
1232 : {
1233 98002 : if ( !pFnd2 )
1234 : {
1235 : // 2nd Item is Default
1236 2908 : if ( !bIgnoreDefaults &&
1237 1454 : **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) )
1238 : {
1239 : // Decision table: set, default, !=, sal_False
1240 1454 : _pPool->Remove( **ppFnd1 );
1241 1454 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1242 : }
1243 : }
1244 96548 : else if ( IsInvalidItem(pFnd2) )
1245 : {
1246 : // 2nd Item is dontcare
1247 192 : if ( !bIgnoreDefaults ||
1248 0 : **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) )
1249 : {
1250 : // Decision table: set, dontcare, doesn't matter, sal_False
1251 : // or: set, dontcare, !=, sal_True
1252 192 : _pPool->Remove( **ppFnd1 );
1253 192 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1254 : }
1255 : }
1256 : else
1257 : {
1258 : // 2nd Item is set
1259 96356 : if ( **ppFnd1 != *pFnd2 )
1260 : {
1261 : // Decision table: set, set, !=, doesn't matter
1262 860 : _pPool->Remove( **ppFnd1 );
1263 860 : *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1);
1264 : }
1265 : }
1266 : }
1267 810648 : }
1268 :
1269 15850 : void SfxItemSet::MergeValues( const SfxItemSet& rSet, bool bIgnoreDefaults )
1270 : {
1271 : // WARNING! When making changes/fixing bugs, always update the table above!!
1272 : DBG_ASSERT( GetPool() == rSet.GetPool(), "MergeValues with different Pools" );
1273 :
1274 : // Test if the which Ranges are different
1275 15850 : bool bEqual = true;
1276 15850 : sal_uInt16* pWh1 = _pWhichRanges;
1277 15850 : sal_uInt16* pWh2 = rSet._pWhichRanges;
1278 15850 : sal_uInt16 nSize = 0;
1279 :
1280 71666 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1281 : {
1282 55816 : if( *pWh1 != *pWh2 )
1283 : {
1284 0 : bEqual = false;
1285 0 : break;
1286 : }
1287 55816 : if( n & 1 )
1288 27908 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1289 : }
1290 15850 : bEqual = *pWh1 == *pWh2; // Also check for 0
1291 :
1292 : // If the Ranges match, they are easier to process!
1293 15850 : if( bEqual )
1294 : {
1295 15850 : SfxItemArray ppFnd1 = _aItems;
1296 15850 : SfxItemArray ppFnd2 = rSet._aItems;
1297 :
1298 824842 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1299 808992 : MergeItem_Impl( _pPool, _nCount, ppFnd1, *ppFnd2, bIgnoreDefaults );
1300 : }
1301 : else
1302 : {
1303 0 : SfxWhichIter aIter( rSet );
1304 : sal_uInt16 nWhich;
1305 0 : while( 0 != ( nWhich = aIter.NextWhich() ) )
1306 : {
1307 0 : const SfxPoolItem* pItem = 0;
1308 0 : rSet.GetItemState( nWhich, true, &pItem );
1309 0 : if( !pItem )
1310 : {
1311 : // Not set, so default
1312 0 : if ( !bIgnoreDefaults )
1313 0 : MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ), bIgnoreDefaults );
1314 : }
1315 0 : else if( IsInvalidItem( pItem ) )
1316 : // dont care
1317 0 : InvalidateItem( nWhich );
1318 : else
1319 0 : MergeValue( *pItem, bIgnoreDefaults );
1320 0 : }
1321 : }
1322 15850 : }
1323 :
1324 :
1325 :
1326 1656 : void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, bool bIgnoreDefaults )
1327 : {
1328 1656 : SfxItemArray ppFnd = _aItems;
1329 1656 : const sal_uInt16* pPtr = _pWhichRanges;
1330 1656 : const sal_uInt16 nWhich = rAttr.Which();
1331 3752 : while( *pPtr )
1332 : {
1333 : // In this Range??
1334 2096 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1335 : {
1336 1656 : ppFnd += nWhich - *pPtr;
1337 1656 : MergeItem_Impl( _pPool, _nCount, ppFnd, &rAttr, bIgnoreDefaults );
1338 1656 : break;
1339 : }
1340 440 : ppFnd += *(pPtr+1) - *pPtr + 1;
1341 440 : pPtr += 2;
1342 : }
1343 1656 : }
1344 :
1345 :
1346 :
1347 12692 : void SfxItemSet::InvalidateItem( sal_uInt16 nWhich )
1348 : {
1349 12692 : SfxItemArray ppFnd = _aItems;
1350 12692 : const sal_uInt16* pPtr = _pWhichRanges;
1351 55808 : while( *pPtr )
1352 : {
1353 33742 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1354 : {
1355 : // In this Range?
1356 3318 : ppFnd += nWhich - *pPtr;
1357 :
1358 3318 : if( *ppFnd ) // Set for me
1359 : {
1360 1780 : if( reinterpret_cast<SfxPoolItem*>(-1) != *ppFnd ) // Not yet dontcare!
1361 : {
1362 970 : _pPool->Remove( **ppFnd );
1363 970 : *ppFnd = reinterpret_cast<SfxPoolItem*>(-1);
1364 : }
1365 : }
1366 : else
1367 : {
1368 1538 : *ppFnd = reinterpret_cast<SfxPoolItem*>(-1);
1369 1538 : ++_nCount;
1370 : }
1371 3318 : break;
1372 : }
1373 30424 : ppFnd += *(pPtr+1) - *pPtr + 1;
1374 30424 : pPtr += 2;
1375 : }
1376 12692 : }
1377 :
1378 :
1379 :
1380 310392 : sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const
1381 : {
1382 310392 : sal_uInt16 n = 0;
1383 310392 : sal_uInt16* pPtr = _pWhichRanges;
1384 985274 : while( *pPtr )
1385 : {
1386 674882 : n = ( *(pPtr+1) - *pPtr ) + 1;
1387 674882 : if( nPos < n )
1388 310392 : return *(pPtr)+nPos;
1389 364490 : nPos = nPos - n;
1390 364490 : pPtr += 2;
1391 : }
1392 : DBG_ASSERT( false, "We're wrong here" );
1393 0 : return 0;
1394 : }
1395 :
1396 :
1397 : /**
1398 : * Saves the SfxItemSet instance to the supplied Stream.
1399 : * The surrogates as well as the ones with 'bDirect == true' are saved
1400 : * to the stream in the following way:
1401 : *
1402 : * sal_uInt16 ... Count of the set Items
1403 : * Count* _pPool->StoreItem()
1404 : *
1405 : * @see SfxItemPool::StoreItem() const
1406 : * @see SfxItemSet::Load(SvStream&,bool,const SfxItemPool*)
1407 : */
1408 10776 : SvStream &SfxItemSet::Store
1409 : (
1410 : SvStream& rStream, // Target stream for normal Items
1411 : bool bDirect /* true: Save Items directly
1412 : false: Surrogates */
1413 : ) const
1414 : {
1415 : DBG_ASSERT( _pPool, "No Pool" );
1416 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "no Master Pool" );
1417 :
1418 : // Remember position of the count (to be able to correct it, if need be)
1419 10776 : sal_uLong nCountPos = rStream.Tell();
1420 10776 : rStream.WriteUInt16( _nCount );
1421 :
1422 : // If there's nothing to save, don't construct an ItemIter
1423 10776 : if ( _nCount )
1424 : {
1425 : // Keep record of how many Items are really saved
1426 656 : sal_uInt16 nWrittenCount = 0; // Count of Items streamed in 'rStream'
1427 :
1428 : // Iterate over all set Items
1429 656 : SfxItemIter aIter(*this);
1430 18424 : for ( const SfxPoolItem *pItem = aIter.FirstItem();
1431 : pItem;
1432 : pItem = aIter.NextItem() )
1433 : {
1434 : // Let Items (if need be as a Surrogate) be saved via Pool
1435 : DBG_ASSERT( !IsInvalidItem(pItem), "can't store invalid items" );
1436 35536 : if ( !IsInvalidItem(pItem) &&
1437 17768 : _pPool->StoreItem( rStream, *pItem, bDirect ) )
1438 : // Item was streamed in 'rStream'
1439 17768 : ++nWrittenCount;
1440 : }
1441 :
1442 : // Fewer written than read (e.g. old format)
1443 656 : if ( nWrittenCount != _nCount )
1444 : {
1445 : // Store real count in the stream
1446 0 : sal_uLong nPos = rStream.Tell();
1447 0 : rStream.Seek( nCountPos );
1448 0 : rStream.WriteUInt16( nWrittenCount );
1449 0 : rStream.Seek( nPos );
1450 656 : }
1451 : }
1452 :
1453 10776 : return rStream;
1454 : }
1455 :
1456 :
1457 : /**
1458 : * This method loads an SfxItemSet from a stream.
1459 : * If the SfxItemPool was loaded without RefCounts the loaded Item
1460 : * references are counted, else we assume the they were accounted for
1461 : * when loadig the SfxItemPool.
1462 : *
1463 : * @see SfxItemSet::Store(Stream&,bool) const
1464 : */
1465 0 : SvStream &SfxItemSet::Load
1466 : (
1467 : SvStream& rStream, // Stream we're loading from
1468 :
1469 : bool bDirect, /* true
1470 : Items are directly read form the stream
1471 : and not via Surrogates
1472 :
1473 : false (default)
1474 : Items are read via Surrogates */
1475 :
1476 : const SfxItemPool* pRefPool /* Pool that can resolve the Surrogates
1477 : (e.g. when inserting documents) */
1478 : )
1479 : {
1480 : DBG_ASSERT( _pPool, "No Pool");
1481 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "No Master Pool");
1482 :
1483 : // No RefPool => Resolve Surrogates with ItemSet's Pool
1484 0 : if ( !pRefPool )
1485 0 : pRefPool = _pPool;
1486 :
1487 : // Load Item count and as many Items
1488 0 : sal_uInt16 nCount = 0;
1489 0 : rStream.ReadUInt16( nCount );
1490 0 : for ( sal_uInt16 i = 0; i < nCount; ++i )
1491 : {
1492 : // Load Surrogate/Item and resolve Surrogate
1493 : const SfxPoolItem *pItem =
1494 0 : _pPool->LoadItem( rStream, bDirect, pRefPool );
1495 :
1496 : // Did we load an Item or resolve a Surrogate?
1497 0 : if ( pItem )
1498 : {
1499 : // Find position for Item pointer in the set
1500 0 : sal_uInt16 nWhich = pItem->Which();
1501 0 : SfxItemArray ppFnd = _aItems;
1502 0 : const sal_uInt16* pPtr = _pWhichRanges;
1503 0 : while ( *pPtr )
1504 : {
1505 : // In this Range??
1506 0 : if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1507 : {
1508 : // Remember Item pointer in the set
1509 0 : ppFnd += nWhich - *pPtr;
1510 : SFX_ASSERT( !*ppFnd, nWhich, "Item is present twice");
1511 0 : *ppFnd = pItem;
1512 0 : ++_nCount;
1513 0 : break;
1514 : }
1515 :
1516 : // In the range array and Item array to the next Which range
1517 0 : ppFnd += *(pPtr+1) - *pPtr + 1;
1518 0 : pPtr += 2;
1519 : }
1520 : }
1521 : }
1522 :
1523 0 : return rStream;
1524 : }
1525 :
1526 :
1527 :
1528 945959 : bool SfxItemSet::operator==(const SfxItemSet &rCmp) const
1529 : {
1530 : // Values we can get quickly need to be the same
1531 2835485 : if ( _pParent != rCmp._pParent ||
1532 1695034 : _pPool != rCmp._pPool ||
1533 749075 : Count() != rCmp.Count() )
1534 508016 : return false;
1535 :
1536 : // Counting Ranges takes longer; they also need to be the same, however
1537 437943 : sal_uInt16 nCount1 = TotalCount();
1538 437943 : sal_uInt16 nCount2 = rCmp.TotalCount();
1539 437943 : if ( nCount1 != nCount2 )
1540 3658 : return false;
1541 :
1542 : // Are the Ranges themselves unequal?
1543 972848 : for ( sal_uInt16 nRange = 0; _pWhichRanges[nRange]; nRange += 2 )
1544 1077126 : if ( _pWhichRanges[nRange] != rCmp._pWhichRanges[nRange] ||
1545 538563 : _pWhichRanges[nRange+1] != rCmp._pWhichRanges[nRange+1] )
1546 : {
1547 : // We must use the slow method then
1548 0 : SfxWhichIter aIter( *this );
1549 0 : for ( sal_uInt16 nWh = aIter.FirstWhich();
1550 : nWh;
1551 : nWh = aIter.NextWhich() )
1552 : {
1553 : // If the pointer of the poolable Items are unequal, the Items must match
1554 0 : const SfxPoolItem *pItem1 = 0, *pItem2 = 0;
1555 0 : if ( GetItemState( nWh, false, &pItem1 ) !=
1556 0 : rCmp.GetItemState( nWh, false, &pItem2 ) ||
1557 0 : ( pItem1 != pItem2 &&
1558 0 : ( !pItem1 || IsInvalidItem(pItem1) ||
1559 0 : ( _pPool->IsItemFlag(*pItem1, SFX_ITEM_POOLABLE) &&
1560 0 : *pItem1 != *pItem2 ) ) ) )
1561 0 : return false;
1562 : }
1563 :
1564 0 : return true;
1565 : }
1566 :
1567 : // Are all pointers the same?
1568 434285 : if ( 0 == memcmp( _aItems, rCmp._aItems, nCount1 * sizeof(_aItems[0]) ) )
1569 410424 : return true;
1570 :
1571 : // We need to compare each one separately then
1572 23861 : const SfxPoolItem **ppItem1 = (const SfxPoolItem**) _aItems;
1573 23861 : const SfxPoolItem **ppItem2 = (const SfxPoolItem**) rCmp._aItems;
1574 391819 : for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos )
1575 : {
1576 : // If the pointers of the poolable Items are not the same, the Items
1577 : // must match
1578 451889 : if ( *ppItem1 != *ppItem2 &&
1579 119993 : ( ( !*ppItem1 || !*ppItem2 ) ||
1580 118305 : ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) ||
1581 60101 : ( _pPool->IsItemFlag(**ppItem1, SFX_ITEM_POOLABLE) ) ||
1582 20666 : **ppItem1 != **ppItem2 ) )
1583 21685 : return false;
1584 :
1585 367958 : ++ppItem1;
1586 367958 : ++ppItem2;
1587 : }
1588 :
1589 2176 : return true;
1590 : }
1591 :
1592 :
1593 :
1594 857137 : SfxItemSet *SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
1595 : {
1596 857137 : if ( pToPool && pToPool != _pPool )
1597 : {
1598 13461 : SfxItemSet *pNewSet = new SfxItemSet( *pToPool, _pWhichRanges );
1599 13461 : if ( bItems )
1600 : {
1601 108 : SfxWhichIter aIter(*pNewSet);
1602 108 : sal_uInt16 nWhich = aIter.FirstWhich();
1603 2364 : while ( nWhich )
1604 : {
1605 : const SfxPoolItem* pItem;
1606 2148 : if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
1607 12 : pNewSet->Put( *pItem, pItem->Which() );
1608 2148 : nWhich = aIter.NextWhich();
1609 108 : }
1610 : }
1611 13461 : return pNewSet;
1612 : }
1613 : else
1614 : return bItems
1615 825048 : ? new SfxItemSet(*this)
1616 1668724 : : new SfxItemSet(*_pPool, _pWhichRanges);
1617 : }
1618 :
1619 :
1620 :
1621 2435420 : int SfxItemSet::PutDirect(const SfxPoolItem &rItem)
1622 : {
1623 2435420 : SfxItemArray ppFnd = _aItems;
1624 2435420 : const sal_uInt16* pPtr = _pWhichRanges;
1625 2435420 : const sal_uInt16 nWhich = rItem.Which();
1626 : #ifdef DBG_UTIL
1627 : IsPoolDefaultItem(&rItem) || _pPool->GetSurrogate(&rItem);
1628 : // Only cause assertion in the callees
1629 : #endif
1630 6168576 : while( *pPtr )
1631 : {
1632 3733156 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1633 : {
1634 : // In this Range?
1635 2435420 : ppFnd += nWhich - *pPtr;
1636 2435420 : const SfxPoolItem* pOld = *ppFnd;
1637 2435420 : if( pOld ) // One already present
1638 : {
1639 728 : if( rItem == **ppFnd )
1640 0 : return sal_False; // Already present!
1641 728 : _pPool->Remove( *pOld );
1642 : }
1643 : else
1644 2434692 : ++_nCount;
1645 :
1646 : // Add the new one
1647 2435420 : if( IsPoolDefaultItem(&rItem) )
1648 174522 : *ppFnd = &_pPool->Put( rItem );
1649 : else
1650 : {
1651 2260898 : *ppFnd = &rItem;
1652 2260898 : if( !IsStaticDefaultItem( &rItem ) )
1653 1643402 : rItem.AddRef();
1654 : }
1655 :
1656 2435420 : return sal_True;
1657 : }
1658 1297736 : ppFnd += *(pPtr+1) - *pPtr + 1;
1659 1297736 : pPtr += 2;
1660 : }
1661 0 : return sal_False;
1662 : }
1663 :
1664 :
1665 :
1666 60151 : SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool )
1667 : : SfxItemSet(rPool, (const sal_uInt16*) 0),
1668 : aDefault(0),
1669 60151 : nFree(nInitCount)
1670 : {
1671 : // Initially no Items
1672 60151 : _aItems = 0;
1673 :
1674 : // Allocate nInitCount pairs at USHORTs for Ranges
1675 60151 : _pWhichRanges = new sal_uInt16[ nInitCount + 1 ];
1676 60151 : memset( _pWhichRanges, 0, ( nInitCount + 1 ) * sizeof(sal_uInt16) );
1677 60151 : }
1678 :
1679 :
1680 :
1681 :
1682 :
1683 1370 : SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy)
1684 : : SfxItemSet(rCopy),
1685 : aDefault(0),
1686 1370 : nFree(0)
1687 : {
1688 1370 : }
1689 :
1690 :
1691 :
1692 :
1693 : /**
1694 : * Explicitly define this ctor to avoid auto-generation by the compiler.
1695 : * The compiler does not take the ctor with the 'const SfxItemSet&'!
1696 : */
1697 5954 : SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy)
1698 : : SfxItemSet(rCopy),
1699 : aDefault(0),
1700 5954 : nFree(0)
1701 : {
1702 5954 : }
1703 :
1704 :
1705 : /**
1706 : * This internal function creates a new WhichRanges array, which is copied
1707 : * from the 'nOldSize'-USHORTs long 'pUS'. It has new USHORTs at the end instead
1708 : * of 'nIncr'.
1709 : * The terminating sal_uInt16 with the '0' is neither accounted for in 'nOldSize'
1710 : * nor in 'nIncr', but always explicitly added.
1711 : *
1712 : * @returns the new WhichRanges array (the old 'pUS' is freed)
1713 : */
1714 21858 : static sal_uInt16 *AddRanges_Impl(
1715 : sal_uInt16 *pUS, std::ptrdiff_t nOldSize, sal_uInt16 nIncr)
1716 : {
1717 : // Create new WhichRanges array
1718 21858 : sal_uInt16 *pNew = new sal_uInt16[ nOldSize + nIncr + 1 ];
1719 :
1720 : // Take over the old Ranges
1721 21858 : memcpy( pNew, pUS, nOldSize * sizeof(sal_uInt16) );
1722 :
1723 : // Initialize the new one to 0
1724 21858 : memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(sal_uInt16) );
1725 :
1726 : // Free the old array
1727 21858 : delete[] pUS;
1728 :
1729 21858 : return pNew;
1730 : }
1731 :
1732 :
1733 : /**
1734 : * This internal function creates a new ItemArray, which is copied from 'pItems',
1735 : * but has room for a new ItemPointer at 'nPos'.
1736 : *
1737 : * @returns the new ItemArray (the old 'pItems' is freed)
1738 : */
1739 181786 : static SfxItemArray AddItem_Impl(SfxItemArray pItems, sal_uInt16 nOldSize, sal_uInt16 nPos)
1740 : {
1741 : // Create new ItemArray
1742 181786 : SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1];
1743 :
1744 : // Was there one before?
1745 181786 : if ( pItems )
1746 : {
1747 : // Copy all Items before nPos
1748 143558 : if ( nPos )
1749 143558 : memcpy( (void*) pNew, pItems, nPos * sizeof(SfxPoolItem *) );
1750 :
1751 : // Copy all Items after nPos
1752 143558 : if ( nPos < nOldSize )
1753 4704 : memcpy( (void*) (pNew + nPos + 1), pItems + nPos,
1754 7056 : (nOldSize-nPos) * sizeof(SfxPoolItem *) );
1755 : }
1756 :
1757 : // Initialize new Item
1758 181786 : *(pNew + nPos) = 0;
1759 :
1760 : // Free old ItemArray
1761 181786 : delete[] pItems;
1762 :
1763 181786 : return pNew;
1764 : }
1765 :
1766 :
1767 : /**
1768 : * Putting with automatic extension of the WhichId with the ID of the Item.
1769 : */
1770 242791 : const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
1771 : {
1772 242791 : sal_uInt16 nPos = 0; // Position for 'rItem' in '_aItems'
1773 242791 : const sal_uInt16 nItemCount = TotalCount();
1774 :
1775 : // Let's see first whether there's a suitable Range already
1776 242791 : sal_uInt16 *pPtr = _pWhichRanges;
1777 1268457 : while ( *pPtr )
1778 : {
1779 : // WhichId is within this Range?
1780 843880 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1781 : {
1782 : // Insert
1783 61005 : nPos += nWhich - *pPtr;
1784 61005 : break;
1785 : }
1786 :
1787 : // Carry over the position of the Item in _aItems
1788 782875 : nPos += *(pPtr+1) - *pPtr + 1;
1789 :
1790 : // To the next Range
1791 782875 : pPtr += 2;
1792 : }
1793 :
1794 : // WhichId not yet present?
1795 242791 : if ( !*pPtr )
1796 : {
1797 : // Let's see if we can attach it somewhere
1798 181786 : pPtr = _pWhichRanges;
1799 181786 : nPos = 0;
1800 913785 : while ( *pPtr )
1801 : {
1802 : // WhichId is right before this Range?
1803 552591 : if ( (nWhich+1) == *pPtr )
1804 : {
1805 : // Range grows downwards
1806 1162 : (*pPtr)--;
1807 :
1808 : // Make room before first Item of this Range
1809 1162 : _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1810 1162 : break;
1811 : }
1812 :
1813 : // WhichId is right after this Range?
1814 551429 : else if ( (nWhich-1) == *(pPtr+1) )
1815 : {
1816 : // Range grows upwards?
1817 1216 : (*(pPtr+1))++;
1818 :
1819 : // Make room after last Item of this Range
1820 1216 : nPos += nWhich - *pPtr;
1821 1216 : _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1822 1216 : break;
1823 : }
1824 :
1825 : // Carry over position of the Item in _aItems
1826 550213 : nPos += *(pPtr+1) - *pPtr + 1;
1827 :
1828 : // To the next Range
1829 550213 : pPtr += 2;
1830 : }
1831 : }
1832 :
1833 : // No extensible Range found?
1834 242791 : if ( !*pPtr )
1835 : {
1836 : // No room left in _pWhichRanges? => Expand!
1837 179408 : std::ptrdiff_t nSize = pPtr - _pWhichRanges;
1838 179408 : if( !nFree )
1839 : {
1840 21858 : _pWhichRanges = AddRanges_Impl(_pWhichRanges, nSize, nInitCount);
1841 21858 : nFree += nInitCount;
1842 : }
1843 :
1844 : // Attach new WhichRange
1845 179408 : pPtr = _pWhichRanges + nSize;
1846 179408 : *pPtr++ = nWhich;
1847 179408 : *pPtr = nWhich;
1848 179408 : nFree -= 2;
1849 :
1850 : // Expand ItemArray
1851 179408 : nPos = nItemCount;
1852 179408 : _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1853 : }
1854 :
1855 : // Add new Item to Pool
1856 242791 : const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
1857 :
1858 : // Remember old Item
1859 242791 : bool bIncrementCount = false;
1860 242791 : const SfxPoolItem* pOld = *( _aItems + nPos );
1861 242791 : if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld ) // state "dontcare"
1862 0 : pOld = NULL;
1863 242791 : if ( !pOld )
1864 : {
1865 181816 : bIncrementCount = true;
1866 : pOld = _pParent ?
1867 0 : &_pParent->Get( nWhich, true )
1868 181816 : : nWhich <= SFX_WHICH_MAX ? &_pPool->GetDefaultItem( nWhich ) : 0;
1869 : }
1870 :
1871 : // Add new Item to ItemSet
1872 242791 : *(_aItems + nPos) = &rNew;
1873 :
1874 : // Send Changed Notification
1875 242791 : if ( pOld )
1876 : {
1877 60975 : Changed( *pOld, rNew );
1878 60975 : if ( !IsDefaultItem(pOld) )
1879 60975 : _pPool->Remove( *pOld );
1880 : }
1881 :
1882 242791 : if ( bIncrementCount )
1883 181816 : ++_nCount;
1884 :
1885 242791 : return &rNew;
1886 : }
1887 :
1888 :
1889 : /**
1890 : * Disable Item
1891 : * Using a VoidItem with Which value 0
1892 : */
1893 347984 : void SfxItemSet::DisableItem(sal_uInt16 nWhich)
1894 : {
1895 347984 : Put( SfxVoidItem(0), nWhich );
1896 347984 : }
1897 :
1898 :
1899 :
1900 0 : SfxItemSet *SfxAllItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const
1901 : {
1902 0 : if ( pToPool && pToPool != _pPool )
1903 : {
1904 0 : SfxAllItemSet *pNewSet = new SfxAllItemSet( *pToPool );
1905 0 : if ( bItems )
1906 0 : pNewSet->Set( *this );
1907 0 : return pNewSet;
1908 : }
1909 : else
1910 0 : return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool);
1911 : }
1912 :
1913 :
1914 :
1915 0 : sal_Int32 SfxItemSet::getHash() const
1916 : {
1917 0 : return stringify().hashCode();
1918 : }
1919 :
1920 :
1921 :
1922 0 : OString SfxItemSet::stringify() const
1923 : {
1924 0 : SvMemoryStream aStream;
1925 0 : SfxItemSet aSet(*this);
1926 0 : aSet.InvalidateDefaultItems();
1927 0 : aSet.Store(aStream, true);
1928 0 : aStream.Flush();
1929 : return OString(
1930 0 : static_cast<char const *>(aStream.GetData()), aStream.GetEndOfData());
1931 : }
1932 :
1933 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|