xref: /aoo41x/main/svl/source/items/poolio.cxx (revision 6fb30688)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svl.hxx"
30 
31 #include <string.h>
32 #include <stdio.h>
33 
34 #ifndef GCC
35 #endif
36 
37 #include <tools/solar.h>
38 #include <svl/itempool.hxx>
39 #include "whassert.hxx"
40 #include <svl/brdcst.hxx>
41 #include <svl/filerec.hxx>
42 #include <svl/svldata.hxx>
43 #include "poolio.hxx"
44 
45 // STATIC DATA -----------------------------------------------------------
46 
47 DBG_NAME(SfxItemPool);
48 
49 //========================================================================
50 
51 void SfxItemPool::SetStoringPool( const SfxItemPool *pStoringPool )
52 
53 /*	[Beschreibung]
54 
55 	Diese Methode setzt den <SfxItemPool>, der gerade gespeichert wird.
56 	Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format-
57 	Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines
58 	<SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen
59 	Pool mit <SfxItemPool::GetStoringPool()> zu besorgen.
60 
61 	Sie wird von <SfxItemPool::Store()> bedient, kann jedoch f"ur nicht
62 	poolable Items auch direkt gerufen werden. Bitte m"oglichst nicht
63 	f"ur jedes Item einzeln, da 2 Calls!
64 */
65 
66 {
67 	ImpSvlData::GetSvlData().pStoringPool = pStoringPool;
68 }
69 
70 //-------------------------------------------------------------------------
71 
72 const SfxItemPool* SfxItemPool::GetStoringPool()
73 
74 /*	[Beschreibung]
75 
76 	Diese Methode liefert den <SfxItemPool>, der gerade gespeichert wird.
77 	Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format-
78 	Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines
79 	<SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen
80 	Pool zu besorgen.
81 */
82 
83 {
84 	return ImpSvlData::GetSvlData().pStoringPool;
85 }
86 
87 //-------------------------------------------------------------------------
88 
89 SvStream &SfxItemPool::Store(SvStream &rStream) const
90 
91 /*	[Beschreibung]
92 
93 	Der SfxItemPool wird inklusive aller seiner Sekund"arpools mit
94 	Pool-Defaults und gepoolten Items in dem angegebenen Stream gespeichert.
95 	Die statischen Defaults werden nicht gespeichert.
96 
97 
98 	[Fileformat]
99 
100 	;zun"achst ein Kompatiblit"ats-Header-Block
101 	Start:		0x1111	SFX_ITEMPOOL_TAG_STARTPOOLS(_4/_5)
102 				sal_uInt8	MAJOR_VER					;SfxItemPool-Version
103 				sal_uInt8	MINOR_VER					;"
104 				0xFFFF	SFX_ITEMPOOL_TAG_TRICK4OLD  ;ex. GetVersion()
105 				sal_uInt16	0x0000						;Pseudo-StyleSheetPool
106 				sal_uInt16	0x0000						;Pseudo-StyleSheetPool
107 
108 	;den ganzen Pool in einen Record
109 				record	SfxMiniRecod(SFX_ITEMPOOL_REC)
110 
111 	;je ein Header vorweg
112 	Header:		record  	SfxMiniRecord(SFX_ITEMPOOL_REC_HEADER)
113 				sal_uInt16			GetVersion()			;Which-Ranges etc.
114 				String			GetName()				;Pool-Name
115 
116 	;die Versions-Map, um WhichIds neuer File-Versionen mappen zu k"onnen
117 	Versions:	record	    SfxMultiRecord(SFX_ITEMPOOL_REC_VERSIONS, 0)
118 				sal_uInt16			OldVersion
119 				sal_uInt16			OldStartWhich
120 				sal_uInt16			OldEndWhich
121 				sal_uInt16[]        NewWhich (OldEndWhich-OldStartWhich+1)
122 
123 	;jetzt die gepoolten Items (zuerst nicht-SfxSetItems)
124 	Items:  	record      SfxMultiRecord(SFX_ITEMPOOL_REC_WHICHIDS, 0)
125 				content 		SlotId, 0
126 				sal_uInt16			WhichId
127 				sal_uInt16			pItem->GetVersion()
128 				sal_uInt16			Array-Size
129 				record			SfxMultiRecord(SFX_, 0)
130 				content				Surrogate
131 				sal_uInt16				RefCount
132 				unknown 			pItem->Store()
133 
134 	;jetzt die gesetzten Pool-Defaults
135 	Defaults:	record	    SfxMultiRecord(SFX_ITEMPOOL_REC_DEFAULTS, 0)
136 				content			SlotId, 0
137 				sal_uInt16			WhichId
138 				sal_uInt16			pPoolDef->GetVersion()
139 				unknown			pPoolDef->Store();
140 
141 	;dahinter folgt ggf. der Secondary ohne Kompatiblit"ats-Header-Block
142 */
143 
144 {
145 	DBG_CHKTHIS(SfxItemPool, 0);
146 
147 	// Store-Master finden
148 	SfxItemPool *pStoreMaster = pMaster != this ? pMaster : 0;
149 	while ( pStoreMaster && !pStoreMaster->pImp->bStreaming )
150 		pStoreMaster = pStoreMaster->pSecondary;
151 
152 	// Alter-Header (Version des Pools an sich und Inhalts-Version 0xffff)
153 	pImp->bStreaming = sal_True;
154 	if ( !pStoreMaster )
155 	{
156 		rStream << ( rStream.GetVersion() >= SOFFICE_FILEFORMAT_50
157 				? SFX_ITEMPOOL_TAG_STARTPOOL_5
158 				: SFX_ITEMPOOL_TAG_STARTPOOL_4 );
159 		rStream << SFX_ITEMPOOL_VER_MAJOR << SFX_ITEMPOOL_VER_MINOR;
160 		rStream << SFX_ITEMPOOL_TAG_TRICK4OLD;
161 
162 		// SfxStyleSheet-Bug umgehen
163 		rStream << sal_uInt16(0); // Version
164 		rStream << sal_uInt16(0); // Count (2. Schleife f"allt sonst auf die Fresse)
165 	}
166 
167 	// jeder Pool ist als ganzes ein Record
168 	SfxMiniRecordWriter aPoolRec( &rStream, SFX_ITEMPOOL_REC );
169 	ImpSvlData::GetSvlData().pStoringPool = this;
170 
171 	// Einzel-Header (Version des Inhalts und Name)
172 	{
173 		SfxMiniRecordWriter aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER);
174 		rStream << pImp->nVersion;
175 		SfxPoolItem::writeByteString(rStream, aName);
176 	}
177 
178 	// Version-Maps
179 	{
180 		SfxMultiVarRecordWriter aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP, 0 );
181 		for ( size_t nVerNo = 0; nVerNo < pImp->aVersions.size(); ++nVerNo )
182 		{
183 			aVerRec.NewContent();
184 			SfxPoolVersion_ImplPtr pVer = pImp->aVersions[nVerNo];
185 			rStream << pVer->_nVer << pVer->_nStart << pVer->_nEnd;
186 			sal_uInt16 nCount = pVer->_nEnd - pVer->_nStart + 1;
187 			sal_uInt16 nNewWhich = 0;
188 			for ( sal_uInt16 n = 0; n < nCount; ++n )
189 			{
190 				nNewWhich = pVer->_pMap[n];
191 				rStream << nNewWhich;
192 			}
193 
194 			// Workaround gegen Bug in SetVersionMap der 312
195 			if ( SOFFICE_FILEFORMAT_31 == _nFileFormatVersion )
196 				rStream << sal_uInt16(nNewWhich+1);
197 		}
198 	}
199 
200 	// gepoolte Items
201 	{
202 		SfxMultiMixRecordWriter aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS, 0 );
203 
204 		// erst Atomaren-Items und dann die Sets schreiben (wichtig beim Laden)
205 		for ( pImp->bInSetItem = sal_False; pImp->bInSetItem <= sal_True && !rStream.GetError(); ++pImp->bInSetItem )
206 		{
207 			SfxPoolItemArray_Impl **pArr = pImp->ppPoolItems;
208 			SfxPoolItem **ppDefItem = ppStaticDefaults;
209 			const sal_uInt16 nSize = GetSize_Impl();
210 			for ( size_t i = 0; i < nSize && !rStream.GetError(); ++i, ++pArr, ++ppDefItem )
211 			{
212 				// Version des Items feststellen
213 				sal_uInt16 nItemVersion = (*ppDefItem)->GetVersion( _nFileFormatVersion );
214 				if ( USHRT_MAX == nItemVersion )
215 					// => kam in zu exportierender Version gar nicht vor
216 					continue;
217 
218 				// !poolable wird gar nicht im Pool gespeichert
219 				// und itemsets/plain-items je nach Runde
220 #ifdef TF_POOLABLE
221 				if ( *pArr && IsItemFlag(**ppDefItem, SFX_ITEM_POOLABLE) &&
222 #else
223 				if ( *pArr && (*ppDefItem)->IsPoolable() &&
224 #endif
225 					 pImp->bInSetItem == (*ppDefItem)->ISA(SfxSetItem) )
226 				{
227 					// eigene Kennung, globale Which-Id und Item-Version
228 					sal_uInt16 nSlotId = GetSlotId( (*ppDefItem)->Which(), sal_False );
229 					aWhichIdsRec.NewContent(nSlotId, 0);
230 					rStream << (*ppDefItem)->Which();
231 					rStream << nItemVersion;
232 					const sal_uInt32 nCount = ::std::min<size_t>( (*pArr)->size(), SAL_MAX_UINT32 );
233 					DBG_ASSERT(nCount, "ItemArr is empty");
234 					rStream << nCount;
235 
236 					// Items an sich schreiben
237 					SfxMultiMixRecordWriter aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS, 0 );
238 					for ( size_t j = 0; j < nCount; ++j )
239 					{
240 						// Item selbst besorgen
241 						const SfxPoolItem *pItem = (*pArr)->operator[](j);
242 						if ( pItem && pItem->GetRefCount() ) //! siehe anderes MI-REF
243 						{
244 							aItemsRec.NewContent((sal_uInt16)j, 'X' );
245 
246 							if ( pItem->GetRefCount() == SFX_ITEMS_SPECIAL )
247 								rStream << (sal_uInt16) pItem->GetKind();
248 							else
249 							{
250 								rStream << (sal_uInt16) pItem->GetRefCount();
251 								if( pItem->GetRefCount() > SFX_ITEMS_OLD_MAXREF )
252 									rStream.SetError( ERRCODE_IO_NOTSTORABLEINBINARYFORMAT );
253 							}
254 
255 							if ( !rStream.GetError() )
256 								pItem->Store(rStream, nItemVersion);
257 							else
258 								break;
259 #ifdef DBG_UTIL_MI
260 							if ( !pItem->ISA(SfxSetItem) )
261 							{
262 								sal_uLong nMark = rStream.Tell();
263 								rStream.Seek( nItemStartPos + sizeof(sal_uInt16) );
264 								SfxPoolItem *pClone = pItem->Create(rStream, nItemVersion );
265 								sal_uInt16 nWh = pItem->Which();
266 								SFX_ASSERT( rStream.Tell() == nMark, nWh,"asymmetric store/create" );
267 								SFX_ASSERT( *pClone == *pItem, nWh, "unequal after store/create" );
268 								delete pClone;
269 							}
270 #endif
271 						}
272 					}
273 				}
274 			}
275 		}
276 
277 		pImp->bInSetItem = sal_False;
278 	}
279 
280 	// die gesetzten Defaults speichern (Pool-Defaults)
281 	if ( !rStream.GetError() )
282 	{
283 		SfxMultiMixRecordWriter aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS, 0 );
284 		sal_uInt16 nCount = GetSize_Impl();
285 		for ( sal_uInt16 n = 0; n < nCount; ++n )
286 		{
287 			const SfxPoolItem* pDefaultItem = ppPoolDefaults[n];
288 			if ( pDefaultItem )
289 			{
290 				// Version ermitteln
291 				sal_uInt16 nItemVersion = pDefaultItem->GetVersion( _nFileFormatVersion );
292 				if ( USHRT_MAX == nItemVersion )
293 					// => gab es in der Version noch nicht
294 					continue;
295 
296 				// eigene Kennung, globale Kennung, Version
297 				sal_uInt16 nSlotId = GetSlotId( pDefaultItem->Which(), sal_False );
298 				aDefsRec.NewContent( nSlotId, 0 );
299 				rStream << pDefaultItem->Which();
300 				rStream << nItemVersion;
301 
302 				// Item an sich
303 				pDefaultItem->Store( rStream, nItemVersion );
304 			}
305 		}
306 	}
307 
308 	// weitere Pools rausschreiben
309 	ImpSvlData::GetSvlData().pStoringPool = 0;
310 	aPoolRec.Close();
311 	if ( !rStream.GetError() && pSecondary )
312 		pSecondary->Store( rStream );
313 
314 	pImp->bStreaming = sal_False;
315 	return rStream;
316 }
317 
318 // -----------------------------------------------------------------------
319 
320 void SfxItemPool::LoadCompleted()
321 
322 /*	[Beschreibung]
323 
324 	Wurde der SfxItemPool mit 'bRefCounts' == sal_False geladen, mu\s das
325 	Laden der Dokumentinhalte mit einem Aufruf dieser Methode beendet
326 	werden. Ansonsten hat der Aufruf dieser Methode keine Funktion.
327 
328 
329 	[Anmerkung]
330 
331 	Beim Laden ohne Ref-Counts werden diese tats"achlich auf 1 gesetzt,
332 	damit nicht w"ahrend des Ladevorgangs SfxPoolItems gel"oscht werden,
333 	die danach, aber auch noch beim Ladevorgang, ben"otigt werden. Diese
334 	Methode setzt den Ref-Count wieder zur"uck und entfernt dabei
335 	gleichzeitig alle nicht mehr ben"otigten Items.
336 
337 
338 	[Querverweise]
339 
340 	<SfxItemPool::Load()>
341 */
342 
343 {
344 	// wurden keine Ref-Counts mitgeladen?
345 	if ( pImp->nInitRefCount > 1 )
346 	{
347 
348 		// "uber alle Which-Werte iterieren
349 		SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
350 		for( sal_uInt16 nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr )
351 		{
352 			// ist "uberhaupt ein Item mit dem Which-Wert da?
353 			if ( *ppItemArr )
354 			{
355 				// "uber alle Items mit dieser Which-Id iterieren
356 				SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
357 				for( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
358 					if (*ppHtArr)
359 					{
360                         #ifdef DBG_UTIL
361 						const SfxPoolItem &rItem = **ppHtArr;
362 						DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
363 									0 != &((const SfxSetItem&)rItem).GetItemSet(),
364 									"SetItem without ItemSet" );
365                         #endif
366 
367 						if ( !ReleaseRef( **ppHtArr, 1 ) )
368 							DELETEZ( *ppHtArr );
369 					}
370 			}
371 		}
372 
373 		// from now on normal initial ref count
374 		pImp->nInitRefCount = 1;
375 	}
376 
377 	// notify secondary pool
378 	if ( pSecondary )
379 		pSecondary->LoadCompleted();
380 }
381 
382 //============================================================================
383 // This had to be moved to a method of its own to keep Solaris GCC happy:
384 void SfxItemPool::readTheItems (
385 	SvStream & rStream, sal_uInt32 nItemCount, sal_uInt16 nVersion,
386 	SfxPoolItem * pDefItem, SfxPoolItemArray_Impl ** ppArr)
387 {
388 	SfxMultiRecordReader aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS );
389 
390 	SfxPoolItemArray_Impl *pNewArr = new SfxPoolItemArray_Impl();
391 	SfxPoolItem *pItem = 0;
392 
393 	sal_uLong n, nLastSurrogate = sal_uLong(-1);
394 	while (aItemsRec.GetContent())
395 	{
396 		// n"achstes Surrogat holen
397 		sal_uInt16 nSurrogate = aItemsRec.GetContentTag();
398 		DBG_ASSERT( aItemsRec.GetContentVersion() == 'X',
399 					"not an item content" );
400 
401 		// fehlende auff"ullen
402 		for ( pItem = 0, n = nLastSurrogate+1; n < nSurrogate; ++n )
403 			pNewArr->push_back( (SfxPoolItem*) pItem );
404 		nLastSurrogate = nSurrogate;
405 
406 		// Ref-Count und Item laden
407 		sal_uInt16 nRef(0);
408 		rStream >> nRef;
409 
410 		pItem = pDefItem->Create(rStream, nVersion);
411 		pNewArr->push_back( (SfxPoolItem*) pItem );
412 
413 		if ( !bPersistentRefCounts )
414 			// bis <SfxItemPool::LoadCompleted()> festhalten
415 			AddRef(*pItem, 1);
416 		else
417 		{
418 			if ( nRef > SFX_ITEMS_OLD_MAXREF )
419 				pItem->SetKind( nRef );
420 			else
421 				AddRef(*pItem, nRef);
422 		}
423 	}
424 
425 	// fehlende auff"ullen
426 	for ( pItem = 0, n = nLastSurrogate+1; n < nItemCount; ++n )
427 		pNewArr->push_back( (SfxPoolItem*) pItem );
428 
429 	SfxPoolItemArray_Impl *pOldArr = *ppArr;
430 	*ppArr = pNewArr;
431 
432 	// die Items merken, die schon im Pool sind
433 	bool bEmpty = true;
434 	if ( 0 != pOldArr )
435 		for ( n = 0; bEmpty && n < pOldArr->size(); ++n )
436 			bEmpty = pOldArr->operator[](n) == 0;
437 	DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" );
438 	if ( !bEmpty )
439 	{
440 		// f"ur alle alten suchen, ob ein gleiches neues existiert
441 		for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld )
442 		{
443 			SfxPoolItem *pOldItem = (*pOldArr)[nOld];
444 			if ( pOldItem )
445 			{
446 				sal_uInt32 nFree = SAL_MAX_UINT32;
447 				bool bFound = false;
448 				for ( size_t nNew = (*ppArr)->size(); nNew--; )
449 				{
450 					// geladenes Item
451 					SfxPoolItem *&rpNewItem =
452 						(SfxPoolItem*&)(*ppArr)->operator[](nNew);
453 
454 					// surrogat unbenutzt?
455 					if ( !rpNewItem )
456 						nFree = nNew;
457 
458 					// gefunden?
459 					else if ( *rpNewItem == *pOldItem )
460 					{
461 						// wiederverwenden
462 						AddRef( *pOldItem, rpNewItem->GetRefCount() );
463 						SetRefCount( *rpNewItem, 0 );
464 						delete rpNewItem;
465 						rpNewItem = pOldItem;
466 						bFound = true;
467 						break;
468 					}
469 				}
470 
471 				// vorhervorhandene, nicht geladene uebernehmen
472 				if ( !bFound )
473 				{
474 					if ( nFree != SAL_MAX_UINT32 )
475 						(SfxPoolItem*&)(*ppArr)->operator[](nFree) = pOldItem;
476 					else
477 						(*ppArr)->push_back( (SfxPoolItem*) pOldItem );
478 				}
479 			}
480 		}
481 	}
482 	delete pOldArr;
483 }
484 
485 // -----------------------------------------------------------------------
486 
487 SvStream &SfxItemPool::Load(SvStream &rStream)
488 {
489 	DBG_CHKTHIS(SfxItemPool, 0);
490 	DBG_ASSERT(ppStaticDefaults, "kein DefaultArray");
491 
492 	// protect items by increasing ref count
493 	if ( !bPersistentRefCounts )
494 	{
495 
496 		// "uber alle Which-Werte iterieren
497 		SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems;
498 		for( size_t nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr )
499 		{
500 			// ist "uberhaupt ein Item mit dem Which-Wert da?
501 			if ( *ppItemArr )
502 			{
503 				// "uber alle Items mit dieser Which-Id iterieren
504 				SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin();
505 				for( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr )
506 					if (*ppHtArr)
507 					{
508                         #ifdef DBG_UTIL
509 						const SfxPoolItem &rItem = **ppHtArr;
510 						DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
511 									0 != &((const SfxSetItem&)rItem).GetItemSet(),
512 									"SetItem without ItemSet" );
513 						DBG_WARNING( "loading non-empty ItemPool" );
514                         #endif
515 
516 						AddRef( **ppHtArr, 1 );
517 					}
518 			}
519 		}
520 
521 		// during loading (until LoadCompleted()) protect all items
522 		pImp->nInitRefCount = 2;
523 	}
524 
525 	// Load-Master finden
526 	SfxItemPool *pLoadMaster = pMaster != this ? pMaster : 0;
527 	while ( pLoadMaster && !pLoadMaster->pImp->bStreaming )
528 		pLoadMaster = pLoadMaster->pSecondary;
529 
530 	// Gesamt Header einlesen
531 	pImp->bStreaming = sal_True;
532 	if ( !pLoadMaster )
533 	{
534 		// Format-Version laden
535 		CHECK_FILEFORMAT2( rStream,
536 				SFX_ITEMPOOL_TAG_STARTPOOL_5, SFX_ITEMPOOL_TAG_STARTPOOL_4 );
537 		rStream >> pImp->nMajorVer >> pImp->nMinorVer;
538 
539 		// Format-Version in Master-Pool "ubertragen
540 		pMaster->pImp->nMajorVer = pImp->nMajorVer;
541 		pMaster->pImp->nMinorVer = pImp->nMinorVer;
542 
543 		// altes Format?
544 		if ( pImp->nMajorVer < 2 )
545 			// pImp->bStreaming wird von Load1_Impl() zur"uckgesetzt
546 			return Load1_Impl( rStream );
547 
548 		// zu neues Format?
549 		if ( pImp->nMajorVer > SFX_ITEMPOOL_VER_MAJOR )
550 		{
551 			rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
552 			pImp->bStreaming = sal_False;
553 			return rStream;
554 		}
555 
556 		// Version 1.2-Trick-Daten "uberspringen
557 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_TRICK4OLD );
558 		rStream.SeekRel( 4 ); // Hack-Daten wegen SfxStyleSheetPool-Bug  skippen
559 	}
560 
561 	// neues Record-orientiertes Format
562 	SfxMiniRecordReader aPoolRec( &rStream, SFX_ITEMPOOL_REC );
563 	if ( rStream.GetError() )
564 	{
565 		pImp->bStreaming = sal_False;
566 		return rStream;
567 	}
568 
569 	// Einzel-Header
570 	int bOwnPool = sal_True;
571 	UniString aExternName;
572 	{
573 		// Header-Record suchen
574 		SfxMiniRecordReader aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER );
575 		if ( rStream.GetError() )
576 		{
577 			pImp->bStreaming = sal_False;
578 			return rStream;
579 		}
580 
581 		// Header-lesen
582 		rStream >> pImp->nLoadingVersion;
583 		SfxPoolItem::readByteString(rStream, aExternName);
584 		bOwnPool = aExternName == aName;
585 
586 		//! solange wir keine fremden Pools laden k"onnen
587 		if ( !bOwnPool )
588 		{
589 			rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
590 			aPoolRec.Skip();
591 			pImp->bStreaming = sal_False;
592 			return rStream;
593 		}
594 	}
595 
596 	// Version-Maps
597 	{
598 		SfxMultiRecordReader aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP );
599 		if ( rStream.GetError() )
600 		{
601 			pImp->bStreaming = sal_False;
602 			return rStream;
603 		}
604 
605 		// Versions-Maps einlesen
606 		sal_uInt16 nOwnVersion = pImp->nVersion;
607 		for ( sal_uInt16 nVerNo = 0; aVerRec.GetContent(); ++nVerNo )
608 		{
609 			// Header f"ur einzelne Version einlesen
610 			sal_uInt16 nVersion(0), nHStart(0), nHEnd(0);
611 			rStream >> nVersion >> nHStart >> nHEnd;
612 			sal_uInt16 nCount = nHEnd - nHStart + 1;
613 
614 			// Is new version is known?
615 			if ( nVerNo >= pImp->aVersions.size() )
616 			{
617 				// Add new Version
618 				sal_uInt16 *pMap = new sal_uInt16[nCount];
619                 memset(pMap, 0, nCount * sizeof(sal_uInt16));
620 				for ( sal_uInt16 n = 0; n < nCount; ++n )
621 					rStream >> pMap[n];
622 				SetVersionMap( nVersion, nHStart, nHEnd, pMap );
623 			}
624 		}
625 		pImp->nVersion = nOwnVersion;
626 	}
627 
628 	// Items laden
629 	FASTBOOL bSecondaryLoaded = sal_False;
630 	long nSecondaryEnd = 0;
631 	{
632 		SfxMultiRecordReader aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS);
633 		while ( aWhichIdsRec.GetContent() )
634 		{
635 			// SlotId, Which-Id und Item-Version besorgen
636 			sal_uInt32 nCount(0);
637 			sal_uInt16 nVersion(0), nWhich(0);
638 			//!sal_uInt16 nSlotId = aWhichIdsRec.GetContentTag();
639 			rStream >> nWhich;
640 			if ( pImp->nLoadingVersion != pImp->nVersion )
641 				// Which-Id aus File-Version in Pool-Version verschieben
642 				nWhich = GetNewWhich( nWhich );
643 
644 			// unbekanntes Item aus neuerer Version
645 			if ( !IsInRange(nWhich) )
646 				continue;
647 
648 			rStream >> nVersion;
649 			rStream >> nCount;
650 			//!SFX_ASSERTWARNING( !nSlotId || !HasMap() ||
651 			//!			( nSlotId == GetSlotId( nWhich, sal_False ) ) ||
652 			//!			!GetSlotId( nWhich, sal_False ),
653 			//!			nWhich, "Slot/Which mismatch" );
654 
655 			sal_uInt16 nIndex = GetIndex_Impl(nWhich);
656 			SfxPoolItemArray_Impl **ppArr = pImp->ppPoolItems + nIndex;
657 
658 			// SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
659 			SfxPoolItem *pDefItem = *(ppStaticDefaults + nIndex);
660 			pImp->bInSetItem = pDefItem->ISA(SfxSetItem);
661 			if ( !bSecondaryLoaded && pSecondary && pImp->bInSetItem )
662 			{
663 				// an das Ende des eigenen Pools seeken
664 				sal_uLong nLastPos = rStream.Tell();
665 				aPoolRec.Skip();
666 
667 				// Sekund"arpool einlesen
668 				pSecondary->Load( rStream );
669 				bSecondaryLoaded = sal_True;
670 				nSecondaryEnd = rStream.Tell();
671 
672 				// zur"uck zu unseren eigenen Items
673 				rStream.Seek(nLastPos);
674 			}
675 
676 			// Items an sich lesen
677 			readTheItems(rStream, nCount, nVersion, pDefItem, ppArr);
678 
679 			pImp->bInSetItem = sal_False;
680 		}
681 	}
682 
683 	// Pool-Defaults lesen
684 	{
685 		SfxMultiRecordReader aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS );
686 
687 		while ( aDefsRec.GetContent() )
688 		{
689 			// SlotId, Which-Id und Item-Version besorgen
690 			sal_uInt16 nVersion(0), nWhich(0);
691 			//!sal_uInt16 nSlotId = aDefsRec.GetContentTag();
692 			rStream >> nWhich;
693 			if ( pImp->nLoadingVersion != pImp->nVersion )
694 				// Which-Id aus File-Version in Pool-Version verschieben
695 				nWhich = GetNewWhich( nWhich );
696 
697 			// unbekanntes Item aus neuerer Version
698 			if ( !IsInRange(nWhich) )
699 				continue;
700 
701 			rStream >> nVersion;
702 			//!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, sal_False ) ),
703 			//!			nWhich, "Slot/Which mismatch" );
704 
705 			// Pool-Default-Item selbst laden
706 			SfxPoolItem *pItem =
707 					( *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
708 					->Create( rStream, nVersion );
709 			pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
710 			*( ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
711 		}
712 	}
713 
714 	// ggf. Secondary-Pool laden
715 	aPoolRec.Skip();
716 	if ( pSecondary )
717 	{
718 		if ( !bSecondaryLoaded )
719 			pSecondary->Load( rStream );
720 		else
721 			rStream.Seek( nSecondaryEnd );
722 	}
723 
724 	// wenn nicht own-Pool, dann kein Name
725 	if ( aExternName != aName )
726 		aName.Erase();
727 
728 	pImp->bStreaming = sal_False;
729 	return rStream;
730 };
731 
732 // -----------------------------------------------------------------------
733 
734 SvStream &SfxItemPool::Load1_Impl(SvStream &rStream)
735 {
736 	// beim Master ist der Header schon von <Load()> geladen worden
737 	if ( !pImp->bStreaming )
738 	{
739 		// Header des Secondary lesen
740 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_STARTPOOL_4 );
741 		rStream >> pImp->nMajorVer >> pImp->nMinorVer;
742 	}
743 	sal_uInt32 nAttribSize(0);
744 	int bOwnPool = sal_True;
745 	UniString aExternName;
746 	if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 2 )
747 		rStream >> pImp->nLoadingVersion;
748 	SfxPoolItem::readByteString(rStream, aExternName);
749 	bOwnPool = aExternName == aName;
750 	pImp->bStreaming = sal_True;
751 
752 	//! solange wir keine fremden laden k"onnen
753 	if ( !bOwnPool )
754 	{
755 		rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
756 		pImp->bStreaming = sal_False;
757 		return rStream;
758 	}
759 
760 	// Versionen bis 1.3 k"onnen noch keine Which-Verschiebungen lesen
761 	if ( pImp->nMajorVer == 1 && pImp->nMinorVer <= 2 &&
762 		 pImp->nVersion < pImp->nLoadingVersion )
763 	{
764 		rStream.SetError(ERRCODE_IO_WRONGVERSION);
765 		pImp->bStreaming = sal_False;
766 		return rStream;
767 	}
768 
769 	// Size-Table liegt hinter den eigentlichen Attributen
770 	rStream >> nAttribSize;
771 
772 	// Size-Table einlesen
773 	sal_uLong nStartPos = rStream.Tell();
774 	rStream.SeekRel( nAttribSize );
775 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_SIZES );
776 	sal_uInt32 nSizeTableLen(0);
777 	rStream >> nSizeTableLen;
778 	sal_Char *pBuf = new sal_Char[nSizeTableLen];
779 	rStream.Read( pBuf, nSizeTableLen );
780 	sal_uLong nEndOfSizes = rStream.Tell();
781 	SvMemoryStream aSizeTable( pBuf, nSizeTableLen, STREAM_READ );
782 
783 	// ab Version 1.3 steht in der Size-Table eine Versions-Map
784 	if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 3 )
785 	{
786 		// Version-Map finden (letztes sal_uLong der Size-Table gibt Pos an)
787 		rStream.Seek( nEndOfSizes - sizeof(sal_uInt32) );
788 		sal_uInt32 nVersionMapPos(0);
789 		rStream >> nVersionMapPos;
790 		rStream.Seek( nVersionMapPos );
791 
792 		// Versions-Maps einlesen
793 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_VERSIONMAP );
794 		sal_uInt16 nVerCount(0);
795 		rStream >> nVerCount;
796 		for ( sal_uInt16 nVerNo = 0; nVerNo < nVerCount; ++nVerNo )
797 		{
798 			// Header f"ur einzelne Version einlesen
799 			sal_uInt16 nVersion(0), nHStart(0), nHEnd(0);
800 			rStream >> nVersion >> nHStart >> nHEnd;
801 			sal_uInt16 nCount = nHEnd - nHStart + 1;
802 			sal_uInt16 nBytes = (nCount)*sizeof(sal_uInt16);
803 
804 			// Is new version is known?
805 			if ( nVerNo >= pImp->aVersions.size() )
806 			{
807 				// Add new Version
808 				sal_uInt16 *pMap = new sal_uInt16[nCount];
809                 memset(pMap, 0, nCount * sizeof(sal_uInt16));
810 				for ( sal_uInt16 n = 0; n < nCount; ++n )
811 					rStream >> pMap[n];
812 				SetVersionMap( nVersion, nHStart, nHEnd, pMap );
813 			}
814 			else
815 				// Version schon bekannt => "uberspringen
816 				rStream.SeekRel( nBytes );
817 		}
818 	}
819 
820 	// Items laden
821 	rStream.Seek( nStartPos );
822 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ITEMS );
823 	FASTBOOL bSecondaryLoaded = sal_False;
824 	long nSecondaryEnd = 0;
825 	sal_uInt16 nWhich(0), nSlot(0);
826 	while ( rStream >> nWhich, nWhich )
827 	{
828 		// ggf. Which-Id aus alter Version verschieben?
829 		if ( pImp->nLoadingVersion != pImp->nVersion )
830 			nWhich = GetNewWhich( nWhich );
831 
832 		rStream >> nSlot;
833 		sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False);
834 		int bKnownItem = bOwnPool || IsWhich(nMappedWhich);
835 
836 		sal_uInt16 nRef(0), nCount(0), nVersion(0);
837 		sal_uInt32 nAttrSize(0);
838 		rStream >> nVersion >> nCount;
839 
840 		SfxPoolItemArray_Impl **ppArr = 0;
841 		SfxPoolItemArray_Impl *pNewArr = 0;
842 		SfxPoolItem *pDefItem = 0;
843 		if ( bKnownItem )
844 		{
845 			if ( !bOwnPool )
846 				nWhich = nMappedWhich;
847 
848 			//!SFX_ASSERTWARNING( !nSlot || !HasMap() ||
849 			//!			( nSlot == GetSlotId( nWhich, sal_False ) ) ||
850 			//!			!GetSlotId( nWhich, sal_False ),
851 			//!			nWhich, "Slot/Which mismatch" );
852 
853 			sal_uInt16 nIndex = GetIndex_Impl(nWhich);
854 			ppArr = pImp->ppPoolItems + nIndex;
855 			pNewArr = new SfxPoolItemArray_Impl();
856 			pDefItem = *(ppStaticDefaults + nIndex);
857 		}
858 
859 		// Position vor ersten Item merken
860 		sal_uLong nLastPos = rStream.Tell();
861 
862 		// SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
863 		if ( !bSecondaryLoaded && pSecondary && pDefItem->ISA(SfxSetItem) )
864 		{
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 );
869 
870 			// Sekund"arpool einlesen
871 			pSecondary->Load1_Impl( rStream );
872 			bSecondaryLoaded = sal_True;
873 			nSecondaryEnd = rStream.Tell();
874 
875 			// zur"uck zu unseren eigenen Items
876 			rStream.Seek(nLastPos);
877 		}
878 
879 		// Items an sich lesen
880 		for ( sal_uInt16 j = 0; j < nCount; ++j )
881 		{
882 			sal_uLong nPos = nLastPos;
883 			rStream >> nRef;
884 
885 			if ( bKnownItem )
886 			{
887 				SfxPoolItem *pItem = 0;
888 				if ( nRef )
889 				{
890 					pItem = pDefItem->Create(rStream, nVersion);
891 
892 					if ( !bPersistentRefCounts )
893 						// bis <SfxItemPool::LoadCompleted()> festhalten
894 						AddRef(*pItem, 1);
895 					else
896 					{
897 						if ( nRef > SFX_ITEMS_OLD_MAXREF )
898 							pItem->SetKind( nRef );
899 						else
900 							AddRef(*pItem, nRef);
901 					}
902 				}
903 				//pNewArr->insert( pItem, j );
904 				pNewArr->push_back( (SfxPoolItem*) pItem );
905 
906 				// restliche gespeicherte Laenge skippen (neueres Format)
907 				nLastPos = rStream.Tell();
908 			}
909 
910 			aSizeTable >> nAttrSize;
911 			SFX_ASSERT( !bKnownItem || ( nPos + nAttrSize) >= nLastPos,
912 						nPos,
913 						"too many bytes read - version mismatch?" );
914 
915 			if ( !bKnownItem || ( nLastPos < (nPos + nAttrSize) ) )
916 			{
917 				nLastPos = nPos + nAttrSize;
918 				rStream.Seek( nLastPos );
919 			}
920 		}
921 
922 		if ( bKnownItem )
923 		{
924 			SfxPoolItemArray_Impl *pOldArr = *ppArr;
925 			*ppArr = pNewArr;
926 
927 			// die Items merken, die schon im Pool sind
928 			int bEmpty = sal_True;
929 			if ( 0 != pOldArr )
930 				for ( size_t n = 0; bEmpty && n < pOldArr->size(); ++n )
931 					bEmpty = pOldArr->operator[](n) == 0;
932 			DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" );
933 			if ( !bEmpty )
934 			{
935 				// f"ur alle alten suchen, ob ein gleiches neues existiert
936 				for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld )
937 				{
938 					SfxPoolItem *pOldItem = (*pOldArr)[nOld];
939 					if ( pOldItem )
940 					{
941 						bool bFound = false;
942 						for ( size_t nNew = 0;
943 							  nNew < (*ppArr)->size();  ++nNew )
944 						{
945 							SfxPoolItem *&rpNewItem =
946 								(SfxPoolItem*&)(*ppArr)->operator[](nNew);
947 
948 							if ( rpNewItem && *rpNewItem == *pOldItem )
949 							{
950 								AddRef( *pOldItem, rpNewItem->GetRefCount() );
951 								SetRefCount( *rpNewItem, 0 );
952 								delete rpNewItem;
953 								rpNewItem = pOldItem;
954 								bFound = true;
955 								SFX_TRACE( "reusing item", pOldItem );
956 								break;
957 							}
958 						}
959 						if ( !bFound )
960                         {
961 							SFX_TRACE( "item not found: ", pOldItem );
962                         }
963 					}
964 				}
965 			}
966 			delete pOldArr; /* @@@ */
967 		}
968 	}
969 
970 	// Pool-Defaults lesen
971 	if ( pImp->nMajorVer > 1 || pImp->nMinorVer > 0 )
972 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_DEFAULTS );
973 
974 	sal_uLong nLastPos = rStream.Tell();
975 	while ( rStream >> nWhich, nWhich )
976 	{
977 		// ggf. Which-Id aus alter Version verschieben?
978 		if ( pImp->nLoadingVersion != pImp->nVersion )
979 			nWhich = GetNewWhich( nWhich );
980 
981 		rStream >> nSlot;
982 		sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False);
983 		int bKnownItem = bOwnPool || IsWhich(nMappedWhich);
984 
985 		sal_uLong nPos = nLastPos;
986 		sal_uInt32 nSize(0);
987 		sal_uInt16 nVersion(0);
988 		rStream >> nVersion;
989 
990 		if ( bKnownItem )
991 		{
992 			if ( !bOwnPool )
993 				nWhich = nMappedWhich;
994 			SfxPoolItem *pItem =
995 				( *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
996 				->Create( rStream, nVersion );
997 			pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
998 			*( ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
999 		}
1000 
1001 		nLastPos = rStream.Tell();
1002 		aSizeTable >> nSize;
1003 		SFX_ASSERT( ( nPos + nSize) >= nLastPos, nPos,
1004 					"too many bytes read - version mismatch?" );
1005 		if ( nLastPos < (nPos + nSize) )
1006 			rStream.Seek( nPos + nSize );
1007 	}
1008 
1009 	delete[] pBuf;
1010 	rStream.Seek(nEndOfSizes);
1011 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL );
1012 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL );
1013 
1014 	if ( pSecondary )
1015 	{
1016 		if ( !bSecondaryLoaded )
1017 			pSecondary->Load1_Impl( rStream );
1018 		else
1019 			rStream.Seek( nSecondaryEnd );
1020 	}
1021 
1022 	if ( aExternName != aName )
1023 		aName.Erase();
1024 
1025 	pImp->bStreaming = sal_False;
1026 	return rStream;
1027 }
1028 
1029 // -----------------------------------------------------------------------
1030 
1031 const SfxPoolItem* SfxItemPool::LoadSurrogate
1032 (
1033 	SvStream&			rStream,	// vor einem Surrogat positionierter Stream
1034 	sal_uInt16& 			rWhich, 	// Which-Id des zu ladenden <SfxPoolItem>s
1035 	sal_uInt16				nSlotId,	// Slot-Id des zu ladenden <SfxPoolItem>s
1036 	const SfxItemPool*	pRefPool	// <SfxItemPool> in dem das Surrogat gilt
1037 )
1038 
1039 /*	[Beschreibung]
1040 
1041 	L"adt Surrogat aus 'rStream' und liefert das dadurch in 'rRefPool'
1042 	repr"asentierte SfxPoolItem zu"ruck. Ist das im Stream befindliche
1043 	Surrogat == SFX_ITEMS_DIRECT (!SFX_ITEM_POOLABLE) wird 0 zur"uckgegeben,
1044 	das Item ist direkt aus dem Stream zu laden. Bei 0xfffffff0 (SFX_ITEMS_NULL)
1045 	wird auch 0 zurueckgegeben und rWhich auf 0 gesetzt, das Item ist nicht
1046 	verfuegbar.
1047 
1048 	Ansonsten wird ber"ucksichtigt, ob der betroffene Pool ohne Ref-Counts
1049 	geladen wird, ob aus einem neuen Pool nachgeladen wird (&rRefPool != this)
1050 	oder ob aus einem g"anzlich anders aufgebauten Pool geladen wird.
1051 
1052 	Wird aus einem anders aufgebauten Pool geladen und die 'nSlotId' kann
1053 	nicht in eine Which-Id dieses Pools gemappt werden, wird ebenfalls 0
1054 	zur"uckgeliefert.
1055 
1056 	Preconditions:	- Pool mu\s geladen sein
1057 					- LoadCompleted darf noch nicht gerufen worden sein
1058 					- 'rStream' steht genau an der Position, an der ein
1059 					  Surrogat f"ur ein Item mit der SlotId 'nSlotId' und
1060 					  der WhichId 'rWhichId' mit StoreSurrogate gepeichert
1061 					  wurde
1062 
1063 	Postconditions:	- 'rStream' ist so positioniert, wie auch StoreSurrogate
1064 					  sein speichern beendet hatte
1065 					- konnte ein Item geladen werden, befindet es sich
1066 					  in diesem SfxItemPool
1067 					- 'rWhichId' enth"alt die ggf. gemappte Which-Id
1068 	Laufzeit:       Tiefe des Ziel Sekund"arpools * 10 + 10
1069 
1070 	[Querverweise]
1071 
1072 	<SfxItemPool::StoreSurrogate(SvStream&,const SfxPoolItem &)const>
1073 */
1074 
1075 {
1076 	// Read the first surrogate
1077 	sal_uInt32 nSurrogat(0);
1078 	rStream >> nSurrogat;
1079 
1080 	// Is item stored directly?
1081 	if ( SFX_ITEMS_DIRECT == nSurrogat )
1082 		return 0;
1083 
1084 	// Item does not exist?
1085 	if ( SFX_ITEMS_NULL == nSurrogat )
1086 	{
1087 		rWhich = 0;
1088 		return 0;
1089 	}
1090 
1091 	// Bei einem identisch aufgebauten Pool (im Stream) kann das Surrogat
1092 	// auf jeden Fall aufgel"ost werden.
1093 	if ( !pRefPool )
1094 		pRefPool = this;
1095 	FASTBOOL bResolvable = pRefPool->GetName().Len() > 0;
1096 	if ( !bResolvable )
1097 	{
1098 		// Bei einem anders aufgebauten Pool im Stream, mu\s die SlotId
1099 		// aus dem Stream in eine Which-Id gemappt werden k"onnen.
1100 		sal_uInt16 nMappedWhich = nSlotId ? GetWhich(nSlotId, sal_True) : 0;
1101 		if ( IsWhich(nMappedWhich) )
1102 		{
1103 			// gemappte SlotId kann "ubernommen werden
1104 			rWhich = nMappedWhich;
1105 			bResolvable = sal_True;
1106 		}
1107 	}
1108 
1109 	// kann Surrogat aufgel"ost werden?
1110 	const SfxPoolItem *pItem = 0;
1111 	if ( bResolvable )
1112 	{
1113 		for ( SfxItemPool *pTarget = this; pTarget; pTarget = pTarget->pSecondary )
1114 		{
1115 			// richtigen (Folge-) Pool gefunden?
1116 			if ( pTarget->IsInRange(rWhich) )
1117 			{
1118 				// dflt-Attribut?
1119 				if ( SFX_ITEMS_DEFAULT == nSurrogat )
1120 					return *(pTarget->ppStaticDefaults +
1121 							pTarget->GetIndex_Impl(rWhich));
1122 
1123 				SfxPoolItemArray_Impl* pItemArr = *(pTarget->pImp->ppPoolItems +
1124 						pTarget->GetIndex_Impl(rWhich));
1125 				pItem = pItemArr && nSurrogat < pItemArr->size()
1126 							? (*pItemArr)[nSurrogat]
1127 							: 0;
1128 				if ( !pItem )
1129 				{
1130 					DBG_ERROR( "can't resolve surrogate" );
1131 					rWhich = 0; // nur zur Sicherheit fuer richtige Stream-Pos
1132 					return 0;
1133 				}
1134 
1135 				// Nachladen aus Ref-Pool?
1136 				if ( pRefPool != pMaster )
1137 					return &pTarget->Put( *pItem );
1138 
1139 				// Referenzen sind NICHT schon mit Pool geladen worden?
1140 				if ( !pTarget->HasPersistentRefCounts() )
1141 					AddRef( *pItem, 1 );
1142 				else
1143 					return pItem;
1144 
1145 				return pItem;
1146 			}
1147 		}
1148 
1149 		SFX_ASSERT( sal_False, rWhich, "can't resolve Which-Id in LoadSurrogate" );
1150 	}
1151 
1152 	return 0;
1153 }
1154 
1155 //-------------------------------------------------------------------------
1156 
1157 
1158 FASTBOOL SfxItemPool::StoreSurrogate
1159 (
1160 	SvStream&			rStream,
1161 	const SfxPoolItem* 	pItem
1162 )	const
1163 
1164 /*	[Beschreibung]
1165 
1166 	Speichert ein Surrogat f"ur '*pItem' in 'rStream'.
1167 
1168 
1169 	[R"uckgabewert]
1170 
1171 	FASTBOOL				sal_True
1172 							es wurde ein echtes Surrogat gespeichert, auch
1173 							SFX_ITEMS_NULL bei 'pItem==0',
1174 							SFX_ITEMS_STATICDEFAULT und SFX_ITEMS_POOLDEFAULT
1175 							gelten als 'echte' Surrogate
1176 
1177 							sal_False
1178 							es wurde ein Dummy-Surrogat (SFX_ITEMS_DIRECT)
1179 							gespeichert, das eigentliche Item mu\s direkt
1180 							hinterher selbst gespeichert werden
1181 */
1182 
1183 {
1184 	if ( pItem )
1185 	{
1186 		FASTBOOL bRealSurrogate = IsItemFlag(*pItem, SFX_ITEM_POOLABLE);
1187 		rStream << ( bRealSurrogate
1188 						? GetSurrogate( pItem )
1189 						: SFX_ITEMS_DIRECT );
1190 		return bRealSurrogate;
1191 	}
1192 
1193     rStream << SFX_ITEMS_NULL;
1194 	return sal_True;
1195 }
1196 
1197 // -----------------------------------------------------------------------
1198 
1199 sal_uInt32 SfxItemPool::GetSurrogate(const SfxPoolItem *pItem) const
1200 {
1201 	DBG_CHKTHIS(SfxItemPool, 0);
1202 	DBG_ASSERT( pItem, "no 0-Pointer Surrogate" );
1203 	DBG_ASSERT( !IsInvalidItem(pItem), "no Invalid-Item Surrogate" );
1204 	DBG_ASSERT( !IsPoolDefaultItem(pItem), "no Pool-Default-Item Surrogate" );
1205 
1206 	if ( !IsInRange(pItem->Which()) )
1207 	{
1208 		if ( pSecondary )
1209 			return pSecondary->GetSurrogate( pItem );
1210 		SFX_ASSERT( 0, pItem->Which(), "unknown Which-Id - dont ask me for surrogates" );
1211 	}
1212 
1213 	// Pointer auf static- oder pool-dflt-Attribut?
1214 	if( IsStaticDefaultItem(pItem) || IsPoolDefaultItem(pItem) )
1215 		return SFX_ITEMS_DEFAULT;
1216 
1217 	SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(pItem->Which()));
1218 	DBG_ASSERT(pItemArr, "ItemArr is not available");
1219 
1220 	for ( size_t i = 0; i < pItemArr->size(); ++i )
1221 	{
1222 		const SfxPoolItem *p = (*pItemArr)[i];
1223 		if ( p == pItem )
1224 			return i;
1225 	}
1226 	SFX_ASSERT( 0, pItem->Which(), "Item not in the pool");
1227 	return SFX_ITEMS_NULL;
1228 }
1229 
1230 // -----------------------------------------------------------------------
1231 
1232 FASTBOOL SfxItemPool::IsInStoringRange( sal_uInt16 nWhich ) const
1233 {
1234 	return nWhich >= pImp->nStoringStart &&
1235 		   nWhich <= pImp->nStoringEnd;
1236 }
1237 
1238 //------------------------------------------------------------------------
1239 
1240 void SfxItemPool::SetStoringRange( sal_uInt16 nFrom, sal_uInt16 nTo )
1241 
1242 /*	[Beschreibung]
1243 
1244 	Mit dieser Methode kann der Which-Bereich eingeengt werden, der
1245 	von ItemSets dieses Pool (und dem Pool selbst) gespeichert wird.
1246 	Die Methode muss dazu vor <SfxItemPool::Store()> gerufen werden
1247 	und die Werte muessen auch noch gesetzt sein, wenn das eigentliche
1248 	Dokument (also die ItemSets gespeicher werden).
1249 
1250 	Ein Zuruecksetzen ist dann nicht noetig, wenn dieser Range vor
1251 	JEDEM Speichern richtig gesetzt wird, da er nur beim Speichern
1252 	beruecksichtigt wird.
1253 
1254 	Dieses muss fuer das 3.1-Format gemacht werden, da dort eine
1255 	Bug in der Pool-Lade-Methode vorliegt.
1256 */
1257 
1258 {
1259 	pImp->nStoringStart = nFrom;
1260 	pImp->nStoringEnd = nTo;
1261 }
1262 
1263 // -----------------------------------------------------------------------
1264 
1265 void SfxItemPool::SetVersionMap
1266 (
1267 	sal_uInt16 	nVer, 				/* 	neue Versionsnummer */
1268 	sal_uInt16  nOldStart,          /*  alte erste Which-Id */
1269 	sal_uInt16  nOldEnd,            /*  alte letzte Which-Id */
1270 	sal_uInt16*	pOldWhichIdTab		/* 	Array mit genau dem Aufbau der Which-Ids
1271 									der vorhergehenden Version, in denen
1272 									die jeweils neue Which-Id steht. */
1273 )
1274 
1275 /*	[Beschreibung]
1276 
1277 	Mit dieser Methode k"onnen neue, inkompatible Which-Id-Folgen oder
1278 	Verteilungen realisiert werden. Pools, die noch mit alten Versionen
1279 	gespeichert wurden, werden dann "uber die angegebene Tabelle solange
1280 	gemappt, bis die aktuelle Version erreicht ist. Neuere Pools k"onnen
1281 	unter Verlust neuer Attribute geladen werden, da die Map mit dem Pool
1282 	gespeichert wird.
1283 
1284 	Precondition:	Pool darf noch nicht geladen sein
1285 	Postcondition:	Which-Ids aus fr"uheren Versionen k"onnen bei Laden auf
1286 					Version 'nVer' gemappt werden
1287 	Laufzeit:       1.5 * new + 10
1288 
1289 	[Anmerkung]
1290 
1291 	F"ur neue Which-Ranges (nStart,nEnd) m"ssen im Vergleich zur Vorg"anger-
1292 	Version (nOldStart,nOldEnd) immer gelten, da\s (nOldStart,nOldEnd)
1293 	vollst"andig in (nStart,nEnd) enthalten ist. Es ist also zul"assig, den
1294 	Which-Range in beide Richtungen zu erweitern, auch durch Einf"ugung
1295 	von Which-Ids, nicht aber ihn zu beschneiden.
1296 
1297 	Diese Methode sollte nur im oder direkt nach Aufruf des Konstruktors
1298 	gerufen werden.
1299 
1300 	Das Array mu\s statisch sein, da es nicht kopiert wird und au\serdem
1301 	im Copy-Ctor des SfxItemPool wiederverwendet wird.
1302 
1303 
1304 	[Beispiel]
1305 
1306 	Urspr"unglich (Version 0) hatte der Pool folgende Which-Ids:
1307 
1308 		1:A, 2:B, 3:C, 4:D
1309 
1310 	Nun soll eine neue Version (Version 1) zwei zus"atzliche Ids X und Y
1311 	zwischen B und C erhalten, also wie folgt aussehen:
1312 
1313 		1:A, 2:B, 3:X, 4:Y, 5:C, 6:D
1314 
1315 	Dabei haben sich also die Ids 3 und 4 ge"andert. F"ur die neue Version
1316 	m"u\ste am Pool folgendes gesetzt werden:
1317 
1318 		static sal_uInt16 nVersion1Map = { 1, 2, 5, 6 };
1319 		pPool->SetVersionMap( 1, 1, 4, &nVersion1Map );
1320 
1321 
1322 	[Querverweise]
1323 
1324 	<SfxItemPool::IsLoadingVersionCurrent()const>
1325 	<SfxItemPool::GetNewWhich(sal_uInt16)>
1326 	<SfxItemPool::GetVersion()const>
1327 	<SfxItemPool::GetLoadingVersion()const>
1328 */
1329 
1330 {
1331 	// create new map entry to insert
1332 	const SfxPoolVersion_ImplPtr pVerMap = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl(
1333 				nVer, nOldStart, nOldEnd, pOldWhichIdTab ) );
1334 	pImp->aVersions.push_back( pVerMap );
1335 
1336 	DBG_ASSERT( nVer > pImp->nVersion, "Versions not sorted" );
1337 	pImp->nVersion = nVer;
1338 
1339 	// Versions-Range anpassen
1340 	for ( sal_uInt16 n = 0; n < nOldEnd-nOldStart+1; ++n )
1341 	{
1342 		sal_uInt16 nWhich = pOldWhichIdTab[n];
1343 		if ( nWhich < pImp->nVerStart )
1344 		{
1345 			if ( !nWhich )
1346 				nWhich = 0;
1347 			pImp->nVerStart = nWhich;
1348 		}
1349 		else if ( nWhich > pImp->nVerEnd )
1350 			pImp->nVerEnd = nWhich;
1351 	}
1352 }
1353 
1354 // -----------------------------------------------------------------------
1355 
1356 sal_uInt16 SfxItemPool::GetNewWhich
1357 (
1358 	sal_uInt16	nFileWhich		// die aus dem Stream geladene Which-Id
1359 )	const
1360 
1361 /*	[Beschreibung]
1362 
1363 	Diese Methoden rechnet Which-Ids aus einem File-Format in die der
1364 	aktuellen Pool-Version um. Ist das File-Format "alter, werden die vom
1365 	Pool-Entwickler mit SetVersion() gesetzten Tabellen verwendet,
1366 	ist das File-Format neuer, dann die aus dem File geladenen Tabellen.
1367 	Im letzteren Fall kann ggf. nicht jede Which-Id gemappt werden,
1368 	so da\s 0 zur"uckgeliefert wird.
1369 
1370 	Die Berechnung ist nur f"ur Which-Ids definiert, die in der betreffenden
1371 	File-Version unterst"utzt wurden. Dies ist per Assertion abgesichert.
1372 
1373 	Precondition:	Pool mu\s geladen sein
1374 	Postcondition:	unver"andert
1375 	Laufzeit:		linear(Anzahl der Sekund"arpools) +
1376 					linear(Differenz zwischen alter und neuer Version)
1377 
1378 
1379 	[Querverweise]
1380 
1381 	<SfxItemPool::IsLoadingVersionCurrent()const>
1382 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1383 	<SfxItemPool::GetVersion()const>
1384 	<SfxItemPool::GetLoadingVersion()const>
1385 */
1386 
1387 {
1388 	// (Sekund"ar-) Pool bestimmen
1389 	if ( !IsInVersionsRange(nFileWhich) )
1390 	{
1391 		if ( pSecondary )
1392 			return pSecondary->GetNewWhich( nFileWhich );
1393 		SFX_ASSERT( 0, nFileWhich, "unknown which in GetNewWhich()" );
1394 	}
1395 
1396 	// Version neuer/gleich/"alter?
1397 	short nDiff = (short)pImp->nLoadingVersion - (short)pImp->nVersion;
1398 
1399 	// Which-Id einer neueren Version?
1400 	if ( nDiff > 0 )
1401 	{
1402 		// von der Top-Version bis runter zur File-Version stufenweise mappen
1403 		for ( size_t nMap = pImp->aVersions.size(); nMap > 0; --nMap )
1404 		{
1405 			SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap-1];
1406 			if ( pVerInfo->_nVer > pImp->nVersion )
1407 			{	sal_uInt16 nOfs;
1408 				sal_uInt16 nCount = pVerInfo->_nEnd - pVerInfo->_nStart + 1;
1409 				for ( nOfs = 0;
1410 					  nOfs <= nCount &&
1411 						pVerInfo->_pMap[nOfs] != nFileWhich;
1412 					  ++nOfs )
1413 					continue;
1414 
1415 				if ( pVerInfo->_pMap[nOfs] == nFileWhich )
1416 					nFileWhich = pVerInfo->_nStart + nOfs;
1417 				else
1418 					return 0;
1419 			}
1420 			else
1421 				break;
1422 		}
1423 	}
1424 
1425 	// Which-Id einer neueren Version?
1426 	else if ( nDiff < 0 )
1427 	{
1428 		// von der File-Version bis zur aktuellen Version stufenweise mappen
1429 		for ( size_t nMap = 0; nMap < pImp->aVersions.size(); ++nMap )
1430 		{
1431 			SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap];
1432 			if ( pVerInfo->_nVer > pImp->nLoadingVersion )
1433 			{
1434 				DBG_ASSERT( nFileWhich >= pVerInfo->_nStart &&
1435 							nFileWhich <= pVerInfo->_nEnd,
1436 							"which-id unknown in version" );
1437 				nFileWhich = pVerInfo->_pMap[nFileWhich - pVerInfo->_nStart];
1438 			}
1439 		}
1440 	}
1441 
1442 	// originale (nDiff==0) bzw. gemappte (nDiff!=0) Id zur"uckliefern
1443 	return nFileWhich;
1444 }
1445 
1446 // -----------------------------------------------------------------------
1447 
1448 
1449 FASTBOOL SfxItemPool::IsInVersionsRange( sal_uInt16 nWhich ) const
1450 {
1451 	return nWhich >= pImp->nVerStart && nWhich <= pImp->nVerEnd;
1452 }
1453 
1454 // -----------------------------------------------------------------------
1455 
1456 FASTBOOL SfxItemPool::IsCurrentVersionLoading() const
1457 
1458 /*	[Beschreibung]
1459 
1460 	Mit dieser Methode kann festgestellt werden, ob die geladene Pool-Version
1461 	dem aktuellen Pool-Aufbau entspricht.
1462 
1463 	Precondition:	Pool mu\s geladen sein
1464 	Postcondition:	unver"andert
1465 	Laufzeit:		linear(Anzahl der Sekund"arpools)
1466 
1467 
1468 	[Querverweise]
1469 
1470 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1471 	<SfxItemPool::GetNewWhich(sal_uInt16)const>
1472 	<SfxItemPool::GetVersion()const>
1473 	<SfxItemPool::GetLoadingVersion()const>
1474 */
1475 
1476 {
1477 	return ( pImp->nVersion == pImp->nLoadingVersion ) &&
1478 		   ( !pSecondary || pSecondary->IsCurrentVersionLoading() );
1479 }
1480 
1481 // -----------------------------------------------------------------------
1482 
1483 sal_uInt16 SfxItemPool::GetVersion() const
1484 
1485 /*	[Beschreibung]
1486 
1487 	Diese Methode liefert die aktuelle Versionsnummer des SfxItemPool-Aufbaus
1488 	(also des Which-Bereichs).
1489 
1490 	Precondition:	keine
1491 	Postcondition:	unver"andert
1492 	Laufzeit:       2
1493 
1494 
1495 	[Anmerkung]
1496 
1497 	Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools
1498 	ber"ucksichtigt werden.
1499 
1500 
1501 	[Querverweise]
1502 
1503 	<SfxItemPool::IsLoadingVersionCurrent()const>
1504 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1505 	<SfxItemPool::GetNewWhich(sal_uInt16)const>
1506 	<SfxItemPool::GetLoadingVersion()const>
1507 */
1508 
1509 {
1510 	return pImp->nVersion;
1511 }
1512 
1513 // -----------------------------------------------------------------------
1514 
1515 sal_uInt16 SfxItemPool::GetLoadingVersion() const
1516 
1517 /*	[Beschreibung]
1518 
1519 	Diese Methode liefert die Versionsnummer des SfxItemPool-Aufbaus
1520 	(also des Which-Bereichs), die bei Laden vorgefunden wurde.
1521 
1522 	Precondition:	Pool mu\s geladen sein
1523 	Postcondition:	unver"andert
1524 	Laufzeit:       2
1525 
1526 
1527 	[Anmerkung]
1528 
1529 	Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools
1530 	ber"ucksichtigt werden.
1531 
1532 
1533 	[Querverweise]
1534 
1535 	<SfxItemPool::IsLoadingVersionCurrent()const>
1536 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1537 	<SfxItemPool::GetNewWhich(sal_uInt16)const>
1538 	<SfxItemPool::GetVersion()const>
1539 */
1540 
1541 {
1542 	return pImp->nLoadingVersion;
1543 }
1544 
1545 //-------------------------------------------------------------------------
1546 
1547 FASTBOOL SfxItemPool::IsVer2_Impl() const
1548 {
1549 	return pMaster->pImp->nMajorVer >= 2;
1550 }
1551 
1552 //-------------------------------------------------------------------------
1553 
1554 
1555 FASTBOOL SfxItemPool::StoreItem( SvStream &rStream, const SfxPoolItem &rItem,
1556 								 FASTBOOL bDirect ) const
1557 
1558 /*	[Beschreibung]
1559 
1560 	Speichert das <SfxPoolItem> 'rItem' in den <SvStream> 'rStream'
1561 	entweder als Surrogat ('bDirect == sal_False') oder direkt mit 'rItem.Store()'.
1562 	Nicht poolable Items werden immer direkt gespeichert. Items ohne Which-Id,
1563 	also SID-Items, werden nicht gespeichert, ebenso wenn Items, die in der
1564 	File-Format-Version noch nicht vorhanden waren (return sal_False).
1565 
1566 	Das Item wird im Stream wie folgt abgelegt:
1567 
1568 	sal_uInt16	rItem.Which()
1569 	sal_uInt16	GetSlotId( rItem.Which() ) bzw. 0 falls nicht verf"urbar
1570 	sal_uInt16	GetSurrogate( &rItem ) bzw. SFX_ITEM_DIRECT bei '!SFX_ITEM_POOLBLE'
1571 
1572 	optional (falls 'bDirect == sal_True' oder '!rItem.IsPoolable()':
1573 
1574 	sal_uInt16  rItem.GetVersion()
1575 	sal_uLong 	Size
1576 	Size    rItem.Store()
1577 
1578 
1579 	[Querverweise]
1580 
1581 	<SfxItemPool::LoadItem(SvStream&,FASTBOOL)const>
1582 */
1583 
1584 {
1585 	DBG_ASSERT( !IsInvalidItem(&rItem), "cannot store invalid items" );
1586 
1587 	if ( IsSlot( rItem.Which() ) )
1588 		return sal_False;
1589 	const SfxItemPool *pPool = this;
1590 	while ( !pPool->IsInStoringRange(rItem.Which()) )
1591 		if ( 0 == ( pPool = pPool->pSecondary ) )
1592 			return sal_False;
1593 
1594 	DBG_ASSERT( !pImp->bInSetItem || !rItem.ISA(SfxSetItem),
1595 				"SetItem contains ItemSet with SetItem" );
1596 
1597 	sal_uInt16 nSlotId = pPool->GetSlotId( rItem.Which(), sal_True );
1598 	sal_uInt16 nItemVersion = rItem.GetVersion(_nFileFormatVersion);
1599 	if ( USHRT_MAX == nItemVersion )
1600 		return sal_False;
1601 
1602 	rStream << rItem.Which() << nSlotId;
1603 	if ( bDirect || !pPool->StoreSurrogate( rStream, &rItem ) )
1604 	{
1605 		rStream << nItemVersion;
1606 		rStream << (sal_uInt32) 0L; 		  // Platz fuer Laenge in Bytes
1607 		sal_uLong nIStart = rStream.Tell();
1608 		rItem.Store(rStream, nItemVersion);
1609 		sal_uLong nIEnd = rStream.Tell();
1610 		rStream.Seek( nIStart-4 );
1611 		rStream << (sal_Int32) ( nIEnd-nIStart );
1612 		rStream.Seek( nIEnd );
1613 	}
1614 
1615 	return sal_True;
1616 }
1617 
1618 //-------------------------------------------------------------------------
1619 
1620 
1621 const SfxPoolItem* SfxItemPool::LoadItem( SvStream &rStream, FASTBOOL bDirect,
1622 										  const SfxItemPool *pRefPool )
1623 
1624 // pRefPool==-1 => nicht putten!
1625 
1626 {
1627 	sal_uInt16 nWhich(0), nSlot(0); // nSurrogate;
1628 	rStream >> nWhich >> nSlot;
1629 
1630 	sal_Bool bDontPut = (SfxItemPool*)-1 == pRefPool;
1631 	if ( bDontPut || !pRefPool )
1632 		pRefPool = this;
1633 
1634 	// richtigen Sekund"ar-Pool finden
1635 	while ( !pRefPool->IsInVersionsRange(nWhich) )
1636 	{
1637 		if ( pRefPool->pSecondary )
1638 			pRefPool = pRefPool->pSecondary;
1639 		else
1640 		{
1641 			// WID in der Version nicht vorhanden => ueberspringen
1642 			sal_uInt32 nSurro(0);
1643 			sal_uInt16 nVersion(0), nLen(0);
1644 			rStream >> nSurro;
1645 			if ( SFX_ITEMS_DIRECT == nSurro )
1646 			{
1647 				rStream >> nVersion >> nLen;
1648 				rStream.SeekRel( nLen );
1649 			}
1650 			return 0;
1651 		}
1652 	}
1653 
1654 	// wird eine andere Version geladen?
1655 	FASTBOOL bCurVersion = pRefPool->IsCurrentVersionLoading();
1656 	if ( !bCurVersion )
1657 		// Which-Id auf neue Version mappen
1658 		nWhich = pRefPool->GetNewWhich( nWhich );
1659 
1660 	DBG_ASSERT( !nWhich || !pImp->bInSetItem ||
1661 				!pRefPool->ppStaticDefaults[pRefPool->GetIndex_Impl(nWhich)]->ISA(SfxSetItem),
1662 				"loading SetItem in ItemSet of SetItem" );
1663 
1664 	// soll "uber Surrogat geladen werden?
1665 	const SfxPoolItem *pItem = 0;
1666 	if ( !bDirect )
1667 	{
1668 		// Which-Id in dieser Version bekannt?
1669 		if ( nWhich )
1670 			// Surrogat laden, reagieren falls keins vorhanden
1671 			pItem = LoadSurrogate( rStream, nWhich, nSlot, pRefPool );
1672 		else
1673 			// sonst "uberspringen
1674 			rStream.SeekRel( sizeof(sal_uInt16) );
1675 	}
1676 
1677 	// wird direkt, also nicht "uber Surrogat geladen?
1678 	if ( bDirect || ( nWhich && !pItem ) )
1679 	{
1680 		// bDirekt bzw. nicht IsPoolable() => Item direkt laden
1681 		sal_uInt16 nVersion(0);
1682 		sal_uInt32 nLen(0);
1683 		rStream >> nVersion >> nLen;
1684 		sal_uLong nIStart = rStream.Tell();
1685 
1686 		// Which-Id in dieser Version bekannt?
1687 		if ( nWhich )
1688 		{
1689 			// Item direkt laden
1690 			SfxPoolItem *pNewItem =
1691 					pRefPool->GetDefaultItem(nWhich).Create(rStream, nVersion);
1692 			if ( bDontPut )
1693 				pItem = pNewItem;
1694 			else
1695 				if ( pNewItem )
1696 				{
1697 					pItem = &Put(*pNewItem);
1698 					delete pNewItem;
1699 				}
1700 				else
1701 					pItem = 0;
1702 			sal_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 );
1706 		}
1707 		else
1708 			// Item "uberspringen
1709 			rStream.Seek( nIStart+nLen );
1710 	}
1711 
1712 	return pItem;
1713 }
1714 
1715 
1716