summaryrefslogtreecommitdiff
path: root/oox/source/xls/workbookfragment.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/xls/workbookfragment.cxx')
-rw-r--r--oox/source/xls/workbookfragment.cxx756
1 files changed, 756 insertions, 0 deletions
diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx
new file mode 100644
index 000000000000..838711bb1198
--- /dev/null
+++ b/oox/source/xls/workbookfragment.cxx
@@ -0,0 +1,756 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: workbookfragment.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#include "oox/xls/workbookfragment.hxx"
+#include <com/sun/star/table/CellAddress.hpp>
+#include "oox/helper/attributelist.hxx"
+#include "oox/helper/progressbar.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/helper/recordinputstream.hxx"
+#include "oox/drawingml/themefragmenthandler.hxx"
+#include "oox/xls/biffinputstream.hxx"
+#include "oox/xls/connectionsfragment.hxx"
+#include "oox/xls/externallinkbuffer.hxx"
+#include "oox/xls/externallinkfragment.hxx"
+#include "oox/xls/pivotcachefragment.hxx"
+#include "oox/xls/sharedstringsbuffer.hxx"
+#include "oox/xls/sharedstringsfragment.hxx"
+#include "oox/xls/stylesfragment.hxx"
+#include "oox/xls/tablebuffer.hxx"
+#include "oox/xls/themebuffer.hxx"
+#include "oox/xls/viewsettings.hxx"
+#include "oox/xls/workbooksettings.hxx"
+#include "oox/xls/worksheetbuffer.hxx"
+#include "oox/xls/worksheetfragment.hxx"
+
+using ::rtl::OUString;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::table::CellAddress;
+using ::oox::core::FragmentHandlerRef;
+using ::oox::core::Relation;
+using ::oox::drawingml::ThemeFragmentHandler;
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+namespace {
+
+const double PROGRESS_LENGTH_GLOBALS = 0.1; /// 10% of progress bar for globals import.
+
+const sal_uInt16 BIFF_FILEPASS_BIFF2 = 0x0000;
+const sal_uInt16 BIFF_FILEPASS_BIFF8 = 0x0001;
+const sal_uInt16 BIFF_FILEPASS_BIFF8_RCF = 0x0001;
+const sal_uInt16 BIFF_FILEPASS_BIFF8_STRONG = 0x0002;
+
+} // namespace
+
+// ============================================================================
+
+OoxWorkbookFragment::OoxWorkbookFragment(
+ const WorkbookHelper& rHelper, const OUString& rFragmentPath ) :
+ OoxWorkbookFragmentBase( rHelper, rFragmentPath )
+{
+}
+
+// oox.xls.OoxContextHelper interface -----------------------------------------
+
+bool OoxWorkbookFragment::onCanCreateContext( sal_Int32 nElement ) const
+{
+ switch( getCurrentContext() )
+ {
+ case XML_ROOT_CONTEXT:
+ return (nElement == XLS_TOKEN( workbook ));
+ case XLS_TOKEN( workbook ):
+ return (nElement == XLS_TOKEN( workbookPr )) ||
+ (nElement == XLS_TOKEN( calcPr )) ||
+ (nElement == XLS_TOKEN( sheets )) ||
+ (nElement == XLS_TOKEN( bookViews )) ||
+ (nElement == XLS_TOKEN( externalReferences )) ||
+ (nElement == XLS_TOKEN( definedNames )) ||
+ (nElement == XLS_TOKEN( pivotCaches ));
+ case XLS_TOKEN( sheets ):
+ return (nElement == XLS_TOKEN( sheet ));
+ case XLS_TOKEN( bookViews ):
+ return (nElement == XLS_TOKEN( workbookView ));
+ case XLS_TOKEN( externalReferences ):
+ return (nElement == XLS_TOKEN( externalReference ));
+ case XLS_TOKEN( definedNames ):
+ return (nElement == XLS_TOKEN( definedName ));
+ case XLS_TOKEN( pivotCaches ):
+ return (nElement == XLS_TOKEN( pivotCache ));
+ }
+ return false;
+}
+
+void OoxWorkbookFragment::onStartElement( const AttributeList& rAttribs )
+{
+ switch( getCurrentContext() )
+ {
+ case XLS_TOKEN( workbookPr ): getWorkbookSettings().importWorkbookPr( rAttribs ); break;
+ case XLS_TOKEN( calcPr ): getWorkbookSettings().importCalcPr( rAttribs ); break;
+ case XLS_TOKEN( sheet ): getWorksheets().importSheet( rAttribs ); break;
+ case XLS_TOKEN( workbookView ): getViewSettings().importWorkbookView( rAttribs ); break;
+ case XLS_TOKEN( externalReference ): importExternalReference( rAttribs ); break;
+ case XLS_TOKEN( definedName ): importDefinedName( rAttribs ); break;
+ case XLS_TOKEN( pivotCache ): importPivotCache( rAttribs ); break;
+ }
+}
+
+void OoxWorkbookFragment::onEndElement( const OUString& rChars )
+{
+ switch( getCurrentContext() )
+ {
+ case XLS_TOKEN( definedName ):
+ if( mxCurrName.get() ) mxCurrName->setFormula( rChars );
+ break;
+ }
+}
+
+bool OoxWorkbookFragment::onCanCreateRecordContext( sal_Int32 nRecId )
+{
+ switch( getCurrentContext() )
+ {
+ case XML_ROOT_CONTEXT:
+ return (nRecId == OOBIN_ID_WORKBOOK);
+ case OOBIN_ID_WORKBOOK:
+ return (nRecId == OOBIN_ID_WORKBOOKPR) ||
+ (nRecId == OOBIN_ID_CALCPR) ||
+ (nRecId == OOBIN_ID_SHEETS) ||
+ (nRecId == OOBIN_ID_BOOKVIEWS) ||
+ (nRecId == OOBIN_ID_EXTERNALREFS) ||
+ (nRecId == OOBIN_ID_DEFINEDNAME);
+ case OOBIN_ID_SHEETS:
+ return (nRecId == OOBIN_ID_SHEET);
+ case OOBIN_ID_BOOKVIEWS:
+ return (nRecId == OOBIN_ID_WORKBOOKVIEW);
+ case OOBIN_ID_EXTERNALREFS:
+ return (nRecId == OOBIN_ID_EXTERNALREF) ||
+ (nRecId == OOBIN_ID_EXTERNALSELF) ||
+ (nRecId == OOBIN_ID_EXTERNALSHEETS);
+ }
+ return false;
+}
+
+void OoxWorkbookFragment::onStartRecord( RecordInputStream& rStrm )
+{
+ switch( getCurrentContext() )
+ {
+ case OOBIN_ID_WORKBOOKPR: getWorkbookSettings().importWorkbookPr( rStrm ); break;
+ case OOBIN_ID_CALCPR: getWorkbookSettings().importCalcPr( rStrm ); break;
+ case OOBIN_ID_SHEET: getWorksheets().importSheet( rStrm ); break;
+ case OOBIN_ID_WORKBOOKVIEW: getViewSettings().importWorkbookView( rStrm ); break;
+ case OOBIN_ID_EXTERNALREF: importExternalRef( rStrm ); break;
+ case OOBIN_ID_EXTERNALSELF: getExternalLinks().importExternalSelf( rStrm ); break;
+ case OOBIN_ID_EXTERNALSHEETS: getExternalLinks().importExternalSheets( rStrm ); break;
+ case OOBIN_ID_DEFINEDNAME: getDefinedNames().importDefinedName( rStrm ); break;
+ }
+}
+
+// oox.xls.OoxFragmentHandler interface ---------------------------------------
+
+void OoxWorkbookFragment::finalizeImport()
+{
+ ISegmentProgressBarRef xGlobalSegment = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS );
+
+ // read the theme substream
+ OUString aThemeFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "theme" ) );
+ if( aThemeFragmentPath.getLength() > 0 )
+ importOoxFragment( new ThemeFragmentHandler( getFilter(), aThemeFragmentPath, getTheme().getCoreTheme() ) );
+ xGlobalSegment->setPosition( 0.25 );
+
+ // read the styles substream (requires finalized theme buffer)
+ OUString aStylesFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "styles" ) );
+ if( aStylesFragmentPath.getLength() > 0 )
+ importOoxFragment( new OoxStylesFragment( *this, aStylesFragmentPath ) );
+ xGlobalSegment->setPosition( 0.5 );
+
+ // read the shared string table substream (requires finalized styles buffer)
+ OUString aSstFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "sharedStrings" ) );
+ if( aSstFragmentPath.getLength() > 0 )
+ importOoxFragment( new OoxSharedStringsFragment( *this, aSstFragmentPath ) );
+ xGlobalSegment->setPosition( 0.75 );
+
+ // read the connections substream
+ OUString aConnFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "connections" ) );
+ if( aConnFragmentPath.getLength() > 0 )
+ importOoxFragment( new OoxConnectionsFragment( *this, aConnFragmentPath ) );
+ xGlobalSegment->setPosition( 1.0 );
+
+ /* Create fragments for all sheets, before importing them. Needed to do
+ some preprocessing in the fragment constructors, e.g. loading the table
+ fragments for all sheets that are needed before the cell formulas are
+ loaded. */
+ typedef ::std::map< sal_Int32, FragmentHandlerRef > SheetFragmentMap;
+ SheetFragmentMap aSheetFragments;
+ WorksheetBuffer& rWorksheets = getWorksheets();
+ sal_Int32 nSheetCount = rWorksheets.getInternalSheetCount();
+ for( sal_Int32 nSheet = 0; nSheet < nSheetCount; ++nSheet )
+ {
+ if( const Relation* pRelation = getRelations().getRelationFromRelId( rWorksheets.getSheetRelId( nSheet ) ) )
+ {
+ // get fragment path of the sheet
+ OUString aFragmentPath = getFragmentPathFromTarget( pRelation->maTarget );
+ OSL_ENSURE( aFragmentPath.getLength() > 0, "OoxWorkbookFragment::finalizeImport - cannot access sheet fragment" );
+ if( aFragmentPath.getLength() > 0 )
+ {
+ ::rtl::Reference< OoxWorksheetFragmentBase > xFragment;
+ double fSegmentLength = getProgressBar().getFreeLength() / (nSheetCount - nSheet);
+ ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength );
+ // create the fragment according to the sheet type
+ if( pRelation->maType == CREATE_RELATIONS_TYPE( "worksheet" ) )
+ xFragment.set( new OoxWorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_WORKSHEET, nSheet ) );
+ // insert the fragment into the map
+ OSL_ENSURE( xFragment.is(), "OoxWorkbookFragment::finalizeImport - unknown sheet type" );
+ OSL_ENSURE( !xFragment.is() || xFragment->isValidSheet(), "OoxWorkbookFragment::finalizeImport - missing sheet in document" );
+ if( xFragment.is() && xFragment->isValidSheet() )
+ aSheetFragments[ nSheet ].set( xFragment.get() );
+ }
+ }
+ }
+
+ // create all defined names and database ranges
+ getDefinedNames().finalizeImport();
+ getTables().finalizeImport();
+
+ // load all worksheets
+ for( sal_Int32 nSheet = 0; nSheet < nSheetCount; ++nSheet )
+ {
+ SheetFragmentMap::iterator aIt = aSheetFragments.find( nSheet );
+ if( aIt != aSheetFragments.end() )
+ {
+ // import the sheet fragment
+ importOoxFragment( aIt->second );
+ // delete fragment object, will free all allocated sheet buffers
+ aSheetFragments.erase( aIt );
+ }
+ }
+
+ // final conversions, e.g. calculation settings and view settings
+ finalizeWorkbookImport();
+
+ getPivotTables().finalizeImport();
+}
+
+// private --------------------------------------------------------------------
+
+void OoxWorkbookFragment::importExternalReference( const AttributeList& rAttribs )
+{
+ if( ExternalLink* pExtLink = getExternalLinks().importExternalReference( rAttribs ).get() )
+ importExternalLinkFragment( *pExtLink );
+}
+
+void OoxWorkbookFragment::importDefinedName( const AttributeList& rAttribs )
+{
+ mxCurrName = getDefinedNames().importDefinedName( rAttribs );
+}
+
+void OoxWorkbookFragment::importPivotCache( const AttributeList& rAttribs )
+{
+ OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ) ) );
+ if( (aFragmentPath.getLength() > 0) && rAttribs.hasAttribute( XML_cacheId ) )
+ {
+ sal_uInt32 nCacheId = rAttribs.getUnsignedInteger( XML_cacheId, 0 );
+ importOoxFragment( new OoxPivotCacheFragment( *this, aFragmentPath, nCacheId ) );
+ }
+}
+
+void OoxWorkbookFragment::importExternalRef( RecordInputStream& rStrm )
+{
+ if( ExternalLink* pExtLink = getExternalLinks().importExternalRef( rStrm ).get() )
+ importExternalLinkFragment( *pExtLink );
+}
+
+void OoxWorkbookFragment::importExternalLinkFragment( ExternalLink& rExtLink )
+{
+ OUString aFragmentPath = getFragmentPathFromRelId( rExtLink.getRelId() );
+ if( aFragmentPath.getLength() > 0 )
+ importOoxFragment( new OoxExternalLinkFragment( *this, aFragmentPath, rExtLink ) );
+}
+
+// ============================================================================
+
+namespace {
+
+BiffDecoderRef lclImportFilePass_XOR( const WorkbookHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDecoderRef xDecoder;
+ OSL_ENSURE( rStrm.getRecLeft() == 4, "lclImportFilePass_XOR - wrong record size" );
+ if( rStrm.getRecLeft() == 4 )
+ {
+ sal_uInt16 nBaseKey, nHash;
+ rStrm >> nBaseKey >> nHash;
+ xDecoder.reset( new BiffDecoder_XOR( rHelper, nBaseKey, nHash ) );
+ }
+ return xDecoder;
+}
+
+BiffDecoderRef lclImportFilePass_RCF( const WorkbookHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDecoderRef xDecoder;
+ OSL_ENSURE( rStrm.getRecLeft() == 48, "lclImportFilePass_RCF - wrong record size" );
+ if( rStrm.getRecLeft() == 48 )
+ {
+ sal_uInt8 pnDocId[ 16 ];
+ sal_uInt8 pnSaltData[ 16 ];
+ sal_uInt8 pnSaltHash[ 16 ];
+ rStrm.read( pnDocId, 16 );
+ rStrm.read( pnSaltData, 16 );
+ rStrm.read( pnSaltHash, 16 );
+ xDecoder.reset( new BiffDecoder_RCF( rHelper, pnDocId, pnSaltData, pnSaltHash ) );
+ }
+ return xDecoder;
+}
+
+BiffDecoderRef lclImportFilePass_Strong( const WorkbookHelper& /*rHelper*/, BiffInputStream& /*rStrm*/ )
+{
+ // not supported
+ return BiffDecoderRef();
+}
+
+BiffDecoderRef lclImportFilePass2( const WorkbookHelper& rHelper, BiffInputStream& rStrm )
+{
+ return lclImportFilePass_XOR( rHelper, rStrm );
+}
+
+BiffDecoderRef lclImportFilePass8( const WorkbookHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDecoderRef xDecoder;
+
+ switch( rStrm.readuInt16() )
+ {
+ case BIFF_FILEPASS_BIFF2:
+ xDecoder = lclImportFilePass_XOR( rHelper, rStrm );
+ break;
+
+ case BIFF_FILEPASS_BIFF8:
+ switch( rStrm.skip( 2 ).readuInt16() )
+ {
+ case BIFF_FILEPASS_BIFF8_RCF:
+ xDecoder = lclImportFilePass_RCF( rHelper, rStrm );
+ break;
+ case BIFF_FILEPASS_BIFF8_STRONG:
+ xDecoder = lclImportFilePass_Strong( rHelper, rStrm );
+ break;
+ default:
+ OSL_ENSURE( false, "lclImportFilePass8 - unknown BIFF8 encryption sub mode" );
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false, "lclImportFilePass8 - unknown encryption mode" );
+ }
+
+ return xDecoder;
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+BiffWorkbookFragment::BiffWorkbookFragment( const WorkbookHelper& rHelper ) :
+ BiffWorkbookFragmentBase( rHelper )
+{
+}
+
+bool BiffWorkbookFragment::importFragment( BiffInputStream& rStrm )
+{
+ bool bRet = false;
+
+ BiffFragmentType eFragment = startFragment( rStrm, getBiff() );
+ switch( eFragment )
+ {
+ case BIFF_FRAGMENT_GLOBALS:
+ {
+ // import workbook globals fragment and create sheets in document
+ ISegmentProgressBarRef xGlobalsProgress = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS );
+ bRet = importGlobalsFragment( rStrm, *xGlobalsProgress );
+ // load sheet fragments (do not return false in bRet on missing/broken sheets)
+ WorksheetBuffer& rWorksheets = getWorksheets();
+ bool bNextSheet = bRet;
+ for( sal_Int32 nSheet = 0, nSheetCount = rWorksheets.getInternalSheetCount(); bNextSheet && (nSheet < nSheetCount); ++nSheet )
+ {
+ // try to start a new sheet fragment
+ double fSegmentLength = getProgressBar().getFreeLength() / (nSheetCount - nSheet);
+ ISegmentProgressBarRef xSheetProgress = getProgressBar().createSegment( fSegmentLength );
+ BiffFragmentType eSheetFragment = startFragment( rStrm, getBiff() );
+ bNextSheet = importSheetFragment( rStrm, *xSheetProgress, eSheetFragment, nSheet );
+ }
+ }
+ break;
+
+ case BIFF_FRAGMENT_WORKSPACE:
+ {
+ bRet = importWorkspaceFragment( rStrm );
+ // sheets are embedded in workspace fragment, nothing to do here
+ }
+ break;
+
+ case BIFF_FRAGMENT_WORKSHEET:
+ case BIFF_FRAGMENT_CHART:
+ case BIFF_FRAGMENT_MACRO:
+ {
+ /* Single sheet without globals
+ - #i62752# possible in all BIFF versions
+ - do not return false in bRet on missing/broken sheets. */
+ getWorksheets().initializeSingleSheet();
+ importSheetFragment( rStrm, getProgressBar(), eFragment, 0 );
+ // success, even if stream is broken
+ bRet = true;
+ }
+ break;
+
+ default:;
+ }
+
+ // final conversions, e.g. calculation settings and view settings
+ finalizeWorkbookImport();
+
+ return bRet;
+}
+
+bool BiffWorkbookFragment::importWorkspaceFragment( BiffInputStream& rStrm )
+{
+ // enable workbook mode, has not been set yet in BIFF4 workspace files
+ setIsWorkbookFile();
+
+ WorksheetBuffer& rWorksheets = getWorksheets();
+ bool bRet = true;
+
+ // import the workspace globals
+ ISegmentProgressBarRef xGlobalsProgress = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS );
+ bool bLoop = true;
+ while( bRet && bLoop && rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) )
+ {
+ switch( rStrm.getRecId() )
+ {
+ case BIFF_ID_SHEET: rWorksheets.importSheet( rStrm ); break;
+ case BIFF_ID_CODEPAGE: setCodePage( rStrm.readuInt16() ); break;
+ case BIFF_ID_FILEPASS: bRet = importFilePass( rStrm ); break;
+ case BIFF_ID_SHEETHEADER: rStrm.rewindRecord(); bLoop = false; break;
+ }
+ }
+ xGlobalsProgress->setPosition( 1.0 );
+
+ // load sheet fragments (do not return false in bRet on missing/broken sheets)
+ bool bNextSheet = bRet;
+ for( sal_Int32 nSheet = 0, nSheetCount = rWorksheets.getInternalSheetCount(); bNextSheet && (nSheet < nSheetCount); ++nSheet )
+ {
+ // try to start a new sheet fragment (with leading SHEETHEADER record)
+ bNextSheet = rStrm.startNextRecord() && (rStrm.getRecId() == BIFF_ID_SHEETHEADER);
+ if( bNextSheet )
+ {
+ double fSegmentLength = getProgressBar().getFreeLength() / (nSheetCount - nSheet);
+ ISegmentProgressBarRef xSheetProgress = getProgressBar().createSegment( fSegmentLength );
+ /* Read current sheet name (sheet substreams may not be in the
+ same order as SHEET records are). */
+ OUString aSheetName = rStrm.skip( 4 ).readByteString( false, getTextEncoding() );
+ sal_Int32 nCurrSheet = rWorksheets.getFinalSheetIndex( aSheetName );
+ // load the sheet fragment records
+ BiffFragmentType eSheetFragment = startFragment( rStrm, getBiff() );
+ bNextSheet = importSheetFragment( rStrm, *xSheetProgress, eSheetFragment, nCurrSheet );
+ // do not return false in bRet on missing/broken sheets
+ }
+ }
+
+ return bRet;
+}
+
+bool BiffWorkbookFragment::importGlobalsFragment( BiffInputStream& rStrm, ISegmentProgressBar& rProgressBar )
+{
+ WorkbookSettings& rWorkbookSett = getWorkbookSettings();
+ ViewSettings& rViewSett = getViewSettings();
+ SharedStringsBuffer& rSharedStrings = getSharedStrings();
+ StylesBuffer& rStyles = getStyles();
+ WorksheetBuffer& rWorksheets = getWorksheets();
+
+ // collect records that need to be loaded in a second pass
+ typedef ::std::vector< sal_Int64 > RecordHandleVec;
+ RecordHandleVec aExtLinkRecs;
+
+ bool bRet = true;
+ bool bLoop = true;
+ while( bRet && bLoop && rStrm.startNextRecord() )
+ {
+ sal_uInt16 nRecId = rStrm.getRecId();
+ bool bExtLinkRec = false;
+
+ /* #i56376# BIFF5-BIFF8: If an EOF record for globals is missing,
+ simulate it. The issue is about a document where the sheet fragment
+ starts directly after the EXTSST record, without terminating the
+ globals fragment with an EOF record. */
+ if( isBofRecord( nRecId ) || (nRecId == BIFF_ID_EOF) )
+ {
+ bLoop = false;
+ }
+ else switch( nRecId )
+ {
+ // records in all BIFF versions
+ case BIFF_ID_CODEPAGE: setCodePage( rStrm.readuInt16() ); break;
+ case BIFF_ID_DATEMODE: rWorkbookSett.importDateMode( rStrm ); break;
+ case BIFF_ID_FILEPASS: bRet = importFilePass( rStrm ); break;
+ case BIFF_ID_PRECISION: rWorkbookSett.importPrecision( rStrm ); break;
+ case BIFF_ID_WINDOW1: rViewSett.importWindow1( rStrm ); break;
+
+ // BIFF specific records
+ default: switch( getBiff() )
+ {
+ case BIFF2: switch( nRecId )
+ {
+ case BIFF2_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF2_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF2_ID_FONT: rStyles.importFont( rStrm ); break;
+ case BIFF_ID_FONTCOLOR: rStyles.importFontColor( rStrm ); break;
+ case BIFF2_ID_FORMAT: rStyles.importFormat( rStrm ); break;
+ case BIFF2_ID_XF: rStyles.importXf( rStrm ); break;
+ }
+ break;
+
+ case BIFF3: switch( nRecId )
+ {
+ case BIFF_ID_CRN: bExtLinkRec = true; break;
+ case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF3_ID_FONT: rStyles.importFont( rStrm ); break;
+ case BIFF2_ID_FORMAT: rStyles.importFormat( rStrm ); break;
+ case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break;
+ case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break;
+ case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break;
+ case BIFF_ID_XCT: bExtLinkRec = true; break;
+ case BIFF3_ID_XF: rStyles.importXf( rStrm ); break;
+ }
+ break;
+
+ case BIFF4: switch( nRecId )
+ {
+ case BIFF_ID_CRN: bExtLinkRec = true; break;
+ case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF3_ID_FONT: rStyles.importFont( rStrm ); break;
+ case BIFF4_ID_FORMAT: rStyles.importFormat( rStrm ); break;
+ case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break;
+ case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break;
+ case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break;
+ case BIFF_ID_XCT: bExtLinkRec = true; break;
+ case BIFF4_ID_XF: rStyles.importXf( rStrm ); break;
+ }
+ break;
+
+ case BIFF5: switch( nRecId )
+ {
+ case BIFF_ID_BOOKBOOL: rWorkbookSett.importBookBool( rStrm ); break;
+ case BIFF_ID_CRN: bExtLinkRec = true; break;
+ case BIFF5_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF5_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF5_ID_FONT: rStyles.importFont( rStrm ); break;
+ case BIFF4_ID_FORMAT: rStyles.importFormat( rStrm ); break;
+ case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break;
+ case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break;
+ case BIFF_ID_SHEET: rWorksheets.importSheet( rStrm ); break;
+ case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break;
+ case BIFF_ID_XCT: bExtLinkRec = true; break;
+ case BIFF5_ID_XF: rStyles.importXf( rStrm ); break;
+ }
+ break;
+
+ case BIFF8: switch( nRecId )
+ {
+ case BIFF_ID_BOOKBOOL: rWorkbookSett.importBookBool( rStrm ); break;
+ case BIFF_ID_CODENAME: rWorkbookSett.importCodeName( rStrm ); break;
+ case BIFF_ID_CRN: bExtLinkRec = true; break;
+ case BIFF5_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNALBOOK: bExtLinkRec = true; break;
+ case BIFF5_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF5_ID_FONT: rStyles.importFont( rStrm ); break;
+ case BIFF4_ID_FORMAT: rStyles.importFormat( rStrm ); break;
+ case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break;
+ case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break;
+ case BIFF_ID_SHEET: rWorksheets.importSheet( rStrm ); break;
+ case BIFF_ID_SST: rSharedStrings.importSst( rStrm ); break;
+ case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break;
+ case BIFF_ID_USESELFS: rWorkbookSett.importUsesElfs( rStrm ); break;
+ case BIFF_ID_XCT: bExtLinkRec = true; break;
+ case BIFF5_ID_XF: rStyles.importXf( rStrm ); break;
+ }
+ break;
+
+ case BIFF_UNKNOWN: break;
+ }
+ }
+
+ if( bExtLinkRec )
+ aExtLinkRecs.push_back( rStrm.getRecHandle() );
+ }
+
+ // finalize global buffers
+ rProgressBar.setPosition( 0.5 );
+ rSharedStrings.finalizeImport();
+ rStyles.finalizeImport();
+
+ /* Import external link data (EXTERNSHEET, EXTERNALNAME, DEFINEDNAME)
+ which need existing internal sheets (SHEET records). The SHEET records
+ may follow the external links records in some BIFF versions. */
+ if( bRet && !aExtLinkRecs.empty() )
+ {
+ // remember current stream position (the EOF record)
+ sal_Int64 nEofHandle = rStrm.getRecHandle();
+ // this fragment class implements import of external link records
+ BiffExternalLinkFragment aLinkFragment( *this, true );
+ // import all records by using their cached record handle
+ for( RecordHandleVec::const_iterator aIt = aExtLinkRecs.begin(), aEnd = aExtLinkRecs.end(); (aIt != aEnd) && rStrm.startRecordByHandle( *aIt ); ++aIt )
+ aLinkFragment.importRecord( rStrm );
+ // finalize global buffers
+ aLinkFragment.finalizeImport();
+ // seek back to the EOF record of the workbook globals fragment
+ bRet = rStrm.startRecordByHandle( nEofHandle );
+ }
+
+ // #i56376# missing EOF - rewind before worksheet BOF record (see above)
+ if( bRet && isBofRecord( rStrm.getRecId() ) )
+ rStrm.rewindRecord();
+
+ rProgressBar.setPosition( 1.0 );
+ return bRet;
+}
+
+bool BiffWorkbookFragment::importSheetFragment( BiffInputStream& rStrm, ISegmentProgressBar& rProgressBar, BiffFragmentType eFragment, sal_Int32 nSheet )
+{
+ // find the sheet type for this fragment
+ WorksheetType eSheetType = SHEETTYPE_WORKSHEET;
+ bool bSkipSheet = false;
+ switch( eFragment )
+ {
+ case BIFF_FRAGMENT_WORKSHEET: eSheetType = SHEETTYPE_WORKSHEET; break;
+ case BIFF_FRAGMENT_CHART: eSheetType = SHEETTYPE_CHART; break;
+ case BIFF_FRAGMENT_MACRO: eSheetType = SHEETTYPE_MACRO; break;
+ case BIFF_FRAGMENT_EMPTYSHEET: bSkipSheet = true; break;
+ default: return false;
+ }
+
+ // skip this worksheet fragment (e.g. fragment type is BIFF_FRAGMENT_EMPTYSHEET)
+ if( bSkipSheet )
+ {
+ rProgressBar.setPosition( 1.0 );
+ return skipFragment( rStrm );
+ }
+
+ /* #i11183# Clear buffers that are used per-sheet, e.g. external links in
+ BIFF4W and BIFF5 files, or defined names in BIFF4W files. */
+ createBuffersPerSheet();
+
+ // preprocess some records
+ switch( getBiff() )
+ {
+ // load the workbook globals fragment records in BIFF2-BIFF4
+ case BIFF2:
+ case BIFF3:
+ case BIFF4:
+ {
+ // set sheet index in defined names buffer to handle built-in names correctly
+ getDefinedNames().setLocalSheetIndex( nSheet );
+ // remember current record to seek back below
+ sal_Int64 nRecHandle = rStrm.getRecHandle();
+ // import the global records
+ ISegmentProgressBarRef xGlobalsProgress = rProgressBar.createSegment( PROGRESS_LENGTH_GLOBALS );
+ importGlobalsFragment( rStrm, *xGlobalsProgress );
+ // rewind stream to fragment BOF record
+ rStrm.startRecordByHandle( nRecHandle );
+ }
+ break;
+
+ // load the external link records for this sheet in BIFF5
+ case BIFF5:
+ {
+ // remember current record to seek back below
+ sal_Int64 nRecHandle = rStrm.getRecHandle();
+ // fragment implementing import of external link records
+ BiffExternalLinkFragment( *this, false ).importFragment( rStrm );
+ // rewind stream to fragment BOF record
+ rStrm.startRecordByHandle( nRecHandle );
+ }
+ break;
+
+ case BIFF8:
+ break;
+
+ case BIFF_UNKNOWN:
+ break;
+ }
+
+ // create the worksheet fragment
+ ISegmentProgressBarRef xSheetProgress = rProgressBar.createSegment( rProgressBar.getFreeLength() );
+ ::boost::shared_ptr< BiffWorksheetFragmentBase > xFragment;
+ switch( eSheetType )
+ {
+ case SHEETTYPE_WORKSHEET:
+ case SHEETTYPE_MACRO:
+ xFragment.reset( new BiffWorksheetFragment( *this, xSheetProgress, eSheetType, nSheet ) );
+ break;
+ case SHEETTYPE_CHART:
+ xFragment.reset( new BiffWorksheetFragmentBase( *this, xSheetProgress, eSheetType, nSheet ) );
+ break;
+ }
+ // load the sheet fragment records
+ return xFragment->isValidSheet() && xFragment->importFragment( rStrm );
+}
+
+bool BiffWorkbookFragment::importFilePass( BiffInputStream& rStrm )
+{
+ rStrm.enableDecoder( false );
+ BiffDecoderRef xDecoder = (getBiff() == BIFF8) ?
+ lclImportFilePass8( *this, rStrm ) : lclImportFilePass2( *this, rStrm );
+
+ // set decoder at import stream
+ rStrm.setDecoder( xDecoder );
+ //! TODO remember encryption state for export
+// rStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true;
+
+ return xDecoder.get() && xDecoder->isValid();
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
+