GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svl / source / items / poolio.cxx
blobe4e011355bc83cf4e2ec60e38a07dd2a2f2ba4fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <string.h>
22 #include <stdio.h>
24 #include <sal/log.hxx>
25 #include <tools/solar.h>
26 #include <svl/itempool.hxx>
27 #include "whassert.hxx"
28 #include <svl/brdcst.hxx>
29 #include <svl/filerec.hxx>
30 #include "poolio.hxx"
32 // STATIC DATA -----------------------------------------------------------
34 DBG_NAME(SfxItemPool);
37 const SfxItemPool* SfxItemPool::GetStoringPool()
39 /* [Beschreibung]
41 Diese Methode liefert den <SfxItemPool>, der gerade gespeichert wird.
42 Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format-
43 Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines
44 <SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen
45 Pool zu besorgen.
49 return pStoringPool_;
53 SvStream &SfxItemPool::Store(SvStream &rStream) const
55 /* [Beschreibung]
57 Der SfxItemPool wird inklusive aller seiner Sekund"arpools mit
58 Pool-Defaults und gepoolten Items in dem angegebenen Stream gespeichert.
59 Die statischen Defaults werden nicht gespeichert.
62 [Fileformat]
64 ;zun"achst ein Kompatiblit"ats-Header-Block
65 Start: 0x1111 SFX_ITEMPOOL_TAG_STARTPOOLS(_4/_5)
66 sal_uInt8 MAJOR_VER ;SfxItemPool-Version
67 sal_uInt8 MINOR_VER ;"
68 0xFFFF SFX_ITEMPOOL_TAG_TRICK4OLD ;ex. GetVersion()
69 sal_uInt16 0x0000 ;Pseudo-StyleSheetPool
70 sal_uInt16 0x0000 ;Pseudo-StyleSheetPool
72 ;den ganzen Pool in einen Record
73 record SfxMiniRecod(SFX_ITEMPOOL_REC)
75 ;je ein Header vorweg
76 Header: record SfxMiniRecord(SFX_ITEMPOOL_REC_HEADER)
77 sal_uInt16 GetVersion() ;Which-Ranges etc.
78 String GetName() ;Pool-Name
80 ;die Versions-Map, um WhichIds neuer File-Versionen mappen zu k"onnen
81 Versions: record SfxMultiRecord(SFX_ITEMPOOL_REC_VERSIONS, 0)
82 sal_uInt16 OldVersion
83 sal_uInt16 OldStartWhich
84 sal_uInt16 OldEndWhich
85 sal_uInt16[] NewWhich (OldEndWhich-OldStartWhich+1)
87 ;jetzt die gepoolten Items (zuerst nicht-SfxSetItems)
88 Items: record SfxMultiRecord(SFX_ITEMPOOL_REC_WHICHIDS, 0)
89 content SlotId, 0
90 sal_uInt16 WhichId
91 sal_uInt16 pItem->GetVersion()
92 sal_uInt16 Array-Size
93 record SfxMultiRecord(SFX_, 0)
94 content Surrogate
95 sal_uInt16 RefCount
96 unknown pItem->Store()
98 ;jetzt die gesetzten Pool-Defaults
99 Defaults: record SfxMultiRecord(SFX_ITEMPOOL_REC_DEFAULTS, 0)
100 content SlotId, 0
101 sal_uInt16 WhichId
102 sal_uInt16 pPoolDef->GetVersion()
103 unknown pPoolDef->Store();
105 ;dahinter folgt ggf. der Secondary ohne Kompatiblit"ats-Header-Block
109 DBG_CHKTHIS(SfxItemPool, 0);
111 // Store-Master finden
112 SfxItemPool *pStoreMaster = pImp->mpMaster != this ? pImp->mpMaster : 0;
113 while ( pStoreMaster && !pStoreMaster->pImp->bStreaming )
114 pStoreMaster = pStoreMaster->pImp->mpSecondary;
116 // Alter-Header (Version des Pools an sich und Inhalts-Version 0xffff)
117 pImp->bStreaming = sal_True;
118 if ( !pStoreMaster )
120 rStream << ( rStream.GetVersion() >= SOFFICE_FILEFORMAT_50
121 ? SFX_ITEMPOOL_TAG_STARTPOOL_5
122 : SFX_ITEMPOOL_TAG_STARTPOOL_4 );
123 rStream << SFX_ITEMPOOL_VER_MAJOR << SFX_ITEMPOOL_VER_MINOR;
124 rStream << SFX_ITEMPOOL_TAG_TRICK4OLD;
126 // SfxStyleSheet-Bug umgehen
127 rStream << sal_uInt16(0); // Version
128 rStream << sal_uInt16(0); // Count (2. Schleife f"allt sonst auf die Fresse)
131 // jeder Pool ist als ganzes ein Record
132 SfxMiniRecordWriter aPoolRec( &rStream, SFX_ITEMPOOL_REC );
133 pStoringPool_ = this;
135 // Einzel-Header (Version des Inhalts und Name)
137 SfxMiniRecordWriter aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER);
138 rStream << pImp->nVersion;
139 SfxPoolItem::writeByteString(rStream, pImp->aName);
142 // Version-Maps
144 SfxMultiVarRecordWriter aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP, 0 );
145 for ( size_t nVerNo = 0; nVerNo < pImp->aVersions.size(); ++nVerNo )
147 aVerRec.NewContent();
148 SfxPoolVersion_ImplPtr pVer = pImp->aVersions[nVerNo];
149 rStream << pVer->_nVer << pVer->_nStart << pVer->_nEnd;
150 sal_uInt16 nCount = pVer->_nEnd - pVer->_nStart + 1;
151 sal_uInt16 nNewWhich = 0;
152 for ( sal_uInt16 n = 0; n < nCount; ++n )
154 nNewWhich = pVer->_pMap[n];
155 rStream << nNewWhich;
158 // Workaround gegen Bug in SetVersionMap der 312
159 if ( SOFFICE_FILEFORMAT_31 == pImp->mnFileFormatVersion )
160 rStream << sal_uInt16(nNewWhich+1);
164 // gepoolte Items
166 SfxMultiMixRecordWriter aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS, 0 );
168 // erst Atomaren-Items und dann die Sets schreiben (wichtig beim Laden)
169 for (int ft = 0 ; ft < 2 && !rStream.GetError(); ft++)
171 pImp->bInSetItem = ft != 0;
173 std::vector<SfxPoolItemArray_Impl*>::iterator itrArr = pImp->maPoolItems.begin();
174 SfxPoolItem **ppDefItem = pImp->ppStaticDefaults;
175 const sal_uInt16 nSize = GetSize_Impl();
176 for ( size_t i = 0; i < nSize && !rStream.GetError(); ++i, ++itrArr, ++ppDefItem )
178 // Version des Items feststellen
179 sal_uInt16 nItemVersion = (*ppDefItem)->GetVersion( pImp->mnFileFormatVersion );
180 if ( USHRT_MAX == nItemVersion )
181 // => kam in zu exportierender Version gar nicht vor
182 continue;
184 // !poolable wird gar nicht im Pool gespeichert
185 // und itemsets/plain-items je nach Runde
186 if ( *itrArr && IsItemFlag(**ppDefItem, SFX_ITEM_POOLABLE) &&
187 pImp->bInSetItem == (bool) (*ppDefItem)->ISA(SfxSetItem) )
189 // eigene Kennung, globale Which-Id und Item-Version
190 sal_uInt16 nSlotId = GetSlotId( (*ppDefItem)->Which(), sal_False );
191 aWhichIdsRec.NewContent(nSlotId, 0);
192 rStream << (*ppDefItem)->Which();
193 rStream << nItemVersion;
194 const sal_uInt32 nCount = ::std::min<size_t>( (*itrArr)->size(), SAL_MAX_UINT32 );
195 DBG_ASSERT(nCount, "ItemArr is empty");
196 rStream << nCount;
198 // Items an sich schreiben
199 SfxMultiMixRecordWriter aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS, 0 );
200 for ( size_t j = 0; j < nCount; ++j )
202 // Item selbst besorgen
203 const SfxPoolItem *pItem = (*itrArr)->operator[](j);
204 if ( pItem && pItem->GetRefCount() ) //! siehe anderes MI-REF
206 aItemsRec.NewContent((sal_uInt16)j, 'X' );
208 if ( pItem->GetRefCount() == SFX_ITEMS_SPECIAL )
209 rStream << (sal_uInt16) pItem->GetKind();
210 else
212 rStream << (sal_uInt16) pItem->GetRefCount();
213 if( pItem->GetRefCount() > SFX_ITEMS_OLD_MAXREF )
214 rStream.SetError( ERRCODE_IO_NOTSTORABLEINBINARYFORMAT );
217 if ( !rStream.GetError() )
218 pItem->Store(rStream, nItemVersion);
219 else
220 break;
221 #ifdef DBG_UTIL_MI
222 if ( !pItem->ISA(SfxSetItem) )
224 sal_uLong nMark = rStream.Tell();
225 rStream.Seek( nItemStartPos + sizeof(sal_uInt16) );
226 SfxPoolItem *pClone = pItem->Create(rStream, nItemVersion );
227 sal_uInt16 nWh = pItem->Which();
228 SFX_ASSERT( rStream.Tell() == nMark, nWh,"asymmetric store/create" );
229 SFX_ASSERT( *pClone == *pItem, nWh, "unequal after store/create" );
230 delete pClone;
232 #endif
239 pImp->bInSetItem = false;
242 // die gesetzten Defaults speichern (Pool-Defaults)
243 if ( !rStream.GetError() )
245 SfxMultiMixRecordWriter aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS, 0 );
246 sal_uInt16 nCount = GetSize_Impl();
247 for ( sal_uInt16 n = 0; n < nCount; ++n )
249 const SfxPoolItem* pDefaultItem = pImp->ppPoolDefaults[n];
250 if ( pDefaultItem )
252 // Version ermitteln
253 sal_uInt16 nItemVersion = pDefaultItem->GetVersion( pImp->mnFileFormatVersion );
254 if ( USHRT_MAX == nItemVersion )
255 // => gab es in der Version noch nicht
256 continue;
258 // eigene Kennung, globale Kennung, Version
259 sal_uInt16 nSlotId = GetSlotId( pDefaultItem->Which(), sal_False );
260 aDefsRec.NewContent( nSlotId, 0 );
261 rStream << pDefaultItem->Which();
262 rStream << nItemVersion;
264 // Item an sich
265 pDefaultItem->Store( rStream, nItemVersion );
270 // weitere Pools rausschreiben
271 pStoringPool_ = 0;
272 aPoolRec.Close();
273 if ( !rStream.GetError() && pImp->mpSecondary )
274 pImp->mpSecondary->Store( rStream );
276 pImp->bStreaming = sal_False;
277 return rStream;
280 bool SfxItemPool::HasPersistentRefCounts() const
282 return pImp->mbPersistentRefCounts;
285 void SfxItemPool::LoadCompleted()
287 /* [Beschreibung]
289 Wurde der SfxItemPool mit 'bRefCounts' == sal_False geladen, mu\s das
290 Laden der Dokumentinhalte mit einem Aufruf dieser Methode beendet
291 werden. Ansonsten hat der Aufruf dieser Methode keine Funktion.
294 [Anmerkung]
296 Beim Laden ohne Ref-Counts werden diese tats"achlich auf 1 gesetzt,
297 damit nicht w"ahrend des Ladevorgangs SfxPoolItems gel"oscht werden,
298 die danach, aber auch noch beim Ladevorgang, ben"otigt werden. Diese
299 Methode setzt den Ref-Count wieder zur"uck und entfernt dabei
300 gleichzeitig alle nicht mehr ben"otigten Items.
303 [Querverweise]
305 <SfxItemPool::Load()>
309 // wurden keine Ref-Counts mitgeladen?
310 if ( pImp->nInitRefCount > 1 )
313 // "uber alle Which-Werte iterieren
314 std::vector<SfxPoolItemArray_Impl*>::iterator itrItemArr = pImp->maPoolItems.begin();
315 for( sal_uInt16 nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++itrItemArr )
317 // ist "uberhaupt ein Item mit dem Which-Wert da?
318 if ( *itrItemArr )
320 // "uber alle Items mit dieser Which-Id iterieren
321 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*itrItemArr)->begin();
322 for( size_t n = (*itrItemArr)->size(); n; --n, ++ppHtArr )
323 if (*ppHtArr)
325 #ifdef DBG_UTIL
326 const SfxPoolItem &rItem = **ppHtArr;
327 DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
328 0 != &((const SfxSetItem&)rItem).GetItemSet(),
329 "SetItem without ItemSet" );
330 #endif
332 if ( !ReleaseRef( **ppHtArr, 1 ) )
333 DELETEZ( *ppHtArr );
338 // from now on normal initial ref count
339 pImp->nInitRefCount = 1;
342 // notify secondary pool
343 if ( pImp->mpSecondary )
344 pImp->mpSecondary->LoadCompleted();
347 sal_uInt16 SfxItemPool::GetFirstWhich() const
349 return pImp->mnStart;
352 sal_uInt16 SfxItemPool::GetLastWhich() const
354 return pImp->mnEnd;
357 bool SfxItemPool::IsInRange( sal_uInt16 nWhich ) const
359 return nWhich >= pImp->mnStart && nWhich <= pImp->mnEnd;
362 // This had to be moved to a method of its own to keep Solaris GCC happy:
363 void SfxItemPool_Impl::readTheItems (
364 SvStream & rStream, sal_uInt32 nItemCount, sal_uInt16 nVer,
365 SfxPoolItem * pDefItem, SfxPoolItemArray_Impl ** ppArr)
367 SfxMultiRecordReader aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS );
369 SfxPoolItemArray_Impl *pNewArr = new SfxPoolItemArray_Impl();
370 SfxPoolItem *pItem = 0;
372 sal_uLong n, nLastSurrogate = sal_uLong(-1);
373 while (aItemsRec.GetContent())
375 // n"achstes Surrogat holen
376 sal_uInt16 nSurrogate = aItemsRec.GetContentTag();
377 DBG_ASSERT( aItemsRec.GetContentVersion() == 'X',
378 "not an item content" );
380 // fehlende auff"ullen
381 for ( pItem = 0, n = nLastSurrogate+1; n < nSurrogate; ++n )
382 pNewArr->push_back( (SfxPoolItem*) pItem );
383 nLastSurrogate = nSurrogate;
385 // Ref-Count und Item laden
386 sal_uInt16 nRef(0);
387 rStream >> nRef;
389 pItem = pDefItem->Create(rStream, nVer);
390 pNewArr->push_back( (SfxPoolItem*) pItem );
392 if ( !mbPersistentRefCounts )
393 // bis <SfxItemPool::LoadCompleted()> festhalten
394 SfxItemPool::AddRef(*pItem, 1);
395 else
397 if ( nRef > SFX_ITEMS_OLD_MAXREF )
398 SfxItemPool::SetKind(*pItem, nRef);
399 else
400 SfxItemPool::AddRef(*pItem, nRef);
404 // fehlende auff"ullen
405 for ( pItem = 0, n = nLastSurrogate+1; n < nItemCount; ++n )
406 pNewArr->push_back( (SfxPoolItem*) pItem );
408 SfxPoolItemArray_Impl *pOldArr = *ppArr;
409 *ppArr = pNewArr;
411 // die Items merken, die schon im Pool sind
412 bool bEmpty = true;
413 if ( 0 != pOldArr )
414 for ( n = 0; bEmpty && n < pOldArr->size(); ++n )
415 bEmpty = pOldArr->operator[](n) == 0;
416 DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" );
417 if ( !bEmpty )
419 // f"ur alle alten suchen, ob ein gleiches neues existiert
420 for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld )
422 SfxPoolItem *pOldItem = (*pOldArr)[nOld];
423 if ( pOldItem )
425 sal_uInt32 nFree = SAL_MAX_UINT32;
426 bool bFound = false;
427 for ( size_t nNew = (*ppArr)->size(); nNew--; )
429 // geladenes Item
430 SfxPoolItem *&rpNewItem =
431 (SfxPoolItem*&)(*ppArr)->operator[](nNew);
433 // surrogat unbenutzt?
434 if ( !rpNewItem )
435 nFree = nNew;
437 // gefunden?
438 else if ( *rpNewItem == *pOldItem )
440 // wiederverwenden
441 SfxItemPool::AddRef( *pOldItem, rpNewItem->GetRefCount() );
442 SfxItemPool::SetRefCount( *rpNewItem, 0 );
443 delete rpNewItem;
444 rpNewItem = pOldItem;
445 bFound = true;
446 break;
450 // vorhervorhandene, nicht geladene uebernehmen
451 if ( !bFound )
453 if ( nFree != SAL_MAX_UINT32 )
454 (SfxPoolItem*&)(*ppArr)->operator[](nFree) = pOldItem;
455 else
456 (*ppArr)->push_back( (SfxPoolItem*) pOldItem );
461 delete pOldArr;
464 // -----------------------------------------------------------------------
466 SvStream &SfxItemPool::Load(SvStream &rStream)
468 DBG_CHKTHIS(SfxItemPool, 0);
469 DBG_ASSERT(pImp->ppStaticDefaults, "kein DefaultArray");
471 // protect items by increasing ref count
472 if ( !pImp->mbPersistentRefCounts )
475 // "uber alle Which-Werte iterieren
476 std::vector<SfxPoolItemArray_Impl*>::iterator itrItemArr = pImp->maPoolItems.begin();
477 for( size_t nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++itrItemArr )
479 // ist "uberhaupt ein Item mit dem Which-Wert da?
480 if ( *itrItemArr )
482 // "uber alle Items mit dieser Which-Id iterieren
483 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*itrItemArr)->begin();
484 for( size_t n = (*itrItemArr)->size(); n; --n, ++ppHtArr )
485 if (*ppHtArr)
487 #ifdef DBG_UTIL
488 const SfxPoolItem &rItem = **ppHtArr;
489 DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
490 0 != &((const SfxSetItem&)rItem).GetItemSet(),
491 "SetItem without ItemSet" );
492 DBG_WARNING( "loading non-empty ItemPool" );
493 #endif
495 AddRef( **ppHtArr, 1 );
500 // during loading (until LoadCompleted()) protect all items
501 pImp->nInitRefCount = 2;
504 // Load-Master finden
505 SfxItemPool *pLoadMaster = pImp->mpMaster != this ? pImp->mpMaster : 0;
506 while ( pLoadMaster && !pLoadMaster->pImp->bStreaming )
507 pLoadMaster = pLoadMaster->pImp->mpSecondary;
509 // Gesamt Header einlesen
510 pImp->bStreaming = sal_True;
511 if ( !pLoadMaster )
513 // Format-Version laden
514 CHECK_FILEFORMAT2( rStream,
515 SFX_ITEMPOOL_TAG_STARTPOOL_5, SFX_ITEMPOOL_TAG_STARTPOOL_4 );
516 rStream >> pImp->nMajorVer >> pImp->nMinorVer;
518 // Format-Version in Master-Pool "ubertragen
519 pImp->mpMaster->pImp->nMajorVer = pImp->nMajorVer;
520 pImp->mpMaster->pImp->nMinorVer = pImp->nMinorVer;
522 // altes Format?
523 if ( pImp->nMajorVer < 2 )
524 // pImp->bStreaming wird von Load1_Impl() zur"uckgesetzt
525 return Load1_Impl( rStream );
527 // zu neues Format?
528 if ( pImp->nMajorVer > SFX_ITEMPOOL_VER_MAJOR )
530 rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
531 pImp->bStreaming = sal_False;
532 return rStream;
535 // Version 1.2-Trick-Daten "uberspringen
536 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_TRICK4OLD );
537 rStream.SeekRel( 4 ); // Hack-Daten wegen SfxStyleSheetPool-Bug skippen
540 // neues Record-orientiertes Format
541 SfxMiniRecordReader aPoolRec( &rStream, SFX_ITEMPOOL_REC );
542 if ( rStream.GetError() )
544 pImp->bStreaming = sal_False;
545 return rStream;
548 // Einzel-Header
549 int bOwnPool = sal_True;
550 OUString aExternName;
552 // Header-Record suchen
553 SfxMiniRecordReader aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER );
554 if ( rStream.GetError() )
556 pImp->bStreaming = sal_False;
557 return rStream;
560 // Header-lesen
561 rStream >> pImp->nLoadingVersion;
562 aExternName = SfxPoolItem::readByteString(rStream);
563 bOwnPool = aExternName == pImp->aName;
565 //! solange wir keine fremden Pools laden k"onnen
566 if ( !bOwnPool )
568 rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
569 aPoolRec.Skip();
570 pImp->bStreaming = sal_False;
571 return rStream;
575 // Version-Maps
577 SfxMultiRecordReader aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP );
578 if ( rStream.GetError() )
580 pImp->bStreaming = sal_False;
581 return rStream;
584 // Versions-Maps einlesen
585 sal_uInt16 nOwnVersion = pImp->nVersion;
586 for ( sal_uInt16 nVerNo = 0; aVerRec.GetContent(); ++nVerNo )
588 // Header f"ur einzelne Version einlesen
589 sal_uInt16 nVersion(0), nHStart(0), nHEnd(0);
590 rStream >> nVersion >> nHStart >> nHEnd;
591 sal_uInt16 nCount = nHEnd - nHStart + 1;
593 // Is new version is known?
594 if ( nVerNo >= pImp->aVersions.size() )
596 // Add new Version
597 sal_uInt16 *pMap = new sal_uInt16[nCount];
598 memset(pMap, 0, nCount * sizeof(sal_uInt16));
599 for ( sal_uInt16 n = 0; n < nCount; ++n )
600 rStream >> pMap[n];
601 SetVersionMap( nVersion, nHStart, nHEnd, pMap );
604 pImp->nVersion = nOwnVersion;
607 // Items laden
608 bool bSecondaryLoaded = false;
609 long nSecondaryEnd = 0;
611 SfxMultiRecordReader aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS);
612 while ( aWhichIdsRec.GetContent() )
614 // SlotId, Which-Id und Item-Version besorgen
615 sal_uInt32 nCount(0);
616 sal_uInt16 nVersion(0), nWhich(0);
617 //!sal_uInt16 nSlotId = aWhichIdsRec.GetContentTag();
618 rStream >> nWhich;
619 if ( pImp->nLoadingVersion != pImp->nVersion )
620 // Which-Id aus File-Version in Pool-Version verschieben
621 nWhich = GetNewWhich( nWhich );
623 // unbekanntes Item aus neuerer Version
624 if ( !IsInRange(nWhich) )
625 continue;
627 rStream >> nVersion;
628 rStream >> nCount;
629 //!SFX_ASSERTWARNING( !nSlotId || !HasMap() ||
630 //! ( nSlotId == GetSlotId( nWhich, sal_False ) ) ||
631 //! !GetSlotId( nWhich, sal_False ),
632 //! nWhich, "Slot/Which mismatch" );
634 sal_uInt16 nIndex = GetIndex_Impl(nWhich);
635 SfxPoolItemArray_Impl **ppArr = &pImp->maPoolItems[0] + nIndex;
637 // SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
638 SfxPoolItem *pDefItem = *(pImp->ppStaticDefaults + nIndex);
639 pImp->bInSetItem = pDefItem->ISA(SfxSetItem);
640 if ( !bSecondaryLoaded && pImp->mpSecondary && pImp->bInSetItem )
642 // an das Ende des eigenen Pools seeken
643 sal_uLong nLastPos = rStream.Tell();
644 aPoolRec.Skip();
646 // Sekund"arpool einlesen
647 pImp->mpSecondary->Load( rStream );
648 bSecondaryLoaded = true;
649 nSecondaryEnd = rStream.Tell();
651 // zur"uck zu unseren eigenen Items
652 rStream.Seek(nLastPos);
655 // Items an sich lesen
656 pImp->readTheItems(rStream, nCount, nVersion, pDefItem, ppArr);
658 pImp->bInSetItem = false;
662 // Pool-Defaults lesen
664 SfxMultiRecordReader aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS );
666 while ( aDefsRec.GetContent() )
668 // SlotId, Which-Id und Item-Version besorgen
669 sal_uInt16 nVersion(0), nWhich(0);
670 //!sal_uInt16 nSlotId = aDefsRec.GetContentTag();
671 rStream >> nWhich;
672 if ( pImp->nLoadingVersion != pImp->nVersion )
673 // Which-Id aus File-Version in Pool-Version verschieben
674 nWhich = GetNewWhich( nWhich );
676 // unbekanntes Item aus neuerer Version
677 if ( !IsInRange(nWhich) )
678 continue;
680 rStream >> nVersion;
681 //!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, sal_False ) ),
682 //! nWhich, "Slot/Which mismatch" );
684 // Pool-Default-Item selbst laden
685 SfxPoolItem *pItem =
686 ( *( pImp->ppStaticDefaults + GetIndex_Impl(nWhich) ) )
687 ->Create( rStream, nVersion );
688 pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
689 *( pImp->ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
693 // ggf. Secondary-Pool laden
694 aPoolRec.Skip();
695 if ( pImp->mpSecondary )
697 if ( !bSecondaryLoaded )
698 pImp->mpSecondary->Load( rStream );
699 else
700 rStream.Seek( nSecondaryEnd );
703 // wenn nicht own-Pool, dann kein Name
704 if ( aExternName != pImp->aName )
705 pImp->aName = OUString();
707 pImp->bStreaming = sal_False;
708 return rStream;
711 sal_uInt16 SfxItemPool::GetIndex_Impl(sal_uInt16 nWhich) const
713 DBG_CHKTHIS(SfxItemPool, 0);
714 DBG_ASSERT(nWhich >= pImp->mnStart && nWhich <= pImp->mnEnd, "Which-Id nicht im Pool-Bereich");
715 return nWhich - pImp->mnStart;
718 sal_uInt16 SfxItemPool::GetSize_Impl() const
720 return pImp->mnEnd - pImp->mnStart + 1;
723 SvStream &SfxItemPool::Load1_Impl(SvStream &rStream)
725 // beim Master ist der Header schon von <Load()> geladen worden
726 if ( !pImp->bStreaming )
728 // Header des Secondary lesen
729 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_STARTPOOL_4 );
730 rStream >> pImp->nMajorVer >> pImp->nMinorVer;
732 sal_uInt32 nAttribSize(0);
733 int bOwnPool = sal_True;
734 OUString aExternName;
735 if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 2 )
736 rStream >> pImp->nLoadingVersion;
737 aExternName = SfxPoolItem::readByteString(rStream);
738 bOwnPool = aExternName == pImp->aName;
739 pImp->bStreaming = sal_True;
741 //! solange wir keine fremden laden k"onnen
742 if ( !bOwnPool )
744 rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
745 pImp->bStreaming = sal_False;
746 return rStream;
749 // Versionen bis 1.3 k"onnen noch keine Which-Verschiebungen lesen
750 if ( pImp->nMajorVer == 1 && pImp->nMinorVer <= 2 &&
751 pImp->nVersion < pImp->nLoadingVersion )
753 rStream.SetError(ERRCODE_IO_WRONGVERSION);
754 pImp->bStreaming = sal_False;
755 return rStream;
758 // Size-Table liegt hinter den eigentlichen Attributen
759 rStream >> nAttribSize;
761 // Size-Table einlesen
762 sal_uLong nStartPos = rStream.Tell();
763 rStream.SeekRel( nAttribSize );
764 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_SIZES );
765 sal_uInt32 nSizeTableLen(0);
766 rStream >> nSizeTableLen;
767 sal_Char *pBuf = new sal_Char[nSizeTableLen];
768 rStream.Read( pBuf, nSizeTableLen );
769 sal_uLong nEndOfSizes = rStream.Tell();
770 SvMemoryStream aSizeTable( pBuf, nSizeTableLen, STREAM_READ );
772 // ab Version 1.3 steht in der Size-Table eine Versions-Map
773 if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 3 )
775 // Version-Map finden (letztes sal_uLong der Size-Table gibt Pos an)
776 rStream.Seek( nEndOfSizes - sizeof(sal_uInt32) );
777 sal_uInt32 nVersionMapPos(0);
778 rStream >> nVersionMapPos;
779 rStream.Seek( nVersionMapPos );
781 // Versions-Maps einlesen
782 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_VERSIONMAP );
783 sal_uInt16 nVerCount(0);
784 rStream >> nVerCount;
785 for ( sal_uInt16 nVerNo = 0; nVerNo < nVerCount; ++nVerNo )
787 // Header f"ur einzelne Version einlesen
788 sal_uInt16 nVersion(0), nHStart(0), nHEnd(0);
789 rStream >> nVersion >> nHStart >> nHEnd;
790 sal_uInt16 nCount = nHEnd - nHStart + 1;
791 sal_uInt16 nBytes = (nCount)*sizeof(sal_uInt16);
793 // Is new version is known?
794 if ( nVerNo >= pImp->aVersions.size() )
796 // Add new Version
797 sal_uInt16 *pMap = new sal_uInt16[nCount];
798 memset(pMap, 0, nCount * sizeof(sal_uInt16));
799 for ( sal_uInt16 n = 0; n < nCount; ++n )
800 rStream >> pMap[n];
801 SetVersionMap( nVersion, nHStart, nHEnd, pMap );
803 else
804 // Version schon bekannt => "uberspringen
805 rStream.SeekRel( nBytes );
809 // Items laden
810 rStream.Seek( nStartPos );
811 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ITEMS );
812 bool bSecondaryLoaded = false;
813 long nSecondaryEnd = 0;
814 sal_uInt16 nWhich(0), nSlot(0);
815 while ( rStream >> nWhich, nWhich )
817 // ggf. Which-Id aus alter Version verschieben?
818 if ( pImp->nLoadingVersion != pImp->nVersion )
819 nWhich = GetNewWhich( nWhich );
821 rStream >> nSlot;
822 sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False);
823 int bKnownItem = bOwnPool || IsWhich(nMappedWhich);
825 sal_uInt16 nRef(0), nCount(0), nVersion(0);
826 sal_uInt32 nAttrSize(0);
827 rStream >> nVersion >> nCount;
829 std::vector<SfxPoolItemArray_Impl*>::iterator ppArr;
830 SfxPoolItemArray_Impl *pNewArr = 0;
831 SfxPoolItem *pDefItem = 0;
832 if ( bKnownItem )
834 if ( !bOwnPool )
835 nWhich = nMappedWhich;
837 //!SFX_ASSERTWARNING( !nSlot || !HasMap() ||
838 //! ( nSlot == GetSlotId( nWhich, sal_False ) ) ||
839 //! !GetSlotId( nWhich, sal_False ),
840 //! nWhich, "Slot/Which mismatch" );
842 sal_uInt16 nIndex = GetIndex_Impl(nWhich);
843 ppArr = pImp->maPoolItems.begin();
844 std::advance(ppArr, nIndex);
845 pNewArr = new SfxPoolItemArray_Impl();
846 pDefItem = *(pImp->ppStaticDefaults + nIndex);
849 // Position vor ersten Item merken
850 sal_uLong nLastPos = rStream.Tell();
852 // SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
853 if ( !bSecondaryLoaded && pImp->mpSecondary && pDefItem->ISA(SfxSetItem) )
855 // an das Ende des eigenen Pools seeken
856 rStream.Seek(nEndOfSizes);
857 CHECK_FILEFORMAT_RELEASE( rStream, SFX_ITEMPOOL_TAG_ENDPOOL, pNewArr );
858 CHECK_FILEFORMAT_RELEASE( rStream, SFX_ITEMPOOL_TAG_ENDPOOL, pNewArr );
860 // Sekund"arpool einlesen
861 pImp->mpSecondary->Load1_Impl( rStream );
862 bSecondaryLoaded = true;
863 nSecondaryEnd = rStream.Tell();
865 // zur"uck zu unseren eigenen Items
866 rStream.Seek(nLastPos);
869 // Items an sich lesen
870 for ( sal_uInt16 j = 0; j < nCount; ++j )
872 sal_uLong nPos = nLastPos;
873 rStream >> nRef;
875 if ( bKnownItem )
877 SfxPoolItem *pItem = 0;
878 if ( nRef )
880 pItem = pDefItem->Create(rStream, nVersion);
882 if ( !pImp->mbPersistentRefCounts )
883 // bis <SfxItemPool::LoadCompleted()> festhalten
884 AddRef(*pItem, 1);
885 else
887 if ( nRef > SFX_ITEMS_OLD_MAXREF )
888 pItem->SetKind( nRef );
889 else
890 AddRef(*pItem, nRef);
893 //pNewArr->insert( pItem, j );
894 pNewArr->push_back( (SfxPoolItem*) pItem );
896 // restliche gespeicherte Laenge skippen (neueres Format)
897 nLastPos = rStream.Tell();
900 aSizeTable >> nAttrSize;
901 SFX_ASSERT( !bKnownItem || ( nPos + nAttrSize) >= nLastPos,
902 nPos,
903 "too many bytes read - version mismatch?" );
905 if ( !bKnownItem || ( nLastPos < (nPos + nAttrSize) ) )
907 nLastPos = nPos + nAttrSize;
908 rStream.Seek( nLastPos );
912 if ( bKnownItem )
914 SfxPoolItemArray_Impl *pOldArr = *ppArr;
915 *ppArr = pNewArr;
917 // die Items merken, die schon im Pool sind
918 int bEmpty = sal_True;
919 if ( 0 != pOldArr )
920 for ( size_t n = 0; bEmpty && n < pOldArr->size(); ++n )
921 bEmpty = pOldArr->operator[](n) == 0;
922 DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" );
923 if ( !bEmpty )
925 // f"ur alle alten suchen, ob ein gleiches neues existiert
926 for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld )
928 SfxPoolItem *pOldItem = (*pOldArr)[nOld];
929 if ( pOldItem )
931 bool bFound = false;
932 for ( size_t nNew = 0;
933 nNew < (*ppArr)->size(); ++nNew )
935 SfxPoolItem *&rpNewItem =
936 (SfxPoolItem*&)(*ppArr)->operator[](nNew);
938 if ( rpNewItem && *rpNewItem == *pOldItem )
940 AddRef( *pOldItem, rpNewItem->GetRefCount() );
941 SetRefCount( *rpNewItem, 0 );
942 delete rpNewItem;
943 rpNewItem = pOldItem;
944 bFound = true;
945 SAL_INFO("svl", "reusing item" << pOldItem);
946 break;
949 SAL_INFO_IF(
950 !bFound, "svl", "item not found: " << pOldItem);
954 delete pOldArr; /* @@@ */
958 // Pool-Defaults lesen
959 if ( pImp->nMajorVer > 1 || pImp->nMinorVer > 0 )
960 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_DEFAULTS );
962 sal_uLong nLastPos = rStream.Tell();
963 while ( rStream >> nWhich, nWhich )
965 // ggf. Which-Id aus alter Version verschieben?
966 if ( pImp->nLoadingVersion != pImp->nVersion )
967 nWhich = GetNewWhich( nWhich );
969 rStream >> nSlot;
970 sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False);
971 int bKnownItem = bOwnPool || IsWhich(nMappedWhich);
973 sal_uLong nPos = nLastPos;
974 sal_uInt32 nSize(0);
975 sal_uInt16 nVersion(0);
976 rStream >> nVersion;
978 if ( bKnownItem )
980 if ( !bOwnPool )
981 nWhich = nMappedWhich;
982 SfxPoolItem *pItem =
983 ( *( pImp->ppStaticDefaults + GetIndex_Impl(nWhich) ) )
984 ->Create( rStream, nVersion );
985 pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
986 *( pImp->ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
989 nLastPos = rStream.Tell();
990 aSizeTable >> nSize;
991 SFX_ASSERT( ( nPos + nSize) >= nLastPos, nPos,
992 "too many bytes read - version mismatch?" );
993 if ( nLastPos < (nPos + nSize) )
994 rStream.Seek( nPos + nSize );
997 delete[] pBuf;
998 rStream.Seek(nEndOfSizes);
999 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL );
1000 CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL );
1002 if ( pImp->mpSecondary )
1004 if ( !bSecondaryLoaded )
1005 pImp->mpSecondary->Load1_Impl( rStream );
1006 else
1007 rStream.Seek( nSecondaryEnd );
1010 if ( aExternName != pImp->aName )
1011 pImp->aName = OUString();
1013 pImp->bStreaming = sal_False;
1014 return rStream;
1017 // -----------------------------------------------------------------------
1019 const SfxPoolItem* SfxItemPool::LoadSurrogate
1021 SvStream& rStream, // vor einem Surrogat positionierter Stream
1022 sal_uInt16& rWhich, // Which-Id des zu ladenden <SfxPoolItem>s
1023 sal_uInt16 nSlotId, // Slot-Id des zu ladenden <SfxPoolItem>s
1024 const SfxItemPool* pRefPool // <SfxItemPool> in dem das Surrogat gilt
1027 /* [Beschreibung]
1029 L"adt Surrogat aus 'rStream' und liefert das dadurch in 'rRefPool'
1030 repr"asentierte SfxPoolItem zu"ruck. Ist das im Stream befindliche
1031 Surrogat == SFX_ITEMS_DIRECT (!SFX_ITEM_POOLABLE) wird 0 zur"uckgegeben,
1032 das Item ist direkt aus dem Stream zu laden. Bei 0xfffffff0 (SFX_ITEMS_NULL)
1033 wird auch 0 zurueckgegeben und rWhich auf 0 gesetzt, das Item ist nicht
1034 verfuegbar.
1036 Ansonsten wird ber"ucksichtigt, ob der betroffene Pool ohne Ref-Counts
1037 geladen wird, ob aus einem neuen Pool nachgeladen wird (&rRefPool != this)
1038 oder ob aus einem g"anzlich anders aufgebauten Pool geladen wird.
1040 Wird aus einem anders aufgebauten Pool geladen und die 'nSlotId' kann
1041 nicht in eine Which-Id dieses Pools gemappt werden, wird ebenfalls 0
1042 zur"uckgeliefert.
1044 Preconditions: - Pool mu\s geladen sein
1045 - LoadCompleted darf noch nicht gerufen worden sein
1046 - 'rStream' steht genau an der Position, an der ein
1047 Surrogat f"ur ein Item mit der SlotId 'nSlotId' und
1048 der WhichId 'rWhichId' mit StoreSurrogate gepeichert
1049 wurde
1051 Postconditions: - 'rStream' ist so positioniert, wie auch StoreSurrogate
1052 sein speichern beendet hatte
1053 - konnte ein Item geladen werden, befindet es sich
1054 in diesem SfxItemPool
1055 - 'rWhichId' enth"alt die ggf. gemappte Which-Id
1056 Laufzeit: Tiefe des Ziel Sekund"arpools * 10 + 10
1058 [Querverweise]
1060 <SfxItemPool::StoreSurrogate(SvStream&,const SfxPoolItem &)const>
1064 // Read the first surrogate
1065 sal_uInt32 nSurrogat(0);
1066 rStream >> nSurrogat;
1068 // Is item stored directly?
1069 if ( SFX_ITEMS_DIRECT == nSurrogat )
1070 return 0;
1072 // Item does not exist?
1073 if ( SFX_ITEMS_NULL == nSurrogat )
1075 rWhich = 0;
1076 return 0;
1079 // Bei einem identisch aufgebauten Pool (im Stream) kann das Surrogat
1080 // auf jeden Fall aufgel"ost werden.
1081 if ( !pRefPool )
1082 pRefPool = this;
1083 bool bResolvable = !pRefPool->GetName().isEmpty();
1084 if ( !bResolvable )
1086 // Bei einem anders aufgebauten Pool im Stream, mu\s die SlotId
1087 // aus dem Stream in eine Which-Id gemappt werden k"onnen.
1088 sal_uInt16 nMappedWhich = nSlotId ? GetWhich(nSlotId, sal_True) : 0;
1089 if ( IsWhich(nMappedWhich) )
1091 // gemappte SlotId kann "ubernommen werden
1092 rWhich = nMappedWhich;
1093 bResolvable = sal_True;
1097 // kann Surrogat aufgel"ost werden?
1098 if ( bResolvable )
1100 const SfxPoolItem *pItem = 0;
1101 for ( SfxItemPool *pTarget = this; pTarget; pTarget = pTarget->pImp->mpSecondary )
1103 // richtigen (Folge-) Pool gefunden?
1104 if ( pTarget->IsInRange(rWhich) )
1106 // dflt-Attribut?
1107 if ( SFX_ITEMS_DEFAULT == nSurrogat )
1108 return *(pTarget->pImp->ppStaticDefaults +
1109 pTarget->GetIndex_Impl(rWhich));
1111 SfxPoolItemArray_Impl* pItemArr =
1112 pTarget->pImp->maPoolItems[pTarget->GetIndex_Impl(rWhich)];
1113 pItem = pItemArr && nSurrogat < pItemArr->size()
1114 ? (*pItemArr)[nSurrogat]
1115 : 0;
1116 if ( !pItem )
1118 OSL_FAIL( "can't resolve surrogate" );
1119 rWhich = 0; // nur zur Sicherheit fuer richtige Stream-Pos
1120 return 0;
1123 // Nachladen aus Ref-Pool?
1124 if ( pRefPool != pImp->mpMaster )
1125 return &pTarget->Put( *pItem );
1127 // Referenzen sind NICHT schon mit Pool geladen worden?
1128 if ( !pTarget->HasPersistentRefCounts() )
1129 AddRef( *pItem, 1 );
1130 else
1131 return pItem;
1133 return pItem;
1137 SFX_ASSERT( sal_False, rWhich, "can't resolve Which-Id in LoadSurrogate" );
1140 return 0;
1145 bool SfxItemPool::StoreSurrogate
1147 SvStream& rStream,
1148 const SfxPoolItem* pItem
1149 ) const
1151 /* [Beschreibung]
1153 Speichert ein Surrogat f"ur '*pItem' in 'rStream'.
1156 [R"uckgabewert]
1158 bool TRUE
1159 es wurde ein echtes Surrogat gespeichert, auch
1160 SFX_ITEMS_NULL bei 'pItem==0',
1161 SFX_ITEMS_STATICDEFAULT und SFX_ITEMS_POOLDEFAULT
1162 gelten als 'echte' Surrogate
1164 sal_False
1165 es wurde ein Dummy-Surrogat (SFX_ITEMS_DIRECT)
1166 gespeichert, das eigentliche Item mu\s direkt
1167 hinterher selbst gespeichert werden
1171 if ( pItem )
1173 bool bRealSurrogate = IsItemFlag(*pItem, SFX_ITEM_POOLABLE);
1174 rStream << ( bRealSurrogate
1175 ? GetSurrogate( pItem )
1176 : SFX_ITEMS_DIRECT );
1177 return bRealSurrogate;
1180 rStream << SFX_ITEMS_NULL;
1181 return sal_True;
1184 // -----------------------------------------------------------------------
1186 sal_uInt32 SfxItemPool::GetSurrogate(const SfxPoolItem *pItem) const
1188 DBG_CHKTHIS(SfxItemPool, 0);
1189 DBG_ASSERT( pItem, "no 0-Pointer Surrogate" );
1190 DBG_ASSERT( !IsInvalidItem(pItem), "no Invalid-Item Surrogate" );
1191 DBG_ASSERT( !IsPoolDefaultItem(pItem), "no Pool-Default-Item Surrogate" );
1193 if ( !IsInRange(pItem->Which()) )
1195 if ( pImp->mpSecondary )
1196 return pImp->mpSecondary->GetSurrogate( pItem );
1197 SFX_ASSERT( 0, pItem->Which(), "unknown Which-Id - dont ask me for surrogates" );
1200 // Pointer auf static- oder pool-dflt-Attribut?
1201 if( IsStaticDefaultItem(pItem) || IsPoolDefaultItem(pItem) )
1202 return SFX_ITEMS_DEFAULT;
1204 SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[GetIndex_Impl(pItem->Which())];
1205 DBG_ASSERT(pItemArr, "ItemArr is not available");
1207 for ( size_t i = 0; i < pItemArr->size(); ++i )
1209 const SfxPoolItem *p = (*pItemArr)[i];
1210 if ( p == pItem )
1211 return i;
1213 SFX_ASSERT( 0, pItem->Which(), "Item not in the pool");
1214 return SFX_ITEMS_NULL;
1217 // -----------------------------------------------------------------------
1219 bool SfxItemPool::IsInStoringRange( sal_uInt16 nWhich ) const
1221 return nWhich >= pImp->nStoringStart &&
1222 nWhich <= pImp->nStoringEnd;
1226 void SfxItemPool::SetStoringRange( sal_uInt16 nFrom, sal_uInt16 nTo )
1228 /* [Beschreibung]
1230 Mit dieser Methode kann der Which-Bereich eingeengt werden, der
1231 von ItemSets dieses Pool (und dem Pool selbst) gespeichert wird.
1232 Die Methode muss dazu vor <SfxItemPool::Store()> gerufen werden
1233 und die Werte muessen auch noch gesetzt sein, wenn das eigentliche
1234 Dokument (also die ItemSets gespeicher werden).
1236 Ein Zuruecksetzen ist dann nicht noetig, wenn dieser Range vor
1237 JEDEM Speichern richtig gesetzt wird, da er nur beim Speichern
1238 beruecksichtigt wird.
1240 Dieses muss fuer das 3.1-Format gemacht werden, da dort eine
1241 Bug in der Pool-Lade-Methode vorliegt.
1245 pImp->nStoringStart = nFrom;
1246 pImp->nStoringEnd = nTo;
1249 // -----------------------------------------------------------------------
1251 void SfxItemPool::SetVersionMap
1253 sal_uInt16 nVer, /* neue Versionsnummer */
1254 sal_uInt16 nOldStart, /* alte erste Which-Id */
1255 sal_uInt16 nOldEnd, /* alte letzte Which-Id */
1256 const sal_uInt16* pOldWhichIdTab /* Array mit genau dem Aufbau der Which-Ids
1257 der vorhergehenden Version, in denen
1258 die jeweils neue Which-Id steht. */
1261 /* [Beschreibung]
1263 Mit dieser Methode k"onnen neue, inkompatible Which-Id-Folgen oder
1264 Verteilungen realisiert werden. Pools, die noch mit alten Versionen
1265 gespeichert wurden, werden dann "uber die angegebene Tabelle solange
1266 gemappt, bis die aktuelle Version erreicht ist. Neuere Pools k"onnen
1267 unter Verlust neuer Attribute geladen werden, da die Map mit dem Pool
1268 gespeichert wird.
1270 Precondition: Pool darf noch nicht geladen sein
1271 Postcondition: Which-Ids aus fr"uheren Versionen k"onnen bei Laden auf
1272 Version 'nVer' gemappt werden
1273 Laufzeit: 1.5 * new + 10
1275 [Anmerkung]
1277 F"ur neue Which-Ranges (nStart,nEnd) m"ssen im Vergleich zur Vorg"anger-
1278 Version (nOldStart,nOldEnd) immer gelten, da\s (nOldStart,nOldEnd)
1279 vollst"andig in (nStart,nEnd) enthalten ist. Es ist also zul"assig, den
1280 Which-Range in beide Richtungen zu erweitern, auch durch Einf"ugung
1281 von Which-Ids, nicht aber ihn zu beschneiden.
1283 Diese Methode sollte nur im oder direkt nach Aufruf des Konstruktors
1284 gerufen werden.
1286 Das Array mu\s statisch sein, da es nicht kopiert wird und au\serdem
1287 im Copy-Ctor des SfxItemPool wiederverwendet wird.
1290 [Beispiel]
1292 Urspr"unglich (Version 0) hatte der Pool folgende Which-Ids:
1294 1:A, 2:B, 3:C, 4:D
1296 Nun soll eine neue Version (Version 1) zwei zus"atzliche Ids X und Y
1297 zwischen B und C erhalten, also wie folgt aussehen:
1299 1:A, 2:B, 3:X, 4:Y, 5:C, 6:D
1301 Dabei haben sich also die Ids 3 und 4 ge"andert. F"ur die neue Version
1302 m"u\ste am Pool folgendes gesetzt werden:
1304 static sal_uInt16 nVersion1Map = { 1, 2, 5, 6 };
1305 pPool->SetVersionMap( 1, 1, 4, &nVersion1Map );
1308 [Querverweise]
1310 <SfxItemPool::IsLoadingVersionCurrent()const>
1311 <SfxItemPool::GetNewWhich(sal_uInt16)>
1312 <SfxItemPool::GetVersion()const>
1316 // create new map entry to insert
1317 const SfxPoolVersion_ImplPtr pVerMap = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl(
1318 nVer, nOldStart, nOldEnd, pOldWhichIdTab ) );
1319 pImp->aVersions.push_back( pVerMap );
1321 DBG_ASSERT( nVer > pImp->nVersion, "Versions not sorted" );
1322 pImp->nVersion = nVer;
1324 // Versions-Range anpassen
1325 for ( sal_uInt16 n = 0; n < nOldEnd-nOldStart+1; ++n )
1327 sal_uInt16 nWhich = pOldWhichIdTab[n];
1328 if ( nWhich < pImp->nVerStart )
1330 if ( !nWhich )
1331 nWhich = 0;
1332 pImp->nVerStart = nWhich;
1334 else if ( nWhich > pImp->nVerEnd )
1335 pImp->nVerEnd = nWhich;
1339 // -----------------------------------------------------------------------
1341 sal_uInt16 SfxItemPool::GetNewWhich
1343 sal_uInt16 nFileWhich // die aus dem Stream geladene Which-Id
1344 ) const
1346 /* [Beschreibung]
1348 Diese Methoden rechnet Which-Ids aus einem File-Format in die der
1349 aktuellen Pool-Version um. Ist das File-Format "alter, werden die vom
1350 Pool-Entwickler mit SetVersion() gesetzten Tabellen verwendet,
1351 ist das File-Format neuer, dann die aus dem File geladenen Tabellen.
1352 Im letzteren Fall kann ggf. nicht jede Which-Id gemappt werden,
1353 so da\s 0 zur"uckgeliefert wird.
1355 Die Berechnung ist nur f"ur Which-Ids definiert, die in der betreffenden
1356 File-Version unterst"utzt wurden. Dies ist per Assertion abgesichert.
1358 Precondition: Pool mu\s geladen sein
1359 Postcondition: unver"andert
1360 Laufzeit: linear(Anzahl der Sekund"arpools) +
1361 linear(Differenz zwischen alter und neuer Version)
1364 [Querverweise]
1366 <SfxItemPool::IsLoadingVersionCurrent()const>
1367 <SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1368 <SfxItemPool::GetVersion()const>
1372 // (Sekund"ar-) Pool bestimmen
1373 if ( !IsInVersionsRange(nFileWhich) )
1375 if ( pImp->mpSecondary )
1376 return pImp->mpSecondary->GetNewWhich( nFileWhich );
1377 SFX_ASSERT( 0, nFileWhich, "unknown which in GetNewWhich()" );
1380 // Version neuer/gleich/"alter?
1381 short nDiff = (short)pImp->nLoadingVersion - (short)pImp->nVersion;
1383 // Which-Id einer neueren Version?
1384 if ( nDiff > 0 )
1386 // von der Top-Version bis runter zur File-Version stufenweise mappen
1387 for ( size_t nMap = pImp->aVersions.size(); nMap > 0; --nMap )
1389 SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap-1];
1390 if ( pVerInfo->_nVer > pImp->nVersion )
1391 { sal_uInt16 nOfs;
1392 sal_uInt16 nCount = pVerInfo->_nEnd - pVerInfo->_nStart + 1;
1393 for ( nOfs = 0;
1394 nOfs <= nCount &&
1395 pVerInfo->_pMap[nOfs] != nFileWhich;
1396 ++nOfs )
1397 continue;
1399 if ( pVerInfo->_pMap[nOfs] == nFileWhich )
1400 nFileWhich = pVerInfo->_nStart + nOfs;
1401 else
1402 return 0;
1404 else
1405 break;
1409 // Which-Id einer neueren Version?
1410 else if ( nDiff < 0 )
1412 // von der File-Version bis zur aktuellen Version stufenweise mappen
1413 for ( size_t nMap = 0; nMap < pImp->aVersions.size(); ++nMap )
1415 SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap];
1416 if ( pVerInfo->_nVer > pImp->nLoadingVersion )
1418 DBG_ASSERT( nFileWhich >= pVerInfo->_nStart &&
1419 nFileWhich <= pVerInfo->_nEnd,
1420 "which-id unknown in version" );
1421 nFileWhich = pVerInfo->_pMap[nFileWhich - pVerInfo->_nStart];
1426 // originale (nDiff==0) bzw. gemappte (nDiff!=0) Id zur"uckliefern
1427 return nFileWhich;
1430 // -----------------------------------------------------------------------
1433 bool SfxItemPool::IsInVersionsRange( sal_uInt16 nWhich ) const
1435 return nWhich >= pImp->nVerStart && nWhich <= pImp->nVerEnd;
1438 // -----------------------------------------------------------------------
1440 bool SfxItemPool::IsCurrentVersionLoading() const
1442 /* [Beschreibung]
1444 Mit dieser Methode kann festgestellt werden, ob die geladene Pool-Version
1445 dem aktuellen Pool-Aufbau entspricht.
1447 Precondition: Pool mu\s geladen sein
1448 Postcondition: unver"andert
1449 Laufzeit: linear(Anzahl der Sekund"arpools)
1452 [Querverweise]
1454 <SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1455 <SfxItemPool::GetNewWhich(sal_uInt16)const>
1456 <SfxItemPool::GetVersion()const>
1460 return ( pImp->nVersion == pImp->nLoadingVersion ) &&
1461 ( !pImp->mpSecondary || pImp->mpSecondary->IsCurrentVersionLoading() );
1466 bool SfxItemPool::StoreItem( SvStream &rStream, const SfxPoolItem &rItem,
1467 bool bDirect ) const
1469 /* [Beschreibung]
1471 Speichert das <SfxPoolItem> 'rItem' in den <SvStream> 'rStream'
1472 entweder als Surrogat ('bDirect == sal_False') oder direkt mit 'rItem.Store()'.
1473 Nicht poolable Items werden immer direkt gespeichert. Items ohne Which-Id,
1474 also SID-Items, werden nicht gespeichert, ebenso wenn Items, die in der
1475 File-Format-Version noch nicht vorhanden waren (return sal_False).
1477 Das Item wird im Stream wie folgt abgelegt:
1479 sal_uInt16 rItem.Which()
1480 sal_uInt16 GetSlotId( rItem.Which() ) bzw. 0 falls nicht verf"urbar
1481 sal_uInt16 GetSurrogate( &rItem ) bzw. SFX_ITEM_DIRECT bei '!SFX_ITEM_POOLBLE'
1483 optional (falls 'bDirect == sal_True' oder '!rItem.IsPoolable()':
1485 sal_uInt16 rItem.GetVersion()
1486 sal_uLong Size
1487 Size rItem.Store()
1490 [Querverweise]
1492 <SfxItemPool::LoadItem(SvStream&,bool)const>
1496 DBG_ASSERT( !IsInvalidItem(&rItem), "cannot store invalid items" );
1498 if ( IsSlot( rItem.Which() ) )
1499 return sal_False;
1500 const SfxItemPool *pPool = this;
1501 while ( !pPool->IsInStoringRange(rItem.Which()) )
1502 if ( 0 == ( pPool = pPool->pImp->mpSecondary ) )
1503 return sal_False;
1505 DBG_ASSERT( !pImp->bInSetItem || !rItem.ISA(SfxSetItem),
1506 "SetItem contains ItemSet with SetItem" );
1508 sal_uInt16 nSlotId = pPool->GetSlotId( rItem.Which(), sal_True );
1509 sal_uInt16 nItemVersion = rItem.GetVersion(pImp->mnFileFormatVersion);
1510 if ( USHRT_MAX == nItemVersion )
1511 return sal_False;
1513 rStream << rItem.Which() << nSlotId;
1514 if ( bDirect || !pPool->StoreSurrogate( rStream, &rItem ) )
1516 rStream << nItemVersion;
1517 rStream << (sal_uInt32) 0L; // Platz fuer Laenge in Bytes
1518 sal_uLong nIStart = rStream.Tell();
1519 rItem.Store(rStream, nItemVersion);
1520 sal_uLong nIEnd = rStream.Tell();
1521 rStream.Seek( nIStart-4 );
1522 rStream << (sal_Int32) ( nIEnd-nIStart );
1523 rStream.Seek( nIEnd );
1526 return sal_True;
1531 const SfxPoolItem* SfxItemPool::LoadItem( SvStream &rStream, bool bDirect,
1532 const SfxItemPool *pRefPool )
1534 // pRefPool==-1 => nicht putten!
1537 sal_uInt16 nWhich(0), nSlot(0); // nSurrogate;
1538 rStream >> nWhich >> nSlot;
1540 bool bDontPut = (SfxItemPool*)-1 == pRefPool;
1541 if ( bDontPut || !pRefPool )
1542 pRefPool = this;
1544 // richtigen Sekund"ar-Pool finden
1545 while ( !pRefPool->IsInVersionsRange(nWhich) )
1547 if ( pRefPool->pImp->mpSecondary )
1548 pRefPool = pRefPool->pImp->mpSecondary;
1549 else
1551 // WID in der Version nicht vorhanden => ueberspringen
1552 sal_uInt32 nSurro(0);
1553 sal_uInt16 nVersion(0), nLen(0);
1554 rStream >> nSurro;
1555 if ( SFX_ITEMS_DIRECT == nSurro )
1557 rStream >> nVersion >> nLen;
1558 rStream.SeekRel( nLen );
1560 return 0;
1564 // wird eine andere Version geladen?
1565 bool bCurVersion = pRefPool->IsCurrentVersionLoading();
1566 if ( !bCurVersion )
1567 // Which-Id auf neue Version mappen
1568 nWhich = pRefPool->GetNewWhich( nWhich );
1570 DBG_ASSERT( !nWhich || !pImp->bInSetItem ||
1571 !pRefPool->pImp->ppStaticDefaults[pRefPool->GetIndex_Impl(nWhich)]->ISA(SfxSetItem),
1572 "loading SetItem in ItemSet of SetItem" );
1574 // soll "uber Surrogat geladen werden?
1575 const SfxPoolItem *pItem = 0;
1576 if ( !bDirect )
1578 // Which-Id in dieser Version bekannt?
1579 if ( nWhich )
1580 // Surrogat laden, reagieren falls keins vorhanden
1581 pItem = LoadSurrogate( rStream, nWhich, nSlot, pRefPool );
1582 else
1583 // sonst "uberspringen
1584 rStream.SeekRel( sizeof(sal_uInt16) );
1587 // wird direkt, also nicht "uber Surrogat geladen?
1588 if ( bDirect || ( nWhich && !pItem ) )
1590 // bDirekt bzw. nicht IsPoolable() => Item direkt laden
1591 sal_uInt16 nVersion(0);
1592 sal_uInt32 nLen(0);
1593 rStream >> nVersion >> nLen;
1594 sal_uLong nIStart = rStream.Tell();
1596 // Which-Id in dieser Version bekannt?
1597 if ( nWhich )
1599 // Item direkt laden
1600 SfxPoolItem *pNewItem =
1601 pRefPool->GetDefaultItem(nWhich).Create(rStream, nVersion);
1602 if ( bDontPut )
1603 pItem = pNewItem;
1604 else
1605 if ( pNewItem )
1607 pItem = &Put(*pNewItem);
1608 delete pNewItem;
1610 else
1611 pItem = 0;
1612 sal_uLong nIEnd = rStream.Tell();
1613 DBG_ASSERT( nIEnd <= (nIStart+nLen), "read past end of item" );
1614 if ( (nIStart+nLen) != nIEnd )
1615 rStream.Seek( nIStart+nLen );
1617 else
1618 // Item "uberspringen
1619 rStream.Seek( nIStart+nLen );
1622 return pItem;
1626 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */