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

Generated by: LCOV version 1.10