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