| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svl.hxx" |
| |
| #include <string.h> |
| #include <stdio.h> |
| |
| #ifndef GCC |
| #endif |
| |
| #include <tools/solar.h> |
| #include <svl/itempool.hxx> |
| #include "whassert.hxx" |
| #include <svl/brdcst.hxx> |
| #include <svl/filerec.hxx> |
| #include <svl/svldata.hxx> |
| #include "poolio.hxx" |
| |
| // STATIC DATA ----------------------------------------------------------- |
| |
| DBG_NAME(SfxItemPool); |
| |
| //======================================================================== |
| |
| void SfxItemPool::SetStoringPool( const SfxItemPool *pStoringPool ) |
| |
| /* [Beschreibung] |
| |
| Diese Methode setzt den <SfxItemPool>, der gerade gespeichert wird. |
| Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format- |
| Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines |
| <SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen |
| Pool mit <SfxItemPool::GetStoringPool()> zu besorgen. |
| |
| Sie wird von <SfxItemPool::Store()> bedient, kann jedoch f"ur nicht |
| poolable Items auch direkt gerufen werden. Bitte m"oglichst nicht |
| f"ur jedes Item einzeln, da 2 Calls! |
| */ |
| |
| { |
| ImpSvlData::GetSvlData().pStoringPool = pStoringPool; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| const SfxItemPool* SfxItemPool::GetStoringPool() |
| |
| /* [Beschreibung] |
| |
| Diese Methode liefert den <SfxItemPool>, der gerade gespeichert wird. |
| Sie sollte nur in Notf"allen verwendet werden, um z.B. File-Format- |
| Kompatibilit"at zu gew"ahrleisten o."o. - z.B. in der "uberladung eines |
| <SfxPoolItem::Store()> zus"atzliche Daten aus dem dazuge"horigen |
| Pool zu besorgen. |
| */ |
| |
| { |
| return ImpSvlData::GetSvlData().pStoringPool; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| SvStream &SfxItemPool::Store(SvStream &rStream) const |
| |
| /* [Beschreibung] |
| |
| Der SfxItemPool wird inklusive aller seiner Sekund"arpools mit |
| Pool-Defaults und gepoolten Items in dem angegebenen Stream gespeichert. |
| Die statischen Defaults werden nicht gespeichert. |
| |
| |
| [Fileformat] |
| |
| ;zun"achst ein Kompatiblit"ats-Header-Block |
| Start: 0x1111 SFX_ITEMPOOL_TAG_STARTPOOLS(_4/_5) |
| sal_uInt8 MAJOR_VER ;SfxItemPool-Version |
| sal_uInt8 MINOR_VER ;" |
| 0xFFFF SFX_ITEMPOOL_TAG_TRICK4OLD ;ex. GetVersion() |
| sal_uInt16 0x0000 ;Pseudo-StyleSheetPool |
| sal_uInt16 0x0000 ;Pseudo-StyleSheetPool |
| |
| ;den ganzen Pool in einen Record |
| record SfxMiniRecod(SFX_ITEMPOOL_REC) |
| |
| ;je ein Header vorweg |
| Header: record SfxMiniRecord(SFX_ITEMPOOL_REC_HEADER) |
| sal_uInt16 GetVersion() ;Which-Ranges etc. |
| String GetName() ;Pool-Name |
| |
| ;die Versions-Map, um WhichIds neuer File-Versionen mappen zu k"onnen |
| Versions: record SfxMultiRecord(SFX_ITEMPOOL_REC_VERSIONS, 0) |
| sal_uInt16 OldVersion |
| sal_uInt16 OldStartWhich |
| sal_uInt16 OldEndWhich |
| sal_uInt16[] NewWhich (OldEndWhich-OldStartWhich+1) |
| |
| ;jetzt die gepoolten Items (zuerst nicht-SfxSetItems) |
| Items: record SfxMultiRecord(SFX_ITEMPOOL_REC_WHICHIDS, 0) |
| content SlotId, 0 |
| sal_uInt16 WhichId |
| sal_uInt16 pItem->GetVersion() |
| sal_uInt16 Array-Size |
| record SfxMultiRecord(SFX_, 0) |
| content Surrogate |
| sal_uInt16 RefCount |
| unknown pItem->Store() |
| |
| ;jetzt die gesetzten Pool-Defaults |
| Defaults: record SfxMultiRecord(SFX_ITEMPOOL_REC_DEFAULTS, 0) |
| content SlotId, 0 |
| sal_uInt16 WhichId |
| sal_uInt16 pPoolDef->GetVersion() |
| unknown pPoolDef->Store(); |
| |
| ;dahinter folgt ggf. der Secondary ohne Kompatiblit"ats-Header-Block |
| */ |
| |
| { |
| DBG_CHKTHIS(SfxItemPool, 0); |
| |
| // Store-Master finden |
| SfxItemPool *pStoreMaster = pMaster != this ? pMaster : 0; |
| while ( pStoreMaster && !pStoreMaster->pImp->bStreaming ) |
| pStoreMaster = pStoreMaster->pSecondary; |
| |
| // Alter-Header (Version des Pools an sich und Inhalts-Version 0xffff) |
| pImp->bStreaming = sal_True; |
| if ( !pStoreMaster ) |
| { |
| rStream << ( rStream.GetVersion() >= SOFFICE_FILEFORMAT_50 |
| ? SFX_ITEMPOOL_TAG_STARTPOOL_5 |
| : SFX_ITEMPOOL_TAG_STARTPOOL_4 ); |
| rStream << SFX_ITEMPOOL_VER_MAJOR << SFX_ITEMPOOL_VER_MINOR; |
| rStream << SFX_ITEMPOOL_TAG_TRICK4OLD; |
| |
| // SfxStyleSheet-Bug umgehen |
| rStream << sal_uInt16(0); // Version |
| rStream << sal_uInt16(0); // Count (2. Schleife f"allt sonst auf die Fresse) |
| } |
| |
| // jeder Pool ist als ganzes ein Record |
| SfxMiniRecordWriter aPoolRec( &rStream, SFX_ITEMPOOL_REC ); |
| ImpSvlData::GetSvlData().pStoringPool = this; |
| |
| // Einzel-Header (Version des Inhalts und Name) |
| { |
| SfxMiniRecordWriter aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER); |
| rStream << pImp->nVersion; |
| SfxPoolItem::writeByteString(rStream, aName); |
| } |
| |
| // Version-Maps |
| { |
| SfxMultiVarRecordWriter aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP, 0 ); |
| for ( size_t nVerNo = 0; nVerNo < pImp->aVersions.size(); ++nVerNo ) |
| { |
| aVerRec.NewContent(); |
| SfxPoolVersion_ImplPtr pVer = pImp->aVersions[nVerNo]; |
| rStream << pVer->_nVer << pVer->_nStart << pVer->_nEnd; |
| sal_uInt16 nCount = pVer->_nEnd - pVer->_nStart + 1; |
| sal_uInt16 nNewWhich = 0; |
| for ( sal_uInt16 n = 0; n < nCount; ++n ) |
| { |
| nNewWhich = pVer->_pMap[n]; |
| rStream << nNewWhich; |
| } |
| |
| // Workaround gegen Bug in SetVersionMap der 312 |
| if ( SOFFICE_FILEFORMAT_31 == _nFileFormatVersion ) |
| rStream << sal_uInt16(nNewWhich+1); |
| } |
| } |
| |
| // gepoolte Items |
| { |
| SfxMultiMixRecordWriter aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS, 0 ); |
| |
| // erst Atomaren-Items und dann die Sets schreiben (wichtig beim Laden) |
| for ( pImp->bInSetItem = sal_False; pImp->bInSetItem <= sal_True && !rStream.GetError(); ++pImp->bInSetItem ) |
| { |
| SfxPoolItemArray_Impl **pArr = pImp->ppPoolItems; |
| SfxPoolItem **ppDefItem = ppStaticDefaults; |
| const sal_uInt16 nSize = GetSize_Impl(); |
| for ( size_t i = 0; i < nSize && !rStream.GetError(); ++i, ++pArr, ++ppDefItem ) |
| { |
| // Version des Items feststellen |
| sal_uInt16 nItemVersion = (*ppDefItem)->GetVersion( _nFileFormatVersion ); |
| if ( USHRT_MAX == nItemVersion ) |
| // => kam in zu exportierender Version gar nicht vor |
| continue; |
| |
| // !poolable wird gar nicht im Pool gespeichert |
| // und itemsets/plain-items je nach Runde |
| #ifdef TF_POOLABLE |
| if ( *pArr && IsItemFlag(**ppDefItem, SFX_ITEM_POOLABLE) && |
| #else |
| if ( *pArr && (*ppDefItem)->IsPoolable() && |
| #endif |
| pImp->bInSetItem == (*ppDefItem)->ISA(SfxSetItem) ) |
| { |
| // eigene Kennung, globale Which-Id und Item-Version |
| sal_uInt16 nSlotId = GetSlotId( (*ppDefItem)->Which(), sal_False ); |
| aWhichIdsRec.NewContent(nSlotId, 0); |
| rStream << (*ppDefItem)->Which(); |
| rStream << nItemVersion; |
| const sal_uInt32 nCount = ::std::min<size_t>( (*pArr)->size(), SAL_MAX_UINT32 ); |
| DBG_ASSERT(nCount, "ItemArr is empty"); |
| rStream << nCount; |
| |
| // Items an sich schreiben |
| SfxMultiMixRecordWriter aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS, 0 ); |
| for ( size_t j = 0; j < nCount; ++j ) |
| { |
| // Item selbst besorgen |
| const SfxPoolItem *pItem = (*pArr)->operator[](j); |
| if ( pItem && pItem->GetRefCount() ) //! siehe anderes MI-REF |
| { |
| aItemsRec.NewContent((sal_uInt16)j, 'X' ); |
| |
| if ( pItem->GetRefCount() == SFX_ITEMS_SPECIAL ) |
| rStream << (sal_uInt16) pItem->GetKind(); |
| else |
| { |
| rStream << (sal_uInt16) pItem->GetRefCount(); |
| if( pItem->GetRefCount() > SFX_ITEMS_OLD_MAXREF ) |
| rStream.SetError( ERRCODE_IO_NOTSTORABLEINBINARYFORMAT ); |
| } |
| |
| if ( !rStream.GetError() ) |
| pItem->Store(rStream, nItemVersion); |
| else |
| break; |
| #ifdef DBG_UTIL_MI |
| if ( !pItem->ISA(SfxSetItem) ) |
| { |
| sal_uLong nMark = rStream.Tell(); |
| rStream.Seek( nItemStartPos + sizeof(sal_uInt16) ); |
| SfxPoolItem *pClone = pItem->Create(rStream, nItemVersion ); |
| sal_uInt16 nWh = pItem->Which(); |
| SFX_ASSERT( rStream.Tell() == nMark, nWh,"asymmetric store/create" ); |
| SFX_ASSERT( *pClone == *pItem, nWh, "unequal after store/create" ); |
| delete pClone; |
| } |
| #endif |
| } |
| } |
| } |
| } |
| } |
| |
| pImp->bInSetItem = sal_False; |
| } |
| |
| // die gesetzten Defaults speichern (Pool-Defaults) |
| if ( !rStream.GetError() ) |
| { |
| SfxMultiMixRecordWriter aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS, 0 ); |
| sal_uInt16 nCount = GetSize_Impl(); |
| for ( sal_uInt16 n = 0; n < nCount; ++n ) |
| { |
| const SfxPoolItem* pDefaultItem = ppPoolDefaults[n]; |
| if ( pDefaultItem ) |
| { |
| // Version ermitteln |
| sal_uInt16 nItemVersion = pDefaultItem->GetVersion( _nFileFormatVersion ); |
| if ( USHRT_MAX == nItemVersion ) |
| // => gab es in der Version noch nicht |
| continue; |
| |
| // eigene Kennung, globale Kennung, Version |
| sal_uInt16 nSlotId = GetSlotId( pDefaultItem->Which(), sal_False ); |
| aDefsRec.NewContent( nSlotId, 0 ); |
| rStream << pDefaultItem->Which(); |
| rStream << nItemVersion; |
| |
| // Item an sich |
| pDefaultItem->Store( rStream, nItemVersion ); |
| } |
| } |
| } |
| |
| // weitere Pools rausschreiben |
| ImpSvlData::GetSvlData().pStoringPool = 0; |
| aPoolRec.Close(); |
| if ( !rStream.GetError() && pSecondary ) |
| pSecondary->Store( rStream ); |
| |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void SfxItemPool::LoadCompleted() |
| |
| /* [Beschreibung] |
| |
| Wurde der SfxItemPool mit 'bRefCounts' == sal_False geladen, mu\s das |
| Laden der Dokumentinhalte mit einem Aufruf dieser Methode beendet |
| werden. Ansonsten hat der Aufruf dieser Methode keine Funktion. |
| |
| |
| [Anmerkung] |
| |
| Beim Laden ohne Ref-Counts werden diese tats"achlich auf 1 gesetzt, |
| damit nicht w"ahrend des Ladevorgangs SfxPoolItems gel"oscht werden, |
| die danach, aber auch noch beim Ladevorgang, ben"otigt werden. Diese |
| Methode setzt den Ref-Count wieder zur"uck und entfernt dabei |
| gleichzeitig alle nicht mehr ben"otigten Items. |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::Load()> |
| */ |
| |
| { |
| // wurden keine Ref-Counts mitgeladen? |
| if ( pImp->nInitRefCount > 1 ) |
| { |
| |
| // "uber alle Which-Werte iterieren |
| SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; |
| for( sal_uInt16 nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr ) |
| { |
| // ist "uberhaupt ein Item mit dem Which-Wert da? |
| if ( *ppItemArr ) |
| { |
| // "uber alle Items mit dieser Which-Id iterieren |
| SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); |
| for( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) |
| if (*ppHtArr) |
| { |
| #ifdef DBG_UTIL |
| const SfxPoolItem &rItem = **ppHtArr; |
| DBG_ASSERT( !rItem.ISA(SfxSetItem) || |
| 0 != &((const SfxSetItem&)rItem).GetItemSet(), |
| "SetItem without ItemSet" ); |
| #endif |
| |
| if ( !ReleaseRef( **ppHtArr, 1 ) ) |
| DELETEZ( *ppHtArr ); |
| } |
| } |
| } |
| |
| // from now on normal initial ref count |
| pImp->nInitRefCount = 1; |
| } |
| |
| // notify secondary pool |
| if ( pSecondary ) |
| pSecondary->LoadCompleted(); |
| } |
| |
| //============================================================================ |
| // This had to be moved to a method of its own to keep Solaris GCC happy: |
| void SfxItemPool::readTheItems ( |
| SvStream & rStream, sal_uInt32 nItemCount, sal_uInt16 nVersion, |
| SfxPoolItem * pDefItem, SfxPoolItemArray_Impl ** ppArr) |
| { |
| SfxMultiRecordReader aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS ); |
| |
| SfxPoolItemArray_Impl *pNewArr = new SfxPoolItemArray_Impl(); |
| SfxPoolItem *pItem = 0; |
| |
| sal_uLong n, nLastSurrogate = sal_uLong(-1); |
| while (aItemsRec.GetContent()) |
| { |
| // n"achstes Surrogat holen |
| sal_uInt16 nSurrogate = aItemsRec.GetContentTag(); |
| DBG_ASSERT( aItemsRec.GetContentVersion() == 'X', |
| "not an item content" ); |
| |
| // fehlende auff"ullen |
| for ( pItem = 0, n = nLastSurrogate+1; n < nSurrogate; ++n ) |
| pNewArr->push_back( (SfxPoolItem*) pItem ); |
| nLastSurrogate = nSurrogate; |
| |
| // Ref-Count und Item laden |
| sal_uInt16 nRef(0); |
| rStream >> nRef; |
| |
| pItem = pDefItem->Create(rStream, nVersion); |
| pNewArr->push_back( (SfxPoolItem*) pItem ); |
| |
| if ( !bPersistentRefCounts ) |
| // bis <SfxItemPool::LoadCompleted()> festhalten |
| AddRef(*pItem, 1); |
| else |
| { |
| if ( nRef > SFX_ITEMS_OLD_MAXREF ) |
| pItem->SetKind( nRef ); |
| else |
| AddRef(*pItem, nRef); |
| } |
| } |
| |
| // fehlende auff"ullen |
| for ( pItem = 0, n = nLastSurrogate+1; n < nItemCount; ++n ) |
| pNewArr->push_back( (SfxPoolItem*) pItem ); |
| |
| SfxPoolItemArray_Impl *pOldArr = *ppArr; |
| *ppArr = pNewArr; |
| |
| // die Items merken, die schon im Pool sind |
| bool bEmpty = true; |
| if ( 0 != pOldArr ) |
| for ( n = 0; bEmpty && n < pOldArr->size(); ++n ) |
| bEmpty = pOldArr->operator[](n) == 0; |
| DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" ); |
| if ( !bEmpty ) |
| { |
| // f"ur alle alten suchen, ob ein gleiches neues existiert |
| for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld ) |
| { |
| SfxPoolItem *pOldItem = (*pOldArr)[nOld]; |
| if ( pOldItem ) |
| { |
| sal_uInt32 nFree = SAL_MAX_UINT32; |
| bool bFound = false; |
| for ( size_t nNew = (*ppArr)->size(); nNew--; ) |
| { |
| // geladenes Item |
| SfxPoolItem *&rpNewItem = |
| (SfxPoolItem*&)(*ppArr)->operator[](nNew); |
| |
| // surrogat unbenutzt? |
| if ( !rpNewItem ) |
| nFree = nNew; |
| |
| // gefunden? |
| else if ( *rpNewItem == *pOldItem ) |
| { |
| // wiederverwenden |
| AddRef( *pOldItem, rpNewItem->GetRefCount() ); |
| SetRefCount( *rpNewItem, 0 ); |
| delete rpNewItem; |
| rpNewItem = pOldItem; |
| bFound = true; |
| break; |
| } |
| } |
| |
| // vorhervorhandene, nicht geladene uebernehmen |
| if ( !bFound ) |
| { |
| if ( nFree != SAL_MAX_UINT32 ) |
| (SfxPoolItem*&)(*ppArr)->operator[](nFree) = pOldItem; |
| else |
| (*ppArr)->push_back( (SfxPoolItem*) pOldItem ); |
| } |
| } |
| } |
| } |
| delete pOldArr; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| SvStream &SfxItemPool::Load(SvStream &rStream) |
| { |
| DBG_CHKTHIS(SfxItemPool, 0); |
| DBG_ASSERT(ppStaticDefaults, "kein DefaultArray"); |
| |
| // protect items by increasing ref count |
| if ( !bPersistentRefCounts ) |
| { |
| |
| // "uber alle Which-Werte iterieren |
| SfxPoolItemArray_Impl** ppItemArr = pImp->ppPoolItems; |
| for( size_t nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++ppItemArr ) |
| { |
| // ist "uberhaupt ein Item mit dem Which-Wert da? |
| if ( *ppItemArr ) |
| { |
| // "uber alle Items mit dieser Which-Id iterieren |
| SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*ppItemArr)->begin(); |
| for( size_t n = (*ppItemArr)->size(); n; --n, ++ppHtArr ) |
| if (*ppHtArr) |
| { |
| #ifdef DBG_UTIL |
| const SfxPoolItem &rItem = **ppHtArr; |
| DBG_ASSERT( !rItem.ISA(SfxSetItem) || |
| 0 != &((const SfxSetItem&)rItem).GetItemSet(), |
| "SetItem without ItemSet" ); |
| DBG_WARNING( "loading non-empty ItemPool" ); |
| #endif |
| |
| AddRef( **ppHtArr, 1 ); |
| } |
| } |
| } |
| |
| // during loading (until LoadCompleted()) protect all items |
| pImp->nInitRefCount = 2; |
| } |
| |
| // Load-Master finden |
| SfxItemPool *pLoadMaster = pMaster != this ? pMaster : 0; |
| while ( pLoadMaster && !pLoadMaster->pImp->bStreaming ) |
| pLoadMaster = pLoadMaster->pSecondary; |
| |
| // Gesamt Header einlesen |
| pImp->bStreaming = sal_True; |
| if ( !pLoadMaster ) |
| { |
| // Format-Version laden |
| CHECK_FILEFORMAT2( rStream, |
| SFX_ITEMPOOL_TAG_STARTPOOL_5, SFX_ITEMPOOL_TAG_STARTPOOL_4 ); |
| rStream >> pImp->nMajorVer >> pImp->nMinorVer; |
| |
| // Format-Version in Master-Pool "ubertragen |
| pMaster->pImp->nMajorVer = pImp->nMajorVer; |
| pMaster->pImp->nMinorVer = pImp->nMinorVer; |
| |
| // altes Format? |
| if ( pImp->nMajorVer < 2 ) |
| // pImp->bStreaming wird von Load1_Impl() zur"uckgesetzt |
| return Load1_Impl( rStream ); |
| |
| // zu neues Format? |
| if ( pImp->nMajorVer > SFX_ITEMPOOL_VER_MAJOR ) |
| { |
| rStream.SetError(SVSTREAM_FILEFORMAT_ERROR); |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // Version 1.2-Trick-Daten "uberspringen |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_TRICK4OLD ); |
| rStream.SeekRel( 4 ); // Hack-Daten wegen SfxStyleSheetPool-Bug skippen |
| } |
| |
| // neues Record-orientiertes Format |
| SfxMiniRecordReader aPoolRec( &rStream, SFX_ITEMPOOL_REC ); |
| if ( rStream.GetError() ) |
| { |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // Einzel-Header |
| int bOwnPool = sal_True; |
| UniString aExternName; |
| { |
| // Header-Record suchen |
| SfxMiniRecordReader aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER ); |
| if ( rStream.GetError() ) |
| { |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // Header-lesen |
| rStream >> pImp->nLoadingVersion; |
| SfxPoolItem::readByteString(rStream, aExternName); |
| bOwnPool = aExternName == aName; |
| |
| //! solange wir keine fremden Pools laden k"onnen |
| if ( !bOwnPool ) |
| { |
| rStream.SetError(SVSTREAM_FILEFORMAT_ERROR); |
| aPoolRec.Skip(); |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| } |
| |
| // Version-Maps |
| { |
| SfxMultiRecordReader aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP ); |
| if ( rStream.GetError() ) |
| { |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // Versions-Maps einlesen |
| sal_uInt16 nOwnVersion = pImp->nVersion; |
| for ( sal_uInt16 nVerNo = 0; aVerRec.GetContent(); ++nVerNo ) |
| { |
| // Header f"ur einzelne Version einlesen |
| sal_uInt16 nVersion(0), nHStart(0), nHEnd(0); |
| rStream >> nVersion >> nHStart >> nHEnd; |
| sal_uInt16 nCount = nHEnd - nHStart + 1; |
| |
| // Is new version is known? |
| if ( nVerNo >= pImp->aVersions.size() ) |
| { |
| // Add new Version |
| sal_uInt16 *pMap = new sal_uInt16[nCount]; |
| memset(pMap, 0, nCount * sizeof(sal_uInt16)); |
| for ( sal_uInt16 n = 0; n < nCount; ++n ) |
| rStream >> pMap[n]; |
| SetVersionMap( nVersion, nHStart, nHEnd, pMap ); |
| } |
| } |
| pImp->nVersion = nOwnVersion; |
| } |
| |
| // Items laden |
| FASTBOOL bSecondaryLoaded = sal_False; |
| long nSecondaryEnd = 0; |
| { |
| SfxMultiRecordReader aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS); |
| while ( aWhichIdsRec.GetContent() ) |
| { |
| // SlotId, Which-Id und Item-Version besorgen |
| sal_uInt32 nCount(0); |
| sal_uInt16 nVersion(0), nWhich(0); |
| //!sal_uInt16 nSlotId = aWhichIdsRec.GetContentTag(); |
| rStream >> nWhich; |
| if ( pImp->nLoadingVersion != pImp->nVersion ) |
| // Which-Id aus File-Version in Pool-Version verschieben |
| nWhich = GetNewWhich( nWhich ); |
| |
| // unbekanntes Item aus neuerer Version |
| if ( !IsInRange(nWhich) ) |
| continue; |
| |
| rStream >> nVersion; |
| rStream >> nCount; |
| //!SFX_ASSERTWARNING( !nSlotId || !HasMap() || |
| //! ( nSlotId == GetSlotId( nWhich, sal_False ) ) || |
| //! !GetSlotId( nWhich, sal_False ), |
| //! nWhich, "Slot/Which mismatch" ); |
| |
| sal_uInt16 nIndex = GetIndex_Impl(nWhich); |
| SfxPoolItemArray_Impl **ppArr = pImp->ppPoolItems + nIndex; |
| |
| // SfxSetItems k"onnten Items aus Sekund"arpools beinhalten |
| SfxPoolItem *pDefItem = *(ppStaticDefaults + nIndex); |
| pImp->bInSetItem = pDefItem->ISA(SfxSetItem); |
| if ( !bSecondaryLoaded && pSecondary && pImp->bInSetItem ) |
| { |
| // an das Ende des eigenen Pools seeken |
| sal_uLong nLastPos = rStream.Tell(); |
| aPoolRec.Skip(); |
| |
| // Sekund"arpool einlesen |
| pSecondary->Load( rStream ); |
| bSecondaryLoaded = sal_True; |
| nSecondaryEnd = rStream.Tell(); |
| |
| // zur"uck zu unseren eigenen Items |
| rStream.Seek(nLastPos); |
| } |
| |
| // Items an sich lesen |
| readTheItems(rStream, nCount, nVersion, pDefItem, ppArr); |
| |
| pImp->bInSetItem = sal_False; |
| } |
| } |
| |
| // Pool-Defaults lesen |
| { |
| SfxMultiRecordReader aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS ); |
| |
| while ( aDefsRec.GetContent() ) |
| { |
| // SlotId, Which-Id und Item-Version besorgen |
| sal_uInt16 nVersion(0), nWhich(0); |
| //!sal_uInt16 nSlotId = aDefsRec.GetContentTag(); |
| rStream >> nWhich; |
| if ( pImp->nLoadingVersion != pImp->nVersion ) |
| // Which-Id aus File-Version in Pool-Version verschieben |
| nWhich = GetNewWhich( nWhich ); |
| |
| // unbekanntes Item aus neuerer Version |
| if ( !IsInRange(nWhich) ) |
| continue; |
| |
| rStream >> nVersion; |
| //!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, sal_False ) ), |
| //! nWhich, "Slot/Which mismatch" ); |
| |
| // Pool-Default-Item selbst laden |
| SfxPoolItem *pItem = |
| ( *( ppStaticDefaults + GetIndex_Impl(nWhich) ) ) |
| ->Create( rStream, nVersion ); |
| pItem->SetKind( SFX_ITEMS_POOLDEFAULT ); |
| *( ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem; |
| } |
| } |
| |
| // ggf. Secondary-Pool laden |
| aPoolRec.Skip(); |
| if ( pSecondary ) |
| { |
| if ( !bSecondaryLoaded ) |
| pSecondary->Load( rStream ); |
| else |
| rStream.Seek( nSecondaryEnd ); |
| } |
| |
| // wenn nicht own-Pool, dann kein Name |
| if ( aExternName != aName ) |
| aName.Erase(); |
| |
| pImp->bStreaming = sal_False; |
| return rStream; |
| }; |
| |
| // ----------------------------------------------------------------------- |
| |
| SvStream &SfxItemPool::Load1_Impl(SvStream &rStream) |
| { |
| // beim Master ist der Header schon von <Load()> geladen worden |
| if ( !pImp->bStreaming ) |
| { |
| // Header des Secondary lesen |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_STARTPOOL_4 ); |
| rStream >> pImp->nMajorVer >> pImp->nMinorVer; |
| } |
| sal_uInt32 nAttribSize(0); |
| int bOwnPool = sal_True; |
| UniString aExternName; |
| if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 2 ) |
| rStream >> pImp->nLoadingVersion; |
| SfxPoolItem::readByteString(rStream, aExternName); |
| bOwnPool = aExternName == aName; |
| pImp->bStreaming = sal_True; |
| |
| //! solange wir keine fremden laden k"onnen |
| if ( !bOwnPool ) |
| { |
| rStream.SetError(SVSTREAM_FILEFORMAT_ERROR); |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // Versionen bis 1.3 k"onnen noch keine Which-Verschiebungen lesen |
| if ( pImp->nMajorVer == 1 && pImp->nMinorVer <= 2 && |
| pImp->nVersion < pImp->nLoadingVersion ) |
| { |
| rStream.SetError(ERRCODE_IO_WRONGVERSION); |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // Size-Table liegt hinter den eigentlichen Attributen |
| rStream >> nAttribSize; |
| |
| // Size-Table einlesen |
| sal_uLong nStartPos = rStream.Tell(); |
| rStream.SeekRel( nAttribSize ); |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_SIZES ); |
| sal_uInt32 nSizeTableLen(0); |
| rStream >> nSizeTableLen; |
| sal_Char *pBuf = new sal_Char[nSizeTableLen]; |
| rStream.Read( pBuf, nSizeTableLen ); |
| sal_uLong nEndOfSizes = rStream.Tell(); |
| SvMemoryStream aSizeTable( pBuf, nSizeTableLen, STREAM_READ ); |
| |
| // ab Version 1.3 steht in der Size-Table eine Versions-Map |
| if ( pImp->nMajorVer > 1 || pImp->nMinorVer >= 3 ) |
| { |
| // Version-Map finden (letztes sal_uLong der Size-Table gibt Pos an) |
| rStream.Seek( nEndOfSizes - sizeof(sal_uInt32) ); |
| sal_uInt32 nVersionMapPos(0); |
| rStream >> nVersionMapPos; |
| rStream.Seek( nVersionMapPos ); |
| |
| // Versions-Maps einlesen |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_VERSIONMAP ); |
| sal_uInt16 nVerCount(0); |
| rStream >> nVerCount; |
| for ( sal_uInt16 nVerNo = 0; nVerNo < nVerCount; ++nVerNo ) |
| { |
| // Header f"ur einzelne Version einlesen |
| sal_uInt16 nVersion(0), nHStart(0), nHEnd(0); |
| rStream >> nVersion >> nHStart >> nHEnd; |
| sal_uInt16 nCount = nHEnd - nHStart + 1; |
| sal_uInt16 nBytes = (nCount)*sizeof(sal_uInt16); |
| |
| // Is new version is known? |
| if ( nVerNo >= pImp->aVersions.size() ) |
| { |
| // Add new Version |
| sal_uInt16 *pMap = new sal_uInt16[nCount]; |
| memset(pMap, 0, nCount * sizeof(sal_uInt16)); |
| for ( sal_uInt16 n = 0; n < nCount; ++n ) |
| rStream >> pMap[n]; |
| SetVersionMap( nVersion, nHStart, nHEnd, pMap ); |
| } |
| else |
| // Version schon bekannt => "uberspringen |
| rStream.SeekRel( nBytes ); |
| } |
| } |
| |
| // Items laden |
| rStream.Seek( nStartPos ); |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ITEMS ); |
| FASTBOOL bSecondaryLoaded = sal_False; |
| long nSecondaryEnd = 0; |
| sal_uInt16 nWhich(0), nSlot(0); |
| while ( rStream >> nWhich, nWhich ) |
| { |
| // ggf. Which-Id aus alter Version verschieben? |
| if ( pImp->nLoadingVersion != pImp->nVersion ) |
| nWhich = GetNewWhich( nWhich ); |
| |
| rStream >> nSlot; |
| sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False); |
| int bKnownItem = bOwnPool || IsWhich(nMappedWhich); |
| |
| sal_uInt16 nRef(0), nCount(0), nVersion(0); |
| sal_uInt32 nAttrSize(0); |
| rStream >> nVersion >> nCount; |
| |
| SfxPoolItemArray_Impl **ppArr = 0; |
| SfxPoolItemArray_Impl *pNewArr = 0; |
| SfxPoolItem *pDefItem = 0; |
| if ( bKnownItem ) |
| { |
| if ( !bOwnPool ) |
| nWhich = nMappedWhich; |
| |
| //!SFX_ASSERTWARNING( !nSlot || !HasMap() || |
| //! ( nSlot == GetSlotId( nWhich, sal_False ) ) || |
| //! !GetSlotId( nWhich, sal_False ), |
| //! nWhich, "Slot/Which mismatch" ); |
| |
| sal_uInt16 nIndex = GetIndex_Impl(nWhich); |
| ppArr = pImp->ppPoolItems + nIndex; |
| pNewArr = new SfxPoolItemArray_Impl(); |
| pDefItem = *(ppStaticDefaults + nIndex); |
| } |
| |
| // Position vor ersten Item merken |
| sal_uLong nLastPos = rStream.Tell(); |
| |
| // SfxSetItems k"onnten Items aus Sekund"arpools beinhalten |
| if ( !bSecondaryLoaded && pSecondary && pDefItem->ISA(SfxSetItem) ) |
| { |
| // an das Ende des eigenen Pools seeken |
| rStream.Seek(nEndOfSizes); |
| CHECK_FILEFORMAT_RELEASE( rStream, SFX_ITEMPOOL_TAG_ENDPOOL, pNewArr ); |
| CHECK_FILEFORMAT_RELEASE( rStream, SFX_ITEMPOOL_TAG_ENDPOOL, pNewArr ); |
| |
| // Sekund"arpool einlesen |
| pSecondary->Load1_Impl( rStream ); |
| bSecondaryLoaded = sal_True; |
| nSecondaryEnd = rStream.Tell(); |
| |
| // zur"uck zu unseren eigenen Items |
| rStream.Seek(nLastPos); |
| } |
| |
| // Items an sich lesen |
| for ( sal_uInt16 j = 0; j < nCount; ++j ) |
| { |
| sal_uLong nPos = nLastPos; |
| rStream >> nRef; |
| |
| if ( bKnownItem ) |
| { |
| SfxPoolItem *pItem = 0; |
| if ( nRef ) |
| { |
| pItem = pDefItem->Create(rStream, nVersion); |
| |
| if ( !bPersistentRefCounts ) |
| // bis <SfxItemPool::LoadCompleted()> festhalten |
| AddRef(*pItem, 1); |
| else |
| { |
| if ( nRef > SFX_ITEMS_OLD_MAXREF ) |
| pItem->SetKind( nRef ); |
| else |
| AddRef(*pItem, nRef); |
| } |
| } |
| //pNewArr->insert( pItem, j ); |
| pNewArr->push_back( (SfxPoolItem*) pItem ); |
| |
| // restliche gespeicherte Laenge skippen (neueres Format) |
| nLastPos = rStream.Tell(); |
| } |
| |
| aSizeTable >> nAttrSize; |
| SFX_ASSERT( !bKnownItem || ( nPos + nAttrSize) >= nLastPos, |
| nPos, |
| "too many bytes read - version mismatch?" ); |
| |
| if ( !bKnownItem || ( nLastPos < (nPos + nAttrSize) ) ) |
| { |
| nLastPos = nPos + nAttrSize; |
| rStream.Seek( nLastPos ); |
| } |
| } |
| |
| if ( bKnownItem ) |
| { |
| SfxPoolItemArray_Impl *pOldArr = *ppArr; |
| *ppArr = pNewArr; |
| |
| // die Items merken, die schon im Pool sind |
| int bEmpty = sal_True; |
| if ( 0 != pOldArr ) |
| for ( size_t n = 0; bEmpty && n < pOldArr->size(); ++n ) |
| bEmpty = pOldArr->operator[](n) == 0; |
| DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" ); |
| if ( !bEmpty ) |
| { |
| // f"ur alle alten suchen, ob ein gleiches neues existiert |
| for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld ) |
| { |
| SfxPoolItem *pOldItem = (*pOldArr)[nOld]; |
| if ( pOldItem ) |
| { |
| bool bFound = false; |
| for ( size_t nNew = 0; |
| nNew < (*ppArr)->size(); ++nNew ) |
| { |
| SfxPoolItem *&rpNewItem = |
| (SfxPoolItem*&)(*ppArr)->operator[](nNew); |
| |
| if ( rpNewItem && *rpNewItem == *pOldItem ) |
| { |
| AddRef( *pOldItem, rpNewItem->GetRefCount() ); |
| SetRefCount( *rpNewItem, 0 ); |
| delete rpNewItem; |
| rpNewItem = pOldItem; |
| bFound = true; |
| SFX_TRACE( "reusing item", pOldItem ); |
| break; |
| } |
| } |
| if ( !bFound ) |
| { |
| SFX_TRACE( "item not found: ", pOldItem ); |
| } |
| } |
| } |
| } |
| delete pOldArr; /* @@@ */ |
| } |
| } |
| |
| // Pool-Defaults lesen |
| if ( pImp->nMajorVer > 1 || pImp->nMinorVer > 0 ) |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_DEFAULTS ); |
| |
| sal_uLong nLastPos = rStream.Tell(); |
| while ( rStream >> nWhich, nWhich ) |
| { |
| // ggf. Which-Id aus alter Version verschieben? |
| if ( pImp->nLoadingVersion != pImp->nVersion ) |
| nWhich = GetNewWhich( nWhich ); |
| |
| rStream >> nSlot; |
| sal_uInt16 nMappedWhich = GetWhich(nSlot, sal_False); |
| int bKnownItem = bOwnPool || IsWhich(nMappedWhich); |
| |
| sal_uLong nPos = nLastPos; |
| sal_uInt32 nSize(0); |
| sal_uInt16 nVersion(0); |
| rStream >> nVersion; |
| |
| if ( bKnownItem ) |
| { |
| if ( !bOwnPool ) |
| nWhich = nMappedWhich; |
| SfxPoolItem *pItem = |
| ( *( ppStaticDefaults + GetIndex_Impl(nWhich) ) ) |
| ->Create( rStream, nVersion ); |
| pItem->SetKind( SFX_ITEMS_POOLDEFAULT ); |
| *( ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem; |
| } |
| |
| nLastPos = rStream.Tell(); |
| aSizeTable >> nSize; |
| SFX_ASSERT( ( nPos + nSize) >= nLastPos, nPos, |
| "too many bytes read - version mismatch?" ); |
| if ( nLastPos < (nPos + nSize) ) |
| rStream.Seek( nPos + nSize ); |
| } |
| |
| delete[] pBuf; |
| rStream.Seek(nEndOfSizes); |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL ); |
| CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_ENDPOOL ); |
| |
| if ( pSecondary ) |
| { |
| if ( !bSecondaryLoaded ) |
| pSecondary->Load1_Impl( rStream ); |
| else |
| rStream.Seek( nSecondaryEnd ); |
| } |
| |
| if ( aExternName != aName ) |
| aName.Erase(); |
| |
| pImp->bStreaming = sal_False; |
| return rStream; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const SfxPoolItem* SfxItemPool::LoadSurrogate |
| ( |
| SvStream& rStream, // vor einem Surrogat positionierter Stream |
| sal_uInt16& rWhich, // Which-Id des zu ladenden <SfxPoolItem>s |
| sal_uInt16 nSlotId, // Slot-Id des zu ladenden <SfxPoolItem>s |
| const SfxItemPool* pRefPool // <SfxItemPool> in dem das Surrogat gilt |
| ) |
| |
| /* [Beschreibung] |
| |
| L"adt Surrogat aus 'rStream' und liefert das dadurch in 'rRefPool' |
| repr"asentierte SfxPoolItem zu"ruck. Ist das im Stream befindliche |
| Surrogat == SFX_ITEMS_DIRECT (!SFX_ITEM_POOLABLE) wird 0 zur"uckgegeben, |
| das Item ist direkt aus dem Stream zu laden. Bei 0xfffffff0 (SFX_ITEMS_NULL) |
| wird auch 0 zurueckgegeben und rWhich auf 0 gesetzt, das Item ist nicht |
| verfuegbar. |
| |
| Ansonsten wird ber"ucksichtigt, ob der betroffene Pool ohne Ref-Counts |
| geladen wird, ob aus einem neuen Pool nachgeladen wird (&rRefPool != this) |
| oder ob aus einem g"anzlich anders aufgebauten Pool geladen wird. |
| |
| Wird aus einem anders aufgebauten Pool geladen und die 'nSlotId' kann |
| nicht in eine Which-Id dieses Pools gemappt werden, wird ebenfalls 0 |
| zur"uckgeliefert. |
| |
| Preconditions: - Pool mu\s geladen sein |
| - LoadCompleted darf noch nicht gerufen worden sein |
| - 'rStream' steht genau an der Position, an der ein |
| Surrogat f"ur ein Item mit der SlotId 'nSlotId' und |
| der WhichId 'rWhichId' mit StoreSurrogate gepeichert |
| wurde |
| |
| Postconditions: - 'rStream' ist so positioniert, wie auch StoreSurrogate |
| sein speichern beendet hatte |
| - konnte ein Item geladen werden, befindet es sich |
| in diesem SfxItemPool |
| - 'rWhichId' enth"alt die ggf. gemappte Which-Id |
| Laufzeit: Tiefe des Ziel Sekund"arpools * 10 + 10 |
| |
| [Querverweise] |
| |
| <SfxItemPool::StoreSurrogate(SvStream&,const SfxPoolItem &)const> |
| */ |
| |
| { |
| // Read the first surrogate |
| sal_uInt32 nSurrogat(0); |
| rStream >> nSurrogat; |
| |
| // Is item stored directly? |
| if ( SFX_ITEMS_DIRECT == nSurrogat ) |
| return 0; |
| |
| // Item does not exist? |
| if ( SFX_ITEMS_NULL == nSurrogat ) |
| { |
| rWhich = 0; |
| return 0; |
| } |
| |
| // Bei einem identisch aufgebauten Pool (im Stream) kann das Surrogat |
| // auf jeden Fall aufgel"ost werden. |
| if ( !pRefPool ) |
| pRefPool = this; |
| FASTBOOL bResolvable = pRefPool->GetName().Len() > 0; |
| if ( !bResolvable ) |
| { |
| // Bei einem anders aufgebauten Pool im Stream, mu\s die SlotId |
| // aus dem Stream in eine Which-Id gemappt werden k"onnen. |
| sal_uInt16 nMappedWhich = nSlotId ? GetWhich(nSlotId, sal_True) : 0; |
| if ( IsWhich(nMappedWhich) ) |
| { |
| // gemappte SlotId kann "ubernommen werden |
| rWhich = nMappedWhich; |
| bResolvable = sal_True; |
| } |
| } |
| |
| // kann Surrogat aufgel"ost werden? |
| const SfxPoolItem *pItem = 0; |
| if ( bResolvable ) |
| { |
| for ( SfxItemPool *pTarget = this; pTarget; pTarget = pTarget->pSecondary ) |
| { |
| // richtigen (Folge-) Pool gefunden? |
| if ( pTarget->IsInRange(rWhich) ) |
| { |
| // dflt-Attribut? |
| if ( SFX_ITEMS_DEFAULT == nSurrogat ) |
| return *(pTarget->ppStaticDefaults + |
| pTarget->GetIndex_Impl(rWhich)); |
| |
| SfxPoolItemArray_Impl* pItemArr = *(pTarget->pImp->ppPoolItems + |
| pTarget->GetIndex_Impl(rWhich)); |
| pItem = pItemArr && nSurrogat < pItemArr->size() |
| ? (*pItemArr)[nSurrogat] |
| : 0; |
| if ( !pItem ) |
| { |
| DBG_ERROR( "can't resolve surrogate" ); |
| rWhich = 0; // nur zur Sicherheit fuer richtige Stream-Pos |
| return 0; |
| } |
| |
| // Nachladen aus Ref-Pool? |
| if ( pRefPool != pMaster ) |
| return &pTarget->Put( *pItem ); |
| |
| // Referenzen sind NICHT schon mit Pool geladen worden? |
| if ( !pTarget->HasPersistentRefCounts() ) |
| AddRef( *pItem, 1 ); |
| else |
| return pItem; |
| |
| return pItem; |
| } |
| } |
| |
| SFX_ASSERT( sal_False, rWhich, "can't resolve Which-Id in LoadSurrogate" ); |
| } |
| |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| |
| FASTBOOL SfxItemPool::StoreSurrogate |
| ( |
| SvStream& rStream, |
| const SfxPoolItem* pItem |
| ) const |
| |
| /* [Beschreibung] |
| |
| Speichert ein Surrogat f"ur '*pItem' in 'rStream'. |
| |
| |
| [R"uckgabewert] |
| |
| FASTBOOL sal_True |
| es wurde ein echtes Surrogat gespeichert, auch |
| SFX_ITEMS_NULL bei 'pItem==0', |
| SFX_ITEMS_STATICDEFAULT und SFX_ITEMS_POOLDEFAULT |
| gelten als 'echte' Surrogate |
| |
| sal_False |
| es wurde ein Dummy-Surrogat (SFX_ITEMS_DIRECT) |
| gespeichert, das eigentliche Item mu\s direkt |
| hinterher selbst gespeichert werden |
| */ |
| |
| { |
| if ( pItem ) |
| { |
| FASTBOOL bRealSurrogate = IsItemFlag(*pItem, SFX_ITEM_POOLABLE); |
| rStream << ( bRealSurrogate |
| ? GetSurrogate( pItem ) |
| : SFX_ITEMS_DIRECT ); |
| return bRealSurrogate; |
| } |
| |
| rStream << SFX_ITEMS_NULL; |
| return sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt32 SfxItemPool::GetSurrogate(const SfxPoolItem *pItem) const |
| { |
| DBG_CHKTHIS(SfxItemPool, 0); |
| DBG_ASSERT( pItem, "no 0-Pointer Surrogate" ); |
| DBG_ASSERT( !IsInvalidItem(pItem), "no Invalid-Item Surrogate" ); |
| DBG_ASSERT( !IsPoolDefaultItem(pItem), "no Pool-Default-Item Surrogate" ); |
| |
| if ( !IsInRange(pItem->Which()) ) |
| { |
| if ( pSecondary ) |
| return pSecondary->GetSurrogate( pItem ); |
| SFX_ASSERT( 0, pItem->Which(), "unknown Which-Id - dont ask me for surrogates" ); |
| } |
| |
| // Pointer auf static- oder pool-dflt-Attribut? |
| if( IsStaticDefaultItem(pItem) || IsPoolDefaultItem(pItem) ) |
| return SFX_ITEMS_DEFAULT; |
| |
| SfxPoolItemArray_Impl* pItemArr = *(pImp->ppPoolItems + GetIndex_Impl(pItem->Which())); |
| DBG_ASSERT(pItemArr, "ItemArr is not available"); |
| |
| for ( size_t i = 0; i < pItemArr->size(); ++i ) |
| { |
| const SfxPoolItem *p = (*pItemArr)[i]; |
| if ( p == pItem ) |
| return i; |
| } |
| SFX_ASSERT( 0, pItem->Which(), "Item not in the pool"); |
| return SFX_ITEMS_NULL; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| FASTBOOL SfxItemPool::IsInStoringRange( sal_uInt16 nWhich ) const |
| { |
| return nWhich >= pImp->nStoringStart && |
| nWhich <= pImp->nStoringEnd; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void SfxItemPool::SetStoringRange( sal_uInt16 nFrom, sal_uInt16 nTo ) |
| |
| /* [Beschreibung] |
| |
| Mit dieser Methode kann der Which-Bereich eingeengt werden, der |
| von ItemSets dieses Pool (und dem Pool selbst) gespeichert wird. |
| Die Methode muss dazu vor <SfxItemPool::Store()> gerufen werden |
| und die Werte muessen auch noch gesetzt sein, wenn das eigentliche |
| Dokument (also die ItemSets gespeicher werden). |
| |
| Ein Zuruecksetzen ist dann nicht noetig, wenn dieser Range vor |
| JEDEM Speichern richtig gesetzt wird, da er nur beim Speichern |
| beruecksichtigt wird. |
| |
| Dieses muss fuer das 3.1-Format gemacht werden, da dort eine |
| Bug in der Pool-Lade-Methode vorliegt. |
| */ |
| |
| { |
| pImp->nStoringStart = nFrom; |
| pImp->nStoringEnd = nTo; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void SfxItemPool::SetVersionMap |
| ( |
| sal_uInt16 nVer, /* neue Versionsnummer */ |
| sal_uInt16 nOldStart, /* alte erste Which-Id */ |
| sal_uInt16 nOldEnd, /* alte letzte Which-Id */ |
| sal_uInt16* pOldWhichIdTab /* Array mit genau dem Aufbau der Which-Ids |
| der vorhergehenden Version, in denen |
| die jeweils neue Which-Id steht. */ |
| ) |
| |
| /* [Beschreibung] |
| |
| Mit dieser Methode k"onnen neue, inkompatible Which-Id-Folgen oder |
| Verteilungen realisiert werden. Pools, die noch mit alten Versionen |
| gespeichert wurden, werden dann "uber die angegebene Tabelle solange |
| gemappt, bis die aktuelle Version erreicht ist. Neuere Pools k"onnen |
| unter Verlust neuer Attribute geladen werden, da die Map mit dem Pool |
| gespeichert wird. |
| |
| Precondition: Pool darf noch nicht geladen sein |
| Postcondition: Which-Ids aus fr"uheren Versionen k"onnen bei Laden auf |
| Version 'nVer' gemappt werden |
| Laufzeit: 1.5 * new + 10 |
| |
| [Anmerkung] |
| |
| F"ur neue Which-Ranges (nStart,nEnd) m"ssen im Vergleich zur Vorg"anger- |
| Version (nOldStart,nOldEnd) immer gelten, da\s (nOldStart,nOldEnd) |
| vollst"andig in (nStart,nEnd) enthalten ist. Es ist also zul"assig, den |
| Which-Range in beide Richtungen zu erweitern, auch durch Einf"ugung |
| von Which-Ids, nicht aber ihn zu beschneiden. |
| |
| Diese Methode sollte nur im oder direkt nach Aufruf des Konstruktors |
| gerufen werden. |
| |
| Das Array mu\s statisch sein, da es nicht kopiert wird und au\serdem |
| im Copy-Ctor des SfxItemPool wiederverwendet wird. |
| |
| |
| [Beispiel] |
| |
| Urspr"unglich (Version 0) hatte der Pool folgende Which-Ids: |
| |
| 1:A, 2:B, 3:C, 4:D |
| |
| Nun soll eine neue Version (Version 1) zwei zus"atzliche Ids X und Y |
| zwischen B und C erhalten, also wie folgt aussehen: |
| |
| 1:A, 2:B, 3:X, 4:Y, 5:C, 6:D |
| |
| Dabei haben sich also die Ids 3 und 4 ge"andert. F"ur die neue Version |
| m"u\ste am Pool folgendes gesetzt werden: |
| |
| static sal_uInt16 nVersion1Map = { 1, 2, 5, 6 }; |
| pPool->SetVersionMap( 1, 1, 4, &nVersion1Map ); |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::IsLoadingVersionCurrent()const> |
| <SfxItemPool::GetNewWhich(sal_uInt16)> |
| <SfxItemPool::GetVersion()const> |
| <SfxItemPool::GetLoadingVersion()const> |
| */ |
| |
| { |
| // create new map entry to insert |
| const SfxPoolVersion_ImplPtr pVerMap = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl( |
| nVer, nOldStart, nOldEnd, pOldWhichIdTab ) ); |
| pImp->aVersions.push_back( pVerMap ); |
| |
| DBG_ASSERT( nVer > pImp->nVersion, "Versions not sorted" ); |
| pImp->nVersion = nVer; |
| |
| // Versions-Range anpassen |
| for ( sal_uInt16 n = 0; n < nOldEnd-nOldStart+1; ++n ) |
| { |
| sal_uInt16 nWhich = pOldWhichIdTab[n]; |
| if ( nWhich < pImp->nVerStart ) |
| { |
| if ( !nWhich ) |
| nWhich = 0; |
| pImp->nVerStart = nWhich; |
| } |
| else if ( nWhich > pImp->nVerEnd ) |
| pImp->nVerEnd = nWhich; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 SfxItemPool::GetNewWhich |
| ( |
| sal_uInt16 nFileWhich // die aus dem Stream geladene Which-Id |
| ) const |
| |
| /* [Beschreibung] |
| |
| Diese Methoden rechnet Which-Ids aus einem File-Format in die der |
| aktuellen Pool-Version um. Ist das File-Format "alter, werden die vom |
| Pool-Entwickler mit SetVersion() gesetzten Tabellen verwendet, |
| ist das File-Format neuer, dann die aus dem File geladenen Tabellen. |
| Im letzteren Fall kann ggf. nicht jede Which-Id gemappt werden, |
| so da\s 0 zur"uckgeliefert wird. |
| |
| Die Berechnung ist nur f"ur Which-Ids definiert, die in der betreffenden |
| File-Version unterst"utzt wurden. Dies ist per Assertion abgesichert. |
| |
| Precondition: Pool mu\s geladen sein |
| Postcondition: unver"andert |
| Laufzeit: linear(Anzahl der Sekund"arpools) + |
| linear(Differenz zwischen alter und neuer Version) |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::IsLoadingVersionCurrent()const> |
| <SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)> |
| <SfxItemPool::GetVersion()const> |
| <SfxItemPool::GetLoadingVersion()const> |
| */ |
| |
| { |
| // (Sekund"ar-) Pool bestimmen |
| if ( !IsInVersionsRange(nFileWhich) ) |
| { |
| if ( pSecondary ) |
| return pSecondary->GetNewWhich( nFileWhich ); |
| SFX_ASSERT( 0, nFileWhich, "unknown which in GetNewWhich()" ); |
| } |
| |
| // Version neuer/gleich/"alter? |
| short nDiff = (short)pImp->nLoadingVersion - (short)pImp->nVersion; |
| |
| // Which-Id einer neueren Version? |
| if ( nDiff > 0 ) |
| { |
| // von der Top-Version bis runter zur File-Version stufenweise mappen |
| for ( size_t nMap = pImp->aVersions.size(); nMap > 0; --nMap ) |
| { |
| SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap-1]; |
| if ( pVerInfo->_nVer > pImp->nVersion ) |
| { sal_uInt16 nOfs; |
| sal_uInt16 nCount = pVerInfo->_nEnd - pVerInfo->_nStart + 1; |
| for ( nOfs = 0; |
| nOfs <= nCount && |
| pVerInfo->_pMap[nOfs] != nFileWhich; |
| ++nOfs ) |
| continue; |
| |
| if ( pVerInfo->_pMap[nOfs] == nFileWhich ) |
| nFileWhich = pVerInfo->_nStart + nOfs; |
| else |
| return 0; |
| } |
| else |
| break; |
| } |
| } |
| |
| // Which-Id einer neueren Version? |
| else if ( nDiff < 0 ) |
| { |
| // von der File-Version bis zur aktuellen Version stufenweise mappen |
| for ( size_t nMap = 0; nMap < pImp->aVersions.size(); ++nMap ) |
| { |
| SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap]; |
| if ( pVerInfo->_nVer > pImp->nLoadingVersion ) |
| { |
| DBG_ASSERT( nFileWhich >= pVerInfo->_nStart && |
| nFileWhich <= pVerInfo->_nEnd, |
| "which-id unknown in version" ); |
| nFileWhich = pVerInfo->_pMap[nFileWhich - pVerInfo->_nStart]; |
| } |
| } |
| } |
| |
| // originale (nDiff==0) bzw. gemappte (nDiff!=0) Id zur"uckliefern |
| return nFileWhich; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| |
| FASTBOOL SfxItemPool::IsInVersionsRange( sal_uInt16 nWhich ) const |
| { |
| return nWhich >= pImp->nVerStart && nWhich <= pImp->nVerEnd; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| FASTBOOL SfxItemPool::IsCurrentVersionLoading() const |
| |
| /* [Beschreibung] |
| |
| Mit dieser Methode kann festgestellt werden, ob die geladene Pool-Version |
| dem aktuellen Pool-Aufbau entspricht. |
| |
| Precondition: Pool mu\s geladen sein |
| Postcondition: unver"andert |
| Laufzeit: linear(Anzahl der Sekund"arpools) |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)> |
| <SfxItemPool::GetNewWhich(sal_uInt16)const> |
| <SfxItemPool::GetVersion()const> |
| <SfxItemPool::GetLoadingVersion()const> |
| */ |
| |
| { |
| return ( pImp->nVersion == pImp->nLoadingVersion ) && |
| ( !pSecondary || pSecondary->IsCurrentVersionLoading() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 SfxItemPool::GetVersion() const |
| |
| /* [Beschreibung] |
| |
| Diese Methode liefert die aktuelle Versionsnummer des SfxItemPool-Aufbaus |
| (also des Which-Bereichs). |
| |
| Precondition: keine |
| Postcondition: unver"andert |
| Laufzeit: 2 |
| |
| |
| [Anmerkung] |
| |
| Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools |
| ber"ucksichtigt werden. |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::IsLoadingVersionCurrent()const> |
| <SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)> |
| <SfxItemPool::GetNewWhich(sal_uInt16)const> |
| <SfxItemPool::GetLoadingVersion()const> |
| */ |
| |
| { |
| return pImp->nVersion; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 SfxItemPool::GetLoadingVersion() const |
| |
| /* [Beschreibung] |
| |
| Diese Methode liefert die Versionsnummer des SfxItemPool-Aufbaus |
| (also des Which-Bereichs), die bei Laden vorgefunden wurde. |
| |
| Precondition: Pool mu\s geladen sein |
| Postcondition: unver"andert |
| Laufzeit: 2 |
| |
| |
| [Anmerkung] |
| |
| Achtung: Es mu\s ggf. die Versionsnummer von Sekund"arpools |
| ber"ucksichtigt werden. |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::IsLoadingVersionCurrent()const> |
| <SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)> |
| <SfxItemPool::GetNewWhich(sal_uInt16)const> |
| <SfxItemPool::GetVersion()const> |
| */ |
| |
| { |
| return pImp->nLoadingVersion; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| FASTBOOL SfxItemPool::IsVer2_Impl() const |
| { |
| return pMaster->pImp->nMajorVer >= 2; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| |
| FASTBOOL SfxItemPool::StoreItem( SvStream &rStream, const SfxPoolItem &rItem, |
| FASTBOOL bDirect ) const |
| |
| /* [Beschreibung] |
| |
| Speichert das <SfxPoolItem> 'rItem' in den <SvStream> 'rStream' |
| entweder als Surrogat ('bDirect == sal_False') oder direkt mit 'rItem.Store()'. |
| Nicht poolable Items werden immer direkt gespeichert. Items ohne Which-Id, |
| also SID-Items, werden nicht gespeichert, ebenso wenn Items, die in der |
| File-Format-Version noch nicht vorhanden waren (return sal_False). |
| |
| Das Item wird im Stream wie folgt abgelegt: |
| |
| sal_uInt16 rItem.Which() |
| sal_uInt16 GetSlotId( rItem.Which() ) bzw. 0 falls nicht verf"urbar |
| sal_uInt16 GetSurrogate( &rItem ) bzw. SFX_ITEM_DIRECT bei '!SFX_ITEM_POOLBLE' |
| |
| optional (falls 'bDirect == sal_True' oder '!rItem.IsPoolable()': |
| |
| sal_uInt16 rItem.GetVersion() |
| sal_uLong Size |
| Size rItem.Store() |
| |
| |
| [Querverweise] |
| |
| <SfxItemPool::LoadItem(SvStream&,FASTBOOL)const> |
| */ |
| |
| { |
| DBG_ASSERT( !IsInvalidItem(&rItem), "cannot store invalid items" ); |
| |
| if ( IsSlot( rItem.Which() ) ) |
| return sal_False; |
| const SfxItemPool *pPool = this; |
| while ( !pPool->IsInStoringRange(rItem.Which()) ) |
| if ( 0 == ( pPool = pPool->pSecondary ) ) |
| return sal_False; |
| |
| DBG_ASSERT( !pImp->bInSetItem || !rItem.ISA(SfxSetItem), |
| "SetItem contains ItemSet with SetItem" ); |
| |
| sal_uInt16 nSlotId = pPool->GetSlotId( rItem.Which(), sal_True ); |
| sal_uInt16 nItemVersion = rItem.GetVersion(_nFileFormatVersion); |
| if ( USHRT_MAX == nItemVersion ) |
| return sal_False; |
| |
| rStream << rItem.Which() << nSlotId; |
| if ( bDirect || !pPool->StoreSurrogate( rStream, &rItem ) ) |
| { |
| rStream << nItemVersion; |
| rStream << (sal_uInt32) 0L; // Platz fuer Laenge in Bytes |
| sal_uLong nIStart = rStream.Tell(); |
| rItem.Store(rStream, nItemVersion); |
| sal_uLong nIEnd = rStream.Tell(); |
| rStream.Seek( nIStart-4 ); |
| rStream << (sal_Int32) ( nIEnd-nIStart ); |
| rStream.Seek( nIEnd ); |
| } |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| |
| const SfxPoolItem* SfxItemPool::LoadItem( SvStream &rStream, FASTBOOL bDirect, |
| const SfxItemPool *pRefPool ) |
| |
| // pRefPool==-1 => nicht putten! |
| |
| { |
| sal_uInt16 nWhich(0), nSlot(0); // nSurrogate; |
| rStream >> nWhich >> nSlot; |
| |
| sal_Bool bDontPut = (SfxItemPool*)-1 == pRefPool; |
| if ( bDontPut || !pRefPool ) |
| pRefPool = this; |
| |
| // richtigen Sekund"ar-Pool finden |
| while ( !pRefPool->IsInVersionsRange(nWhich) ) |
| { |
| if ( pRefPool->pSecondary ) |
| pRefPool = pRefPool->pSecondary; |
| else |
| { |
| // WID in der Version nicht vorhanden => ueberspringen |
| sal_uInt32 nSurro(0); |
| sal_uInt16 nVersion(0), nLen(0); |
| rStream >> nSurro; |
| if ( SFX_ITEMS_DIRECT == nSurro ) |
| { |
| rStream >> nVersion >> nLen; |
| rStream.SeekRel( nLen ); |
| } |
| return 0; |
| } |
| } |
| |
| // wird eine andere Version geladen? |
| FASTBOOL bCurVersion = pRefPool->IsCurrentVersionLoading(); |
| if ( !bCurVersion ) |
| // Which-Id auf neue Version mappen |
| nWhich = pRefPool->GetNewWhich( nWhich ); |
| |
| DBG_ASSERT( !nWhich || !pImp->bInSetItem || |
| !pRefPool->ppStaticDefaults[pRefPool->GetIndex_Impl(nWhich)]->ISA(SfxSetItem), |
| "loading SetItem in ItemSet of SetItem" ); |
| |
| // soll "uber Surrogat geladen werden? |
| const SfxPoolItem *pItem = 0; |
| if ( !bDirect ) |
| { |
| // Which-Id in dieser Version bekannt? |
| if ( nWhich ) |
| // Surrogat laden, reagieren falls keins vorhanden |
| pItem = LoadSurrogate( rStream, nWhich, nSlot, pRefPool ); |
| else |
| // sonst "uberspringen |
| rStream.SeekRel( sizeof(sal_uInt16) ); |
| } |
| |
| // wird direkt, also nicht "uber Surrogat geladen? |
| if ( bDirect || ( nWhich && !pItem ) ) |
| { |
| // bDirekt bzw. nicht IsPoolable() => Item direkt laden |
| sal_uInt16 nVersion(0); |
| sal_uInt32 nLen(0); |
| rStream >> nVersion >> nLen; |
| sal_uLong nIStart = rStream.Tell(); |
| |
| // Which-Id in dieser Version bekannt? |
| if ( nWhich ) |
| { |
| // Item direkt laden |
| SfxPoolItem *pNewItem = |
| pRefPool->GetDefaultItem(nWhich).Create(rStream, nVersion); |
| if ( bDontPut ) |
| pItem = pNewItem; |
| else |
| if ( pNewItem ) |
| { |
| pItem = &Put(*pNewItem); |
| delete pNewItem; |
| } |
| else |
| pItem = 0; |
| sal_uLong nIEnd = rStream.Tell(); |
| DBG_ASSERT( nIEnd <= (nIStart+nLen), "read past end of item" ); |
| if ( (nIStart+nLen) != nIEnd ) |
| rStream.Seek( nIStart+nLen ); |
| } |
| else |
| // Item "uberspringen |
| rStream.Seek( nIStart+nLen ); |
| } |
| |
| return pItem; |
| } |
| |
| |