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 385 if ( pImp->ppPoolItems && ppPoolDefaults ) 386 Delete(); 387 delete[] _pPoolRanges; 388 delete pImp; 389 390 if (pMaster != NULL && pMaster != this) 391 { 392 // This condition indicates an error. A 393 // pMaster->SetSecondaryPool(...) call should have been made 394 // earlier to prevent this. At this point we can only try to 395 // prevent a crash later on. 396 DBG_ASSERT( pMaster == this, "destroying active Secondary-Pool" ); 397 if (pMaster->pSecondary == this) 398 pMaster->pSecondary = NULL; 399 } 400 } 401 402 void SfxItemPool::Free(SfxItemPool* pPool) 403 { 404 if(pPool) 405 { 406 // tell all the registered SfxItemPoolUsers that the pool is in destruction 407 SfxItemPoolUserVector aListCopy(pPool->maSfxItemPoolUsers.begin(), pPool->maSfxItemPoolUsers.end()); 408 for(SfxItemPoolUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++) 409 { 410 SfxItemPoolUser* pSfxItemPoolUser = *aIterator; 411 DBG_ASSERT(pSfxItemPoolUser, "corrupt SfxItemPoolUser list (!)"); 412 pSfxItemPoolUser->ObjectInDestruction(*pPool); 413 } 414 415 // Clear the vector. This means that user do not need to call RemoveSfxItemPoolUser() 416 // when they get called from ObjectInDestruction(). 417 pPool->maSfxItemPoolUsers.clear(); 418 419 // delete pool 420 delete pPool; 421 } 422 } 423 424 // ----------------------------------------------------------------------- 425 426 427 void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool ) 428 { 429 // ggf. an abgeh"angten Pools den Master zur"ucksetzen 430 if ( pSecondary ) 431 { 432 #ifdef DBG_UTIL 433 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) 434 if ( ppStaticDefaults ) 435 { 436 // Delete() ist noch nicht gelaufen? 437 if ( pImp->ppPoolItems && pSecondary->pImp->ppPoolItems ) 438 { 439 // hat der master SetItems? 440 sal_Bool bHasSetItems = sal_False; 441 for ( sal_uInt16 i = 0; !bHasSetItems && i < nEnd-nStart; ++i ) 442 bHasSetItems = ppStaticDefaults[i]->ISA(SfxSetItem); 443 444 // abgehaengte Pools muessen leer sein 445 sal_Bool bOK = bHasSetItems; 446 for ( sal_uInt16 n = 0; 447 bOK && n <= pSecondary->nEnd - pSecondary->nStart; 448 ++n ) 449 { 450 SfxPoolItemArray_Impl** ppItemArr = 451 pSecondary->pImp->ppPoolItems + n; 452 if ( *ppItemArr ) 453 { 454 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 455 for( size_t i = (*ppItemArr)->size(); i; ++ppHtArr, --i ) 456 if ( !(*ppHtArr) ) 457 { 458 DBG_ERROR( "old secondary pool must be empty" ); 459 bOK = sal_False; 460 break; 461 } 462 } 463 } 464 } 465 } 466 #endif 467 468 pSecondary->pMaster = pSecondary; 469 for ( SfxItemPool *p = pSecondary->pSecondary; p; p = p->pSecondary ) 470 p->pMaster = pSecondary; 471 } 472 473 // ggf. den Master der neuen Secondary-Pools setzen 474 DBG_ASSERT( !pPool || pPool->pMaster == pPool, "Secondary tanzt auf zwei Hochzeiten " ); 475 SfxItemPool *pNewMaster = pMaster ? pMaster : this; 476 for ( SfxItemPool *p = pPool; p; p = p->pSecondary ) 477 p->pMaster = pNewMaster; 478 479 // neuen Secondary-Pool merken 480 pSecondary = pPool; 481 } 482 483 // ----------------------------------------------------------------------- 484 485 SfxMapUnit SfxItemPool::GetMetric( sal_uInt16 ) const 486 { 487 DBG_CHKTHIS(SfxItemPool, 0); 488 489 return pImp->eDefMetric; 490 } 491 492 // ----------------------------------------------------------------------- 493 494 void SfxItemPool::SetDefaultMetric( SfxMapUnit eNewMetric ) 495 { 496 DBG_CHKTHIS(SfxItemPool, 0); 497 498 pImp->eDefMetric = eNewMetric; 499 } 500 501 // ----------------------------------------------------------------------- 502 503 SfxItemPresentation SfxItemPool::GetPresentation 504 ( 505 const SfxPoolItem& rItem, /* IN: <SfxPoolItem>, dessen textuelle 506 Wert-Darstellung geliefert werden 507 soll */ 508 SfxItemPresentation ePresent, /* IN: gew"unschte Art der Darstellung; 509 siehe <SfxItemPresentation> */ 510 SfxMapUnit eMetric, /* IN: gew"unschte Ma\seinheit der Darstellung */ 511 XubString& rText, /* OUT: textuelle Darstellung von 'rItem' */ 512 const IntlWrapper * pIntlWrapper 513 ) const 514 515 /* [Beschreibung] 516 517 "Uber diese virtuelle Methode k"onnen textuelle Darstellungen der 518 von der jeweilige SfxItemPool-Subklasse verwalteten SfxPoolItems 519 angefordert werden. 520 521 In Ableitungen sollte diese Methode "uberladen werden und auf 522 SfxPoolItems reagiert werden, die bei <SfxPoolItem::GetPresentation()const> 523 keine vollst"andige Information liefern k"onnen. 524 525 Die Basisklasse liefert die unver"anderte Presentation von 'rItem'. 526 */ 527 528 { 529 DBG_CHKTHIS(SfxItemPool, 0); 530 return rItem.GetPresentation( 531 ePresent, GetMetric(rItem.Which()), eMetric, rText, pIntlWrapper ); 532 } 533 534 535 // ----------------------------------------------------------------------- 536 537 SfxItemPool* SfxItemPool::Clone() const 538 { 539 DBG_CHKTHIS(SfxItemPool, 0); 540 541 SfxItemPool *pPool = new SfxItemPool( *this ); 542 return pPool; 543 } 544 545 // ---------------------------------------------------------------------- 546 547 void SfxItemPool::Delete() 548 { 549 DBG_CHKTHIS(SfxItemPool, 0); 550 551 // schon deleted? 552 if ( !pImp->ppPoolItems || !ppPoolDefaults ) 553 return; 554 555 // z.B. laufenden Requests bescheidsagen 556 pImp->aBC.Broadcast( SfxSimpleHint( SFX_HINT_DYING ) ); 557 558 //MA 16. Apr. 97: Zweimal durchlaufen, in der ersten Runde fuer die SetItems. 559 //Der Klarheit halber wird das jetzt in zwei besser lesbare Schleifen aufgeteilt. 560 561 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; 562 SfxPoolItem** ppDefaultItem = ppPoolDefaults; 563 SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults; 564 sal_uInt16 nArrCnt; 565 566 //Erst die SetItems abraeumen 567 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) 568 if ( ppStaticDefaults ) 569 { 570 for ( nArrCnt = GetSize_Impl(); 571 nArrCnt; 572 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem ) 573 { 574 // KSO (22.10.98): *ppStaticDefaultItem kann im dtor einer 575 // von SfxItemPool abgeleiteten Klasse bereits geloescht worden 576 // sein! -> CHAOS Itempool 577 if ( *ppStaticDefaultItem && (*ppStaticDefaultItem)->ISA(SfxSetItem) ) 578 { 579 if ( *ppItemArr ) 580 { 581 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 582 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 583 if (*ppHtArr) 584 { 585 #ifdef DBG_UTIL 586 ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); 587 #endif 588 delete *ppHtArr; 589 } 590 DELETEZ( *ppItemArr ); 591 } 592 if ( *ppDefaultItem ) 593 { 594 #ifdef DBG_UTIL 595 SetRefCount( **ppDefaultItem, 0 ); 596 #endif 597 DELETEZ( *ppDefaultItem ); 598 } 599 } 600 } 601 } 602 603 ppItemArr = pImp->ppPoolItems; 604 ppDefaultItem = ppPoolDefaults; 605 606 //Jetzt die 'einfachen' Items 607 for ( nArrCnt = GetSize_Impl(); 608 nArrCnt; 609 --nArrCnt, ++ppItemArr, ++ppDefaultItem ) 610 { 611 if ( *ppItemArr ) 612 { 613 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 614 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 615 if (*ppHtArr) 616 { 617 #ifdef DBG_UTIL 618 ReleaseRef( **ppHtArr, (*ppHtArr)->GetRefCount() ); 619 #endif 620 delete *ppHtArr; 621 } 622 delete *ppItemArr; 623 } 624 if ( *ppDefaultItem ) 625 { 626 #ifdef DBG_UTIL 627 SetRefCount( **ppDefaultItem, 0 ); 628 #endif 629 delete *ppDefaultItem; 630 } 631 } 632 633 pImp->DeleteItems(); 634 delete[] ppPoolDefaults; ppPoolDefaults = 0; 635 } 636 637 // ---------------------------------------------------------------------- 638 639 void SfxItemPool::Cleanup() 640 { 641 DBG_CHKTHIS(SfxItemPool, 0); 642 643 //MA 16. Apr. 97: siehe ::Delete() 644 645 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; 646 SfxPoolItem** ppDefaultItem = ppPoolDefaults; 647 SfxPoolItem** ppStaticDefaultItem = ppStaticDefaults; 648 sal_uInt16 nArrCnt; 649 650 HACK( "fuer Image, dort gibt es derzeit keine Statics - Bug" ) 651 if ( ppStaticDefaults ) //HACK fuer Image, dort gibt es keine Statics!! 652 { 653 for ( nArrCnt = GetSize_Impl(); 654 nArrCnt; 655 --nArrCnt, ++ppItemArr, ++ppDefaultItem, ++ppStaticDefaultItem ) 656 { 657 //Fuer jedes Item gibt es entweder ein Default oder ein static Default! 658 if ( *ppItemArr && 659 ((*ppDefaultItem && (*ppDefaultItem)->ISA(SfxSetItem)) || 660 (*ppStaticDefaultItem)->ISA(SfxSetItem)) ) 661 { 662 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 663 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 664 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) 665 { 666 DELETEZ(*ppHtArr); 667 } 668 } 669 } 670 } 671 672 ppItemArr = pImp->ppPoolItems; 673 674 for ( nArrCnt = GetSize_Impl(); 675 nArrCnt; 676 --nArrCnt, ++ppItemArr ) 677 { 678 if ( *ppItemArr ) 679 { 680 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 681 for ( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) 682 if ( *ppHtArr && !(*ppHtArr)->GetRefCount() ) 683 DELETEZ( *ppHtArr ); 684 } 685 } 686 } 687 688 // ---------------------------------------------------------------------- 689 690 void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem) 691 { 692 DBG_CHKTHIS(SfxItemPool, 0); 693 if ( IsInRange(rItem.Which()) ) 694 { 695 SfxPoolItem **ppOldDefault = 696 ppPoolDefaults + GetIndex_Impl(rItem.Which()); 697 SfxPoolItem *pNewDefault = rItem.Clone(this); 698 pNewDefault->SetKind(SFX_ITEMS_POOLDEFAULT); 699 if ( *ppOldDefault ) 700 { 701 (*ppOldDefault)->SetRefCount(0); 702 DELETEZ( *ppOldDefault ); 703 } 704 *ppOldDefault = pNewDefault; 705 } 706 else if ( pSecondary ) 707 pSecondary->SetPoolDefaultItem(rItem); 708 else 709 { 710 SFX_ASSERT( 0, rItem.Which(), "unknown Which-Id - cannot set pool default" ); 711 } 712 } 713 714 /* 715 * Resets the default of the given <Which-Id> back to the static default. 716 * If a pool default exists it is removed. 717 */ 718 void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId ) 719 { 720 DBG_CHKTHIS(SfxItemPool, 0); 721 if ( IsInRange(nWhichId) ) 722 { 723 SfxPoolItem **ppOldDefault = 724 ppPoolDefaults + GetIndex_Impl( nWhichId ); 725 if ( *ppOldDefault ) 726 { 727 (*ppOldDefault)->SetRefCount(0); 728 DELETEZ( *ppOldDefault ); 729 } 730 } 731 else if ( pSecondary ) 732 pSecondary->ResetPoolDefaultItem(nWhichId); 733 else 734 { 735 SFX_ASSERT( 0, nWhichId, "unknown Which-Id - cannot set pool default" ); 736 } 737 } 738 739 // ----------------------------------------------------------------------- 740 741 const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich ) 742 { 743 DBG_ASSERT( !rItem.ISA(SfxSetItem) || 744 0 != &((const SfxSetItem&)rItem).GetItemSet(), 745 "SetItem without ItemSet" ); 746 747 DBG_CHKTHIS(SfxItemPool, 0); 748 if ( 0 == nWhich ) 749 nWhich = rItem.Which(); 750 751 // richtigen Secondary-Pool finden 752 sal_Bool bSID = nWhich > SFX_WHICH_MAX; 753 if ( !bSID && !IsInRange(nWhich) ) 754 { 755 if ( pSecondary ) 756 return pSecondary->Put( rItem, nWhich ); 757 DBG_ERROR( "unknown Which-Id - cannot put item" ); 758 } 759 760 // SID oder nicht poolable (neue Definition)? 761 sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich); 762 if ( USHRT_MAX == nIndex || 763 IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) ) 764 { 765 SFX_ASSERT( USHRT_MAX != nIndex || rItem.Which() != nWhich || 766 !IsDefaultItem(&rItem) || rItem.GetKind() == SFX_ITEMS_DELETEONIDLE, 767 nWhich, "ein nicht Pool-Item ist Default?!" ); 768 SfxPoolItem *pPoolItem = rItem.Clone(pMaster); 769 pPoolItem->SetWhich(nWhich); 770 AddRef( *pPoolItem ); 771 return *pPoolItem; 772 } 773 774 SFX_ASSERT( rItem.IsA(GetDefaultItem(nWhich).Type()), nWhich, 775 "SFxItemPool: wrong item type in Put" ); 776 777 SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems + nIndex; 778 if( !*ppItemArr ) 779 *ppItemArr = new SfxPoolItemArray_Impl; 780 781 SfxPoolItemArrayBase_Impl::iterator ppFree; 782 sal_Bool ppFreeIsSet = sal_False; 783 SfxPoolItemArrayBase_Impl::iterator ppHtArray = (*ppItemArr)->begin(); 784 if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) ) 785 { 786 // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein 787 if ( IsPooledItem(&rItem) ) 788 { 789 // 1. Schleife: teste ob der Pointer vorhanden ist. 790 for( size_t n = (*ppItemArr)->size(); n; ++ppHtArray, --n ) 791 if( &rItem == (*ppHtArray) ) 792 { 793 AddRef( **ppHtArray ); 794 return **ppHtArray; 795 } 796 } 797 798 // 2. Schleife: dann muessen eben die Attribute verglichen werden 799 size_t n; 800 for ( n = (*ppItemArr)->size(), ppHtArray = (*ppItemArr)->begin(); 801 n; ++ppHtArray, --n ) 802 { 803 if ( *ppHtArray ) 804 { 805 if( **ppHtArray == rItem ) 806 { 807 AddRef( **ppHtArray ); 808 return **ppHtArray; 809 } 810 } 811 else 812 if ( ppFreeIsSet == sal_False ) 813 { 814 ppFree = ppHtArray; 815 ppFreeIsSet = sal_True; 816 } 817 } 818 } 819 else 820 { 821 // freien Platz suchen 822 SfxPoolItemArrayBase_Impl::iterator ppHtArr; 823 size_t n, nCount = (*ppItemArr)->size(); 824 for ( n = (*ppItemArr)->nFirstFree, 825 ppHtArr = (*ppItemArr)->begin() + n; 826 n < nCount; 827 ++ppHtArr, ++n ) 828 if ( !*ppHtArr ) 829 { 830 ppFree = ppHtArr; 831 ppFreeIsSet = sal_True; 832 break; 833 } 834 835 // naechstmoeglichen freien Platz merken 836 (*ppItemArr)->nFirstFree = n; 837 } 838 839 // nicht vorhanden, also im PtrArray eintragen 840 SfxPoolItem* pNewItem = rItem.Clone(pMaster); 841 pNewItem->SetWhich(nWhich); 842 #ifdef DBG_UTIL 843 SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" ) 844 #ifdef TF_POOLABLE 845 if ( !rItem.ISA(SfxSetItem) ) 846 { 847 SFX_ASSERT( !IsItemFlag(nWhich, SFX_ITEM_POOLABLE) || 848 rItem == *pNewItem, 849 nWhich, "unequal items in Put(): no operator==?" ); 850 SFX_ASSERT( !IsItemFlag(*pNewItem, SFX_ITEM_POOLABLE) || 851 *pNewItem == rItem, 852 nWhich, "unequal items in Put(): no operator==?" ); 853 } 854 #endif 855 #endif 856 AddRef( *pNewItem, pImp->nInitRefCount ); 857 SfxPoolItem* pTemp = pNewItem; 858 if ( ppFreeIsSet == sal_False ) 859 (*ppItemArr)->push_back( pTemp ); 860 else 861 { 862 DBG_ASSERT( *ppFree == 0, "using surrogate in use" ); 863 *ppFree = pNewItem; 864 } 865 return *pNewItem; 866 } 867 868 // ----------------------------------------------------------------------- 869 870 void SfxItemPool::Remove( const SfxPoolItem& rItem ) 871 { 872 DBG_CHKTHIS(SfxItemPool, 0); 873 874 DBG_ASSERT( !rItem.ISA(SfxSetItem) || 875 0 != &((const SfxSetItem&)rItem).GetItemSet(), 876 "SetItem without ItemSet" ); 877 878 SFX_ASSERT( !IsPoolDefaultItem(&rItem), rItem.Which(), 879 "wo kommt denn hier ein Pool-Default her" ); 880 881 // richtigen Secondary-Pool finden 882 const sal_uInt16 nWhich = rItem.Which(); 883 sal_Bool bSID = nWhich > SFX_WHICH_MAX; 884 if ( !bSID && !IsInRange(nWhich) ) 885 { 886 if ( pSecondary ) 887 { 888 pSecondary->Remove( rItem ); 889 return; 890 } 891 DBG_ERROR( "unknown Which-Id - cannot remove item" ); 892 } 893 894 // SID oder nicht poolable (neue Definition)? 895 sal_uInt16 nIndex = bSID ? USHRT_MAX : GetIndex_Impl(nWhich); 896 if ( bSID || IsItemFlag_Impl( nIndex, SFX_ITEM_NOT_POOLABLE ) ) 897 { 898 SFX_ASSERT( USHRT_MAX != nIndex || 899 !IsDefaultItem(&rItem), rItem.Which(), 900 "ein nicht Pool-Item ist Default?!" ); 901 if ( 0 == ReleaseRef(rItem) ) 902 { 903 SfxPoolItem *pItem = &(SfxPoolItem &)rItem; 904 delete pItem; 905 } 906 return; 907 } 908 909 SFX_ASSERT( rItem.GetRefCount(), rItem.Which(), "RefCount == 0, Remove unmoeglich" ); 910 911 // statische Defaults sind eben einfach da 912 if ( rItem.GetKind() == SFX_ITEMS_STATICDEFAULT && 913 &rItem == *( ppStaticDefaults + GetIndex_Impl(nWhich) ) ) 914 return; 915 916 // Item im eigenen Pool suchen 917 SfxPoolItemArray_Impl** ppItemArr = (pImp->ppPoolItems + nIndex); 918 SFX_ASSERT( *ppItemArr, rItem.Which(), "removing Item not in Pool" ); 919 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); 920 for( size_t n = (*ppItemArr)->size(); n; ++ppHtArr, --n ) 921 if( *ppHtArr == &rItem ) 922 { 923 if ( (*ppHtArr)->GetRefCount() ) //! 924 ReleaseRef( **ppHtArr ); 925 else 926 { 927 SFX_ASSERT( 0, rItem.Which(), "removing Item without ref" ); 928 SFX_TRACE( "to be removed, but not no refs: ", *ppHtArr ); 929 } 930 931 // ggf. kleinstmoegliche freie Position merken 932 size_t nPos = (*ppItemArr)->size() - n; 933 if ( (*ppItemArr)->nFirstFree > nPos ) 934 (*ppItemArr)->nFirstFree = nPos; 935 936 //! MI: Hack, solange wir das Problem mit dem Outliner haben 937 //! siehe anderes MI-REF 938 if ( 0 == (*ppHtArr)->GetRefCount() && nWhich < 4000 ) 939 DELETEZ(*ppHtArr); 940 return; 941 } 942 943 // nicht vorhanden 944 SFX_ASSERT( 0, rItem.Which(), "removing Item not in Pool" ); 945 SFX_TRACE( "to be removed, but not in pool: ", &rItem ); 946 } 947 948 // ----------------------------------------------------------------------- 949 950 const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const 951 { 952 DBG_CHKTHIS(SfxItemPool, 0); 953 954 if ( !IsInRange(nWhich) ) 955 { 956 if ( pSecondary ) 957 return pSecondary->GetDefaultItem( nWhich ); 958 SFX_ASSERT( 0, nWhich, "unknown which - dont ask me for defaults" ); 959 } 960 961 DBG_ASSERT( ppStaticDefaults, "no defaults known - dont ask me for defaults" ); 962 sal_uInt16 nPos = GetIndex_Impl(nWhich); 963 SfxPoolItem *pDefault = *(ppPoolDefaults + nPos); 964 if ( pDefault ) 965 return *pDefault; 966 return **(ppStaticDefaults + nPos); 967 } 968 969 // ----------------------------------------------------------------------- 970 971 972 void SfxItemPool::FreezeIdRanges() 973 974 /* [Beschreibung] 975 976 This method should be called at the master pool, when all secondary 977 pools are appended to it. 978 979 It calculates the ranges of 'which-ids' for fast construction of 980 item-sets, which contains all 'which-ids'. 981 */ 982 983 { 984 FillItemIdRanges_Impl( _pPoolRanges ); 985 } 986 987 988 // ----------------------------------------------------------------------- 989 990 void SfxItemPool::FillItemIdRanges_Impl( sal_uInt16*& pWhichRanges ) const 991 { 992 DBG_CHKTHIS(SfxItemPool, 0); 993 DBG_ASSERT( !_pPoolRanges, "GetFrozenRanges() would be faster!" ); 994 995 const SfxItemPool *pPool; 996 sal_uInt16 nLevel = 0; 997 for( pPool = this; pPool; pPool = pPool->pSecondary ) 998 ++nLevel; 999 1000 pWhichRanges = new sal_uInt16[ 2*nLevel + 1 ]; 1001 1002 nLevel = 0; 1003 for( pPool = this; pPool; pPool = pPool->pSecondary ) 1004 { 1005 *(pWhichRanges+(nLevel++)) = pPool->nStart; 1006 *(pWhichRanges+(nLevel++)) = pPool->nEnd; 1007 *(pWhichRanges+nLevel) = 0; 1008 } 1009 } 1010 1011 // ----------------------------------------------------------------------- 1012 1013 const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) const 1014 { 1015 DBG_CHKTHIS(SfxItemPool, 0); 1016 1017 if ( !IsInRange(nWhich) ) 1018 { 1019 if ( pSecondary ) 1020 return pSecondary->GetItem2( nWhich, nOfst ); 1021 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); 1022 return 0; 1023 } 1024 1025 // dflt-Attribut? 1026 if ( nOfst == SFX_ITEMS_DEFAULT ) 1027 return *(ppStaticDefaults + GetIndex_Impl(nWhich)); 1028 1029 SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); 1030 if( pItemArr && nOfst < pItemArr->size() ) 1031 return (*pItemArr)[nOfst]; 1032 1033 return 0; 1034 } 1035 1036 // ----------------------------------------------------------------------- 1037 1038 sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const 1039 { 1040 DBG_CHKTHIS(SfxItemPool, 0); 1041 1042 if ( !IsInRange(nWhich) ) 1043 { 1044 if ( pSecondary ) 1045 return pSecondary->GetItemCount2( nWhich ); 1046 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot resolve surrogate" ); 1047 return 0; 1048 } 1049 1050 SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(nWhich)); 1051 if ( pItemArr ) 1052 return pItemArr->size(); 1053 return 0; 1054 } 1055 1056 // ----------------------------------------------------------------------- 1057 1058 sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const 1059 { 1060 if ( !IsSlot(nSlotId) ) 1061 return nSlotId; 1062 1063 #ifdef TF_POOLABLE 1064 sal_uInt16 nCount = nEnd - nStart + 1; 1065 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1066 if ( pItemInfos[nOfs]._nSID == nSlotId ) 1067 return nOfs + nStart; 1068 #else 1069 if ( pSlotIds ) 1070 { 1071 sal_uInt16 nCount = nEnd - nStart + 1; 1072 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1073 if ( pSlotIds[nOfs] == nSlotId ) 1074 return nOfs + nStart; 1075 } 1076 #endif 1077 if ( pSecondary && bDeep ) 1078 return pSecondary->GetWhich(nSlotId); 1079 return nSlotId; 1080 } 1081 1082 // ----------------------------------------------------------------------- 1083 1084 sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const 1085 { 1086 if ( !IsWhich(nWhich) ) 1087 return nWhich; 1088 1089 if ( !IsInRange( nWhich ) ) 1090 { 1091 if ( pSecondary && bDeep ) 1092 return pSecondary->GetSlotId(nWhich); 1093 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" ); 1094 return 0; 1095 } 1096 #ifdef TF_POOLABLE 1097 1098 sal_uInt16 nSID = pItemInfos[nWhich - nStart]._nSID; 1099 return nSID ? nSID : nWhich; 1100 #else 1101 else if ( pSlotIds ) 1102 return pSlotIds[nWhich - nStart]; 1103 return nWhich; 1104 #endif 1105 } 1106 1107 // ----------------------------------------------------------------------- 1108 1109 sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, sal_Bool bDeep ) const 1110 { 1111 if ( !IsSlot(nSlotId) ) 1112 return 0; 1113 1114 #ifdef TF_POOLABLE 1115 sal_uInt16 nCount = nEnd - nStart + 1; 1116 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1117 if ( pItemInfos[nOfs]._nSID == nSlotId ) 1118 return nOfs + nStart; 1119 #else 1120 if ( pSlotIds ) 1121 { 1122 sal_uInt16 nCount = nEnd - nStart + 1; 1123 for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) 1124 if ( pSlotIds[nOfs] == nSlotId ) 1125 return nOfs + nStart; 1126 } 1127 #endif 1128 if ( pSecondary && bDeep ) 1129 return pSecondary->GetTrueWhich(nSlotId); 1130 return 0; 1131 } 1132 1133 // ----------------------------------------------------------------------- 1134 1135 sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich, sal_Bool bDeep ) const 1136 { 1137 if ( !IsWhich(nWhich) ) 1138 return 0; 1139 1140 if ( !IsInRange( nWhich ) ) 1141 { 1142 if ( pSecondary && bDeep ) 1143 return pSecondary->GetTrueSlotId(nWhich); 1144 SFX_ASSERT( 0, nWhich, "unknown Which-Id - cannot get slot-id" ); 1145 return 0; 1146 } 1147 #ifdef TF_POOLABLE 1148 return pItemInfos[nWhich - nStart]._nSID; 1149 #else 1150 else if ( pSlotIds ) 1151 return pSlotIds[nWhich - nStart]; 1152 else 1153 return 0; 1154 #endif 1155 } 1156 // ----------------------------------------------------------------------- 1157 void SfxItemPool::SetFileFormatVersion( sal_uInt16 nFileFormatVersion ) 1158 1159 /* [Description] 1160 1161 You must call this function to set the file format version after 1162 concatenating your secondary-pools but before you store any 1163 pool, itemset or item. Only set the version at the master pool, 1164 never at any secondary pool. 1165 */ 1166 1167 { 1168 DBG_ASSERT( this == pMaster, 1169 "SfxItemPool::SetFileFormatVersion() but not a master pool" ); 1170 for ( SfxItemPool *pPool = this; pPool; pPool = pPool->pSecondary ) 1171 pPool->_nFileFormatVersion = nFileFormatVersion; 1172 } 1173 1174 1175