LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xelink.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 393 982 40.0 %
Date: 2015-06-13 12:38:46 Functions: 86 195 44.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "xelink.hxx"
      21             : 
      22             : #include <algorithm>
      23             : #include <unotools/collatorwrapper.hxx>
      24             : #include <svl/zforlist.hxx>
      25             : #include "document.hxx"
      26             : #include "formulacell.hxx"
      27             : #include "scextopt.hxx"
      28             : #include "externalrefmgr.hxx"
      29             : #include "tokenarray.hxx"
      30             : #include "xecontent.hxx"
      31             : 
      32             : #include <vector>
      33             : #include <memory>
      34             : 
      35             : using ::std::unique_ptr;
      36             : using ::std::vector;
      37             : using ::com::sun::star::uno::Any;
      38             : 
      39             : using namespace oox;
      40             : 
      41             : // *** Helper classes ***
      42             : 
      43             : // External names =============================================================
      44             : 
      45             : /** This is a base class for any external name (i.e. add-in names or DDE links).
      46             :     @descr  Derived classes implement creation and export of the external names. */
      47             : class XclExpExtNameBase : public XclExpRecord, protected XclExpRoot
      48             : {
      49             : public:
      50             :     /** @param nFlags  The flags to export. */
      51             :     explicit            XclExpExtNameBase( const XclExpRoot& rRoot,
      52             :                             const OUString& rName, sal_uInt16 nFlags = 0 );
      53             :     virtual             ~XclExpExtNameBase();
      54             : 
      55             :     /** Returns the name string of the external name. */
      56           0 :     inline const OUString& GetName() const { return maName; }
      57             : 
      58             : private:
      59             :     /** Writes the start of the record that is equal in all EXTERNNAME records and calls WriteAddData(). */
      60             :     virtual void        WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
      61             :     /** Called to write additional data following the common record contents.
      62             :         @descr  Derived classes should overwrite this function to write their data. */
      63             :     virtual void        WriteAddData( XclExpStream& rStrm );
      64             : 
      65             : protected:
      66             :     OUString            maName;         /// Calc name (title) of the external name.
      67             :     XclExpStringRef     mxName;         /// Excel name (title) of the external name.
      68             :     sal_uInt16          mnFlags;        /// Flags for record export.
      69             : };
      70             : 
      71             : /** Represents an EXTERNNAME record for an add-in function name. */
      72           0 : class XclExpExtNameAddIn : public XclExpExtNameBase
      73             : {
      74             : public:
      75             :     explicit            XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName );
      76             : 
      77             : private:
      78             :     /** Writes additional record contents. */
      79             :     virtual void        WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
      80             : };
      81             : 
      82             : /** Represents an EXTERNNAME record for a DDE link. */
      83           0 : class XclExpExtNameDde : public XclExpExtNameBase
      84             : {
      85             : public:
      86             :     explicit            XclExpExtNameDde( const XclExpRoot& rRoot, const OUString& rName,
      87             :                             sal_uInt16 nFlags, const ScMatrix* pResults = 0 );
      88             : 
      89             : private:
      90             :     /** Writes additional record contents. */
      91             :     virtual void        WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
      92             : 
      93             : private:
      94             :     typedef boost::shared_ptr< XclExpCachedMatrix > XclExpCachedMatRef;
      95             :     XclExpCachedMatRef  mxMatrix;       /// Cached results of the DDE link.
      96             : };
      97             : 
      98             : class XclExpSupbook;
      99             : 
     100           0 : class XclExpExtName : public XclExpExtNameBase
     101             : {
     102             : public:
     103             :     explicit            XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook, const OUString& rName,
     104             :                                        const ScExternalRefCache::TokenArrayRef& rArray );
     105             : 
     106             :     virtual void SaveXml(XclExpXmlStream& rStrm) SAL_OVERRIDE;
     107             : 
     108             : private:
     109             :     /** Writes additional record contents. */
     110             :     virtual void        WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
     111             : 
     112             : private:
     113             :     const XclExpSupbook&    mrSupbook;
     114             :     unique_ptr<ScTokenArray>  mpArray;
     115             : };
     116             : 
     117             : // List of external names =====================================================
     118             : 
     119             : /** List of all external names of a sheet. */
     120           0 : class XclExpExtNameBuffer : public XclExpRecordBase, protected XclExpRoot
     121             : {
     122             : public:
     123             :     explicit            XclExpExtNameBuffer( const XclExpRoot& rRoot );
     124             : 
     125             :     /** Inserts an add-in function name
     126             :         @return  The 1-based (Excel-like) list index of the name. */
     127             :     sal_uInt16          InsertAddIn( const OUString& rName );
     128             :     /** InsertEuroTool */
     129             :     sal_uInt16          InsertEuroTool( const OUString& rName );
     130             :     /** Inserts a DDE link.
     131             :         @return  The 1-based (Excel-like) list index of the DDE link. */
     132             :     sal_uInt16          InsertDde( const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
     133             : 
     134             :     sal_uInt16          InsertExtName( const XclExpSupbook& rSupbook, const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
     135             : 
     136             :     /** Writes the EXTERNNAME record list. */
     137             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     138             : 
     139             :     virtual void SaveXml(XclExpXmlStream& rStrm) SAL_OVERRIDE;
     140             : 
     141             : private:
     142             :     typedef XclExpRecordList< XclExpExtNameBase >   XclExpExtNameList;
     143             :     typedef XclExpExtNameList::RecordRefType        XclExpExtNameRef;
     144             : 
     145             : private:
     146             :     /** Returns the 1-based (Excel-like) list index of the external name or 0, if not found. */
     147             :     sal_uInt16          GetIndex( const OUString& rName ) const;
     148             :     /** Appends the passed newly crested external name.
     149             :         @return  The 1-based (Excel-like) list index of the appended name. */
     150             :     sal_uInt16          AppendNew( XclExpExtNameBase* pExtName );
     151             : 
     152             : private:
     153             :     XclExpExtNameList   maNameList;     /// The list with all EXTERNNAME records.
     154             : };
     155             : 
     156             : // Cached external cells ======================================================
     157             : 
     158             : /** Stores the contents of a consecutive row of external cells (record CRN). */
     159           2 : class XclExpCrn : public XclExpRecord
     160             : {
     161             : public:
     162             :     explicit            XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue );
     163             : 
     164             :     /** Returns true, if the passed value could be appended to this record. */
     165             :     bool                InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
     166             : 
     167             :     /** Writes the row and child elements. */
     168             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
     169             : 
     170             : private:
     171             :     virtual void        WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
     172             : 
     173             :     static void         WriteBool( XclExpStream& rStrm, bool bValue );
     174             :     static void         WriteDouble( XclExpStream& rStrm, double fValue );
     175             :     static void         WriteString( XclExpStream& rStrm, const OUString& rValue );
     176             :     static void         WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode );
     177             :     static void         WriteEmpty( XclExpStream& rStrm );
     178             : 
     179             : private:
     180             :     typedef ::std::vector< Any > CachedValues;
     181             : 
     182             :     CachedValues        maValues;   /// All cached values.
     183             :     SCCOL               mnScCol;    /// Column index of the first external cell.
     184             :     SCROW               mnScRow;    /// Row index of the external cells.
     185             : };
     186             : 
     187             : namespace { class XclExpCrnList; }
     188             : 
     189             : /** Represents the record XCT which is the header record of a CRN record list.
     190             :  */
     191           2 : class XclExpXct : public XclExpRecordBase, protected XclExpRoot
     192             : {
     193             : public:
     194             :     explicit            XclExpXct( const XclExpRoot& rRoot,
     195             :                             const OUString& rTabName, sal_uInt16 nSBTab,
     196             :                             ScExternalRefCache::TableTypeRef xCacheTable );
     197             : 
     198             :     /** Returns the external sheet name. */
     199           4 :     inline const XclExpString& GetTabName() const { return maTabName; }
     200             : 
     201             :     /** Stores all cells in the given range in the CRN list. */
     202             :     void                StoreCellRange( const ScRange& rRange );
     203             : 
     204             :     void                StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken );
     205             :     void                StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken );
     206             : 
     207             :     /** Writes the XCT and all CRN records. */
     208             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     209             : 
     210             :     /** Writes the sheetDataSet and child elements. */
     211             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
     212             : 
     213             : private:
     214             :     ScExternalRefCache::TableTypeRef mxCacheTable;
     215             :     ScMarkData          maUsedCells;    /// Contains addresses of all stored cells.
     216             :     ScRange             maBoundRange;   /// Bounding box of maUsedCells.
     217             :     XclExpString        maTabName;      /// Sheet name of the external sheet.
     218             :     sal_uInt16          mnSBTab;        /// Referred sheet index in SUPBOOK record.
     219             : 
     220             :     /** Build the internal representation of records to be saved as BIFF or OOXML. */
     221             :     bool                BuildCrnList( XclExpCrnList& rCrnRecs );
     222             : };
     223             : 
     224             : // External documents (EXTERNSHEET/SUPBOOK), base class =======================
     225             : 
     226             : /** Base class for records representing external sheets/documents.
     227             : 
     228             :     In BIFF5/BIFF7, this record is the EXTERNSHEET record containing one sheet
     229             :     of the own or an external document. In BIFF8, this record is the SUPBOOK
     230             :     record representing the entire own or external document with all referenced
     231             :     sheets.
     232             :  */
     233          73 : class XclExpExternSheetBase : public XclExpRecord, protected XclExpRoot
     234             : {
     235             : public:
     236             :     explicit            XclExpExternSheetBase( const XclExpRoot& rRoot,
     237             :                             sal_uInt16 nRecId, sal_uInt32 nRecSize = 0 );
     238             : 
     239             : protected:
     240             :     /** Creates and returns the list of EXTERNNAME records. */
     241             :     XclExpExtNameBuffer& GetExtNameBuffer();
     242             :     /** Writes the list of EXTERNNAME records. */
     243             :     void                WriteExtNameBuffer( XclExpStream& rStrm );
     244             :     /** Writes the list of externalName elements. */
     245             :     void                WriteExtNameBufferXml( XclExpXmlStream& rStrm );
     246             : 
     247             : protected:
     248             :     typedef boost::shared_ptr< XclExpExtNameBuffer >   XclExpExtNameBfrRef;
     249             :     XclExpExtNameBfrRef mxExtNameBfr;   /// List of EXTERNNAME records.
     250             : };
     251             : 
     252             : // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
     253             : 
     254             : /** Represents an EXTERNSHEET record containing the URL and sheet name of a sheet.
     255             :     @descr  This class is used up to BIFF7 only, writing a BIFF8 EXTERNSHEET
     256             :         record is implemented directly in the link manager. */
     257           0 : class XclExpExternSheet : public XclExpExternSheetBase
     258             : {
     259             : public:
     260             :     /** Creates an EXTERNSHEET record containing a special code (i.e. own document or sheet). */
     261             :     explicit            XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode );
     262             :     /** Creates an EXTERNSHEET record referring to an internal sheet. */
     263             :     explicit            XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName );
     264             : 
     265             :     /** Finds or inserts an EXTERNNAME record for add-ins.
     266             :         @return  The 1-based EXTERNNAME record index; or 0, if the record list is full. */
     267             :     sal_uInt16          InsertAddIn( const OUString& rName );
     268             : 
     269             :     /** Writes the EXTERNSHEET and all EXTERNNAME, XCT and CRN records. */
     270             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     271             : 
     272             : private:
     273             :     /** Initializes the record data with the passed encoded URL. */
     274             :     void                Init( const OUString& rEncUrl );
     275             :     /** Writes the contents of the EXTERNSHEET  record. */
     276             :     virtual void        WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
     277             : 
     278             : private:
     279             :     XclExpString        maTabName;      /// The name of the sheet.
     280             : };
     281             : 
     282             : // External documents (SUPBOOK, BIFF8) ========================================
     283             : 
     284             : /** The SUPBOOK record contains data for an external document (URL, sheet names, external values). */
     285         146 : class XclExpSupbook : public XclExpExternSheetBase
     286             : {
     287             : public:
     288             :     /** Creates a SUPBOOK record for internal references. */
     289             :     explicit            XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount );
     290             :     /** Creates a SUPBOOK record for add-in functions. */
     291             :     explicit            XclExpSupbook( const XclExpRoot& rRoot );
     292             :     /** EUROTOOL SUPBOOK */
     293             :     explicit            XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType );
     294             :     /** Creates a SUPBOOK record for an external document. */
     295             :     explicit            XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl );
     296             :     /** Creates a SUPBOOK record for a DDE link. */
     297             :     explicit            XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic );
     298             : 
     299             :     /** Returns true, if this SUPBOOK contains the passed URL of an external document. */
     300             :     bool                IsUrlLink( const OUString& rUrl ) const;
     301             :     /** Returns true, if this SUPBOOK contains the passed DDE link. */
     302             :     bool                IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const;
     303             :     /** Fills the passed reference log entry with the URL and sheet names. */
     304             :     void                FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
     305             :                             sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const;
     306             : 
     307             :     /** Stores all cells in the given range in the CRN list of the specified SUPBOOK sheet. */
     308             :     void                StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
     309             : 
     310             :     void                StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ::formula::FormulaToken& rToken );
     311             :     void                StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ::formula::FormulaToken& rToken );
     312             : 
     313             :     sal_uInt16          GetTabIndex( const OUString& rTabName ) const;
     314             :     sal_uInt16          GetTabCount() const;
     315             : 
     316             :     /** Inserts a new sheet name into the SUPBOOK and returns the SUPBOOK internal sheet index. */
     317             :     sal_uInt16          InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef xCacheTable );
     318             :     /** Finds or inserts an EXTERNNAME record for add-ins.
     319             :         @return  The 1-based EXTERNNAME record index; or 0, if the record list is full. */
     320             :     sal_uInt16          InsertAddIn( const OUString& rName );
     321             :     /** InsertEuroTool */
     322             :     sal_uInt16          InsertEuroTool( const OUString& rName );
     323             :     /** Finds or inserts an EXTERNNAME record for DDE links.
     324             :         @return  The 1-based EXTERNNAME record index; or 0, if the record list is full. */
     325             :     sal_uInt16          InsertDde( const OUString& rItem );
     326             : 
     327             :     sal_uInt16          InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
     328             : 
     329             :     /** Get the type of record. */
     330             :     XclSupbookType      GetType() const;
     331             : 
     332             :     /** For references to an external document, 1-based OOXML file ID. */
     333             :     sal_uInt16          GetFileId() const;
     334             : 
     335             :     /** For references to an external document. */
     336             :     const OUString&     GetUrl() const;
     337             : 
     338             :     /** Writes the SUPBOOK and all EXTERNNAME, XCT and CRN records. */
     339             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     340             : 
     341             :     /** Writes the externalBook and all child elements. */
     342             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
     343             : 
     344             : private:
     345             :     /** Returns the sheet name inside of this SUPBOOK. */
     346             :     const XclExpString* GetTabName( sal_uInt16 nSBTab ) const;
     347             : 
     348             :     /** Writes the SUPBOOK record contents. */
     349             :     virtual void        WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
     350             : 
     351             : private:
     352             :     typedef XclExpRecordList< XclExpXct >   XclExpXctList;
     353             :     typedef XclExpXctList::RecordRefType    XclExpXctRef;
     354             : 
     355             :     XclExpXctList       maXctList;      /// List of XCT records (which contain CRN records).
     356             :     OUString            maUrl;          /// URL of the external document or application name for DDE.
     357             :     OUString            maDdeTopic;     /// Topic of an DDE link.
     358             :     XclExpString        maUrlEncoded;   /// Document name encoded for Excel.
     359             :     XclSupbookType      meType;         /// Type of this SUPBOOK record.
     360             :     sal_uInt16          mnXclTabCount;  /// Number of internal sheets.
     361             :     sal_uInt16          mnFileId;       /// 1-based external reference file ID for OOXML
     362             : };
     363             : 
     364             : // All SUPBOOKS in a document =================================================
     365             : 
     366             : /** This struct contains a sheet index range for 3D references.
     367             :     @descr  This reference consists of an index to a SUPBOOK record and indexes
     368             :     to SUPBOOK sheet names. */
     369             : struct XclExpXti
     370             : {
     371             :     sal_uInt16          mnSupbook;      /// Index to SUPBOOK record.
     372             :     sal_uInt16          mnFirstSBTab;   /// Index to the first sheet of the range in the SUPBOOK.
     373             :     sal_uInt16          mnLastSBTab;    /// Index to the last sheet of the range in the SUPBOOK.
     374             : 
     375         138 :     inline explicit     XclExpXti() : mnSupbook( 0 ), mnFirstSBTab( 0 ), mnLastSBTab( 0 ) {}
     376           1 :     inline explicit     XclExpXti( sal_uInt16 nSupbook, sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) :
     377           1 :                             mnSupbook( nSupbook ), mnFirstSBTab( nFirstSBTab ), mnLastSBTab( nLastSBTab ) {}
     378             : 
     379             :     /** Writes this XTI structure (inside of the EXTERNSHEET record). */
     380           7 :     inline void         Save( XclExpStream& rStrm ) const
     381           7 :                             { rStrm << mnSupbook << mnFirstSBTab << mnLastSBTab; }
     382             : };
     383             : 
     384         114 : inline bool operator==( const XclExpXti& rLeft, const XclExpXti& rRight )
     385             : {
     386             :     return
     387         228 :         (rLeft.mnSupbook    == rRight.mnSupbook)    &&
     388         218 :         (rLeft.mnFirstSBTab == rRight.mnFirstSBTab) &&
     389         218 :         (rLeft.mnLastSBTab  == rRight.mnLastSBTab);
     390             : }
     391             : 
     392             : /** Contains a list of all SUPBOOK records and index arrays of external sheets. */
     393          72 : class XclExpSupbookBuffer : public XclExpRecordBase, protected XclExpRoot
     394             : {
     395             : public:
     396             :     explicit            XclExpSupbookBuffer( const XclExpRoot& rRoot );
     397             : 
     398             :     /** Finds SUPBOOK index and SUPBOOK sheet range from given Excel sheet range.
     399             :         @return  An XTI structure containing SUPBOOK and sheet indexes. */
     400             :     XclExpXti           GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
     401             :                             XclExpRefLogEntry* pRefLogEntry = 0 ) const;
     402             : 
     403             :     /** Stores all cells in the given range in a CRN record list. */
     404             :     void                StoreCellRange( const ScRange& rRange );
     405             : 
     406             :     void                StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell );
     407             :     void                StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange );
     408             : 
     409             :     /** Finds or inserts an EXTERNNAME record for an add-in function name.
     410             :         @param rnSupbook  Returns the index of the SUPBOOK record which contains the add-in function name.
     411             :         @param rnExtName  Returns the 1-based EXTERNNAME record index. */
     412             :     bool                InsertAddIn(
     413             :                             sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
     414             :                             const OUString& rName );
     415             :     /** InsertEuroTool */
     416             :     bool                InsertEuroTool(
     417             :                              sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
     418             :                              const OUString& rName );
     419             :     /** Finds or inserts an EXTERNNAME record for DDE links.
     420             :         @param rnSupbook  Returns the index of the SUPBOOK record which contains the DDE link.
     421             :         @param rnExtName  Returns the 1-based EXTERNNAME record index. */
     422             :     bool                InsertDde(
     423             :                             sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
     424             :                             const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
     425             : 
     426             :     bool                InsertExtName(
     427             :                             sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
     428             :                             const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
     429             : 
     430             :     XclExpXti           GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
     431             :                                 XclExpRefLogEntry* pRefLogEntry = NULL );
     432             : 
     433             :     /** Writes all SUPBOOK records with their sub records. */
     434             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     435             : 
     436             :     /** Writes all externalBook elements with their child elements to OOXML. */
     437             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
     438             : 
     439             :     /** Whether we need to write externalReferences or not. */
     440             :     bool                HasExternalReferences() const;
     441             : 
     442             :     struct XclExpSBIndex
     443             :     {
     444             :         sal_uInt16          mnSupbook;          /// SUPBOOK index for an Excel sheet.
     445             :         sal_uInt16          mnSBTab;            /// Sheet name index in SUPBOOK for an Excel sheet.
     446         129 :         inline void         Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
     447         129 :                                 { mnSupbook = nSupbook; mnSBTab = nSBTab; }
     448             :     };
     449             :     typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
     450             : 
     451             : private:
     452             :     typedef XclExpRecordList< XclExpSupbook >   XclExpSupbookList;
     453             :     typedef XclExpSupbookList::RecordRefType    XclExpSupbookRef;
     454             : 
     455             : private:
     456             :     /** Searches for the SUPBOOK record containing the passed document URL.
     457             :         @param rxSupbook  (out-param) Returns a reference to the SUPBOOK record, or 0.
     458             :         @param rnIndex  (out-param) Returns the list index, if the SUPBOOK exists.
     459             :         @return  True, if the SUPBOOK record exists (out-parameters are valid). */
     460             :     bool                GetSupbookUrl( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
     461             :                             const OUString& rUrl ) const;
     462             :     /** Searches for the SUPBOOK record containing the passed DDE link.
     463             :         @param rxSupbook  (out-param) Returns a reference to the SUPBOOK record, or 0.
     464             :         @param rnIndex  (out-param) Returns the list index, if the SUPBOOK exists.
     465             :         @return  True, if the SUPBOOK record exists (out-parameters are valid). */
     466             :     bool                GetSupbookDde( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
     467             :                             const OUString& rApplic, const OUString& rTopic ) const;
     468             : 
     469             :     /** Appends a new SUPBOOK to the list.
     470             :         @return  The list index of the SUPBOOK record. */
     471             :     sal_uInt16          Append( XclExpSupbookRef xSupbook );
     472             : 
     473             : private:
     474             :     XclExpSupbookList   maSupbookList;      /// List of all SUPBOOK records.
     475             :     XclExpSBIndexVec    maSBIndexVec;       /// SUPBOOK and sheet name index for each Excel sheet.
     476             :     sal_uInt16          mnOwnDocSB;         /// Index to SUPBOOK for own document.
     477             :     sal_uInt16          mnAddInSB;          /// Index to add-in SUPBOOK.
     478             : };
     479             : 
     480             : // Export link manager ========================================================
     481             : 
     482             : /** Abstract base class for implementation classes of the link manager. */
     483          72 : class XclExpLinkManagerImpl : protected XclExpRoot
     484             : {
     485             : public:
     486             :     /** Derived classes search for an EXTSHEET structure for the given Calc sheet range. */
     487             :     virtual void        FindExtSheet( sal_uInt16& rnExtSheet,
     488             :                             sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
     489             :                             SCTAB nFirstScTab, SCTAB nLastScTab,
     490             :                             XclExpRefLogEntry* pRefLogEntry ) = 0;
     491             :     /** Derived classes search for a special EXTERNSHEET index for the own document. */
     492             :     virtual sal_uInt16  FindExtSheet( sal_Unicode cCode ) = 0;
     493             : 
     494             :     virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
     495             :                                sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
     496             :                                XclExpRefLogEntry* pRefLogEntry ) = 0;
     497             : 
     498             :     /** Derived classes store all cells in the given range in a CRN record list. */
     499             :     virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) = 0;
     500             : 
     501             :     virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) = 0;
     502             :     virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) = 0;
     503             : 
     504             :     /** Derived classes find or insert an EXTERNNAME record for an add-in function name. */
     505             :     virtual bool        InsertAddIn(
     506             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     507             :                             const OUString& rName ) = 0;
     508             :     /** InsertEuroTool */
     509             :     virtual bool        InsertEuroTool(
     510             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     511             :                             const OUString& rName ) = 0;
     512             : 
     513             :     /** Derived classes find or insert an EXTERNNAME record for DDE links. */
     514             :     virtual bool        InsertDde(
     515             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     516             :                             const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) = 0;
     517             : 
     518             :     virtual bool        InsertExtName(
     519             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
     520             :                             const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) = 0;
     521             : 
     522             :     /** Derived classes write the entire link table to the passed stream. */
     523             :     virtual void        Save( XclExpStream& rStrm ) = 0;
     524             : 
     525             :     /** Derived classes write the entire link table to the passed OOXML stream. */
     526             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) = 0;
     527             : 
     528             : protected:
     529             :     explicit            XclExpLinkManagerImpl( const XclExpRoot& rRoot );
     530             : };
     531             : 
     532             : /** Implementation of the link manager for BIFF5/BIFF7. */
     533           0 : class XclExpLinkManagerImpl5 : public XclExpLinkManagerImpl
     534             : {
     535             : public:
     536             :     explicit            XclExpLinkManagerImpl5( const XclExpRoot& rRoot );
     537             : 
     538             :     virtual void        FindExtSheet( sal_uInt16& rnExtSheet,
     539             :                             sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
     540             :                             SCTAB nFirstScTab, SCTAB nLastScTab,
     541             :                             XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
     542             :     virtual sal_uInt16  FindExtSheet( sal_Unicode cCode ) SAL_OVERRIDE;
     543             : 
     544             :     virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
     545             :                                sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
     546             :                                XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
     547             : 
     548             :     virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) SAL_OVERRIDE;
     549             : 
     550             :     virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) SAL_OVERRIDE;
     551             :     virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) SAL_OVERRIDE;
     552             : 
     553             :     virtual bool        InsertAddIn(
     554             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     555             :                             const OUString& rName ) SAL_OVERRIDE;
     556             : 
     557             :     /** InsertEuroTool */
     558             :     virtual bool        InsertEuroTool(
     559             :                              sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     560             :                              const OUString& rName ) SAL_OVERRIDE;
     561             : 
     562             :     virtual bool        InsertDde(
     563             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     564             :                             const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) SAL_OVERRIDE;
     565             : 
     566             :     virtual bool        InsertExtName(
     567             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
     568             :                             const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) SAL_OVERRIDE;
     569             : 
     570             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     571             : 
     572             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
     573             : 
     574             : private:
     575             :     typedef XclExpRecordList< XclExpExternSheet >   XclExpExtSheetList;
     576             :     typedef XclExpExtSheetList::RecordRefType       XclExpExtSheetRef;
     577             :     typedef ::std::map< SCTAB, sal_uInt16 >         XclExpIntTabMap;
     578             :     typedef ::std::map< sal_Unicode, sal_uInt16 >   XclExpCodeMap;
     579             : 
     580             : private:
     581             :     /** Returns the number of EXTERNSHEET records. */
     582             :     sal_uInt16          GetExtSheetCount() const;
     583             : 
     584             :     /** Appends an internal EXTERNSHEET record and returns the one-based index. */
     585             :     sal_uInt16          AppendInternal( XclExpExtSheetRef xExtSheet );
     586             :     /** Creates all EXTERNSHEET records for internal sheets on first call. */
     587             :     void                CreateInternal();
     588             : 
     589             :     /** Returns the specified internal EXTERNSHEET record. */
     590             :     XclExpExtSheetRef   GetInternal( sal_uInt16 nExtSheet );
     591             :     /** Returns the EXTERNSHEET index of an internal Calc sheet, or a deleted reference. */
     592             :     XclExpExtSheetRef   FindInternal( sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab );
     593             :     /** Finds or creates the EXTERNSHEET index of an internal special EXTERNSHEET. */
     594             :     XclExpExtSheetRef   FindInternal( sal_uInt16& rnExtSheet, sal_Unicode cCode );
     595             : 
     596             : private:
     597             :     XclExpExtSheetList  maExtSheetList;     /// List with EXTERNSHEET records.
     598             :     XclExpIntTabMap     maIntTabMap;        /// Maps internal Calc sheets to EXTERNSHEET records.
     599             :     XclExpCodeMap       maCodeMap;          /// Maps special external codes to EXTERNSHEET records.
     600             : };
     601             : 
     602             : /** Implementation of the link manager for BIFF8 and OOXML. */
     603         144 : class XclExpLinkManagerImpl8 : public XclExpLinkManagerImpl
     604             : {
     605             : public:
     606             :     explicit            XclExpLinkManagerImpl8( const XclExpRoot& rRoot );
     607             : 
     608             :     virtual void        FindExtSheet( sal_uInt16& rnExtSheet,
     609             :                             sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
     610             :                             SCTAB nFirstScTab, SCTAB nLastScTab,
     611             :                             XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
     612             :     virtual sal_uInt16  FindExtSheet( sal_Unicode cCode ) SAL_OVERRIDE;
     613             : 
     614             :     virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
     615             :                                sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
     616             :                                XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
     617             : 
     618             :     virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) SAL_OVERRIDE;
     619             : 
     620             :     virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) SAL_OVERRIDE;
     621             :     virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) SAL_OVERRIDE;
     622             : 
     623             :     virtual bool        InsertAddIn(
     624             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     625             :                             const OUString& rName ) SAL_OVERRIDE;
     626             :     /** InsertEuroTool */
     627             :     virtual bool        InsertEuroTool(
     628             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     629             :                             const OUString& rName ) SAL_OVERRIDE;
     630             : 
     631             :     virtual bool        InsertDde(
     632             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
     633             :                             const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) SAL_OVERRIDE;
     634             : 
     635             :     virtual bool        InsertExtName(
     636             :                             sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
     637             :                             const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) SAL_OVERRIDE;
     638             : 
     639             :     virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
     640             : 
     641             :     virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
     642             : 
     643             : private:
     644             :     /** Searches for or inserts a new XTI structure.
     645             :         @return  The 0-based list index of the XTI structure. */
     646             :     sal_uInt16          InsertXti( const XclExpXti& rXti );
     647             : 
     648             : private:
     649             :     typedef ::std::vector< XclExpXti > XclExpXtiVec;
     650             : 
     651             :     XclExpSupbookBuffer maSBBuffer;     /// List of all SUPBOOK records.
     652             :     XclExpXtiVec        maXtiVec;       /// List of XTI structures for the EXTERNSHEET record.
     653             : };
     654             : 
     655             : // *** Implementation ***
     656             : 
     657             : // Excel sheet indexes ========================================================
     658             : 
     659             : const sal_uInt8 EXC_TABBUF_IGNORE   = 0x01;     /// Sheet will be ignored completely.
     660             : const sal_uInt8 EXC_TABBUF_EXTERN   = 0x02;     /// Sheet is linked externally.
     661             : const sal_uInt8 EXC_TABBUF_SKIPMASK = 0x0F;     /// Sheet will be skipped, if any flag is set.
     662             : const sal_uInt8 EXC_TABBUF_VISIBLE  = 0x10;     /// Sheet is visible.
     663             : const sal_uInt8 EXC_TABBUF_SELECTED = 0x20;     /// Sheet is selected.
     664             : const sal_uInt8 EXC_TABBUF_MIRRORED = 0x40;     /// Sheet is mirrored (right-to-left).
     665             : 
     666          72 : XclExpTabInfo::XclExpTabInfo( const XclExpRoot& rRoot ) :
     667             :     XclExpRoot( rRoot ),
     668             :     mnScCnt( 0 ),
     669             :     mnXclCnt( 0 ),
     670             :     mnXclExtCnt( 0 ),
     671             :     mnXclSelCnt( 0 ),
     672             :     mnDisplXclTab( 0 ),
     673          72 :     mnFirstVisXclTab( 0 )
     674             : {
     675          72 :     ScDocument& rDoc = GetDoc();
     676          72 :     ScExtDocOptions& rDocOpt = GetExtDocOptions();
     677             : 
     678          72 :     mnScCnt = rDoc.GetTableCount();
     679             : 
     680             :     SCTAB nScTab;
     681          72 :     SCTAB nFirstVisScTab = SCTAB_INVALID;   // first visible sheet
     682          72 :     SCTAB nFirstExpScTab = SCTAB_INVALID;   // first exported sheet
     683             : 
     684             :     // --- initialize the flags in the index buffer ---
     685             : 
     686          72 :     maTabInfoVec.resize( mnScCnt );
     687         201 :     for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
     688             :     {
     689             :         // ignored sheets (skipped by export, with invalid Excel sheet index)
     690         129 :         if( rDoc.IsScenario( nScTab ) )
     691             :         {
     692           0 :             SetFlag( nScTab, EXC_TABBUF_IGNORE );
     693             :         }
     694             : 
     695             :         // external sheets (skipped, but with valid Excel sheet index for ref's)
     696         129 :         else if( rDoc.GetLinkMode( nScTab ) == SC_LINK_VALUE )
     697             :         {
     698           0 :             SetFlag( nScTab, EXC_TABBUF_EXTERN );
     699             :         }
     700             : 
     701             :         // exported sheets
     702             :         else
     703             :         {
     704             :             // sheet name
     705         129 :             rDoc.GetName( nScTab, maTabInfoVec[ nScTab ].maScName );
     706             : 
     707             :             // remember first exported sheet
     708         129 :             if( nFirstExpScTab == SCTAB_INVALID )
     709          72 :                nFirstExpScTab = nScTab;
     710             :             // remember first visible exported sheet
     711         129 :             if( (nFirstVisScTab == SCTAB_INVALID) && rDoc.IsVisible( nScTab ) )
     712          72 :                nFirstVisScTab = nScTab;
     713             : 
     714             :             // sheet visible (only exported sheets)
     715         129 :             SetFlag( nScTab, EXC_TABBUF_VISIBLE, rDoc.IsVisible( nScTab ) );
     716             : 
     717             :             // sheet selected (only exported sheets)
     718         129 :             if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nScTab ) )
     719          46 :                 SetFlag( nScTab, EXC_TABBUF_SELECTED, pTabSett->mbSelected );
     720             : 
     721             :             // sheet mirrored (only exported sheets)
     722         129 :             SetFlag( nScTab, EXC_TABBUF_MIRRORED, rDoc.IsLayoutRTL( nScTab ) );
     723             :         }
     724             :     }
     725             : 
     726             :     // --- visible/selected sheets ---
     727             : 
     728          72 :     SCTAB nDisplScTab = rDocOpt.GetDocSettings().mnDisplTab;
     729             : 
     730             :     // find first visible exported sheet
     731          72 :     if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
     732             :     {
     733             :         // no exportable visible sheet -> use first exportable sheet
     734           0 :         nFirstVisScTab = nFirstExpScTab;
     735           0 :         if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
     736             :         {
     737             :             // no exportable sheet at all -> use active sheet and export it
     738           0 :             nFirstVisScTab = nDisplScTab;
     739           0 :             SetFlag( nFirstVisScTab, EXC_TABBUF_SKIPMASK, false ); // clear skip flags
     740             :         }
     741           0 :         SetFlag( nFirstVisScTab, EXC_TABBUF_VISIBLE ); // must be visible, even if originally hidden
     742             :     }
     743             : 
     744             :     // find currently displayed sheet
     745          72 :     if( !IsExportTab( nDisplScTab ) )   // selected sheet not exported (i.e. scenario) -> use first visible
     746           0 :         nDisplScTab = nFirstVisScTab;
     747          72 :     SetFlag( nDisplScTab, EXC_TABBUF_VISIBLE | EXC_TABBUF_SELECTED );
     748             : 
     749             :     // number of selected sheets
     750         201 :     for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
     751         129 :         if( IsSelectedTab( nScTab ) )
     752          72 :             ++mnXclSelCnt;
     753             : 
     754             :     // --- calculate resulting Excel sheet indexes ---
     755             : 
     756          72 :     CalcXclIndexes();
     757          72 :     mnFirstVisXclTab = GetXclTab( nFirstVisScTab );
     758          72 :     mnDisplXclTab = GetXclTab( nDisplScTab );
     759             : 
     760             :     // --- sorted vectors for index lookup ---
     761             : 
     762          72 :     CalcSortedIndexes();
     763          72 : }
     764             : 
     765        1075 : bool XclExpTabInfo::IsExportTab( SCTAB nScTab ) const
     766             : {
     767             :     /*  Check sheet index before to avoid assertion in GetFlag(). */
     768        1075 :     return (nScTab < mnScCnt && nScTab >= 0) && !GetFlag( nScTab, EXC_TABBUF_SKIPMASK );
     769             : }
     770             : 
     771         869 : bool XclExpTabInfo::IsExternalTab( SCTAB nScTab ) const
     772             : {
     773             :     /*  Check sheet index before to avoid assertion (called from formula
     774             :         compiler also for deleted references). */
     775         869 :     return (nScTab < mnScCnt && nScTab >= 0) && GetFlag( nScTab, EXC_TABBUF_EXTERN );
     776             : }
     777             : 
     778         129 : bool XclExpTabInfo::IsVisibleTab( SCTAB nScTab ) const
     779             : {
     780         129 :     return GetFlag( nScTab, EXC_TABBUF_VISIBLE );
     781             : }
     782             : 
     783         258 : bool XclExpTabInfo::IsSelectedTab( SCTAB nScTab ) const
     784             : {
     785         258 :     return GetFlag( nScTab, EXC_TABBUF_SELECTED );
     786             : }
     787             : 
     788         129 : bool XclExpTabInfo::IsDisplayedTab( SCTAB nScTab ) const
     789             : {
     790             :     OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::IsActiveTab - sheet out of range" );
     791         129 :     return GetXclTab( nScTab ) == mnDisplXclTab;
     792             : }
     793             : 
     794         129 : bool XclExpTabInfo::IsMirroredTab( SCTAB nScTab ) const
     795             : {
     796         129 :     return GetFlag( nScTab, EXC_TABBUF_MIRRORED );
     797             : }
     798             : 
     799         129 : OUString XclExpTabInfo::GetScTabName( SCTAB nScTab ) const
     800             : {
     801             :     OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::IsActiveTab - sheet out of range" );
     802         129 :     return (nScTab < mnScCnt && nScTab >= 0) ? maTabInfoVec[ nScTab ].maScName : OUString();
     803             : }
     804             : 
     805         704 : sal_uInt16 XclExpTabInfo::GetXclTab( SCTAB nScTab ) const
     806             : {
     807         704 :     return (nScTab < mnScCnt && nScTab >= 0) ? maTabInfoVec[ nScTab ].mnXclTab : EXC_TAB_DELETED;
     808             : }
     809             : 
     810         129 : SCTAB XclExpTabInfo::GetRealScTab( SCTAB nSortedScTab ) const
     811             : {
     812             :     OSL_ENSURE( nSortedScTab < mnScCnt && nSortedScTab >= 0, "XclExpTabInfo::GetRealScTab - sheet out of range" );
     813         129 :     return (nSortedScTab < mnScCnt && nSortedScTab >= 0) ? maFromSortedVec[ nSortedScTab ] : SCTAB_INVALID;
     814             : }
     815             : 
     816        2405 : bool XclExpTabInfo::GetFlag( SCTAB nScTab, sal_uInt8 nFlags ) const
     817             : {
     818             :     OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::GetFlag - sheet out of range" );
     819        2405 :     return (nScTab < mnScCnt && nScTab >= 0) && ::get_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags );
     820             : }
     821             : 
     822         376 : void XclExpTabInfo::SetFlag( SCTAB nScTab, sal_uInt8 nFlags, bool bSet )
     823             : {
     824             :     OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::SetFlag - sheet out of range" );
     825         376 :     if( nScTab < mnScCnt && nScTab >= 0 )
     826         376 :         ::set_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags, bSet );
     827         376 : }
     828             : 
     829          72 : void XclExpTabInfo::CalcXclIndexes()
     830             : {
     831          72 :     sal_uInt16 nXclTab = 0;
     832          72 :     SCTAB nScTab = 0;
     833             : 
     834             :     // --- pass 1: process regular sheets ---
     835         201 :     for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
     836             :     {
     837         129 :         if( IsExportTab( nScTab ) )
     838             :         {
     839         129 :             maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
     840         129 :             ++nXclTab;
     841             :         }
     842             :         else
     843           0 :             maTabInfoVec[ nScTab ].mnXclTab = EXC_TAB_DELETED;
     844             :     }
     845          72 :     mnXclCnt = nXclTab;
     846             : 
     847             :     // --- pass 2: process external sheets (nXclTab continues) ---
     848         201 :     for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
     849             :     {
     850         129 :         if( IsExternalTab( nScTab ) )
     851             :         {
     852           0 :             maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
     853           0 :             ++nXclTab;
     854           0 :             ++mnXclExtCnt;
     855             :         }
     856             :     }
     857             : 
     858             :     // result: first occur all exported sheets, followed by all external sheets
     859          72 : }
     860             : 
     861             : typedef ::std::pair< OUString, SCTAB > XclExpTabName;
     862             : typedef ::std::vector< XclExpTabName >  XclExpTabNameVec;
     863             : 
     864             : struct XclExpTabNameSort {
     865         112 :     bool operator ()( const XclExpTabName& rArg1, const XclExpTabName& rArg2 )
     866             :     {
     867             :         // compare the sheet names only
     868         112 :         return ScGlobal::GetCollator()->compareString( rArg1.first, rArg2.first ) < 0;
     869             :     }
     870             : };
     871             : 
     872          72 : void XclExpTabInfo::CalcSortedIndexes()
     873             : {
     874          72 :     ScDocument& rDoc = GetDoc();
     875          72 :     XclExpTabNameVec aVec( mnScCnt );
     876             :     SCTAB nScTab;
     877             : 
     878             :     // fill with sheet names
     879         201 :     for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
     880             :     {
     881         129 :         rDoc.GetName( nScTab, aVec[ nScTab ].first );
     882         129 :         aVec[ nScTab ].second = nScTab;
     883             :     }
     884          72 :     ::std::sort( aVec.begin(), aVec.end(), XclExpTabNameSort() );
     885             : 
     886             :     // fill index vectors from sorted sheet name vector
     887          72 :     maFromSortedVec.resize( mnScCnt );
     888          72 :     maToSortedVec.resize( mnScCnt );
     889         201 :     for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
     890             :     {
     891         129 :         maFromSortedVec[ nScTab ] = aVec[ nScTab ].second;
     892         129 :         maToSortedVec[ aVec[ nScTab ].second ] = nScTab;
     893          72 :     }
     894          72 : }
     895             : 
     896             : // External names =============================================================
     897             : 
     898           0 : XclExpExtNameBase::XclExpExtNameBase(
     899             :         const XclExpRoot& rRoot, const OUString& rName, sal_uInt16 nFlags ) :
     900             :     XclExpRecord( EXC_ID_EXTERNNAME ),
     901             :     XclExpRoot( rRoot ),
     902             :     maName( rName ),
     903             :     mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
     904           0 :     mnFlags( nFlags )
     905             : {
     906             :     OSL_ENSURE( maName.getLength() <= 255, "XclExpExtNameBase::XclExpExtNameBase - string too long" );
     907           0 :     SetRecSize( 6 + mxName->GetSize() );
     908           0 : }
     909             : 
     910           0 : XclExpExtNameBase::~XclExpExtNameBase()
     911             : {
     912           0 : }
     913             : 
     914           0 : void XclExpExtNameBase::WriteBody( XclExpStream& rStrm )
     915             : {
     916           0 :     rStrm   << mnFlags
     917           0 :             << sal_uInt32( 0 )
     918           0 :             << *mxName;
     919           0 :     WriteAddData( rStrm );
     920           0 : }
     921             : 
     922           0 : void XclExpExtNameBase::WriteAddData( XclExpStream& /*rStrm*/ )
     923             : {
     924           0 : }
     925             : 
     926           0 : XclExpExtNameAddIn::XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName ) :
     927           0 :     XclExpExtNameBase( rRoot, rName )
     928             : {
     929           0 :     AddRecSize( 4 );
     930           0 : }
     931             : 
     932           0 : void XclExpExtNameAddIn::WriteAddData( XclExpStream& rStrm )
     933             : {
     934             :     // write a #REF! error formula
     935           0 :     rStrm << sal_uInt16( 2 ) << EXC_TOKID_ERR << EXC_ERR_REF;
     936           0 : }
     937             : 
     938           0 : XclExpExtNameDde::XclExpExtNameDde( const XclExpRoot& rRoot,
     939             :         const OUString& rName, sal_uInt16 nFlags, const ScMatrix* pResults ) :
     940           0 :     XclExpExtNameBase( rRoot, rName, nFlags )
     941             : {
     942           0 :     if( pResults )
     943             :     {
     944           0 :         mxMatrix.reset( new XclExpCachedMatrix( *pResults ) );
     945           0 :         AddRecSize( mxMatrix->GetSize() );
     946             :     }
     947           0 : }
     948             : 
     949           0 : void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
     950             : {
     951           0 :     if( mxMatrix )
     952           0 :         mxMatrix->Save( rStrm );
     953           0 : }
     954             : 
     955           0 : XclExpExtName::XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook,
     956             :         const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) :
     957             :     XclExpExtNameBase( rRoot, rName ),
     958             :     mrSupbook(rSupbook),
     959           0 :     mpArray(rArray->Clone())
     960             : {
     961           0 : }
     962             : 
     963           0 : void XclExpExtName::WriteAddData( XclExpStream& rStrm )
     964             : {
     965             :     // Write only if it only has a single token that is either a cell or cell
     966             :     // range address.  Excel just writes '02 00 1C 17' for all the other types
     967             :     // of external names.
     968             : 
     969             :     using namespace ::formula;
     970             :     do
     971             :     {
     972           0 :         if (mpArray->GetLen() != 1)
     973           0 :             break;
     974             : 
     975           0 :         const formula::FormulaToken* p = mpArray->First();
     976           0 :         if (!p->IsExternalRef())
     977           0 :             break;
     978             : 
     979           0 :         switch (p->GetType())
     980             :         {
     981             :             case svExternalSingleRef:
     982             :             {
     983           0 :                 const ScSingleRefData& rRef = *p->GetSingleRef();
     984           0 :                 if (rRef.IsTabRel())
     985           0 :                     break;
     986             : 
     987           0 :                 bool bColRel = rRef.IsColRel();
     988           0 :                 bool bRowRel = rRef.IsRowRel();
     989           0 :                 sal_uInt16 nCol = static_cast<sal_uInt16>(rRef.Col());
     990           0 :                 sal_uInt16 nRow = static_cast<sal_uInt16>(rRef.Row());
     991           0 :                 if (bColRel) nCol |= 0x4000;
     992           0 :                 if (bRowRel) nCol |= 0x8000;
     993             : 
     994           0 :                 OUString aTabName = p->GetString().getString();
     995           0 :                 sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
     996             : 
     997             :                 // size is always 9
     998           0 :                 rStrm << static_cast<sal_uInt16>(9);
     999             :                 // operator token (3A for cell reference)
    1000           0 :                 rStrm << static_cast<sal_uInt8>(0x3A);
    1001             :                 // cell address (Excel's address has 2 sheet IDs.)
    1002           0 :                 rStrm << nSBTab << nSBTab << nRow << nCol;
    1003           0 :                 return;
    1004             :             }
    1005             :             case svExternalDoubleRef:
    1006             :             {
    1007           0 :                 const ScComplexRefData& rRef = *p->GetDoubleRef();
    1008           0 :                 const ScSingleRefData& r1 = rRef.Ref1;
    1009           0 :                 const ScSingleRefData& r2 = rRef.Ref2;
    1010           0 :                 if (r1.IsTabRel() || r2.IsTabRel())
    1011           0 :                     break;
    1012             : 
    1013           0 :                 sal_uInt16 nTab1 = r1.Tab();
    1014           0 :                 sal_uInt16 nTab2 = r2.Tab();
    1015           0 :                 bool bCol1Rel = r1.IsColRel();
    1016           0 :                 bool bRow1Rel = r1.IsRowRel();
    1017           0 :                 bool bCol2Rel = r2.IsColRel();
    1018           0 :                 bool bRow2Rel = r2.IsRowRel();
    1019             : 
    1020           0 :                 sal_uInt16 nCol1 = static_cast<sal_uInt16>(r1.Col());
    1021           0 :                 sal_uInt16 nCol2 = static_cast<sal_uInt16>(r2.Col());
    1022           0 :                 sal_uInt16 nRow1 = static_cast<sal_uInt16>(r1.Row());
    1023           0 :                 sal_uInt16 nRow2 = static_cast<sal_uInt16>(r2.Row());
    1024           0 :                 if (bCol1Rel) nCol1 |= 0x4000;
    1025           0 :                 if (bRow1Rel) nCol1 |= 0x8000;
    1026           0 :                 if (bCol2Rel) nCol2 |= 0x4000;
    1027           0 :                 if (bRow2Rel) nCol2 |= 0x8000;
    1028             : 
    1029           0 :                 OUString aTabName = p->GetString().getString();
    1030           0 :                 sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
    1031             : 
    1032             :                 // size is always 13 (0x0D)
    1033           0 :                 rStrm << static_cast<sal_uInt16>(13);
    1034             :                 // operator token (3B for area reference)
    1035           0 :                 rStrm << static_cast<sal_uInt8>(0x3B);
    1036             :                 // range (area) address
    1037           0 :                 sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
    1038           0 :                 rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
    1039           0 :                 return;
    1040             :             }
    1041             :             default:
    1042             :                 ;   // nothing
    1043             :         }
    1044             :     }
    1045             :     while (false);
    1046             : 
    1047             :     // special value for #REF! (02 00 1C 17)
    1048           0 :     rStrm << static_cast<sal_uInt16>(2) << EXC_TOKID_ERR << EXC_ERR_REF;
    1049             : }
    1050             : 
    1051           0 : void XclExpExtName::SaveXml(XclExpXmlStream& rStrm)
    1052             : {
    1053           0 :     sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
    1054             : 
    1055             :     pExternalLink->startElement(XML_definedName,
    1056             :             XML_name, XclXmlUtils::ToOString(maName).getStr(),
    1057             :             XML_refersTo, NULL,
    1058             :             XML_sheetId, NULL,
    1059           0 :             FSEND);
    1060             : 
    1061           0 :     pExternalLink->endElement(XML_definedName);
    1062           0 : }
    1063             : 
    1064             : // List of external names =====================================================
    1065             : 
    1066           0 : XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
    1067           0 :     XclExpRoot( rRoot )
    1068             : {
    1069           0 : }
    1070             : 
    1071           0 : sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const OUString& rName )
    1072             : {
    1073           0 :     sal_uInt16 nIndex = GetIndex( rName );
    1074           0 :     return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
    1075             : }
    1076             : 
    1077           0 : sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const OUString& rName )
    1078             : {
    1079           0 :     sal_uInt16 nIndex = GetIndex( rName );
    1080           0 :     return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
    1081             : }
    1082             : 
    1083           0 : sal_uInt16 XclExpExtNameBuffer::InsertDde(
    1084             :         const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
    1085             : {
    1086           0 :     sal_uInt16 nIndex = GetIndex( rItem );
    1087           0 :     if( nIndex == 0 )
    1088             :     {
    1089             :         size_t nPos;
    1090           0 :         if( GetDoc().FindDdeLink( rApplic, rTopic, rItem, SC_DDE_IGNOREMODE, nPos ) )
    1091             :         {
    1092             :             // create the leading 'StdDocumentName' EXTERNNAME record
    1093           0 :             if( maNameList.IsEmpty() )
    1094             :                 AppendNew( new XclExpExtNameDde(
    1095           0 :                     GetRoot(), OUString("StdDocumentName"), EXC_EXTN_EXPDDE_STDDOC ) );
    1096             : 
    1097             :             // try to find DDE result array, but create EXTERNNAME record without them too
    1098           0 :             const ScMatrix* pScMatrix = GetDoc().GetDdeLinkResultMatrix( nPos );
    1099           0 :             nIndex = AppendNew( new XclExpExtNameDde( GetRoot(), rItem, EXC_EXTN_EXPDDE, pScMatrix ) );
    1100             :         }
    1101             :     }
    1102           0 :     return nIndex;
    1103             : }
    1104             : 
    1105           0 : sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
    1106             :         const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
    1107             : {
    1108           0 :     sal_uInt16 nIndex = GetIndex( rName );
    1109           0 :     return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, rArray ) );
    1110             : }
    1111             : 
    1112           0 : void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
    1113             : {
    1114           0 :     maNameList.Save( rStrm );
    1115           0 : }
    1116             : 
    1117           0 : void XclExpExtNameBuffer::SaveXml(XclExpXmlStream& rStrm)
    1118             : {
    1119           0 :     maNameList.SaveXml(rStrm);
    1120           0 : }
    1121             : 
    1122           0 : sal_uInt16 XclExpExtNameBuffer::GetIndex( const OUString& rName ) const
    1123             : {
    1124           0 :     for( size_t nPos = 0, nSize = maNameList.GetSize(); nPos < nSize; ++nPos )
    1125           0 :         if( maNameList.GetRecord( nPos )->GetName() == rName )
    1126           0 :             return static_cast< sal_uInt16 >( nPos + 1 );
    1127           0 :     return 0;
    1128             : }
    1129             : 
    1130           0 : sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
    1131             : {
    1132           0 :     XclExpExtNameRef xExtName( pExtName );
    1133           0 :     size_t nSize = maNameList.GetSize();
    1134           0 :     if( nSize < 0x7FFF )
    1135             :     {
    1136           0 :         maNameList.AppendRecord( xExtName );
    1137           0 :         return static_cast< sal_uInt16 >( nSize + 1 );
    1138             :     }
    1139           0 :     return 0;
    1140             : }
    1141             : 
    1142             : // Cached external cells ======================================================
    1143             : 
    1144           1 : XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
    1145             :     XclExpRecord( EXC_ID_CRN, 4 ),
    1146             :     mnScCol( nScCol ),
    1147           1 :     mnScRow( nScRow )
    1148             : {
    1149           1 :     maValues.push_back( rValue );
    1150           1 : }
    1151             : 
    1152           0 : bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
    1153             : {
    1154           0 :     if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
    1155           0 :         return false;
    1156           0 :     maValues.push_back( rValue );
    1157           0 :     return true;
    1158             : }
    1159             : 
    1160           1 : void XclExpCrn::WriteBody( XclExpStream& rStrm )
    1161             : {
    1162           1 :     rStrm   << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
    1163           2 :             << static_cast< sal_uInt8 >( mnScCol )
    1164           2 :             << static_cast< sal_uInt16 >( mnScRow );
    1165           2 :     for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt )
    1166             :     {
    1167           1 :         if( aIt->has< bool >() )
    1168           0 :             WriteBool( rStrm, aIt->get< bool >() );
    1169           1 :         else if( aIt->has< double >() )
    1170           0 :             WriteDouble( rStrm, aIt->get< double >() );
    1171           1 :         else if( aIt->has< OUString >() )
    1172           1 :             WriteString( rStrm, aIt->get< OUString >() );
    1173             :         else
    1174           0 :             WriteEmpty( rStrm );
    1175             :     }
    1176           1 : }
    1177             : 
    1178           0 : void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
    1179             : {
    1180           0 :     rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
    1181           0 :     rStrm.WriteZeroBytes( 7 );
    1182           0 : }
    1183             : 
    1184           0 : void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
    1185             : {
    1186           0 :     if( ::rtl::math::isNan( fValue ) )
    1187             :     {
    1188           0 :         sal_uInt16 nScError = static_cast< sal_uInt16 >( reinterpret_cast< const sal_math_Double* >( &fValue )->nan_parts.fraction_lo );
    1189           0 :         WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
    1190             :     }
    1191             :     else
    1192             :     {
    1193           0 :         rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
    1194             :     }
    1195           0 : }
    1196             : 
    1197           1 : void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
    1198             : {
    1199           1 :     rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
    1200           1 : }
    1201             : 
    1202           0 : void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
    1203             : {
    1204           0 :     rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
    1205           0 :     rStrm.WriteZeroBytes( 7 );
    1206           0 : }
    1207             : 
    1208           0 : void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
    1209             : {
    1210           0 :     rStrm << EXC_CACHEDVAL_EMPTY;
    1211           0 :     rStrm.WriteZeroBytes( 8 );
    1212           0 : }
    1213             : 
    1214           0 : void XclExpCrn::SaveXml( XclExpXmlStream& rStrm )
    1215             : {
    1216           0 :     sax_fastparser::FSHelperPtr pFS = rStrm.GetCurrentStream();
    1217             : 
    1218             :     pFS->startElement( XML_row,
    1219             :             XML_r,  OString::number( mnScRow + 1 ).getStr(),
    1220           0 :             FSEND);
    1221             : 
    1222           0 :     ScAddress aAdr( mnScCol, mnScRow, 0);   // Tab number doesn't matter
    1223           0 :     for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt, aAdr.IncCol() )
    1224             :     {
    1225           0 :         if( aIt->has< double >() )
    1226             :         {
    1227           0 :             double fVal = aIt->get< double >();
    1228           0 :             if (rtl::math::isFinite( fVal))
    1229             :             {
    1230             :                 // t='n' is omitted
    1231             :                 pFS->startElement( XML_cell,
    1232             :                         XML_r,      XclXmlUtils::ToOString( aAdr),
    1233           0 :                         FSEND);
    1234           0 :                 pFS->startElement( XML_v, FSEND );
    1235           0 :                 pFS->write( fVal );
    1236             :             }
    1237             :             else
    1238             :             {
    1239             :                 pFS->startElement( XML_cell,
    1240             :                         XML_r,      XclXmlUtils::ToOString( aAdr),
    1241             :                         XML_t,      "e",
    1242           0 :                         FSEND);
    1243           0 :                 pFS->startElement( XML_v, FSEND );
    1244           0 :                 pFS->write( "#VALUE!" );    // OOXTODO: support other error values
    1245             :             }
    1246             :         }
    1247           0 :         else if( aIt->has< OUString >() )
    1248             :         {
    1249             :             pFS->startElement( XML_cell,
    1250             :                     XML_r,      XclXmlUtils::ToOString( aAdr),
    1251             :                     XML_t,      "str",
    1252           0 :                     FSEND);
    1253           0 :             pFS->startElement( XML_v, FSEND );
    1254           0 :             pFS->write( aIt->get< OUString >() );
    1255             :         }
    1256           0 :         else if( aIt->has< bool >() )
    1257             :         {
    1258             :             pFS->startElement( XML_cell,
    1259             :                     XML_r,      XclXmlUtils::ToOString( aAdr),
    1260             :                     XML_t,      "b",
    1261           0 :                     FSEND);
    1262           0 :             pFS->startElement( XML_v, FSEND );
    1263           0 :             pFS->write( aIt->get< bool >() ? "1" : "0" );
    1264             :         }
    1265             :         // OOXTODO: error type cell t='e'
    1266             :         else
    1267             :         {
    1268             :             // Empty/blank cell not stored, only aAdr is incremented.
    1269             :         }
    1270           0 :         pFS->endElement( XML_v );
    1271           0 :         pFS->endElement( XML_cell);
    1272             :     }
    1273             : 
    1274           0 :     pFS->endElement( XML_row);
    1275           0 : }
    1276             : 
    1277             : // Cached cells of a sheet ====================================================
    1278             : 
    1279           1 : XclExpXct::XclExpXct( const XclExpRoot& rRoot, const OUString& rTabName,
    1280             :         sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef xCacheTable ) :
    1281             :     XclExpRoot( rRoot ),
    1282             :     mxCacheTable( xCacheTable ),
    1283             :     maBoundRange( ScAddress::INITIALIZE_INVALID ),
    1284             :     maTabName( rTabName ),
    1285           1 :     mnSBTab( nSBTab )
    1286             : {
    1287           1 : }
    1288             : 
    1289           0 : void XclExpXct::StoreCellRange( const ScRange& rRange )
    1290             : {
    1291             :     // #i70418# restrict size of external range to prevent memory overflow
    1292           0 :     if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
    1293           0 :         return;
    1294             : 
    1295           0 :     maUsedCells.SetMultiMarkArea( rRange );
    1296           0 :     maBoundRange.ExtendTo( rRange );
    1297             : }
    1298             : 
    1299           1 : void XclExpXct::StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken )
    1300             : {
    1301           1 :     maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
    1302           1 :     maBoundRange.ExtendTo( ScRange( rCell ) );
    1303             :     (void)rToken;
    1304           1 : }
    1305             : 
    1306           0 : void XclExpXct::StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken )
    1307             : {
    1308           0 :     maUsedCells.SetMultiMarkArea( rRange );
    1309           0 :     maBoundRange.ExtendTo( rRange );
    1310             :     (void)rToken;
    1311           0 : }
    1312             : 
    1313             : namespace {
    1314             : 
    1315           2 : class XclExpCrnList : public XclExpRecordList< XclExpCrn >
    1316             : {
    1317             : public:
    1318             :     /** Inserts the passed value into an existing or new CRN record.
    1319             :         @return  True = value inserted successfully, false = CRN list is full. */
    1320             :     bool                InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
    1321             : };
    1322             : 
    1323           1 : bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
    1324             : {
    1325           1 :     RecordRefType xLastRec = GetLastRecord();
    1326           1 :     if( xLastRec && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
    1327           0 :         return true;
    1328           1 :     if( GetSize() == SAL_MAX_UINT16 )
    1329           0 :         return false;
    1330           1 :     AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
    1331           1 :     return true;
    1332             : }
    1333             : 
    1334             : } // namespace
    1335             : 
    1336           1 : bool XclExpXct::BuildCrnList( XclExpCrnList& rCrnRecs )
    1337             : {
    1338           1 :     if( !mxCacheTable )
    1339           0 :         return false;
    1340             : 
    1341             :     /*  Get the range of used rows in the cache table. This may help to
    1342             :         optimize building the CRN record list if the cache table does not
    1343             :         contain all referred cells, e.g. if big empty ranges are used in the
    1344             :         formulas. */
    1345           1 :     ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
    1346           1 :     if( aRowRange.first >= aRowRange.second )
    1347           0 :         return false;
    1348             : 
    1349             :     /*  Crop the bounding range of used cells in this table to Excel limits.
    1350             :         Return if there is no external cell inside these limits. */
    1351           1 :     if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
    1352           0 :         return false;
    1353             : 
    1354             :     /*  Find the resulting row range that needs to be processed. */
    1355           1 :     SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
    1356           1 :     SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
    1357           1 :     if( nScRow1 > nScRow2 )
    1358           0 :         return false;
    1359             : 
    1360             :     /*  Build and collect all CRN records before writing the XCT record. This
    1361             :         is needed to determine the total number of CRN records which must be
    1362             :         known when writing the XCT record (possibly encrypted, so seeking the
    1363             :         output strem back after writing the CRN records is not an option). */
    1364           1 :     SvNumberFormatter& rFormatter = GetFormatter();
    1365           1 :     bool bValid = true;
    1366           2 :     for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
    1367             :     {
    1368           1 :         ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
    1369           1 :         const SCCOL nScEnd = ::std::min( aColRange.second, MAXCOLCOUNT );
    1370           2 :         for( SCCOL nScCol = aColRange.first; bValid && (nScCol < nScEnd); ++nScCol )
    1371             :         {
    1372           1 :             if( maUsedCells.IsCellMarked( nScCol, nScRow, true ) )
    1373             :             {
    1374           1 :                 sal_uInt32 nScNumFmt = 0;
    1375           1 :                 ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
    1376             :                 using namespace ::formula;
    1377           1 :                 if( xToken.get() ) switch( xToken->GetType() )
    1378             :                 {
    1379             :                     case svDouble:
    1380           0 :                         bValid = (rFormatter.GetType( nScNumFmt ) == css::util::NumberFormat::LOGICAL) ?
    1381           0 :                             rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
    1382           0 :                             rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
    1383           0 :                     break;
    1384             :                     case svString:
    1385             :                         // do not save empty strings (empty cells) to cache
    1386           1 :                         if( !xToken->GetString().isEmpty() )
    1387           1 :                             bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
    1388           1 :                     break;
    1389             :                     default:
    1390           0 :                     break;
    1391           1 :                 }
    1392             :             }
    1393             :         }
    1394             :     }
    1395           1 :     return true;
    1396             : }
    1397             : 
    1398           1 : void XclExpXct::Save( XclExpStream& rStrm )
    1399             : {
    1400           1 :     XclExpCrnList aCrnRecs;
    1401           1 :     if (!BuildCrnList( aCrnRecs))
    1402           1 :         return;
    1403             : 
    1404             :     // write the XCT record and the list of CRN records
    1405           1 :     rStrm.StartRecord( EXC_ID_XCT, 4 );
    1406           1 :     rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
    1407           1 :     rStrm.EndRecord();
    1408           1 :     aCrnRecs.Save( rStrm );
    1409             : }
    1410             : 
    1411           0 : void XclExpXct::SaveXml( XclExpXmlStream& rStrm )
    1412             : {
    1413           0 :     XclExpCrnList aCrnRecs;
    1414             : 
    1415           0 :     sax_fastparser::FSHelperPtr pFS = rStrm.GetCurrentStream();
    1416             : 
    1417           0 :     bool bValid = BuildCrnList( aCrnRecs);
    1418             :     pFS->startElement( XML_sheetData,
    1419             :             XML_sheetId, OString::number( mnSBTab).getStr(),
    1420           0 :             FSEND);
    1421           0 :     if (bValid)
    1422             :     {
    1423             :         // row elements
    1424           0 :         aCrnRecs.SaveXml( rStrm );
    1425             :     }
    1426           0 :     pFS->endElement( XML_sheetData);
    1427           0 : }
    1428             : 
    1429             : // External documents (EXTERNSHEET/SUPBOOK), base class =======================
    1430             : 
    1431          73 : XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
    1432             :     XclExpRecord( nRecId, nRecSize ),
    1433          73 :     XclExpRoot( rRoot )
    1434             : {
    1435          73 : }
    1436             : 
    1437           0 : XclExpExtNameBuffer& XclExpExternSheetBase::GetExtNameBuffer()
    1438             : {
    1439           0 :     if( !mxExtNameBfr )
    1440           0 :         mxExtNameBfr.reset( new XclExpExtNameBuffer( GetRoot() ) );
    1441           0 :     return *mxExtNameBfr;
    1442             : }
    1443             : 
    1444           8 : void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
    1445             : {
    1446           8 :     if( mxExtNameBfr )
    1447           0 :         mxExtNameBfr->Save( rStrm );
    1448           8 : }
    1449             : 
    1450           0 : void XclExpExternSheetBase::WriteExtNameBufferXml( XclExpXmlStream& rStrm )
    1451             : {
    1452           0 :     if( mxExtNameBfr )
    1453           0 :         mxExtNameBfr->SaveXml( rStrm );
    1454           0 : }
    1455             : 
    1456             : // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
    1457             : 
    1458           0 : XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
    1459           0 :     XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
    1460             : {
    1461           0 :     Init( OUString(cCode) );
    1462           0 : }
    1463             : 
    1464           0 : XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName ) :
    1465           0 :     XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
    1466             : {
    1467             :     // reference to own sheet: \03<sheetname>
    1468           0 :     Init(OUStringLiteral1<EXC_EXTSH_TABNAME>() + rTabName);
    1469           0 : }
    1470             : 
    1471           0 : void XclExpExternSheet::Save( XclExpStream& rStrm )
    1472             : {
    1473             :     // EXTERNSHEET record
    1474           0 :     XclExpRecord::Save( rStrm );
    1475             :     // EXTERNNAME records
    1476           0 :     WriteExtNameBuffer( rStrm );
    1477           0 : }
    1478             : 
    1479           0 : void XclExpExternSheet::Init( const OUString& rEncUrl )
    1480             : {
    1481             :     OSL_ENSURE_BIFF( GetBiff() <= EXC_BIFF5 );
    1482           0 :     maTabName.AssignByte( rEncUrl, GetTextEncoding(), EXC_STR_8BITLENGTH );
    1483           0 :     SetRecSize( maTabName.GetSize() );
    1484           0 : }
    1485             : 
    1486           0 : sal_uInt16 XclExpExternSheet::InsertAddIn( const OUString& rName )
    1487             : {
    1488           0 :     return GetExtNameBuffer().InsertAddIn( rName );
    1489             : }
    1490             : 
    1491           0 : void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
    1492             : {
    1493           0 :     sal_uInt8 nNameSize = static_cast< sal_uInt8 >( maTabName.Len() );
    1494             :     // special case: reference to own sheet (starting with '\03') needs wrong string length
    1495           0 :     if( maTabName.GetChar( 0 ) == EXC_EXTSH_TABNAME )
    1496           0 :         --nNameSize;
    1497           0 :     rStrm << nNameSize;
    1498           0 :     maTabName.WriteBuffer( rStrm );
    1499           0 : }
    1500             : 
    1501             : // External document (SUPBOOK, BIFF8) =========================================
    1502             : 
    1503          72 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
    1504             :     XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
    1505             :     meType( EXC_SBTYPE_SELF ),
    1506             :     mnXclTabCount( nXclTabCount ),
    1507          72 :     mnFileId( 0 )
    1508             : {
    1509          72 : }
    1510             : 
    1511           0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
    1512             :     XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
    1513             :     meType( EXC_SBTYPE_ADDIN ),
    1514             :     mnXclTabCount( 1 ),
    1515           0 :     mnFileId( 0 )
    1516             : {
    1517           0 : }
    1518             : 
    1519           0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType ) :
    1520             :     XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
    1521             :     maUrl( rUrl ),
    1522             :     maUrlEncoded( rUrl ),
    1523             :     meType( EXC_SBTYPE_EUROTOOL ),
    1524             :     mnXclTabCount( 0 ),
    1525           0 :     mnFileId( 0 )
    1526             : {
    1527           0 :     SetRecSize( 2 + maUrlEncoded.GetSize() );
    1528           0 : }
    1529             : 
    1530           1 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) :
    1531             :     XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
    1532             :     maUrl( rUrl ),
    1533             :     maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
    1534             :     meType( EXC_SBTYPE_EXTERN ),
    1535             :     mnXclTabCount( 0 ),
    1536           1 :     mnFileId( 0 )
    1537             : {
    1538           1 :     SetRecSize( 2 + maUrlEncoded.GetSize() );
    1539             : 
    1540             :     // We need to create all tables up front to ensure the correct table order.
    1541           1 :     ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
    1542           1 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
    1543           1 :     mnFileId = nFileId + 1;
    1544           1 :     ScfStringVec aTabNames;
    1545           1 :     pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
    1546           2 :     for( ScfStringVec::const_iterator aBeg = aTabNames.begin(), aIt = aBeg, aEnd = aTabNames.end(); aIt != aEnd; ++aIt )
    1547           2 :         InsertTabName( *aIt, pRefMgr->getCacheTable( nFileId, aIt - aBeg ) );
    1548           1 : }
    1549             : 
    1550           0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic ) :
    1551             :     XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
    1552             :     maUrl( rApplic ),
    1553             :     maDdeTopic( rTopic ),
    1554             :     maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
    1555             :     meType( EXC_SBTYPE_SPECIAL ),
    1556             :     mnXclTabCount( 0 ),
    1557           0 :     mnFileId( 0 )
    1558             : {
    1559           0 :     SetRecSize( 2 + maUrlEncoded.GetSize() );
    1560           0 : }
    1561             : 
    1562           3 : bool XclExpSupbook::IsUrlLink( const OUString& rUrl ) const
    1563             : {
    1564           3 :     return (meType == EXC_SBTYPE_EXTERN || meType == EXC_SBTYPE_EUROTOOL) && (maUrl == rUrl);
    1565             : }
    1566             : 
    1567           0 : bool XclExpSupbook::IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const
    1568             : {
    1569           0 :     return (meType == EXC_SBTYPE_SPECIAL) && (maUrl == rApplic) && (maDdeTopic == rTopic);
    1570             : }
    1571             : 
    1572           0 : void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
    1573             :         sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const
    1574             : {
    1575           0 :     rRefLogEntry.mpUrl = maUrlEncoded.IsEmpty() ? 0 : &maUrlEncoded;
    1576           0 :     rRefLogEntry.mpFirstTab = GetTabName( nFirstSBTab );
    1577           0 :     rRefLogEntry.mpLastTab = GetTabName( nLastSBTab );
    1578           0 : }
    1579             : 
    1580           0 : void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
    1581             : {
    1582           0 :     if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
    1583           0 :         pXct->StoreCellRange( rRange );
    1584           0 : }
    1585             : 
    1586           1 : void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const formula::FormulaToken& rToken )
    1587             : {
    1588           1 :     if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
    1589           1 :         pXct->StoreCell( rCell, rToken );
    1590           1 : }
    1591             : 
    1592           0 : void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const formula::FormulaToken& rToken )
    1593             : {
    1594             :     // multi-table range is not allowed!
    1595           0 :     if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
    1596           0 :         if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
    1597           0 :             pXct->StoreCellRange( rRange, rToken );
    1598           0 : }
    1599             : 
    1600           2 : sal_uInt16 XclExpSupbook::GetTabIndex( const OUString& rTabName ) const
    1601             : {
    1602           2 :     XclExpString aXclName(rTabName);
    1603           2 :     size_t nSize = maXctList.GetSize();
    1604           2 :     for (size_t i = 0; i < nSize; ++i)
    1605             :     {
    1606           2 :         XclExpXctRef aRec = maXctList.GetRecord(i);
    1607           2 :         if (aXclName == aRec->GetTabName())
    1608           2 :             return ulimit_cast<sal_uInt16>(i);
    1609           0 :     }
    1610           0 :     return EXC_NOTAB;
    1611             : }
    1612             : 
    1613           1 : sal_uInt16 XclExpSupbook::GetTabCount() const
    1614             : {
    1615           1 :     return ulimit_cast<sal_uInt16>(maXctList.GetSize());
    1616             : }
    1617             : 
    1618           1 : sal_uInt16 XclExpSupbook::InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef xCacheTable )
    1619             : {
    1620             :     OSL_ENSURE( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
    1621           1 :     sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
    1622           1 :     XclExpXctRef xXct( new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable ) );
    1623           1 :     AddRecSize( xXct->GetTabName().GetSize() );
    1624           1 :     maXctList.AppendRecord( xXct );
    1625           1 :     return nSBTab;
    1626             : }
    1627             : 
    1628           0 : sal_uInt16 XclExpSupbook::InsertAddIn( const OUString& rName )
    1629             : {
    1630           0 :     return GetExtNameBuffer().InsertAddIn( rName );
    1631             : }
    1632             : 
    1633           0 : sal_uInt16 XclExpSupbook::InsertEuroTool( const OUString& rName )
    1634             : {
    1635           0 :     return GetExtNameBuffer().InsertEuroTool( rName );
    1636             : }
    1637             : 
    1638           0 : sal_uInt16 XclExpSupbook::InsertDde( const OUString& rItem )
    1639             : {
    1640           0 :     return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
    1641             : }
    1642             : 
    1643           0 : sal_uInt16 XclExpSupbook::InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
    1644             : {
    1645           0 :     return GetExtNameBuffer().InsertExtName(*this, rName, rArray);
    1646             : }
    1647             : 
    1648          55 : XclSupbookType XclExpSupbook::GetType() const
    1649             : {
    1650          55 :     return meType;
    1651             : }
    1652             : 
    1653           0 : sal_uInt16 XclExpSupbook::GetFileId() const
    1654             : {
    1655           0 :     return mnFileId;
    1656             : }
    1657             : 
    1658           0 : const OUString& XclExpSupbook::GetUrl() const
    1659             : {
    1660           0 :     return maUrl;
    1661             : }
    1662             : 
    1663           8 : void XclExpSupbook::Save( XclExpStream& rStrm )
    1664             : {
    1665             :     // SUPBOOK record
    1666           8 :     XclExpRecord::Save( rStrm );
    1667             :     // XCT record, CRN records
    1668           8 :     maXctList.Save( rStrm );
    1669             :     // EXTERNNAME records
    1670           8 :     WriteExtNameBuffer( rStrm );
    1671           8 : }
    1672             : 
    1673           0 : void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm )
    1674             : {
    1675           0 :     sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
    1676             : 
    1677             :     // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels
    1678           0 :     sal_uInt16 nLevel = 0;
    1679           0 :     bool bRel = true;
    1680             :     OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(),
    1681             :             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
    1682           0 :             XclExpHyperlink::BuildFileName( nLevel, bRel, maUrl, GetRoot(), true),
    1683           0 :             true );
    1684             : 
    1685             :     pExternalLink->startElement( XML_externalLink,
    1686             :             XML_xmlns,              "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
    1687           0 :             FSEND);
    1688             : 
    1689             :     pExternalLink->startElement( XML_externalBook,
    1690             :             FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
    1691             :             FSNS(XML_r, XML_id),    XclXmlUtils::ToOString( sId ).getStr(),
    1692           0 :             FSEND);
    1693             : 
    1694           0 :     if (!maXctList.IsEmpty())
    1695             :     {
    1696           0 :         pExternalLink->startElement( XML_sheetNames, FSEND);
    1697           0 :         for (size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos)
    1698             :         {
    1699             :             pExternalLink->singleElement( XML_sheetName,
    1700           0 :                     XML_val,    XclXmlUtils::ToOString( maXctList.GetRecord( nPos )->GetTabName()).getStr(),
    1701           0 :                     FSEND);
    1702             :         }
    1703           0 :         pExternalLink->endElement( XML_sheetNames);
    1704             : 
    1705             :     }
    1706             : 
    1707           0 :     if (mxExtNameBfr)
    1708             :     {
    1709           0 :         pExternalLink->startElement(XML_definedNames, FSEND);
    1710             :         // externalName elements
    1711           0 :         WriteExtNameBufferXml( rStrm );
    1712           0 :         pExternalLink->endElement(XML_definedNames);
    1713             :     }
    1714             : 
    1715           0 :     if (!maXctList.IsEmpty())
    1716             :     {
    1717           0 :         pExternalLink->startElement( XML_sheetDataSet, FSEND);
    1718             : 
    1719             :         // sheetData elements
    1720           0 :         maXctList.SaveXml( rStrm );
    1721             : 
    1722           0 :         pExternalLink->endElement( XML_sheetDataSet);
    1723             : 
    1724             :     }
    1725           0 :     pExternalLink->endElement( XML_externalBook);
    1726           0 :     pExternalLink->endElement( XML_externalLink);
    1727           0 : }
    1728             : 
    1729           0 : const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
    1730             : {
    1731           0 :     XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
    1732           0 :     return xXct ? &xXct->GetTabName() : 0;
    1733             : }
    1734             : 
    1735           8 : void XclExpSupbook::WriteBody( XclExpStream& rStrm )
    1736             : {
    1737           8 :     switch( meType )
    1738             :     {
    1739             :         case EXC_SBTYPE_SELF:
    1740           7 :             rStrm << mnXclTabCount << EXC_SUPB_SELF;
    1741           7 :         break;
    1742             :         case EXC_SBTYPE_EXTERN:
    1743             :         case EXC_SBTYPE_SPECIAL:
    1744             :         case EXC_SBTYPE_EUROTOOL:
    1745             :         {
    1746           1 :             sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
    1747           1 :             rStrm << nCount << maUrlEncoded;
    1748             : 
    1749           2 :             for( size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos )
    1750           1 :                 rStrm << maXctList.GetRecord( nPos )->GetTabName();
    1751             :         }
    1752           1 :         break;
    1753             :         case EXC_SBTYPE_ADDIN:
    1754           0 :             rStrm << mnXclTabCount << EXC_SUPB_ADDIN;
    1755           0 :         break;
    1756             :         default:
    1757             :             OSL_FAIL( "XclExpSupbook::WriteBody - unknown SUPBOOK type" );
    1758             :     }
    1759           8 : }
    1760             : 
    1761             : // All SUPBOOKS in a document =================================================
    1762             : 
    1763          72 : XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
    1764             :     XclExpRoot( rRoot ),
    1765             :     mnOwnDocSB( SAL_MAX_UINT16 ),
    1766          72 :     mnAddInSB( SAL_MAX_UINT16 )
    1767             : {
    1768          72 :     XclExpTabInfo& rTabInfo = GetTabInfo();
    1769          72 :     sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
    1770          72 :     sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
    1771          72 :     size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
    1772             : 
    1773             :     OSL_ENSURE( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
    1774          72 :     if( nCount )
    1775             :     {
    1776          72 :         maSBIndexVec.resize( nCount );
    1777             : 
    1778             :         // self-ref SUPBOOK first of list
    1779          72 :         XclExpSupbookRef xSupbook( new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) ) );
    1780          72 :         mnOwnDocSB = Append( xSupbook );
    1781         201 :         for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
    1782         201 :             maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
    1783             :     }
    1784          72 : }
    1785             : 
    1786         138 : XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
    1787             :         XclExpRefLogEntry* pRefLogEntry ) const
    1788             : {
    1789         138 :     XclExpXti aXti;
    1790         138 :     size_t nSize = maSBIndexVec.size();
    1791         138 :     if( (nFirstXclTab < nSize) && (nLastXclTab < nSize) )
    1792             :     {
    1793             :         // index of the SUPBOOK record
    1794         138 :         aXti.mnSupbook = maSBIndexVec[ nFirstXclTab ].mnSupbook;
    1795             : 
    1796             :         // all sheets in the same supbook?
    1797         138 :         bool bSameSB = true;
    1798         138 :         for( sal_uInt16 nXclTab = nFirstXclTab + 1; bSameSB && (nXclTab <= nLastXclTab); ++nXclTab )
    1799             :         {
    1800           0 :             bSameSB = maSBIndexVec[ nXclTab ].mnSupbook == aXti.mnSupbook;
    1801           0 :             if( !bSameSB )
    1802           0 :                 nLastXclTab = nXclTab - 1;
    1803             :         }
    1804         138 :         aXti.mnFirstSBTab = maSBIndexVec[ nFirstXclTab ].mnSBTab;
    1805         138 :         aXti.mnLastSBTab = maSBIndexVec[ nLastXclTab ].mnSBTab;
    1806             : 
    1807             :         // fill external reference log entry (for change tracking)
    1808         138 :         if( pRefLogEntry )
    1809             :         {
    1810           0 :             pRefLogEntry->mnFirstXclTab = nFirstXclTab;
    1811           0 :             pRefLogEntry->mnLastXclTab = nLastXclTab;
    1812           0 :             XclExpSupbookRef xSupbook = maSupbookList.GetRecord( aXti.mnSupbook );
    1813           0 :             if( xSupbook )
    1814           0 :                 xSupbook->FillRefLogEntry( *pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab );
    1815         138 :         }
    1816             :     }
    1817             :     else
    1818             :     {
    1819             :         // special range, i.e. for deleted sheets or add-ins
    1820           0 :         aXti.mnSupbook = mnOwnDocSB;
    1821           0 :         aXti.mnFirstSBTab = nFirstXclTab;
    1822           0 :         aXti.mnLastSBTab = nLastXclTab;
    1823             :     }
    1824             : 
    1825         138 :     return aXti;
    1826             : }
    1827             : 
    1828           0 : void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
    1829             : {
    1830           0 :     sal_uInt16 nXclTab = GetTabInfo().GetXclTab( rRange.aStart.Tab() );
    1831           0 :     if( nXclTab < maSBIndexVec.size() )
    1832             :     {
    1833           0 :         const XclExpSBIndex& rSBIndex = maSBIndexVec[ nXclTab ];
    1834           0 :         XclExpSupbookRef xSupbook = maSupbookList.GetRecord( rSBIndex.mnSupbook );
    1835             :         OSL_ENSURE( xSupbook , "XclExpSupbookBuffer::StoreCellRange - missing SUPBOOK record" );
    1836           0 :         if( xSupbook )
    1837           0 :             xSupbook->StoreCellRange( rRange, rSBIndex.mnSBTab );
    1838             :     }
    1839           0 : }
    1840             : 
    1841             : namespace {
    1842             : 
    1843             : class FindSBIndexEntry
    1844             : {
    1845             : public:
    1846           2 :     explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
    1847           2 :         mnSupbookId(nSupbookId), mnTabId(nTabId) {}
    1848             : 
    1849           3 :     bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
    1850             :     {
    1851           3 :         return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
    1852             :     }
    1853             : 
    1854             : private:
    1855             :     sal_uInt16 mnSupbookId;
    1856             :     sal_uInt16 mnTabId;
    1857             : };
    1858             : 
    1859             : }
    1860             : 
    1861           1 : void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell )
    1862             : {
    1863           1 :     ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
    1864           1 :     const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
    1865           1 :     if (!pUrl)
    1866           0 :         return;
    1867             : 
    1868           1 :     XclExpSupbookRef xSupbook;
    1869             :     sal_uInt16 nSupbookId;
    1870           1 :     if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
    1871             :     {
    1872           1 :         xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
    1873           1 :         nSupbookId = Append(xSupbook);
    1874             :     }
    1875             : 
    1876           2 :     ScExternalRefCache::TokenRef pToken = pRefMgr->getSingleRefToken(nFileId, rTabName, rCell, NULL, NULL);
    1877           1 :     if (!pToken.get())
    1878           0 :         return;
    1879             : 
    1880           1 :     sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
    1881           1 :     if (nSheetId == EXC_NOTAB)
    1882             :         // specified table name not found in this SUPBOOK.
    1883           0 :         return;
    1884             : 
    1885           1 :     FindSBIndexEntry f(nSupbookId, nSheetId);
    1886           1 :     if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
    1887             :     {
    1888           1 :         maSBIndexVec.push_back(XclExpSBIndex());
    1889           1 :         XclExpSBIndex& r = maSBIndexVec.back();
    1890           1 :         r.mnSupbook = nSupbookId;
    1891           1 :         r.mnSBTab   = nSheetId;
    1892             :     }
    1893             : 
    1894           2 :     xSupbook->StoreCell(nSheetId, rCell, *pToken);
    1895             : }
    1896             : 
    1897           0 : void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
    1898             : {
    1899           0 :     ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
    1900           0 :     const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
    1901           0 :     if (!pUrl)
    1902           0 :         return;
    1903             : 
    1904           0 :     XclExpSupbookRef xSupbook;
    1905             :     sal_uInt16 nSupbookId;
    1906           0 :     if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
    1907             :     {
    1908           0 :         xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
    1909           0 :         nSupbookId = Append(xSupbook);
    1910             :     }
    1911             : 
    1912           0 :     SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
    1913             : 
    1914             :     // If this is a multi-table range, get token for each table.
    1915             :     using namespace ::formula;
    1916           0 :     vector<FormulaToken*> aMatrixList;
    1917           0 :     aMatrixList.reserve(nTabCount);
    1918             : 
    1919             :     // This is a new'ed instance, so we must manage its life cycle here.
    1920           0 :     ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, NULL);
    1921           0 :     if (!pArray.get())
    1922           0 :         return;
    1923             : 
    1924           0 :     for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
    1925             :     {
    1926           0 :         if (p->GetType() == svMatrix)
    1927           0 :             aMatrixList.push_back(p);
    1928           0 :         else if (p->GetOpCode() != ocSep)
    1929             :         {
    1930             :             // This is supposed to be ocSep!!!
    1931           0 :             return;
    1932             :         }
    1933             :     }
    1934             : 
    1935           0 :     if (aMatrixList.size() != static_cast<size_t>(nTabCount))
    1936             :     {
    1937             :         // matrix size mis-match !
    1938           0 :         return;
    1939             :     }
    1940             : 
    1941           0 :     sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
    1942             : 
    1943           0 :     ScRange aRange(rRange);
    1944           0 :     aRange.aStart.SetTab(0);
    1945           0 :     aRange.aEnd.SetTab(0);
    1946           0 :     for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
    1947             :     {
    1948           0 :         sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
    1949           0 :         FindSBIndexEntry f(nSupbookId, nSheetId);
    1950           0 :         if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
    1951             :         {
    1952           0 :             maSBIndexVec.push_back(XclExpSBIndex());
    1953           0 :             XclExpSBIndex& r = maSBIndexVec.back();
    1954           0 :             r.mnSupbook = nSupbookId;
    1955           0 :             r.mnSBTab   = nSheetId;
    1956             :         }
    1957             : 
    1958           0 :         xSupbook->StoreCellRange(nSheetId, aRange, *aMatrixList[nTab]);
    1959           0 :     }
    1960             : }
    1961             : 
    1962           0 : bool XclExpSupbookBuffer::InsertAddIn(
    1963             :         sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
    1964             : {
    1965           0 :     XclExpSupbookRef xSupbook;
    1966           0 :     if( mnAddInSB == SAL_MAX_UINT16 )
    1967             :     {
    1968           0 :         xSupbook.reset( new XclExpSupbook( GetRoot() ) );
    1969           0 :         mnAddInSB = Append( xSupbook );
    1970             :     }
    1971             :     else
    1972           0 :         xSupbook = maSupbookList.GetRecord( mnAddInSB );
    1973             :     OSL_ENSURE( xSupbook, "XclExpSupbookBuffer::InsertAddin - missing add-in supbook" );
    1974           0 :     rnSupbook = mnAddInSB;
    1975           0 :     rnExtName = xSupbook->InsertAddIn( rName );
    1976           0 :     return rnExtName > 0;
    1977             : }
    1978             : 
    1979           0 : bool XclExpSupbookBuffer::InsertEuroTool(
    1980             :         sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
    1981             : {
    1982           0 :     XclExpSupbookRef xSupbook;
    1983           0 :     OUString aUrl( "\001\010EUROTOOL.XLA" );
    1984           0 :     if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
    1985             :     {
    1986           0 :         xSupbook.reset( new XclExpSupbook( GetRoot(), aUrl, EXC_SBTYPE_EUROTOOL ) );
    1987           0 :         rnSupbook = Append( xSupbook );
    1988             :     }
    1989           0 :     rnExtName = xSupbook->InsertEuroTool( rName );
    1990           0 :     return rnExtName > 0;
    1991             : }
    1992             : 
    1993           0 : bool XclExpSupbookBuffer::InsertDde(
    1994             :         sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
    1995             :         const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
    1996             : {
    1997           0 :     XclExpSupbookRef xSupbook;
    1998           0 :     if( !GetSupbookDde( xSupbook, rnSupbook, rApplic, rTopic ) )
    1999             :     {
    2000           0 :         xSupbook.reset( new XclExpSupbook( GetRoot(), rApplic, rTopic ) );
    2001           0 :         rnSupbook = Append( xSupbook );
    2002             :     }
    2003           0 :     rnExtName = xSupbook->InsertDde( rItem );
    2004           0 :     return rnExtName > 0;
    2005             : }
    2006             : 
    2007           0 : bool XclExpSupbookBuffer::InsertExtName(
    2008             :         sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
    2009             :         const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
    2010             : {
    2011           0 :     XclExpSupbookRef xSupbook;
    2012           0 :     if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
    2013             :     {
    2014           0 :         xSupbook.reset( new XclExpSupbook(GetRoot(), rUrl) );
    2015           0 :         rnSupbook = Append(xSupbook);
    2016             :     }
    2017           0 :     rnExtName = xSupbook->InsertExtName(rName, rArray);
    2018           0 :     return rnExtName > 0;
    2019             : }
    2020             : 
    2021           1 : XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
    2022             :                                        XclExpRefLogEntry* pRefLogEntry )
    2023             : {
    2024           1 :     XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
    2025           1 :     ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
    2026           1 :     const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
    2027           1 :     if (!pUrl)
    2028           0 :         return aXti;
    2029             : 
    2030           1 :     XclExpSupbookRef xSupbook;
    2031             :     sal_uInt16 nSupbookId;
    2032           1 :     if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
    2033             :     {
    2034           0 :         xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
    2035           0 :         nSupbookId = Append(xSupbook);
    2036             :     }
    2037           1 :     aXti.mnSupbook = nSupbookId;
    2038             : 
    2039           1 :     sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
    2040           1 :     if (nFirstSheetId == EXC_NOTAB)
    2041             :     {
    2042             :         // first sheet not found in SUPBOOK.
    2043           0 :         return aXti;
    2044             :     }
    2045           1 :     sal_uInt16 nSheetCount = xSupbook->GetTabCount();
    2046           2 :     for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
    2047             :     {
    2048           1 :         sal_uInt16 nSheetId = nFirstSheetId + i;
    2049           1 :         if (nSheetId >= nSheetCount)
    2050           0 :             return aXti;
    2051             : 
    2052           1 :         FindSBIndexEntry f(nSupbookId, nSheetId);
    2053           1 :         if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
    2054             :         {
    2055           0 :             maSBIndexVec.push_back(XclExpSBIndex());
    2056           0 :             XclExpSBIndex& r = maSBIndexVec.back();
    2057           0 :             r.mnSupbook = nSupbookId;
    2058           0 :             r.mnSBTab   = nSheetId;
    2059             :         }
    2060           1 :         if (i == 0)
    2061           1 :             aXti.mnFirstSBTab = nSheetId;
    2062           1 :         if (i == nXclTabSpan - 1)
    2063           1 :             aXti.mnLastSBTab = nSheetId;
    2064             :     }
    2065             : 
    2066           1 :     if (pRefLogEntry)
    2067             :     {
    2068           0 :         pRefLogEntry->mnFirstXclTab = 0;
    2069           0 :         pRefLogEntry->mnLastXclTab  = 0;
    2070           0 :         if (xSupbook)
    2071           0 :             xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
    2072             :     }
    2073             : 
    2074           1 :     return aXti;
    2075             : }
    2076             : 
    2077           7 : void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
    2078             : {
    2079           7 :     maSupbookList.Save( rStrm );
    2080           7 : }
    2081             : 
    2082           0 : void XclExpSupbookBuffer::SaveXml( XclExpXmlStream& rStrm )
    2083             : {
    2084           0 :     ::std::map< sal_uInt16, OUString > aMap;
    2085           0 :     for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
    2086             :     {
    2087           0 :         XclExpSupbookRef xRef( maSupbookList.GetRecord( nPos));
    2088           0 :         if (xRef->GetType() != EXC_SBTYPE_EXTERN)
    2089           0 :             continue;   // handle only external reference (for now?)
    2090             : 
    2091           0 :         sal_uInt16 nId = xRef->GetFileId();
    2092           0 :         const OUString& rUrl = xRef->GetUrl();
    2093             :         ::std::pair< ::std::map< sal_uInt16, OUString >::iterator, bool > xInsert(
    2094           0 :                 aMap.insert( ::std::make_pair( nId, rUrl)));
    2095           0 :         if (!xInsert.second)
    2096             :         {
    2097             :             SAL_WARN( "sc.filter", "XclExpSupbookBuffer::SaveXml: file ID already used: " << nId <<
    2098             :                     " wanted for " << rUrl << " and is " << (*xInsert.first).second <<
    2099             :                     (rUrl == (*xInsert.first).second ? " multiple Supbook not supported" : ""));
    2100           0 :             continue;
    2101             :         }
    2102             : 
    2103           0 :         OUString sId;
    2104             :         sax_fastparser::FSHelperPtr pExternalLink = rStrm.CreateOutputStream(
    2105             :                 XclXmlUtils::GetStreamName( "xl/", "externalLinks/externalLink", nId),
    2106             :                 XclXmlUtils::GetStreamName( NULL, "externalLinks/externalLink", nId),
    2107           0 :                 rStrm.GetCurrentStream()->getOutputStream(),
    2108             :                 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
    2109             :                 CREATE_OFFICEDOC_RELATION_TYPE("externalLink"),
    2110           0 :                 &sId );
    2111             : 
    2112             :         // externalReference entry in workbook externalReferences
    2113           0 :         rStrm.GetCurrentStream()->singleElement( XML_externalReference,
    2114             :                 FSNS( XML_r, XML_id ),  XclXmlUtils::ToOString( sId ).getStr(),
    2115           0 :                 FSEND );
    2116             : 
    2117             :         // Each externalBook in a separate stream.
    2118           0 :         rStrm.PushStream( pExternalLink );
    2119           0 :         xRef->SaveXml( rStrm );
    2120           0 :         rStrm.PopStream();
    2121           0 :     }
    2122           0 : }
    2123             : 
    2124          55 : bool XclExpSupbookBuffer::HasExternalReferences() const
    2125             : {
    2126         110 :     for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
    2127             :     {
    2128          55 :         if (maSupbookList.GetRecord( nPos)->GetType() == EXC_SBTYPE_EXTERN)
    2129           0 :             return true;
    2130             :     }
    2131          55 :     return false;
    2132             : }
    2133             : 
    2134           2 : bool XclExpSupbookBuffer::GetSupbookUrl(
    2135             :         XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, const OUString& rUrl ) const
    2136             : {
    2137           4 :     for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
    2138             :     {
    2139           3 :         rxSupbook = maSupbookList.GetRecord( nPos );
    2140           3 :         if( rxSupbook->IsUrlLink( rUrl ) )
    2141             :         {
    2142           1 :             rnIndex = ulimit_cast< sal_uInt16 >( nPos );
    2143           1 :             return true;
    2144             :         }
    2145             :     }
    2146           1 :     return false;
    2147             : }
    2148             : 
    2149           0 : bool XclExpSupbookBuffer::GetSupbookDde( XclExpSupbookRef& rxSupbook,
    2150             :         sal_uInt16& rnIndex, const OUString& rApplic, const OUString& rTopic ) const
    2151             : {
    2152           0 :     for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
    2153             :     {
    2154           0 :         rxSupbook = maSupbookList.GetRecord( nPos );
    2155           0 :         if( rxSupbook->IsDdeLink( rApplic, rTopic ) )
    2156             :         {
    2157           0 :             rnIndex = ulimit_cast< sal_uInt16 >( nPos );
    2158           0 :             return true;
    2159             :         }
    2160             :     }
    2161           0 :     return false;
    2162             : }
    2163             : 
    2164          73 : sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef xSupbook )
    2165             : {
    2166          73 :     maSupbookList.AppendRecord( xSupbook );
    2167          73 :     return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
    2168             : }
    2169             : 
    2170             : // Export link manager ========================================================
    2171             : 
    2172          72 : XclExpLinkManagerImpl::XclExpLinkManagerImpl( const XclExpRoot& rRoot ) :
    2173          72 :     XclExpRoot( rRoot )
    2174             : {
    2175          72 : }
    2176             : 
    2177           0 : XclExpLinkManagerImpl5::XclExpLinkManagerImpl5( const XclExpRoot& rRoot ) :
    2178           0 :     XclExpLinkManagerImpl( rRoot )
    2179             : {
    2180           0 : }
    2181             : 
    2182           0 : void XclExpLinkManagerImpl5::FindExtSheet(
    2183             :         sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
    2184             :         SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
    2185             : {
    2186           0 :     FindInternal( rnExtSheet, rnFirstXclTab, nFirstScTab );
    2187           0 :     if( (rnFirstXclTab == EXC_TAB_DELETED) || (nFirstScTab == nLastScTab) )
    2188             :     {
    2189           0 :         rnLastXclTab = rnFirstXclTab;
    2190             :     }
    2191             :     else
    2192             :     {
    2193             :         sal_uInt16 nDummyExtSheet;
    2194           0 :         FindInternal( nDummyExtSheet, rnLastXclTab, nLastScTab );
    2195             :     }
    2196             : 
    2197             :     (void)pRefLogEntry;     // avoid compiler warning
    2198             :     OSL_ENSURE( !pRefLogEntry, "XclExpLinkManagerImpl5::FindExtSheet - fill reflog entry not implemented" );
    2199           0 : }
    2200             : 
    2201           0 : sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
    2202             : {
    2203             :     sal_uInt16 nExtSheet;
    2204           0 :     FindInternal( nExtSheet, cCode );
    2205           0 :     return nExtSheet;
    2206             : }
    2207             : 
    2208           0 : void XclExpLinkManagerImpl5::FindExtSheet(
    2209             :     sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
    2210             :     sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
    2211             :     XclExpRefLogEntry* /*pRefLogEntry*/ )
    2212             : {
    2213             :     // not implemented
    2214           0 : }
    2215             : 
    2216           0 : void XclExpLinkManagerImpl5::StoreCellRange( const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/, const ScAddress& /*rPos*/ )
    2217             : {
    2218             :     // not implemented
    2219           0 : }
    2220             : 
    2221           0 : void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScAddress& /*rPos*/ )
    2222             : {
    2223             :     // not implemented
    2224           0 : }
    2225             : 
    2226           0 : void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScRange& /*rRange*/ )
    2227             : {
    2228             :     // not implemented
    2229           0 : }
    2230             : 
    2231           0 : bool XclExpLinkManagerImpl5::InsertAddIn(
    2232             :         sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
    2233             : {
    2234           0 :     XclExpExtSheetRef xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_ADDIN );
    2235           0 :     if( xExtSheet )
    2236             :     {
    2237           0 :         rnExtName = xExtSheet->InsertAddIn( rName );
    2238           0 :         return rnExtName > 0;
    2239             :     }
    2240           0 :     return false;
    2241             : }
    2242             : 
    2243           0 : bool XclExpLinkManagerImpl5::InsertEuroTool(
    2244             :          sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rName*/ )
    2245             : {
    2246           0 :      return false;
    2247             : }
    2248             : 
    2249           0 : bool XclExpLinkManagerImpl5::InsertDde(
    2250             :         sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
    2251             :         const OUString& /*rApplic*/, const OUString& /*rTopic*/, const OUString& /*rItem*/ )
    2252             : {
    2253             :     // not implemented
    2254           0 :     return false;
    2255             : }
    2256             : 
    2257           0 : bool XclExpLinkManagerImpl5::InsertExtName(
    2258             :         sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rUrl*/,
    2259             :         const OUString& /*rName*/, const ScExternalRefCache::TokenArrayRef& /*rArray*/ )
    2260             : {
    2261             :     // not implemented
    2262           0 :     return false;
    2263             : }
    2264             : 
    2265           0 : void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
    2266             : {
    2267           0 :     if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
    2268             :     {
    2269             :         // EXTERNCOUNT record
    2270           0 :         XclExpUInt16Record( EXC_ID_EXTERNCOUNT, nExtSheetCount ).Save( rStrm );
    2271             :         // list of EXTERNSHEET records with EXTERNNAME, XCT, CRN records
    2272           0 :         maExtSheetList.Save( rStrm );
    2273             :     }
    2274           0 : }
    2275             : 
    2276           0 : void XclExpLinkManagerImpl5::SaveXml( XclExpXmlStream& /*rStrm*/ )
    2277             : {
    2278             :     // not applicable
    2279           0 : }
    2280             : 
    2281           0 : sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
    2282             : {
    2283           0 :     return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
    2284             : }
    2285             : 
    2286           0 : sal_uInt16 XclExpLinkManagerImpl5::AppendInternal( XclExpExtSheetRef xExtSheet )
    2287             : {
    2288           0 :     if( GetExtSheetCount() < 0x7FFF )
    2289             :     {
    2290           0 :         maExtSheetList.AppendRecord( xExtSheet );
    2291             :         // return negated one-based EXTERNSHEET index (i.e. 0xFFFD for 3rd record)
    2292           0 :         return static_cast< sal_uInt16 >( -GetExtSheetCount() );
    2293             :     }
    2294           0 :     return 0;
    2295             : }
    2296             : 
    2297           0 : void XclExpLinkManagerImpl5::CreateInternal()
    2298             : {
    2299           0 :     if( maIntTabMap.empty() )
    2300             :     {
    2301             :         // create EXTERNSHEET records for all internal exported sheets
    2302           0 :         XclExpTabInfo& rTabInfo = GetTabInfo();
    2303           0 :         for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
    2304             :         {
    2305           0 :             if( rTabInfo.IsExportTab( nScTab ) )
    2306             :             {
    2307           0 :                 XclExpExtSheetRef xRec;
    2308           0 :                 if( nScTab == GetCurrScTab() )
    2309           0 :                     xRec.reset( new XclExpExternSheet( GetRoot(), EXC_EXTSH_OWNTAB ) );
    2310             :                 else
    2311           0 :                     xRec.reset( new XclExpExternSheet( GetRoot(), rTabInfo.GetScTabName( nScTab ) ) );
    2312           0 :                 maIntTabMap[ nScTab ] = AppendInternal( xRec );
    2313             :             }
    2314             :         }
    2315             :     }
    2316           0 : }
    2317             : 
    2318           0 : XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::GetInternal( sal_uInt16 nExtSheet )
    2319             : {
    2320           0 :     return maExtSheetList.GetRecord( static_cast< sal_uInt16 >( -nExtSheet - 1 ) );
    2321             : }
    2322             : 
    2323           0 : XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
    2324             :         sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab )
    2325             : {
    2326             :     // create internal EXTERNSHEET records on demand
    2327           0 :     CreateInternal();
    2328             : 
    2329             :     // try to find an EXTERNSHEET record - if not, return a "deleted sheet" reference
    2330           0 :     XclExpExtSheetRef xExtSheet;
    2331           0 :     XclExpIntTabMap::const_iterator aIt = maIntTabMap.find( nScTab );
    2332           0 :     if( aIt == maIntTabMap.end() )
    2333             :     {
    2334           0 :         xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_OWNDOC );
    2335           0 :         rnXclTab = EXC_TAB_DELETED;
    2336             :     }
    2337             :     else
    2338             :     {
    2339           0 :         rnExtSheet = aIt->second;
    2340           0 :         xExtSheet = GetInternal( rnExtSheet );
    2341           0 :         rnXclTab = GetTabInfo().GetXclTab( nScTab );
    2342             :     }
    2343           0 :     return xExtSheet;
    2344             : }
    2345             : 
    2346           0 : XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
    2347             :     sal_uInt16& rnExtSheet, sal_Unicode cCode )
    2348             : {
    2349           0 :     XclExpExtSheetRef xExtSheet;
    2350           0 :     XclExpCodeMap::const_iterator aIt = maCodeMap.find( cCode );
    2351           0 :     if( aIt == maCodeMap.end() )
    2352             :     {
    2353           0 :         xExtSheet.reset( new XclExpExternSheet( GetRoot(), cCode ) );
    2354           0 :         rnExtSheet = maCodeMap[ cCode ] = AppendInternal( xExtSheet );
    2355             :     }
    2356             :     else
    2357             :     {
    2358           0 :         rnExtSheet = aIt->second;
    2359           0 :         xExtSheet = GetInternal( rnExtSheet );
    2360             :     }
    2361           0 :     return xExtSheet;
    2362             : }
    2363             : 
    2364          72 : XclExpLinkManagerImpl8::XclExpLinkManagerImpl8( const XclExpRoot& rRoot ) :
    2365             :     XclExpLinkManagerImpl( rRoot ),
    2366          72 :     maSBBuffer( rRoot )
    2367             : {
    2368          72 : }
    2369             : 
    2370         138 : void XclExpLinkManagerImpl8::FindExtSheet(
    2371             :         sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
    2372             :         SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
    2373             : {
    2374         138 :     XclExpTabInfo& rTabInfo = GetTabInfo();
    2375         138 :     rnFirstXclTab = rTabInfo.GetXclTab( nFirstScTab );
    2376         138 :     rnLastXclTab = rTabInfo.GetXclTab( nLastScTab );
    2377         138 :     rnExtSheet = InsertXti( maSBBuffer.GetXti( rnFirstXclTab, rnLastXclTab, pRefLogEntry ) );
    2378         138 : }
    2379             : 
    2380           0 : sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
    2381             : {
    2382             :     (void)cCode;    // avoid compiler warning
    2383             :     OSL_ENSURE( (cCode == EXC_EXTSH_OWNDOC) || (cCode == EXC_EXTSH_ADDIN),
    2384             :         "XclExpLinkManagerImpl8::FindExtSheet - unknown externsheet code" );
    2385           0 :     return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
    2386             : }
    2387             : 
    2388           1 : void XclExpLinkManagerImpl8::FindExtSheet(
    2389             :     sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
    2390             :     sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
    2391             :     XclExpRefLogEntry* pRefLogEntry )
    2392             : {
    2393           1 :     XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
    2394           1 :     rnExtSheet = InsertXti(aXti);
    2395           1 :     rnFirstSBTab = aXti.mnFirstSBTab;
    2396           1 :     rnLastSBTab  = aXti.mnLastSBTab;
    2397           1 : }
    2398             : 
    2399         740 : void XclExpLinkManagerImpl8::StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos )
    2400             : {
    2401         740 :     ScAddress aAbs1 = rRef1.toAbs(rPos);
    2402         740 :     ScAddress aAbs2 = rRef2.toAbs(rPos);
    2403         740 :     if (!rRef1.IsDeleted() && !rRef2.IsDeleted() && (aAbs1.Tab() >= 0) && (aAbs2.Tab() >= 0))
    2404             :     {
    2405         740 :         const XclExpTabInfo& rTabInfo = GetTabInfo();
    2406         740 :         SCTAB nFirstScTab = aAbs1.Tab();
    2407         740 :         SCTAB nLastScTab = aAbs2.Tab();
    2408         740 :         ScRange aRange(aAbs1.Col(), aAbs1.Row(), 0, aAbs2.Col(), aAbs2.Row(), 0);
    2409        1480 :         for (SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab)
    2410             :         {
    2411         740 :             if( rTabInfo.IsExternalTab( nScTab ) )
    2412             :             {
    2413           0 :                 aRange.aStart.SetTab( nScTab );
    2414           0 :                 aRange.aEnd.SetTab( nScTab );
    2415           0 :                 maSBBuffer.StoreCellRange( aRange );
    2416             :             }
    2417             :         }
    2418             :     }
    2419         740 : }
    2420             : 
    2421           1 : void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
    2422             : {
    2423           1 :     maSBBuffer.StoreCell(nFileId, rTabName, rPos);
    2424           1 : }
    2425             : 
    2426           0 : void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
    2427             : {
    2428           0 :     maSBBuffer.StoreCellRange(nFileId, rTabName, rRange);
    2429           0 : }
    2430             : 
    2431           0 : bool XclExpLinkManagerImpl8::InsertAddIn(
    2432             :         sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
    2433             : {
    2434             :     sal_uInt16 nSupbook;
    2435           0 :     if( maSBBuffer.InsertAddIn( nSupbook, rnExtName, rName ) )
    2436             :     {
    2437           0 :         rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
    2438           0 :         return true;
    2439             :     }
    2440           0 :     return false;
    2441             : }
    2442             : 
    2443           0 : bool XclExpLinkManagerImpl8::InsertEuroTool(
    2444             :          sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
    2445             : {
    2446             :     sal_uInt16 nSupbook;
    2447           0 :     if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
    2448             :     {
    2449           0 :         rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
    2450           0 :         return true;
    2451             :     }
    2452           0 :     return false;
    2453             : }
    2454             : 
    2455           0 : bool XclExpLinkManagerImpl8::InsertDde(
    2456             :         sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
    2457             :         const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
    2458             : {
    2459             :     sal_uInt16 nSupbook;
    2460           0 :     if( maSBBuffer.InsertDde( nSupbook, rnExtName, rApplic, rTopic, rItem ) )
    2461             :     {
    2462           0 :         rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
    2463           0 :         return true;
    2464             :     }
    2465           0 :     return false;
    2466             : }
    2467             : 
    2468           0 : bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
    2469             :         const OUString& rName, const OUString& rUrl, const ScExternalRefCache::TokenArrayRef& rArray )
    2470             : {
    2471             :     sal_uInt16 nSupbook;
    2472           0 :     if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, rArray ) )
    2473             :     {
    2474           0 :         rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
    2475           0 :         return true;
    2476             :     }
    2477           0 :     return false;
    2478             : }
    2479             : 
    2480          17 : void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
    2481             : {
    2482          17 :     if( !maXtiVec.empty() )
    2483             :     {
    2484             :         // SUPBOOKs, XCTs, CRNs, EXTERNNAMEs
    2485           7 :         maSBBuffer.Save( rStrm );
    2486             : 
    2487             :         // EXTERNSHEET
    2488           7 :         sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXtiVec.size() );
    2489           7 :         rStrm.StartRecord( EXC_ID_EXTERNSHEET, 2 + 6 * nCount );
    2490           7 :         rStrm << nCount;
    2491           7 :         rStrm.SetSliceSize( 6 );
    2492          14 :         for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
    2493           7 :             aIt->Save( rStrm );
    2494           7 :         rStrm.EndRecord();
    2495             :     }
    2496          17 : }
    2497             : 
    2498          55 : void XclExpLinkManagerImpl8::SaveXml( XclExpXmlStream& rStrm )
    2499             : {
    2500          55 :     if (maSBBuffer.HasExternalReferences())
    2501             :     {
    2502           0 :         sax_fastparser::FSHelperPtr pWorkbook = rStrm.GetCurrentStream();
    2503           0 :         pWorkbook->startElement( XML_externalReferences, FSEND);
    2504             : 
    2505             :         // externalLink, externalBook, sheetNames, sheetDataSet, externalName
    2506           0 :         maSBBuffer.SaveXml( rStrm );
    2507             : 
    2508           0 :         pWorkbook->endElement( XML_externalReferences);
    2509             :     }
    2510             : 
    2511             :     // TODO: equivalent for EXTERNSHEET in OOXML?
    2512             : #if 0
    2513             :     if( !maXtiVec.empty() )
    2514             :     {
    2515             :         for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
    2516             :             aIt->SaveXml( rStrm );
    2517             :     }
    2518             : #endif
    2519          55 : }
    2520             : 
    2521         139 : sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
    2522             : {
    2523         149 :     for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
    2524         114 :         if( *aIt == rXti )
    2525         104 :             return ulimit_cast< sal_uInt16 >( aIt - maXtiVec.begin() );
    2526          35 :     maXtiVec.push_back( rXti );
    2527          35 :     return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
    2528             : }
    2529             : 
    2530          72 : XclExpLinkManager::XclExpLinkManager( const XclExpRoot& rRoot ) :
    2531          72 :     XclExpRoot( rRoot )
    2532             : {
    2533          72 :     switch( GetBiff() )
    2534             :     {
    2535             :         case EXC_BIFF5:
    2536           0 :             mxImpl.reset( new XclExpLinkManagerImpl5( rRoot ) );
    2537           0 :         break;
    2538             :         case EXC_BIFF8:
    2539          72 :             mxImpl.reset( new XclExpLinkManagerImpl8( rRoot ) );
    2540          72 :         break;
    2541             :         default:
    2542             :             DBG_ERROR_BIFF();
    2543             :     }
    2544          72 : }
    2545             : 
    2546         144 : XclExpLinkManager::~XclExpLinkManager()
    2547             : {
    2548         144 : }
    2549             : 
    2550          81 : void XclExpLinkManager::FindExtSheet(
    2551             :         sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab,
    2552             :         SCTAB nScTab, XclExpRefLogEntry* pRefLogEntry )
    2553             : {
    2554          81 :     mxImpl->FindExtSheet( rnExtSheet, rnXclTab, rnXclTab, nScTab, nScTab, pRefLogEntry );
    2555          81 : }
    2556             : 
    2557          57 : void XclExpLinkManager::FindExtSheet(
    2558             :         sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
    2559             :         SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
    2560             : {
    2561          57 :     mxImpl->FindExtSheet( rnExtSheet, rnFirstXclTab, rnLastXclTab, nFirstScTab, nLastScTab, pRefLogEntry );
    2562          57 : }
    2563             : 
    2564           0 : sal_uInt16 XclExpLinkManager::FindExtSheet( sal_Unicode cCode )
    2565             : {
    2566           0 :     return mxImpl->FindExtSheet( cCode );
    2567             : }
    2568             : 
    2569           1 : void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
    2570             :                                       sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
    2571             :                                       XclExpRefLogEntry* pRefLogEntry )
    2572             : {
    2573           1 :     mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
    2574           1 : }
    2575             : 
    2576         560 : void XclExpLinkManager::StoreCell( const ScSingleRefData& rRef, const ScAddress& rPos )
    2577             : {
    2578         560 :     mxImpl->StoreCellRange(rRef, rRef, rPos);
    2579         560 : }
    2580             : 
    2581         180 : void XclExpLinkManager::StoreCellRange( const ScComplexRefData& rRef, const ScAddress& rPos )
    2582             : {
    2583         180 :     mxImpl->StoreCellRange(rRef.Ref1, rRef.Ref2, rPos);
    2584         180 : }
    2585             : 
    2586           1 : void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
    2587             : {
    2588           1 :     mxImpl->StoreCell(nFileId, rTabName, rPos);
    2589           1 : }
    2590             : 
    2591           0 : void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
    2592             : {
    2593           0 :     mxImpl->StoreCellRange(nFileId, rTabName, rRange);
    2594           0 : }
    2595             : 
    2596           0 : bool XclExpLinkManager::InsertAddIn(
    2597             :         sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
    2598             : {
    2599           0 :     return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
    2600             : }
    2601             : 
    2602           0 : bool XclExpLinkManager::InsertEuroTool(
    2603             :         sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
    2604             : {
    2605           0 :     return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
    2606             : }
    2607             : 
    2608           0 : bool XclExpLinkManager::InsertDde(
    2609             :         sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
    2610             :         const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
    2611             : {
    2612           0 :     return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
    2613             : }
    2614             : 
    2615           0 : bool XclExpLinkManager::InsertExtName(
    2616             :     sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName, const OUString& rUrl,
    2617             :     const ScExternalRefCache::TokenArrayRef& rArray )
    2618             : {
    2619           0 :     return mxImpl->InsertExtName(rnExtSheet, rnExtName, rUrl, rName, rArray);
    2620             : }
    2621             : 
    2622          17 : void XclExpLinkManager::Save( XclExpStream& rStrm )
    2623             : {
    2624          17 :     mxImpl->Save( rStrm );
    2625          17 : }
    2626             : 
    2627          55 : void XclExpLinkManager::SaveXml( XclExpXmlStream& rStrm )
    2628             : {
    2629          55 :     mxImpl->SaveXml( rStrm );
    2630          85 : }
    2631             : 
    2632             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11