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