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

Generated by: LCOV version 1.10