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 51 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 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 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 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 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 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 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 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 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 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 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 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 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 507 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 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 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 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 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 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 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 948 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 994 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 1053 void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& ) 1054 { 1055 DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet); 1056 } 1057 1058 // ----------------------------------------------------------------------- 1059 1060 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 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 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 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 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 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 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 1491 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 1510 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 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 1655 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 1725 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 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 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 1817 SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy) 1818 : SfxItemSet(rCopy), 1819 aDefault(0), 1820 nFree(0) 1821 { 1822 } 1823 1824 // ----------------------------------------------------------------------- 1825 1826 1827 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 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 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 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 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 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 2126 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. 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 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 additional bool data field for saving space. 2153 if (!IsValidateHashKey() ) 2154 { 2155 _aHashKey = 1; 2156 } 2157 } 2158 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