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