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