/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



#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.getLength() > 0, "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.getLength() > 0, "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.getLength() > 0, "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.getLength() > 0, "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.getLength() > 0, "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.getLength() > 0) )
    {
        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.getLength() > 0) )
    {
        // 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_ENSURE( false, "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_ENSURE( false, "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.getLength() > 0) ? aSheetName : WorksheetBuffer::getBaseFileName( maTargetUrl ) );
        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.getLength() == 0, "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_SELF:
        case LINKTYPE_SAME:
        case LINKTYPE_INTERNAL:
            aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF;
        break;
        case LINKTYPE_EXTERNAL:
            aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
            aLinkInfo.Data <<= maTargetUrl;
        break;
        case LINKTYPE_LIBRARY:
            // parser will return library function names in OPCODE_BAD string tokens
            aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL;
        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.getLength() > 0 )
            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.getLength() > 0) && (maTargetUrl.getLength() > 0)) ? eLinkType : LINKTYPE_UNKNOWN;
    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.getLength() == 0 )
            {
                meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF;
            }
            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.getLength() == 0) && (aSheetName.getLength() == 0), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" );
            meLinkType = LINKTYPE_SAME;
        break;

        case BIFF_TARGETTYPE_LIBRARY:
            OSL_ENSURE( aSheetName.getLength() == 0, "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.getLength() > 0, "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;
    // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
    OSL_ENSURE( getFilterType() == FILTER_OOXML, "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
