diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-01-06 13:57:48 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-01-06 13:57:48 +0000 |
commit | 730272a2d67e99c0195ea42c26022ffbd489e994 (patch) | |
tree | 2268883449c5ccd3242d5c58cb0d59bc55420ecc /oox/source | |
parent | 75ab7be7fc7114e775442305bd1fb26a36975acc (diff) |
CWS-TOOLING: integrate CWS odff05
2008-12-11 04:17:37 +0100 er r265237 : #i94555# AppendIntToken for GAMMADIST, Excel needs 4 parameters; also use AppendIntToken instead of AppendNumToken for POISSON
2008-12-11 04:04:27 +0100 er r265236 : #i96837# make cumulative parameter of POISSON optional; patch from <lvyue> with slight modifications
2008-12-11 03:35:03 +0100 er r265235 : #i96835# make base parameter of LOG() optional also in UI; patch from <lvyue>
2008-12-11 03:15:30 +0100 er r265234 : #i94555# patch from <regina>, ODFF:
Add GAMMA, CHISQDIST, CHISQINV.
Make the 'cumulative' parameter of GAMMADIST optional.
Adapt the domain of CHIDIST to allow negative x.
Remove the constraint "degrees of freedom < 1.0E5" from CHIDIST and CHIINV.
Plus a mechanism to write the now optional parameter of GAMMADIST to PODF and
ODFF if omitted, for backwards compatibility.
2008-12-10 18:14:16 +0100 er r265214 : DBG_... need semicolon
2008-12-05 00:49:55 +0100 er r264881 : WaE unxlngi6: declaration of 'pFuncInfo' shadows a previous local
2008-12-05 00:26:05 +0100 er r264879 : #i91547# BETADIST with optional density/cumulative parameter and much better precision; patch from <regina>
2008-12-04 22:51:40 +0100 er r264877 : #i91602# add expm1() and log1p() replacements; based on a patch from <regina>
2008-12-01 16:07:35 +0100 dr r264614 : #i93789# import of EUROCONVERT from XLSX/XLSB
2008-11-28 13:15:01 +0100 dr r264543 : #i93789# new sheet function EUROCONVERT + XLS import/export, patch contributed by lvyue
2008-11-26 14:54:23 +0100 er r264397 : CWS-TOOLING: rebase CWS odff05 to trunk@264325 (milestone: DEV300:m36)
2008-11-20 14:23:33 +0100 er r264053 : CWS-TOOLING: rebase CWS odff05 to trunk@263288 (milestone: DEV300:m35)
2008-11-19 18:07:43 +0100 er r264012 : merged from trunk
2008-11-19 17:51:36 +0100 er r264011 : migrate CWS odff05 to SVN
Diffstat (limited to 'oox/source')
-rw-r--r-- | oox/source/xls/addressconverter.cxx | 27 | ||||
-rw-r--r-- | oox/source/xls/defnamesbuffer.cxx | 9 | ||||
-rw-r--r-- | oox/source/xls/externallinkbuffer.cxx | 89 | ||||
-rw-r--r-- | oox/source/xls/formulabase.cxx | 31 | ||||
-rw-r--r-- | oox/source/xls/formulaparser.cxx | 106 | ||||
-rw-r--r-- | oox/source/xls/workbookfragment.cxx | 4 |
6 files changed, 206 insertions, 60 deletions
diff --git a/oox/source/xls/addressconverter.cxx b/oox/source/xls/addressconverter.cxx index 16d57b3c80ff..60f46771f3de 100644 --- a/oox/source/xls/addressconverter.cxx +++ b/oox/source/xls/addressconverter.cxx @@ -93,7 +93,7 @@ const sal_Unicode BIFF_URL_PARENT = '\x04'; /// Parent directory. const sal_Unicode BIFF_URL_RAW = '\x05'; /// Unencoded URL. const sal_Unicode BIFF_URL_INSTALL = '\x06'; /// Application installation directory. const sal_Unicode BIFF_URL_INSTALL2 = '\x07'; /// Alternative application installation directory. -const sal_Unicode BIFF_URL_ADDIN = '\x08'; /// Add-in installation directory. +const sal_Unicode BIFF_URL_LIBRARY = '\x08'; /// Library directory in application installation. const sal_Unicode BIFF4_URL_SHEET = '\x09'; /// BIFF4 internal sheet. const sal_Unicode BIFF_URL_UNC = '@'; /// UNC path root. @@ -385,13 +385,13 @@ bool lclAppendUrlChar( OUStringBuffer& orUrl, sal_Unicode cChar, bool bEncodeSpe } // namespace -bool AddressConverter::parseBiffTargetUrl( - OUString& orClassName, OUString& orTargetUrl, OUString& orSheetName, bool& orbSameSheet, - const OUString& rBiffTargetUrl ) +BiffTargetType AddressConverter::parseBiffTargetUrl( + OUString& orClassName, OUString& orTargetUrl, OUString& orSheetName, const OUString& rBiffTargetUrl ) { OUStringBuffer aTargetUrl; OUStringBuffer aSheetName; - orbSameSheet = false; + // default target type: some URL with/without sheet name, may be overridden below + BiffTargetType eTargetType = BIFF_TARGETTYPE_URL; enum { @@ -419,8 +419,10 @@ bool AddressConverter::parseBiffTargetUrl( case STATE_START: if( (cChar == mcUrlThisWorkbook) || (cChar == mcUrlThisSheet) || (cChar == mcUrlSameSheet) ) { - if( pcChar + 1 < pcEnd ) eState = STATE_ERROR; - orbSameSheet = cChar == mcUrlSameSheet; + if( pcChar + 1 < pcEnd ) + eState = STATE_ERROR; + if( cChar == mcUrlSameSheet ) + eTargetType = BIFF_TARGETTYPE_SAMESHEET; } else if( cChar == mcUrlExternal ) eState = (pcChar + 1 < pcEnd) ? STATE_ENCODED_PATH_START : STATE_ERROR; @@ -446,8 +448,11 @@ bool AddressConverter::parseBiffTargetUrl( eState = STATE_UNSUPPORTED; else if( cChar == BIFF_URL_INSTALL2 ) eState = STATE_UNSUPPORTED; - else if( cChar == BIFF_URL_ADDIN ) - eState = STATE_UNSUPPORTED; + else if( cChar == BIFF_URL_LIBRARY ) + { + eState = STATE_ENCODED_PATH; + eTargetType = BIFF_TARGETTYPE_LIBRARY; + } else if( (getBiff() == BIFF4) && (cChar == BIFF4_URL_SHEET) ) eState = STATE_SHEETNAME; else if( cChar == '[' ) @@ -496,6 +501,7 @@ bool AddressConverter::parseBiffTargetUrl( { orClassName = aTargetUrl.makeStringAndClear(); eState = STATE_DDE_OLE; + eTargetType = BIFF_TARGETTYPE_DDE_OLE; } else if( cChar == '[' ) eState = STATE_FILENAME; @@ -535,7 +541,8 @@ bool AddressConverter::parseBiffTargetUrl( OSL_ENSURE( (eState != STATE_ERROR) && (pcChar == pcEnd), OStringBuffer( "AddressConverter::parseBiffTargetUrl - parser error in target \"" ). append( OUStringToOString( rBiffTargetUrl, RTL_TEXTENCODING_UTF8 ) ).append( '"' ).getStr() ); - return (eState != STATE_ERROR) && (eState != STATE_UNSUPPORTED) && (pcChar == pcEnd); + bool bParserOk = (eState != STATE_ERROR) && (eState != STATE_UNSUPPORTED) && (pcChar == pcEnd); + return bParserOk ? eTargetType : BIFF_TARGETTYPE_UNKNOWN; } // ---------------------------------------------------------------------------- diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx index 1bd0b0d039a6..b9197ea6edb2 100644 --- a/oox/source/xls/defnamesbuffer.cxx +++ b/oox/source/xls/defnamesbuffer.cxx @@ -142,11 +142,18 @@ DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper, sal_Int32 nLoca maOoxData.mnSheet = nLocalSheet; } +const OUString& DefinedNameBase::getUpcaseOoxName() const +{ + if( maUpOoxName.getLength() == 0 ) + maUpOoxName = maOoxData.maName.toAsciiUpperCase(); + return maUpOoxName; +} + Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const { if( maRefAny.hasValue() && (maOoxData.maName.getLength() >= 2) && (maOoxData.maName[ 0 ] == '\x01') ) { - sal_Unicode cFlagsChar = maOoxData.maName.toAsciiUpperCase()[ 1 ]; + sal_Unicode cFlagsChar = getUpcaseOoxName()[ 1 ]; if( ('A' <= cFlagsChar) && (cFlagsChar <= 'P') ) { sal_uInt16 nFlags = static_cast< sal_uInt16 >( cFlagsChar - 'A' ); diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx index 00653a60ddd5..f05d28ce799c 100644 --- a/oox/source/xls/externallinkbuffer.cxx +++ b/oox/source/xls/externallinkbuffer.cxx @@ -62,6 +62,7 @@ using ::com::sun::star::sheet::XDDELinks; using ::com::sun::star::sheet::XDDELinkResults; using ::com::sun::star::sheet::XExternalDocLinks; using ::com::sun::star::sheet::XExternalSheetCache; +using ::oox::core::Relation; using ::oox::core::Relations; namespace oox { @@ -435,7 +436,8 @@ void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper ), - meLinkType( LINKTYPE_UNKNOWN ) + meLinkType( LINKTYPE_UNKNOWN ), + meFuncLibType( FUNCLIB_UNKNOWN ) { } @@ -446,8 +448,7 @@ void ExternalLink::importExternalReference( const AttributeList& rAttribs ) void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs ) { - OUString aTargetUrl = rRelations.getTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); - setExternalTargetUrl( aTargetUrl ); + parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) ); } void ExternalLink::importSheetName( const AttributeList& rAttribs ) @@ -513,10 +514,7 @@ void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputS switch( rStrm.readuInt16() ) { case OOBIN_EXTERNALBOOK_BOOK: - { - OUString aTargetUrl = rRelations.getTargetFromRelId( rStrm.readString() ); - setExternalTargetUrl( aTargetUrl ); - } + parseExternalReference( rRelations, rStrm.readString() ); break; case OOBIN_EXTERNALBOOK_DDE: { @@ -540,8 +538,9 @@ void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputS void ExternalLink::importExtSheetNames( RecordInputStream& rStrm ) { // load external sheet names and create the sheet caches in the Calc document - OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::importExtSheetNames - invalid link type" ); - if( meLinkType == LINKTYPE_EXTERNAL ) + OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY), + "ExternalLink::importExtSheetNames - invalid link type" ); + if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet ) insertExternalSheet( rStrm.readString() ); } @@ -659,6 +658,11 @@ ExternalLinkInfo ExternalLink::getLinkInfo() const return aLinkInfo; } +FunctionLibraryType ExternalLink::getFuncLibraryType() const +{ + return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN; +} + sal_Int32 ExternalLink::getSheetIndex( sal_Int32 nTabId ) const { OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOX) || (getBiff() == BIFF8), @@ -743,11 +747,25 @@ ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const // private -------------------------------------------------------------------- -void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl ) +#define OOX_TARGETTYPE_EXTLINK CREATE_OFFICEDOC_RELATIONSTYPE( "externalLinkPath" ) +#define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATIONSTYPE( "xlExternalLinkPath/xlLibrary" ) + +void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType ) { + meLinkType = LINKTYPE_UNKNOWN; + if( rTargetType == OOX_TARGETTYPE_EXTLINK ) + { maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl ); - meLinkType = (maTargetUrl.getLength() > 0) ? LINKTYPE_EXTERNAL : LINKTYPE_UNKNOWN; - OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::setExternalTargetUrl - empty target URL" ); + if( maTargetUrl.getLength() > 0 ) + meLinkType = LINKTYPE_EXTERNAL; + } + else if( rTargetType == OOX_TARGETTYPE_LIBRARY ) + { + meLinkType = LINKTYPE_LIBRARY; + if( rTargetUrl.equalsIgnoreAsciiCaseAscii( "EUROTOOL.XLA" ) || rTargetUrl.equalsIgnoreAsciiCaseAscii( "EUROTOOL.XLAM" ) ) + meFuncLibType = FUNCLIB_EUROTOOL; + } + OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" ); // create the external document link API object that will contain the sheet caches if( meLinkType == LINKTYPE_EXTERNAL ) @@ -766,34 +784,51 @@ void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUStrin OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" ); } +void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId ) +{ + if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) ) + setExternalTargetUrl( pRelation->maTarget, pRelation->maType ); +} + OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl ) { - OUString aClassName, aTargetUrl, aSheetName; - bool bSameSheet = false; meLinkType = LINKTYPE_UNKNOWN; - if( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, bSameSheet, rBiffTargetUrl ) ) - { - if( aClassName.getLength() > 0 ) + + OUString aClassName, aTargetUrl, aSheetName; + switch( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) ) { - setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE ); - } - else if( aTargetUrl.getLength() == 0 ) + case BIFF_TARGETTYPE_URL: + if( aTargetUrl.getLength() == 0 ) { - meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : (bSameSheet ? LINKTYPE_SAME : LINKTYPE_SELF); + meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF; } else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') ) { if( getBiff() >= BIFF4 ) meLinkType = LINKTYPE_ANALYSIS; } - else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ' ') ) + else if( (aTargetUrl.getLength() > 1) || (aTargetUrl[ 0 ] != ' ') ) { - meLinkType = LINKTYPE_UNKNOWN; - } - else - { - setExternalTargetUrl( aTargetUrl ); + setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_EXTLINK ); } + break; + + case BIFF_TARGETTYPE_SAMESHEET: + OSL_ENSURE( (aTargetUrl.getLength() == 0) && (aSheetName.getLength() == 0), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" ); + meLinkType = LINKTYPE_SAME; + break; + + case BIFF_TARGETTYPE_LIBRARY: + OSL_ENSURE( aSheetName.getLength() == 0, "ExternalLink::parseBiffTargetUrl - unexpected sheet name" ); + setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_LIBRARY ); + break; + + case BIFF_TARGETTYPE_DDE_OLE: + setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE ); + break; + + case BIFF_TARGETTYPE_UNKNOWN: + break; } return aSheetName; } diff --git a/oox/source/xls/formulabase.cxx b/oox/source/xls/formulabase.cxx index 87c1fc67adf7..6696c211e61d 100644 --- a/oox/source/xls/formulabase.cxx +++ b/oox/source/xls/formulabase.cxx @@ -227,14 +227,17 @@ namespace { const size_t FUNCINFO_CLASSCOUNT = 5; /// Number of token class entries. -const sal_uInt8 FUNCFLAG_VOLATILE = 0x01; /// Result is volatile (e.g. NOW() function). -const sal_uInt8 FUNCFLAG_IMPORTONLY = 0x02; /// Only used in import filter. -const sal_uInt8 FUNCFLAG_EXPORTONLY = 0x04; /// Only used in export filter. -const sal_uInt8 FUNCFLAG_MACROCALL = 0x08; /// Function is simulated by macro call in Excel. -const sal_uInt8 FUNCFLAG_EXTERNAL = 0x10; /// Function is external in Calc. -const sal_uInt8 FUNCFLAG_MACROFUNC = 0x20; /// Function is a macro sheet function. -const sal_uInt8 FUNCFLAG_MACROCMD = 0x40; /// Function is a macro sheet command. -const sal_uInt8 FUNCFLAG_ALWAYSVAR = 0x80; /// Function is always represented by a tFuncVar token. +const sal_uInt16 FUNCFLAG_VOLATILE = 0x0001; /// Result is volatile (e.g. NOW() function). +const sal_uInt16 FUNCFLAG_IMPORTONLY = 0x0002; /// Only used in import filter. +const sal_uInt16 FUNCFLAG_EXPORTONLY = 0x0004; /// Only used in export filter. +const sal_uInt16 FUNCFLAG_MACROCALL = 0x0008; /// Function is simulated by macro call in Excel. +const sal_uInt16 FUNCFLAG_EXTERNAL = 0x0010; /// Function is external in Calc. +const sal_uInt16 FUNCFLAG_MACROFUNC = 0x0020; /// Function is a macro-sheet function. +const sal_uInt16 FUNCFLAG_MACROCMD = 0x0040; /// Function is a macro-sheet command. +const sal_uInt16 FUNCFLAG_ALWAYSVAR = 0x0080; /// Function is always represented by a tFuncVar token. + +const sal_uInt16 FUNCFLAG_FUNCLIBMASK = 0xF000; /// Mask for function library bits. +const sal_uInt16 FUNCFLAG_EUROTOOL = 0x1000; /// Function is part of the EuroTool add-in. typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef; @@ -248,7 +251,7 @@ struct FunctionData sal_uInt8 mnMaxParamCount; /// Maximum number of parameters. sal_uInt8 mnRetClass; /// BIFF token class of the return value. sal_uInt8 mpnParamClass[ FUNCINFO_CLASSCOUNT ]; /// Expected BIFF token classes of parameters. - sal_uInt8 mnFlags; /// Additional flags. + sal_uInt16 mnFlags; /// Additional flags. inline bool isSupported( bool bImportFilter ) const; }; @@ -632,7 +635,6 @@ static const FunctionData saFuncTableBiff4[] = { "MULTINOMIAL", "MULTINOMIAL", 474, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, { "LCM", "LCM", 475, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in { "FVSCHEDULE", "FVSCHEDULE", 476, NOID, 2, 2, V, { V, A }, FUNCFLAG_EXTERNAL }, -// { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { V }, FUNCFLAG_EXTERNAL }, // Euro conversion add-in // *** macro sheet commands *** @@ -664,6 +666,10 @@ static const FunctionData saFuncTableBiff5[] = { 0, "NUMBERSTRING", 353, 353, 2, 2, V, { V }, FUNCFLAG_IMPORTONLY }, // not supported in Calc, missing in OOX spec { "ROMAN", "ROMAN", 354, 354, 1, 2, V, { V }, 0 }, + // *** EuroTool add-in *** + + { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { V }, FUNCFLAG_EUROTOOL }, + // *** macro sheet commands *** { 0, "ADD.CHART.AUTOFORMAT", 390, 390, 0, 2, V, { V }, FUNCFLAG_MACROCMD }, @@ -868,6 +874,11 @@ void FunctionProvider::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxPa xFuncInfo->maOoxFuncName = OUString::createFromAscii( rFuncData.mpcOoxFuncName ); if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALL ) ) xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfn." ) + xFuncInfo->maOoxFuncName; + switch( rFuncData.mnFlags & FUNCFLAG_FUNCLIBMASK ) + { + case FUNCFLAG_EUROTOOL: xFuncInfo->meFuncLibType = FUNCLIB_EUROTOOL; break; + default: xFuncInfo->meFuncLibType = FUNCLIB_UNKNOWN; + } xFuncInfo->mnApiOpCode = -1; xFuncInfo->mnOobFuncId = rFuncData.mnOobFuncId; xFuncInfo->mnBiffFuncId = rFuncData.mnBiffFuncId; diff --git a/oox/source/xls/formulaparser.cxx b/oox/source/xls/formulaparser.cxx index dff1b42dc991..161802b6c63c 100644 --- a/oox/source/xls/formulaparser.cxx +++ b/oox/source/xls/formulaparser.cxx @@ -169,8 +169,9 @@ protected: bool pushNlrOperand( const BinSingleRef2d& rRef ); bool pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken ); bool pushDefinedNameOperand( const DefinedNameRef& rxDefName ); + bool pushExternalFuncOperand( const FunctionInfo& rFuncInfo ); bool pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ); - bool pushExternalNameOperand( const ExternalNameRef& rxExtName, ExternalLinkType eLinkType ); + bool pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink ); bool pushUnaryPreOperator( sal_Int32 nOpCode ); bool pushUnaryPostOperator( sal_Int32 nOpCode ); @@ -199,6 +200,7 @@ private: void processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ); const ApiToken* processParameters( const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ); + const FunctionInfo* getFuncInfoFromLibFuncName( const ApiToken& rToken ) const; bool isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; const ApiToken* getExternCallToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; const FunctionInfo* convertExternCallParam( ApiToken& orFuncToken, const ApiToken& rECToken ) const; @@ -669,6 +671,13 @@ bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef& rxDefName return pushEmbeddedRefOperand( *rxDefName, true ); } +bool FormulaParserImpl::pushExternalFuncOperand( const FunctionInfo& rFuncInfo ) +{ + return (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) ? + pushValueOperand( rFuncInfo.maExtProgName, OPCODE_EXTERNAL ) : + pushOperand( rFuncInfo.mnApiOpCode ); +} + bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ) { // create the function call DDE("server";"topic";"item") @@ -679,9 +688,9 @@ bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OU pushFunctionOperator( OPCODE_DDE, 3 ); } -bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, ExternalLinkType eLinkType ) +bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink ) { - if( rxExtName.get() ) switch( eLinkType ) + if( rxExtName.get() ) switch( rExtLink.getLinkType() ) { case LINKTYPE_INTERNAL: case LINKTYPE_EXTERNAL: @@ -689,8 +698,14 @@ bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtNam case LINKTYPE_ANALYSIS: // TODO: need support for localized addin function names - if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getOoxName() ) ) - return pushValueOperand( pFuncInfo->maExtProgName, OPCODE_EXTERNAL ); + if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseOoxName() ) ) + return pushExternalFuncOperand( *pFuncInfo ); + break; + + case LINKTYPE_LIBRARY: + if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseOoxName() ) ) + if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == rExtLink.getFuncLibraryType()) ) + return pushExternalFuncOperand( *pFuncInfo ); break; case LINKTYPE_DDE: @@ -702,7 +717,7 @@ bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtNam break; default: - OSL_ENSURE( eLinkType != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" ); + OSL_ENSURE( rExtLink.getLinkType() != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" ); } return pushBiffErrorOperand( BIFF_ERR_NAME ); } @@ -852,17 +867,65 @@ void FormulaParserImpl::processTokens( const ApiToken* pToken, const ApiToken* p { // push the current token into the vector appendFinalToken( *pToken ); - // try to process a function, otherwise go to next token - if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( *pToken ) ) + const FunctionInfo* pFuncInfo; + // try to process a function + if( (pFuncInfo = getFuncInfoFromApiToken( *pToken )) != 0 ) + { + pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); + } + // try to process a function from an external library + else if( (pFuncInfo = getFuncInfoFromLibFuncName( *pToken )) != 0 ) + { + ApiToken& rFuncToken = maTokenStorage.back(); + rFuncToken.OpCode = pFuncInfo->mnApiOpCode; + if( (rFuncToken.OpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) ) + rFuncToken.Data <<= pFuncInfo->maExtProgName; + else + rFuncToken.Data.clear(); // clear string from OPCODE_BAD pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); + } + // otherwise, go to next token else + { ++pToken; + } } } +namespace { + +bool lclTokenHasChar( const ApiToken& rToken, sal_Int32 nOpCode, sal_Unicode cChar ) +{ + return (rToken.OpCode == nOpCode) && rToken.Data.has< OUString >() && (rToken.Data.get< OUString >() == OUString( cChar )); +} + +bool lclTokenHasDouble( const ApiToken& rToken, sal_Int32 nOpCode ) +{ + return (rToken.OpCode == nOpCode) && rToken.Data.has< double >(); +} + +} // namespace + const ApiToken* FormulaParserImpl::processParameters( const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ) { + /* OOXML import of library functions pushes the external reference "[n]!" + as BAD/PUSH/BAD/BAD tokens in front of the function name. Try to find + and remove them here. TODO: This will change with CWS mooxlsc, there, + the reference ID and function name are passed together in a BAD token, + see getFuncInfoFromLibFuncName(). */ + if( (rFuncInfo.meFuncLibType != FUNCLIB_UNKNOWN) && (maTokenStorage.size() >= 5) ) + { + sal_Size nSize = maTokenStorage.size(); + if( lclTokenHasChar( maTokenStorage[ nSize - 5 ], OPCODE_BAD, '[' ) && + lclTokenHasDouble( maTokenStorage[ nSize - 4 ], OPCODE_PUSH ) && + lclTokenHasChar( maTokenStorage[ nSize - 3 ], OPCODE_BAD, ']' ) && + lclTokenHasChar( maTokenStorage[ nSize - 2 ], OPCODE_BAD, '!' ) ) + { + maTokenStorage.erase( maTokenStorage.end() - 5, maTokenStorage.end() - 1 ); + } + } + // remember position of the token containing the function op-code size_t nFuncNameIdx = maTokenStorage.size() - 1; @@ -980,6 +1043,29 @@ const ApiToken* FormulaParserImpl::processParameters( return pToken; } +const FunctionInfo* FormulaParserImpl::getFuncInfoFromLibFuncName( const ApiToken& rToken ) const +{ + // try to parse calls to library functions + if( (rToken.OpCode == OPCODE_BAD) && rToken.Data.has< OUString >() ) + { + // format of the function call is "[n]!funcname", n being the link to the library + OUString aString = rToken.Data.get< OUString >(); + sal_Int32 nBracketOpen = aString.indexOf( '[' ); + sal_Int32 nBracketClose = aString.indexOf( ']' ); + sal_Int32 nExclamation = aString.indexOf( '!' ); + if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < aString.getLength()) ) + { + sal_Int32 nRefId = aString.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32(); + const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get(); + if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) ) + if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aString.copy( nExclamation + 1 ).toAsciiUpperCase() ) ) + if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) ) + return pFuncInfo; + } + } + return 0; +} + bool FormulaParserImpl::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const { while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; @@ -1666,7 +1752,7 @@ bool OoxFormulaParserImpl::pushOobExtName( sal_Int32 nRefId, sal_Int32 nNameId ) return pushOobName( nNameId ); // external name indexes are one-based in OOBIN ExternalNameRef xExtName = pExtLink->getNameByIndex( nNameId - 1 ); - return pushExternalNameOperand( xExtName, pExtLink->getLinkType() ); + return pushExternalNameOperand( xExtName, *pExtLink ); } return pushBiffErrorOperand( BIFF_ERR_NAME ); } @@ -2603,7 +2689,7 @@ bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameI return pushBiffName( nNameId ); // external name indexes are one-based in BIFF ExternalNameRef xExtName = pExtLink->getNameByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ); - return pushExternalNameOperand( xExtName, pExtLink->getLinkType() ); + return pushExternalNameOperand( xExtName, *pExtLink ); } return pushBiffErrorOperand( BIFF_ERR_NAME ); } diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx index 44be166e6580..d14c20f2ef0f 100644 --- a/oox/source/xls/workbookfragment.cxx +++ b/oox/source/xls/workbookfragment.cxx @@ -258,8 +258,8 @@ void OoxWorkbookFragment::finalizeImport() { xFragment.set( new OoxChartsheetFragment( *this, aFragmentPath, xSheetSegment, nSheet ) ); } - else if( (pRelation->maType == CREATE_OUSTRING( "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet" )) || - (pRelation->maType == CREATE_OUSTRING( "http://schemas.microsoft.com/office/2006/relationships/xlIntlMacrosheet" )) ) + else if( (pRelation->maType == CREATE_MSOFFICE_RELATIONSTYPE( "xlMacrosheet" )) || + (pRelation->maType == CREATE_MSOFFICE_RELATIONSTYPE( "xlIntlMacrosheet" )) ) { xFragment.set( new OoxWorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_MACROSHEET, nSheet ) ); } |