xref: /aoo41x/main/svl/source/items/poolio.cxx (revision cdf0e10c)
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;
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, nHStart, nHEnd;
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 				for ( sal_uInt16 n = 0; n < nCount; ++n )
620 					rStream >> pMap[n];
621 				SetVersionMap( nVersion, nHStart, nHEnd, pMap );
622 			}
623 		}
624 		pImp->nVersion = nOwnVersion;
625 	}
626 
627 	// Items laden
628 	FASTBOOL bSecondaryLoaded = sal_False;
629 	long nSecondaryEnd = 0;
630 	{
631 		SfxMultiRecordReader aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS);
632 		while ( aWhichIdsRec.GetContent() )
633 		{
634 			// SlotId, Which-Id und Item-Version besorgen
635 			sal_uInt32 nCount;
636 			sal_uInt16 nVersion, nWhich;
637 			//!sal_uInt16 nSlotId = aWhichIdsRec.GetContentTag();
638 			rStream >> nWhich;
639 			if ( pImp->nLoadingVersion != pImp->nVersion )
640 				// Which-Id aus File-Version in Pool-Version verschieben
641 				nWhich = GetNewWhich( nWhich );
642 
643 			// unbekanntes Item aus neuerer Version
644 			if ( !IsInRange(nWhich) )
645 				continue;
646 
647 			rStream >> nVersion;
648 			rStream >> nCount;
649 			//!SFX_ASSERTWARNING( !nSlotId || !HasMap() ||
650 			//!			( nSlotId == GetSlotId( nWhich, sal_False ) ) ||
651 			//!			!GetSlotId( nWhich, sal_False ),
652 			//!			nWhich, "Slot/Which mismatch" );
653 
654 			sal_uInt16 nIndex = GetIndex_Impl(nWhich);
655 			SfxPoolItemArray_Impl **ppArr = pImp->ppPoolItems + nIndex;
656 
657 			// SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
658 			SfxPoolItem *pDefItem = *(ppStaticDefaults + nIndex);
659 			pImp->bInSetItem = pDefItem->ISA(SfxSetItem);
660 			if ( !bSecondaryLoaded && pSecondary && pImp->bInSetItem )
661 			{
662 				// an das Ende des eigenen Pools seeken
663 				sal_uLong nLastPos = rStream.Tell();
664 				aPoolRec.Skip();
665 
666 				// Sekund"arpool einlesen
667 				pSecondary->Load( rStream );
668 				bSecondaryLoaded = sal_True;
669 				nSecondaryEnd = rStream.Tell();
670 
671 				// zur"uck zu unseren eigenen Items
672 				rStream.Seek(nLastPos);
673 			}
674 
675 			// Items an sich lesen
676 			readTheItems(rStream, nCount, nVersion, pDefItem, ppArr);
677 
678 			pImp->bInSetItem = sal_False;
679 		}
680 	}
681 
682 	// Pool-Defaults lesen
683 	{
684 		SfxMultiRecordReader aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS );
685 
686 		while ( aDefsRec.GetContent() )
687 		{
688 			// SlotId, Which-Id und Item-Version besorgen
689 			sal_uInt16 nVersion, nWhich;
690 			//!sal_uInt16 nSlotId = aDefsRec.GetContentTag();
691 			rStream >> nWhich;
692 			if ( pImp->nLoadingVersion != pImp->nVersion )
693 				// Which-Id aus File-Version in Pool-Version verschieben
694 				nWhich = GetNewWhich( nWhich );
695 
696 			// unbekanntes Item aus neuerer Version
697 			if ( !IsInRange(nWhich) )
698 				continue;
699 
700 			rStream >> nVersion;
701 			//!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, sal_False ) ),
702 			//!			nWhich, "Slot/Which mismatch" );
703 
704 			// Pool-Default-Item selbst laden
705 			SfxPoolItem *pItem =
706 					( *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
707 					->Create( rStream, nVersion );
708 			pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
709 			*( ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
710 		}
711 	}
712 
713 	// ggf. Secondary-Pool laden
714 	aPoolRec.Skip();
715 	if ( pSecondary )
716 	{
717 		if ( !bSecondaryLoaded )
718 			pSecondary->Load( rStream );
719 		else
720 			rStream.Seek( nSecondaryEnd );
721 	}
722 
723 	// wenn nicht own-Pool, dann kein Name
724 	if ( aExternName != aName )
725 		aName.Erase();
726 
727 	pImp->bStreaming = sal_False;
728 	return rStream;
729 };
730 
731 // -----------------------------------------------------------------------
732 
733 SvStream &SfxItemPool::Load1_Impl(SvStream &rStream)
734 {
735 	// beim Master ist der Header schon von <Load()> geladen worden
736 	if ( !pImp->bStreaming )
737 	{
738 		// Header des Secondary lesen
739 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_STARTPOOL_4 );
740 		rStream >> pImp->nMajorVer >> pImp->nMinorVer;
741 	}
742 	sal_uInt32 nAttribSize;
743 	int bOwnPool = sal_True;
744 	UniString aExternName;
745 	if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 2 )
746 		rStream >> pImp->nLoadingVersion;
747 	SfxPoolItem::readByteString(rStream, aExternName);
748 	bOwnPool = aExternName == aName;
749 	pImp->bStreaming = sal_True;
750 
751 	//! solange wir keine fremden laden k"onnen
752 	if ( !bOwnPool )
753 	{
754 		rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
755 		pImp->bStreaming = sal_False;
756 		return rStream;
757 	}
758 
759 	// Versionen bis 1.3 k"onnen noch keine Which-Verschiebungen lesen
760 	if ( pImp->nMajorVer == 1 && pImp->nMinorVer <= 2 &&
761 		 pImp->nVersion < pImp->nLoadingVersion )
762 	{
763 		rStream.SetError(ERRCODE_IO_WRONGVERSION);
764 		pImp->bStreaming = sal_False;
765 		return rStream;
766 	}
767 
768 	// Size-Table liegt hinter den eigentlichen Attributen
769 	rStream >> nAttribSize;
770 
771 	// Size-Table einlesen
772 	sal_uLong nStartPos = rStream.Tell();
773 	rStream.SeekRel( nAttribSize );
774 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_SIZES );
775 	sal_uInt32 nSizeTableLen;
776 	rStream >> nSizeTableLen;
777 	sal_Char *pBuf = new sal_Char[nSizeTableLen];
778 	rStream.Read( pBuf, nSizeTableLen );
779 	sal_uLong nEndOfSizes = rStream.Tell();
780 	SvMemoryStream aSizeTable( pBuf, nSizeTableLen, STREAM_READ );
781 
782 	// ab Version 1.3 steht in der Size-Table eine Versions-Map
783 	if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 3 )
784 	{
785 		// Version-Map finden (letztes sal_uLong der Size-Table gibt Pos an)
786 		rStream.Seek( nEndOfSizes - sizeof(sal_uInt32) );
787 		sal_uInt32 nVersionMapPos;
788 		rStream >> nVersionMapPos;
789 		rStream.Seek( nVersionMapPos );
790 
791 		// Versions-Maps einlesen
792 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_VERSIONMAP );
793 		sal_uInt16 nVerCount;
794 		rStream >> nVerCount;
795 		for ( sal_uInt16 nVerNo = 0; nVerNo < nVerCount; ++nVerNo )
796 		{
797 			// Header f"ur einzelne Version einlesen
798 			sal_uInt16 nVersion, nHStart, nHEnd;
799 			rStream >> nVersion >> nHStart >> nHEnd;
800 			sal_uInt16 nCount = nHEnd - nHStart + 1;
801 			sal_uInt16 nBytes = (nCount)*sizeof(sal_uInt16);
802 
803 			// Is new version is known?
804 			if ( nVerNo >= pImp->aVersions.size() )
805 			{
806 				// Add new Version
807 				sal_uInt16 *pMap = new sal_uInt16[nCount];
808 				for ( sal_uInt16 n = 0; n < nCount; ++n )
809 					rStream >> pMap[n];
810 				SetVersionMap( nVersion, nHStart, nHEnd, pMap );
811 			}
812 			else
813 				// Version schon bekannt => "uberspringen
814 				rStream.SeekRel( nBytes );
815 		}
816 	}
817 
818 	// Items laden
819 	rStream.Seek( nStartPos );
820 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ITEMS );
821 	FASTBOOL bSecondaryLoaded = sal_False;
822 	long nSecondaryEnd = 0;
823 	sal_uInt16 nWhich, nSlot;
824 	while ( rStream >> nWhich, nWhich )
825 	{
826 		// ggf. Which-Id aus alter Version verschieben?
827 		if ( pImp->nLoadingVersion != pImp->nVersion )
828 			nWhich = GetNewWhich( nWhich );
829 
830 		rStream >> nSlot;
831 		sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False);
832 		int bKnownItem = bOwnPool || IsWhich(nMappedWhich);
833 
834 		sal_uInt16 nRef, nCount, nVersion;
835 		sal_uInt32 nAttrSize;
836 		rStream >> nVersion >> nCount;
837 
838 		SfxPoolItemArray_Impl **ppArr = 0;
839 		SfxPoolItemArray_Impl *pNewArr = 0;
840 		SfxPoolItem *pDefItem = 0;
841 		if ( bKnownItem )
842 		{
843 			if ( !bOwnPool )
844 				nWhich = nMappedWhich;
845 
846 			//!SFX_ASSERTWARNING( !nSlot || !HasMap() ||
847 			//!			( nSlot == GetSlotId( nWhich, sal_False ) ) ||
848 			//!			!GetSlotId( nWhich, sal_False ),
849 			//!			nWhich, "Slot/Which mismatch" );
850 
851 			sal_uInt16 nIndex = GetIndex_Impl(nWhich);
852 			ppArr = pImp->ppPoolItems + nIndex;
853 			pNewArr = new SfxPoolItemArray_Impl();
854 			pDefItem = *(ppStaticDefaults + nIndex);
855 		}
856 
857 		// Position vor ersten Item merken
858 		sal_uLong nLastPos = rStream.Tell();
859 
860 		// SfxSetItems k"onnten Items aus Sekund"arpools beinhalten
861 		if ( !bSecondaryLoaded && pSecondary && pDefItem->ISA(SfxSetItem) )
862 		{
863 			// an das Ende des eigenen Pools seeken
864 			rStream.Seek(nEndOfSizes);
865             CHECK_FILEFORMAT_RELEASE( rStream, SFX_ITEMPOOL_TAG_ENDPOOL, pNewArr );
866             CHECK_FILEFORMAT_RELEASE( rStream, SFX_ITEMPOOL_TAG_ENDPOOL, pNewArr );
867 
868 			// Sekund"arpool einlesen
869 			pSecondary->Load1_Impl( rStream );
870 			bSecondaryLoaded = sal_True;
871 			nSecondaryEnd = rStream.Tell();
872 
873 			// zur"uck zu unseren eigenen Items
874 			rStream.Seek(nLastPos);
875 		}
876 
877 		// Items an sich lesen
878 		for ( sal_uInt16 j = 0; j < nCount; ++j )
879 		{
880 			sal_uLong nPos = nLastPos;
881 			rStream >> nRef;
882 
883 			if ( bKnownItem )
884 			{
885 				SfxPoolItem *pItem = 0;
886 				if ( nRef )
887 				{
888 					pItem = pDefItem->Create(rStream, nVersion);
889 
890 					if ( !bPersistentRefCounts )
891 						// bis <SfxItemPool::LoadCompleted()> festhalten
892 						AddRef(*pItem, 1);
893 					else
894 					{
895 						if ( nRef > SFX_ITEMS_OLD_MAXREF )
896 							pItem->SetKind( nRef );
897 						else
898 							AddRef(*pItem, nRef);
899 					}
900 				}
901 				//pNewArr->insert( pItem, j );
902 				pNewArr->push_back( (SfxPoolItem*) pItem );
903 
904 				// restliche gespeicherte Laenge skippen (neueres Format)
905 				nLastPos = rStream.Tell();
906 			}
907 
908 			aSizeTable >> nAttrSize;
909 			SFX_ASSERT( !bKnownItem || ( nPos + nAttrSize) >= nLastPos,
910 						nPos,
911 						"too many bytes read - version mismatch?" );
912 
913 			if ( !bKnownItem || ( nLastPos < (nPos + nAttrSize) ) )
914 			{
915 				nLastPos = nPos + nAttrSize;
916 				rStream.Seek( nLastPos );
917 			}
918 		}
919 
920 		if ( bKnownItem )
921 		{
922 			SfxPoolItemArray_Impl *pOldArr = *ppArr;
923 			*ppArr = pNewArr;
924 
925 			// die Items merken, die schon im Pool sind
926 			int bEmpty = sal_True;
927 			if ( 0 != pOldArr )
928 				for ( size_t n = 0; bEmpty && n < pOldArr->size(); ++n )
929 					bEmpty = pOldArr->operator[](n) == 0;
930 			DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" );
931 			if ( !bEmpty )
932 			{
933 				// f"ur alle alten suchen, ob ein gleiches neues existiert
934 				for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld )
935 				{
936 					SfxPoolItem *pOldItem = (*pOldArr)[nOld];
937 					if ( pOldItem )
938 					{
939 						bool bFound = false;
940 						for ( size_t nNew = 0;
941 							  nNew < (*ppArr)->size();  ++nNew )
942 						{
943 							SfxPoolItem *&rpNewItem =
944 								(SfxPoolItem*&)(*ppArr)->operator[](nNew);
945 
946 							if ( rpNewItem && *rpNewItem == *pOldItem )
947 							{
948 								AddRef( *pOldItem, rpNewItem->GetRefCount() );
949 								SetRefCount( *rpNewItem, 0 );
950 								delete rpNewItem;
951 								rpNewItem = pOldItem;
952 								bFound = true;
953 								SFX_TRACE( "reusing item", pOldItem );
954 								break;
955 							}
956 						}
957 						if ( !bFound )
958                         {
959 							SFX_TRACE( "item not found: ", pOldItem );
960                         }
961 					}
962 				}
963 			}
964 			delete pOldArr; /* @@@ */
965 		}
966 	}
967 
968 	// Pool-Defaults lesen
969 	if ( pImp->nMajorVer > 1 || pImp->nMinorVer > 0 )
970 		CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_DEFAULTS );
971 
972 	sal_uLong nLastPos = rStream.Tell();
973 	while ( rStream >> nWhich, nWhich )
974 	{
975 		// ggf. Which-Id aus alter Version verschieben?
976 		if ( pImp->nLoadingVersion != pImp->nVersion )
977 			nWhich = GetNewWhich( nWhich );
978 
979 		rStream >> nSlot;
980 		sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False);
981 		int bKnownItem = bOwnPool || IsWhich(nMappedWhich);
982 
983 		sal_uLong nPos = nLastPos;
984 		sal_uInt32 nSize;
985 		sal_uInt16 nVersion;
986 		rStream >> nVersion;
987 
988 		if ( bKnownItem )
989 		{
990 			if ( !bOwnPool )
991 				nWhich = nMappedWhich;
992 			SfxPoolItem *pItem =
993 				( *( ppStaticDefaults + GetIndex_Impl(nWhich) ) )
994 				->Create( rStream, nVersion );
995 			pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
996 			*( ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
997 		}
998 
999 		nLastPos = rStream.Tell();
1000 		aSizeTable >> nSize;
1001 		SFX_ASSERT( ( nPos + nSize) >= nLastPos, nPos,
1002 					"too many bytes read - version mismatch?" );
1003 		if ( nLastPos < (nPos + nSize) )
1004 			rStream.Seek( nPos + nSize );
1005 	}
1006 
1007 	delete[] pBuf;
1008 	rStream.Seek(nEndOfSizes);
1009 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL );
1010 	CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL );
1011 
1012 	if ( pSecondary )
1013 	{
1014 		if ( !bSecondaryLoaded )
1015 			pSecondary->Load1_Impl( rStream );
1016 		else
1017 			rStream.Seek( nSecondaryEnd );
1018 	}
1019 
1020 	if ( aExternName != aName )
1021 		aName.Erase();
1022 
1023 	pImp->bStreaming = sal_False;
1024 	return rStream;
1025 }
1026 
1027 // -----------------------------------------------------------------------
1028 
1029 const SfxPoolItem* SfxItemPool::LoadSurrogate
1030 (
1031 	SvStream&			rStream,	// vor einem Surrogat positionierter Stream
1032 	sal_uInt16& 			rWhich, 	// Which-Id des zu ladenden <SfxPoolItem>s
1033 	sal_uInt16				nSlotId,	// Slot-Id des zu ladenden <SfxPoolItem>s
1034 	const SfxItemPool*	pRefPool	// <SfxItemPool> in dem das Surrogat gilt
1035 )
1036 
1037 /*	[Beschreibung]
1038 
1039 	L"adt Surrogat aus 'rStream' und liefert das dadurch in 'rRefPool'
1040 	repr"asentierte SfxPoolItem zu"ruck. Ist das im Stream befindliche
1041 	Surrogat == SFX_ITEMS_DIRECT (!SFX_ITEM_POOLABLE) wird 0 zur"uckgegeben,
1042 	das Item ist direkt aus dem Stream zu laden. Bei 0xfffffff0 (SFX_ITEMS_NULL)
1043 	wird auch 0 zurueckgegeben und rWhich auf 0 gesetzt, das Item ist nicht
1044 	verfuegbar.
1045 
1046 	Ansonsten wird ber"ucksichtigt, ob der betroffene Pool ohne Ref-Counts
1047 	geladen wird, ob aus einem neuen Pool nachgeladen wird (&rRefPool != this)
1048 	oder ob aus einem g"anzlich anders aufgebauten Pool geladen wird.
1049 
1050 	Wird aus einem anders aufgebauten Pool geladen und die 'nSlotId' kann
1051 	nicht in eine Which-Id dieses Pools gemappt werden, wird ebenfalls 0
1052 	zur"uckgeliefert.
1053 
1054 	Preconditions:	- Pool mu\s geladen sein
1055 					- LoadCompleted darf noch nicht gerufen worden sein
1056 					- 'rStream' steht genau an der Position, an der ein
1057 					  Surrogat f"ur ein Item mit der SlotId 'nSlotId' und
1058 					  der WhichId 'rWhichId' mit StoreSurrogate gepeichert
1059 					  wurde
1060 
1061 	Postconditions:	- 'rStream' ist so positioniert, wie auch StoreSurrogate
1062 					  sein speichern beendet hatte
1063 					- konnte ein Item geladen werden, befindet es sich
1064 					  in diesem SfxItemPool
1065 					- 'rWhichId' enth"alt die ggf. gemappte Which-Id
1066 	Laufzeit:       Tiefe des Ziel Sekund"arpools * 10 + 10
1067 
1068 	[Querverweise]
1069 
1070 	<SfxItemPool::StoreSurrogate(SvStream&,const SfxPoolItem &)const>
1071 */
1072 
1073 {
1074 	// Read the first surrogate
1075 	sal_uInt32 nSurrogat;
1076 	rStream >> nSurrogat;
1077 
1078 	// Is item stored directly?
1079 	if ( SFX_ITEMS_DIRECT == nSurrogat )
1080 		return 0;
1081 
1082 	// Item does not exist?
1083 	if ( SFX_ITEMS_NULL == nSurrogat )
1084 	{
1085 		rWhich = 0;
1086 		return 0;
1087 	}
1088 
1089 	// Bei einem identisch aufgebauten Pool (im Stream) kann das Surrogat
1090 	// auf jeden Fall aufgel"ost werden.
1091 	if ( !pRefPool )
1092 		pRefPool = this;
1093 	FASTBOOL bResolvable = pRefPool->GetName().Len() > 0;
1094 	if ( !bResolvable )
1095 	{
1096 		// Bei einem anders aufgebauten Pool im Stream, mu\s die SlotId
1097 		// aus dem Stream in eine Which-Id gemappt werden k"onnen.
1098 		sal_uInt16 nMappedWhich = nSlotId ? GetWhich(nSlotId, sal_True) : 0;
1099 		if ( IsWhich(nMappedWhich) )
1100 		{
1101 			// gemappte SlotId kann "ubernommen werden
1102 			rWhich = nMappedWhich;
1103 			bResolvable = sal_True;
1104 		}
1105 	}
1106 
1107 	// kann Surrogat aufgel"ost werden?
1108 	const SfxPoolItem *pItem = 0;
1109 	if ( bResolvable )
1110 	{
1111 		for ( SfxItemPool *pTarget = this; pTarget; pTarget = pTarget->pSecondary )
1112 		{
1113 			// richtigen (Folge-) Pool gefunden?
1114 			if ( pTarget->IsInRange(rWhich) )
1115 			{
1116 				// dflt-Attribut?
1117 				if ( SFX_ITEMS_DEFAULT == nSurrogat )
1118 					return *(pTarget->ppStaticDefaults +
1119 							pTarget->GetIndex_Impl(rWhich));
1120 
1121 				SfxPoolItemArray_Impl* pItemArr = *(pTarget->pImp->ppPoolItems +
1122 						pTarget->GetIndex_Impl(rWhich));
1123 				pItem = pItemArr && nSurrogat < pItemArr->size()
1124 							? (*pItemArr)[nSurrogat]
1125 							: 0;
1126 				if ( !pItem )
1127 				{
1128 					DBG_ERROR( "can't resolve surrogate" );
1129 					rWhich = 0; // nur zur Sicherheit fuer richtige Stream-Pos
1130 					return 0;
1131 				}
1132 
1133 				// Nachladen aus Ref-Pool?
1134 				if ( pRefPool != pMaster )
1135 					return &pTarget->Put( *pItem );
1136 
1137 				// Referenzen sind NICHT schon mit Pool geladen worden?
1138 				if ( !pTarget->HasPersistentRefCounts() )
1139 					AddRef( *pItem, 1 );
1140 				else
1141 					return pItem;
1142 
1143 				return pItem;
1144 			}
1145 		}
1146 
1147 		SFX_ASSERT( sal_False, rWhich, "can't resolve Which-Id in LoadSurrogate" );
1148 	}
1149 
1150 	return 0;
1151 }
1152 
1153 //-------------------------------------------------------------------------
1154 
1155 
1156 FASTBOOL SfxItemPool::StoreSurrogate
1157 (
1158 	SvStream&			rStream,
1159 	const SfxPoolItem* 	pItem
1160 )	const
1161 
1162 /*	[Beschreibung]
1163 
1164 	Speichert ein Surrogat f"ur '*pItem' in 'rStream'.
1165 
1166 
1167 	[R"uckgabewert]
1168 
1169 	FASTBOOL				sal_True
1170 							es wurde ein echtes Surrogat gespeichert, auch
1171 							SFX_ITEMS_NULL bei 'pItem==0',
1172 							SFX_ITEMS_STATICDEFAULT und SFX_ITEMS_POOLDEFAULT
1173 							gelten als 'echte' Surrogate
1174 
1175 							sal_False
1176 							es wurde ein Dummy-Surrogat (SFX_ITEMS_DIRECT)
1177 							gespeichert, das eigentliche Item mu\s direkt
1178 							hinterher selbst gespeichert werden
1179 */
1180 
1181 {
1182 	if ( pItem )
1183 	{
1184 		FASTBOOL bRealSurrogate = IsItemFlag(*pItem, SFX_ITEM_POOLABLE);
1185 		rStream << ( bRealSurrogate
1186 						? GetSurrogate( pItem )
1187 						: SFX_ITEMS_DIRECT );
1188 		return bRealSurrogate;
1189 	}
1190 
1191     rStream << SFX_ITEMS_NULL;
1192 	return sal_True;
1193 }
1194 
1195 // -----------------------------------------------------------------------
1196 
1197 sal_uInt32 SfxItemPool::GetSurrogate(const SfxPoolItem *pItem) const
1198 {
1199 	DBG_CHKTHIS(SfxItemPool, 0);
1200 	DBG_ASSERT( pItem, "no 0-Pointer Surrogate" );
1201 	DBG_ASSERT( !IsInvalidItem(pItem), "no Invalid-Item Surrogate" );
1202 	DBG_ASSERT( !IsPoolDefaultItem(pItem), "no Pool-Default-Item Surrogate" );
1203 
1204 	if ( !IsInRange(pItem->Which()) )
1205 	{
1206 		if ( pSecondary )
1207 			return pSecondary->GetSurrogate( pItem );
1208 		SFX_ASSERT( 0, pItem->Which(), "unknown Which-Id - dont ask me for surrogates" );
1209 	}
1210 
1211 	// Pointer auf static- oder pool-dflt-Attribut?
1212 	if( IsStaticDefaultItem(pItem) || IsPoolDefaultItem(pItem) )
1213 		return SFX_ITEMS_DEFAULT;
1214 
1215 	SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(pItem->Which()));
1216 	DBG_ASSERT(pItemArr, "ItemArr is not available");
1217 
1218 	for ( size_t i = 0; i < pItemArr->size(); ++i )
1219 	{
1220 		const SfxPoolItem *p = (*pItemArr)[i];
1221 		if ( p == pItem )
1222 			return i;
1223 	}
1224 	SFX_ASSERT( 0, pItem->Which(), "Item not in the pool");
1225 	return SFX_ITEMS_NULL;
1226 }
1227 
1228 // -----------------------------------------------------------------------
1229 
1230 FASTBOOL SfxItemPool::IsInStoringRange( sal_uInt16 nWhich ) const
1231 {
1232 	return nWhich >= pImp->nStoringStart &&
1233 		   nWhich <= pImp->nStoringEnd;
1234 }
1235 
1236 //------------------------------------------------------------------------
1237 
1238 void SfxItemPool::SetStoringRange( sal_uInt16 nFrom, sal_uInt16 nTo )
1239 
1240 /*	[Beschreibung]
1241 
1242 	Mit dieser Methode kann der Which-Bereich eingeengt werden, der
1243 	von ItemSets dieses Pool (und dem Pool selbst) gespeichert wird.
1244 	Die Methode muss dazu vor <SfxItemPool::Store()> gerufen werden
1245 	und die Werte muessen auch noch gesetzt sein, wenn das eigentliche
1246 	Dokument (also die ItemSets gespeicher werden).
1247 
1248 	Ein Zuruecksetzen ist dann nicht noetig, wenn dieser Range vor
1249 	JEDEM Speichern richtig gesetzt wird, da er nur beim Speichern
1250 	beruecksichtigt wird.
1251 
1252 	Dieses muss fuer das 3.1-Format gemacht werden, da dort eine
1253 	Bug in der Pool-Lade-Methode vorliegt.
1254 */
1255 
1256 {
1257 	pImp->nStoringStart = nFrom;
1258 	pImp->nStoringEnd = nTo;
1259 }
1260 
1261 // -----------------------------------------------------------------------
1262 
1263 void SfxItemPool::SetVersionMap
1264 (
1265 	sal_uInt16 	nVer, 				/* 	neue Versionsnummer */
1266 	sal_uInt16  nOldStart,          /*  alte erste Which-Id */
1267 	sal_uInt16  nOldEnd,            /*  alte letzte Which-Id */
1268 	sal_uInt16*	pOldWhichIdTab		/* 	Array mit genau dem Aufbau der Which-Ids
1269 									der vorhergehenden Version, in denen
1270 									die jeweils neue Which-Id steht. */
1271 )
1272 
1273 /*	[Beschreibung]
1274 
1275 	Mit dieser Methode k"onnen neue, inkompatible Which-Id-Folgen oder
1276 	Verteilungen realisiert werden. Pools, die noch mit alten Versionen
1277 	gespeichert wurden, werden dann "uber die angegebene Tabelle solange
1278 	gemappt, bis die aktuelle Version erreicht ist. Neuere Pools k"onnen
1279 	unter Verlust neuer Attribute geladen werden, da die Map mit dem Pool
1280 	gespeichert wird.
1281 
1282 	Precondition:	Pool darf noch nicht geladen sein
1283 	Postcondition:	Which-Ids aus fr"uheren Versionen k"onnen bei Laden auf
1284 					Version 'nVer' gemappt werden
1285 	Laufzeit:       1.5 * new + 10
1286 
1287 	[Anmerkung]
1288 
1289 	F"ur neue Which-Ranges (nStart,nEnd) m"ssen im Vergleich zur Vorg"anger-
1290 	Version (nOldStart,nOldEnd) immer gelten, da\s (nOldStart,nOldEnd)
1291 	vollst"andig in (nStart,nEnd) enthalten ist. Es ist also zul"assig, den
1292 	Which-Range in beide Richtungen zu erweitern, auch durch Einf"ugung
1293 	von Which-Ids, nicht aber ihn zu beschneiden.
1294 
1295 	Diese Methode sollte nur im oder direkt nach Aufruf des Konstruktors
1296 	gerufen werden.
1297 
1298 	Das Array mu\s statisch sein, da es nicht kopiert wird und au\serdem
1299 	im Copy-Ctor des SfxItemPool wiederverwendet wird.
1300 
1301 
1302 	[Beispiel]
1303 
1304 	Urspr"unglich (Version 0) hatte der Pool folgende Which-Ids:
1305 
1306 		1:A, 2:B, 3:C, 4:D
1307 
1308 	Nun soll eine neue Version (Version 1) zwei zus"atzliche Ids X und Y
1309 	zwischen B und C erhalten, also wie folgt aussehen:
1310 
1311 		1:A, 2:B, 3:X, 4:Y, 5:C, 6:D
1312 
1313 	Dabei haben sich also die Ids 3 und 4 ge"andert. F"ur die neue Version
1314 	m"u\ste am Pool folgendes gesetzt werden:
1315 
1316 		static sal_uInt16 nVersion1Map = { 1, 2, 5, 6 };
1317 		pPool->SetVersionMap( 1, 1, 4, &nVersion1Map );
1318 
1319 
1320 	[Querverweise]
1321 
1322 	<SfxItemPool::IsLoadingVersionCurrent()const>
1323 	<SfxItemPool::GetNewWhich(sal_uInt16)>
1324 	<SfxItemPool::GetVersion()const>
1325 	<SfxItemPool::GetLoadingVersion()const>
1326 */
1327 
1328 {
1329 	// create new map entry to insert
1330 	const SfxPoolVersion_ImplPtr pVerMap = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl(
1331 				nVer, nOldStart, nOldEnd, pOldWhichIdTab ) );
1332 	pImp->aVersions.push_back( pVerMap );
1333 
1334 	DBG_ASSERT( nVer > pImp->nVersion, "Versions not sorted" );
1335 	pImp->nVersion = nVer;
1336 
1337 	// Versions-Range anpassen
1338 	for ( sal_uInt16 n = 0; n < nOldEnd-nOldStart+1; ++n )
1339 	{
1340 		sal_uInt16 nWhich = pOldWhichIdTab[n];
1341 		if ( nWhich < pImp->nVerStart )
1342 		{
1343 			if ( !nWhich )
1344 				nWhich = 0;
1345 			pImp->nVerStart = nWhich;
1346 		}
1347 		else if ( nWhich > pImp->nVerEnd )
1348 			pImp->nVerEnd = nWhich;
1349 	}
1350 }
1351 
1352 // -----------------------------------------------------------------------
1353 
1354 sal_uInt16 SfxItemPool::GetNewWhich
1355 (
1356 	sal_uInt16	nFileWhich		// die aus dem Stream geladene Which-Id
1357 )	const
1358 
1359 /*	[Beschreibung]
1360 
1361 	Diese Methoden rechnet Which-Ids aus einem File-Format in die der
1362 	aktuellen Pool-Version um. Ist das File-Format "alter, werden die vom
1363 	Pool-Entwickler mit SetVersion() gesetzten Tabellen verwendet,
1364 	ist das File-Format neuer, dann die aus dem File geladenen Tabellen.
1365 	Im letzteren Fall kann ggf. nicht jede Which-Id gemappt werden,
1366 	so da\s 0 zur"uckgeliefert wird.
1367 
1368 	Die Berechnung ist nur f"ur Which-Ids definiert, die in der betreffenden
1369 	File-Version unterst"utzt wurden. Dies ist per Assertion abgesichert.
1370 
1371 	Precondition:	Pool mu\s geladen sein
1372 	Postcondition:	unver"andert
1373 	Laufzeit:		linear(Anzahl der Sekund"arpools) +
1374 					linear(Differenz zwischen alter und neuer Version)
1375 
1376 
1377 	[Querverweise]
1378 
1379 	<SfxItemPool::IsLoadingVersionCurrent()const>
1380 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1381 	<SfxItemPool::GetVersion()const>
1382 	<SfxItemPool::GetLoadingVersion()const>
1383 */
1384 
1385 {
1386 	// (Sekund"ar-) Pool bestimmen
1387 	if ( !IsInVersionsRange(nFileWhich) )
1388 	{
1389 		if ( pSecondary )
1390 			return pSecondary->GetNewWhich( nFileWhich );
1391 		SFX_ASSERT( 0, nFileWhich, "unknown which in GetNewWhich()" );
1392 	}
1393 
1394 	// Version neuer/gleich/"alter?
1395 	short nDiff = (short)pImp->nLoadingVersion - (short)pImp->nVersion;
1396 
1397 	// Which-Id einer neueren Version?
1398 	if ( nDiff > 0 )
1399 	{
1400 		// von der Top-Version bis runter zur File-Version stufenweise mappen
1401 		for ( size_t nMap = pImp->aVersions.size(); nMap > 0; --nMap )
1402 		{
1403 			SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap-1];
1404 			if ( pVerInfo->_nVer > pImp->nVersion )
1405 			{	sal_uInt16 nOfs;
1406 				sal_uInt16 nCount = pVerInfo->_nEnd - pVerInfo->_nStart + 1;
1407 				for ( nOfs = 0;
1408 					  nOfs <= nCount &&
1409 						pVerInfo->_pMap[nOfs] != nFileWhich;
1410 					  ++nOfs )
1411 					continue;
1412 
1413 				if ( pVerInfo->_pMap[nOfs] == nFileWhich )
1414 					nFileWhich = pVerInfo->_nStart + nOfs;
1415 				else
1416 					return 0;
1417 			}
1418 			else
1419 				break;
1420 		}
1421 	}
1422 
1423 	// Which-Id einer neueren Version?
1424 	else if ( nDiff < 0 )
1425 	{
1426 		// von der File-Version bis zur aktuellen Version stufenweise mappen
1427 		for ( size_t nMap = 0; nMap < pImp->aVersions.size(); ++nMap )
1428 		{
1429 			SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap];
1430 			if ( pVerInfo->_nVer > pImp->nLoadingVersion )
1431 			{
1432 				DBG_ASSERT( nFileWhich >= pVerInfo->_nStart &&
1433 							nFileWhich <= pVerInfo->_nEnd,
1434 							"which-id unknown in version" );
1435 				nFileWhich = pVerInfo->_pMap[nFileWhich - pVerInfo->_nStart];
1436 			}
1437 		}
1438 	}
1439 
1440 	// originale (nDiff==0) bzw. gemappte (nDiff!=0) Id zur"uckliefern
1441 	return nFileWhich;
1442 }
1443 
1444 // -----------------------------------------------------------------------
1445 
1446 
1447 FASTBOOL SfxItemPool::IsInVersionsRange( sal_uInt16 nWhich ) const
1448 {
1449 	return nWhich >= pImp->nVerStart && nWhich <= pImp->nVerEnd;
1450 }
1451 
1452 // -----------------------------------------------------------------------
1453 
1454 FASTBOOL SfxItemPool::IsCurrentVersionLoading() const
1455 
1456 /*	[Beschreibung]
1457 
1458 	Mit dieser Methode kann festgestellt werden, ob die geladene Pool-Version
1459 	dem aktuellen Pool-Aufbau entspricht.
1460 
1461 	Precondition:	Pool mu\s geladen sein
1462 	Postcondition:	unver"andert
1463 	Laufzeit:		linear(Anzahl der Sekund"arpools)
1464 
1465 
1466 	[Querverweise]
1467 
1468 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1469 	<SfxItemPool::GetNewWhich(sal_uInt16)const>
1470 	<SfxItemPool::GetVersion()const>
1471 	<SfxItemPool::GetLoadingVersion()const>
1472 */
1473 
1474 {
1475 	return ( pImp->nVersion == pImp->nLoadingVersion ) &&
1476 		   ( !pSecondary || pSecondary->IsCurrentVersionLoading() );
1477 }
1478 
1479 // -----------------------------------------------------------------------
1480 
1481 sal_uInt16 SfxItemPool::GetVersion() const
1482 
1483 /*	[Beschreibung]
1484 
1485 	Diese Methode liefert die aktuelle Versionsnummer des SfxItemPool-Aufbaus
1486 	(also des Which-Bereichs).
1487 
1488 	Precondition:	keine
1489 	Postcondition:	unver"andert
1490 	Laufzeit:       2
1491 
1492 
1493 	[Anmerkung]
1494 
1495 	Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools
1496 	ber"ucksichtigt werden.
1497 
1498 
1499 	[Querverweise]
1500 
1501 	<SfxItemPool::IsLoadingVersionCurrent()const>
1502 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1503 	<SfxItemPool::GetNewWhich(sal_uInt16)const>
1504 	<SfxItemPool::GetLoadingVersion()const>
1505 */
1506 
1507 {
1508 	return pImp->nVersion;
1509 }
1510 
1511 // -----------------------------------------------------------------------
1512 
1513 sal_uInt16 SfxItemPool::GetLoadingVersion() const
1514 
1515 /*	[Beschreibung]
1516 
1517 	Diese Methode liefert die Versionsnummer des SfxItemPool-Aufbaus
1518 	(also des Which-Bereichs), die bei Laden vorgefunden wurde.
1519 
1520 	Precondition:	Pool mu\s geladen sein
1521 	Postcondition:	unver"andert
1522 	Laufzeit:       2
1523 
1524 
1525 	[Anmerkung]
1526 
1527 	Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools
1528 	ber"ucksichtigt werden.
1529 
1530 
1531 	[Querverweise]
1532 
1533 	<SfxItemPool::IsLoadingVersionCurrent()const>
1534 	<SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)>
1535 	<SfxItemPool::GetNewWhich(sal_uInt16)const>
1536 	<SfxItemPool::GetVersion()const>
1537 */
1538 
1539 {
1540 	return pImp->nLoadingVersion;
1541 }
1542 
1543 //-------------------------------------------------------------------------
1544 
1545 FASTBOOL SfxItemPool::IsVer2_Impl() const
1546 {
1547 	return pMaster->pImp->nMajorVer >= 2;
1548 }
1549 
1550 //-------------------------------------------------------------------------
1551 
1552 
1553 FASTBOOL SfxItemPool::StoreItem( SvStream &rStream, const SfxPoolItem &rItem,
1554 								 FASTBOOL bDirect ) const
1555 
1556 /*	[Beschreibung]
1557 
1558 	Speichert das <SfxPoolItem> 'rItem' in den <SvStream> 'rStream'
1559 	entweder als Surrogat ('bDirect == sal_False') oder direkt mit 'rItem.Store()'.
1560 	Nicht poolable Items werden immer direkt gespeichert. Items ohne Which-Id,
1561 	also SID-Items, werden nicht gespeichert, ebenso wenn Items, die in der
1562 	File-Format-Version noch nicht vorhanden waren (return sal_False).
1563 
1564 	Das Item wird im Stream wie folgt abgelegt:
1565 
1566 	sal_uInt16	rItem.Which()
1567 	sal_uInt16	GetSlotId( rItem.Which() ) bzw. 0 falls nicht verf"urbar
1568 	sal_uInt16	GetSurrogate( &rItem ) bzw. SFX_ITEM_DIRECT bei '!SFX_ITEM_POOLBLE'
1569 
1570 	optional (falls 'bDirect == sal_True' oder '!rItem.IsPoolable()':
1571 
1572 	sal_uInt16  rItem.GetVersion()
1573 	sal_uLong 	Size
1574 	Size    rItem.Store()
1575 
1576 
1577 	[Querverweise]
1578 
1579 	<SfxItemPool::LoadItem(SvStream&,FASTBOOL)const>
1580 */
1581 
1582 {
1583 	DBG_ASSERT( !IsInvalidItem(&rItem), "cannot store invalid items" );
1584 
1585 	if ( IsSlot( rItem.Which() ) )
1586 		return sal_False;
1587 	const SfxItemPool *pPool = this;
1588 	while ( !pPool->IsInStoringRange(rItem.Which()) )
1589 		if ( 0 == ( pPool = pPool->pSecondary ) )
1590 			return sal_False;
1591 
1592 	DBG_ASSERT( !pImp->bInSetItem || !rItem.ISA(SfxSetItem),
1593 				"SetItem contains ItemSet with SetItem" );
1594 
1595 	sal_uInt16 nSlotId = pPool->GetSlotId( rItem.Which(), sal_True );
1596 	sal_uInt16 nItemVersion = rItem.GetVersion(_nFileFormatVersion);
1597 	if ( USHRT_MAX == nItemVersion )
1598 		return sal_False;
1599 
1600 	rStream << rItem.Which() << nSlotId;
1601 	if ( bDirect || !pPool->StoreSurrogate( rStream, &rItem ) )
1602 	{
1603 		rStream << nItemVersion;
1604 		rStream << (sal_uInt32) 0L; 		  // Platz fuer Laenge in Bytes
1605 		sal_uLong nIStart = rStream.Tell();
1606 		rItem.Store(rStream, nItemVersion);
1607 		sal_uLong nIEnd = rStream.Tell();
1608 		rStream.Seek( nIStart-4 );
1609 		rStream << (sal_Int32) ( nIEnd-nIStart );
1610 		rStream.Seek( nIEnd );
1611 	}
1612 
1613 	return sal_True;
1614 }
1615 
1616 //-------------------------------------------------------------------------
1617 
1618 
1619 const SfxPoolItem* SfxItemPool::LoadItem( SvStream &rStream, FASTBOOL bDirect,
1620 										  const SfxItemPool *pRefPool )
1621 
1622 // pRefPool==-1 => nicht putten!
1623 
1624 {
1625 	sal_uInt16 nWhich, nSlot; // nSurrogate;
1626 	rStream >> nWhich >> nSlot;
1627 
1628 	sal_Bool bDontPut = (SfxItemPool*)-1 == pRefPool;
1629 	if ( bDontPut || !pRefPool )
1630 		pRefPool = this;
1631 
1632 	// richtigen Sekund"ar-Pool finden
1633 	while ( !pRefPool->IsInVersionsRange(nWhich) )
1634 	{
1635 		if ( pRefPool->pSecondary )
1636 			pRefPool = pRefPool->pSecondary;
1637 		else
1638 		{
1639 			// WID in der Version nicht vorhanden => ueberspringen
1640 			sal_uInt32 nSurro;
1641 			sal_uInt16 nVersion, nLen;
1642 			rStream >> nSurro;
1643 			if ( SFX_ITEMS_DIRECT == nSurro )
1644 			{
1645 				rStream >> nVersion >> nLen;
1646 				rStream.SeekRel( nLen );
1647 			}
1648 			return 0;
1649 		}
1650 	}
1651 
1652 	// wird eine andere Version geladen?
1653 	FASTBOOL bCurVersion = pRefPool->IsCurrentVersionLoading();
1654 	if ( !bCurVersion )
1655 		// Which-Id auf neue Version mappen
1656 		nWhich = pRefPool->GetNewWhich( nWhich );
1657 
1658 	DBG_ASSERT( !nWhich || !pImp->bInSetItem ||
1659 				!pRefPool->ppStaticDefaults[pRefPool->GetIndex_Impl(nWhich)]->ISA(SfxSetItem),
1660 				"loading SetItem in ItemSet of SetItem" );
1661 
1662 	// soll "uber Surrogat geladen werden?
1663 	const SfxPoolItem *pItem = 0;
1664 	if ( !bDirect )
1665 	{
1666 		// Which-Id in dieser Version bekannt?
1667 		if ( nWhich )
1668 			// Surrogat laden, reagieren falls keins vorhanden
1669 			pItem = LoadSurrogate( rStream, nWhich, nSlot, pRefPool );
1670 		else
1671 			// sonst "uberspringen
1672 			rStream.SeekRel( sizeof(sal_uInt16) );
1673 	}
1674 
1675 	// wird direkt, also nicht "uber Surrogat geladen?
1676 	if ( bDirect || ( nWhich && !pItem ) )
1677 	{
1678 		// bDirekt bzw. nicht IsPoolable() => Item direkt laden
1679 		sal_uInt16 nVersion;
1680 		sal_uInt32 nLen;
1681 		rStream >> nVersion >> nLen;
1682 		sal_uLong nIStart = rStream.Tell();
1683 
1684 		// Which-Id in dieser Version bekannt?
1685 		if ( nWhich )
1686 		{
1687 			// Item direkt laden
1688 			SfxPoolItem *pNewItem =
1689 					pRefPool->GetDefaultItem(nWhich).Create(rStream, nVersion);
1690 			if ( bDontPut )
1691 				pItem = pNewItem;
1692 			else
1693 				if ( pNewItem )
1694 				{
1695 					pItem = &Put(*pNewItem);
1696 					delete pNewItem;
1697 				}
1698 				else
1699 					pItem = 0;
1700 			sal_uLong nIEnd = rStream.Tell();
1701 			DBG_ASSERT( nIEnd <= (nIStart+nLen), "read past end of item" );
1702 			if ( (nIStart+nLen) != nIEnd )
1703 				rStream.Seek( nIStart+nLen );
1704 		}
1705 		else
1706 			// Item "uberspringen
1707 			rStream.Seek( nIStart+nLen );
1708 	}
1709 
1710 	return pItem;
1711 }
1712 
1713 
1714