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