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 #include <stdio.h> 33 #ifndef GCC 34 #endif 35 36 #include <svl/itempool.hxx> 37 #include "whassert.hxx" 38 #include <svl/brdcst.hxx> 39 #include <svl/smplhint.hxx> 40 #include "poolio.hxx" 41 42 //======================================================================== 43 44 45 void SfxItemPool::AddSfxItemPoolUser(SfxItemPoolUser& rNewUser) 46 { 47 maSfxItemPoolUsers.push_back(&rNewUser); 48 } 49 50 void SfxItemPool::RemoveSfxItemPoolUser(SfxItemPoolUser& rOldUser) 51 { 52 const SfxItemPoolUserVector::iterator aFindResult = ::std::find(maSfxItemPoolUsers.begin(), maSfxItemPoolUsers.end(), &rOldUser); 53 if(aFindResult != maSfxItemPoolUsers.end()) 54 { 55 maSfxItemPoolUsers.erase(aFindResult); 56 } 57 } 58 59 const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const 60 { 61 DBG_CHKTHIS(SfxItemPool, 0); 62 const SfxPoolItem* pRet; 63 if( IsInRange( nWhich ) ) 64 pRet = *(ppPoolDefaults + GetIndex_Impl( nWhich )); 65 else if( pSecondary ) 66 pRet = pSecondary->GetPoolDefaultItem( nWhich ); 67 else 68 { 69 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get pool default" ); 70 pRet = 0; 71 } 72 return pRet; 73 } 74 75 // ----------------------------------------------------------------------- 76 77 inline FASTBOOL SfxItemPool::IsItemFlag_Impl( sal_uInt16 nPos, sal_uInt16 nFlag ) const 78 { 79 sal_uInt16 nItemFlag = pItemInfos[nPos]._nFlags; 80 return nFlag == (nItemFlag & nFlag); 81 } 82 83 // ----------------------------------------------------------------------- 84 85 FASTBOOL SfxItemPool::IsItemFlag( sal_uInt16 nWhich, sal_uInt16 nFlag ) const 86 { 87 for ( const SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary ) 88 { 89 if ( pPool->IsInRange(nWhich) ) 90 return pPool->IsItemFlag_Impl( pPool->GetIndex_Impl(nWhich), nFlag); 91 } 92 DBG_ASSERT( !IsWhich(nWhich), "unknown which-id" ); 93 return sal_False; 94 } 95 96 // ----------------------------------------------------------------------- 97 98 SfxBroadcaster& SfxItemPool::BC() 99 { 100 return pImp->aBC; 101 } 102 103 // ----------------------------------------------------------------------- 104 105 106 SfxItemPool::SfxItemPool 107 ( 108 UniString const & rName, /* Name des Pools zur Idetifikation 109 im File-Format */ 110 sal_uInt16 nStartWhich, /* erste Which-Id des Pools */ 111 sal_uInt16 nEndWhich, /* letzte Which-Id des Pools */ 112 #ifdef TF_POOLABLE 113 const SfxItemInfo* pInfos, /* SID-Map und Item-Flags */ 114 #endif 115 SfxPoolItem** pDefaults, /* Pointer auf statische Defaults, 116 wird direkt vom Pool referenziert, 117 jedoch kein Eigent"umer"ubergang */ 118 #ifndef TF_POOLABLE 119 sal_uInt16* pSlotIdArray, /* Zuordnung von Slot-Ids zu Which-Ids */ 120 #endif 121 FASTBOOL bLoadRefCounts /* Ref-Counts mitladen oder auf 1 setzen */ 122 ) 123 124 /* [Beschreibung] 125 126 Der im Normalfall verwendete Konstruktor der Klasse SfxItemPool. Es 127 wird eine SfxItemPool-Instanz initialisiert, die Items im b"undigen 128 Which-Bereich von 'nStartWhich' bis 'nEndWhich' verwalten kann. 129 130 F"ur jede dieser Which-Ids mu\s ein statischer Default im Array 'pDefaults' 131 vorhanden sein, die dort beginnend mit einem <SfxPoolItem> mit der 132 Which-Id 'nStartWhich' nach Which-Ids sortiert aufeinanderfolgend 133 eingetragen sein m"ussen. 134 135 'pItemInfos' ist ein identisch angeordnetes Array von USHORTs, die 136 Slot-Ids darstellen und Flags. Die Slot-Ids k"onnen 0 sein, wenn die 137 betreffenden Items ausschlie\slich in der Core verwendet werden. 138 "Uber die Flags kann z.B. bestimmt werden, ob Value-Sharing 139 (SFX_ITEM_POOLABLE) stattfinden soll. 140 141 [Anmerkung] 142 143 Wenn der Pool <SfxSetItem>s enthalten soll, k"onnen im Konstruktor noch 144 keine static-Defaults angegeben werden. Dies mu\s dann nachtr"aglich 145 mit <SfxItemPool::SetDefaults(SfxItemPool**)> geschehen. 146 147 148 [Querverweise] 149 150 <SfxItemPool::SetDefaults(SfxItemPool**)> 151 <SfxItemPool::ReleaseDefaults(SfxPoolItem**,sal_uInt16,sal_Bool)> 152 <SfxItemPool::ReldaseDefaults(sal_Bool)> 153 */ 154 155 : aName(rName), 156 nStart(nStartWhich), 157 nEnd(nEndWhich), 158 #ifdef TF_POOLABLE 159 pItemInfos(pInfos), 160 #else 161 pSlotIds(pSlotIdArray), 162 #endif 163 pImp( new SfxItemPool_Impl( nStart, nEnd ) ), 164 ppStaticDefaults(0), 165 ppPoolDefaults(new SfxPoolItem* [ nEndWhich - nStartWhich + 1]), 166 pSecondary(0), 167 pMaster(this), 168 _pPoolRanges( 0 ), 169 bPersistentRefCounts(bLoadRefCounts), 170 maSfxItemPoolUsers() 171 { 172 DBG_CTOR(SfxItemPool, 0); 173 DBG_ASSERT(nStart, "Start-Which-Id must be greater 0" ); 174 175 pImp->eDefMetric = SFX_MAPUNIT_TWIP; 176 pImp->nVersion = 0; 177 pImp->bStreaming = sal_False; 178 pImp->nLoadingVersion = 0; 179 pImp->nInitRefCount = 1; 180 pImp->nVerStart = nStart; 181 pImp->nVerEnd = nEnd; 182 pImp->bInSetItem = sal_False; 183 pImp->nStoringStart = nStartWhich; 184 pImp->nStoringEnd = nEndWhich; 185 186 memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1)); 187 188 if ( pDefaults ) 189 SetDefaults(pDefaults); 190 } 191 192 // ----------------------------------------------------------------------- 193 194 195 SfxItemPool::SfxItemPool 196 ( 197 const SfxItemPool& rPool, // von dieser Instanz kopieren 198 sal_Bool bCloneStaticDefaults /* sal_True 199 statische Defaults kopieren 200 201 sal_False 202 statische Defaults 203 "ubernehehmen */ 204 ) 205 206 /* [Beschreibung] 207 208 Copy-Konstruktor der Klasse SfxItemPool. 209 210 211 [Querverweise] 212 213 <SfxItemPool::Clone()const> 214 */ 215 216 : aName(rPool.aName), 217 nStart(rPool.nStart), 218 nEnd(rPool.nEnd), 219 #ifdef TF_POOLABLE 220 pItemInfos(rPool.pItemInfos), 221 #else 222 pSlotIds(rPool.pSlotIds), 223 #endif 224 pImp( new SfxItemPool_Impl( nStart, nEnd ) ), 225 ppStaticDefaults(0), 226 ppPoolDefaults(new SfxPoolItem* [ nEnd - nStart + 1]), 227 pSecondary(0), 228 pMaster(this), 229 _pPoolRanges( 0 ), 230 bPersistentRefCounts(rPool.bPersistentRefCounts ), 231 maSfxItemPoolUsers() 232 { 233 DBG_CTOR(SfxItemPool, 0); 234 pImp->eDefMetric = rPool.pImp->eDefMetric; 235 pImp->nVersion = rPool.pImp->nVersion; 236 pImp->bStreaming = sal_False; 237 pImp->nLoadingVersion = 0; 238 pImp->nInitRefCount = 1; 239 pImp->nVerStart = rPool.pImp->nVerStart; 240 pImp->nVerEnd = rPool.pImp->nVerEnd; 241 pImp->bInSetItem = sal_False; 242 pImp->nStoringStart = nStart; 243 pImp->nStoringEnd = nEnd; 244 245 memset( ppPoolDefaults, 0, sizeof( SfxPoolItem* ) * (nEnd - nStart + 1)); 246 247 // Static Defaults "ubernehmen 248 if ( bCloneStaticDefaults ) 249 { 250 SfxPoolItem **ppDefaults = new SfxPoolItem*[nEnd-nStart+1]; 251 for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n ) 252 { 253 (*( ppDefaults + n )) = (*( rPool.ppStaticDefaults + n ))->Clone(this); 254 (*( ppDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT ); 255 } 256 257 SetDefaults( ppDefaults ); 258 } 259 else 260 SetDefaults( rPool.ppStaticDefaults ); 261 262 // Pool Defaults kopieren 263 for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n ) 264 if ( (*( rPool.ppPoolDefaults + n )) ) 265 { 266 (*( ppPoolDefaults + n )) = (*( rPool.ppPoolDefaults + n ))->Clone(this); 267 (*( ppPoolDefaults + n ))->SetKind( SFX_ITEMS_POOLDEFAULT ); 268 } 269 270 // Copy Version-Map 271 for ( size_t nVer = 0; nVer < rPool.pImp->aVersions.size(); ++nVer ) 272 { 273 const SfxPoolVersion_ImplPtr pOld = rPool.pImp->aVersions[nVer]; 274 SfxPoolVersion_ImplPtr pNew = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl( *pOld ) ); 275 pImp->aVersions.push_back( pNew ); 276 } 277 278 // Verkettung wiederherstellen 279 if ( rPool.pSecondary ) 280 SetSecondaryPool( rPool.pSecondary->Clone() ); 281 } 282 283 // ----------------------------------------------------------------------- 284 285 void SfxItemPool::SetDefaults( SfxPoolItem **pDefaults ) 286 { 287 DBG_CHKTHIS(SfxItemPool, 0); 288 DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." ); 289 DBG_ASSERT( !ppStaticDefaults, "habe schon defaults" ); 290 291 ppStaticDefaults = pDefaults; 292 //! if ( (*ppStaticDefaults)->GetKind() != SFX_ITEMS_STATICDEFAULT ) 293 //! geht wohl nicht im Zshg mit SetItems, die hinten stehen 294 { 295 DBG_ASSERT( (*ppStaticDefaults)->GetRefCount() == 0 || 296 IsDefaultItem( (*ppStaticDefaults) ), 297 "das sind keine statics" ); 298 for ( sal_uInt16 n = 0; n <= nEnd - nStart; ++n ) 299 { 300 SFX_ASSERT( (*( ppStaticDefaults + n ))->Which() == n + nStart, 301 n + nStart, "static defaults not sorted" ); 302 (*( ppStaticDefaults + n ))->SetKind( SFX_ITEMS_STATICDEFAULT ); 303 DBG_ASSERT( !(pImp->ppPoolItems[n]), "defaults with setitems with items?!" ); 304 } 305 } 306 } 307 308 // ----------------------------------------------------------------------- 309 310 void SfxItemPool::ReleaseDefaults 311 ( 312 sal_Bool bDelete /* sal_True 313 l"oscht sowohl das Array als auch die einzelnen 314 statischen Defaults 315 316 sal_False 317 l"oscht weder das Array noch die einzelnen 318 statischen Defaults */ 319 ) 320 321 /* [Beschreibung] 322 323 Gibt die statischen Defaults der betreffenden SfxItemPool-Instanz frei 324 und l"oscht ggf. die statischen Defaults. 325 326 Nach Aufruf dieser Methode darf die SfxItemPool-Instanz nicht mehr 327 verwendet werden, einzig ist der Aufruf des Destruktors zu"lassig. 328 */ 329 330 { 331 DBG_ASSERT( ppStaticDefaults, "keine Arme keine Kekse" ); 332 ReleaseDefaults( ppStaticDefaults, nEnd - nStart + 1, bDelete ); 333 334 // KSO (22.10.98): ppStaticDefaults zeigt auf geloeschten Speicher, 335 // wenn bDelete == sal_True. 336 if ( bDelete ) 337 ppStaticDefaults = 0; 338 } 339 340 // ----------------------------------------------------------------------- 341 342 void SfxItemPool::ReleaseDefaults 343 ( 344 SfxPoolItem** pDefaults, /* freizugebende statische Defaults */ 345 346 sal_uInt16 nCount, /* Anzahl der statischen Defaults */ 347 348 sal_Bool bDelete /* sal_True 349 l"oscht sowohl das Array als auch die 350 einzelnen statischen Defaults 351 352 sal_False 353 l"oscht weder das Array noch die 354 einzelnen statischen Defaults */ 355 ) 356 357 /* [Beschreibung] 358 359 Gibt die angegebenen statischen Defaults frei und l"oscht ggf. 360 die statischen Defaults. 361 362 Diese Methode darf erst nach Zerst"orung aller SfxItemPool-Instanzen, 363 welche die angegebenen statischen Defaults 'pDefault' verwenden, 364 aufgerufen werden. 365 */ 366 367 { 368 DBG_ASSERT( pDefaults, "erst wollen, dann nichts geben..." ); 369 370 for ( sal_uInt16 n = 0; n < nCount; ++n ) 371 { 372 SFX_ASSERT( IsStaticDefaultItem( *(pDefaults+n) ), 373 n, "das ist kein static-default" ); 374 (*( pDefaults + n ))->SetRefCount( 0 ); 375 if ( bDelete ) 376 { delete *( pDefaults + n ); *(pDefaults + n) = 0; } 377 } 378 379 if ( bDelete ) 380 { delete[] pDefaults; pDefaults = 0; } 381 } 382 383 // ----------------------------------------------------------------------- 384 385 SfxItemPool::~SfxItemPool() 386 { 387 DBG_DTOR(SfxItemPool, 0); 388 DBG_ASSERT( pMaster == this, "destroying active Secondary-Pool" ); 389 390 if ( pImp->ppPoolItems && ppPoolDefaults ) 391 Delete(); 392 delete[] _pPoolRanges; 393 delete pImp; 394 } 395 396 void SfxItemPool::Free(SfxItemPool* pPool) 397 { 398 if(pPool) 399 { 400 // tell all the registered SfxItemPoolUsers that the pool is in destruction 401 SfxItemPoolUserVector aListCopy(pPool->maSfxItemPoolUsers.begin(), pPool->maSfxItemPoolUsers.end()); 402 for(SfxItemPoolUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++) 403 { 404 SfxItemPoolUser* pSfxItemPoolUser = *aIterator; 405 DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)"); 406 pSfxItemPoolUser->ObjectInDestruction(*pPool); 407 } 408 409 // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser() 410 // when they get called from ObjectInDestruction(). 411 pPool->maSfxItemPoolUsers.clear(); 412 413 // delete pool 414 delete pPool; 415 } 416 } 417 418 // ----------------------------------------------------------------------- 419 420 421 void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool ) 422 { 423 // ggf. an abgeh"angten Pools den Master zur"ucksetzen 424 if ( pSecondary ) 425 { 426 #ifdef DBG_UTIL 427 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) 428 if ( ppStaticDefaults ) 429 { 430 // Delete() ist noch nicht gelaufen? 431 if ( pImp->ppPoolItems && pSecondary->pImp->ppPoolItems ) 432 { 433 // hat der master SetItems? 434 sal_Bool bHasSetItems = sal_False; 435 for ( sal_uInt16 i = 0; !bHasSetItems && i < nEnd-nStart; ++i ) 436 bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem); 437 438 // abgehaengte Pools muessen leer sein 439 sal_Bool bOK = bHasSetItems; 440 for ( sal_uInt16 n = 0; 441 bOK && n <= pSecondary->nEnd - pSecondary->nStart; 442 ++n ) 443 { 444 SfxPoolItemArray_Impl** ppItemArr = 445 pSecondary->pImp->ppPoolItems + n; 446 if ( *ppItemArr ) 447 { 448 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 449 for( size_t i = (*ppItemArr)->size(); i; ++ppHtArr, --i ) 450 if ( !(*ppHtArr) ) 451 { 452 DBG_ERROR( "old secondary pool must be empty" ); 453 bOK = sal_False; 454 break; 455 } 456 } 457 } 458 } 459 } 460 #endif 461 462 pSecondary->pMaster = pSecondary; 463 for ( SfxItemPool *p = pSecondary->pSecondary; p; p = p->pSecondary ) 464 p->pMaster = pSecondary; 465 } 466 467 // ggf. den Master der neuen Secondary-Pools setzen 468 DBG_ASSERT( !pPool || pPool->pMaster == pPool, "Secondary tanzt auf zwei Hochzeiten " ); 469 SfxItemPool *pNewMaster = pMaster ? pMaster : this; 470 for ( SfxItemPool *p = pPool; p; p = p->pSecondary ) 471 p->pMaster = pNewMaster; 472 473 // neuen Secondary-Pool merken 474 pSecondary = pPool; 475 } 476 477 // ----------------------------------------------------------------------- 478 479 SfxMapUnit SfxItemPool::GetMetric( sal_uInt16 ) const 480 { 481 DBG_CHKTHIS(SfxItemPool, 0); 482 483 return pImp->eDefMetric; 484 } 485 486 // ----------------------------------------------------------------------- 487 488 void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric ) 489 { 490 DBG_CHKTHIS(SfxItemPool, 0); 491 492 pImp->eDefMetric = eNewMetric; 493 } 494 495 // ----------------------------------------------------------------------- 496 497 SfxItemPresentation SfxItemPool::GetPresentation 498 ( 499 const SfxPoolItem& rItem, /* IN: <SfxPoolItem>, dessen textuelle 500 Wert-Darstellung geliefert werden 501 soll */ 502 SfxItemPresentation ePresent, /* IN: gew"unschte Art der Darstellung; 503 siehe <SfxItemPresentation> */ 504 SfxMapUnit eMetric, /* IN: gew"unschte Ma\seinheit der Darstellung */ 505 XubString& rText, /* OUT: textuelle Darstellung von 'rItem' */ 506 const IntlWrapper * pIntlWrapper 507 ) const 508 509 /* [Beschreibung] 510 511 "Uber diese virtuelle Methode k"onnen textuelle Darstellungen der 512 von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems 513 angefordert werden. 514 515 In Ableitungen sollte diese Methode "uberladen werden und auf 516 SfxPoolItems reagiert werden, die bei <SfxPoolItem::GetPresentation()const> 517 keine vollst"andige Information liefern k"onnen. 518 519 Die Basisklasse liefert die unver"anderte Presentation von 'rItem'. 520 */ 521 522 { 523 DBG_CHKTHIS(SfxItemPool, 0); 524 return rItem.GetPresentation( 525 ePresent, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper ); 526 } 527 528 529 // ----------------------------------------------------------------------- 530 531 SfxItemPool* SfxItemPool::Clone() const 532 { 533 DBG_CHKTHIS(SfxItemPool, 0); 534 535 SfxItemPool *pPool = new SfxItemPool( *this ); 536 return pPool; 537 } 538 539 // ---------------------------------------------------------------------- 540 541 void SfxItemPool::Delete() 542 { 543 DBG_CHKTHIS(SfxItemPool, 0); 544 545 // schon deleted? 546 if ( !pImp->ppPoolItems || !ppPoolDefaults ) 547 return; 548 549 // z.B. laufenden Requests bescheidsagen 550 pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) ); 551 552 //MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems. 553 //Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt. 554 555 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; 556 SfxPoolItem** ppDefaultItem = ppPoolDefaults; 557 SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults; 558 sal_uInt16 nArrCnt; 559 560 //Erst die SetItems abraeumen 561 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) 562 if ( ppStaticDefaults ) 563 { 564 for ( nArrCnt = GetSize_Impl(); 565 nArrCnt; 566 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem ) 567 { 568 // KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer 569 // von SfxItemPool abgeleiteten Klasse bereits geloescht worden 570 // sein! -> CHAOS Itempool 571 if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) ) 572 { 573 if ( *ppItemArr ) 574 { 575 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 576 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 577 if (*ppHtArr) 578 { 579 #ifdef DBG_UTIL 580 ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); 581 #endif 582 delete *ppHtArr; 583 } 584 DELETEZ( *ppItemArr ); 585 } 586 if ( *ppDefaultItem ) 587 { 588 #ifdef DBG_UTIL 589 SetRefCount( **ppDefaultItem, 0 ); 590 #endif 591 DELETEZ( *ppDefaultItem ); 592 } 593 } 594 } 595 } 596 597 ppItemArr = pImp->ppPoolItems; 598 ppDefaultItem = ppPoolDefaults; 599 600 //Jetzt die 'einfachen' Items 601 for ( nArrCnt = GetSize_Impl(); 602 nArrCnt; 603 --nArrCnt, ++ppItemArr, ++ppDefaultItem ) 604 { 605 if ( *ppItemArr ) 606 { 607 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 608 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 609 if (*ppHtArr) 610 { 611 #ifdef DBG_UTIL 612 ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); 613 #endif 614 delete *ppHtArr; 615 } 616 delete *ppItemArr; 617 } 618 if ( *ppDefaultItem ) 619 { 620 #ifdef DBG_UTIL 621 SetRefCount( **ppDefaultItem, 0 ); 622 #endif 623 delete *ppDefaultItem; 624 } 625 } 626 627 pImp->DeleteItems(); 628 delete[] ppPoolDefaults; ppPoolDefaults = 0; 629 } 630 631 // ---------------------------------------------------------------------- 632 633 void SfxItemPool::Cleanup() 634 { 635 DBG_CHKTHIS(SfxItemPool, 0); 636 637 //MA 16. Apr. 97: siehe ::Delete() 638 639 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; 640 SfxPoolItem** ppDefaultItem = ppPoolDefaults; 641 SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults; 642 sal_uInt16 nArrCnt; 643 644 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) 645 if ( ppStaticDefaults ) //HACK fuer Image, dort gibt es keine Statics!! 646 { 647 for ( nArrCnt = GetSize_Impl(); 648 nArrCnt; 649 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem ) 650 { 651 //Fuer jedes Item gibt es entweder ein Default oder ein static Default! 652 if ( *ppItemArr && 653 ((*ppDefaultItem && (*ppDefaultItem)->ISA(SfxSetItem)) || 654 (*ppStaticDefaultItem)->ISA(SfxSetItem)) ) 655 { 656 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 657 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 658 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) 659 { 660 DELETEZ(*ppHtArr); 661 } 662 } 663 } 664 } 665 666 ppItemArr = pImp->ppPoolItems; 667 668 for ( nArrCnt = GetSize_Impl(); 669 nArrCnt; 670 --nArrCnt, ++ppItemArr ) 671 { 672 if ( *ppItemArr ) 673 { 674 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 675 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 676 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) 677 DELETEZ( *ppHtArr ); 678 } 679 } 680 } 681 682 // ---------------------------------------------------------------------- 683 684 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem) 685 { 686 DBG_CHKTHIS(SfxItemPool, 0); 687 if ( IsInRange(rItem.Which()) ) 688 { 689 SfxPoolItem **ppOldDefault = 690 ppPoolDefaults + GetIndex_Impl(rItem.Which()); 691 SfxPoolItem *pNewDefault = rItem.Clone(this); 692 pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT); 693 if ( *ppOldDefault ) 694 { 695 (*ppOldDefault)->SetRefCount(0); 696 DELETEZ( *ppOldDefault ); 697 } 698 *ppOldDefault = pNewDefault; 699 } 700 else if ( pSecondary ) 701 pSecondary->SetPoolDefaultItem(rItem); 702 else 703 { 704 SFX_ASSERT( 0, rItem.Which(), "unknown Which-Id - cannot set pool default" ); 705 } 706 } 707 708 /* 709 * Resets the default of the given <Which-Id> back to the static default. 710 * If a pool default exists it is removed. 711 */ 712 void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId ) 713 { 714 DBG_CHKTHIS(SfxItemPool, 0); 715 if ( IsInRange(nWhichId) ) 716 { 717 SfxPoolItem **ppOldDefault = 718 ppPoolDefaults + GetIndex_Impl( nWhichId ); 719 if ( *ppOldDefault ) 720 { 721 (*ppOldDefault)->SetRefCount(0); 722 DELETEZ( *ppOldDefault ); 723 } 724 } 725 else if ( pSecondary ) 726 pSecondary->ResetPoolDefaultItem(nWhichId); 727 else 728 { 729 SFX_ASSERT( 0, nWhichId, "unknown Which-Id - cannot set pool default" ); 730 } 731 } 732 733 // ----------------------------------------------------------------------- 734 735 const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich ) 736 { 737 DBG_ASSERT( !rItem.ISA(SfxSetItem) || 738 0 != &((const SfxSetItem&)rItem).GetItemSet(), 739 "SetItem without ItemSet" ); 740 741 DBG_CHKTHIS(SfxItemPool, 0); 742 if ( 0 == nWhich ) 743 nWhich = rItem.Which(); 744 745 // richtigen Secondary-Pool finden 746 sal_Bool bSID = nWhich > SFX_WHICH_MAX; 747 if ( !bSID && !IsInRange(nWhich) ) 748 { 749 if ( pSecondary ) 750 return pSecondary->Put( rItem, nWhich ); 751 DBG_ERROR( "unknown Which-Id - cannot put item" ); 752 } 753 754 // SID oder nicht poolable (neue Definition)? 755 sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich); 756 if ( USHRT_MAX == nIndex || 757 IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) ) 758 { 759 SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich || 760 !IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE, 761 nWhich, "ein nicht Pool-Item ist Default?!" ); 762 SfxPoolItem *pPoolItem = rItem.Clone(pMaster); 763 pPoolItem->SetWhich(nWhich); 764 AddRef( *pPoolItem ); 765 return *pPoolItem; 766 } 767 768 SFX_ASSERT( rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich, 769 "SFxItemPool: wrong item type in Put" ); 770 771 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems + nIndex; 772 if( !*ppItemArr ) 773 *ppItemArr = new SfxPoolItemArray_Impl; 774 775 SfxPoolItemArrayBase_Impl::iterator ppFree; 776 sal_Bool ppFreeIsSet = sal_False; 777 SfxPoolItemArrayBase_Impl::iterator ppHtArray = (*ppItemArr)->begin(); 778 if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) ) 779 { 780 // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein 781 if ( IsPooledItem(&rItem) ) 782 { 783 // 1. Schleife: teste ob der Pointer vorhanden ist. 784 for( size_t n = (*ppItemArr)->size(); n; ++ppHtArray, --n ) 785 if( &rItem == (*ppHtArray) ) 786 { 787 AddRef( **ppHtArray ); 788 return **ppHtArray; 789 } 790 } 791 792 // 2. Schleife: dann muessen eben die Attribute verglichen werden 793 size_t n; 794 for ( n = (*ppItemArr)->size(), ppHtArray = (*ppItemArr)->begin(); 795 n; ++ppHtArray, --n ) 796 { 797 if ( *ppHtArray ) 798 { 799 if( **ppHtArray == rItem ) 800 { 801 AddRef( **ppHtArray ); 802 return **ppHtArray; 803 } 804 } 805 else 806 if ( ppFreeIsSet == sal_False ) 807 { 808 ppFree = ppHtArray; 809 ppFreeIsSet = sal_True; 810 } 811 } 812 } 813 else 814 { 815 // freien Platz suchen 816 SfxPoolItemArrayBase_Impl::iterator ppHtArr; 817 size_t n, nCount = (*ppItemArr)->size(); 818 for ( n = (*ppItemArr)->nFirstFree, 819 ppHtArr = (*ppItemArr)->begin() + n; 820 n < nCount; 821 ++ppHtArr, ++n ) 822 if ( !*ppHtArr ) 823 { 824 ppFree = ppHtArr; 825 ppFreeIsSet = sal_True; 826 break; 827 } 828 829 // naechstmoeglichen freien Platz merken 830 (*ppItemArr)->nFirstFree = n; 831 } 832 833 // nicht vorhanden, also im PtrArray eintragen 834 SfxPoolItem* pNewItem = rItem.Clone(pMaster); 835 pNewItem->SetWhich(nWhich); 836 #ifdef DBG_UTIL 837 SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" ) 838 #ifdef TF_POOLABLE 839 if ( !rItem.ISA(SfxSetItem) ) 840 { 841 SFX_ASSERT( !IsItemFlag(nWhich, SFX_ITEM_POOLABLE) || 842 rItem == *pNewItem, 843 nWhich, "unequal items in Put(): no operator==?" ); 844 SFX_ASSERT( !IsItemFlag(*pNewItem, SFX_ITEM_POOLABLE) || 845 *pNewItem == rItem, 846 nWhich, "unequal items in Put(): no operator==?" ); 847 } 848 #endif 849 #endif 850 AddRef( *pNewItem, pImp->nInitRefCount ); 851 SfxPoolItem* pTemp = pNewItem; 852 if ( ppFreeIsSet == sal_False ) 853 (*ppItemArr)->push_back( pTemp ); 854 else 855 { 856 DBG_ASSERT( *ppFree == 0, "using surrogate in use" ); 857 *ppFree = pNewItem; 858 } 859 return *pNewItem; 860 } 861 862 // ----------------------------------------------------------------------- 863 864 void SfxItemPool::Remove( const SfxPoolItem& rItem ) 865 { 866 DBG_CHKTHIS(SfxItemPool, 0); 867 868 DBG_ASSERT( !rItem.ISA(SfxSetItem) || 869 0 != &((const SfxSetItem&)rItem).GetItemSet(), 870 "SetItem without ItemSet" ); 871 872 SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(), 873 "wo kommt denn hier ein Pool-Default her" ); 874 875 // richtigen Secondary-Pool finden 876 const sal_uInt16 nWhich = rItem.Which(); 877 sal_Bool bSID = nWhich > SFX_WHICH_MAX; 878 if ( !bSID && !IsInRange(nWhich) ) 879 { 880 if ( pSecondary ) 881 { 882 pSecondary->Remove( rItem ); 883 return; 884 } 885 DBG_ERROR( "unknown Which-Id - cannot remove item" ); 886 } 887 888 // SID oder nicht poolable (neue Definition)? 889 sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich); 890 if ( bSID || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) ) 891 { 892 SFX_ASSERT( USHRT_MAX != nIndex || 893 !IsDefaultItem(&rItem), rItem.Which(), 894 "ein nicht Pool-Item ist Default?!" ); 895 if ( 0 == ReleaseRef(rItem) ) 896 { 897 SfxPoolItem *pItem = &(SfxPoolItem &)rItem; 898 delete pItem; 899 } 900 return; 901 } 902 903 SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove unmoeglich" ); 904 905 // statische Defaults sind eben einfach da 906 if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT && 907 &rItem == *( ppStaticDefaults + GetIndex_Impl(nWhich) ) ) 908 return; 909 910 // Item im eigenen Pool suchen 911 SfxPoolItemArray_Impl** ppItemArr = (pImp->ppPoolItems + nIndex); 912 SFX_ASSERT( *ppItemArr, rItem.Which(), "removing Item not in Pool" ); 913 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 914 for( size_t n = (*ppItemArr)->size(); n; ++ppHtArr, --n ) 915 if( *ppHtArr == &rItem ) 916 { 917 if ( (*ppHtArr)->GetRefCount() ) //! 918 ReleaseRef( **ppHtArr ); 919 else 920 { 921 SFX_ASSERT( 0, rItem.Which(), "removing Item without ref" ); 922 SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr ); 923 } 924 925 // ggf. kleinstmoegliche freie Position merken 926 size_t nPos = (*ppItemArr)->size() - n; 927 if ( (*ppItemArr)->nFirstFree > nPos ) 928 (*ppItemArr)->nFirstFree = nPos; 929 930 //! MI: Hack, solange wir das Problem mit dem Outliner haben 931 //! siehe anderes MI-REF 932 if ( 0 == (*ppHtArr)->GetRefCount() && nWhich < 4000 ) 933 DELETEZ(*ppHtArr); 934 return; 935 } 936 937 // nicht vorhanden 938 SFX_ASSERT( 0, rItem.Which(), "removing Item not in Pool" ); 939 SFX_TRACE( "to be removed, but not in pool: ", &rItem ); 940 } 941 942 // ----------------------------------------------------------------------- 943 944 const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const 945 { 946 DBG_CHKTHIS(SfxItemPool, 0); 947 948 if ( !IsInRange(nWhich) ) 949 { 950 if ( pSecondary ) 951 return pSecondary->GetDefaultItem( nWhich ); 952 SFX_ASSERT( 0, nWhich, "unknown which - dont ask me for defaults" ); 953 } 954 955 DBG_ASSERT( ppStaticDefaults, "no defaults known - dont ask me for defaults" ); 956 sal_uInt16 nPos = GetIndex_Impl(nWhich); 957 SfxPoolItem *pDefault = *(ppPoolDefaults + nPos); 958 if ( pDefault ) 959 return *pDefault; 960 return **(ppStaticDefaults + nPos); 961 } 962 963 // ----------------------------------------------------------------------- 964 965 966 void SfxItemPool::FreezeIdRanges() 967 968 /* [Beschreibung] 969 970 This method should be called at the master pool, when all secondary 971 pools are appended to it. 972 973 It calculates the ranges of 'which-ids' for fast construction of 974 item-sets, which contains all 'which-ids'. 975 */ 976 977 { 978 FillItemIdRanges_Impl( _pPoolRanges ); 979 } 980 981 982 // ----------------------------------------------------------------------- 983 984 void SfxItemPool::FillItemIdRanges_Impl( sal_uInt16*& pWhichRanges ) const 985 { 986 DBG_CHKTHIS(SfxItemPool, 0); 987 DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" ); 988 989 const SfxItemPool *pPool; 990 sal_uInt16 nLevel = 0; 991 for( pPool = this; pPool; pPool = pPool->pSecondary ) 992 ++nLevel; 993 994 pWhichRanges = new sal_uInt16[ 2*nLevel + 1 ]; 995 996 nLevel = 0; 997 for( pPool = this; pPool; pPool = pPool->pSecondary ) 998 { 999 *(pWhichRanges+(nLevel++)) = pPool->nStart; 1000 *(pWhichRanges+(nLevel++)) = pPool->nEnd; 1001 *(pWhichRanges+nLevel) = 0; 1002 } 1003 } 1004 1005 // ----------------------------------------------------------------------- 1006 1007 const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) const 1008 { 1009 DBG_CHKTHIS(SfxItemPool, 0); 1010 1011 if ( !IsInRange(nWhich) ) 1012 { 1013 if ( pSecondary ) 1014 return pSecondary->GetItem2( nWhich, nOfst ); 1015 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); 1016 return 0; 1017 } 1018 1019 // dflt-Attribut? 1020 if ( nOfst == SFX_ITEMS_DEFAULT ) 1021 return *(ppStaticDefaults + GetIndex_Impl(nWhich)); 1022 1023 SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); 1024 if( pItemArr && nOfst < pItemArr->size() ) 1025 return (*pItemArr)[nOfst]; 1026 1027 return 0; 1028 } 1029 1030 // ----------------------------------------------------------------------- 1031 1032 sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const 1033 { 1034 DBG_CHKTHIS(SfxItemPool, 0); 1035 1036 if ( !IsInRange(nWhich) ) 1037 { 1038 if ( pSecondary ) 1039 return pSecondary->GetItemCount2( nWhich ); 1040 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); 1041 return 0; 1042 } 1043 1044 SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); 1045 if ( pItemArr ) 1046 return pItemArr->size(); 1047 return 0; 1048 } 1049 1050 // ----------------------------------------------------------------------- 1051 1052 sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const 1053 { 1054 if ( !IsSlot(nSlotId) ) 1055 return nSlotId; 1056 1057 #ifdef TF_POOLABLE 1058 sal_uInt16 nCount = nEnd - nStart + 1; 1059 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1060 if ( pItemInfos[nOfs]._nSID == nSlotId ) 1061 return nOfs + nStart; 1062 #else 1063 if ( pSlotIds ) 1064 { 1065 sal_uInt16 nCount = nEnd - nStart + 1; 1066 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1067 if ( pSlotIds[nOfs] == nSlotId ) 1068 return nOfs + nStart; 1069 } 1070 #endif 1071 if ( pSecondary && bDeep ) 1072 return pSecondary->GetWhich(nSlotId); 1073 return nSlotId; 1074 } 1075 1076 // ----------------------------------------------------------------------- 1077 1078 sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const 1079 { 1080 if ( !IsWhich(nWhich) ) 1081 return nWhich; 1082 1083 if ( !IsInRange( nWhich ) ) 1084 { 1085 if ( pSecondary && bDeep ) 1086 return pSecondary->GetSlotId(nWhich); 1087 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" ); 1088 return 0; 1089 } 1090 #ifdef TF_POOLABLE 1091 1092 sal_uInt16 nSID = pItemInfos[nWhich - nStart]._nSID; 1093 return nSID ? nSID : nWhich; 1094 #else 1095 else if ( pSlotIds ) 1096 return pSlotIds[nWhich - nStart]; 1097 return nWhich; 1098 #endif 1099 } 1100 1101 // ----------------------------------------------------------------------- 1102 1103 sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const 1104 { 1105 if ( !IsSlot(nSlotId) ) 1106 return 0; 1107 1108 #ifdef TF_POOLABLE 1109 sal_uInt16 nCount = nEnd - nStart + 1; 1110 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1111 if ( pItemInfos[nOfs]._nSID == nSlotId ) 1112 return nOfs + nStart; 1113 #else 1114 if ( pSlotIds ) 1115 { 1116 sal_uInt16 nCount = nEnd - nStart + 1; 1117 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1118 if ( pSlotIds[nOfs] == nSlotId ) 1119 return nOfs + nStart; 1120 } 1121 #endif 1122 if ( pSecondary && bDeep ) 1123 return pSecondary->GetTrueWhich(nSlotId); 1124 return 0; 1125 } 1126 1127 // ----------------------------------------------------------------------- 1128 1129 sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const 1130 { 1131 if ( !IsWhich(nWhich) ) 1132 return 0; 1133 1134 if ( !IsInRange( nWhich ) ) 1135 { 1136 if ( pSecondary && bDeep ) 1137 return pSecondary->GetTrueSlotId(nWhich); 1138 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" ); 1139 return 0; 1140 } 1141 #ifdef TF_POOLABLE 1142 return pItemInfos[nWhich - nStart]._nSID; 1143 #else 1144 else if ( pSlotIds ) 1145 return pSlotIds[nWhich - nStart]; 1146 else 1147 return 0; 1148 #endif 1149 } 1150 // ----------------------------------------------------------------------- 1151 void SfxItemPool::SetFileFormatVersion( sal_uInt16 nFileFormatVersion ) 1152 1153 /* [Description] 1154 1155 You must call this function to set the file format version after 1156 concatenating your secondary-pools but before you store any 1157 pool, itemset or item. Only set the version at the master pool, 1158 never at any secondary pool. 1159 */ 1160 1161 { 1162 DBG_ASSERT( this == pMaster, 1163 "SfxItemPool::SetFileFormatVersion() but not a master pool" ); 1164 for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary ) 1165 pPool->_nFileFormatVersion = nFileFormatVersion; 1166 } 1167 1168 1169