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