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