1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: poolio.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
40 #include <tools/solar.h>
41 #include <svtools/itempool.hxx>
42 #include "whassert.hxx"
43 #include <svtools/brdcst.hxx>
44 #include <svtools/filerec.hxx>
45 #include <svtools/svtdata.hxx>
48 // STATIC DATA -----------------------------------------------------------
50 DBG_NAME(SfxItemPool
);
52 //========================================================================
54 void SfxItemPool::SetStoringPool( const SfxItemPool
*pStoringPool
)
58 Diese Methode setzt den <SfxItemPool>, der gerade gespeichert wird.
59 Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format-
60 Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines
61 <SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen
62 Pool mit <SfxItemPool::GetStoringPool()> zu besorgen.
64 Sie wird von <SfxItemPool::Store()> bedient, kann jedoch f"ur nicht
65 poolable Items auch direkt gerufen werden. Bitte m"oglichst nicht
66 f"ur jedes Item einzeln, da 2 Calls!
70 ImpSvtData::GetSvtData().pStoringPool
= pStoringPool
;
73 //-------------------------------------------------------------------------
75 const SfxItemPool
* SfxItemPool::GetStoringPool()
79 Diese Methode liefert den <SfxItemPool>, der gerade gespeichert wird.
80 Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format-
81 Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines
82 <SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen
87 return ImpSvtData::GetSvtData().pStoringPool
;
90 //-------------------------------------------------------------------------
92 SvStream
&SfxItemPool::Store(SvStream
&rStream
) const
96 Der SfxItemPool wird inklusive aller seiner Sekund"arpools mit
97 Pool-Defaults und gepoolten Items in dem angegebenen Stream gespeichert.
98 Die statischen Defaults werden nicht gespeichert.
103 ;zun"achst ein Kompatiblit"ats-Header-Block
104 Start: 0x1111 SFX_ITEMPOOL_TAG_STARTPOOLS(_4/_5)
105 BYTE MAJOR_VER ;SfxItemPool-Version
107 0xFFFF SFX_ITEMPOOL_TAG_TRICK4OLD ;ex. GetVersion()
108 USHORT 0x0000 ;Pseudo-StyleSheetPool
109 USHORT 0x0000 ;Pseudo-StyleSheetPool
111 ;den ganzen Pool in einen Record
112 record SfxMiniRecod(SFX_ITEMPOOL_REC)
114 ;je ein Header vorweg
115 Header: record SfxMiniRecord(SFX_ITEMPOOL_REC_HEADER)
116 USHORT GetVersion() ;Which-Ranges etc.
117 String GetName() ;Pool-Name
119 ;die Versions-Map, um WhichIds neuer File-Versionen mappen zu k"onnen
120 Versions: record SfxMultiRecord(SFX_ITEMPOOL_REC_VERSIONS, 0)
124 USHORT[] NewWhich (OldEndWhich-OldStartWhich+1)
126 ;jetzt die gepoolten Items (zuerst nicht-SfxSetItems)
127 Items: record SfxMultiRecord(SFX_ITEMPOOL_REC_WHICHIDS, 0)
130 USHORT pItem->GetVersion()
132 record SfxMultiRecord(SFX_, 0)
135 unknown pItem->Store()
137 ;jetzt die gesetzten Pool-Defaults
138 Defaults: record SfxMultiRecord(SFX_ITEMPOOL_REC_DEFAULTS, 0)
141 USHORT pPoolDef->GetVersion()
142 unknown pPoolDef->Store();
144 ;dahinter folgt ggf. der Secondary ohne Kompatiblit"ats-Header-Block
148 DBG_CHKTHIS(SfxItemPool
, 0);
150 // Store-Master finden
151 SfxItemPool
*pStoreMaster
= pMaster
!= this ? pMaster
: 0;
152 while ( pStoreMaster
&& !pStoreMaster
->pImp
->bStreaming
)
153 pStoreMaster
= pStoreMaster
->pSecondary
;
155 // Alter-Header (Version des Pools an sich und Inhalts-Version 0xffff)
156 pImp
->bStreaming
= TRUE
;
159 rStream
<< ( rStream
.GetVersion() >= SOFFICE_FILEFORMAT_50
160 ? SFX_ITEMPOOL_TAG_STARTPOOL_5
161 : SFX_ITEMPOOL_TAG_STARTPOOL_4
);
162 rStream
<< SFX_ITEMPOOL_VER_MAJOR
<< SFX_ITEMPOOL_VER_MINOR
;
163 rStream
<< SFX_ITEMPOOL_TAG_TRICK4OLD
;
165 // SfxStyleSheet-Bug umgehen
166 rStream
<< UINT16(0); // Version
167 rStream
<< UINT16(0); // Count (2. Schleife f"allt sonst auf die Fresse)
170 // jeder Pool ist als ganzes ein Record
171 SfxMiniRecordWriter
aPoolRec( &rStream
, SFX_ITEMPOOL_REC
);
172 ImpSvtData::GetSvtData().pStoringPool
= this;
174 // Einzel-Header (Version des Inhalts und Name)
176 SfxMiniRecordWriter
aPoolHeaderRec( &rStream
, SFX_ITEMPOOL_REC_HEADER
);
177 rStream
<< pImp
->nVersion
;
178 SfxPoolItem::writeByteString(rStream
, aName
);
183 SfxMultiVarRecordWriter
aVerRec( &rStream
, SFX_ITEMPOOL_REC_VERSIONMAP
, 0 );
184 for ( USHORT nVerNo
= 0; nVerNo
< pImp
->aVersions
.Count(); ++nVerNo
)
186 aVerRec
.NewContent();
187 SfxPoolVersion_Impl
*pVer
= pImp
->aVersions
[nVerNo
];
188 rStream
<< pVer
->_nVer
<< pVer
->_nStart
<< pVer
->_nEnd
;
189 USHORT nCount
= pVer
->_nEnd
- pVer
->_nStart
+ 1;
190 USHORT nNewWhich
= 0;
191 for ( USHORT n
= 0; n
< nCount
; ++n
)
193 nNewWhich
= pVer
->_pMap
[n
];
194 rStream
<< nNewWhich
;
197 // Workaround gegen Bug in SetVersionMap der 312
198 if ( SOFFICE_FILEFORMAT_31
== _nFileFormatVersion
)
199 rStream
<< USHORT(nNewWhich
+1);
205 SfxMultiMixRecordWriter
aWhichIdsRec( &rStream
, SFX_ITEMPOOL_REC_WHICHIDS
, 0 );
207 // erst Atomaren-Items und dann die Sets schreiben (wichtig beim Laden)
208 for ( pImp
->bInSetItem
= FALSE
; pImp
->bInSetItem
<= TRUE
&& !rStream
.GetError(); ++pImp
->bInSetItem
)
210 SfxPoolItemArray_Impl
**pArr
= pImp
->ppPoolItems
;
211 SfxPoolItem
**ppDefItem
= ppStaticDefaults
;
212 const USHORT nSize
= GetSize_Impl();
213 for ( USHORT i
= 0; i
< nSize
&& !rStream
.GetError(); ++i
, ++pArr
, ++ppDefItem
)
215 // Version des Items feststellen
216 USHORT nItemVersion
= (*ppDefItem
)->GetVersion( _nFileFormatVersion
);
217 if ( USHRT_MAX
== nItemVersion
)
218 // => kam in zu exportierender Version gar nicht vor
221 // !poolable wird gar nicht im Pool gespeichert
222 // und itemsets/plain-items je nach Runde
224 if ( *pArr
&& IsItemFlag(**ppDefItem
, SFX_ITEM_POOLABLE
) &&
226 if ( *pArr
&& (*ppDefItem
)->IsPoolable() &&
228 pImp
->bInSetItem
== (*ppDefItem
)->ISA(SfxSetItem
) )
230 // eigene Kennung, globale Which-Id und Item-Version
231 USHORT nSlotId
= GetSlotId( (*ppDefItem
)->Which(), FALSE
);
232 aWhichIdsRec
.NewContent(nSlotId
, 0);
233 rStream
<< (*ppDefItem
)->Which();
234 rStream
<< nItemVersion
;
235 const USHORT nCount
= (*pArr
)->Count();
236 DBG_ASSERT(nCount
, "ItemArr ist leer");
239 // Items an sich schreiben
240 SfxMultiMixRecordWriter
aItemsRec( &rStream
, SFX_ITEMPOOL_REC_ITEMS
, 0 );
241 for ( USHORT j
= 0; j
< nCount
; ++j
)
243 // Item selbst besorgen
244 const SfxPoolItem
*pItem
= (*pArr
)->GetObject(j
);
245 if ( pItem
&& pItem
->GetRefCount() ) //! siehe anderes MI-REF
247 aItemsRec
.NewContent(j
, 'X' );
249 if ( pItem
->GetRefCount() == SFX_ITEMS_SPECIAL
)
250 rStream
<< (USHORT
) pItem
->GetKind();
253 rStream
<< (USHORT
) pItem
->GetRefCount();
254 if( pItem
->GetRefCount() > SFX_ITEMS_OLD_MAXREF
)
255 rStream
.SetError( ERRCODE_IO_NOTSTORABLEINBINARYFORMAT
);
258 if ( !rStream
.GetError() )
259 pItem
->Store(rStream
, nItemVersion
);
263 if ( !pItem
->ISA(SfxSetItem
) )
265 ULONG nMark
= rStream
.Tell();
266 rStream
.Seek( nItemStartPos
+ sizeof(USHORT
) );
267 SfxPoolItem
*pClone
= pItem
->Create(rStream
, nItemVersion
);
268 USHORT nWh
= pItem
->Which();
269 SFX_ASSERT( rStream
.Tell() == nMark
, nWh
,"asymmetric store/create" );
270 SFX_ASSERT( *pClone
== *pItem
, nWh
, "unequal after store/create" );
280 pImp
->bInSetItem
= FALSE
;
283 // die gesetzten Defaults speichern (Pool-Defaults)
284 if ( !rStream
.GetError() )
286 SfxMultiMixRecordWriter
aDefsRec( &rStream
, SFX_ITEMPOOL_REC_DEFAULTS
, 0 );
287 USHORT nCount
= GetSize_Impl();
288 for ( USHORT n
= 0; n
< nCount
; ++n
)
290 const SfxPoolItem
* pDefaultItem
= ppPoolDefaults
[n
];
294 USHORT nItemVersion
= pDefaultItem
->GetVersion( _nFileFormatVersion
);
295 if ( USHRT_MAX
== nItemVersion
)
296 // => gab es in der Version noch nicht
299 // eigene Kennung, globale Kennung, Version
300 USHORT nSlotId
= GetSlotId( pDefaultItem
->Which(), FALSE
);
301 aDefsRec
.NewContent( nSlotId
, 0 );
302 rStream
<< pDefaultItem
->Which();
303 rStream
<< nItemVersion
;
306 pDefaultItem
->Store( rStream
, nItemVersion
);
311 // weitere Pools rausschreiben
312 ImpSvtData::GetSvtData().pStoringPool
= 0;
314 if ( !rStream
.GetError() && pSecondary
)
315 pSecondary
->Store( rStream
);
317 pImp
->bStreaming
= FALSE
;
321 // -----------------------------------------------------------------------
323 void SfxItemPool::LoadCompleted()
327 Wurde der SfxItemPool mit 'bRefCounts' == FALSE geladen, mu\s das
328 Laden der Dokumentinhalte mit einem Aufruf dieser Methode beendet
329 werden. Ansonsten hat der Aufruf dieser Methode keine Funktion.
334 Beim Laden ohne Ref-Counts werden diese tats"achlich auf 1 gesetzt,
335 damit nicht w"ahrend des Ladevorgangs SfxPoolItems gel"oscht werden,
336 die danach, aber auch noch beim Ladevorgang, ben"otigt werden. Diese
337 Methode setzt den Ref-Count wieder zur"uck und entfernt dabei
338 gleichzeitig alle nicht mehr ben"otigten Items.
343 <SfxItemPool::Load()>
347 // wurden keine Ref-Counts mitgeladen?
348 if ( pImp
->nInitRefCount
> 1 )
351 // "uber alle Which-Werte iterieren
352 SfxPoolItemArray_Impl
** ppItemArr
= pImp
->ppPoolItems
;
353 for( USHORT nArrCnt
= GetSize_Impl(); nArrCnt
; --nArrCnt
, ++ppItemArr
)
355 // ist "uberhaupt ein Item mit dem Which-Wert da?
358 // "uber alle Items mit dieser Which-Id iterieren
359 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
360 for( USHORT n
= (*ppItemArr
)->Count(); n
; --n
, ++ppHtArr
)
364 const SfxPoolItem
&rItem
= **ppHtArr
;
365 DBG_ASSERT( !rItem
.ISA(SfxSetItem
) ||
366 0 != &((const SfxSetItem
&)rItem
).GetItemSet(),
367 "SetItem without ItemSet" );
370 if ( !ReleaseRef( **ppHtArr
, 1 ) )
376 // from now on normal initial ref count
377 pImp
->nInitRefCount
= 1;
380 // notify secondary pool
382 pSecondary
->LoadCompleted();
385 //============================================================================
386 // This had to be moved to a method of its own to keep Solaris GCC happy:
387 void SfxItemPool::readTheItems (
388 SvStream
& rStream
, USHORT nItemCount
, USHORT nVersion
,
389 SfxPoolItem
* pDefItem
, SfxPoolItemArray_Impl
** ppArr
)
391 SfxMultiRecordReader
aItemsRec( &rStream
, SFX_ITEMPOOL_REC_ITEMS
);
393 SfxPoolItemArray_Impl
*pNewArr
= new SfxPoolItemArray_Impl( nItemCount
);
394 SfxPoolItem
*pItem
= 0;
396 USHORT n
, nLastSurrogate
= USHORT(-1);
397 while (aItemsRec
.GetContent())
399 // n"achstes Surrogat holen
400 USHORT nSurrogate
= aItemsRec
.GetContentTag();
401 DBG_ASSERT( aItemsRec
.GetContentVersion() == 'X',
402 "not an item content" );
404 // fehlende auff"ullen
405 for ( pItem
= 0, n
= nLastSurrogate
+1; n
< nSurrogate
; ++n
)
406 pNewArr
->C40_INSERT(SfxPoolItem
, pItem
, n
);
407 nLastSurrogate
= nSurrogate
;
409 // Ref-Count und Item laden
413 pItem
= pDefItem
->Create(rStream
, nVersion
);
414 pNewArr
->C40_INSERT(SfxPoolItem
, pItem
, nSurrogate
);
416 if ( !bPersistentRefCounts
)
417 // bis <SfxItemPool::LoadCompleted()> festhalten
421 if ( nRef
> SFX_ITEMS_OLD_MAXREF
)
422 pItem
->SetKind( nRef
);
424 AddRef(*pItem
, nRef
);
428 // fehlende auff"ullen
429 for ( pItem
= 0, n
= nLastSurrogate
+1; n
< nItemCount
; ++n
)
430 pNewArr
->C40_INSERT(SfxPoolItem
, pItem
, n
);
432 SfxPoolItemArray_Impl
*pOldArr
= *ppArr
;
435 // die Items merken, die schon im Pool sind
438 for ( n
= 0; bEmpty
&& n
< pOldArr
->Count(); ++n
)
439 bEmpty
= pOldArr
->GetObject(n
) == 0;
440 DBG_ASSERTWARNING( bEmpty
, "loading non-empty pool" );
443 // f"ur alle alten suchen, ob ein gleiches neues existiert
444 for ( USHORT nOld
= 0; nOld
< pOldArr
->Count(); ++nOld
)
446 SfxPoolItem
*pOldItem
= (*pOldArr
)[nOld
];
449 USHORT nFree
= USHRT_MAX
;
451 USHORT nCount
= (*ppArr
)->Count();
452 for ( USHORT nNew
= nCount
; !bFound
&& nNew
--; )
455 SfxPoolItem
*&rpNewItem
=
456 (SfxPoolItem
*&)(*ppArr
)->GetData()[nNew
];
458 // surrogat unbenutzt?
463 else if ( *rpNewItem
== *pOldItem
)
466 AddRef( *pOldItem
, rpNewItem
->GetRefCount() );
467 SetRefCount( *rpNewItem
, 0 );
469 rpNewItem
= pOldItem
;
474 // vorhervorhandene, nicht geladene uebernehmen
477 if ( nFree
!= USHRT_MAX
)
478 (SfxPoolItem
*&)(*ppArr
)->GetData()[nFree
] = pOldItem
;
480 (*ppArr
)->C40_INSERT( SfxPoolItem
, pOldItem
, nCount
);
488 // -----------------------------------------------------------------------
490 SvStream
&SfxItemPool::Load(SvStream
&rStream
)
492 DBG_CHKTHIS(SfxItemPool
, 0);
493 DBG_ASSERT(ppStaticDefaults
, "kein DefaultArray");
495 // protect items by increasing ref count
496 if ( !bPersistentRefCounts
)
499 // "uber alle Which-Werte iterieren
500 SfxPoolItemArray_Impl
** ppItemArr
= pImp
->ppPoolItems
;
501 for( USHORT nArrCnt
= GetSize_Impl(); nArrCnt
; --nArrCnt
, ++ppItemArr
)
503 // ist "uberhaupt ein Item mit dem Which-Wert da?
506 // "uber alle Items mit dieser Which-Id iterieren
507 SfxPoolItem
** ppHtArr
= (SfxPoolItem
**)(*ppItemArr
)->GetData();
508 for( USHORT n
= (*ppItemArr
)->Count(); n
; --n
, ++ppHtArr
)
512 const SfxPoolItem
&rItem
= **ppHtArr
;
513 DBG_ASSERT( !rItem
.ISA(SfxSetItem
) ||
514 0 != &((const SfxSetItem
&)rItem
).GetItemSet(),
515 "SetItem without ItemSet" );
516 DBG_WARNING( "loading non-empty ItemPool" );
519 AddRef( **ppHtArr
, 1 );
524 // during loading (until LoadCompleted()) protect all items
525 pImp
->nInitRefCount
= 2;
528 // Load-Master finden
529 SfxItemPool
*pLoadMaster
= pMaster
!= this ? pMaster
: 0;
530 while ( pLoadMaster
&& !pLoadMaster
->pImp
->bStreaming
)
531 pLoadMaster
= pLoadMaster
->pSecondary
;
533 // Gesamt Header einlesen
534 pImp
->bStreaming
= TRUE
;
537 // Format-Version laden
538 CHECK_FILEFORMAT2( rStream
,
539 SFX_ITEMPOOL_TAG_STARTPOOL_5
, SFX_ITEMPOOL_TAG_STARTPOOL_4
);
540 rStream
>> pImp
->nMajorVer
>> pImp
->nMinorVer
;
542 // Format-Version in Master-Pool "ubertragen
543 pMaster
->pImp
->nMajorVer
= pImp
->nMajorVer
;
544 pMaster
->pImp
->nMinorVer
= pImp
->nMinorVer
;
547 if ( pImp
->nMajorVer
< 2 )
548 // pImp->bStreaming wird von Load1_Impl() zur"uckgesetzt
549 return Load1_Impl( rStream
);
552 if ( pImp
->nMajorVer
> SFX_ITEMPOOL_VER_MAJOR
)
554 rStream
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
555 pImp
->bStreaming
= FALSE
;
559 // Version 1.2-Trick-Daten "uberspringen
560 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_TRICK4OLD
);
561 rStream
.SeekRel( 4 ); // Hack-Daten wegen SfxStyleSheetPool-Bug skippen
564 // neues Record-orientiertes Format
565 SfxMiniRecordReader
aPoolRec( &rStream
, SFX_ITEMPOOL_REC
);
566 if ( rStream
.GetError() )
568 pImp
->bStreaming
= FALSE
;
574 UniString aExternName
;
576 // Header-Record suchen
577 SfxMiniRecordReader
aPoolHeaderRec( &rStream
, SFX_ITEMPOOL_REC_HEADER
);
578 if ( rStream
.GetError() )
580 pImp
->bStreaming
= FALSE
;
585 rStream
>> pImp
->nLoadingVersion
;
586 SfxPoolItem::readByteString(rStream
, aExternName
);
587 bOwnPool
= aExternName
== aName
;
589 //! solange wir keine fremden Pools laden k"onnen
592 rStream
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
594 pImp
->bStreaming
= FALSE
;
601 SfxMultiRecordReader
aVerRec( &rStream
, SFX_ITEMPOOL_REC_VERSIONMAP
);
602 if ( rStream
.GetError() )
604 pImp
->bStreaming
= FALSE
;
608 // Versions-Maps einlesen
609 USHORT nOwnVersion
= pImp
->nVersion
;
610 for ( USHORT nVerNo
= 0; aVerRec
.GetContent(); ++nVerNo
)
612 // Header f"ur einzelne Version einlesen
613 USHORT nVersion
, nHStart
, nHEnd
;
614 rStream
>> nVersion
>> nHStart
>> nHEnd
;
615 USHORT nCount
= nHEnd
- nHStart
+ 1;
617 // Version neuer als bekannt?
618 if ( nVerNo
>= pImp
->aVersions
.Count() )
620 // neue Version hinzufuegen
621 USHORT
*pMap
= new USHORT
[nCount
];
622 for ( USHORT n
= 0; n
< nCount
; ++n
)
624 SetVersionMap( nVersion
, nHStart
, nHEnd
, pMap
);
627 pImp
->nVersion
= nOwnVersion
;
631 FASTBOOL bSecondaryLoaded
= FALSE
;
632 long nSecondaryEnd
= 0;
634 SfxMultiRecordReader
aWhichIdsRec( &rStream
, SFX_ITEMPOOL_REC_WHICHIDS
);
635 while ( aWhichIdsRec
.GetContent() )
637 // SlotId, Which-Id und Item-Version besorgen
638 USHORT nCount
, nVersion
, nWhich
;
639 //!USHORT nSlotId = aWhichIdsRec.GetContentTag();
641 if ( pImp
->nLoadingVersion
!= pImp
->nVersion
)
642 // Which-Id aus File-Version in Pool-Version verschieben
643 nWhich
= GetNewWhich( nWhich
);
645 // unbekanntes Item aus neuerer Version
646 if ( !IsInRange(nWhich
) )
651 //!SFX_ASSERTWARNING( !nSlotId || !HasMap() ||
652 //! ( nSlotId == GetSlotId( nWhich, FALSE ) ) ||
653 //! !GetSlotId( nWhich, FALSE ),
654 //! nWhich, "Slot/Which mismatch" );
656 USHORT nIndex
= GetIndex_Impl(nWhich
);
657 SfxPoolItemArray_Impl
**ppArr
= pImp
->ppPoolItems
+ nIndex
;
659 // SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
660 SfxPoolItem
*pDefItem
= *(ppStaticDefaults
+ nIndex
);
661 pImp
->bInSetItem
= pDefItem
->ISA(SfxSetItem
);
662 if ( !bSecondaryLoaded
&& pSecondary
&& pImp
->bInSetItem
)
664 // an das Ende des eigenen Pools seeken
665 ULONG nLastPos
= rStream
.Tell();
668 // Sekund"arpool einlesen
669 pSecondary
->Load( rStream
);
670 bSecondaryLoaded
= TRUE
;
671 nSecondaryEnd
= rStream
.Tell();
673 // zur"uck zu unseren eigenen Items
674 rStream
.Seek(nLastPos
);
677 // Items an sich lesen
678 readTheItems(rStream
, nCount
, nVersion
, pDefItem
, ppArr
);
680 pImp
->bInSetItem
= FALSE
;
684 // Pool-Defaults lesen
686 SfxMultiRecordReader
aDefsRec( &rStream
, SFX_ITEMPOOL_REC_DEFAULTS
);
688 while ( aDefsRec
.GetContent() )
690 // SlotId, Which-Id und Item-Version besorgen
691 USHORT nVersion
, nWhich
;
692 //!USHORT nSlotId = aDefsRec.GetContentTag();
694 if ( pImp
->nLoadingVersion
!= pImp
->nVersion
)
695 // Which-Id aus File-Version in Pool-Version verschieben
696 nWhich
= GetNewWhich( nWhich
);
698 // unbekanntes Item aus neuerer Version
699 if ( !IsInRange(nWhich
) )
703 //!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, FALSE ) ),
704 //! nWhich, "Slot/Which mismatch" );
706 // Pool-Default-Item selbst laden
708 ( *( ppStaticDefaults
+ GetIndex_Impl(nWhich
) ) )
709 ->Create( rStream
, nVersion
);
710 pItem
->SetKind( SFX_ITEMS_POOLDEFAULT
);
711 *( ppPoolDefaults
+ GetIndex_Impl(nWhich
) ) = pItem
;
715 // ggf. Secondary-Pool laden
719 if ( !bSecondaryLoaded
)
720 pSecondary
->Load( rStream
);
722 rStream
.Seek( nSecondaryEnd
);
725 // wenn nicht own-Pool, dann kein Name
726 if ( aExternName
!= aName
)
729 pImp
->bStreaming
= FALSE
;
733 // -----------------------------------------------------------------------
735 SvStream
&SfxItemPool::Load1_Impl(SvStream
&rStream
)
737 // beim Master ist der Header schon von <Load()> geladen worden
738 if ( !pImp
->bStreaming
)
740 // Header des Secondary lesen
741 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_STARTPOOL_4
);
742 rStream
>> pImp
->nMajorVer
>> pImp
->nMinorVer
;
744 sal_uInt32 nAttribSize
;
746 UniString aExternName
;
747 if ( pImp
->nMajorVer
> 1 || pImp
->nMinorVer
>= 2 )
748 rStream
>> pImp
->nLoadingVersion
;
749 SfxPoolItem::readByteString(rStream
, aExternName
);
750 bOwnPool
= aExternName
== aName
;
751 pImp
->bStreaming
= TRUE
;
753 //! solange wir keine fremden laden k"onnen
756 rStream
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
757 pImp
->bStreaming
= FALSE
;
761 // Versionen bis 1.3 k"onnen noch keine Which-Verschiebungen lesen
762 if ( pImp
->nMajorVer
== 1 && pImp
->nMinorVer
<= 2 &&
763 pImp
->nVersion
< pImp
->nLoadingVersion
)
765 rStream
.SetError(ERRCODE_IO_WRONGVERSION
);
766 pImp
->bStreaming
= FALSE
;
770 // Size-Table liegt hinter den eigentlichen Attributen
771 rStream
>> nAttribSize
;
773 // Size-Table einlesen
774 ULONG nStartPos
= rStream
.Tell();
775 rStream
.SeekRel( nAttribSize
);
776 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_SIZES
);
777 sal_uInt32 nSizeTableLen
;
778 rStream
>> nSizeTableLen
;
779 sal_Char
*pBuf
= new sal_Char
[nSizeTableLen
];
780 rStream
.Read( pBuf
, nSizeTableLen
);
781 ULONG nEndOfSizes
= rStream
.Tell();
782 SvMemoryStream
aSizeTable( pBuf
, nSizeTableLen
, STREAM_READ
);
784 // ab Version 1.3 steht in der Size-Table eine Versions-Map
785 if ( pImp
->nMajorVer
> 1 || pImp
->nMinorVer
>= 3 )
787 // Version-Map finden (letztes ULONG der Size-Table gibt Pos an)
788 rStream
.Seek( nEndOfSizes
- sizeof(sal_uInt32
) );
789 sal_uInt32 nVersionMapPos
;
790 rStream
>> nVersionMapPos
;
791 rStream
.Seek( nVersionMapPos
);
793 // Versions-Maps einlesen
794 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_VERSIONMAP
);
796 rStream
>> nVerCount
;
797 for ( USHORT nVerNo
= 0; nVerNo
< nVerCount
; ++nVerNo
)
799 // Header f"ur einzelne Version einlesen
800 USHORT nVersion
, nHStart
, nHEnd
;
801 rStream
>> nVersion
>> nHStart
>> nHEnd
;
802 USHORT nCount
= nHEnd
- nHStart
+ 1;
803 USHORT nBytes
= (nCount
)*sizeof(USHORT
);
805 // Version neuer als bekannt?
806 if ( nVerNo
>= pImp
->aVersions
.Count() )
808 // neue Version hinzufuegen
809 USHORT
*pMap
= new USHORT
[nCount
];
810 for ( USHORT n
= 0; n
< nCount
; ++n
)
812 SetVersionMap( nVersion
, nHStart
, nHEnd
, pMap
);
815 // Version schon bekannt => "uberspringen
816 rStream
.SeekRel( nBytes
);
821 rStream
.Seek( nStartPos
);
822 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_ITEMS
);
823 FASTBOOL bSecondaryLoaded
= FALSE
;
824 long nSecondaryEnd
= 0;
825 USHORT nWhich
, nSlot
;
826 while ( rStream
>> nWhich
, nWhich
)
828 // ggf. Which-Id aus alter Version verschieben?
829 if ( pImp
->nLoadingVersion
!= pImp
->nVersion
)
830 nWhich
= GetNewWhich( nWhich
);
833 USHORT nMappedWhich
= GetWhich(nSlot
, FALSE
);
834 int bKnownItem
= bOwnPool
|| IsWhich(nMappedWhich
);
836 USHORT nRef
, nCount
, nVersion
;
837 sal_uInt32 nAttrSize
;
838 rStream
>> nVersion
>> nCount
;
840 SfxPoolItemArray_Impl
**ppArr
= 0;
841 SfxPoolItemArray_Impl
*pNewArr
= 0;
842 SfxPoolItem
*pDefItem
= 0;
846 nWhich
= nMappedWhich
;
848 //!SFX_ASSERTWARNING( !nSlot || !HasMap() ||
849 //! ( nSlot == GetSlotId( nWhich, FALSE ) ) ||
850 //! !GetSlotId( nWhich, FALSE ),
851 //! nWhich, "Slot/Which mismatch" );
853 USHORT nIndex
= GetIndex_Impl(nWhich
);
854 ppArr
= pImp
->ppPoolItems
+ nIndex
;
855 pNewArr
= new SfxPoolItemArray_Impl( nCount
);
856 pDefItem
= *(ppStaticDefaults
+ nIndex
);
859 // Position vor ersten Item merken
860 ULONG nLastPos
= rStream
.Tell();
862 // SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
863 if ( !bSecondaryLoaded
&& pSecondary
&& pDefItem
->ISA(SfxSetItem
) )
865 // an das Ende des eigenen Pools seeken
866 rStream
.Seek(nEndOfSizes
);
867 CHECK_FILEFORMAT_RELEASE( rStream
, SFX_ITEMPOOL_TAG_ENDPOOL
, pNewArr
);
868 CHECK_FILEFORMAT_RELEASE( rStream
, SFX_ITEMPOOL_TAG_ENDPOOL
, pNewArr
);
870 // Sekund"arpool einlesen
871 pSecondary
->Load1_Impl( rStream
);
872 bSecondaryLoaded
= TRUE
;
873 nSecondaryEnd
= rStream
.Tell();
875 // zur"uck zu unseren eigenen Items
876 rStream
.Seek(nLastPos
);
879 // Items an sich lesen
880 for ( USHORT j
= 0; j
< nCount
; ++j
)
882 ULONG nPos
= nLastPos
;
887 SfxPoolItem
*pItem
= 0;
890 pItem
= pDefItem
->Create(rStream
, nVersion
);
892 if ( !bPersistentRefCounts
)
893 // bis <SfxItemPool::LoadCompleted()> festhalten
897 if ( nRef
> SFX_ITEMS_OLD_MAXREF
)
898 pItem
->SetKind( nRef
);
900 AddRef(*pItem
, nRef
);
904 pNewArr
->C40_INSERT( SfxPoolItem
, pItem
, j
);
906 // restliche gespeicherte Laenge skippen (neueres Format)
907 nLastPos
= rStream
.Tell();
910 aSizeTable
>> nAttrSize
;
911 SFX_ASSERT( !bKnownItem
|| ( nPos
+ nAttrSize
) >= nLastPos
,
913 "too many bytes read - version mismatch?" );
915 if ( !bKnownItem
|| ( nLastPos
< (nPos
+ nAttrSize
) ) )
917 nLastPos
= nPos
+ nAttrSize
;
918 rStream
.Seek( nLastPos
);
924 SfxPoolItemArray_Impl
*pOldArr
= *ppArr
;
927 // die Items merken, die schon im Pool sind
930 for ( USHORT n
= 0; bEmpty
&& n
< pOldArr
->Count(); ++n
)
931 bEmpty
= pOldArr
->GetObject(n
) == 0;
932 DBG_ASSERTWARNING( bEmpty
, "loading non-empty pool" );
935 // f"ur alle alten suchen, ob ein gleiches neues existiert
936 for ( USHORT nOld
= 0; nOld
< pOldArr
->Count(); ++nOld
)
938 SfxPoolItem
*pOldItem
= (*pOldArr
)[nOld
];
942 for ( USHORT nNew
= 0;
943 !bFound
&& nNew
< (*ppArr
)->Count();
946 SfxPoolItem
*&rpNewItem
=
947 (SfxPoolItem
*&)(*ppArr
)->GetData()[nNew
];
949 if ( rpNewItem
&& *rpNewItem
== *pOldItem
)
951 AddRef( *pOldItem
, rpNewItem
->GetRefCount() );
952 SetRefCount( *rpNewItem
, 0 );
954 rpNewItem
= pOldItem
;
956 SFX_TRACE( "reusing item", pOldItem
);
959 //! DBG_ASSERT( bFound, "old-item not found in file" );
962 SFX_TRACE( "item not found: ", pOldItem
);
967 delete pOldArr
; /* @@@ */
971 // Pool-Defaults lesen
972 if ( pImp
->nMajorVer
> 1 || pImp
->nMinorVer
> 0 )
973 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_DEFAULTS
);
975 ULONG nLastPos
= rStream
.Tell();
976 while ( rStream
>> nWhich
, nWhich
)
978 // ggf. Which-Id aus alter Version verschieben?
979 if ( pImp
->nLoadingVersion
!= pImp
->nVersion
)
980 nWhich
= GetNewWhich( nWhich
);
983 USHORT nMappedWhich
= GetWhich(nSlot
, FALSE
);
984 int bKnownItem
= bOwnPool
|| IsWhich(nMappedWhich
);
986 ULONG nPos
= nLastPos
;
994 nWhich
= nMappedWhich
;
996 ( *( ppStaticDefaults
+ GetIndex_Impl(nWhich
) ) )
997 ->Create( rStream
, nVersion
);
998 pItem
->SetKind( SFX_ITEMS_POOLDEFAULT
);
999 *( ppPoolDefaults
+ GetIndex_Impl(nWhich
) ) = pItem
;
1002 nLastPos
= rStream
.Tell();
1003 aSizeTable
>> nSize
;
1004 SFX_ASSERT( ( nPos
+ nSize
) >= nLastPos
, nPos
,
1005 "too many bytes read - version mismatch?" );
1006 if ( nLastPos
< (nPos
+ nSize
) )
1007 rStream
.Seek( nPos
+ nSize
);
1011 rStream
.Seek(nEndOfSizes
);
1012 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_ENDPOOL
);
1013 CHECK_FILEFORMAT( rStream
, SFX_ITEMPOOL_TAG_ENDPOOL
);
1017 if ( !bSecondaryLoaded
)
1018 pSecondary
->Load1_Impl( rStream
);
1020 rStream
.Seek( nSecondaryEnd
);
1023 if ( aExternName
!= aName
)
1026 pImp
->bStreaming
= FALSE
;
1030 // -----------------------------------------------------------------------
1032 const SfxPoolItem
* SfxItemPool::LoadSurrogate
1034 SvStream
& rStream
, // vor einem Surrogat positionierter Stream
1035 USHORT
& rWhich
, // Which-Id des zu ladenden <SfxPoolItem>s
1036 USHORT nSlotId
, // Slot-Id des zu ladenden <SfxPoolItem>s
1037 const SfxItemPool
* pRefPool
// <SfxItemPool> in dem das Surrogat gilt
1042 L"adt Surrogat aus 'rStream' und liefert das dadurch in 'rRefPool'
1043 repr"asentierte SfxPoolItem zu"ruck. Ist das im Stream befindliche
1044 Surrogat == SFX_ITEMS_DIRECT (!SFX_ITEM_POOLABLE) wird 0 zur"uckgegeben,
1045 das Item ist direkt aus dem Stream zu laden. Bei 0xfff0 (SFX_ITEMS_NULL)
1046 wird auch 0 zurueckgegeben und rWhich auf 0 gesetzt, das Item ist nicht
1049 Ansonsten wird ber"ucksichtigt, ob der betroffene Pool ohne Ref-Counts
1050 geladen wird, ob aus einem neuen Pool nachgeladen wird (&rRefPool != this)
1051 oder ob aus einem g"anzlich anders aufgebauten Pool geladen wird.
1053 Wird aus einem anders aufgebauten Pool geladen und die 'nSlotId' kann
1054 nicht in eine Which-Id dieses Pools gemappt werden, wird ebenfalls 0
1057 Preconditions: - Pool mu\s geladen sein
1058 - LoadCompleted darf noch nicht gerufen worden sein
1059 - 'rStream' steht genau an der Position, an der ein
1060 Surrogat f"ur ein Item mit der SlotId 'nSlotId' und
1061 der WhichId 'rWhichId' mit StoreSurrogate gepeichert
1064 Postconditions: - 'rStream' ist so positioniert, wie auch StoreSurrogate
1065 sein speichern beendet hatte
1066 - konnte ein Item geladen werden, befindet es sich
1067 in diesem SfxItemPool
1068 - 'rWhichId' enth"alt die ggf. gemappte Which-Id
1069 Laufzeit: Tiefe des Ziel Sekund"arpools * 10 + 10
1073 <SfxItemPool::StoreSurrogate(SvStream&,const SfxPoolItem &)const>
1077 // erstmal das Surrogat lesen
1079 rStream
>> nSurrogat
;
1081 // direkt gespeichertes Item?
1082 if ( SFX_ITEMS_DIRECT
== nSurrogat
)
1085 // nicht vorhandenes Item?
1086 if ( SFX_ITEMS_NULL
== nSurrogat
)
1092 // Bei einem identisch aufgebauten Pool (im Stream) kann das Surrogat
1093 // auf jeden Fall aufgel"ost werden.
1096 FASTBOOL bResolvable
= pRefPool
->GetName().Len() > 0;
1099 // Bei einem anders aufgebauten Pool im Stream, mu\s die SlotId
1100 // aus dem Stream in eine Which-Id gemappt werden k"onnen.
1101 USHORT nMappedWhich
= nSlotId
? GetWhich(nSlotId
, TRUE
) : 0;
1102 if ( IsWhich(nMappedWhich
) )
1104 // gemappte SlotId kann "ubernommen werden
1105 rWhich
= nMappedWhich
;
1110 // kann Surrogat aufgel"ost werden?
1111 const SfxPoolItem
*pItem
= 0;
1114 for ( SfxItemPool
*pTarget
= this; pTarget
; pTarget
= pTarget
->pSecondary
)
1116 // richtigen (Folge-) Pool gefunden?
1117 if ( pTarget
->IsInRange(rWhich
) )
1120 if ( SFX_ITEMS_STATICDEFAULT
== nSurrogat
)
1121 return *(pTarget
->ppStaticDefaults
+
1122 pTarget
->GetIndex_Impl(rWhich
));
1124 SfxPoolItemArray_Impl
* pItemArr
= *(pTarget
->pImp
->ppPoolItems
+
1125 pTarget
->GetIndex_Impl(rWhich
));
1126 pItem
= pItemArr
&& nSurrogat
< pItemArr
->Count()
1127 ? (*pItemArr
)[nSurrogat
]
1131 DBG_ERROR( "can't resolve surrogate" );
1132 rWhich
= 0; // nur zur Sicherheit fuer richtige Stream-Pos
1136 // Nachladen aus Ref-Pool?
1137 if ( pRefPool
!= pMaster
)
1138 return &pTarget
->Put( *pItem
);
1140 // Referenzen sind NICHT schon mit Pool geladen worden?
1141 if ( !pTarget
->HasPersistentRefCounts() )
1142 AddRef( *pItem
, 1 );
1150 SFX_ASSERT( FALSE
, rWhich
, "can't resolve Which-Id in LoadSurrogate" );
1156 //-------------------------------------------------------------------------
1159 FASTBOOL
SfxItemPool::StoreSurrogate
1162 const SfxPoolItem
* pItem
1167 Speichert ein Surrogat f"ur '*pItem' in 'rStream'.
1173 es wurde ein echtes Surrogat gespeichert, auch
1174 SFX_ITEMS_NULL bei 'pItem==0',
1175 SFX_ITEMS_STATICDEFAULT und SFX_ITEMS_POOLDEFAULT
1176 gelten als 'echte' Surrogate
1179 es wurde ein Dummy-Surrogat (SFX_ITEMS_DIRECT)
1180 gespeichert, das eigentliche Item mu\s direkt
1181 hinterher selbst gespeichert werden
1187 FASTBOOL bRealSurrogate
= IsItemFlag(*pItem
, SFX_ITEM_POOLABLE
);
1188 rStream
<< ( bRealSurrogate
1189 ? GetSurrogate( pItem
)
1190 : (UINT16
) SFX_ITEMS_DIRECT
);
1191 return bRealSurrogate
;
1194 rStream
<< (UINT16
) SFX_ITEMS_NULL
;
1198 // -----------------------------------------------------------------------
1200 USHORT
SfxItemPool::GetSurrogate(const SfxPoolItem
*pItem
) const
1202 DBG_CHKTHIS(SfxItemPool
, 0);
1203 DBG_ASSERT( pItem
, "no 0-Pointer Surrogate" );
1204 DBG_ASSERT( !IsInvalidItem(pItem
), "no Invalid-Item Surrogate" );
1205 DBG_ASSERT( !IsPoolDefaultItem(pItem
), "no Pool-Default-Item Surrogate" );
1207 if ( !IsInRange(pItem
->Which()) )
1210 return pSecondary
->GetSurrogate( pItem
);
1211 SFX_ASSERT( 0, pItem
->Which(), "unknown Which-Id - dont ask me for surrogates" );
1214 // Pointer auf static- oder pool-dflt-Attribut?
1215 if( IsStaticDefaultItem(pItem
) || IsPoolDefaultItem(pItem
) )
1216 return SFX_ITEMS_STATICDEFAULT
;
1218 SfxPoolItemArray_Impl
* pItemArr
= *(pImp
->ppPoolItems
+ GetIndex_Impl(pItem
->Which()));
1219 DBG_ASSERT(pItemArr
, "ItemArr nicht vorhanden");
1220 const USHORT nCount
= pItemArr
->Count();
1221 for ( USHORT i
= 0; i
< nCount
; ++i
)
1223 const SfxPoolItem
*p
= (*pItemArr
)[i
];
1227 SFX_ASSERT( 0, pItem
->Which(), "Item nicht im Pool");
1228 return SFX_ITEMS_NULL
;
1231 // -----------------------------------------------------------------------
1233 FASTBOOL
SfxItemPool::IsInStoringRange( USHORT nWhich
) const
1235 return nWhich
>= pImp
->nStoringStart
&&
1236 nWhich
<= pImp
->nStoringEnd
;
1239 //------------------------------------------------------------------------
1241 void SfxItemPool::SetStoringRange( USHORT nFrom
, USHORT nTo
)
1245 Mit dieser Methode kann der Which-Bereich eingeengt werden, der
1246 von ItemSets dieses Pool (und dem Pool selbst) gespeichert wird.
1247 Die Methode muss dazu vor <SfxItemPool::Store()> gerufen werden
1248 und die Werte muessen auch noch gesetzt sein, wenn das eigentliche
1249 Dokument (also die ItemSets gespeicher werden).
1251 Ein Zuruecksetzen ist dann nicht noetig, wenn dieser Range vor
1252 JEDEM Speichern richtig gesetzt wird, da er nur beim Speichern
1253 beruecksichtigt wird.
1255 Dieses muss fuer das 3.1-Format gemacht werden, da dort eine
1256 Bug in der Pool-Lade-Methode vorliegt.
1260 pImp
->nStoringStart
= nFrom
;
1261 pImp
->nStoringEnd
= nTo
;
1264 // -----------------------------------------------------------------------
1266 void SfxItemPool::SetVersionMap
1268 USHORT nVer
, /* neue Versionsnummer */
1269 USHORT nOldStart
, /* alte erste Which-Id */
1270 USHORT nOldEnd
, /* alte letzte Which-Id */
1271 USHORT
* pOldWhichIdTab
/* Array mit genau dem Aufbau der Which-Ids
1272 der vorhergehenden Version, in denen
1273 die jeweils neue Which-Id steht. */
1278 Mit dieser Methode k"onnen neue, inkompatible Which-Id-Folgen oder
1279 Verteilungen realisiert werden. Pools, die noch mit alten Versionen
1280 gespeichert wurden, werden dann "uber die angegebene Tabelle solange
1281 gemappt, bis die aktuelle Version erreicht ist. Neuere Pools k"onnen
1282 unter Verlust neuer Attribute geladen werden, da die Map mit dem Pool
1285 Precondition: Pool darf noch nicht geladen sein
1286 Postcondition: Which-Ids aus fr"uheren Versionen k"onnen bei Laden auf
1287 Version 'nVer' gemappt werden
1288 Laufzeit: 1.5 * new + 10
1292 F"ur neue Which-Ranges (nStart,nEnd) m"ssen im Vergleich zur Vorg"anger-
1293 Version (nOldStart,nOldEnd) immer gelten, da\s (nOldStart,nOldEnd)
1294 vollst"andig in (nStart,nEnd) enthalten ist. Es ist also zul"assig, den
1295 Which-Range in beide Richtungen zu erweitern, auch durch Einf"ugung
1296 von Which-Ids, nicht aber ihn zu beschneiden.
1298 Diese Methode sollte nur im oder direkt nach Aufruf des Konstruktors
1301 Das Array mu\s statisch sein, da es nicht kopiert wird und au\serdem
1302 im Copy-Ctor des SfxItemPool wiederverwendet wird.
1307 Urspr"unglich (Version 0) hatte der Pool folgende Which-Ids:
1311 Nun soll eine neue Version (Version 1) zwei zus"atzliche Ids X und Y
1312 zwischen B und C erhalten, also wie folgt aussehen:
1314 1:A, 2:B, 3:X, 4:Y, 5:C, 6:D
1316 Dabei haben sich also die Ids 3 und 4 ge"andert. F"ur die neue Version
1317 m"u\ste am Pool folgendes gesetzt werden:
1319 static USHORT nVersion1Map = { 1, 2, 5, 6 };
1320 pPool->SetVersionMap( 1, 1, 4, &nVersion1Map );
1325 <SfxItemPool::IsLoadingVersionCurrent()const>
1326 <SfxItemPool::GetNewWhich(USHORT)>
1327 <SfxItemPool::GetVersion()const>
1328 <SfxItemPool::GetLoadingVersion()const>
1332 // neuen Map-Eintrag erzeugen und einf"ugen
1333 const SfxPoolVersion_Impl
*pVerMap
= new SfxPoolVersion_Impl(
1334 nVer
, nOldStart
, nOldEnd
, pOldWhichIdTab
);
1335 pImp
->aVersions
.Insert( pVerMap
, pImp
->aVersions
.Count() );
1337 DBG_ASSERT( nVer
> pImp
->nVersion
, "Versions not sorted" );
1338 pImp
->nVersion
= nVer
;
1340 // Versions-Range anpassen
1341 for ( USHORT n
= 0; n
< nOldEnd
-nOldStart
+1; ++n
)
1343 USHORT nWhich
= pOldWhichIdTab
[n
];
1344 if ( nWhich
< pImp
->nVerStart
)
1348 pImp
->nVerStart
= nWhich
;
1350 else if ( nWhich
> pImp
->nVerEnd
)
1351 pImp
->nVerEnd
= nWhich
;
1355 // -----------------------------------------------------------------------
1357 USHORT
SfxItemPool::GetNewWhich
1359 USHORT nFileWhich
// die aus dem Stream geladene Which-Id
1364 Diese Methoden rechnet Which-Ids aus einem File-Format in die der
1365 aktuellen Pool-Version um. Ist das File-Format "alter, werden die vom
1366 Pool-Entwickler mit SetVersion() gesetzten Tabellen verwendet,
1367 ist das File-Format neuer, dann die aus dem File geladenen Tabellen.
1368 Im letzteren Fall kann ggf. nicht jede Which-Id gemappt werden,
1369 so da\s 0 zur"uckgeliefert wird.
1371 Die Berechnung ist nur f"ur Which-Ids definiert, die in der betreffenden
1372 File-Version unterst"utzt wurden. Dies ist per Assertion abgesichert.
1374 Precondition: Pool mu\s geladen sein
1375 Postcondition: unver"andert
1376 Laufzeit: linear(Anzahl der Sekund"arpools) +
1377 linear(Differenz zwischen alter und neuer Version)
1382 <SfxItemPool::IsLoadingVersionCurrent()const>
1383 <SfxItemPool::SetVersionMap(USHORT,USHORT,USHORT,USHORT*)>
1384 <SfxItemPool::GetVersion()const>
1385 <SfxItemPool::GetLoadingVersion()const>
1389 // (Sekund"ar-) Pool bestimmen
1390 if ( !IsInVersionsRange(nFileWhich
) )
1393 return pSecondary
->GetNewWhich( nFileWhich
);
1394 SFX_ASSERT( 0, nFileWhich
, "unknown which in GetNewWhich()" );
1397 // Version neuer/gleich/"alter?
1398 short nDiff
= (short)pImp
->nLoadingVersion
- (short)pImp
->nVersion
;
1400 // Which-Id einer neueren Version?
1403 // von der Top-Version bis runter zur File-Version stufenweise mappen
1404 for ( USHORT nMap
= pImp
->aVersions
.Count(); nMap
> 0; --nMap
)
1406 SfxPoolVersion_Impl
*pVerInfo
= pImp
->aVersions
[nMap
-1];
1407 if ( pVerInfo
->_nVer
> pImp
->nVersion
)
1409 USHORT nCount
= pVerInfo
->_nEnd
- pVerInfo
->_nStart
+ 1;
1412 pVerInfo
->_pMap
[nOfs
] != nFileWhich
;
1416 if ( pVerInfo
->_pMap
[nOfs
] == nFileWhich
)
1417 nFileWhich
= pVerInfo
->_nStart
+ nOfs
;
1426 // Which-Id einer neueren Version?
1427 else if ( nDiff
< 0 )
1429 // von der File-Version bis zur aktuellen Version stufenweise mappen
1430 for ( USHORT nMap
= 0; nMap
< pImp
->aVersions
.Count(); ++nMap
)
1432 SfxPoolVersion_Impl
*pVerInfo
= pImp
->aVersions
[nMap
];
1433 if ( pVerInfo
->_nVer
> pImp
->nLoadingVersion
)
1435 DBG_ASSERT( nFileWhich
>= pVerInfo
->_nStart
&&
1436 nFileWhich
<= pVerInfo
->_nEnd
,
1437 "which-id unknown in version" );
1438 nFileWhich
= pVerInfo
->_pMap
[nFileWhich
- pVerInfo
->_nStart
];
1443 // originale (nDiff==0) bzw. gemappte (nDiff!=0) Id zur"uckliefern
1447 // -----------------------------------------------------------------------
1450 FASTBOOL
SfxItemPool::IsInVersionsRange( USHORT nWhich
) const
1452 return nWhich
>= pImp
->nVerStart
&& nWhich
<= pImp
->nVerEnd
;
1455 // -----------------------------------------------------------------------
1457 FASTBOOL
SfxItemPool::IsCurrentVersionLoading() const
1461 Mit dieser Methode kann festgestellt werden, ob die geladene Pool-Version
1462 dem aktuellen Pool-Aufbau entspricht.
1464 Precondition: Pool mu\s geladen sein
1465 Postcondition: unver"andert
1466 Laufzeit: linear(Anzahl der Sekund"arpools)
1471 <SfxItemPool::SetVersionMap(USHORT,USHORT,USHORT,USHORT*)>
1472 <SfxItemPool::GetNewWhich(USHORT)const>
1473 <SfxItemPool::GetVersion()const>
1474 <SfxItemPool::GetLoadingVersion()const>
1478 return ( pImp
->nVersion
== pImp
->nLoadingVersion
) &&
1479 ( !pSecondary
|| pSecondary
->IsCurrentVersionLoading() );
1482 // -----------------------------------------------------------------------
1484 USHORT
SfxItemPool::GetVersion() const
1488 Diese Methode liefert die aktuelle Versionsnummer des SfxItemPool-Aufbaus
1489 (also des Which-Bereichs).
1492 Postcondition: unver"andert
1498 Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools
1499 ber"ucksichtigt werden.
1504 <SfxItemPool::IsLoadingVersionCurrent()const>
1505 <SfxItemPool::SetVersionMap(USHORT,USHORT,USHORT,USHORT*)>
1506 <SfxItemPool::GetNewWhich(USHORT)const>
1507 <SfxItemPool::GetLoadingVersion()const>
1511 return pImp
->nVersion
;
1514 // -----------------------------------------------------------------------
1516 USHORT
SfxItemPool::GetLoadingVersion() const
1520 Diese Methode liefert die Versionsnummer des SfxItemPool-Aufbaus
1521 (also des Which-Bereichs), die bei Laden vorgefunden wurde.
1523 Precondition: Pool mu\s geladen sein
1524 Postcondition: unver"andert
1530 Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools
1531 ber"ucksichtigt werden.
1536 <SfxItemPool::IsLoadingVersionCurrent()const>
1537 <SfxItemPool::SetVersionMap(USHORT,USHORT,USHORT,USHORT*)>
1538 <SfxItemPool::GetNewWhich(USHORT)const>
1539 <SfxItemPool::GetVersion()const>
1543 return pImp
->nLoadingVersion
;
1546 //-------------------------------------------------------------------------
1548 FASTBOOL
SfxItemPool::IsVer2_Impl() const
1550 return pMaster
->pImp
->nMajorVer
>= 2;
1553 //-------------------------------------------------------------------------
1556 FASTBOOL
SfxItemPool::StoreItem( SvStream
&rStream
, const SfxPoolItem
&rItem
,
1557 FASTBOOL bDirect
) const
1561 Speichert das <SfxPoolItem> 'rItem' in den <SvStream> 'rStream'
1562 entweder als Surrogat ('bDirect == FALSE') oder direkt mit 'rItem.Store()'.
1563 Nicht poolable Items werden immer direkt gespeichert. Items ohne Which-Id,
1564 also SID-Items, werden nicht gespeichert, ebenso wenn Items, die in der
1565 File-Format-Version noch nicht vorhanden waren (return FALSE).
1567 Das Item wird im Stream wie folgt abgelegt:
1569 USHORT rItem.Which()
1570 USHORT GetSlotId( rItem.Which() ) bzw. 0 falls nicht verf"urbar
1571 USHORT GetSurrogate( &rItem ) bzw. SFX_ITEM_DIRECT bei '!SFX_ITEM_POOLBLE'
1573 optional (falls 'bDirect == TRUE' oder '!rItem.IsPoolable()':
1575 USHORT rItem.GetVersion()
1582 <SfxItemPool::LoadItem(SvStream&,FASTBOOL)const>
1586 DBG_ASSERT( !IsInvalidItem(&rItem
), "cannot store invalid items" );
1588 if ( IsSlot( rItem
.Which() ) )
1590 const SfxItemPool
*pPool
= this;
1591 while ( !pPool
->IsInStoringRange(rItem
.Which()) )
1592 if ( 0 == ( pPool
= pPool
->pSecondary
) )
1595 DBG_ASSERT( !pImp
->bInSetItem
|| !rItem
.ISA(SfxSetItem
),
1596 "SetItem contains ItemSet with SetItem" );
1598 USHORT nSlotId
= pPool
->GetSlotId( rItem
.Which(), TRUE
);
1599 USHORT nItemVersion
= rItem
.GetVersion(_nFileFormatVersion
);
1600 if ( USHRT_MAX
== nItemVersion
)
1603 rStream
<< rItem
.Which() << nSlotId
;
1604 if ( bDirect
|| !pPool
->StoreSurrogate( rStream
, &rItem
) )
1606 rStream
<< nItemVersion
;
1607 rStream
<< (UINT32
) 0L; // Platz fuer Laenge in Bytes
1608 ULONG nIStart
= rStream
.Tell();
1609 rItem
.Store(rStream
, nItemVersion
);
1610 ULONG nIEnd
= rStream
.Tell();
1611 rStream
.Seek( nIStart
-4 );
1612 rStream
<< (INT32
) ( nIEnd
-nIStart
);
1613 rStream
.Seek( nIEnd
);
1619 //-------------------------------------------------------------------------
1622 const SfxPoolItem
* SfxItemPool::LoadItem( SvStream
&rStream
, FASTBOOL bDirect
,
1623 const SfxItemPool
*pRefPool
)
1625 // pRefPool==-1 => nicht putten!
1628 USHORT nWhich
, nSlot
; // nSurrogate;
1629 rStream
>> nWhich
>> nSlot
;
1631 BOOL bDontPut
= (SfxItemPool
*)-1 == pRefPool
;
1632 if ( bDontPut
|| !pRefPool
)
1635 // richtigen Sekund"ar-Pool finden
1636 while ( !pRefPool
->IsInVersionsRange(nWhich
) )
1638 if ( pRefPool
->pSecondary
)
1639 pRefPool
= pRefPool
->pSecondary
;
1642 // WID in der Version nicht vorhanden => ueberspringen
1643 USHORT nSurro
, nVersion
, nLen
;
1645 if ( SFX_ITEMS_DIRECT
== nSurro
)
1647 rStream
>> nVersion
>> nLen
;
1648 rStream
.SeekRel( nLen
);
1654 // wird eine andere Version geladen?
1655 FASTBOOL bCurVersion
= pRefPool
->IsCurrentVersionLoading();
1657 // Which-Id auf neue Version mappen
1658 nWhich
= pRefPool
->GetNewWhich( nWhich
);
1660 DBG_ASSERT( !nWhich
|| !pImp
->bInSetItem
||
1661 !pRefPool
->ppStaticDefaults
[pRefPool
->GetIndex_Impl(nWhich
)]->ISA(SfxSetItem
),
1662 "loading SetItem in ItemSet of SetItem" );
1664 // soll "uber Surrogat geladen werden?
1665 const SfxPoolItem
*pItem
= 0;
1668 // Which-Id in dieser Version bekannt?
1670 // Surrogat laden, reagieren falls keins vorhanden
1671 pItem
= LoadSurrogate( rStream
, nWhich
, nSlot
, pRefPool
);
1673 // sonst "uberspringen
1674 rStream
.SeekRel( sizeof(USHORT
) );
1677 // wird direkt, also nicht "uber Surrogat geladen?
1678 if ( bDirect
|| ( nWhich
&& !pItem
) )
1680 // bDirekt bzw. nicht IsPoolable() => Item direkt laden
1683 rStream
>> nVersion
>> nLen
;
1684 ULONG nIStart
= rStream
.Tell();
1686 // Which-Id in dieser Version bekannt?
1689 // Item direkt laden
1690 SfxPoolItem
*pNewItem
=
1691 pRefPool
->GetDefaultItem(nWhich
).Create(rStream
, nVersion
);
1697 pItem
= &Put(*pNewItem
);
1702 ULONG nIEnd
= rStream
.Tell();
1703 DBG_ASSERT( nIEnd
<= (nIStart
+nLen
), "read past end of item" );
1704 if ( (nIStart
+nLen
) != nIEnd
)
1705 rStream
.Seek( nIStart
+nLen
);
1708 // Item "uberspringen
1709 rStream
.Seek( nIStart
+nLen
);