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