diff options
author | Daniel Rentz [dr] <daniel.rentz@oracle.com> | 2010-12-16 16:50:35 +0100 |
---|---|---|
committer | Daniel Rentz [dr] <daniel.rentz@oracle.com> | 2010-12-16 16:50:35 +0100 |
commit | dddebac86dd6b1608bb59479e672c69ef3a48e0e (patch) | |
tree | 1e13334be2e84dfbaf10623d48c7178ed60139fd | |
parent | 340bea2639e78081b9115a6077ea9d269061d983 (diff) |
dr78: #i109800# SHEET record may not point to BOF but to any record in the sheet substream (but now with reading that record too)
-rw-r--r-- | sc/source/filter/excel/read.cxx | 99 | ||||
-rw-r--r-- | sc/source/filter/excel/xiescher.cxx | 40 | ||||
-rw-r--r-- | sc/source/filter/excel/xistream.cxx | 6 | ||||
-rw-r--r-- | sc/source/filter/inc/xistream.hxx | 11 |
4 files changed, 93 insertions, 63 deletions
diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index 67f0965b1..67db61103 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -836,11 +836,56 @@ FltError ImportExcel8::Read( void ) if( eAkt == EXC_STATE_BEFORE_SHEET ) { sal_uInt16 nScTab = GetCurrScTab(); - if( nScTab < maSheetOffsets.size() ) + if( nScTab < maSheetOffsets.size() ) { - nProgressBaseSize += (aIn.GetSvStreamPos() - nProgressBasePos); + nProgressBaseSize += (maStrm.GetSvStreamPos() - nProgressBasePos); nProgressBasePos = maSheetOffsets[ nScTab ]; - aIn.StartNextRecord( nProgressBasePos ); + maStrm.StartNextRecord( nProgressBasePos ); + + // #94191# import only 256 sheets + if( nScTab > GetScMaxPos().Tab() ) + { + if( maStrm.GetRecId() != EXC_ID_EOF ) + XclTools::SkipSubStream( maStrm ); + // #i29930# show warning box + GetAddressConverter().CheckScTab( nScTab, true ); + eAkt = EXC_STATE_END; + } + else + { + // #i109800# SHEET record may point to any record inside the sheet substream + bool bIsBof = maStrm.GetRecId() == EXC_ID5_BOF; + if( bIsBof ) + Bof5(); // read the BOF record + else + pExcRoot->eDateiTyp = Biff8; // on missing BOF, assume a standard worksheet + + NeueTabelle(); + switch( pExcRoot->eDateiTyp ) + { + case Biff8: // worksheet + case Biff8M4: // macro sheet + eAkt = EXC_STATE_SHEET_PRE; // Shrfmla Prefetch, Row-Prefetch + // go to next record + if( bIsBof ) maStrm.StartNextRecord(); + maStrm.StoreGlobalPosition(); + break; + case Biff8C: // chart sheet + GetCurrSheetDrawing().ReadTabChart( maStrm ); + Eof(); + GetTracer().TraceChartOnlySheet(); + break; + case Biff8W: // workbook + DBG_ERRORFILE( "ImportExcel8::Read - double workbook globals" ); + // run through + case Biff8V: // VB module + default: + // TODO: do not create a sheet in the Calc document + pD->SetVisible( GetCurrScTab(), FALSE ); + XclTools::SkipSubStream( maStrm ); + IncCurrScTab(); + } + } } else eAkt = EXC_STATE_END; @@ -1018,54 +1063,6 @@ FltError ImportExcel8::Read( void ) break; // ---------------------------------------------------------------- - // before worksheet: expecting worksheet BOF - case EXC_STATE_BEFORE_SHEET: - { - // #94191# import only 256 sheets - if( GetCurrScTab() > GetScMaxPos().Tab() ) - { - if( nRecId != EXC_ID_EOF ) - XclTools::SkipSubStream( maStrm ); - // #i29930# show warning box - GetAddressConverter().CheckScTab( GetCurrScTab(), true ); - eAkt = EXC_STATE_END; - } - else - { - /* #i109800# SHEET record may point to any record inside the - sheet substream. We will assume a standard worksheet. */ - if( nRecId == EXC_ID5_BOF ) - Bof5(); - else - pExcRoot->eDateiTyp = Biff8; - NeueTabelle(); - switch( pExcRoot->eDateiTyp ) - { - case Biff8: // worksheet - case Biff8M4: // macro sheet - eAkt = EXC_STATE_SHEET_PRE; // Shrfmla Prefetch, Row-Prefetch - aIn.StoreGlobalPosition(); - break; - case Biff8C: // chart sheet - GetCurrSheetDrawing().ReadTabChart( maStrm ); - Eof(); - GetTracer().TraceChartOnlySheet(); - break; - case Biff8W: // workbook - DBG_ERRORFILE( "ImportExcel8::Read - double workbook globals" ); - // run through - case Biff8V: // VB module - default: - // TODO: do not create a sheet in the Calc document - pD->SetVisible( GetCurrScTab(), FALSE ); - XclTools::SkipSubStream( maStrm ); - IncCurrScTab(); - } - } - } - break; - - // ---------------------------------------------------------------- // prefetch for worksheet case EXC_STATE_SHEET_PRE: { diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index c4a7715d0..c1ee4df43 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -1540,23 +1540,39 @@ XclImpChartObj::XclImpChartObj( const XclImpRoot& rRoot, bool bOwnTab ) : void XclImpChartObj::ReadChartSubStream( XclImpStream& rStrm ) { - if( mbOwnTab ? (rStrm.GetRecId() == EXC_ID5_BOF) : ((rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord()) ) + /* If chart is read from a chartsheet (mbOwnTab == true), the BOF record + has already been read. If chart is embedded as object, the next record + has to be the BOF record. */ + if( mbOwnTab ) { - sal_uInt16 nBofType; - rStrm.Seek( 2 ); - rStrm >> nBofType; - DBG_ASSERT( nBofType == EXC_BOF_CHART, "XclImpChartObj::ReadChartSubStream - no chart BOF record" ); - - // read chart, even if BOF record contains wrong substream identifier - mxChart.reset( new XclImpChart( GetRoot(), mbOwnTab ) ); - mxChart->ReadChartSubStream( rStrm ); - if( mbOwnTab ) - FinalizeTabChart(); + /* #i109800# The input stream may point somewhere inside the chart + substream and not exactly to the leading BOF record. To read this + record correctly in the following, the stream has to rewind it, so + that the next call to StartNextRecord() will find it correctly. */ + if( rStrm.GetRecId() != EXC_ID5_BOF ) + rStrm.RewindRecord(); } else { - DBG_ERRORFILE( "XclImpChartObj::ReadChartSubStream - missing chart substream" ); + if( (rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord() ) + { + sal_uInt16 nBofType; + rStrm.Seek( 2 ); + rStrm >> nBofType; + DBG_ASSERT( nBofType == EXC_BOF_CHART, "XclImpChartObj::ReadChartSubStream - no chart BOF record" ); + } + else + { + DBG_ERRORFILE( "XclImpChartObj::ReadChartSubStream - missing chart substream" ); + return; + } } + + // read chart, even if BOF record contains wrong substream identifier + mxChart.reset( new XclImpChart( GetRoot(), mbOwnTab ) ); + mxChart->ReadChartSubStream( rStrm ); + if( mbOwnTab ) + FinalizeTabChart(); } void XclImpChartObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) diff --git a/sc/source/filter/excel/xistream.cxx b/sc/source/filter/excel/xistream.cxx index 84f28383e..cd20f26e3 100644 --- a/sc/source/filter/excel/xistream.cxx +++ b/sc/source/filter/excel/xistream.cxx @@ -431,6 +431,12 @@ void XclImpStream::ResetRecord( bool bContLookup, sal_uInt16 nAltContId ) } } +void XclImpStream::RewindRecord() +{ + mnNextRecPos = maFirstRec.GetPos(); + mbValid = mbValidRec = false; +} + void XclImpStream::SetDecrypter( XclImpDecrypterRef xDecrypter ) { mxDecrypter = xDecrypter; diff --git a/sc/source/filter/inc/xistream.hxx b/sc/source/filter/inc/xistream.hxx index de4e86bf0..65d0e58c1 100644 --- a/sc/source/filter/inc/xistream.hxx +++ b/sc/source/filter/inc/xistream.hxx @@ -182,6 +182,9 @@ public: sal_uInt16& rnRawRecId, sal_uInt16& rnRawRecSize, sal_uInt16& rnRawRecLeft, bool& rbValid ) const; + /** Returns the stored stream position. */ + inline sal_Size GetPos() const { return mnPos; } + private: sal_Size mnPos; /// Absolute position of the stream. sal_Size mnNextPos; /// Absolute position of next record. @@ -280,6 +283,14 @@ public: started with StartNextRecord(). */ void ResetRecord( bool bContLookup, sal_uInt16 nAltContId = EXC_ID_UNKNOWN ); + /** Sets stream pointer before current record and invalidates stream. + @descr The next call to StartNextRecord() will start again the current + record. This can be used in situations where a loop or a function + leaves on a specific record, but the parent context expects to start + this record by itself. The stream is invalid as long as the first + record has not been started (it is not allowed to call any other stream + operation then). */ + void RewindRecord(); /** Enables decryption of record contents for the rest of the stream. */ void SetDecrypter( XclImpDecrypterRef xDecrypter ); |