fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / oox / externallinkbuffer.cxx
blob896c898307b07fe8bc847e6dc981b14f76f521d5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "externallinkbuffer.hxx"
22 #include <com/sun/star/sheet/ComplexReference.hpp>
23 #include <com/sun/star/sheet/DDELinkInfo.hpp>
24 #include <com/sun/star/sheet/ExternalLinkType.hpp>
25 #include <com/sun/star/sheet/ExternalReference.hpp>
26 #include <com/sun/star/sheet/ReferenceFlags.hpp>
27 #include <com/sun/star/sheet/SingleReference.hpp>
28 #include <com/sun/star/sheet/XDDELinks.hpp>
29 #include <com/sun/star/sheet/XDDELink.hpp>
30 #include <com/sun/star/sheet/XDDELinkResults.hpp>
31 #include <com/sun/star/sheet/XExternalDocLink.hpp>
32 #include <com/sun/star/sheet/XExternalDocLinks.hpp>
33 #include <osl/diagnose.h>
34 #include <rtl/strbuf.hxx>
35 #include <oox/core/filterbase.hxx>
36 #include <oox/helper/attributelist.hxx>
37 #include <oox/token/properties.hxx>
38 #include "addressconverter.hxx"
39 #include "biffinputstream.hxx"
40 #include "excelhandlers.hxx"
41 #include "formulaparser.hxx"
42 #include "worksheetbuffer.hxx"
44 namespace oox {
45 namespace xls {
47 using namespace ::com::sun::star::sheet;
48 using namespace ::com::sun::star::table;
49 using namespace ::com::sun::star::uno;
51 using ::oox::core::Relation;
52 using ::oox::core::Relations;
54 namespace {
56 const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK = 0;
57 const sal_uInt16 BIFF12_EXTERNALBOOK_DDE = 1;
58 const sal_uInt16 BIFF12_EXTERNALBOOK_OLE = 2;
60 const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC = 0x0002;
61 const sal_uInt16 BIFF12_EXTNAME_PREFERPIC = 0x0004;
62 const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME = 0x0008;
63 const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT = 0x0010;
64 const sal_uInt16 BIFF12_EXTNAME_ICONIFIED = 0x0020;
66 } // namespace
68 ExternalNameModel::ExternalNameModel() :
69 mbBuiltIn( false ),
70 mbNotify( false ),
71 mbPreferPic( false ),
72 mbStdDocName( false ),
73 mbOleObj( false ),
74 mbIconified( false )
78 ExternalName::ExternalName( const ExternalLink& rParentLink ) :
79 DefinedNameBase( rParentLink ),
80 mrParentLink( rParentLink ),
81 mbDdeLinkCreated( false )
85 void ExternalName::importDefinedName( const AttributeList& rAttribs )
87 maModel.maName = rAttribs.getXString( XML_name, OUString() );
88 OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDefinedName - empty name" );
89 // zero-based index into sheet list of externalBook
90 maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 );
93 void ExternalName::importDdeItem( const AttributeList& rAttribs )
95 maModel.maName = rAttribs.getXString( XML_name, OUString() );
96 OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDdeItem - empty name" );
97 maExtNameModel.mbOleObj = false;
98 maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false );
99 maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
100 maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
103 void ExternalName::importValues( const AttributeList& rAttribs )
105 setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) );
108 void ExternalName::importOleItem( const AttributeList& rAttribs )
110 maModel.maName = rAttribs.getXString( XML_name, OUString() );
111 OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importOleItem - empty name" );
112 maExtNameModel.mbOleObj = true;
113 maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
114 maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
115 maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false );
118 void ExternalName::importExternalName( SequenceInputStream& rStrm )
120 rStrm >> maModel.maName;
121 OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importExternalName - empty name" );
124 void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm )
126 sal_uInt16 nFlags;
127 sal_Int32 nSheetId;
128 nFlags = rStrm.readuInt16();
129 nSheetId = rStrm.readInt32();
130 // index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
131 maModel.mnSheet = nSheetId - 1;
132 // no flag for built-in names, as in OOXML...
133 maExtNameModel.mbNotify = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC );
134 maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC );
135 maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME );
136 maExtNameModel.mbOleObj = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT );
137 maExtNameModel.mbIconified = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED );
138 OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj,
139 "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
142 void ExternalName::importDdeItemValues( SequenceInputStream& rStrm )
144 sal_Int32 nRows, nCols;
145 nRows = rStrm.readInt32();
146 nCols = rStrm.readInt32();
147 setResultSize( nCols, nRows );
150 void ExternalName::importDdeItemBool( SequenceInputStream& rStrm )
152 appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
155 void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm )
157 appendResultValue( rStrm.readDouble() );
160 void ExternalName::importDdeItemError( SequenceInputStream& rStrm )
162 appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
165 void ExternalName::importDdeItemString( SequenceInputStream& rStrm )
167 appendResultValue( BiffHelper::readString( rStrm ) );
170 #if 0
171 sal_Int32 ExternalName::getSheetCacheIndex() const
173 OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" );
174 sal_Int32 nCacheIdx = -1;
175 switch( getFilterType() )
177 case FILTER_OOXML:
178 // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
179 if( maModel.mnSheet >= 0 )
180 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
181 break;
182 case FILTER_BIFF:
183 switch( getBiff() )
185 case BIFF2:
186 case BIFF3:
187 case BIFF4:
188 break;
189 case BIFF5:
190 if( maModel.mnSheet > 0 )
191 if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() )
192 if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL )
193 nCacheIdx = pExtLink->getSheetIndex();
194 break;
195 case BIFF8:
196 if( maModel.mnSheet > 0 )
197 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
198 break;
199 case BIFF_UNKNOWN:
200 break;
202 break;
203 case FILTER_UNKNOWN:
204 break;
206 return nCacheIdx;
208 #endif
210 bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const
212 if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
214 orItemInfo.Item = maModel.maName;
215 orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults );
216 return true;
218 return false;
221 bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem )
223 if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
225 // try to create a DDE link and to set the imported link results
226 if( !mbDdeLinkCreated ) try
228 PropertySet aDocProps( getDocument() );
229 Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW );
230 mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT );
231 mbDdeLinkCreated = true; // ignore if setting results fails
232 if( !maResults.empty() )
234 Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW );
235 xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) );
238 catch( Exception& )
240 OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
242 // get link data from created DDE link
243 if( mxDdeLink.is() )
245 orDdeServer = mxDdeLink->getApplication();
246 orDdeTopic = mxDdeLink->getTopic();
247 orDdeItem = mxDdeLink->getItem();
248 return true;
251 return false;
254 // private --------------------------------------------------------------------
256 void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows )
258 OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) ||
259 (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" );
260 OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" );
261 const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
262 if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) )
263 maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) );
264 else
265 maResults.clear();
266 maCurrIt = maResults.begin();
269 void LinkSheetRange::setDeleted()
271 meType = LINKSHEETRANGE_INTERNAL;
272 mnDocLink = mnFirst = mnLast = -1;
275 void LinkSheetRange::setSameSheet()
277 meType = LINKSHEETRANGE_SAMESHEET;
278 mnDocLink = -1;
279 mnFirst = mnLast = 0;
282 void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
284 meType = LINKSHEETRANGE_INTERNAL;
285 mnDocLink = -1;
286 mnFirst = ::std::min( nFirst, nLast );
287 mnLast = ::std::max( nFirst, nLast );
290 void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast )
292 if( nDocLink < 0 )
294 setDeleted();
296 else
298 meType = LINKSHEETRANGE_EXTERNAL;
299 mnDocLink = nDocLink;
300 mnFirst = ::std::min( nFirst, nLast );
301 mnLast = ::std::max( nFirst, nLast );
305 ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
306 WorkbookHelper( rHelper ),
307 meLinkType( LINKTYPE_UNKNOWN ),
308 meFuncLibType( FUNCLIB_UNKNOWN )
312 void ExternalLink::importExternalReference( const AttributeList& rAttribs )
314 maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
317 void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
319 parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
322 void ExternalLink::importSheetName( const AttributeList& rAttribs )
324 insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) );
327 void ExternalLink::importDefinedName( const AttributeList& rAttribs )
329 createExternalName()->importDefinedName( rAttribs );
332 void ExternalLink::importDdeLink( const AttributeList& rAttribs )
334 OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() );
335 OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() );
336 setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
339 ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs )
341 ExternalNameRef xExtName = createExternalName();
342 xExtName->importDdeItem( rAttribs );
343 return xExtName;
346 void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs )
348 OUString aProgId = rAttribs.getXString( XML_progId, OUString() );
349 OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
350 setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
353 ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs )
355 ExternalNameRef xExtName = createExternalName();
356 xExtName->importOleItem( rAttribs );
357 return xExtName;
360 void ExternalLink::importExternalRef( SequenceInputStream& rStrm )
362 rStrm >> maRelId;
365 void ExternalLink::importExternalSelf( SequenceInputStream& )
367 meLinkType = LINKTYPE_SELF;
370 void ExternalLink::importExternalSame( SequenceInputStream& )
372 meLinkType = LINKTYPE_SAME;
375 void ExternalLink::importExternalAddin( SequenceInputStream& )
377 meLinkType = LINKTYPE_UNKNOWN;
380 void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm )
382 switch( rStrm.readuInt16() )
384 case BIFF12_EXTERNALBOOK_BOOK:
385 parseExternalReference( rRelations, BiffHelper::readString( rStrm ) );
386 break;
387 case BIFF12_EXTERNALBOOK_DDE:
389 OUString aDdeService, aDdeTopic;
390 rStrm >> aDdeService >> aDdeTopic;
391 setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
393 break;
394 case BIFF12_EXTERNALBOOK_OLE:
396 OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
397 OUString aProgId = BiffHelper::readString( rStrm );
398 setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
400 break;
401 default:
402 OSL_FAIL( "ExternalLink::importExternalBook - unknown link type" );
406 void ExternalLink::importExtSheetNames( SequenceInputStream& rStrm )
408 // load external sheet names and create the sheet caches in the Calc document
409 OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
410 "ExternalLink::importExtSheetNames - invalid link type" );
411 if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries
412 for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
413 insertExternalSheet( BiffHelper::readString( rStrm ) );
416 ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& rStrm )
418 ExternalNameRef xExtName = createExternalName();
419 xExtName->importExternalName( rStrm );
420 return xExtName;
423 ExternalLinkInfo ExternalLink::getLinkInfo() const
425 ExternalLinkInfo aLinkInfo;
426 switch( meLinkType )
428 case LINKTYPE_SELF:
429 case LINKTYPE_SAME:
430 case LINKTYPE_INTERNAL:
431 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF;
432 break;
433 case LINKTYPE_EXTERNAL:
434 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
435 aLinkInfo.Data <<= maTargetUrl;
436 break;
437 case LINKTYPE_LIBRARY:
438 // parser will return library function names in OPCODE_BAD string tokens
439 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL;
440 break;
441 case LINKTYPE_DDE:
443 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE;
444 DDELinkInfo aDdeLinkInfo;
445 aDdeLinkInfo.Service = maClassName;
446 aDdeLinkInfo.Topic = maTargetUrl;
447 ::std::vector< DDEItemInfo > aItemInfos;
448 DDEItemInfo aItemInfo;
449 for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt )
450 if( (*aIt)->getDdeItemInfo( aItemInfo ) )
451 aItemInfos.push_back( aItemInfo );
452 aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos );
453 aLinkInfo.Data <<= aDdeLinkInfo;
455 break;
456 default:
457 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN;
459 return aLinkInfo;
462 FunctionLibraryType ExternalLink::getFuncLibraryType() const
464 return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
467 sal_Int32 ExternalLink::getDocumentLinkIndex() const
469 OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" );
470 return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1;
473 sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const
475 OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" );
476 OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
477 "ExternalLink::getSheetCacheIndex - invalid sheet index" );
478 return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 );
481 Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const
483 sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId );
484 if( mxDocLink.is() && (nCacheIdx >= 0) ) try
486 // existing mxDocLink implies that this is an external link
487 Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW );
488 return xSheetCache;
490 catch( Exception& )
493 return 0;
496 void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
498 switch( meLinkType )
500 case LINKTYPE_SAME:
501 orSheetRange.setSameSheet();
502 break;
504 case LINKTYPE_SELF:
505 case LINKTYPE_INTERNAL:
506 orSheetRange.setRange( nTabId1, nTabId2 );
507 break;
509 case LINKTYPE_EXTERNAL:
511 sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
512 switch( getFilterType() )
514 case FILTER_OOXML:
515 // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
516 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
517 break;
518 case FILTER_BIFF:
519 switch( getBiff() )
521 case BIFF2:
522 case BIFF3:
523 case BIFF4:
524 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
525 break;
526 case BIFF5:
527 // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
528 if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() )
529 if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) )
530 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() );
531 break;
532 case BIFF8:
533 // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
534 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
535 break;
536 case BIFF_UNKNOWN: break;
538 break;
539 case FILTER_UNKNOWN: break;
542 break;
544 default:
545 // unsupported/unexpected link type: #REF! error
546 orSheetRange.setDeleted();
550 ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
552 return maExtNames.get( nIndex );
555 // private --------------------------------------------------------------------
557 void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
559 meLinkType = LINKTYPE_UNKNOWN;
560 if( rTargetType == CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" ) ||
561 rTargetType == CREATE_OFFICEDOC_RELATION_TYPE_STRICT( "externalLinkPath" ) )
563 maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
564 if( !maTargetUrl.isEmpty() )
565 meLinkType = LINKTYPE_EXTERNAL;
567 else if( rTargetType == CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" ) )
569 meLinkType = LINKTYPE_LIBRARY;
570 meFuncLibType = FunctionProvider::getFuncLibTypeFromLibraryName( rTargetUrl );
572 OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
574 // create the external document link API object that will contain the sheet caches
575 if( meLinkType == LINKTYPE_EXTERNAL ) try
577 PropertySet aDocProps( getDocument() );
578 Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW );
579 mxDocLink = xDocLinks->addDocLink( maTargetUrl );
581 catch( Exception& )
586 void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType )
588 maClassName = rClassName;
589 maTargetUrl = rTargetUrl;
590 meLinkType = (maClassName.isEmpty() || maTargetUrl.isEmpty()) ? LINKTYPE_UNKNOWN : eLinkType;
591 OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
594 void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
596 if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
597 setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
600 void ExternalLink::insertExternalSheet( const OUString& rSheetName )
602 OSL_ENSURE( !rSheetName.isEmpty(), "ExternalLink::insertExternalSheet - empty sheet name" );
603 if( mxDocLink.is() )
605 Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false );
606 sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1;
607 maSheetCaches.push_back( nCacheIdx );
611 ExternalNameRef ExternalLink::createExternalName()
613 ExternalNameRef xExtName( new ExternalName( *this ) );
614 maExtNames.push_back( xExtName );
615 return xExtName;
618 RefSheetsModel::RefSheetsModel() :
619 mnExtRefId( -1 ),
620 mnTabId1( -1 ),
621 mnTabId2( -1 )
625 void RefSheetsModel::readBiff12Data( SequenceInputStream& rStrm )
627 mnExtRefId = rStrm.readInt32();
628 mnTabId1 = rStrm.readInt32();
629 mnTabId2 = rStrm.readInt32();
632 ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) :
633 WorkbookHelper( rHelper ),
634 mxSelfRef( new ExternalLink( rHelper ) ),
635 mbUseRefSheets( false )
637 mxSelfRef->setSelfLinkType();
640 ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs )
642 ExternalLinkRef xExtLink = createExternalLink();
643 xExtLink->importExternalReference( rAttribs );
644 maExtLinks.push_back( xExtLink );
645 return xExtLink;
648 ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm )
650 mbUseRefSheets = true;
651 ExternalLinkRef xExtLink = createExternalLink();
652 xExtLink->importExternalRef( rStrm );
653 maExtLinks.push_back( xExtLink );
654 return xExtLink;
657 void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm )
659 mbUseRefSheets = true;
660 createExternalLink()->importExternalSelf( rStrm );
663 void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm )
665 mbUseRefSheets = true;
666 createExternalLink()->importExternalSame( rStrm );
669 void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm )
671 mbUseRefSheets = true;
672 createExternalLink()->importExternalAddin( rStrm );
675 void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& rStrm )
677 OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
678 mbUseRefSheets = true;
679 OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
680 maRefSheets.clear();
681 sal_Int32 nRefCount;
682 nRefCount = rStrm.readInt32();
683 size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 );
684 maRefSheets.reserve( nMaxCount );
685 for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId )
687 RefSheetsModel aRefSheets;
688 aRefSheets.readBiff12Data( rStrm );
689 maRefSheets.push_back( aRefSheets );
693 Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const
695 ::std::vector< ExternalLinkInfo > aLinkInfos;
696 // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
697 OSL_ENSURE( getFilterType() == FILTER_OOXML, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
698 // add entry for implicit index 0 (self reference to this document)
699 aLinkInfos.push_back( mxSelfRef->getLinkInfo() );
700 for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt )
701 aLinkInfos.push_back( (*aIt)->getLinkInfo() );
702 return ContainerHelper::vectorToSequence( aLinkInfos );
705 ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId, bool bUseRefSheets ) const
707 ExternalLinkRef xExtLink;
708 switch( getFilterType() )
710 case FILTER_OOXML:
711 // OOXML: 0 = this document, otherwise one-based index into link list
712 if( !bUseRefSheets || !mbUseRefSheets )
713 xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 );
714 // BIFF12: zero-based index into ref-sheets list
715 else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
716 xExtLink = maLinks.get( pRefSheets->mnExtRefId );
717 break;
718 case FILTER_BIFF:
719 switch( getBiff() )
721 case BIFF2:
722 case BIFF3:
723 case BIFF4:
724 // one-based index to EXTERNSHEET records
725 xExtLink = maLinks.get( nRefId - 1 );
726 break;
727 case BIFF5:
728 if( nRefId < 0 )
730 // internal links in formula tokens have negative index
731 xExtLink = maLinks.get( -nRefId - 1 );
732 if( xExtLink.get() && !xExtLink->isInternalLink() )
733 xExtLink.reset();
735 else
737 // one-based index to EXTERNSHEET records
738 xExtLink = maLinks.get( nRefId - 1 );
740 break;
741 case BIFF8:
742 // zero-based index into REF list in EXTERNSHEET record
743 if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
744 xExtLink = maLinks.get( pRefSheets->mnExtRefId );
745 break;
746 case BIFF_UNKNOWN: break;
748 break;
749 case FILTER_UNKNOWN: break;
751 return xExtLink;
754 LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const
756 OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
757 LinkSheetRange aSheetRange;
758 if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
759 pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 );
760 return aSheetRange;
763 LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const
765 OSL_ENSURE( ((getFilterType() == FILTER_OOXML) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
766 LinkSheetRange aSheetRange;
767 if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
768 if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
769 pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 );
770 return aSheetRange;
773 // private --------------------------------------------------------------------
775 ExternalLinkRef ExternalLinkBuffer::createExternalLink()
777 ExternalLinkRef xExtLink( new ExternalLink( *this ) );
778 maLinks.push_back( xExtLink );
779 return xExtLink;
782 const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const
784 return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ?
785 &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0;
788 } // namespace xls
789 } // namespace oox
791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */