1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
32 // STATIC DATA -----------------------------------------------------------
34 DBG_NAME(SfxItemPool
);
37 const SfxItemPool
* SfxItemPool::GetStoringPool()
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
53 SvStream
&SfxItemPool::Store(SvStream
&rStream
) const
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.
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)
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)
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)
91 sal_uInt16 pItem->GetVersion()
93 record SfxMultiRecord(SFX_, 0)
96 unknown pItem->Store()
98 ;jetzt die gesetzten Pool-Defaults
99 Defaults: record SfxMultiRecord(SFX_ITEMPOOL_REC_DEFAULTS, 0)
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
;
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
);
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);
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
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");
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();
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
);
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" );
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
];
253 sal_uInt16 nItemVersion
= pDefaultItem
->GetVersion( pImp
->mnFileFormatVersion
);
254 if ( USHRT_MAX
== nItemVersion
)
255 // => gab es in der Version noch nicht
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
;
265 pDefaultItem
->Store( rStream
, nItemVersion
);
270 // weitere Pools rausschreiben
273 if ( !rStream
.GetError() && pImp
->mpSecondary
)
274 pImp
->mpSecondary
->Store( rStream
);
276 pImp
->bStreaming
= sal_False
;
280 bool SfxItemPool::HasPersistentRefCounts() const
282 return pImp
->mbPersistentRefCounts
;
285 void SfxItemPool::LoadCompleted()
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.
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.
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?
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
)
326 const SfxPoolItem
&rItem
= **ppHtArr
;
327 DBG_ASSERT( !rItem
.ISA(SfxSetItem
) ||
328 0 != &((const SfxSetItem
&)rItem
).GetItemSet(),
329 "SetItem without ItemSet" );
332 if ( !ReleaseRef( **ppHtArr
, 1 ) )
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
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
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);
397 if ( nRef
> SFX_ITEMS_OLD_MAXREF
)
398 SfxItemPool::SetKind(*pItem
, nRef
);
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
;
411 // die Items merken, die schon im Pool sind
414 for ( n
= 0; bEmpty
&& n
< pOldArr
->size(); ++n
)
415 bEmpty
= pOldArr
->operator[](n
) == 0;
416 DBG_ASSERTWARNING( bEmpty
, "loading non-empty pool" );
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
];
425 sal_uInt32 nFree
= SAL_MAX_UINT32
;
427 for ( size_t nNew
= (*ppArr
)->size(); nNew
--; )
430 SfxPoolItem
*&rpNewItem
=
431 (SfxPoolItem
*&)(*ppArr
)->operator[](nNew
);
433 // surrogat unbenutzt?
438 else if ( *rpNewItem
== *pOldItem
)
441 SfxItemPool::AddRef( *pOldItem
, rpNewItem
->GetRefCount() );
442 SfxItemPool::SetRefCount( *rpNewItem
, 0 );
444 rpNewItem
= pOldItem
;
450 // vorhervorhandene, nicht geladene uebernehmen
453 if ( nFree
!= SAL_MAX_UINT32
)
454 (SfxPoolItem
*&)(*ppArr
)->operator[](nFree
) = pOldItem
;
456 (*ppArr
)->push_back( (SfxPoolItem
*) pOldItem
);
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?
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
)
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" );
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
;
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
;
523 if ( pImp
->nMajorVer
< 2 )
524 // pImp->bStreaming wird von Load1_Impl() zur"uckgesetzt
525 return Load1_Impl( rStream
);
528 if ( pImp
->nMajorVer
> SFX_ITEMPOOL_VER_MAJOR
)
530 rStream
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
531 pImp
->bStreaming
= sal_False
;
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
;
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
;
561 rStream
>> pImp
->nLoadingVersion
;
562 aExternName
= SfxPoolItem::readByteString(rStream
);
563 bOwnPool
= aExternName
== pImp
->aName
;
565 //! solange wir keine fremden Pools laden k"onnen
568 rStream
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
570 pImp
->bStreaming
= sal_False
;
577 SfxMultiRecordReader
aVerRec( &rStream
, SFX_ITEMPOOL_REC_VERSIONMAP
);
578 if ( rStream
.GetError() )
580 pImp
->bStreaming
= sal_False
;
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() )
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
)
601 SetVersionMap( nVersion
, nHStart
, nHEnd
, pMap
);
604 pImp
->nVersion
= nOwnVersion
;
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();
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
) )
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();
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();
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
) )
681 //!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, sal_False ) ),
682 //! nWhich, "Slot/Which mismatch" );
684 // Pool-Default-Item selbst laden
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
695 if ( pImp
->mpSecondary
)
697 if ( !bSecondaryLoaded
)
698 pImp
->mpSecondary
->Load( rStream
);
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
;
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
744 rStream
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
745 pImp
->bStreaming
= sal_False
;
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
;
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() )
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
)
801 SetVersionMap( nVersion
, nHStart
, nHEnd
, pMap
);
804 // Version schon bekannt => "uberspringen
805 rStream
.SeekRel( nBytes
);
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
);
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;
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
;
877 SfxPoolItem
*pItem
= 0;
880 pItem
= pDefItem
->Create(rStream
, nVersion
);
882 if ( !pImp
->mbPersistentRefCounts
)
883 // bis <SfxItemPool::LoadCompleted()> festhalten
887 if ( nRef
> SFX_ITEMS_OLD_MAXREF
)
888 pItem
->SetKind( nRef
);
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
,
903 "too many bytes read - version mismatch?" );
905 if ( !bKnownItem
|| ( nLastPos
< (nPos
+ nAttrSize
) ) )
907 nLastPos
= nPos
+ nAttrSize
;
908 rStream
.Seek( nLastPos
);
914 SfxPoolItemArray_Impl
*pOldArr
= *ppArr
;
917 // die Items merken, die schon im Pool sind
918 int bEmpty
= sal_True
;
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" );
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
];
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 );
943 rpNewItem
= pOldItem
;
945 SAL_INFO("svl", "reusing item" << pOldItem
);
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
);
970 sal_uInt16 nMappedWhich
= GetWhich(nSlot
, sal_False
);
971 int bKnownItem
= bOwnPool
|| IsWhich(nMappedWhich
);
973 sal_uLong nPos
= nLastPos
;
975 sal_uInt16
nVersion(0);
981 nWhich
= nMappedWhich
;
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();
991 SFX_ASSERT( ( nPos
+ nSize
) >= nLastPos
, nPos
,
992 "too many bytes read - version mismatch?" );
993 if ( nLastPos
< (nPos
+ nSize
) )
994 rStream
.Seek( nPos
+ nSize
);
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
);
1007 rStream
.Seek( nSecondaryEnd
);
1010 if ( aExternName
!= pImp
->aName
)
1011 pImp
->aName
= OUString();
1013 pImp
->bStreaming
= sal_False
;
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
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
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
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
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
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
)
1072 // Item does not exist?
1073 if ( SFX_ITEMS_NULL
== nSurrogat
)
1079 // Bei einem identisch aufgebauten Pool (im Stream) kann das Surrogat
1080 // auf jeden Fall aufgel"ost werden.
1083 bool bResolvable
= !pRefPool
->GetName().isEmpty();
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?
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
) )
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
]
1118 OSL_FAIL( "can't resolve surrogate" );
1119 rWhich
= 0; // nur zur Sicherheit fuer richtige Stream-Pos
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 );
1137 SFX_ASSERT( sal_False
, rWhich
, "can't resolve Which-Id in LoadSurrogate" );
1145 bool SfxItemPool::StoreSurrogate
1148 const SfxPoolItem
* pItem
1153 Speichert ein Surrogat f"ur '*pItem' in 'rStream'.
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
1165 es wurde ein Dummy-Surrogat (SFX_ITEMS_DIRECT)
1166 gespeichert, das eigentliche Item mu\s direkt
1167 hinterher selbst gespeichert werden
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
;
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
];
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
)
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. */
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
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
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
1286 Das Array mu\s statisch sein, da es nicht kopiert wird und au\serdem
1287 im Copy-Ctor des SfxItemPool wiederverwendet wird.
1292 Urspr"unglich (Version 0) hatte der Pool folgende Which-Ids:
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 );
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
)
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
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)
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?
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
)
1392 sal_uInt16 nCount
= pVerInfo
->_nEnd
- pVerInfo
->_nStart
+ 1;
1395 pVerInfo
->_pMap
[nOfs
] != nFileWhich
;
1399 if ( pVerInfo
->_pMap
[nOfs
] == nFileWhich
)
1400 nFileWhich
= pVerInfo
->_nStart
+ nOfs
;
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
1430 // -----------------------------------------------------------------------
1433 bool SfxItemPool::IsInVersionsRange( sal_uInt16 nWhich
) const
1435 return nWhich
>= pImp
->nVerStart
&& nWhich
<= pImp
->nVerEnd
;
1438 // -----------------------------------------------------------------------
1440 bool SfxItemPool::IsCurrentVersionLoading() const
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)
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
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()
1492 <SfxItemPool::LoadItem(SvStream&,bool)const>
1496 DBG_ASSERT( !IsInvalidItem(&rItem
), "cannot store invalid items" );
1498 if ( IsSlot( rItem
.Which() ) )
1500 const SfxItemPool
*pPool
= this;
1501 while ( !pPool
->IsInStoringRange(rItem
.Which()) )
1502 if ( 0 == ( pPool
= pPool
->pImp
->mpSecondary
) )
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
)
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
);
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
)
1544 // richtigen Sekund"ar-Pool finden
1545 while ( !pRefPool
->IsInVersionsRange(nWhich
) )
1547 if ( pRefPool
->pImp
->mpSecondary
)
1548 pRefPool
= pRefPool
->pImp
->mpSecondary
;
1551 // WID in der Version nicht vorhanden => ueberspringen
1552 sal_uInt32
nSurro(0);
1553 sal_uInt16
nVersion(0), nLen(0);
1555 if ( SFX_ITEMS_DIRECT
== nSurro
)
1557 rStream
>> nVersion
>> nLen
;
1558 rStream
.SeekRel( nLen
);
1564 // wird eine andere Version geladen?
1565 bool bCurVersion
= pRefPool
->IsCurrentVersionLoading();
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;
1578 // Which-Id in dieser Version bekannt?
1580 // Surrogat laden, reagieren falls keins vorhanden
1581 pItem
= LoadSurrogate( rStream
, nWhich
, nSlot
, pRefPool
);
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);
1593 rStream
>> nVersion
>> nLen
;
1594 sal_uLong nIStart
= rStream
.Tell();
1596 // Which-Id in dieser Version bekannt?
1599 // Item direkt laden
1600 SfxPoolItem
*pNewItem
=
1601 pRefPool
->GetDefaultItem(nWhich
).Create(rStream
, nVersion
);
1607 pItem
= &Put(*pNewItem
);
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
);
1618 // Item "uberspringen
1619 rStream
.Seek( nIStart
+nLen
);
1626 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */