1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/xls/externallinkbuffer.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <com/sun/star/sheet/ComplexReference.hpp>
27cdf0e10cSrcweir #include <com/sun/star/sheet/DDELinkInfo.hpp>
28cdf0e10cSrcweir #include <com/sun/star/sheet/ExternalLinkType.hpp>
29cdf0e10cSrcweir #include <com/sun/star/sheet/ExternalReference.hpp>
30cdf0e10cSrcweir #include <com/sun/star/sheet/ReferenceFlags.hpp>
31cdf0e10cSrcweir #include <com/sun/star/sheet/SingleReference.hpp>
32cdf0e10cSrcweir #include <com/sun/star/sheet/XDDELinks.hpp>
33cdf0e10cSrcweir #include <com/sun/star/sheet/XDDELink.hpp>
34cdf0e10cSrcweir #include <com/sun/star/sheet/XDDELinkResults.hpp>
35cdf0e10cSrcweir #include <com/sun/star/sheet/XExternalDocLink.hpp>
36cdf0e10cSrcweir #include <com/sun/star/sheet/XExternalDocLinks.hpp>
37cdf0e10cSrcweir #include <rtl/strbuf.hxx>
38cdf0e10cSrcweir #include "oox/core/filterbase.hxx"
39cdf0e10cSrcweir #include "oox/helper/attributelist.hxx"
40cdf0e10cSrcweir #include "oox/xls/addressconverter.hxx"
41cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx"
42cdf0e10cSrcweir #include "oox/xls/excelhandlers.hxx"
43cdf0e10cSrcweir #include "oox/xls/formulaparser.hxx"
44cdf0e10cSrcweir #include "oox/xls/worksheetbuffer.hxx"
45cdf0e10cSrcweir 
46cdf0e10cSrcweir namespace oox {
47cdf0e10cSrcweir namespace xls {
48cdf0e10cSrcweir 
49cdf0e10cSrcweir // ============================================================================
50cdf0e10cSrcweir 
51cdf0e10cSrcweir using namespace ::com::sun::star::sheet;
52cdf0e10cSrcweir using namespace ::com::sun::star::table;
53cdf0e10cSrcweir using namespace ::com::sun::star::uno;
54cdf0e10cSrcweir 
55cdf0e10cSrcweir using ::oox::core::Relation;
56cdf0e10cSrcweir using ::oox::core::Relations;
57cdf0e10cSrcweir using ::rtl::OString;
58cdf0e10cSrcweir using ::rtl::OStringBuffer;
59cdf0e10cSrcweir using ::rtl::OStringToOUString;
60cdf0e10cSrcweir using ::rtl::OUString;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir // ============================================================================
63cdf0e10cSrcweir 
64cdf0e10cSrcweir namespace {
65cdf0e10cSrcweir 
66cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK   = 0;
67cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTERNALBOOK_DDE    = 1;
68cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTERNALBOOK_OLE    = 2;
69cdf0e10cSrcweir 
70cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC   = 0x0002;
71cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTNAME_PREFERPIC   = 0x0004;
72cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME  = 0x0008;
73cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT   = 0x0010;
74cdf0e10cSrcweir const sal_uInt16 BIFF12_EXTNAME_ICONIFIED   = 0x0020;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir const sal_uInt16 BIFF_EXTNAME_BUILTIN       = 0x0001;
77cdf0e10cSrcweir const sal_uInt16 BIFF_EXTNAME_AUTOMATIC     = 0x0002;
78cdf0e10cSrcweir const sal_uInt16 BIFF_EXTNAME_PREFERPIC     = 0x0004;
79cdf0e10cSrcweir const sal_uInt16 BIFF_EXTNAME_STDDOCNAME    = 0x0008;
80cdf0e10cSrcweir const sal_uInt16 BIFF_EXTNAME_OLEOBJECT     = 0x0010;
81cdf0e10cSrcweir const sal_uInt16 BIFF_EXTNAME_ICONIFIED     = 0x8000;
82cdf0e10cSrcweir 
83cdf0e10cSrcweir } // namespace
84cdf0e10cSrcweir 
85cdf0e10cSrcweir // ============================================================================
86cdf0e10cSrcweir 
ExternalNameModel()87cdf0e10cSrcweir ExternalNameModel::ExternalNameModel() :
88cdf0e10cSrcweir     mbBuiltIn( false ),
89cdf0e10cSrcweir     mbNotify( false ),
90cdf0e10cSrcweir     mbPreferPic( false ),
91cdf0e10cSrcweir     mbStdDocName( false ),
92cdf0e10cSrcweir     mbOleObj( false ),
93cdf0e10cSrcweir     mbIconified( false )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir // ============================================================================
98cdf0e10cSrcweir 
ExternalName(const ExternalLink & rParentLink)99cdf0e10cSrcweir ExternalName::ExternalName( const ExternalLink& rParentLink ) :
100cdf0e10cSrcweir     DefinedNameBase( rParentLink ),
101cdf0e10cSrcweir     mrParentLink( rParentLink ),
102cdf0e10cSrcweir     mnStorageId( 0 ),
103cdf0e10cSrcweir     mbDdeLinkCreated( false )
104cdf0e10cSrcweir {
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
importDefinedName(const AttributeList & rAttribs)107cdf0e10cSrcweir void ExternalName::importDefinedName( const AttributeList& rAttribs )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir     maModel.maName = rAttribs.getXString( XML_name, OUString() );
110cdf0e10cSrcweir     OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDefinedName - empty name" );
111cdf0e10cSrcweir     // zero-based index into sheet list of externalBook
112cdf0e10cSrcweir     maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 );
113cdf0e10cSrcweir }
114cdf0e10cSrcweir 
importDdeItem(const AttributeList & rAttribs)115cdf0e10cSrcweir void ExternalName::importDdeItem( const AttributeList& rAttribs )
116cdf0e10cSrcweir {
117cdf0e10cSrcweir     maModel.maName = rAttribs.getXString( XML_name, OUString() );
118cdf0e10cSrcweir     OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDdeItem - empty name" );
119cdf0e10cSrcweir     maExtNameModel.mbOleObj     = false;
120cdf0e10cSrcweir     maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false );
121cdf0e10cSrcweir     maExtNameModel.mbNotify     = rAttribs.getBool( XML_advise, false );
122cdf0e10cSrcweir     maExtNameModel.mbPreferPic  = rAttribs.getBool( XML_preferPic, false );
123cdf0e10cSrcweir }
124cdf0e10cSrcweir 
importValues(const AttributeList & rAttribs)125cdf0e10cSrcweir void ExternalName::importValues( const AttributeList& rAttribs )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir     setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) );
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
importOleItem(const AttributeList & rAttribs)130cdf0e10cSrcweir void ExternalName::importOleItem( const AttributeList& rAttribs )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     maModel.maName = rAttribs.getXString( XML_name, OUString() );
133cdf0e10cSrcweir     OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importOleItem - empty name" );
134cdf0e10cSrcweir     maExtNameModel.mbOleObj    = true;
135cdf0e10cSrcweir     maExtNameModel.mbNotify    = rAttribs.getBool( XML_advise, false );
136cdf0e10cSrcweir     maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
137cdf0e10cSrcweir     maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false );
138cdf0e10cSrcweir }
139cdf0e10cSrcweir 
importExternalName(SequenceInputStream & rStrm)140cdf0e10cSrcweir void ExternalName::importExternalName( SequenceInputStream& rStrm )
141cdf0e10cSrcweir {
142cdf0e10cSrcweir     rStrm >> maModel.maName;
143cdf0e10cSrcweir     OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" );
144cdf0e10cSrcweir }
145cdf0e10cSrcweir 
importExternalNameFlags(SequenceInputStream & rStrm)146cdf0e10cSrcweir void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm )
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     sal_uInt16 nFlags;
149cdf0e10cSrcweir     sal_Int32 nSheetId;
150cdf0e10cSrcweir     rStrm >> nFlags >> nSheetId;
151cdf0e10cSrcweir     // index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
152cdf0e10cSrcweir     maModel.mnSheet = nSheetId - 1;
153cdf0e10cSrcweir     // no flag for built-in names, as in OOXML...
154cdf0e10cSrcweir     maExtNameModel.mbNotify     = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC );
155cdf0e10cSrcweir     maExtNameModel.mbPreferPic  = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC );
156cdf0e10cSrcweir     maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME );
157cdf0e10cSrcweir     maExtNameModel.mbOleObj     = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT );
158cdf0e10cSrcweir     maExtNameModel.mbIconified  = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED );
159cdf0e10cSrcweir     OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj,
160cdf0e10cSrcweir         "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
importDdeItemValues(SequenceInputStream & rStrm)163cdf0e10cSrcweir void ExternalName::importDdeItemValues( SequenceInputStream& rStrm )
164cdf0e10cSrcweir {
165cdf0e10cSrcweir     sal_Int32 nRows, nCols;
166cdf0e10cSrcweir     rStrm >> nRows >> nCols;
167cdf0e10cSrcweir     setResultSize( nCols, nRows );
168cdf0e10cSrcweir }
169cdf0e10cSrcweir 
importDdeItemBool(SequenceInputStream & rStrm)170cdf0e10cSrcweir void ExternalName::importDdeItemBool( SequenceInputStream& rStrm )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
importDdeItemDouble(SequenceInputStream & rStrm)175cdf0e10cSrcweir void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir     appendResultValue( rStrm.readDouble() );
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
importDdeItemError(SequenceInputStream & rStrm)180cdf0e10cSrcweir void ExternalName::importDdeItemError( SequenceInputStream& rStrm )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
importDdeItemString(SequenceInputStream & rStrm)185cdf0e10cSrcweir void ExternalName::importDdeItemString( SequenceInputStream& rStrm )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir     appendResultValue( BiffHelper::readString( rStrm ) );
188cdf0e10cSrcweir }
189cdf0e10cSrcweir 
importExternalName(BiffInputStream & rStrm)190cdf0e10cSrcweir void ExternalName::importExternalName( BiffInputStream& rStrm )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir     sal_uInt16 nFlags = 0;
193cdf0e10cSrcweir     if( getBiff() >= BIFF3 )
194cdf0e10cSrcweir     {
195cdf0e10cSrcweir         rStrm >> nFlags;
196cdf0e10cSrcweir         maExtNameModel.mbBuiltIn    = getFlag( nFlags, BIFF_EXTNAME_BUILTIN );
197cdf0e10cSrcweir         maExtNameModel.mbNotify     = getFlag( nFlags, BIFF_EXTNAME_AUTOMATIC );
198cdf0e10cSrcweir         maExtNameModel.mbPreferPic  = getFlag( nFlags, BIFF_EXTNAME_PREFERPIC );
199cdf0e10cSrcweir 
200cdf0e10cSrcweir         // BIFF5-BIFF8: sheet index for sheet-local names, OLE settings
201cdf0e10cSrcweir         if( getBiff() >= BIFF5 )
202cdf0e10cSrcweir         {
203cdf0e10cSrcweir             maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF_EXTNAME_STDDOCNAME );
204cdf0e10cSrcweir             maExtNameModel.mbOleObj     = getFlag( nFlags, BIFF_EXTNAME_OLEOBJECT );
205cdf0e10cSrcweir             maExtNameModel.mbIconified  = getFlag( nFlags, BIFF_EXTNAME_ICONIFIED );
206cdf0e10cSrcweir 
207cdf0e10cSrcweir             if( maExtNameModel.mbOleObj )
208cdf0e10cSrcweir             {
209cdf0e10cSrcweir                 rStrm >> mnStorageId;
210cdf0e10cSrcweir             }
211cdf0e10cSrcweir             else
212cdf0e10cSrcweir             {
213cdf0e10cSrcweir                 /*  Import the reference ID for names that are sheet-local in
214cdf0e10cSrcweir                     the external document. This index will be resolved later to
215cdf0e10cSrcweir                     the index of the external sheet cache which is able to
216cdf0e10cSrcweir                     provide the name of the sheet related to this defined name.
217cdf0e10cSrcweir                     - BIFF5: one-based index to EXTERNSHEET record containing
218cdf0e10cSrcweir                         the document and sheet name
219cdf0e10cSrcweir                     - BIFF8: one-based index into EXTERNALBOOK sheet name list
220cdf0e10cSrcweir                     The value zero means this external name is a global name.
221cdf0e10cSrcweir                  */
222cdf0e10cSrcweir                 rStrm.skip( 2 );
223cdf0e10cSrcweir                 maModel.mnSheet = rStrm.readuInt16();
224cdf0e10cSrcweir             }
225cdf0e10cSrcweir         }
226cdf0e10cSrcweir     }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     maModel.maName = (getBiff() == BIFF8) ?
229cdf0e10cSrcweir         rStrm.readUniStringBody( rStrm.readuInt8() ) :
230cdf0e10cSrcweir         rStrm.readByteStringUC( false, getTextEncoding() );
231cdf0e10cSrcweir     OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" );
232cdf0e10cSrcweir 
233cdf0e10cSrcweir     // load cell references that are stored in hidden external names (seen in BIFF3-BIFF4)
234cdf0e10cSrcweir     bool bHiddenRef = (getBiff() <= BIFF4) && (maModel.maName.getLength() > 1) && (maModel.maName[ 0 ] == '\x01') && (rStrm.getRemaining() > 2);
235cdf0e10cSrcweir     switch( mrParentLink.getLinkType() )
236cdf0e10cSrcweir     {
237cdf0e10cSrcweir         case LINKTYPE_INTERNAL:
238cdf0e10cSrcweir             // cell references to other internal sheets are stored in hidden external names
239cdf0e10cSrcweir             if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() )
240cdf0e10cSrcweir             {
241cdf0e10cSrcweir                 ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm );
242cdf0e10cSrcweir                 extractReference( aTokens );
243cdf0e10cSrcweir             }
244cdf0e10cSrcweir         break;
245cdf0e10cSrcweir 
246cdf0e10cSrcweir         case LINKTYPE_EXTERNAL:
247cdf0e10cSrcweir             // cell references to other documents are stored in hidden external names
248cdf0e10cSrcweir             if( bHiddenRef )
249cdf0e10cSrcweir             {
250cdf0e10cSrcweir                 ApiTokenSequence aTokens = importBiffFormula( 0, rStrm );
251cdf0e10cSrcweir                 extractExternalReference( aTokens );
252cdf0e10cSrcweir             }
253cdf0e10cSrcweir         break;
254cdf0e10cSrcweir 
255cdf0e10cSrcweir         case LINKTYPE_DDE:
256cdf0e10cSrcweir         case LINKTYPE_OLE:
257cdf0e10cSrcweir         case LINKTYPE_MAYBE_DDE_OLE:
258cdf0e10cSrcweir             // DDE/OLE link results
259cdf0e10cSrcweir             if( rStrm.getRemaining() > 3 )
260cdf0e10cSrcweir             {
261cdf0e10cSrcweir                 bool bBiff8 = getBiff() == BIFF8;
262cdf0e10cSrcweir                 sal_Int32 nCols = rStrm.readuInt8();
263cdf0e10cSrcweir                 sal_Int32 nRows = rStrm.readuInt16();
264cdf0e10cSrcweir                 if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256;
265cdf0e10cSrcweir                 setResultSize( nCols, nRows );
266cdf0e10cSrcweir 
267cdf0e10cSrcweir                 bool bLoop = true;
268cdf0e10cSrcweir                 while( bLoop && !rStrm.isEof() && (maCurrIt != maResults.end()) )
269cdf0e10cSrcweir                 {
270cdf0e10cSrcweir                     switch( rStrm.readuInt8() )
271cdf0e10cSrcweir                     {
272cdf0e10cSrcweir                         case BIFF_DATATYPE_EMPTY:
273cdf0e10cSrcweir                             appendResultValue( OUString() );
274cdf0e10cSrcweir                             rStrm.skip( 8 );
275cdf0e10cSrcweir                         break;
276cdf0e10cSrcweir                         case BIFF_DATATYPE_DOUBLE:
277cdf0e10cSrcweir                             appendResultValue( rStrm.readDouble() );
278cdf0e10cSrcweir                         break;
279cdf0e10cSrcweir                         case BIFF_DATATYPE_STRING:
280cdf0e10cSrcweir                             appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ) );
281cdf0e10cSrcweir                         break;
282cdf0e10cSrcweir                         case BIFF_DATATYPE_BOOL:
283cdf0e10cSrcweir                             appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
284cdf0e10cSrcweir                             rStrm.skip( 7 );
285cdf0e10cSrcweir                         break;
286cdf0e10cSrcweir                         case BIFF_DATATYPE_ERROR:
287cdf0e10cSrcweir                             appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
288cdf0e10cSrcweir                             rStrm.skip( 7 );
289cdf0e10cSrcweir                         break;
290cdf0e10cSrcweir                         default:
291cdf0e10cSrcweir                             bLoop = false;
292cdf0e10cSrcweir                     }
293cdf0e10cSrcweir                 }
294cdf0e10cSrcweir                 OSL_ENSURE( bLoop && !rStrm.isEof() && (maCurrIt == maResults.end()),
295cdf0e10cSrcweir                     "ExternalName::importExternalName - stream error in result set" );
296cdf0e10cSrcweir             }
297cdf0e10cSrcweir         break;
298cdf0e10cSrcweir 
299cdf0e10cSrcweir         default:;
300cdf0e10cSrcweir     }
301cdf0e10cSrcweir }
302cdf0e10cSrcweir 
303cdf0e10cSrcweir #if 0
304cdf0e10cSrcweir sal_Int32 ExternalName::getSheetCacheIndex() const
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" );
307cdf0e10cSrcweir     sal_Int32 nCacheIdx = -1;
308cdf0e10cSrcweir     switch( getFilterType() )
309cdf0e10cSrcweir     {
310cdf0e10cSrcweir         case FILTER_OOXML:
311cdf0e10cSrcweir             // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
312cdf0e10cSrcweir             if( maModel.mnSheet >= 0 )
313cdf0e10cSrcweir                 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
314cdf0e10cSrcweir         break;
315cdf0e10cSrcweir         case FILTER_BIFF:
316cdf0e10cSrcweir             switch( getBiff() )
317cdf0e10cSrcweir             {
318cdf0e10cSrcweir                 case BIFF2:
319cdf0e10cSrcweir                 case BIFF3:
320cdf0e10cSrcweir                 case BIFF4:
321cdf0e10cSrcweir                 break;
322cdf0e10cSrcweir                 case BIFF5:
323cdf0e10cSrcweir                     if( maModel.mnSheet > 0 )
324cdf0e10cSrcweir                         if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() )
325cdf0e10cSrcweir                             if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL )
326cdf0e10cSrcweir                                 nCacheIdx = pExtLink->getSheetIndex();
327cdf0e10cSrcweir                 break;
328cdf0e10cSrcweir                 case BIFF8:
329cdf0e10cSrcweir                     if( maModel.mnSheet > 0 )
330cdf0e10cSrcweir                         nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
331cdf0e10cSrcweir                 break;
332cdf0e10cSrcweir                 case BIFF_UNKNOWN:
333cdf0e10cSrcweir                 break;
334cdf0e10cSrcweir             }
335cdf0e10cSrcweir         break;
336cdf0e10cSrcweir         case FILTER_UNKNOWN:
337cdf0e10cSrcweir         break;
338cdf0e10cSrcweir     }
339cdf0e10cSrcweir     return nCacheIdx;
340cdf0e10cSrcweir }
341cdf0e10cSrcweir #endif
342cdf0e10cSrcweir 
getDdeItemInfo(DDEItemInfo & orItemInfo) const343cdf0e10cSrcweir bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const
344cdf0e10cSrcweir {
345cdf0e10cSrcweir     if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maModel.maName.getLength() > 0) )
346cdf0e10cSrcweir     {
347cdf0e10cSrcweir         orItemInfo.Item = maModel.maName;
348cdf0e10cSrcweir         orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults );
349cdf0e10cSrcweir         return true;
350cdf0e10cSrcweir     }
351cdf0e10cSrcweir     return false;
352cdf0e10cSrcweir }
353cdf0e10cSrcweir 
getDdeLinkData(OUString & orDdeServer,OUString & orDdeTopic,OUString & orDdeItem)354cdf0e10cSrcweir bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem )
355cdf0e10cSrcweir {
356cdf0e10cSrcweir     if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maModel.maName.getLength() > 0) )
357cdf0e10cSrcweir     {
358cdf0e10cSrcweir         // try to create a DDE link and to set the imported link results
359cdf0e10cSrcweir         if( !mbDdeLinkCreated ) try
360cdf0e10cSrcweir         {
361cdf0e10cSrcweir             PropertySet aDocProps( getDocument() );
362cdf0e10cSrcweir             Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW );
363cdf0e10cSrcweir             mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT );
364cdf0e10cSrcweir             mbDdeLinkCreated = true;    // ignore if setting results fails
365cdf0e10cSrcweir             if( !maResults.empty() )
366cdf0e10cSrcweir             {
367cdf0e10cSrcweir                 Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW );
368cdf0e10cSrcweir                 xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) );
369cdf0e10cSrcweir             }
370cdf0e10cSrcweir         }
371cdf0e10cSrcweir         catch( Exception& )
372cdf0e10cSrcweir         {
373cdf0e10cSrcweir             OSL_ENSURE( false, "ExternalName::getDdeLinkData - cannot create DDE link" );
374cdf0e10cSrcweir         }
375cdf0e10cSrcweir         // get link data from created DDE link
376cdf0e10cSrcweir         if( mxDdeLink.is() )
377cdf0e10cSrcweir         {
378cdf0e10cSrcweir             orDdeServer = mxDdeLink->getApplication();
379cdf0e10cSrcweir             orDdeTopic = mxDdeLink->getTopic();
380cdf0e10cSrcweir             orDdeItem = mxDdeLink->getItem();
381cdf0e10cSrcweir             return true;
382cdf0e10cSrcweir         }
383cdf0e10cSrcweir     }
384cdf0e10cSrcweir     return false;
385cdf0e10cSrcweir }
386cdf0e10cSrcweir 
387cdf0e10cSrcweir // private --------------------------------------------------------------------
388cdf0e10cSrcweir 
389cdf0e10cSrcweir namespace {
390cdf0e10cSrcweir 
lclSetSheetCacheIndex(SingleReference & orApiRef,sal_Int32 nCacheIdx)391cdf0e10cSrcweir void lclSetSheetCacheIndex( SingleReference& orApiRef, sal_Int32 nCacheIdx )
392cdf0e10cSrcweir {
393cdf0e10cSrcweir     using namespace ::com::sun::star::sheet::ReferenceFlags;
394cdf0e10cSrcweir     setFlag( orApiRef.Flags, SHEET_RELATIVE, false );
395cdf0e10cSrcweir     setFlag( orApiRef.Flags, SHEET_3D, true );
396cdf0e10cSrcweir     orApiRef.Sheet = nCacheIdx;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir 
399cdf0e10cSrcweir } // namespace
400cdf0e10cSrcweir 
extractExternalReference(const ApiTokenSequence & rTokens)401cdf0e10cSrcweir void ExternalName::extractExternalReference( const ApiTokenSequence& rTokens )
402cdf0e10cSrcweir {
403cdf0e10cSrcweir     OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4), "ExternalName::setExternalReference - unexpected call" );
404cdf0e10cSrcweir     sal_Int32 nDocLinkIdx = mrParentLink.getDocumentLinkIndex();
405cdf0e10cSrcweir     sal_Int32 nCacheIdx = mrParentLink.getSheetCacheIndex();
406cdf0e10cSrcweir     if( (nDocLinkIdx >= 0) && (nCacheIdx >= 0) )
407cdf0e10cSrcweir     {
408cdf0e10cSrcweir         ExternalReference aExtApiRef;
409cdf0e10cSrcweir         aExtApiRef.Index = nDocLinkIdx;
410cdf0e10cSrcweir 
411cdf0e10cSrcweir         Any aRefAny = getFormulaParser().extractReference( rTokens );
412cdf0e10cSrcweir         if( aRefAny.has< SingleReference >() )
413cdf0e10cSrcweir         {
414cdf0e10cSrcweir             SingleReference aApiRef;
415cdf0e10cSrcweir             aRefAny >>= aApiRef;
416cdf0e10cSrcweir             lclSetSheetCacheIndex( aApiRef, nCacheIdx );
417cdf0e10cSrcweir             aExtApiRef.Reference <<= aApiRef;
418cdf0e10cSrcweir             maRefAny <<= aExtApiRef;
419cdf0e10cSrcweir         }
420cdf0e10cSrcweir         else if( aRefAny.has< ComplexReference >() )
421cdf0e10cSrcweir         {
422cdf0e10cSrcweir             ComplexReference aApiRef;
423cdf0e10cSrcweir             aRefAny >>= aApiRef;
424cdf0e10cSrcweir             lclSetSheetCacheIndex( aApiRef.Reference1, nCacheIdx );
425cdf0e10cSrcweir             lclSetSheetCacheIndex( aApiRef.Reference2, nCacheIdx );
426cdf0e10cSrcweir             aExtApiRef.Reference <<= aApiRef;
427cdf0e10cSrcweir             maRefAny <<= aExtApiRef;
428cdf0e10cSrcweir         }
429cdf0e10cSrcweir     }
430cdf0e10cSrcweir }
431cdf0e10cSrcweir 
setResultSize(sal_Int32 nColumns,sal_Int32 nRows)432cdf0e10cSrcweir void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows )
433cdf0e10cSrcweir {
434cdf0e10cSrcweir     OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) ||
435cdf0e10cSrcweir         (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" );
436cdf0e10cSrcweir     OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" );
437cdf0e10cSrcweir     const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
438cdf0e10cSrcweir     if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) )
439cdf0e10cSrcweir         maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) );
440cdf0e10cSrcweir     else
441cdf0e10cSrcweir         maResults.clear();
442cdf0e10cSrcweir     maCurrIt = maResults.begin();
443cdf0e10cSrcweir }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir // ============================================================================
446cdf0e10cSrcweir 
setDeleted()447cdf0e10cSrcweir void LinkSheetRange::setDeleted()
448cdf0e10cSrcweir {
449cdf0e10cSrcweir     meType = LINKSHEETRANGE_INTERNAL;
450cdf0e10cSrcweir     mnDocLink = mnFirst = mnLast = -1;
451cdf0e10cSrcweir }
452cdf0e10cSrcweir 
setSameSheet()453cdf0e10cSrcweir void LinkSheetRange::setSameSheet()
454cdf0e10cSrcweir {
455cdf0e10cSrcweir     meType = LINKSHEETRANGE_SAMESHEET;
456cdf0e10cSrcweir     mnDocLink = -1;
457cdf0e10cSrcweir     mnFirst = mnLast = 0;
458cdf0e10cSrcweir }
459cdf0e10cSrcweir 
setRange(sal_Int32 nFirst,sal_Int32 nLast)460cdf0e10cSrcweir void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
461cdf0e10cSrcweir {
462cdf0e10cSrcweir     meType = LINKSHEETRANGE_INTERNAL;
463cdf0e10cSrcweir     mnDocLink = -1;
464cdf0e10cSrcweir     mnFirst = ::std::min( nFirst, nLast );
465cdf0e10cSrcweir     mnLast = ::std::max( nFirst, nLast );
466cdf0e10cSrcweir }
467cdf0e10cSrcweir 
setExternalRange(sal_Int32 nDocLink,sal_Int32 nFirst,sal_Int32 nLast)468cdf0e10cSrcweir void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast )
469cdf0e10cSrcweir {
470cdf0e10cSrcweir     if( nDocLink < 0 )
471cdf0e10cSrcweir     {
472cdf0e10cSrcweir         setDeleted();
473cdf0e10cSrcweir     }
474cdf0e10cSrcweir     else
475cdf0e10cSrcweir     {
476cdf0e10cSrcweir         meType = LINKSHEETRANGE_EXTERNAL;
477cdf0e10cSrcweir         mnDocLink = nDocLink;
478cdf0e10cSrcweir         mnFirst = ::std::min( nFirst, nLast );
479cdf0e10cSrcweir         mnLast = ::std::max( nFirst, nLast );
480cdf0e10cSrcweir     }
481cdf0e10cSrcweir }
482cdf0e10cSrcweir 
483cdf0e10cSrcweir // ============================================================================
484cdf0e10cSrcweir 
ExternalLink(const WorkbookHelper & rHelper)485cdf0e10cSrcweir ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
486cdf0e10cSrcweir     WorkbookHelper( rHelper ),
487cdf0e10cSrcweir     meLinkType( LINKTYPE_UNKNOWN ),
488cdf0e10cSrcweir     meFuncLibType( FUNCLIB_UNKNOWN )
489cdf0e10cSrcweir {
490cdf0e10cSrcweir }
491cdf0e10cSrcweir 
importExternalReference(const AttributeList & rAttribs)492cdf0e10cSrcweir void ExternalLink::importExternalReference( const AttributeList& rAttribs )
493cdf0e10cSrcweir {
494cdf0e10cSrcweir     maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
495cdf0e10cSrcweir }
496cdf0e10cSrcweir 
importExternalBook(const Relations & rRelations,const AttributeList & rAttribs)497cdf0e10cSrcweir void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
498cdf0e10cSrcweir {
499cdf0e10cSrcweir     parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
500cdf0e10cSrcweir }
501cdf0e10cSrcweir 
importSheetName(const AttributeList & rAttribs)502cdf0e10cSrcweir void ExternalLink::importSheetName( const AttributeList& rAttribs )
503cdf0e10cSrcweir {
504cdf0e10cSrcweir     insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) );
505cdf0e10cSrcweir }
506cdf0e10cSrcweir 
importDefinedName(const AttributeList & rAttribs)507cdf0e10cSrcweir void ExternalLink::importDefinedName( const AttributeList& rAttribs )
508cdf0e10cSrcweir {
509cdf0e10cSrcweir     createExternalName()->importDefinedName( rAttribs );
510cdf0e10cSrcweir }
511cdf0e10cSrcweir 
importDdeLink(const AttributeList & rAttribs)512cdf0e10cSrcweir void ExternalLink::importDdeLink( const AttributeList& rAttribs )
513cdf0e10cSrcweir {
514cdf0e10cSrcweir     OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() );
515cdf0e10cSrcweir     OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() );
516cdf0e10cSrcweir     setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
517cdf0e10cSrcweir }
518cdf0e10cSrcweir 
importDdeItem(const AttributeList & rAttribs)519cdf0e10cSrcweir ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs )
520cdf0e10cSrcweir {
521cdf0e10cSrcweir     ExternalNameRef xExtName = createExternalName();
522cdf0e10cSrcweir     xExtName->importDdeItem( rAttribs );
523cdf0e10cSrcweir     return xExtName;
524cdf0e10cSrcweir }
525cdf0e10cSrcweir 
importOleLink(const Relations & rRelations,const AttributeList & rAttribs)526cdf0e10cSrcweir void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs )
527cdf0e10cSrcweir {
528cdf0e10cSrcweir     OUString aProgId = rAttribs.getXString( XML_progId, OUString() );
529cdf0e10cSrcweir     OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
530cdf0e10cSrcweir     setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
531cdf0e10cSrcweir }
532cdf0e10cSrcweir 
importOleItem(const AttributeList & rAttribs)533cdf0e10cSrcweir ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs )
534cdf0e10cSrcweir {
535cdf0e10cSrcweir     ExternalNameRef xExtName = createExternalName();
536cdf0e10cSrcweir     xExtName->importOleItem( rAttribs );
537cdf0e10cSrcweir     return xExtName;
538cdf0e10cSrcweir }
539cdf0e10cSrcweir 
importExternalRef(SequenceInputStream & rStrm)540cdf0e10cSrcweir void ExternalLink::importExternalRef( SequenceInputStream& rStrm )
541cdf0e10cSrcweir {
542cdf0e10cSrcweir     rStrm >> maRelId;
543cdf0e10cSrcweir }
544cdf0e10cSrcweir 
importExternalSelf(SequenceInputStream &)545cdf0e10cSrcweir void ExternalLink::importExternalSelf( SequenceInputStream& )
546cdf0e10cSrcweir {
547cdf0e10cSrcweir     meLinkType = LINKTYPE_SELF;
548cdf0e10cSrcweir }
549cdf0e10cSrcweir 
importExternalSame(SequenceInputStream &)550cdf0e10cSrcweir void ExternalLink::importExternalSame( SequenceInputStream& )
551cdf0e10cSrcweir {
552cdf0e10cSrcweir     meLinkType = LINKTYPE_SAME;
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
importExternalAddin(SequenceInputStream &)555cdf0e10cSrcweir void ExternalLink::importExternalAddin( SequenceInputStream& )
556cdf0e10cSrcweir {
557cdf0e10cSrcweir     meLinkType = LINKTYPE_UNKNOWN;
558cdf0e10cSrcweir }
559cdf0e10cSrcweir 
importExternalBook(const Relations & rRelations,SequenceInputStream & rStrm)560cdf0e10cSrcweir void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm )
561cdf0e10cSrcweir {
562cdf0e10cSrcweir     switch( rStrm.readuInt16() )
563cdf0e10cSrcweir     {
564cdf0e10cSrcweir         case BIFF12_EXTERNALBOOK_BOOK:
565cdf0e10cSrcweir             parseExternalReference( rRelations, BiffHelper::readString( rStrm ) );
566cdf0e10cSrcweir         break;
567cdf0e10cSrcweir         case BIFF12_EXTERNALBOOK_DDE:
568cdf0e10cSrcweir         {
569cdf0e10cSrcweir             OUString aDdeService, aDdeTopic;
570cdf0e10cSrcweir             rStrm >> aDdeService >> aDdeTopic;
571cdf0e10cSrcweir             setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
572cdf0e10cSrcweir         }
573cdf0e10cSrcweir         break;
574cdf0e10cSrcweir         case BIFF12_EXTERNALBOOK_OLE:
575cdf0e10cSrcweir         {
576cdf0e10cSrcweir             OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
577cdf0e10cSrcweir             OUString aProgId = BiffHelper::readString( rStrm );
578cdf0e10cSrcweir             setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
579cdf0e10cSrcweir         }
580cdf0e10cSrcweir         break;
581cdf0e10cSrcweir         default:
582cdf0e10cSrcweir             OSL_ENSURE( false, "ExternalLink::importExternalBook - unknown link type" );
583cdf0e10cSrcweir     }
584cdf0e10cSrcweir }
585cdf0e10cSrcweir 
importExtSheetNames(SequenceInputStream & rStrm)586cdf0e10cSrcweir void ExternalLink::importExtSheetNames( SequenceInputStream& rStrm )
587cdf0e10cSrcweir {
588cdf0e10cSrcweir     // load external sheet names and create the sheet caches in the Calc document
589cdf0e10cSrcweir     OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
590cdf0e10cSrcweir         "ExternalLink::importExtSheetNames - invalid link type" );
591cdf0e10cSrcweir     if( meLinkType == LINKTYPE_EXTERNAL )   // ignore sheets of external libraries
592cdf0e10cSrcweir         for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
593cdf0e10cSrcweir             insertExternalSheet( BiffHelper::readString( rStrm ) );
594cdf0e10cSrcweir }
595cdf0e10cSrcweir 
importExternalName(SequenceInputStream & rStrm)596cdf0e10cSrcweir ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& rStrm )
597cdf0e10cSrcweir {
598cdf0e10cSrcweir     ExternalNameRef xExtName = createExternalName();
599cdf0e10cSrcweir     xExtName->importExternalName( rStrm );
600cdf0e10cSrcweir     return xExtName;
601cdf0e10cSrcweir }
602cdf0e10cSrcweir 
importExternSheet(BiffInputStream & rStrm)603cdf0e10cSrcweir void ExternalLink::importExternSheet( BiffInputStream& rStrm )
604cdf0e10cSrcweir {
605cdf0e10cSrcweir     OStringBuffer aTargetBuffer( rStrm.readByteString( false, true ) );
606cdf0e10cSrcweir     // references to own sheets have wrong string length field (off by 1)
607cdf0e10cSrcweir     if( (aTargetBuffer.getLength() > 0) && (aTargetBuffer[ 0 ] == 3) )
608cdf0e10cSrcweir         aTargetBuffer.append( static_cast< sal_Char >( rStrm.readuInt8() ) );
609cdf0e10cSrcweir     // parse the encoded URL
610cdf0e10cSrcweir     OUString aBiffTarget = OStringToOUString( aTargetBuffer.makeStringAndClear(), getTextEncoding() );
611cdf0e10cSrcweir     OUString aSheetName = parseBiffTargetUrl( aBiffTarget );
612cdf0e10cSrcweir     switch( meLinkType )
613cdf0e10cSrcweir     {
614cdf0e10cSrcweir         case LINKTYPE_INTERNAL:
615cdf0e10cSrcweir             maCalcSheets.push_back( getWorksheets().getCalcSheetIndex( aSheetName ) );
616cdf0e10cSrcweir         break;
617cdf0e10cSrcweir         case LINKTYPE_EXTERNAL:
618cdf0e10cSrcweir             insertExternalSheet( (aSheetName.getLength() > 0) ? aSheetName : WorksheetBuffer::getBaseFileName( maTargetUrl ) );
619cdf0e10cSrcweir         break;
620cdf0e10cSrcweir         default:;
621cdf0e10cSrcweir     }
622cdf0e10cSrcweir }
623cdf0e10cSrcweir 
importExternalBook(BiffInputStream & rStrm)624cdf0e10cSrcweir void ExternalLink::importExternalBook( BiffInputStream& rStrm )
625cdf0e10cSrcweir {
626cdf0e10cSrcweir     OUString aTarget;
627cdf0e10cSrcweir     sal_uInt16 nSheetCount;
628cdf0e10cSrcweir     rStrm >> nSheetCount;
629cdf0e10cSrcweir     if( rStrm.getRemaining() == 2 )
630cdf0e10cSrcweir     {
631cdf0e10cSrcweir         if( rStrm.readuInt8() == 1 )
632cdf0e10cSrcweir         {
633cdf0e10cSrcweir             sal_Char cChar = static_cast< sal_Char >( rStrm.readuInt8() );
634cdf0e10cSrcweir             if( cChar != 0 )
635cdf0e10cSrcweir                 aTarget = OStringToOUString( OString( cChar ), getTextEncoding() );
636cdf0e10cSrcweir         }
637cdf0e10cSrcweir     }
638cdf0e10cSrcweir     else if( rStrm.getRemaining() >= 3 )
639cdf0e10cSrcweir     {
640cdf0e10cSrcweir         // NUL characters may occur
641cdf0e10cSrcweir         aTarget = rStrm.readUniString( true );
642cdf0e10cSrcweir     }
643cdf0e10cSrcweir 
644cdf0e10cSrcweir     // parse the encoded URL
645cdf0e10cSrcweir     OUString aDummySheetName = parseBiffTargetUrl( aTarget );
646cdf0e10cSrcweir     OSL_ENSURE( aDummySheetName.getLength() == 0, "ExternalLink::importExternalBook - sheet name in encoded URL" );
647cdf0e10cSrcweir     (void)aDummySheetName;  // prevent compiler warning
648cdf0e10cSrcweir 
649cdf0e10cSrcweir     // load external sheet names and create the sheet caches in the Calc document
650cdf0e10cSrcweir     if( meLinkType == LINKTYPE_EXTERNAL )
651cdf0e10cSrcweir         for( sal_uInt16 nSheet = 0; !rStrm.isEof() && (nSheet < nSheetCount); ++nSheet )
652cdf0e10cSrcweir             insertExternalSheet( rStrm.readUniString() );
653cdf0e10cSrcweir }
654cdf0e10cSrcweir 
importExternalName(BiffInputStream & rStrm)655cdf0e10cSrcweir void ExternalLink::importExternalName( BiffInputStream& rStrm )
656cdf0e10cSrcweir {
657cdf0e10cSrcweir     ExternalNameRef xExtName = createExternalName();
658cdf0e10cSrcweir     xExtName->importExternalName( rStrm );
659cdf0e10cSrcweir     switch( meLinkType )
660cdf0e10cSrcweir     {
661cdf0e10cSrcweir         case LINKTYPE_DDE:
662cdf0e10cSrcweir             OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in DDE link" );
663cdf0e10cSrcweir         break;
664cdf0e10cSrcweir         case LINKTYPE_OLE:
665cdf0e10cSrcweir             OSL_ENSURE( xExtName->isOleObject(), "ExternalLink::importExternalName - anything but OLE object in OLE link" );
666cdf0e10cSrcweir         break;
667cdf0e10cSrcweir         case LINKTYPE_MAYBE_DDE_OLE:
668cdf0e10cSrcweir             meLinkType = xExtName->isOleObject() ? LINKTYPE_OLE : LINKTYPE_DDE;
669cdf0e10cSrcweir         break;
670cdf0e10cSrcweir         default:
671cdf0e10cSrcweir             OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in external name" );
672cdf0e10cSrcweir     }
673cdf0e10cSrcweir }
674cdf0e10cSrcweir 
getLinkInfo() const675cdf0e10cSrcweir ExternalLinkInfo ExternalLink::getLinkInfo() const
676cdf0e10cSrcweir {
677cdf0e10cSrcweir     ExternalLinkInfo aLinkInfo;
678cdf0e10cSrcweir     switch( meLinkType )
679cdf0e10cSrcweir     {
680cdf0e10cSrcweir         case LINKTYPE_SELF:
681cdf0e10cSrcweir         case LINKTYPE_SAME:
682cdf0e10cSrcweir         case LINKTYPE_INTERNAL:
683cdf0e10cSrcweir             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF;
684cdf0e10cSrcweir         break;
685cdf0e10cSrcweir         case LINKTYPE_EXTERNAL:
686cdf0e10cSrcweir             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
687cdf0e10cSrcweir             aLinkInfo.Data <<= maTargetUrl;
688cdf0e10cSrcweir         break;
689cdf0e10cSrcweir         case LINKTYPE_LIBRARY:
690cdf0e10cSrcweir             // parser will return library function names in OPCODE_BAD string tokens
691cdf0e10cSrcweir             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL;
692cdf0e10cSrcweir         break;
693cdf0e10cSrcweir         case LINKTYPE_DDE:
694cdf0e10cSrcweir         {
695cdf0e10cSrcweir             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE;
696cdf0e10cSrcweir             DDELinkInfo aDdeLinkInfo;
697cdf0e10cSrcweir             aDdeLinkInfo.Service = maClassName;
698cdf0e10cSrcweir             aDdeLinkInfo.Topic = maTargetUrl;
699cdf0e10cSrcweir             ::std::vector< DDEItemInfo > aItemInfos;
700cdf0e10cSrcweir             DDEItemInfo aItemInfo;
701cdf0e10cSrcweir             for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt )
702cdf0e10cSrcweir                 if( (*aIt)->getDdeItemInfo( aItemInfo ) )
703cdf0e10cSrcweir                     aItemInfos.push_back( aItemInfo );
704cdf0e10cSrcweir             aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos );
705cdf0e10cSrcweir             aLinkInfo.Data <<= aDdeLinkInfo;
706cdf0e10cSrcweir         }
707cdf0e10cSrcweir         break;
708cdf0e10cSrcweir         default:
709cdf0e10cSrcweir             aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN;
710cdf0e10cSrcweir     }
711cdf0e10cSrcweir     return aLinkInfo;
712cdf0e10cSrcweir }
713cdf0e10cSrcweir 
getFuncLibraryType() const714cdf0e10cSrcweir FunctionLibraryType ExternalLink::getFuncLibraryType() const
715cdf0e10cSrcweir {
716cdf0e10cSrcweir     return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
717cdf0e10cSrcweir }
718cdf0e10cSrcweir 
getCalcSheetIndex(sal_Int32 nTabId) const719cdf0e10cSrcweir sal_Int16 ExternalLink::getCalcSheetIndex( sal_Int32 nTabId ) const
720cdf0e10cSrcweir {
721cdf0e10cSrcweir     OSL_ENSURE( meLinkType == LINKTYPE_INTERNAL, "ExternalLink::getCalcSheetIndex - invalid link type" );
722cdf0e10cSrcweir     OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
723cdf0e10cSrcweir         "ExternalLink::getCalcSheetIndex - invalid sheet index" );
724cdf0e10cSrcweir     return ContainerHelper::getVectorElement( maCalcSheets, nTabId, -1 );
725cdf0e10cSrcweir }
726cdf0e10cSrcweir 
getDocumentLinkIndex() const727cdf0e10cSrcweir sal_Int32 ExternalLink::getDocumentLinkIndex() const
728cdf0e10cSrcweir {
729cdf0e10cSrcweir     OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" );
730cdf0e10cSrcweir     return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1;
731cdf0e10cSrcweir }
732cdf0e10cSrcweir 
getSheetCacheIndex(sal_Int32 nTabId) const733cdf0e10cSrcweir sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const
734cdf0e10cSrcweir {
735cdf0e10cSrcweir     OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" );
736cdf0e10cSrcweir     OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
737cdf0e10cSrcweir         "ExternalLink::getSheetCacheIndex - invalid sheet index" );
738cdf0e10cSrcweir     return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 );
739cdf0e10cSrcweir }
740cdf0e10cSrcweir 
getSheetCache(sal_Int32 nTabId) const741cdf0e10cSrcweir Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const
742cdf0e10cSrcweir {
743cdf0e10cSrcweir     sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId );
744cdf0e10cSrcweir     if( mxDocLink.is() && (nCacheIdx >= 0) ) try
745cdf0e10cSrcweir     {
746cdf0e10cSrcweir         // existing mxDocLink implies that this is an external link
747cdf0e10cSrcweir         Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW );
748cdf0e10cSrcweir         return xSheetCache;
749cdf0e10cSrcweir     }
750cdf0e10cSrcweir     catch( Exception& )
751cdf0e10cSrcweir     {
752cdf0e10cSrcweir     }
753cdf0e10cSrcweir     return 0;
754cdf0e10cSrcweir }
755cdf0e10cSrcweir 
getSheetRange(LinkSheetRange & orSheetRange,sal_Int32 nTabId1,sal_Int32 nTabId2) const756cdf0e10cSrcweir void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
757cdf0e10cSrcweir {
758cdf0e10cSrcweir     switch( meLinkType )
759cdf0e10cSrcweir     {
760cdf0e10cSrcweir         case LINKTYPE_SAME:
761cdf0e10cSrcweir             orSheetRange.setSameSheet();
762cdf0e10cSrcweir         break;
763cdf0e10cSrcweir 
764cdf0e10cSrcweir         case LINKTYPE_SELF:
765cdf0e10cSrcweir         case LINKTYPE_INTERNAL:
766cdf0e10cSrcweir             orSheetRange.setRange( nTabId1, nTabId2 );
767cdf0e10cSrcweir         break;
768cdf0e10cSrcweir 
769cdf0e10cSrcweir         case LINKTYPE_EXTERNAL:
770cdf0e10cSrcweir         {
771cdf0e10cSrcweir             sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
772cdf0e10cSrcweir             switch( getFilterType() )
773cdf0e10cSrcweir             {
774cdf0e10cSrcweir                 case FILTER_OOXML:
775cdf0e10cSrcweir                     // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
776cdf0e10cSrcweir                     orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
777cdf0e10cSrcweir                 break;
778cdf0e10cSrcweir                 case FILTER_BIFF:
779cdf0e10cSrcweir                     switch( getBiff() )
780cdf0e10cSrcweir                     {
781cdf0e10cSrcweir                         case BIFF2:
782cdf0e10cSrcweir                         case BIFF3:
783cdf0e10cSrcweir                         case BIFF4:
784cdf0e10cSrcweir                             orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
785cdf0e10cSrcweir                         break;
786cdf0e10cSrcweir                         case BIFF5:
787cdf0e10cSrcweir                             // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
788cdf0e10cSrcweir                             if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() )
789cdf0e10cSrcweir                                 if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) )
790cdf0e10cSrcweir                                     orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() );
791cdf0e10cSrcweir                         break;
792cdf0e10cSrcweir                         case BIFF8:
793cdf0e10cSrcweir                             // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
794cdf0e10cSrcweir                             orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
795cdf0e10cSrcweir                         break;
796cdf0e10cSrcweir                         case BIFF_UNKNOWN: break;
797cdf0e10cSrcweir                     }
798cdf0e10cSrcweir                 break;
799cdf0e10cSrcweir                 case FILTER_UNKNOWN: break;
800cdf0e10cSrcweir             }
801cdf0e10cSrcweir         }
802cdf0e10cSrcweir         break;
803cdf0e10cSrcweir 
804cdf0e10cSrcweir         default:
805cdf0e10cSrcweir             // unsupported/unexpected link type: #REF! error
806cdf0e10cSrcweir             orSheetRange.setDeleted();
807cdf0e10cSrcweir     }
808cdf0e10cSrcweir }
809cdf0e10cSrcweir 
getNameByIndex(sal_Int32 nIndex) const810cdf0e10cSrcweir ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
811cdf0e10cSrcweir {
812cdf0e10cSrcweir     return maExtNames.get( nIndex );
813cdf0e10cSrcweir }
814cdf0e10cSrcweir 
815cdf0e10cSrcweir // private --------------------------------------------------------------------
816cdf0e10cSrcweir 
817cdf0e10cSrcweir #define OOX_TARGETTYPE_EXTLINK      CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" )
818cdf0e10cSrcweir #define OOX_TARGETTYPE_LIBRARY      CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" )
819cdf0e10cSrcweir 
setExternalTargetUrl(const OUString & rTargetUrl,const OUString & rTargetType)820cdf0e10cSrcweir void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
821cdf0e10cSrcweir {
822cdf0e10cSrcweir     meLinkType = LINKTYPE_UNKNOWN;
823cdf0e10cSrcweir     if( rTargetType == OOX_TARGETTYPE_EXTLINK )
824cdf0e10cSrcweir     {
825cdf0e10cSrcweir         maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
826cdf0e10cSrcweir         if( maTargetUrl.getLength() > 0 )
827cdf0e10cSrcweir             meLinkType = LINKTYPE_EXTERNAL;
828cdf0e10cSrcweir     }
829cdf0e10cSrcweir     else if( rTargetType == OOX_TARGETTYPE_LIBRARY )
830cdf0e10cSrcweir     {
831cdf0e10cSrcweir         meLinkType = LINKTYPE_LIBRARY;
832cdf0e10cSrcweir         meFuncLibType = getFormulaParser().getFuncLibTypeFromLibraryName( rTargetUrl );
833cdf0e10cSrcweir     }
834cdf0e10cSrcweir     OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
835cdf0e10cSrcweir 
836cdf0e10cSrcweir     // create the external document link API object that will contain the sheet caches
837cdf0e10cSrcweir     if( meLinkType == LINKTYPE_EXTERNAL ) try
838cdf0e10cSrcweir     {
839cdf0e10cSrcweir         PropertySet aDocProps( getDocument() );
840cdf0e10cSrcweir         Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW );
841cdf0e10cSrcweir         mxDocLink = xDocLinks->addDocLink( maTargetUrl );
842cdf0e10cSrcweir     }
843cdf0e10cSrcweir     catch( Exception& )
844cdf0e10cSrcweir     {
845cdf0e10cSrcweir     }
846cdf0e10cSrcweir }
847cdf0e10cSrcweir 
setDdeOleTargetUrl(const OUString & rClassName,const OUString & rTargetUrl,ExternalLinkType eLinkType)848cdf0e10cSrcweir void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType )
849cdf0e10cSrcweir {
850cdf0e10cSrcweir     maClassName = rClassName;
851cdf0e10cSrcweir     maTargetUrl = rTargetUrl;
852cdf0e10cSrcweir     meLinkType = ((maClassName.getLength() > 0) && (maTargetUrl.getLength() > 0)) ? eLinkType : LINKTYPE_UNKNOWN;
853cdf0e10cSrcweir     OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
854cdf0e10cSrcweir }
855cdf0e10cSrcweir 
parseExternalReference(const Relations & rRelations,const OUString & rRelId)856cdf0e10cSrcweir void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
857cdf0e10cSrcweir {
858cdf0e10cSrcweir     if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
859cdf0e10cSrcweir         setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
860cdf0e10cSrcweir }
861cdf0e10cSrcweir 
parseBiffTargetUrl(const OUString & rBiffTargetUrl)862cdf0e10cSrcweir OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl )
863cdf0e10cSrcweir {
864cdf0e10cSrcweir     meLinkType = LINKTYPE_UNKNOWN;
865cdf0e10cSrcweir 
866cdf0e10cSrcweir     OUString aClassName, aTargetUrl, aSheetName;
867cdf0e10cSrcweir     switch( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) )
868cdf0e10cSrcweir     {
869cdf0e10cSrcweir         case BIFF_TARGETTYPE_URL:
870cdf0e10cSrcweir             if( aTargetUrl.getLength() == 0 )
871cdf0e10cSrcweir             {
872cdf0e10cSrcweir                 meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF;
873cdf0e10cSrcweir             }
874cdf0e10cSrcweir             else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') )
875cdf0e10cSrcweir             {
876cdf0e10cSrcweir                 if( getBiff() >= BIFF4 )
877cdf0e10cSrcweir                     meLinkType = LINKTYPE_ANALYSIS;
878cdf0e10cSrcweir             }
879cdf0e10cSrcweir             else if( (aTargetUrl.getLength() > 1) || (aTargetUrl[ 0 ] != ' ') )
880cdf0e10cSrcweir             {
881cdf0e10cSrcweir                 setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_EXTLINK );
882cdf0e10cSrcweir             }
883cdf0e10cSrcweir         break;
884cdf0e10cSrcweir 
885cdf0e10cSrcweir         case BIFF_TARGETTYPE_SAMESHEET:
886cdf0e10cSrcweir             OSL_ENSURE( (aTargetUrl.getLength() == 0) && (aSheetName.getLength() == 0), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" );
887cdf0e10cSrcweir             meLinkType = LINKTYPE_SAME;
888cdf0e10cSrcweir         break;
889cdf0e10cSrcweir 
890cdf0e10cSrcweir         case BIFF_TARGETTYPE_LIBRARY:
891cdf0e10cSrcweir             OSL_ENSURE( aSheetName.getLength() == 0, "ExternalLink::parseBiffTargetUrl - unexpected sheet name" );
892cdf0e10cSrcweir             setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_LIBRARY );
893cdf0e10cSrcweir         break;
894cdf0e10cSrcweir 
895cdf0e10cSrcweir         case BIFF_TARGETTYPE_DDE_OLE:
896cdf0e10cSrcweir             setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE );
897cdf0e10cSrcweir         break;
898cdf0e10cSrcweir 
899cdf0e10cSrcweir         case BIFF_TARGETTYPE_UNKNOWN:
900cdf0e10cSrcweir         break;
901cdf0e10cSrcweir     }
902cdf0e10cSrcweir     return aSheetName;
903cdf0e10cSrcweir }
904cdf0e10cSrcweir 
insertExternalSheet(const OUString & rSheetName)905cdf0e10cSrcweir void ExternalLink::insertExternalSheet( const OUString& rSheetName )
906cdf0e10cSrcweir {
907cdf0e10cSrcweir     OSL_ENSURE( rSheetName.getLength() > 0, "ExternalLink::insertExternalSheet - empty sheet name" );
908cdf0e10cSrcweir     if( mxDocLink.is() )
909cdf0e10cSrcweir     {
910cdf0e10cSrcweir         Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false );
911cdf0e10cSrcweir         sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1;
912cdf0e10cSrcweir         maSheetCaches.push_back( nCacheIdx );
913cdf0e10cSrcweir     }
914cdf0e10cSrcweir }
915cdf0e10cSrcweir 
createExternalName()916cdf0e10cSrcweir ExternalNameRef ExternalLink::createExternalName()
917cdf0e10cSrcweir {
918cdf0e10cSrcweir     ExternalNameRef xExtName( new ExternalName( *this ) );
919cdf0e10cSrcweir     maExtNames.push_back( xExtName );
920cdf0e10cSrcweir     return xExtName;
921cdf0e10cSrcweir }
922cdf0e10cSrcweir 
923cdf0e10cSrcweir // ============================================================================
924cdf0e10cSrcweir 
RefSheetsModel()925cdf0e10cSrcweir RefSheetsModel::RefSheetsModel() :
926cdf0e10cSrcweir     mnExtRefId( -1 ),
927cdf0e10cSrcweir     mnTabId1( -1 ),
928cdf0e10cSrcweir     mnTabId2( -1 )
929cdf0e10cSrcweir {
930cdf0e10cSrcweir }
931cdf0e10cSrcweir 
readBiff12Data(SequenceInputStream & rStrm)932cdf0e10cSrcweir void RefSheetsModel::readBiff12Data( SequenceInputStream& rStrm )
933cdf0e10cSrcweir {
934cdf0e10cSrcweir     rStrm >> mnExtRefId >> mnTabId1 >> mnTabId2;
935cdf0e10cSrcweir }
936cdf0e10cSrcweir 
readBiff8Data(BiffInputStream & rStrm)937cdf0e10cSrcweir void RefSheetsModel::readBiff8Data( BiffInputStream& rStrm )
938cdf0e10cSrcweir {
939cdf0e10cSrcweir     mnExtRefId = rStrm.readuInt16();
940cdf0e10cSrcweir     mnTabId1 = rStrm.readInt16();
941cdf0e10cSrcweir     mnTabId2 = rStrm.readInt16();
942cdf0e10cSrcweir }
943cdf0e10cSrcweir 
944cdf0e10cSrcweir // ----------------------------------------------------------------------------
945cdf0e10cSrcweir 
ExternalLinkBuffer(const WorkbookHelper & rHelper)946cdf0e10cSrcweir ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) :
947cdf0e10cSrcweir     WorkbookHelper( rHelper ),
948cdf0e10cSrcweir     mxSelfRef( new ExternalLink( rHelper ) ),
949cdf0e10cSrcweir     mbUseRefSheets( false )
950cdf0e10cSrcweir {
951cdf0e10cSrcweir     mxSelfRef->setSelfLinkType();
952cdf0e10cSrcweir }
953cdf0e10cSrcweir 
importExternalReference(const AttributeList & rAttribs)954cdf0e10cSrcweir ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs )
955cdf0e10cSrcweir {
956cdf0e10cSrcweir     ExternalLinkRef xExtLink = createExternalLink();
957cdf0e10cSrcweir     xExtLink->importExternalReference( rAttribs );
958cdf0e10cSrcweir     maExtLinks.push_back( xExtLink );
959cdf0e10cSrcweir     return xExtLink;
960cdf0e10cSrcweir }
961cdf0e10cSrcweir 
importExternalRef(SequenceInputStream & rStrm)962cdf0e10cSrcweir ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir     mbUseRefSheets = true;
965cdf0e10cSrcweir     ExternalLinkRef xExtLink = createExternalLink();
966cdf0e10cSrcweir     xExtLink->importExternalRef( rStrm );
967cdf0e10cSrcweir     maExtLinks.push_back( xExtLink );
968cdf0e10cSrcweir     return xExtLink;
969cdf0e10cSrcweir }
970cdf0e10cSrcweir 
importExternalSelf(SequenceInputStream & rStrm)971cdf0e10cSrcweir void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm )
972cdf0e10cSrcweir {
973cdf0e10cSrcweir     mbUseRefSheets = true;
974cdf0e10cSrcweir     createExternalLink()->importExternalSelf( rStrm );
975cdf0e10cSrcweir }
976cdf0e10cSrcweir 
importExternalSame(SequenceInputStream & rStrm)977cdf0e10cSrcweir void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm )
978cdf0e10cSrcweir {
979cdf0e10cSrcweir     mbUseRefSheets = true;
980cdf0e10cSrcweir     createExternalLink()->importExternalSame( rStrm );
981cdf0e10cSrcweir }
982cdf0e10cSrcweir 
importExternalAddin(SequenceInputStream & rStrm)983cdf0e10cSrcweir void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir     mbUseRefSheets = true;
986cdf0e10cSrcweir     createExternalLink()->importExternalAddin( rStrm );
987cdf0e10cSrcweir }
988cdf0e10cSrcweir 
importExternalSheets(SequenceInputStream & rStrm)989cdf0e10cSrcweir void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& rStrm )
990cdf0e10cSrcweir {
991cdf0e10cSrcweir     OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
992cdf0e10cSrcweir     mbUseRefSheets = true;
993cdf0e10cSrcweir     OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
994cdf0e10cSrcweir     maRefSheets.clear();
995cdf0e10cSrcweir     sal_Int32 nRefCount;
996cdf0e10cSrcweir     rStrm >> nRefCount;
997cdf0e10cSrcweir     size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 );
998cdf0e10cSrcweir     maRefSheets.reserve( nMaxCount );
999cdf0e10cSrcweir     for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId )
1000cdf0e10cSrcweir     {
1001cdf0e10cSrcweir         RefSheetsModel aRefSheets;
1002cdf0e10cSrcweir         aRefSheets.readBiff12Data( rStrm );
1003cdf0e10cSrcweir         maRefSheets.push_back( aRefSheets );
1004cdf0e10cSrcweir     }
1005cdf0e10cSrcweir }
1006cdf0e10cSrcweir 
importExternSheet(BiffInputStream & rStrm)1007cdf0e10cSrcweir ExternalLinkRef ExternalLinkBuffer::importExternSheet( BiffInputStream& rStrm )
1008cdf0e10cSrcweir {
1009cdf0e10cSrcweir     OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::importExternSheet - wrong BIFF version" );
1010cdf0e10cSrcweir     ExternalLinkRef xExtLink = createExternalLink();
1011cdf0e10cSrcweir     xExtLink->importExternSheet( rStrm );
1012cdf0e10cSrcweir     return xExtLink;
1013cdf0e10cSrcweir }
1014cdf0e10cSrcweir 
importExternalBook(BiffInputStream & rStrm)1015cdf0e10cSrcweir ExternalLinkRef ExternalLinkBuffer::importExternalBook( BiffInputStream& rStrm )
1016cdf0e10cSrcweir {
1017cdf0e10cSrcweir     ExternalLinkRef xExtLink = createExternalLink();
1018cdf0e10cSrcweir     xExtLink->importExternalBook( rStrm );
1019cdf0e10cSrcweir     return xExtLink;
1020cdf0e10cSrcweir }
1021cdf0e10cSrcweir 
importExternalName(BiffInputStream & rStrm)1022cdf0e10cSrcweir void ExternalLinkBuffer::importExternalName( BiffInputStream& rStrm )
1023cdf0e10cSrcweir {
1024cdf0e10cSrcweir     if( !maLinks.empty() )
1025cdf0e10cSrcweir         maLinks.back()->importExternalName( rStrm );
1026cdf0e10cSrcweir }
1027cdf0e10cSrcweir 
importExternSheet8(BiffInputStream & rStrm)1028cdf0e10cSrcweir void ExternalLinkBuffer::importExternSheet8( BiffInputStream& rStrm )
1029cdf0e10cSrcweir {
1030cdf0e10cSrcweir     OSL_ENSURE( getBiff() == BIFF8, "ExternalLinkBuffer::importExternSheet8 - wrong BIFF version" );
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir     sal_uInt16 nRefCount;
1033cdf0e10cSrcweir     rStrm >> nRefCount;
1034cdf0e10cSrcweir     OSL_ENSURE( static_cast< sal_Int64 >( nRefCount * 6 ) == rStrm.getRemaining(), "ExternalLinkBuffer::importExternSheet8 - invalid count" );
1035cdf0e10cSrcweir     nRefCount = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nRefCount, rStrm.getRemaining() / 6 ) );
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir     /*  #i104057# A weird external XLS generator writes multiple EXTERNSHEET
1038cdf0e10cSrcweir         records instead of only one as expected. Surprisingly, Excel seems to
1039cdf0e10cSrcweir         insert the entries of the second record before the entries of the first
1040cdf0e10cSrcweir         record. */
1041cdf0e10cSrcweir     maRefSheets.insert( maRefSheets.begin(), nRefCount, RefSheetsModel() );
1042cdf0e10cSrcweir     for( RefSheetsModelVec::iterator aIt = maRefSheets.begin(), aEnd = aIt + nRefCount; !rStrm.isEof() && (aIt != aEnd); ++aIt )
1043cdf0e10cSrcweir         aIt->readBiff8Data( rStrm );
1044cdf0e10cSrcweir }
1045cdf0e10cSrcweir 
getLinkInfos() const1046cdf0e10cSrcweir Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const
1047cdf0e10cSrcweir {
1048cdf0e10cSrcweir     ::std::vector< ExternalLinkInfo > aLinkInfos;
1049cdf0e10cSrcweir     // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
1050cdf0e10cSrcweir     OSL_ENSURE( getFilterType() == FILTER_OOXML, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
1051cdf0e10cSrcweir     // add entry for implicit index 0 (self reference to this document)
1052cdf0e10cSrcweir     aLinkInfos.push_back( mxSelfRef->getLinkInfo() );
1053cdf0e10cSrcweir     for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt )
1054cdf0e10cSrcweir         aLinkInfos.push_back( (*aIt)->getLinkInfo() );
1055cdf0e10cSrcweir     return ContainerHelper::vectorToSequence( aLinkInfos );
1056cdf0e10cSrcweir }
1057cdf0e10cSrcweir 
getExternalLink(sal_Int32 nRefId,bool bUseRefSheets) const1058cdf0e10cSrcweir ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId, bool bUseRefSheets ) const
1059cdf0e10cSrcweir {
1060cdf0e10cSrcweir     ExternalLinkRef xExtLink;
1061cdf0e10cSrcweir     switch( getFilterType() )
1062cdf0e10cSrcweir     {
1063cdf0e10cSrcweir         case FILTER_OOXML:
1064cdf0e10cSrcweir             // OOXML: 0 = this document, otherwise one-based index into link list
1065cdf0e10cSrcweir             if( !bUseRefSheets || !mbUseRefSheets )
1066cdf0e10cSrcweir                 xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 );
1067cdf0e10cSrcweir             // BIFF12: zero-based index into ref-sheets list
1068cdf0e10cSrcweir             else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
1069cdf0e10cSrcweir                 xExtLink = maLinks.get( pRefSheets->mnExtRefId );
1070cdf0e10cSrcweir         break;
1071cdf0e10cSrcweir         case FILTER_BIFF:
1072cdf0e10cSrcweir             switch( getBiff() )
1073cdf0e10cSrcweir             {
1074cdf0e10cSrcweir                 case BIFF2:
1075cdf0e10cSrcweir                 case BIFF3:
1076cdf0e10cSrcweir                 case BIFF4:
1077cdf0e10cSrcweir                     // one-based index to EXTERNSHEET records
1078cdf0e10cSrcweir                     xExtLink = maLinks.get( nRefId - 1 );
1079cdf0e10cSrcweir                 break;
1080cdf0e10cSrcweir                 case BIFF5:
1081cdf0e10cSrcweir                     if( nRefId < 0 )
1082cdf0e10cSrcweir                     {
1083cdf0e10cSrcweir                         // internal links in formula tokens have negative index
1084cdf0e10cSrcweir                         xExtLink = maLinks.get( -nRefId - 1 );
1085cdf0e10cSrcweir                         if( xExtLink.get() && !xExtLink->isInternalLink() )
1086cdf0e10cSrcweir                             xExtLink.reset();
1087cdf0e10cSrcweir                     }
1088cdf0e10cSrcweir                     else
1089cdf0e10cSrcweir                     {
1090cdf0e10cSrcweir                         // one-based index to EXTERNSHEET records
1091cdf0e10cSrcweir                         xExtLink = maLinks.get( nRefId - 1 );
1092cdf0e10cSrcweir                     }
1093cdf0e10cSrcweir                 break;
1094cdf0e10cSrcweir                 case BIFF8:
1095cdf0e10cSrcweir                     // zero-based index into REF list in EXTERNSHEET record
1096cdf0e10cSrcweir                     if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
1097cdf0e10cSrcweir                         xExtLink = maLinks.get( pRefSheets->mnExtRefId );
1098cdf0e10cSrcweir                 break;
1099cdf0e10cSrcweir                 case BIFF_UNKNOWN: break;
1100cdf0e10cSrcweir             }
1101cdf0e10cSrcweir         break;
1102cdf0e10cSrcweir         case FILTER_UNKNOWN: break;
1103cdf0e10cSrcweir     }
1104cdf0e10cSrcweir     return xExtLink;
1105cdf0e10cSrcweir }
1106cdf0e10cSrcweir 
getSheetRange(sal_Int32 nRefId,sal_Int16 nTabId1,sal_Int16 nTabId2) const1107cdf0e10cSrcweir LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const
1108cdf0e10cSrcweir {
1109cdf0e10cSrcweir     OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
1110cdf0e10cSrcweir     LinkSheetRange aSheetRange;
1111cdf0e10cSrcweir     if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
1112cdf0e10cSrcweir         pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 );
1113cdf0e10cSrcweir     return aSheetRange;
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir 
getSheetRange(sal_Int32 nRefId) const1116cdf0e10cSrcweir LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const
1117cdf0e10cSrcweir {
1118cdf0e10cSrcweir     OSL_ENSURE( ((getFilterType() == FILTER_OOXML) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
1119cdf0e10cSrcweir     LinkSheetRange aSheetRange;
1120cdf0e10cSrcweir     if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
1121cdf0e10cSrcweir         if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
1122cdf0e10cSrcweir             pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 );
1123cdf0e10cSrcweir     return aSheetRange;
1124cdf0e10cSrcweir }
1125cdf0e10cSrcweir 
1126cdf0e10cSrcweir // private --------------------------------------------------------------------
1127cdf0e10cSrcweir 
createExternalLink()1128cdf0e10cSrcweir ExternalLinkRef ExternalLinkBuffer::createExternalLink()
1129cdf0e10cSrcweir {
1130cdf0e10cSrcweir     ExternalLinkRef xExtLink( new ExternalLink( *this ) );
1131cdf0e10cSrcweir     maLinks.push_back( xExtLink );
1132cdf0e10cSrcweir     return xExtLink;
1133cdf0e10cSrcweir }
1134cdf0e10cSrcweir 
getRefSheets(sal_Int32 nRefId) const1135cdf0e10cSrcweir const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const
1136cdf0e10cSrcweir {
1137cdf0e10cSrcweir     return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ?
1138cdf0e10cSrcweir         &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0;
1139cdf0e10cSrcweir }
1140cdf0e10cSrcweir 
1141cdf0e10cSrcweir // ============================================================================
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir } // namespace xls
1144cdf0e10cSrcweir } // namespace oox
1145