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 :
35 : // STATIC DATA -----------------------------------------------------------
36 :
37 : static const sal_uInt16 nInitCount = 10; // einzelne USHORTs => 5 Paare ohne '0'
38 : #if OSL_DEBUG_LEVEL > 1
39 : static sal_uLong nRangesCopyCount = 0; // wie oft wurden Ranges kopiert
40 : #endif
41 :
42 : DBG_NAME(SfxItemSet)
43 :
44 : //========================================================================
45 :
46 : #define NUMTYPE sal_uInt16
47 : #define SfxNumRanges SfxUShortRanges
48 : #include "nranges.cxx"
49 : #undef NUMTYPE
50 : #undef SfxNumRanges
51 :
52 : //========================================================================
53 :
54 : #ifdef DBG_UTIL
55 :
56 :
57 : const sal_Char *DbgCheckItemSet( const void* pVoid )
58 : {
59 : const SfxItemSet *pSet = (const SfxItemSet*) pVoid;
60 : SfxWhichIter aIter( *pSet );
61 : sal_uInt16 nCount = 0, n = 0;
62 : for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh; nWh = aIter.NextWhich(), ++n )
63 : {
64 : const SfxPoolItem *pItem = pSet->_aItems[n];
65 : if ( pItem )
66 : {
67 : ++nCount;
68 : DBG_ASSERT( IsInvalidItem(pItem) ||
69 : pItem->Which() == 0 || pItem->Which() == nWh,
70 : "SfxItemSet: invalid which-id" );
71 : DBG_ASSERT( IsInvalidItem(pItem) || !pItem->Which() ||
72 : !SfxItemPool::IsWhich(pItem->Which()) ||
73 : pSet->GetPool()->IsItemFlag(nWh, SFX_ITEM_NOT_POOLABLE) ||
74 : SFX_ITEMS_NULL != pSet->GetPool()->GetSurrogate(pItem),
75 : "SfxItemSet: item in set which is not in pool" );
76 : }
77 :
78 : }
79 : DBG_ASSERT( pSet->_nCount == nCount, "wrong SfxItemSet::nCount detected" );
80 :
81 : return 0;
82 : }
83 :
84 : #endif
85 : // -----------------------------------------------------------------------
86 :
87 2878 : SfxItemSet::SfxItemSet
88 : (
89 : SfxItemPool& rPool, /* der Pool, in dem die SfxPoolItems,
90 : welche in dieses SfxItemSet gelangen,
91 : aufgenommen werden sollen */
92 : sal_Bool bTotalRanges /* komplette Pool-Ranges uebernehmen,
93 : muss auf sal_True gesetzt werden */
94 : )
95 : /* [Beschreibung]
96 :
97 : Konstruktor fuer ein SfxItemSet mit genau den Which-Bereichen, welche
98 : dem angegebenen <SfxItemPool> bekannt sind.
99 :
100 :
101 : [Anmerkung]
102 :
103 : F"ur Sfx-Programmierer ein derart konstruiertes SfxItemSet kann
104 : keinerlei Items mit Slot-Ids als Which-Werte aufnehmen!
105 : */
106 :
107 : : _pPool( &rPool ),
108 : _pParent( 0 ),
109 2878 : _nCount( 0 )
110 : {
111 : DBG_CTOR(SfxItemSet, DbgCheckItemSet);
112 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
113 : DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
114 : // DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
115 : // "please use suitable ranges" );
116 : #if defined DBG_UTIL && defined SFX_ITEMSET_NO_DEFAULT_CTOR
117 : if ( !bTotalRanges )
118 : *(int*)0 = 0; // GPF
119 : #else
120 : (void) bTotalRanges; // avoid warnings
121 : #endif
122 :
123 2878 : _pWhichRanges = (sal_uInt16*) _pPool->GetFrozenIdRanges();
124 : DBG_ASSERT( _pWhichRanges, "don't create ItemSets with full range before FreezeIdRanges()" );
125 2878 : if ( !_pWhichRanges )
126 0 : _pPool->FillItemIdRanges_Impl( _pWhichRanges );
127 :
128 2878 : const sal_uInt16 nSize = TotalCount();
129 2878 : _aItems = new const SfxPoolItem* [ nSize ];
130 2878 : memset( (void*) _aItems, 0, nSize * sizeof( SfxPoolItem* ) );
131 2878 : }
132 :
133 : // -----------------------------------------------------------------------
134 :
135 170426 : SfxItemSet::SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2 ):
136 : _pPool( &rPool ),
137 : _pParent( 0 ),
138 170426 : _nCount( 0 )
139 : {
140 : DBG_CTOR(SfxItemSet, DbgCheckItemSet);
141 : DBG_ASSERT( nWhich1 <= nWhich2, "Ungueltiger Bereich" );
142 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
143 : DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
144 :
145 170426 : InitRanges_Impl(nWhich1, nWhich2);
146 170426 : }
147 :
148 : // -----------------------------------------------------------------------
149 :
150 170427 : void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2)
151 : {
152 : DBG_CHKTHIS(SfxItemSet, 0);
153 170427 : _pWhichRanges = new sal_uInt16[ 3 ];
154 170427 : *(_pWhichRanges+0) = nWh1;
155 170427 : *(_pWhichRanges+1) = nWh2;
156 170427 : *(_pWhichRanges+2) = 0;
157 170427 : const sal_uInt16 nRg = nWh2 - nWh1 + 1;
158 170427 : _aItems = new const SfxPoolItem* [ nRg ];
159 170427 : memset( (void*) _aItems, 0, nRg * sizeof( SfxPoolItem* ) );
160 170427 : }
161 :
162 : // -----------------------------------------------------------------------
163 :
164 12306 : void SfxItemSet::InitRanges_Impl(va_list pArgs, sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull)
165 : {
166 : DBG_CHKTHIS(SfxItemSet, 0);
167 :
168 12306 : sal_uInt16 nSize = InitializeRanges_Impl( _pWhichRanges, pArgs, nWh1, nWh2, nNull );
169 12306 : _aItems = new const SfxPoolItem* [ nSize ];
170 12306 : memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nSize );
171 12306 : }
172 :
173 : // -----------------------------------------------------------------------
174 :
175 12307 : SfxItemSet::SfxItemSet( SfxItemPool& rPool,
176 : USHORT_ARG nWh1, USHORT_ARG nWh2, USHORT_ARG nNull, ... ):
177 : _pPool( &rPool ),
178 : _pParent( 0 ),
179 : _pWhichRanges( 0 ),
180 12307 : _nCount( 0 )
181 : {
182 : DBG_CTOR(SfxItemSet, DbgCheckItemSet);
183 : DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
184 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
185 : DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
186 :
187 12307 : if(!nNull)
188 : InitRanges_Impl(
189 1 : sal::static_int_cast< sal_uInt16 >(nWh1),
190 2 : sal::static_int_cast< sal_uInt16 >(nWh2));
191 : else {
192 : va_list pArgs;
193 12306 : va_start( pArgs, nNull );
194 : InitRanges_Impl(
195 12306 : pArgs, sal::static_int_cast< sal_uInt16 >(nWh1),
196 12306 : sal::static_int_cast< sal_uInt16 >(nWh2),
197 36918 : sal::static_int_cast< sal_uInt16 >(nNull));
198 12306 : va_end(pArgs);
199 : }
200 12307 : }
201 :
202 : // -----------------------------------------------------------------------
203 :
204 175708 : void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable)
205 : {
206 : DBG_CHKTHIS(SfxItemSet, 0);
207 : #if OSL_DEBUG_LEVEL > 1
208 : OSL_TRACE("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
209 : #endif
210 :
211 175708 : sal_uInt16 nCnt = 0;
212 175708 : const sal_uInt16* pPtr = pWhichPairTable;
213 889806 : while( *pPtr )
214 : {
215 538390 : nCnt += ( *(pPtr+1) - *pPtr ) + 1;
216 538390 : pPtr += 2;
217 : }
218 :
219 175708 : _aItems = new const SfxPoolItem* [ nCnt ];
220 175708 : memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nCnt );
221 :
222 175708 : std::ptrdiff_t cnt = pPtr - pWhichPairTable +1;
223 175708 : _pWhichRanges = new sal_uInt16[ cnt ];
224 175708 : memcpy( _pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt );
225 175708 : }
226 :
227 :
228 : // -----------------------------------------------------------------------
229 :
230 179511 : SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ):
231 : _pPool( &rPool ),
232 : _pParent( 0 ),
233 : _pWhichRanges(0),
234 179511 : _nCount( 0 )
235 : {
236 : DBG_CTOR(SfxItemSet, 0);
237 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
238 : DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
239 :
240 : // pWhichPairTable == 0 ist f"ur das SfxAllEnumItemSet
241 179511 : if ( pWhichPairTable )
242 175708 : InitRanges_Impl(pWhichPairTable);
243 179511 : }
244 :
245 : // -----------------------------------------------------------------------
246 :
247 276915 : SfxItemSet::SfxItemSet( const SfxItemSet& rASet ):
248 : _pPool( rASet._pPool ),
249 : _pParent( rASet._pParent ),
250 276915 : _nCount( rASet._nCount )
251 : {
252 : DBG_CTOR(SfxItemSet, DbgCheckItemSet);
253 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
254 : DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
255 : DBG( ++*_pChildCount(_pParent) );
256 :
257 : // errechne die Anzahl von Attributen
258 276915 : sal_uInt16 nCnt = 0;
259 276915 : sal_uInt16* pPtr = rASet._pWhichRanges;
260 1210676 : while( *pPtr )
261 : {
262 656846 : nCnt += ( *(pPtr+1) - *pPtr ) + 1;
263 656846 : pPtr += 2;
264 : }
265 :
266 276915 : _aItems = new const SfxPoolItem* [ nCnt ];
267 :
268 : // Attribute kopieren
269 276915 : SfxItemArray ppDst = _aItems, ppSrc = rASet._aItems;
270 13474199 : for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc )
271 14631936 : if ( 0 == *ppSrc || // aktueller Default?
272 717381 : IsInvalidItem(*ppSrc) || // Dont Care?
273 717271 : IsStaticDefaultItem(*ppSrc) ) // nicht zu poolende Defaults
274 : // einfach Pointer kopieren
275 12482832 : *ppDst = *ppSrc;
276 714452 : else if ( _pPool->IsItemFlag( **ppSrc, SFX_ITEM_POOLABLE ) )
277 : {
278 : // einfach Pointer kopieren und Ref-Count erh"ohen
279 682496 : *ppDst = *ppSrc;
280 682496 : ( (SfxPoolItem*) (*ppDst) )->AddRef();
281 : }
282 31956 : else if ( !(*ppSrc)->Which() )
283 0 : *ppDst = (*ppSrc)->Clone();
284 : else
285 : // !IsPoolable() => via Pool zuweisen
286 31956 : *ppDst = &_pPool->Put( **ppSrc );
287 :
288 : // dann noch die Which Ranges kopieren
289 : #if OSL_DEBUG_LEVEL > 1
290 : OSL_TRACE("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
291 : #endif
292 276915 : std::ptrdiff_t cnt = pPtr - rASet._pWhichRanges+1;
293 276915 : _pWhichRanges = new sal_uInt16[ cnt ];
294 276915 : memcpy( _pWhichRanges, rASet._pWhichRanges, sizeof( sal_uInt16 ) * cnt);
295 276915 : }
296 :
297 : // -----------------------------------------------------------------------
298 :
299 705583 : SfxItemSet::~SfxItemSet()
300 : {
301 : DBG_DTOR(SfxItemSet, DbgCheckItemSet);
302 : #ifdef DBG_UTIL
303 : DBG( DBG_ASSERT( 0 == *_pChildCount(this), "SfxItemSet: deleting parent-itemset" ) )
304 : #endif
305 :
306 632871 : sal_uInt16 nCount = TotalCount();
307 632871 : if( Count() )
308 : {
309 454481 : SfxItemArray ppFnd = _aItems;
310 49187155 : for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd )
311 48732674 : if( *ppFnd && !IsInvalidItem(*ppFnd) )
312 : {
313 1667895 : if( !(*ppFnd)->Which() )
314 605 : delete (SfxPoolItem*) *ppFnd;
315 : else {
316 : // noch mehrer Referenzen vorhanden, also nur den
317 : // ReferenzCounter manipulieren
318 1667290 : if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) )
319 1498259 : (*ppFnd)->ReleaseRef();
320 : else
321 169031 : if ( !IsDefaultItem(*ppFnd) )
322 : // aus dem Pool loeschen
323 141178 : _pPool->Remove( **ppFnd );
324 : }
325 : }
326 : }
327 :
328 : // FIXME: could be delete[] (SfxPoolItem **)_aItems;
329 632871 : delete[] _aItems;
330 632871 : if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
331 630348 : delete[] _pWhichRanges;
332 632871 : _pWhichRanges = 0; // for invariant-testing
333 :
334 : DBG( --*_pChildCount(_pParent) );
335 : DBG( delete _pChildCount(this); _pChildCountDtor );
336 705583 : }
337 :
338 : // -----------------------------------------------------------------------
339 :
340 322551 : sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
341 :
342 : // einzelnes Item oder alle Items (nWhich==0) l"oschen
343 :
344 : {
345 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
346 322551 : if( !Count() )
347 67468 : return 0;
348 :
349 255083 : sal_uInt16 nDel = 0;
350 255083 : SfxItemArray ppFnd = _aItems;
351 :
352 255083 : if( nWhich )
353 : {
354 233390 : const sal_uInt16* pPtr = _pWhichRanges;
355 571626 : while( *pPtr )
356 : {
357 : // in diesem Bereich?
358 330023 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
359 : {
360 : // "uberhaupt gesetzt?
361 225177 : ppFnd += nWhich - *pPtr;
362 225177 : if( *ppFnd )
363 : {
364 : // wegen der Assertions ins Sub-Calls mu\s das hier sein
365 8246 : --_nCount;
366 8246 : const SfxPoolItem *pItemToClear = *ppFnd;
367 8246 : *ppFnd = 0;
368 :
369 8246 : if ( !IsInvalidItem(pItemToClear) )
370 : {
371 8246 : if ( nWhich <= SFX_WHICH_MAX )
372 : {
373 : const SfxPoolItem& rNew = _pParent
374 2979 : ? _pParent->Get( nWhich, sal_True )
375 9461 : : _pPool->GetDefaultItem( nWhich );
376 :
377 6482 : Changed( *pItemToClear, rNew );
378 : }
379 8246 : if ( pItemToClear->Which() )
380 8246 : _pPool->Remove( *pItemToClear );
381 : }
382 8246 : ++nDel;
383 : }
384 :
385 : // gefunden => raus
386 225177 : break;
387 : }
388 104846 : ppFnd += *(pPtr+1) - *pPtr + 1;
389 104846 : pPtr += 2;
390 : }
391 : }
392 : else
393 : {
394 21693 : nDel = _nCount;
395 :
396 21693 : sal_uInt16* pPtr = _pWhichRanges;
397 116976 : while( *pPtr )
398 : {
399 1403938 : for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
400 1330348 : if( *ppFnd )
401 : {
402 : // wegen der Assertions ins Sub-Calls mu\s das hier sein
403 68942 : --_nCount;
404 68942 : const SfxPoolItem *pItemToClear = *ppFnd;
405 68942 : *ppFnd = 0;
406 :
407 68942 : if ( !IsInvalidItem(pItemToClear) )
408 : {
409 68942 : if ( nWhich <= SFX_WHICH_MAX )
410 : {
411 : const SfxPoolItem& rNew = _pParent
412 14264 : ? _pParent->Get( nWhich, sal_True )
413 76961 : : _pPool->GetDefaultItem( nWhich );
414 :
415 62697 : Changed( *pItemToClear, rNew );
416 : }
417 :
418 : // #i32448#
419 : // Take care of disabled items, too.
420 68942 : if(!pItemToClear->nWhich)
421 : {
422 : // item is disabled, delete it
423 0 : delete pItemToClear;
424 : }
425 : else
426 : {
427 : // remove item from pool
428 68942 : _pPool->Remove( *pItemToClear );
429 : }
430 : }
431 : }
432 73590 : pPtr += 2;
433 : }
434 : }
435 255083 : return nDel;
436 : }
437 :
438 : // -----------------------------------------------------------------------
439 :
440 3308 : void SfxItemSet::ClearInvalidItems( sal_Bool bHardDefault )
441 : {
442 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
443 3308 : sal_uInt16* pPtr = _pWhichRanges;
444 3308 : SfxItemArray ppFnd = _aItems;
445 3308 : if ( bHardDefault )
446 0 : while( *pPtr )
447 : {
448 0 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
449 0 : if ( IsInvalidItem(*ppFnd) )
450 0 : *ppFnd = &_pPool->Put( _pPool->GetDefaultItem(nWhich) );
451 0 : pPtr += 2;
452 : }
453 : else
454 56130 : while( *pPtr )
455 : {
456 423207 : for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
457 373693 : if( IsInvalidItem(*ppFnd) )
458 : {
459 88 : *ppFnd = 0;
460 88 : --_nCount;
461 : }
462 49514 : pPtr += 2;
463 : }
464 3308 : }
465 :
466 : //------------------------------------------------------------------------
467 :
468 :
469 0 : void SfxItemSet::InvalidateAllItems()
470 : {
471 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
472 : DBG_ASSERT( !_nCount, "Es sind noch Items gesetzt" );
473 :
474 0 : memset( (void*)_aItems, -1, ( _nCount = TotalCount() ) * sizeof( SfxPoolItem*) );
475 0 : }
476 :
477 : // -----------------------------------------------------------------------
478 :
479 8942914 : SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich,
480 : sal_Bool bSrchInParent,
481 : const SfxPoolItem **ppItem ) const
482 : {
483 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
484 : // suche den Bereich in dem das Which steht:
485 8942914 : const SfxItemSet* pAktSet = this;
486 8942914 : SfxItemState eRet = SFX_ITEM_UNKNOWN;
487 6968316 : do
488 : {
489 10331356 : SfxItemArray ppFnd = pAktSet->_aItems;
490 10331356 : const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
491 10331356 : if (pPtr)
492 : {
493 29662345 : while ( *pPtr )
494 : {
495 18583043 : if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
496 : {
497 : // in diesem Bereich
498 9583410 : ppFnd += nWhich - *pPtr;
499 9583410 : if ( !*ppFnd )
500 : {
501 7489165 : eRet = SFX_ITEM_DEFAULT;
502 7489165 : if( !bSrchInParent )
503 1268795 : return eRet; // nicht vorhanden
504 6220370 : break; // JP: in den Parents weitersuchen !!!
505 : }
506 :
507 2094245 : if ( (SfxPoolItem*) -1 == *ppFnd )
508 : // Unterschiedlich vorhanden
509 13 : return SFX_ITEM_DONTCARE;
510 :
511 2094232 : if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) )
512 1117 : return SFX_ITEM_DISABLED;
513 :
514 2093115 : if (ppItem)
515 : {
516 : #ifdef DBG_UTIL
517 : const SfxPoolItem *pItem = *ppFnd;
518 : DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
519 : 0 != &((const SfxSetItem*)pItem)->GetItemSet(),
520 : "SetItem without ItemSet" );
521 : #endif
522 621499 : *ppItem = *ppFnd;
523 : }
524 2093115 : return SFX_ITEM_SET;
525 : }
526 8999633 : ppFnd += *(pPtr+1) - *pPtr + 1;
527 8999633 : pPtr += 2;
528 : }
529 : }
530 : } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
531 5579874 : return eRet;
532 : }
533 :
534 0 : bool SfxItemSet::HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem) const
535 : {
536 0 : bool bRet = SFX_ITEM_SET == GetItemState(nWhich, true, ppItem);
537 0 : if (!bRet && ppItem)
538 0 : *ppItem = NULL;
539 0 : return bRet;
540 : }
541 :
542 : // -----------------------------------------------------------------------
543 :
544 1326165 : const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
545 : {
546 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
547 : DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
548 : 0 != &((const SfxSetItem&)rItem).GetItemSet(),
549 : "SetItem without ItemSet" );
550 1326165 : if ( !nWhich )
551 0 : return 0; //! nur wegen Outliner-Bug
552 1326165 : SfxItemArray ppFnd = _aItems;
553 1326165 : const sal_uInt16* pPtr = _pWhichRanges;
554 3614347 : while( *pPtr )
555 : {
556 2160173 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
557 : {
558 : // in diesem Bereich
559 1198156 : ppFnd += nWhich - *pPtr;
560 1198156 : if( *ppFnd ) // schon einer vorhanden
561 : {
562 : // selbes Item bereits vorhanden?
563 222483 : if ( *ppFnd == &rItem )
564 83624 : return 0;
565 :
566 : // wird dontcare oder disabled mit was echtem ueberschrieben?
567 138859 : if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) )
568 : {
569 0 : *ppFnd = &_pPool->Put( rItem, nWhich );
570 0 : return *ppFnd;
571 : }
572 :
573 : // wird disabled?
574 138859 : if( !rItem.Which() )
575 : {
576 0 : *ppFnd = rItem.Clone(_pPool);
577 0 : return 0;
578 : }
579 : else
580 : {
581 : // selber Wert bereits vorhanden?
582 138859 : if ( rItem == **ppFnd )
583 89605 : return 0;
584 :
585 : // den neuen eintragen, den alten austragen
586 49254 : const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
587 49254 : const SfxPoolItem* pOld = *ppFnd;
588 49254 : *ppFnd = &rNew;
589 49254 : if(nWhich <= SFX_WHICH_MAX)
590 48595 : Changed( *pOld, rNew );
591 49254 : _pPool->Remove( *pOld );
592 : }
593 : }
594 : else
595 : {
596 975673 : ++_nCount;
597 975673 : if( !rItem.Which() )
598 605 : *ppFnd = rItem.Clone(_pPool);
599 : else {
600 975068 : const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
601 975068 : *ppFnd = &rNew;
602 975068 : if (nWhich <= SFX_WHICH_MAX )
603 : {
604 : const SfxPoolItem& rOld = _pParent
605 111706 : ? _pParent->Get( nWhich, sal_True )
606 1069339 : : _pPool->GetDefaultItem( nWhich );
607 957633 : Changed( rOld, rNew );
608 : }
609 : }
610 : }
611 : SFX_ASSERT( !_pPool->IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
612 : rItem.ISA(SfxSetItem) || **ppFnd == rItem,
613 : nWhich, "putted Item unequal" );
614 1024927 : return *ppFnd;
615 : }
616 962017 : ppFnd += *(pPtr+1) - *pPtr + 1;
617 962017 : pPtr += 2;
618 : }
619 128009 : return 0;
620 : }
621 :
622 : // -----------------------------------------------------------------------
623 :
624 90758 : int SfxItemSet::Put( const SfxItemSet& rSet, sal_Bool bInvalidAsDefault )
625 : {
626 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
627 90758 : sal_Bool bRet = sal_False;
628 90758 : if( rSet.Count() )
629 : {
630 85698 : SfxItemArray ppFnd = rSet._aItems;
631 85698 : const sal_uInt16* pPtr = rSet._pWhichRanges;
632 387264 : while ( *pPtr )
633 : {
634 19833063 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
635 19617195 : if( *ppFnd )
636 : {
637 259075 : if ( IsInvalidItem( *ppFnd ) )
638 : {
639 0 : if ( bInvalidAsDefault )
640 0 : bRet |= 0 != ClearItem( nWhich );
641 : // gab GPF bei non.WIDs:
642 : // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
643 : else
644 0 : InvalidateItem( nWhich );
645 : }
646 : else
647 259075 : bRet |= 0 != Put( **ppFnd, nWhich );
648 : }
649 215868 : pPtr += 2;
650 : }
651 : }
652 90758 : return bRet;
653 : }
654 :
655 : // -----------------------------------------------------------------------
656 :
657 0 : void SfxItemSet::PutExtended
658 : (
659 : const SfxItemSet& rSet, // Quelle der zu puttenden Items
660 : SfxItemState eDontCareAs, // was mit DontCare-Items passiert
661 : SfxItemState eDefaultAs // was mit Default-Items passiert
662 : )
663 :
664 : /* [Beschreibung]
665 :
666 : Diese Methode "ubernimmt die Items aus 'rSet' in '*this'. Die
667 : Which-Bereiche in '*this', die in 'rSet' nicht vorkommen bleiben unver-
668 : "andert. Der Which-Bereich von '*this' bleibt auch unver"andert.
669 :
670 : In 'rSet' gesetzte Items werden auch in '*this*' gesetzt. Default-
671 : (0 Pointer) und Invalid- (-1 Pointer) Items werden je nach Parameter
672 : ('eDontCareAs' und 'eDefaultAs' behandelt:
673 :
674 : SFX_ITEM_SET: hart auf Default des Pools gesetzt
675 : SFX_ITEM_DEFAULT: gel"oscht (0 Pointer)
676 : SFX_ITEM_DONTCARE: invalidiert (-1 Pointer)
677 :
678 : Alle anderen Werte f"ur 'eDontCareAs' und 'eDefaultAs' sind ung"ultig.
679 : */
680 :
681 : {
682 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
683 :
684 : // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
685 0 : SfxItemArray ppFnd = rSet._aItems;
686 0 : const sal_uInt16* pPtr = rSet._pWhichRanges;
687 0 : while ( *pPtr )
688 : {
689 0 : for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
690 0 : if( *ppFnd )
691 : {
692 0 : if ( IsInvalidItem( *ppFnd ) )
693 : {
694 : // Item ist DontCare:
695 0 : switch ( eDontCareAs )
696 : {
697 : case SFX_ITEM_SET:
698 0 : Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
699 0 : break;
700 :
701 : case SFX_ITEM_DEFAULT:
702 0 : ClearItem( nWhich );
703 0 : break;
704 :
705 : case SFX_ITEM_DONTCARE:
706 0 : InvalidateItem( nWhich );
707 0 : break;
708 :
709 : default:
710 : OSL_FAIL( "invalid Argument for eDontCareAs" );
711 : }
712 : }
713 : else
714 : // Item ist gesetzt:
715 0 : Put( **ppFnd, nWhich );
716 : }
717 : else
718 : {
719 : // Item ist Default:
720 0 : switch ( eDefaultAs )
721 : {
722 : case SFX_ITEM_SET:
723 0 : Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
724 0 : break;
725 :
726 : case SFX_ITEM_DEFAULT:
727 0 : ClearItem( nWhich );
728 0 : break;
729 :
730 : case SFX_ITEM_DONTCARE:
731 0 : InvalidateItem( nWhich );
732 0 : break;
733 :
734 : default:
735 : OSL_FAIL( "invalid Argument for eDefaultAs" );
736 : }
737 : }
738 0 : pPtr += 2;
739 : }
740 0 : }
741 :
742 : // -----------------------------------------------------------------------
743 :
744 0 : void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
745 : /** <H3>Description</H3>
746 :
747 : Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
748 : items which are new ranges too.
749 : */
750 :
751 : {
752 : // special case: exactly one sal_uInt16 which is already included?
753 0 : if ( nFrom == nTo && SFX_ITEM_AVAILABLE <= GetItemState(nFrom, sal_False) )
754 0 : return;
755 :
756 : // merge new range
757 0 : SfxUShortRanges aRanges( _pWhichRanges );
758 0 : aRanges += SfxUShortRanges( nFrom, nTo );
759 0 : SetRanges( aRanges );
760 : }
761 :
762 : // -----------------------------------------------------------------------
763 :
764 0 : void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges )
765 :
766 : /** <H3>Description</H3>
767 :
768 : Modifies the ranges of settable items. Keeps state of items which
769 : are new ranges too.
770 : */
771 :
772 : {
773 : // identische Ranges?
774 0 : if ( _pWhichRanges == pNewRanges )
775 0 : return;
776 0 : const sal_uInt16* pOld = _pWhichRanges;
777 0 : const sal_uInt16* pNew = pNewRanges;
778 0 : while ( *pOld == *pNew )
779 : {
780 0 : if ( !*pOld && !*pNew )
781 0 : return;
782 0 : ++pOld, ++pNew;
783 : }
784 :
785 : // create new item-array (by iterating through all new ranges)
786 0 : sal_uLong nSize = Capacity_Impl(pNewRanges);
787 0 : SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ];
788 0 : sal_uInt16 nNewCount = 0;
789 0 : if ( _nCount == 0 )
790 0 : memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) );
791 : else
792 : {
793 0 : sal_uInt16 n = 0;
794 0 : for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 )
795 : {
796 : // iterate through all ids in the range
797 0 : for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n )
798 : {
799 : // direct move of pointer (not via pool)
800 0 : SfxItemState eState = GetItemState( nWID, sal_False, aNewItems+n );
801 0 : if ( SFX_ITEM_SET == eState )
802 : {
803 : // increment new item count and possibly increment ref count
804 0 : ++nNewCount;
805 0 : aNewItems[n]->AddRef();
806 : }
807 0 : else if ( SFX_ITEM_DISABLED == eState )
808 : {
809 : // put "disabled" item
810 0 : ++nNewCount;
811 0 : aNewItems[n] = new SfxVoidItem(0);
812 : }
813 0 : else if ( SFX_ITEM_DONTCARE == eState )
814 : {
815 0 : ++nNewCount;
816 0 : aNewItems[n] = (SfxPoolItem*)-1;
817 : }
818 : else
819 : {
820 : // default
821 0 : aNewItems[n] = 0;
822 : }
823 : }
824 : }
825 : // free old items
826 0 : sal_uInt16 nOldTotalCount = TotalCount();
827 0 : for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem )
828 : {
829 0 : const SfxPoolItem *pItem = _aItems[nItem];
830 0 : if ( pItem && !IsInvalidItem(pItem) && pItem->Which() )
831 0 : _pPool->Remove(*pItem);
832 : }
833 : }
834 :
835 : // replace old items-array and ranges
836 0 : delete[] _aItems;
837 0 : _aItems = aNewItems;
838 0 : _nCount = nNewCount;
839 :
840 0 : if( pNewRanges == GetPool()->GetFrozenIdRanges() )
841 : {
842 0 : delete[] _pWhichRanges;
843 0 : _pWhichRanges = ( sal_uInt16* ) pNewRanges;
844 : }
845 : else
846 : {
847 0 : sal_uInt16 nCount = Count_Impl(pNewRanges) + 1;
848 0 : if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
849 0 : delete[] _pWhichRanges;
850 0 : _pWhichRanges = new sal_uInt16[ nCount ];
851 0 : memcpy( _pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount );
852 : }
853 : }
854 :
855 : // -----------------------------------------------------------------------
856 :
857 91284 : int SfxItemSet::Set
858 : (
859 : const SfxItemSet& rSet, /* das SfxItemSet, dessen SfxPoolItems
860 : "ubernommen werden sollen */
861 :
862 : sal_Bool bDeep /* sal_True (default)
863 : auch die SfxPoolItems aus den ggf. an
864 : rSet vorhandenen Parents werden direkt
865 : in das SfxItemSet "ubernommen
866 :
867 : sal_False
868 : die SfxPoolItems aus den Parents von
869 : rSet werden nicht ber"ucksichtigt */
870 : )
871 :
872 : /* [Beschreibung]
873 :
874 : Das SfxItemSet nimmt genau die SfxPoolItems an, die auch in
875 : rSet gesetzt sind und im eigenen <Which-Bereich> liegen. Alle
876 : anderen werden entfernt. Der SfxItemPool wird dabei beibehalten,
877 : so da"s die "ubernommenen SfxPoolItems dabei ggf. vom SfxItemPool
878 : von rSet in den SfxItemPool von *this "ubernommen werden.
879 :
880 : SfxPoolItems, f"ur die in rSet IsInvalidItem() == sal_True gilt,
881 : werden als Invalid-Item "ubernommen.
882 :
883 :
884 : [R"uckgabewert]
885 :
886 : int sal_True
887 : es wurden SfxPoolItems "ubernommen
888 :
889 : sal_False
890 : es wurden keine SfxPoolItems "ubernommen,
891 : da z.B. die Which-Bereiche der SfxItemSets
892 : keine Schnittmenge haben oder in der
893 : Schnittmenge keine SfxPoolItems in rSet
894 : gesetzt sind
895 :
896 : */
897 :
898 : {
899 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
900 91284 : int bRet = sal_False;
901 91284 : if ( _nCount )
902 16771 : ClearItem();
903 91284 : if ( bDeep )
904 : {
905 91177 : SfxWhichIter aIter(*this);
906 91177 : sal_uInt16 nWhich = aIter.FirstWhich();
907 3851043 : while ( nWhich )
908 : {
909 : const SfxPoolItem* pItem;
910 3668689 : if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_True, &pItem ) )
911 360681 : bRet |= 0 != Put( *pItem, pItem->Which() );
912 3668689 : nWhich = aIter.NextWhich();
913 91177 : }
914 : }
915 : else
916 107 : bRet = Put(rSet, sal_False);
917 :
918 91284 : return bRet;
919 : }
920 :
921 : //------------------------------------------------------------------------
922 :
923 10593 : const SfxPoolItem* SfxItemSet::GetItem
924 : (
925 : sal_uInt16 nId, // Slot-Id oder Which-Id des Items
926 : sal_Bool bSrchInParent, // sal_True: auch in Parent-ItemSets suchen
927 : TypeId aItemType // != 0 => RTTI Pruefung mit Assertion
928 : ) const
929 :
930 : /* [Beschreibung]
931 :
932 : Mit dieser Methode wird der Zugriff auf einzelne Items im
933 : SfxItemSet wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
934 : (per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
935 : wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
936 : eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
937 : angegebenen Klasse ist. Ist kein Item mit der Id 'nWhich' in dem ItemSet,
938 : so wird 0 zurueckgegeben.
939 : */
940 :
941 : {
942 : // ggf. in Which-Id umrechnen
943 10593 : sal_uInt16 nWhich = GetPool()->GetWhich(nId);
944 :
945 : // ist das Item gesetzt oder bei bDeep==sal_True verf"ugbar?
946 10593 : const SfxPoolItem *pItem = 0;
947 10593 : SfxItemState eState = GetItemState( nWhich, bSrchInParent, &pItem );
948 10593 : if ( bSrchInParent && SFX_ITEM_AVAILABLE == eState &&
949 : nWhich <= SFX_WHICH_MAX )
950 452 : pItem = &_pPool->GetDefaultItem(nWhich);
951 10593 : if ( pItem )
952 : {
953 : // stimmt der Typ "uberein?
954 9905 : if ( !aItemType || pItem->IsA(aItemType) )
955 9905 : return pItem;
956 :
957 : // sonst Fehler melden
958 : OSL_FAIL( "invalid argument type" );
959 : }
960 :
961 : // kein Item gefunden oder falschen Typ gefunden
962 688 : return 0;
963 : }
964 :
965 :
966 : //------------------------------------------------------------------------
967 :
968 :
969 6290616 : const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, sal_Bool bSrchInParent) const
970 : {
971 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
972 : // suche den Bereich in dem das Which steht:
973 6290616 : const SfxItemSet* pAktSet = this;
974 8992568 : do
975 : {
976 10580661 : if( pAktSet->Count() )
977 : {
978 6200764 : SfxItemArray ppFnd = pAktSet->_aItems;
979 6200764 : const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
980 16759600 : while( *pPtr )
981 : {
982 10524921 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
983 : {
984 : // in diesem Bereich
985 6166849 : ppFnd += nWhich - *pPtr;
986 6166849 : if( *ppFnd )
987 : {
988 1588093 : if( (SfxPoolItem*)-1 == *ppFnd ) {
989 : //?MI: folgender code ist Doppelt (unten)
990 : SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig");
991 : //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
992 : //!return aDefault;
993 66 : return _pPool->GetDefaultItem( nWhich );
994 : }
995 : #ifdef DBG_UTIL
996 : const SfxPoolItem *pItem = *ppFnd;
997 : DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
998 : 0 != &((const SfxSetItem*)pItem)->GetItemSet(),
999 : "SetItem without ItemSet" );
1000 : if ( pItem->ISA(SfxVoidItem) || !pItem->Which() )
1001 : DBG_WARNING( "SFX_WARNING: Getting disabled Item" );
1002 : #endif
1003 1588027 : return **ppFnd;
1004 : }
1005 4578756 : break; // dann beim Parent suchen
1006 : }
1007 4358072 : ppFnd += *(pPtr+1) - *pPtr + 1;
1008 4358072 : pPtr += 2;
1009 : }
1010 : }
1011 : // bis zum Ende vom Such-Bereich: was nun ? zum Parent, oder Default ??
1012 : // if( !*pPtr ) // bis zum Ende vom Such-Bereich ?
1013 : // break;
1014 : } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
1015 :
1016 : // dann das Default vom Pool holen und returnen
1017 : SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig");
1018 4702523 : const SfxPoolItem *pItem = &_pPool->GetDefaultItem( nWhich );
1019 : DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
1020 : 0 != &((const SfxSetItem*)pItem)->GetItemSet(),
1021 : "SetItem without ItemSet" );
1022 4702523 : return *pItem;
1023 : }
1024 :
1025 : // Notification-Callback
1026 : // -----------------------------------------------------------------------
1027 :
1028 991153 : void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& )
1029 : {
1030 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1031 991153 : }
1032 :
1033 : // -----------------------------------------------------------------------
1034 :
1035 755119 : sal_uInt16 SfxItemSet::TotalCount() const
1036 : {
1037 : DBG_CHKTHIS(SfxItemSet, 0); // wird im Ctor benutzt bevor vollst. init.
1038 755119 : sal_uInt16 nRet = 0;
1039 755119 : sal_uInt16* pPtr = _pWhichRanges;
1040 3264468 : while( *pPtr )
1041 : {
1042 1754230 : nRet += ( *(pPtr+1) - *pPtr ) + 1;
1043 1754230 : pPtr += 2;
1044 : }
1045 755119 : return nRet;
1046 : }
1047 : // -----------------------------------------------------------------------
1048 :
1049 : // behalte nur die Items, die auch in rSet enthalten sein (Wert egal)
1050 :
1051 1659 : void SfxItemSet::Intersect( const SfxItemSet& rSet )
1052 : {
1053 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1054 : DBG_ASSERT(_pPool, "nicht implementiert ohne Pool");
1055 1659 : if( !Count() ) // gar keine gesetzt ?
1056 837 : return;
1057 :
1058 : // loesche alle Items, die im rSet nicht mehr vorhanden sind
1059 822 : if( !rSet.Count() )
1060 : {
1061 0 : ClearItem(); // alles loeschen
1062 0 : return;
1063 : }
1064 :
1065 : // teste mal, ob sich die Which-Bereiche unterscheiden.
1066 822 : sal_Bool bEqual = sal_True;
1067 822 : sal_uInt16* pWh1 = _pWhichRanges;
1068 822 : sal_uInt16* pWh2 = rSet._pWhichRanges;
1069 822 : sal_uInt16 nSize = 0;
1070 :
1071 4110 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1072 : {
1073 3288 : if( *pWh1 != *pWh2 )
1074 : {
1075 0 : bEqual = sal_False;
1076 0 : break;
1077 : }
1078 3288 : if( n & 1 )
1079 1644 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1080 : }
1081 822 : bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen
1082 :
1083 : // sind die Bereiche identisch, ist es einfacher zu handhaben !
1084 822 : if( bEqual )
1085 : {
1086 822 : SfxItemArray ppFnd1 = _aItems;
1087 822 : SfxItemArray ppFnd2 = rSet._aItems;
1088 :
1089 35346 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1090 34524 : if( *ppFnd1 && !*ppFnd2 )
1091 : {
1092 : // aus dem Pool loeschen
1093 708 : if( !IsInvalidItem( *ppFnd1 ) )
1094 : {
1095 708 : sal_uInt16 nWhich = (*ppFnd1)->Which();
1096 708 : if(nWhich <= SFX_WHICH_MAX)
1097 : {
1098 : const SfxPoolItem& rNew = _pParent
1099 708 : ? _pParent->Get( nWhich, sal_True )
1100 1416 : : _pPool->GetDefaultItem( nWhich );
1101 :
1102 708 : Changed( **ppFnd1, rNew );
1103 : }
1104 708 : _pPool->Remove( **ppFnd1 );
1105 : }
1106 708 : *ppFnd1 = 0;
1107 708 : --_nCount;
1108 : }
1109 : }
1110 : else
1111 : {
1112 0 : SfxItemIter aIter( *this );
1113 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
1114 0 : while( sal_True )
1115 : {
1116 0 : sal_uInt16 nWhich = IsInvalidItem( pItem )
1117 0 : ? GetWhichByPos( aIter.GetCurPos() )
1118 0 : : pItem->Which();
1119 0 : if( 0 == rSet.GetItemState( nWhich, sal_False ) )
1120 0 : ClearItem( nWhich ); // loeschen
1121 0 : if( aIter.IsAtEnd() )
1122 0 : break;
1123 0 : pItem = aIter.NextItem();
1124 0 : }
1125 : }
1126 : }
1127 :
1128 : // -----------------------------------------------------------------------
1129 :
1130 56817 : void SfxItemSet::Differentiate( const SfxItemSet& rSet )
1131 : {
1132 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1133 56817 : if( !Count() || !rSet.Count() ) // gar keine gesetzt ?
1134 82710 : return;
1135 :
1136 : // teste mal, ob sich die Which-Bereiche unterscheiden.
1137 30924 : sal_Bool bEqual = sal_True;
1138 30924 : sal_uInt16* pWh1 = _pWhichRanges;
1139 30924 : sal_uInt16* pWh2 = rSet._pWhichRanges;
1140 30924 : sal_uInt16 nSize = 0;
1141 :
1142 82316 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1143 : {
1144 75880 : if( *pWh1 != *pWh2 )
1145 : {
1146 24488 : bEqual = sal_False;
1147 24488 : break;
1148 : }
1149 51392 : if( n & 1 )
1150 25696 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1151 : }
1152 30924 : bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen
1153 :
1154 : // sind die Bereiche identisch, ist es einfacher zu handhaben !
1155 30924 : if( bEqual )
1156 : {
1157 6436 : SfxItemArray ppFnd1 = _aItems;
1158 6436 : SfxItemArray ppFnd2 = rSet._aItems;
1159 :
1160 648452 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1161 642016 : if( *ppFnd1 && *ppFnd2 )
1162 : {
1163 : // aus dem Pool loeschen
1164 3018 : if( !IsInvalidItem( *ppFnd1 ) )
1165 : {
1166 3018 : sal_uInt16 nWhich = (*ppFnd1)->Which();
1167 3018 : if(nWhich <= SFX_WHICH_MAX)
1168 : {
1169 : const SfxPoolItem& rNew = _pParent
1170 0 : ? _pParent->Get( nWhich, sal_True )
1171 3018 : : _pPool->GetDefaultItem( nWhich );
1172 :
1173 3018 : Changed( **ppFnd1, rNew );
1174 : }
1175 3018 : _pPool->Remove( **ppFnd1 );
1176 : }
1177 3018 : *ppFnd1 = 0;
1178 3018 : --_nCount;
1179 : }
1180 : }
1181 : else
1182 : {
1183 24488 : SfxItemIter aIter( *this );
1184 24488 : const SfxPoolItem* pItem = aIter.GetCurItem();
1185 24 : while( sal_True )
1186 : {
1187 24512 : sal_uInt16 nWhich = IsInvalidItem( pItem )
1188 0 : ? GetWhichByPos( aIter.GetCurPos() )
1189 24512 : : pItem->Which();
1190 24512 : if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False ) )
1191 1264 : ClearItem( nWhich ); // loeschen
1192 24512 : if( aIter.IsAtEnd() )
1193 24488 : break;
1194 24 : pItem = aIter.NextItem();
1195 24488 : }
1196 :
1197 : }
1198 : }
1199 :
1200 : // -----------------------------------------------------------------------
1201 : /* Entscheidungstabelle fuer MergeValue[s]
1202 :
1203 : Grundsaetze:
1204 : 1. Ist der Which-Wert im 1.Set "unknown", dann folgt niemals eine Aktion.
1205 : 2. Ist der Which-Wert im 2.Set "unknown", dann gilt er als "default".
1206 : 3. Es gelten fuer Vergleiche die Werte der "default"-Items.
1207 :
1208 : 1.-Item 2.-Item Values bIgnoreDefs Remove Assign Add
1209 :
1210 : set set == sal_False - - -
1211 : default set == sal_False - - -
1212 : dontcare set == sal_False - - -
1213 : unknown set == sal_False - - -
1214 : set default == sal_False - - -
1215 : default default == sal_False - - -
1216 : dontcare default == sal_False - - -
1217 : unknown default == sal_False - - -
1218 : set dontcare == sal_False 1.-Item -1 -
1219 : default dontcare == sal_False - -1 -
1220 : dontcare dontcare == sal_False - - -
1221 : unknown dontcare == sal_False - - -
1222 : set unknown == sal_False 1.-Item -1 -
1223 : default unknown == sal_False - - -
1224 : dontcare unknown == sal_False - - -
1225 : unknown unknown == sal_False - - -
1226 :
1227 : set set != sal_False 1.-Item -1 -
1228 : default set != sal_False - -1 -
1229 : dontcare set != sal_False - - -
1230 : unknown set != sal_False - - -
1231 : set default != sal_False 1.-Item -1 -
1232 : default default != sal_False - - -
1233 : dontcare default != sal_False - - -
1234 : unknown default != sal_False - - -
1235 : set dontcare != sal_False 1.-Item -1 -
1236 : default dontcare != sal_False - -1 -
1237 : dontcare dontcare != sal_False - - -
1238 : unknown dontcare != sal_False - - -
1239 : set unknown != sal_False 1.-Item -1 -
1240 : default unknown != sal_False - - -
1241 : dontcare unknown != sal_False - - -
1242 : unknown unknown != sal_False - - -
1243 :
1244 : set set == sal_True - - -
1245 : default set == sal_True - 2.-Item 2.-Item
1246 : dontcare set == sal_True - - -
1247 : unknown set == sal_True - - -
1248 : set default == sal_True - - -
1249 : default default == sal_True - - -
1250 : dontcare default == sal_True - - -
1251 : unknown default == sal_True - - -
1252 : set dontcare == sal_True - - -
1253 : default dontcare == sal_True - -1 -
1254 : dontcare dontcare == sal_True - - -
1255 : unknown dontcare == sal_True - - -
1256 : set unknown == sal_True - - -
1257 : default unknown == sal_True - - -
1258 : dontcare unknown == sal_True - - -
1259 : unknown unknown == sal_True - - -
1260 :
1261 : set set != sal_True 1.-Item -1 -
1262 : default set != sal_True - 2.-Item 2.-Item
1263 : dontcare set != sal_True - - -
1264 : unknown set != sal_True - - -
1265 : set default != sal_True - - -
1266 : default default != sal_True - - -
1267 : dontcare default != sal_True - - -
1268 : unknown default != sal_True - - -
1269 : set dontcare != sal_True 1.-Item -1 -
1270 : default dontcare != sal_True - -1 -
1271 : dontcare dontcare != sal_True - - -
1272 : unknown dontcare != sal_True - - -
1273 : set unknown != sal_True - - -
1274 : default unknown != sal_True - - -
1275 : dontcare unknown != sal_True - - -
1276 : unknown unknown != sal_True - - -
1277 : */
1278 :
1279 :
1280 3952 : static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount,
1281 : const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2,
1282 : sal_Bool bIgnoreDefaults )
1283 : {
1284 : DBG_ASSERT( ppFnd1 != 0, "Merging to 0-Item" );
1285 :
1286 : // 1. Item ist default?
1287 3952 : if ( !*ppFnd1 )
1288 : {
1289 3482 : if ( IsInvalidItem(pFnd2) )
1290 : // Entscheidungstabelle: default, dontcare, egal, egal
1291 0 : *ppFnd1 = (SfxPoolItem*) -1;
1292 :
1293 3482 : else if ( pFnd2 && !bIgnoreDefaults &&
1294 0 : _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
1295 : // Entscheidungstabelle: default, set, !=, sal_False
1296 0 : *ppFnd1 = (SfxPoolItem*) -1;
1297 :
1298 3482 : else if ( pFnd2 && bIgnoreDefaults )
1299 : // Entscheidungstabelle: default, set, egal, sal_True
1300 0 : *ppFnd1 = &_pPool->Put( *pFnd2 );
1301 :
1302 3482 : if ( *ppFnd1 )
1303 0 : ++rCount;
1304 : }
1305 :
1306 : // 1. Item ist gesetzt?
1307 470 : else if ( !IsInvalidItem(*ppFnd1) )
1308 : {
1309 462 : if ( !pFnd2 )
1310 : {
1311 : // 2. Item ist default
1312 16 : if ( !bIgnoreDefaults &&
1313 8 : **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) )
1314 : {
1315 : // Entscheidungstabelle: set, default, !=, sal_False
1316 8 : _pPool->Remove( **ppFnd1 );
1317 8 : *ppFnd1 = (SfxPoolItem*) -1;
1318 : }
1319 : }
1320 454 : else if ( IsInvalidItem(pFnd2) )
1321 : {
1322 : // 2. Item ist dontcare
1323 0 : if ( !bIgnoreDefaults ||
1324 0 : **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) )
1325 : {
1326 : // Entscheidungstabelle: set, dontcare, egal, sal_False
1327 : // oder: set, dontcare, !=, sal_True
1328 0 : _pPool->Remove( **ppFnd1 );
1329 0 : *ppFnd1 = (SfxPoolItem*) -1;
1330 : }
1331 : }
1332 : else
1333 : {
1334 : // 2. Item ist gesetzt
1335 454 : if ( **ppFnd1 != *pFnd2 )
1336 : {
1337 : // Entscheidungstabelle: set, set, !=, egal
1338 0 : _pPool->Remove( **ppFnd1 );
1339 0 : *ppFnd1 = (SfxPoolItem*) -1;
1340 : }
1341 : }
1342 : }
1343 3952 : }
1344 :
1345 : // -----------------------------------------------------------------------
1346 :
1347 48 : void SfxItemSet::MergeValues( const SfxItemSet& rSet, sal_Bool bIgnoreDefaults )
1348 : {
1349 : // Achtung!!! Bei Aenderungen/Bugfixes immer obenstehende Tabelle pflegen!
1350 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1351 : DBG_ASSERT( GetPool() == rSet.GetPool(), "MergeValues mit verschiedenen Pools" );
1352 :
1353 : // teste mal, ob sich die Which-Bereiche unterscheiden.
1354 48 : sal_Bool bEqual = sal_True;
1355 48 : sal_uInt16* pWh1 = _pWhichRanges;
1356 48 : sal_uInt16* pWh2 = rSet._pWhichRanges;
1357 48 : sal_uInt16 nSize = 0;
1358 :
1359 272 : for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1360 : {
1361 224 : if( *pWh1 != *pWh2 )
1362 : {
1363 0 : bEqual = sal_False;
1364 0 : break;
1365 : }
1366 224 : if( n & 1 )
1367 112 : nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1368 : }
1369 48 : bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen
1370 :
1371 : // sind die Bereiche identisch, ist es effizieter zu handhaben !
1372 48 : if( bEqual )
1373 : {
1374 48 : SfxItemArray ppFnd1 = _aItems;
1375 48 : SfxItemArray ppFnd2 = rSet._aItems;
1376 :
1377 4000 : for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1378 3952 : MergeItem_Impl( _pPool, _nCount, ppFnd1, *ppFnd2, bIgnoreDefaults );
1379 : }
1380 : else
1381 : {
1382 0 : SfxWhichIter aIter( rSet );
1383 : register sal_uInt16 nWhich;
1384 0 : while( 0 != ( nWhich = aIter.NextWhich() ) )
1385 : {
1386 0 : const SfxPoolItem* pItem = 0;
1387 0 : rSet.GetItemState( nWhich, sal_True, &pItem );
1388 0 : if( !pItem )
1389 : {
1390 : // nicht gesetzt, also default
1391 0 : if ( !bIgnoreDefaults )
1392 0 : MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ), bIgnoreDefaults );
1393 : }
1394 0 : else if( IsInvalidItem( pItem ) )
1395 : // dont care
1396 0 : InvalidateItem( nWhich );
1397 : else
1398 0 : MergeValue( *pItem, bIgnoreDefaults );
1399 0 : }
1400 : }
1401 48 : }
1402 :
1403 : // -----------------------------------------------------------------------
1404 :
1405 0 : void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, sal_Bool bIgnoreDefaults )
1406 : {
1407 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1408 0 : SfxItemArray ppFnd = _aItems;
1409 0 : const sal_uInt16* pPtr = _pWhichRanges;
1410 0 : const sal_uInt16 nWhich = rAttr.Which();
1411 0 : while( *pPtr )
1412 : {
1413 : // in diesem Bereich?
1414 0 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1415 : {
1416 0 : ppFnd += nWhich - *pPtr;
1417 0 : MergeItem_Impl( _pPool, _nCount, ppFnd, &rAttr, bIgnoreDefaults );
1418 0 : break;
1419 : }
1420 0 : ppFnd += *(pPtr+1) - *pPtr + 1;
1421 0 : pPtr += 2;
1422 : }
1423 0 : }
1424 :
1425 : // -----------------------------------------------------------------------
1426 :
1427 212 : void SfxItemSet::InvalidateItem( sal_uInt16 nWhich )
1428 : {
1429 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1430 212 : SfxItemArray ppFnd = _aItems;
1431 212 : const sal_uInt16* pPtr = _pWhichRanges;
1432 445 : while( *pPtr )
1433 : {
1434 212 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1435 : {
1436 : // in diesem Bereich
1437 191 : ppFnd += nWhich - *pPtr;
1438 :
1439 191 : if( *ppFnd ) // bei mir gesetzt
1440 : {
1441 67 : if( (SfxPoolItem*)-1 != *ppFnd ) // noch nicht dontcare !
1442 : {
1443 1 : _pPool->Remove( **ppFnd );
1444 1 : *ppFnd = (SfxPoolItem*)-1;
1445 : }
1446 : }
1447 : else
1448 : {
1449 124 : *ppFnd = (SfxPoolItem*)-1;
1450 124 : ++_nCount;
1451 : }
1452 191 : break;
1453 : }
1454 21 : ppFnd += *(pPtr+1) - *pPtr + 1;
1455 21 : pPtr += 2;
1456 : }
1457 212 : }
1458 :
1459 : // -----------------------------------------------------------------------
1460 :
1461 38620 : sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const
1462 : {
1463 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1464 38620 : sal_uInt16 n = 0;
1465 38620 : sal_uInt16* pPtr = _pWhichRanges;
1466 105277 : while( *pPtr )
1467 : {
1468 66657 : n = ( *(pPtr+1) - *pPtr ) + 1;
1469 66657 : if( nPos < n )
1470 38620 : return *(pPtr)+nPos;
1471 28037 : nPos = nPos - n;
1472 28037 : pPtr += 2;
1473 : }
1474 : DBG_ASSERT( sal_False, "Hier sind wir falsch" );
1475 0 : return 0;
1476 : }
1477 :
1478 : // -----------------------------------------------------------------------
1479 :
1480 888 : SvStream &SfxItemSet::Store
1481 : (
1482 : SvStream& rStream, // Zielstream f"ur normale Items
1483 : bool bDirect // TRUE: Items direkt speicher, FALSE: Surrogate
1484 : ) const
1485 :
1486 : /* [Beschreibung]
1487 :
1488 : Speichert die <SfxItemSet>-Instanz in den angegebenen Stream. Dabei
1489 : werden die Surrorage der gesetzten <SfxPoolItem>s bzw. ('bDirect==sal_True')
1490 : die gesetzten Items selbst wie folgt im Stream abgelegt:
1491 :
1492 : sal_uInt16 (Count) Anzahl der gesetzten Items
1493 : Count* _pPool->StoreItem() siehe <SfxItemPool::StoreItem()const>
1494 :
1495 :
1496 : [Querverweise]
1497 :
1498 : <SfxItemSet::Load(SvStream&,sal_Bool,const SfxItemPool*)>
1499 : */
1500 :
1501 : {
1502 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1503 : DBG_ASSERT( _pPool, "Kein Pool" );
1504 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
1505 :
1506 : // Position des Counts merken, um ggf. zu korrigieren
1507 888 : sal_uLong nCountPos = rStream.Tell();
1508 888 : rStream << _nCount;
1509 :
1510 : // wenn nichts zu speichern ist, auch keinen ItemIter aufsetzen!
1511 888 : if ( _nCount )
1512 : {
1513 : // mitz"ahlen wieviel Items tats"achlich gespeichert werden
1514 150 : sal_uInt16 nWrittenCount = 0; // Anzahl in 'rStream' gestreamter Items
1515 :
1516 : // "uber alle gesetzten Items iterieren
1517 150 : SfxItemIter aIter(*this);
1518 4200 : for ( const SfxPoolItem *pItem = aIter.FirstItem();
1519 : pItem;
1520 : pItem = aIter.NextItem() )
1521 : {
1522 : // Item (ggf. als Surrogat) via Pool speichern lassen
1523 : DBG_ASSERT( !IsInvalidItem(pItem), "can't store invalid items" );
1524 8100 : if ( !IsInvalidItem(pItem) &&
1525 4050 : _pPool->StoreItem( rStream, *pItem, bDirect ) )
1526 : // Item wurde in 'rStream' gestreamt
1527 4050 : ++nWrittenCount;
1528 : };
1529 :
1530 : // weniger geschrieben als enthalten (z.B. altes Format)
1531 150 : if ( nWrittenCount != _nCount )
1532 : {
1533 : // tats"achlichen Count im Stream ablegen
1534 0 : sal_uLong nPos = rStream.Tell();
1535 0 : rStream.Seek( nCountPos );
1536 0 : rStream << nWrittenCount;
1537 0 : rStream.Seek( nPos );
1538 150 : }
1539 : }
1540 :
1541 888 : return rStream;
1542 : }
1543 :
1544 : // -----------------------------------------------------------------------
1545 :
1546 0 : SvStream &SfxItemSet::Load
1547 : (
1548 : SvStream& rStream, // Stream, aus dem geladen werden soll
1549 :
1550 : bool bDirect, /* TRUE
1551 : Items werden direkt aus dem Stream
1552 : gelesen, nicht "uber Surrogate
1553 :
1554 : sal_False (default)
1555 : Items werden "uber Surrogate gelesen */
1556 :
1557 : const SfxItemPool* pRefPool /* Pool, der die Surrogate aufl"osen kann
1558 : (z.B. zum Einf"ugen von Dokumenten) */
1559 : )
1560 :
1561 : /* [Beschreibung]
1562 :
1563 : Diese Methode l"adt ein <SfxItemSet> aus einem Stream. Falls der
1564 : <SfxItemPool> ohne Ref-Counts geladen wurde, werden die geladenen
1565 : Item-Referenzen in den Items hochgez"ahlt, ansonsten wird vorausgesetzt,
1566 : da\s sie schon beim Laden des SfxItemPools ber"ucksichtigt waren.
1567 :
1568 : [Querverweise]
1569 :
1570 : <SfxItemSet::Store(Stream&,sal_Bool)const>
1571 : */
1572 :
1573 : {
1574 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1575 : DBG_ASSERT( _pPool, "Kein Pool");
1576 : DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "Kein Master-Pool");
1577 :
1578 : // kein Ref-Pool => Surrogate mit Pool des ItemSets aufl"osen
1579 0 : if ( !pRefPool )
1580 0 : pRefPool = _pPool;
1581 :
1582 : // Anzahl der zu ladenden Items laden und dann ebensoviele Items
1583 0 : sal_uInt16 nCount = 0;
1584 0 : rStream >> nCount;
1585 0 : for ( sal_uInt16 i = 0; i < nCount; ++i )
1586 : {
1587 : // Surrogat/Item laden und (Surrogat) aufl"osen lassen
1588 : const SfxPoolItem *pItem =
1589 0 : _pPool->LoadItem( rStream, bDirect, pRefPool );
1590 :
1591 : // konnte ein Item geladen oder via Surrogat aufgel"ost werden?
1592 0 : if ( pItem )
1593 : {
1594 : // Position f"ur Item-Pointer im Set suchen
1595 0 : sal_uInt16 nWhich = pItem->Which();
1596 0 : SfxItemArray ppFnd = _aItems;
1597 0 : const sal_uInt16* pPtr = _pWhichRanges;
1598 0 : while ( *pPtr )
1599 : {
1600 : // in diesem Bereich?
1601 0 : if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1602 : {
1603 : // Item-Pointer im Set merken
1604 0 : ppFnd += nWhich - *pPtr;
1605 : SFX_ASSERT( !*ppFnd, nWhich, "Item doppelt eingetragen");
1606 0 : *ppFnd = pItem;
1607 0 : ++_nCount;
1608 0 : break;
1609 : }
1610 :
1611 : // im Range-Array und Item-Array zum n"achsten Which-Range
1612 0 : ppFnd += *(pPtr+1) - *pPtr + 1;
1613 0 : pPtr += 2;
1614 : }
1615 : }
1616 : }
1617 :
1618 0 : return rStream;
1619 : }
1620 :
1621 : // -----------------------------------------------------------------------
1622 :
1623 71502 : int SfxItemSet::operator==(const SfxItemSet &rCmp) const
1624 : {
1625 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1626 : DBG_CHKOBJ(&rCmp, SfxItemSet, DbgCheckItemSet);
1627 :
1628 : // besonders schnell zu ermittelnde Werte muessen gleich sein
1629 129027 : if ( _pParent != rCmp._pParent ||
1630 : _pPool != rCmp._pPool ||
1631 57525 : Count() != rCmp.Count() )
1632 37570 : return sal_False;
1633 :
1634 : // Ranges durchzaehlen lassen dauert laenger, muss aber auch gleich sein
1635 33932 : sal_uInt16 nCount1 = TotalCount();
1636 33932 : sal_uInt16 nCount2 = rCmp.TotalCount();
1637 33932 : if ( nCount1 != nCount2 )
1638 157 : return sal_False;
1639 :
1640 : // sind die Ranges selbst ungleich?
1641 75666 : for ( sal_uInt16 nRange = 0; _pWhichRanges[nRange]; nRange += 2 )
1642 83782 : if ( _pWhichRanges[nRange] != rCmp._pWhichRanges[nRange] ||
1643 41891 : _pWhichRanges[nRange+1] != rCmp._pWhichRanges[nRange+1] )
1644 : {
1645 : // dann m"ussen wir die langsame Methode verwenden
1646 0 : SfxWhichIter aIter( *this );
1647 0 : for ( sal_uInt16 nWh = aIter.FirstWhich();
1648 : nWh;
1649 : nWh = aIter.NextWhich() )
1650 : {
1651 : // wenn die Pointer von poolable Items ungleich sind,
1652 : // muessen die Items gleich sein
1653 0 : const SfxPoolItem *pItem1 = 0, *pItem2 = 0;
1654 0 : if ( GetItemState( nWh, sal_False, &pItem1 ) !=
1655 0 : rCmp.GetItemState( nWh, sal_False, &pItem2 ) ||
1656 : ( pItem1 != pItem2 &&
1657 0 : ( !pItem1 || IsInvalidItem(pItem1) ||
1658 0 : ( _pPool->IsItemFlag(*pItem1, SFX_ITEM_POOLABLE) &&
1659 0 : *pItem1 != *pItem2 ) ) ) )
1660 0 : return sal_False;
1661 : }
1662 :
1663 0 : return sal_True;
1664 : }
1665 :
1666 : // Pointer alle gleich?
1667 33775 : if ( 0 == memcmp( _aItems, rCmp._aItems, nCount1 * sizeof(_aItems[0]) ) )
1668 31816 : return sal_True;
1669 :
1670 : // dann werden wir wohl alle einzeln vergleichen muessen
1671 1959 : const SfxPoolItem **ppItem1 = (const SfxPoolItem**) _aItems;
1672 1959 : const SfxPoolItem **ppItem2 = (const SfxPoolItem**) rCmp._aItems;
1673 12970 : for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos )
1674 : {
1675 : // wenn die Pointer von poolable Items ungleich sind,
1676 : // muessen die Items gleich sein
1677 28842 : if ( *ppItem1 != *ppItem2 &&
1678 5952 : ( ( !*ppItem1 || !*ppItem2 ) ||
1679 5808 : ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) ||
1680 2904 : ( _pPool->IsItemFlag(**ppItem1, SFX_ITEM_POOLABLE) ) ||
1681 1208 : **ppItem1 != **ppItem2 ) )
1682 1959 : return sal_False;
1683 :
1684 11011 : ++ppItem1;
1685 11011 : ++ppItem2;
1686 : }
1687 :
1688 0 : return sal_True;
1689 : }
1690 :
1691 : // -----------------------------------------------------------------------
1692 :
1693 37186 : SfxItemSet *SfxItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const
1694 : {
1695 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1696 37186 : if ( pToPool && pToPool != _pPool )
1697 : {
1698 294 : SfxItemSet *pNewSet = new SfxItemSet( *pToPool, _pWhichRanges );
1699 294 : if ( bItems )
1700 : {
1701 0 : SfxWhichIter aIter(*pNewSet);
1702 0 : sal_uInt16 nWhich = aIter.FirstWhich();
1703 0 : while ( nWhich )
1704 : {
1705 : const SfxPoolItem* pItem;
1706 0 : if ( SFX_ITEM_SET == GetItemState( nWhich, sal_False, &pItem ) )
1707 0 : pNewSet->Put( *pItem, pItem->Which() );
1708 0 : nWhich = aIter.NextWhich();
1709 0 : }
1710 : }
1711 294 : return pNewSet;
1712 : }
1713 : else
1714 : return bItems
1715 36445 : ? new SfxItemSet(*this)
1716 73337 : : new SfxItemSet(*_pPool, _pWhichRanges);
1717 : }
1718 :
1719 : // -----------------------------------------------------------------------
1720 :
1721 74236 : int SfxItemSet::PutDirect(const SfxPoolItem &rItem)
1722 : {
1723 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1724 74236 : SfxItemArray ppFnd = _aItems;
1725 74236 : const sal_uInt16* pPtr = _pWhichRanges;
1726 74236 : const sal_uInt16 nWhich = rItem.Which();
1727 : #ifdef DBG_UTIL
1728 : IsPoolDefaultItem(&rItem) || _pPool->GetSurrogate(&rItem);
1729 : // nur Assertion in den callees provozieren
1730 : #endif
1731 183956 : while( *pPtr )
1732 : {
1733 109720 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1734 : {
1735 : // in diesem Bereich
1736 74236 : ppFnd += nWhich - *pPtr;
1737 74236 : const SfxPoolItem* pOld = *ppFnd;
1738 74236 : if( pOld ) // schon einer vorhanden
1739 : {
1740 130 : if( rItem == **ppFnd )
1741 0 : return sal_False; // schon vorhanden !
1742 130 : _pPool->Remove( *pOld );
1743 : }
1744 : else
1745 74106 : ++_nCount;
1746 :
1747 : // den neuen eintragen
1748 74236 : if( IsPoolDefaultItem(&rItem) )
1749 2944 : *ppFnd = &_pPool->Put( rItem );
1750 : else
1751 : {
1752 71292 : *ppFnd = &rItem;
1753 71292 : if( !IsStaticDefaultItem( &rItem ) )
1754 46242 : rItem.AddRef();
1755 : }
1756 :
1757 74236 : return sal_True;
1758 : }
1759 35484 : ppFnd += *(pPtr+1) - *pPtr + 1;
1760 35484 : pPtr += 2;
1761 : }
1762 0 : return sal_False;
1763 : }
1764 :
1765 : // -----------------------------------------------------------------------
1766 :
1767 3803 : SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool )
1768 : : SfxItemSet(rPool, (const sal_uInt16*) 0),
1769 : aDefault(0),
1770 3803 : nFree(nInitCount)
1771 : {
1772 : // initial keine Items
1773 3803 : _aItems = 0;
1774 :
1775 : // nInitCount Paare an USHORTs fuer Ranges allozieren
1776 3803 : _pWhichRanges = new sal_uInt16[ nInitCount + 1 ];
1777 3803 : memset( _pWhichRanges, 0, ( nInitCount + 1 ) * sizeof(sal_uInt16) );
1778 3803 : }
1779 :
1780 :
1781 : // -----------------------------------------------------------------------
1782 :
1783 :
1784 59 : SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy)
1785 : : SfxItemSet(rCopy),
1786 : aDefault(0),
1787 59 : nFree(0)
1788 : {
1789 59 : }
1790 :
1791 : // -----------------------------------------------------------------------
1792 :
1793 :
1794 :
1795 5 : SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy)
1796 : : SfxItemSet(rCopy),
1797 : aDefault(0),
1798 5 : nFree(0)
1799 : /* [Anmerkung]
1800 :
1801 : Der mu\s sein, da sonst vom Compiler einer generiert wird, er nimmt
1802 : nicht den Ctor mit der 'const SfxItemSet&'!
1803 : */
1804 : {
1805 5 : }
1806 :
1807 : // -----------------------------------------------------------------------
1808 :
1809 1179 : static sal_uInt16 *AddRanges_Impl(
1810 : sal_uInt16 *pUS, std::ptrdiff_t nOldSize, sal_uInt16 nIncr)
1811 :
1812 : /* Diese interne Funktion erzeugt ein neues Which-Range-Array, welches von
1813 : dem 'nOldSize'-USHORTs langen 'pUS' kopiert wird und hinten an Platz
1814 : f"ur 'nIncr' neue USHORTs hat. Das terminierende sal_uInt16 mit der '0'
1815 : wird weder in 'nOldSize' noch in 'nIncr' mitgez"ahlt, sondern implizit
1816 : hinzugerechnet.
1817 :
1818 : Das neue Which-Range-Array wird als Returnwert zur"uckgegeben, das alte
1819 : 'pUS' freigegeben.
1820 : */
1821 :
1822 : {
1823 : // neues Which-Range-Array anlegen
1824 1179 : sal_uInt16 *pNew = new sal_uInt16[ nOldSize + nIncr + 1 ];
1825 :
1826 : // die alten Ranges "ubernehmen
1827 1179 : memcpy( pNew, pUS, nOldSize * sizeof(sal_uInt16) );
1828 :
1829 : // die neuen auf 0 initialisieren
1830 1179 : memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(sal_uInt16) );
1831 :
1832 : // das alte Array freigeben
1833 1179 : delete[] pUS;
1834 :
1835 1179 : return pNew;
1836 : }
1837 :
1838 : // -----------------------------------------------------------------------
1839 :
1840 11896 : static SfxItemArray AddItem_Impl(SfxItemArray pItems, sal_uInt16 nOldSize, sal_uInt16 nPos)
1841 :
1842 : /* Diese interne Funktion erzeugt ein neues ItemArray, welches von 'pItems'
1843 : kopiert wird, an der Position 'nPos' jedoch Platz f"ur einen neuen
1844 : ItemPointer hat.
1845 :
1846 : Das neue ItemArray wird als Returnwert zur"uckgegeben, das alte 'pItems'
1847 : wird freigegeben.
1848 : */
1849 :
1850 : {
1851 : // neues ItemArray anlegen
1852 11896 : SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1];
1853 :
1854 : // war schon vorher eins da?
1855 11896 : if ( pItems )
1856 : {
1857 : // alte Items vor nPos kopieren
1858 8867 : if ( nPos )
1859 8867 : memcpy( (void*) pNew, pItems, nPos * sizeof(SfxPoolItem *) );
1860 :
1861 : // alte Items hinter nPos kopieren
1862 8867 : if ( nPos < nOldSize )
1863 1148 : memcpy( (void*) (pNew + nPos + 1), pItems + nPos,
1864 1722 : (nOldSize-nPos) * sizeof(SfxPoolItem *) );
1865 : }
1866 :
1867 : // neues Item initialisieren
1868 11896 : *(pNew + nPos) = 0;
1869 :
1870 : // altes ItemArray freigeben
1871 11896 : delete[] pItems;
1872 :
1873 11896 : return pNew;
1874 : }
1875 :
1876 : // -----------------------------------------------------------------------
1877 :
1878 16348 : const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
1879 :
1880 : // Putten mit automatischer Erweiterung der Whichs-Ids um die ID
1881 : // des Items.
1882 :
1883 : {
1884 16348 : sal_uInt16 nPos = 0; // Position f"ur 'rItem' in '_aItems'
1885 16348 : const sal_uInt16 nItemCount = TotalCount();
1886 :
1887 : // erstmal sehen, ob es schon einen passenden Bereich gibt
1888 16348 : sal_uInt16 *pPtr = _pWhichRanges;
1889 79138 : while ( *pPtr )
1890 : {
1891 : // Which-Id liegt in diesem Bereich?
1892 50894 : if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1893 : {
1894 : // Einfuegen
1895 4452 : nPos += nWhich - *pPtr;
1896 4452 : break;
1897 : }
1898 :
1899 : // Position des Items in _aItems mitf"uhren
1900 46442 : nPos += *(pPtr+1) - *pPtr + 1;
1901 :
1902 : // zum n"achsten Bereich
1903 46442 : pPtr += 2;
1904 : }
1905 :
1906 : // Which-Id noch nicht vorhanden?
1907 16348 : if ( !*pPtr )
1908 : {
1909 : // suchen, ob man sie irgendwo dranpacken kann
1910 11896 : pPtr = _pWhichRanges;
1911 11896 : nPos = 0;
1912 55723 : while ( *pPtr )
1913 : {
1914 : // Which-Id liegt exakt vor diesem Bereich?
1915 32505 : if ( (nWhich+1) == *pPtr )
1916 : {
1917 : // Bereich waechst nach unten
1918 288 : (*pPtr)--;
1919 :
1920 : // vor erstem Item dieses Bereichs Platz schaffen
1921 288 : _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1922 288 : break;
1923 : }
1924 :
1925 : // Which-Id liegt exakt hinter diesem Bereich?
1926 32217 : else if ( (nWhich-1) == *(pPtr+1) )
1927 : {
1928 : // Bereich waechst nach oben
1929 286 : (*(pPtr+1))++;
1930 :
1931 : // hinter letztem Item dieses Bereichs Platz schaffen
1932 286 : nPos += nWhich - *pPtr;
1933 286 : _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1934 286 : break;
1935 : }
1936 :
1937 : // Position des Items in _aItems mitf"uhren
1938 31931 : nPos += *(pPtr+1) - *pPtr + 1;
1939 :
1940 : // zum n"achsten Bereich
1941 31931 : pPtr += 2;
1942 : }
1943 : }
1944 :
1945 : // keinen erweiterbaren Bereich gefunden?
1946 16348 : if ( !*pPtr )
1947 : {
1948 : // kein Platz mehr in _pWhichRanges => erweitern
1949 11322 : std::ptrdiff_t nSize = pPtr - _pWhichRanges;
1950 11322 : if( !nFree )
1951 : {
1952 1179 : _pWhichRanges = AddRanges_Impl(_pWhichRanges, nSize, nInitCount);
1953 1179 : nFree += nInitCount;
1954 : }
1955 :
1956 : // neuen Which-Range anh"angen
1957 11322 : pPtr = _pWhichRanges + nSize;
1958 11322 : *pPtr++ = nWhich;
1959 11322 : *pPtr = nWhich;
1960 11322 : nFree -= 2;
1961 :
1962 : // Itemarray vergroessern
1963 11322 : nPos = nItemCount;
1964 11322 : _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1965 : }
1966 :
1967 : // neues Item in Pool aufnehmen
1968 16348 : const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
1969 :
1970 : // altes Item merken
1971 16348 : sal_Bool bIncrementCount = sal_False;
1972 16348 : const SfxPoolItem* pOld = *( _aItems + nPos );
1973 16348 : if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld ) // state "dontcare"
1974 0 : pOld = NULL;
1975 16348 : if ( !pOld )
1976 : {
1977 11911 : bIncrementCount = sal_True;
1978 : pOld = _pParent ?
1979 0 : &_pParent->Get( nWhich, sal_True )
1980 11911 : : nWhich <= SFX_WHICH_MAX ? &_pPool->GetDefaultItem( nWhich ) : 0;
1981 : }
1982 :
1983 : // neue Item in ItemSet aufnehmen
1984 16348 : *(_aItems + nPos) = &rNew;
1985 :
1986 : // Changed Notification versenden
1987 16348 : if ( pOld )
1988 : {
1989 4437 : Changed( *pOld, rNew );
1990 4437 : if ( !IsDefaultItem(pOld) )
1991 4437 : _pPool->Remove( *pOld );
1992 : }
1993 :
1994 16348 : if ( bIncrementCount )
1995 11911 : ++_nCount;
1996 :
1997 16348 : return &rNew;
1998 : }
1999 :
2000 : // -----------------------------------------------------------------------
2001 :
2002 :
2003 : /* Diese Methode wird forwarded, damit sie nicht durch die anderen
2004 : Put-Methoden dieser SubClass gehided wird.
2005 : */
2006 :
2007 1358 : int SfxAllItemSet::Put( const SfxItemSet& rSet, sal_Bool bInvalidAsDefault )
2008 : {
2009 : //? pruefen, ob Which-Ranges erweitert werden
2010 1358 : return SfxItemSet::Put( rSet, bInvalidAsDefault );
2011 : }
2012 :
2013 : // -----------------------------------------------------------------------
2014 : // Item disablen, wenn durch ein VoidItem mit dem Which-Wert 0 ausgedrueckt
2015 :
2016 605 : void SfxItemSet::DisableItem(sal_uInt16 nWhich)
2017 : {
2018 : DBG_CHKTHIS(SfxItemSet, 0);
2019 605 : Put( SfxVoidItem(0), nWhich );
2020 605 : }
2021 :
2022 : // -----------------------------------------------------------------------
2023 :
2024 0 : SfxItemSet *SfxAllItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const
2025 : {
2026 : DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
2027 0 : if ( pToPool && pToPool != _pPool )
2028 : {
2029 0 : SfxAllItemSet *pNewSet = new SfxAllItemSet( *pToPool );
2030 0 : if ( bItems )
2031 0 : pNewSet->Set( *this );
2032 0 : return pNewSet;
2033 : }
2034 : else
2035 0 : return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool);
2036 : }
2037 :
2038 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|