6af59644d6
Please find attached a partial fix for Easy Hack FDO43460 Part XXI Module oox
1142 lines
42 KiB
C++
1142 lines
42 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org 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 version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "oox/xls/externallinkbuffer.hxx"
|
|
|
|
#include <com/sun/star/sheet/ComplexReference.hpp>
|
|
#include <com/sun/star/sheet/DDELinkInfo.hpp>
|
|
#include <com/sun/star/sheet/ExternalLinkType.hpp>
|
|
#include <com/sun/star/sheet/ExternalReference.hpp>
|
|
#include <com/sun/star/sheet/ReferenceFlags.hpp>
|
|
#include <com/sun/star/sheet/SingleReference.hpp>
|
|
#include <com/sun/star/sheet/XDDELinks.hpp>
|
|
#include <com/sun/star/sheet/XDDELink.hpp>
|
|
#include <com/sun/star/sheet/XDDELinkResults.hpp>
|
|
#include <com/sun/star/sheet/XExternalDocLink.hpp>
|
|
#include <com/sun/star/sheet/XExternalDocLinks.hpp>
|
|
#include <rtl/strbuf.hxx>
|
|
#include "oox/core/filterbase.hxx"
|
|
#include "oox/helper/attributelist.hxx"
|
|
#include "oox/xls/addressconverter.hxx"
|
|
#include "oox/xls/biffinputstream.hxx"
|
|
#include "oox/xls/excelhandlers.hxx"
|
|
#include "oox/xls/formulaparser.hxx"
|
|
#include "oox/xls/worksheetbuffer.hxx"
|
|
|
|
namespace oox {
|
|
namespace xls {
|
|
|
|
// ============================================================================
|
|
|
|
using namespace ::com::sun::star::sheet;
|
|
using namespace ::com::sun::star::table;
|
|
using namespace ::com::sun::star::uno;
|
|
|
|
using ::oox::core::Relation;
|
|
using ::oox::core::Relations;
|
|
using ::rtl::OString;
|
|
using ::rtl::OStringBuffer;
|
|
using ::rtl::OStringToOUString;
|
|
using ::rtl::OUString;
|
|
|
|
// ============================================================================
|
|
|
|
namespace {
|
|
|
|
const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK = 0;
|
|
const sal_uInt16 BIFF12_EXTERNALBOOK_DDE = 1;
|
|
const sal_uInt16 BIFF12_EXTERNALBOOK_OLE = 2;
|
|
|
|
const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC = 0x0002;
|
|
const sal_uInt16 BIFF12_EXTNAME_PREFERPIC = 0x0004;
|
|
const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME = 0x0008;
|
|
const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT = 0x0010;
|
|
const sal_uInt16 BIFF12_EXTNAME_ICONIFIED = 0x0020;
|
|
|
|
const sal_uInt16 BIFF_EXTNAME_BUILTIN = 0x0001;
|
|
const sal_uInt16 BIFF_EXTNAME_AUTOMATIC = 0x0002;
|
|
const sal_uInt16 BIFF_EXTNAME_PREFERPIC = 0x0004;
|
|
const sal_uInt16 BIFF_EXTNAME_STDDOCNAME = 0x0008;
|
|
const sal_uInt16 BIFF_EXTNAME_OLEOBJECT = 0x0010;
|
|
const sal_uInt16 BIFF_EXTNAME_ICONIFIED = 0x8000;
|
|
|
|
} // namespace
|
|
|
|
// ============================================================================
|
|
|
|
ExternalNameModel::ExternalNameModel() :
|
|
mbBuiltIn( false ),
|
|
mbNotify( false ),
|
|
mbPreferPic( false ),
|
|
mbStdDocName( false ),
|
|
mbOleObj( false ),
|
|
mbIconified( false )
|
|
{
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
ExternalName::ExternalName( const ExternalLink& rParentLink ) :
|
|
DefinedNameBase( rParentLink ),
|
|
mrParentLink( rParentLink ),
|
|
mnStorageId( 0 ),
|
|
mbDdeLinkCreated( false )
|
|
{
|
|
}
|
|
|
|
void ExternalName::importDefinedName( const AttributeList& rAttribs )
|
|
{
|
|
maModel.maName = rAttribs.getXString( XML_name, OUString() );
|
|
OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDefinedName - empty name" );
|
|
// zero-based index into sheet list of externalBook
|
|
maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 );
|
|
}
|
|
|
|
void ExternalName::importDdeItem( const AttributeList& rAttribs )
|
|
{
|
|
maModel.maName = rAttribs.getXString( XML_name, OUString() );
|
|
OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDdeItem - empty name" );
|
|
maExtNameModel.mbOleObj = false;
|
|
maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false );
|
|
maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
|
|
maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
|
|
}
|
|
|
|
void ExternalName::importValues( const AttributeList& rAttribs )
|
|
{
|
|
setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) );
|
|
}
|
|
|
|
void ExternalName::importOleItem( const AttributeList& rAttribs )
|
|
{
|
|
maModel.maName = rAttribs.getXString( XML_name, OUString() );
|
|
OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importOleItem - empty name" );
|
|
maExtNameModel.mbOleObj = true;
|
|
maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
|
|
maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
|
|
maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false );
|
|
}
|
|
|
|
void ExternalName::importExternalName( SequenceInputStream& rStrm )
|
|
{
|
|
rStrm >> maModel.maName;
|
|
OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importExternalName - empty name" );
|
|
}
|
|
|
|
void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm )
|
|
{
|
|
sal_uInt16 nFlags;
|
|
sal_Int32 nSheetId;
|
|
rStrm >> nFlags >> nSheetId;
|
|
// index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
|
|
maModel.mnSheet = nSheetId - 1;
|
|
// no flag for built-in names, as in OOXML...
|
|
maExtNameModel.mbNotify = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC );
|
|
maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC );
|
|
maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME );
|
|
maExtNameModel.mbOleObj = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT );
|
|
maExtNameModel.mbIconified = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED );
|
|
OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj,
|
|
"ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
|
|
}
|
|
|
|
void ExternalName::importDdeItemValues( SequenceInputStream& rStrm )
|
|
{
|
|
sal_Int32 nRows, nCols;
|
|
rStrm >> nRows >> nCols;
|
|
setResultSize( nCols, nRows );
|
|
}
|
|
|
|
void ExternalName::importDdeItemBool( SequenceInputStream& rStrm )
|
|
{
|
|
appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
|
|
}
|
|
|
|
void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm )
|
|
{
|
|
appendResultValue( rStrm.readDouble() );
|
|
}
|
|
|
|
void ExternalName::importDdeItemError( SequenceInputStream& rStrm )
|
|
{
|
|
appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
|
|
}
|
|
|
|
void ExternalName::importDdeItemString( SequenceInputStream& rStrm )
|
|
{
|
|
appendResultValue( BiffHelper::readString( rStrm ) );
|
|
}
|
|
|
|
void ExternalName::importExternalName( BiffInputStream& rStrm )
|
|
{
|
|
sal_uInt16 nFlags = 0;
|
|
if( getBiff() >= BIFF3 )
|
|
{
|
|
rStrm >> nFlags;
|
|
maExtNameModel.mbBuiltIn = getFlag( nFlags, BIFF_EXTNAME_BUILTIN );
|
|
maExtNameModel.mbNotify = getFlag( nFlags, BIFF_EXTNAME_AUTOMATIC );
|
|
maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF_EXTNAME_PREFERPIC );
|
|
|
|
// BIFF5-BIFF8: sheet index for sheet-local names, OLE settings
|
|
if( getBiff() >= BIFF5 )
|
|
{
|
|
maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF_EXTNAME_STDDOCNAME );
|
|
maExtNameModel.mbOleObj = getFlag( nFlags, BIFF_EXTNAME_OLEOBJECT );
|
|
maExtNameModel.mbIconified = getFlag( nFlags, BIFF_EXTNAME_ICONIFIED );
|
|
|
|
if( maExtNameModel.mbOleObj )
|
|
{
|
|
rStrm >> mnStorageId;
|
|
}
|
|
else
|
|
{
|
|
/* Import the reference ID for names that are sheet-local in
|
|
the external document. This index will be resolved later to
|
|
the index of the external sheet cache which is able to
|
|
provide the name of the sheet related to this defined name.
|
|
- BIFF5: one-based index to EXTERNSHEET record containing
|
|
the document and sheet name
|
|
- BIFF8: one-based index into EXTERNALBOOK sheet name list
|
|
The value zero means this external name is a global name.
|
|
*/
|
|
rStrm.skip( 2 );
|
|
maModel.mnSheet = rStrm.readuInt16();
|
|
}
|
|
}
|
|
}
|
|
|
|
maModel.maName = (getBiff() == BIFF8) ?
|
|
rStrm.readUniStringBody( rStrm.readuInt8() ) :
|
|
rStrm.readByteStringUC( false, getTextEncoding() );
|
|
OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importExternalName - empty name" );
|
|
|
|
// load cell references that are stored in hidden external names (seen in BIFF3-BIFF4)
|
|
bool bHiddenRef = (getBiff() <= BIFF4) && (maModel.maName.getLength() > 1) && (maModel.maName[ 0 ] == '\x01') && (rStrm.getRemaining() > 2);
|
|
switch( mrParentLink.getLinkType() )
|
|
{
|
|
case LINKTYPE_INTERNAL:
|
|
// cell references to other internal sheets are stored in hidden external names
|
|
if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() )
|
|
{
|
|
ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm );
|
|
extractReference( aTokens );
|
|
}
|
|
break;
|
|
|
|
case LINKTYPE_EXTERNAL:
|
|
// cell references to other documents are stored in hidden external names
|
|
if( bHiddenRef )
|
|
{
|
|
ApiTokenSequence aTokens = importBiffFormula( 0, rStrm );
|
|
extractExternalReference( aTokens );
|
|
}
|
|
break;
|
|
|
|
case LINKTYPE_DDE:
|
|
case LINKTYPE_OLE:
|
|
case LINKTYPE_MAYBE_DDE_OLE:
|
|
// DDE/OLE link results
|
|
if( rStrm.getRemaining() > 3 )
|
|
{
|
|
bool bBiff8 = getBiff() == BIFF8;
|
|
sal_Int32 nCols = rStrm.readuInt8();
|
|
sal_Int32 nRows = rStrm.readuInt16();
|
|
if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256;
|
|
setResultSize( nCols, nRows );
|
|
|
|
bool bLoop = true;
|
|
while( bLoop && !rStrm.isEof() && (maCurrIt != maResults.end()) )
|
|
{
|
|
switch( rStrm.readuInt8() )
|
|
{
|
|
case BIFF_DATATYPE_EMPTY:
|
|
appendResultValue( OUString() );
|
|
rStrm.skip( 8 );
|
|
break;
|
|
case BIFF_DATATYPE_DOUBLE:
|
|
appendResultValue( rStrm.readDouble() );
|
|
break;
|
|
case BIFF_DATATYPE_STRING:
|
|
appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ) );
|
|
break;
|
|
case BIFF_DATATYPE_BOOL:
|
|
appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
|
|
rStrm.skip( 7 );
|
|
break;
|
|
case BIFF_DATATYPE_ERROR:
|
|
appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
|
|
rStrm.skip( 7 );
|
|
break;
|
|
default:
|
|
bLoop = false;
|
|
}
|
|
}
|
|
OSL_ENSURE( bLoop && !rStrm.isEof() && (maCurrIt == maResults.end()),
|
|
"ExternalName::importExternalName - stream error in result set" );
|
|
}
|
|
break;
|
|
|
|
default:;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
sal_Int32 ExternalName::getSheetCacheIndex() const
|
|
{
|
|
OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" );
|
|
sal_Int32 nCacheIdx = -1;
|
|
switch( getFilterType() )
|
|
{
|
|
case FILTER_OOXML:
|
|
// OOXML/BIFF12: zero-based index into sheet list, -1 means global name
|
|
if( maModel.mnSheet >= 0 )
|
|
nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
|
|
break;
|
|
case FILTER_BIFF:
|
|
switch( getBiff() )
|
|
{
|
|
case BIFF2:
|
|
case BIFF3:
|
|
case BIFF4:
|
|
break;
|
|
case BIFF5:
|
|
if( maModel.mnSheet > 0 )
|
|
if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() )
|
|
if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL )
|
|
nCacheIdx = pExtLink->getSheetIndex();
|
|
break;
|
|
case BIFF8:
|
|
if( maModel.mnSheet > 0 )
|
|
nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
|
|
break;
|
|
case BIFF_UNKNOWN:
|
|
break;
|
|
}
|
|
break;
|
|
case FILTER_UNKNOWN:
|
|
break;
|
|
}
|
|
return nCacheIdx;
|
|
}
|
|
#endif
|
|
|
|
bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const
|
|
{
|
|
if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
|
|
{
|
|
orItemInfo.Item = maModel.maName;
|
|
orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults );
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem )
|
|
{
|
|
if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
|
|
{
|
|
// try to create a DDE link and to set the imported link results
|
|
if( !mbDdeLinkCreated ) try
|
|
{
|
|
PropertySet aDocProps( getDocument() );
|
|
Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW );
|
|
mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT );
|
|
mbDdeLinkCreated = true; // ignore if setting results fails
|
|
if( !maResults.empty() )
|
|
{
|
|
Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW );
|
|
xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) );
|
|
}
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
|
|
}
|
|
// get link data from created DDE link
|
|
if( mxDdeLink.is() )
|
|
{
|
|
orDdeServer = mxDdeLink->getApplication();
|
|
orDdeTopic = mxDdeLink->getTopic();
|
|
orDdeItem = mxDdeLink->getItem();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// private --------------------------------------------------------------------
|
|
|
|
namespace {
|
|
|
|
void lclSetSheetCacheIndex( SingleReference& orApiRef, sal_Int32 nCacheIdx )
|
|
{
|
|
using namespace ::com::sun::star::sheet::ReferenceFlags;
|
|
setFlag( orApiRef.Flags, SHEET_RELATIVE, false );
|
|
setFlag( orApiRef.Flags, SHEET_3D, true );
|
|
orApiRef.Sheet = nCacheIdx;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void ExternalName::extractExternalReference( const ApiTokenSequence& rTokens )
|
|
{
|
|
OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4), "ExternalName::setExternalReference - unexpected call" );
|
|
sal_Int32 nDocLinkIdx = mrParentLink.getDocumentLinkIndex();
|
|
sal_Int32 nCacheIdx = mrParentLink.getSheetCacheIndex();
|
|
if( (nDocLinkIdx >= 0) && (nCacheIdx >= 0) )
|
|
{
|
|
ExternalReference aExtApiRef;
|
|
aExtApiRef.Index = nDocLinkIdx;
|
|
|
|
Any aRefAny = getFormulaParser().extractReference( rTokens );
|
|
if( aRefAny.has< SingleReference >() )
|
|
{
|
|
SingleReference aApiRef;
|
|
aRefAny >>= aApiRef;
|
|
lclSetSheetCacheIndex( aApiRef, nCacheIdx );
|
|
aExtApiRef.Reference <<= aApiRef;
|
|
maRefAny <<= aExtApiRef;
|
|
}
|
|
else if( aRefAny.has< ComplexReference >() )
|
|
{
|
|
ComplexReference aApiRef;
|
|
aRefAny >>= aApiRef;
|
|
lclSetSheetCacheIndex( aApiRef.Reference1, nCacheIdx );
|
|
lclSetSheetCacheIndex( aApiRef.Reference2, nCacheIdx );
|
|
aExtApiRef.Reference <<= aApiRef;
|
|
maRefAny <<= aExtApiRef;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows )
|
|
{
|
|
OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) ||
|
|
(mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" );
|
|
OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" );
|
|
const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
|
|
if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) )
|
|
maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) );
|
|
else
|
|
maResults.clear();
|
|
maCurrIt = maResults.begin();
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
void LinkSheetRange::setDeleted()
|
|
{
|
|
meType = LINKSHEETRANGE_INTERNAL;
|
|
mnDocLink = mnFirst = mnLast = -1;
|
|
}
|
|
|
|
void LinkSheetRange::setSameSheet()
|
|
{
|
|
meType = LINKSHEETRANGE_SAMESHEET;
|
|
mnDocLink = -1;
|
|
mnFirst = mnLast = 0;
|
|
}
|
|
|
|
void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
|
|
{
|
|
meType = LINKSHEETRANGE_INTERNAL;
|
|
mnDocLink = -1;
|
|
mnFirst = ::std::min( nFirst, nLast );
|
|
mnLast = ::std::max( nFirst, nLast );
|
|
}
|
|
|
|
void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast )
|
|
{
|
|
if( nDocLink < 0 )
|
|
{
|
|
setDeleted();
|
|
}
|
|
else
|
|
{
|
|
meType = LINKSHEETRANGE_EXTERNAL;
|
|
mnDocLink = nDocLink;
|
|
mnFirst = ::std::min( nFirst, nLast );
|
|
mnLast = ::std::max( nFirst, nLast );
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
|
|
WorkbookHelper( rHelper ),
|
|
meLinkType( LINKTYPE_UNKNOWN ),
|
|
meFuncLibType( FUNCLIB_UNKNOWN )
|
|
{
|
|
}
|
|
|
|
void ExternalLink::importExternalReference( const AttributeList& rAttribs )
|
|
{
|
|
maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
|
|
}
|
|
|
|
void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
|
|
{
|
|
parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
|
|
}
|
|
|
|
void ExternalLink::importSheetName( const AttributeList& rAttribs )
|
|
{
|
|
insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) );
|
|
}
|
|
|
|
void ExternalLink::importDefinedName( const AttributeList& rAttribs )
|
|
{
|
|
createExternalName()->importDefinedName( rAttribs );
|
|
}
|
|
|
|
void ExternalLink::importDdeLink( const AttributeList& rAttribs )
|
|
{
|
|
OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() );
|
|
OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() );
|
|
setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
|
|
}
|
|
|
|
ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs )
|
|
{
|
|
ExternalNameRef xExtName = createExternalName();
|
|
xExtName->importDdeItem( rAttribs );
|
|
return xExtName;
|
|
}
|
|
|
|
void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs )
|
|
{
|
|
OUString aProgId = rAttribs.getXString( XML_progId, OUString() );
|
|
OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
|
|
setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
|
|
}
|
|
|
|
ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs )
|
|
{
|
|
ExternalNameRef xExtName = createExternalName();
|
|
xExtName->importOleItem( rAttribs );
|
|
return xExtName;
|
|
}
|
|
|
|
void ExternalLink::importExternalRef( SequenceInputStream& rStrm )
|
|
{
|
|
rStrm >> maRelId;
|
|
}
|
|
|
|
void ExternalLink::importExternalSelf( SequenceInputStream& )
|
|
{
|
|
meLinkType = LINKTYPE_SELF;
|
|
}
|
|
|
|
void ExternalLink::importExternalSame( SequenceInputStream& )
|
|
{
|
|
meLinkType = LINKTYPE_SAME;
|
|
}
|
|
|
|
void ExternalLink::importExternalAddin( SequenceInputStream& )
|
|
{
|
|
meLinkType = LINKTYPE_UNKNOWN;
|
|
}
|
|
|
|
void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm )
|
|
{
|
|
switch( rStrm.readuInt16() )
|
|
{
|
|
case BIFF12_EXTERNALBOOK_BOOK:
|
|
parseExternalReference( rRelations, BiffHelper::readString( rStrm ) );
|
|
break;
|
|
case BIFF12_EXTERNALBOOK_DDE:
|
|
{
|
|
OUString aDdeService, aDdeTopic;
|
|
rStrm >> aDdeService >> aDdeTopic;
|
|
setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
|
|
}
|
|
break;
|
|
case BIFF12_EXTERNALBOOK_OLE:
|
|
{
|
|
OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
|
|
OUString aProgId = BiffHelper::readString( rStrm );
|
|
setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
|
|
}
|
|
break;
|
|
default:
|
|
OSL_FAIL( "ExternalLink::importExternalBook - unknown link type" );
|
|
}
|
|
}
|
|
|
|
void ExternalLink::importExtSheetNames( SequenceInputStream& rStrm )
|
|
{
|
|
// load external sheet names and create the sheet caches in the Calc document
|
|
OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
|
|
"ExternalLink::importExtSheetNames - invalid link type" );
|
|
if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries
|
|
for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
|
|
insertExternalSheet( BiffHelper::readString( rStrm ) );
|
|
}
|
|
|
|
ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& rStrm )
|
|
{
|
|
ExternalNameRef xExtName = createExternalName();
|
|
xExtName->importExternalName( rStrm );
|
|
return xExtName;
|
|
}
|
|
|
|
void ExternalLink::importExternSheet( BiffInputStream& rStrm )
|
|
{
|
|
OStringBuffer aTargetBuffer( rStrm.readByteString( false, true ) );
|
|
// references to own sheets have wrong string length field (off by 1)
|
|
if( (aTargetBuffer.getLength() > 0) && (aTargetBuffer[ 0 ] == 3) )
|
|
aTargetBuffer.append( static_cast< sal_Char >( rStrm.readuInt8() ) );
|
|
// parse the encoded URL
|
|
OUString aBiffTarget = OStringToOUString( aTargetBuffer.makeStringAndClear(), getTextEncoding() );
|
|
OUString aSheetName = parseBiffTargetUrl( aBiffTarget );
|
|
switch( meLinkType )
|
|
{
|
|
case LINKTYPE_INTERNAL:
|
|
maCalcSheets.push_back( getWorksheets().getCalcSheetIndex( aSheetName ) );
|
|
break;
|
|
case LINKTYPE_EXTERNAL:
|
|
insertExternalSheet( aSheetName.isEmpty() ? WorksheetBuffer::getBaseFileName( maTargetUrl ) : aSheetName);
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
|
|
void ExternalLink::importExternalBook( BiffInputStream& rStrm )
|
|
{
|
|
OUString aTarget;
|
|
sal_uInt16 nSheetCount;
|
|
rStrm >> nSheetCount;
|
|
if( rStrm.getRemaining() == 2 )
|
|
{
|
|
if( rStrm.readuInt8() == 1 )
|
|
{
|
|
sal_Char cChar = static_cast< sal_Char >( rStrm.readuInt8() );
|
|
if( cChar != 0 )
|
|
aTarget = OStringToOUString( OString( cChar ), getTextEncoding() );
|
|
}
|
|
}
|
|
else if( rStrm.getRemaining() >= 3 )
|
|
{
|
|
// NUL characters may occur
|
|
aTarget = rStrm.readUniString( true );
|
|
}
|
|
|
|
// parse the encoded URL
|
|
OUString aDummySheetName = parseBiffTargetUrl( aTarget );
|
|
OSL_ENSURE( aDummySheetName.isEmpty(), "ExternalLink::importExternalBook - sheet name in encoded URL" );
|
|
(void)aDummySheetName; // prevent compiler warning
|
|
|
|
// load external sheet names and create the sheet caches in the Calc document
|
|
if( meLinkType == LINKTYPE_EXTERNAL )
|
|
for( sal_uInt16 nSheet = 0; !rStrm.isEof() && (nSheet < nSheetCount); ++nSheet )
|
|
insertExternalSheet( rStrm.readUniString() );
|
|
}
|
|
|
|
void ExternalLink::importExternalName( BiffInputStream& rStrm )
|
|
{
|
|
ExternalNameRef xExtName = createExternalName();
|
|
xExtName->importExternalName( rStrm );
|
|
switch( meLinkType )
|
|
{
|
|
case LINKTYPE_DDE:
|
|
OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in DDE link" );
|
|
break;
|
|
case LINKTYPE_OLE:
|
|
OSL_ENSURE( xExtName->isOleObject(), "ExternalLink::importExternalName - anything but OLE object in OLE link" );
|
|
break;
|
|
case LINKTYPE_MAYBE_DDE_OLE:
|
|
meLinkType = xExtName->isOleObject() ? LINKTYPE_OLE : LINKTYPE_DDE;
|
|
break;
|
|
default:
|
|
OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in external name" );
|
|
}
|
|
}
|
|
|
|
ExternalLinkInfo ExternalLink::getLinkInfo() const
|
|
{
|
|
ExternalLinkInfo aLinkInfo;
|
|
switch( meLinkType )
|
|
{
|
|
case LINKTYPE_EXTERNAL:
|
|
aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
|
|
aLinkInfo.Data <<= maTargetUrl;
|
|
break;
|
|
case LINKTYPE_DDE:
|
|
{
|
|
aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE;
|
|
DDELinkInfo aDdeLinkInfo;
|
|
aDdeLinkInfo.Service = maClassName;
|
|
aDdeLinkInfo.Topic = maTargetUrl;
|
|
::std::vector< DDEItemInfo > aItemInfos;
|
|
DDEItemInfo aItemInfo;
|
|
for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt )
|
|
if( (*aIt)->getDdeItemInfo( aItemInfo ) )
|
|
aItemInfos.push_back( aItemInfo );
|
|
aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos );
|
|
aLinkInfo.Data <<= aDdeLinkInfo;
|
|
}
|
|
break;
|
|
default:
|
|
aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN;
|
|
}
|
|
return aLinkInfo;
|
|
}
|
|
|
|
FunctionLibraryType ExternalLink::getFuncLibraryType() const
|
|
{
|
|
return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
|
|
}
|
|
|
|
sal_Int16 ExternalLink::getCalcSheetIndex( sal_Int32 nTabId ) const
|
|
{
|
|
OSL_ENSURE( meLinkType == LINKTYPE_INTERNAL, "ExternalLink::getCalcSheetIndex - invalid link type" );
|
|
OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
|
|
"ExternalLink::getCalcSheetIndex - invalid sheet index" );
|
|
return ContainerHelper::getVectorElement( maCalcSheets, nTabId, -1 );
|
|
}
|
|
|
|
sal_Int32 ExternalLink::getDocumentLinkIndex() const
|
|
{
|
|
OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" );
|
|
return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1;
|
|
}
|
|
|
|
sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const
|
|
{
|
|
OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" );
|
|
OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
|
|
"ExternalLink::getSheetCacheIndex - invalid sheet index" );
|
|
return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 );
|
|
}
|
|
|
|
Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const
|
|
{
|
|
sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId );
|
|
if( mxDocLink.is() && (nCacheIdx >= 0) ) try
|
|
{
|
|
// existing mxDocLink implies that this is an external link
|
|
Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW );
|
|
return xSheetCache;
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
|
|
{
|
|
switch( meLinkType )
|
|
{
|
|
case LINKTYPE_SAME:
|
|
orSheetRange.setSameSheet();
|
|
break;
|
|
|
|
case LINKTYPE_SELF:
|
|
case LINKTYPE_INTERNAL:
|
|
orSheetRange.setRange( nTabId1, nTabId2 );
|
|
break;
|
|
|
|
case LINKTYPE_EXTERNAL:
|
|
{
|
|
sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
|
|
switch( getFilterType() )
|
|
{
|
|
case FILTER_OOXML:
|
|
// BIFF12: passed indexes point into sheet list of EXTSHEETLIST
|
|
orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
|
|
break;
|
|
case FILTER_BIFF:
|
|
switch( getBiff() )
|
|
{
|
|
case BIFF2:
|
|
case BIFF3:
|
|
case BIFF4:
|
|
orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
|
|
break;
|
|
case BIFF5:
|
|
// BIFF5: first sheet from this external link, last sheet is passed in nTabId2
|
|
if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() )
|
|
if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) )
|
|
orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() );
|
|
break;
|
|
case BIFF8:
|
|
// BIFF8: passed indexes point into sheet list of EXTERNALBOOK
|
|
orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
|
|
break;
|
|
case BIFF_UNKNOWN: break;
|
|
}
|
|
break;
|
|
case FILTER_UNKNOWN: break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// unsupported/unexpected link type: #REF! error
|
|
orSheetRange.setDeleted();
|
|
}
|
|
}
|
|
|
|
ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
|
|
{
|
|
return maExtNames.get( nIndex );
|
|
}
|
|
|
|
// private --------------------------------------------------------------------
|
|
|
|
#define OOX_TARGETTYPE_EXTLINK CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" )
|
|
#define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" )
|
|
|
|
void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
|
|
{
|
|
meLinkType = LINKTYPE_UNKNOWN;
|
|
if( rTargetType == OOX_TARGETTYPE_EXTLINK )
|
|
{
|
|
maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
|
|
if( !maTargetUrl.isEmpty() )
|
|
meLinkType = LINKTYPE_EXTERNAL;
|
|
}
|
|
else if( rTargetType == OOX_TARGETTYPE_LIBRARY )
|
|
{
|
|
meLinkType = LINKTYPE_LIBRARY;
|
|
meFuncLibType = getFormulaParser().getFuncLibTypeFromLibraryName( rTargetUrl );
|
|
}
|
|
OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
|
|
|
|
// create the external document link API object that will contain the sheet caches
|
|
if( meLinkType == LINKTYPE_EXTERNAL ) try
|
|
{
|
|
PropertySet aDocProps( getDocument() );
|
|
Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW );
|
|
mxDocLink = xDocLinks->addDocLink( maTargetUrl );
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType )
|
|
{
|
|
maClassName = rClassName;
|
|
maTargetUrl = rTargetUrl;
|
|
meLinkType = (maClassName.isEmpty() || maTargetUrl.isEmpty()) ? LINKTYPE_UNKNOWN : eLinkType;
|
|
OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
|
|
}
|
|
|
|
void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
|
|
{
|
|
if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
|
|
setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
|
|
}
|
|
|
|
OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl )
|
|
{
|
|
meLinkType = LINKTYPE_UNKNOWN;
|
|
|
|
OUString aClassName, aTargetUrl, aSheetName;
|
|
switch( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) )
|
|
{
|
|
case BIFF_TARGETTYPE_URL:
|
|
if( aTargetUrl.isEmpty() )
|
|
{
|
|
meLinkType = aSheetName.isEmpty() ? LINKTYPE_SELF : LINKTYPE_INTERNAL;
|
|
}
|
|
else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') )
|
|
{
|
|
if( getBiff() >= BIFF4 )
|
|
meLinkType = LINKTYPE_ANALYSIS;
|
|
}
|
|
else if( (aTargetUrl.getLength() > 1) || (aTargetUrl[ 0 ] != ' ') )
|
|
{
|
|
setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_EXTLINK );
|
|
}
|
|
break;
|
|
|
|
case BIFF_TARGETTYPE_SAMESHEET:
|
|
OSL_ENSURE( aTargetUrl.isEmpty() && aSheetName.isEmpty(), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" );
|
|
meLinkType = LINKTYPE_SAME;
|
|
break;
|
|
|
|
case BIFF_TARGETTYPE_LIBRARY:
|
|
OSL_ENSURE( aSheetName.isEmpty(), "ExternalLink::parseBiffTargetUrl - unexpected sheet name" );
|
|
setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_LIBRARY );
|
|
break;
|
|
|
|
case BIFF_TARGETTYPE_DDE_OLE:
|
|
setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE );
|
|
break;
|
|
|
|
case BIFF_TARGETTYPE_UNKNOWN:
|
|
break;
|
|
}
|
|
return aSheetName;
|
|
}
|
|
|
|
void ExternalLink::insertExternalSheet( const OUString& rSheetName )
|
|
{
|
|
OSL_ENSURE( !rSheetName.isEmpty(), "ExternalLink::insertExternalSheet - empty sheet name" );
|
|
if( mxDocLink.is() )
|
|
{
|
|
Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false );
|
|
sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1;
|
|
maSheetCaches.push_back( nCacheIdx );
|
|
}
|
|
}
|
|
|
|
ExternalNameRef ExternalLink::createExternalName()
|
|
{
|
|
ExternalNameRef xExtName( new ExternalName( *this ) );
|
|
maExtNames.push_back( xExtName );
|
|
return xExtName;
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
RefSheetsModel::RefSheetsModel() :
|
|
mnExtRefId( -1 ),
|
|
mnTabId1( -1 ),
|
|
mnTabId2( -1 )
|
|
{
|
|
}
|
|
|
|
void RefSheetsModel::readBiff12Data( SequenceInputStream& rStrm )
|
|
{
|
|
rStrm >> mnExtRefId >> mnTabId1 >> mnTabId2;
|
|
}
|
|
|
|
void RefSheetsModel::readBiff8Data( BiffInputStream& rStrm )
|
|
{
|
|
mnExtRefId = rStrm.readuInt16();
|
|
mnTabId1 = rStrm.readInt16();
|
|
mnTabId2 = rStrm.readInt16();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) :
|
|
WorkbookHelper( rHelper ),
|
|
mxSelfRef( new ExternalLink( rHelper ) ),
|
|
mbUseRefSheets( false )
|
|
{
|
|
mxSelfRef->setSelfLinkType();
|
|
}
|
|
|
|
ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs )
|
|
{
|
|
ExternalLinkRef xExtLink = createExternalLink();
|
|
xExtLink->importExternalReference( rAttribs );
|
|
maExtLinks.push_back( xExtLink );
|
|
return xExtLink;
|
|
}
|
|
|
|
ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm )
|
|
{
|
|
mbUseRefSheets = true;
|
|
ExternalLinkRef xExtLink = createExternalLink();
|
|
xExtLink->importExternalRef( rStrm );
|
|
maExtLinks.push_back( xExtLink );
|
|
return xExtLink;
|
|
}
|
|
|
|
void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm )
|
|
{
|
|
mbUseRefSheets = true;
|
|
createExternalLink()->importExternalSelf( rStrm );
|
|
}
|
|
|
|
void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm )
|
|
{
|
|
mbUseRefSheets = true;
|
|
createExternalLink()->importExternalSame( rStrm );
|
|
}
|
|
|
|
void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm )
|
|
{
|
|
mbUseRefSheets = true;
|
|
createExternalLink()->importExternalAddin( rStrm );
|
|
}
|
|
|
|
void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& rStrm )
|
|
{
|
|
OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
|
|
mbUseRefSheets = true;
|
|
OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
|
|
maRefSheets.clear();
|
|
sal_Int32 nRefCount;
|
|
rStrm >> nRefCount;
|
|
size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 );
|
|
maRefSheets.reserve( nMaxCount );
|
|
for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId )
|
|
{
|
|
RefSheetsModel aRefSheets;
|
|
aRefSheets.readBiff12Data( rStrm );
|
|
maRefSheets.push_back( aRefSheets );
|
|
}
|
|
}
|
|
|
|
ExternalLinkRef ExternalLinkBuffer::importExternSheet( BiffInputStream& rStrm )
|
|
{
|
|
OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::importExternSheet - wrong BIFF version" );
|
|
ExternalLinkRef xExtLink = createExternalLink();
|
|
xExtLink->importExternSheet( rStrm );
|
|
return xExtLink;
|
|
}
|
|
|
|
ExternalLinkRef ExternalLinkBuffer::importExternalBook( BiffInputStream& rStrm )
|
|
{
|
|
ExternalLinkRef xExtLink = createExternalLink();
|
|
xExtLink->importExternalBook( rStrm );
|
|
return xExtLink;
|
|
}
|
|
|
|
void ExternalLinkBuffer::importExternalName( BiffInputStream& rStrm )
|
|
{
|
|
if( !maLinks.empty() )
|
|
maLinks.back()->importExternalName( rStrm );
|
|
}
|
|
|
|
void ExternalLinkBuffer::importExternSheet8( BiffInputStream& rStrm )
|
|
{
|
|
OSL_ENSURE( getBiff() == BIFF8, "ExternalLinkBuffer::importExternSheet8 - wrong BIFF version" );
|
|
|
|
sal_uInt16 nRefCount;
|
|
rStrm >> nRefCount;
|
|
OSL_ENSURE( static_cast< sal_Int64 >( nRefCount * 6 ) == rStrm.getRemaining(), "ExternalLinkBuffer::importExternSheet8 - invalid count" );
|
|
nRefCount = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nRefCount, rStrm.getRemaining() / 6 ) );
|
|
|
|
/* #i104057# A weird external XLS generator writes multiple EXTERNSHEET
|
|
records instead of only one as expected. Surprisingly, Excel seems to
|
|
insert the entries of the second record before the entries of the first
|
|
record. */
|
|
maRefSheets.insert( maRefSheets.begin(), nRefCount, RefSheetsModel() );
|
|
for( RefSheetsModelVec::iterator aIt = maRefSheets.begin(), aEnd = aIt + nRefCount; !rStrm.isEof() && (aIt != aEnd); ++aIt )
|
|
aIt->readBiff8Data( rStrm );
|
|
}
|
|
|
|
Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const
|
|
{
|
|
::std::vector< ExternalLinkInfo > aLinkInfos;
|
|
// should not be used for BIFF12 documents
|
|
OSL_ENSURE( (getFilterType() == FILTER_OOXML) && !mbUseRefSheets, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
|
|
// add entry for implicit index 0 (self reference to this document)
|
|
aLinkInfos.push_back( mxSelfRef->getLinkInfo() );
|
|
for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt )
|
|
aLinkInfos.push_back( (*aIt)->getLinkInfo() );
|
|
return ContainerHelper::vectorToSequence( aLinkInfos );
|
|
}
|
|
|
|
ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId, bool bUseRefSheets ) const
|
|
{
|
|
ExternalLinkRef xExtLink;
|
|
switch( getFilterType() )
|
|
{
|
|
case FILTER_OOXML:
|
|
// OOXML: 0 = this document, otherwise one-based index into link list
|
|
if( !bUseRefSheets || !mbUseRefSheets )
|
|
xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 );
|
|
// BIFF12: zero-based index into ref-sheets list
|
|
else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
|
|
xExtLink = maLinks.get( pRefSheets->mnExtRefId );
|
|
break;
|
|
case FILTER_BIFF:
|
|
switch( getBiff() )
|
|
{
|
|
case BIFF2:
|
|
case BIFF3:
|
|
case BIFF4:
|
|
// one-based index to EXTERNSHEET records
|
|
xExtLink = maLinks.get( nRefId - 1 );
|
|
break;
|
|
case BIFF5:
|
|
if( nRefId < 0 )
|
|
{
|
|
// internal links in formula tokens have negative index
|
|
xExtLink = maLinks.get( -nRefId - 1 );
|
|
if( xExtLink.get() && !xExtLink->isInternalLink() )
|
|
xExtLink.reset();
|
|
}
|
|
else
|
|
{
|
|
// one-based index to EXTERNSHEET records
|
|
xExtLink = maLinks.get( nRefId - 1 );
|
|
}
|
|
break;
|
|
case BIFF8:
|
|
// zero-based index into REF list in EXTERNSHEET record
|
|
if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
|
|
xExtLink = maLinks.get( pRefSheets->mnExtRefId );
|
|
break;
|
|
case BIFF_UNKNOWN: break;
|
|
}
|
|
break;
|
|
case FILTER_UNKNOWN: break;
|
|
}
|
|
return xExtLink;
|
|
}
|
|
|
|
LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const
|
|
{
|
|
OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
|
|
LinkSheetRange aSheetRange;
|
|
if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
|
|
pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 );
|
|
return aSheetRange;
|
|
}
|
|
|
|
LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const
|
|
{
|
|
OSL_ENSURE( ((getFilterType() == FILTER_OOXML) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
|
|
LinkSheetRange aSheetRange;
|
|
if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
|
|
if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
|
|
pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 );
|
|
return aSheetRange;
|
|
}
|
|
|
|
// private --------------------------------------------------------------------
|
|
|
|
ExternalLinkRef ExternalLinkBuffer::createExternalLink()
|
|
{
|
|
ExternalLinkRef xExtLink( new ExternalLink( *this ) );
|
|
maLinks.push_back( xExtLink );
|
|
return xExtLink;
|
|
}
|
|
|
|
const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const
|
|
{
|
|
return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ?
|
|
&maRefSheets[ static_cast< size_t >( nRefId ) ] : 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
} // namespace xls
|
|
} // namespace oox
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|