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