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