diff options
Diffstat (limited to 'sc/source/core/tool/addincol.cxx')
-rw-r--r-- | sc/source/core/tool/addincol.cxx | 1781 |
1 files changed, 0 insertions, 1781 deletions
diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx deleted file mode 100644 index a76db2908..000000000 --- a/sc/source/core/tool/addincol.cxx +++ /dev/null @@ -1,1781 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sc.hxx" - - - -#include <comphelper/processfactory.hxx> -#include <i18npool/mslangid.hxx> -#include <vcl/svapp.hxx> -#include <sfx2/objsh.hxx> -#include <unotools/charclass.hxx> - -#include <com/sun/star/container/XContentEnumerationAccess.hpp> -#include <com/sun/star/lang/XServiceName.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> -#include <com/sun/star/lang/XSingleComponentFactory.hpp> -#include <com/sun/star/reflection/XIdlClass.hpp> -#include <com/sun/star/reflection/XIdlClassProvider.hpp> -#include <com/sun/star/beans/XIntrospectionAccess.hpp> -#include <com/sun/star/beans/XIntrospection.hpp> -#include <com/sun/star/beans/MethodConcept.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/table/XCellRange.hpp> -#include <com/sun/star/lang/Locale.hpp> -#include <com/sun/star/sheet/XCompatibilityNames.hpp> -#include <com/sun/star/sheet/NoConvergenceException.hpp> - -#include "addincol.hxx" -#include "addinhelpid.hxx" -#include "compiler.hxx" -#include "scmatrix.hxx" -#include "addinlis.hxx" -#include "formula/errorcodes.hxx" -#include "scfuncs.hrc" -#include "optutil.hxx" -#include "addincfg.hxx" -#include "scmod.hxx" -#include "rangeseq.hxx" -#include "funcdesc.hxx" - -using namespace com::sun::star; - -//------------------------------------------------------------------------ - -#define SC_CALLERPOS_NONE (-1) - -#define SCADDINSUPPLIER_SERVICE "com.sun.star.sheet.AddIn" - -//------------------------------------------------------------------------ - - - - -//------------------------------------------------------------------------ - -ScUnoAddInFuncData::ScUnoAddInFuncData( const String& rNam, const String& rLoc, - const String& rDesc, - sal_uInt16 nCat, const rtl::OString& sHelp, - const uno::Reference<reflection::XIdlMethod>& rFunc, - const uno::Any& rO, - long nAC, const ScAddInArgDesc* pAD, - long nCP ) : - aOriginalName( rNam ), - aLocalName( rLoc ), - aUpperName( rNam ), - aUpperLocal( rLoc ), - aDescription( rDesc ), - xFunction( rFunc ), - aObject( rO ), - nArgCount( nAC ), - nCallerPos( nCP ), - nCategory( nCat ), - sHelpId( sHelp ), - bCompInitialized( false ) -{ - if ( nArgCount ) - { - pArgDescs = new ScAddInArgDesc[nArgCount]; - for (long i=0; i<nArgCount; i++) - pArgDescs[i] = pAD[i]; - } - else - pArgDescs = NULL; - - ScGlobal::pCharClass->toUpper(aUpperName); - ScGlobal::pCharClass->toUpper(aUpperLocal); -} - -ScUnoAddInFuncData::~ScUnoAddInFuncData() -{ - delete[] pArgDescs; -} - -const uno::Sequence<sheet::LocalizedName>& ScUnoAddInFuncData::GetCompNames() const -{ - if ( !bCompInitialized ) - { - // read sequence of compatibility names on demand - - uno::Reference<sheet::XAddIn> xAddIn; - if ( aObject >>= xAddIn ) - { - uno::Reference<sheet::XCompatibilityNames> xComp( xAddIn, uno::UNO_QUERY ); - if ( xComp.is() && xFunction.is() ) - { - rtl::OUString aMethodName = xFunction->getName(); - aCompNames = xComp->getCompatibilityNames( aMethodName ); - - // change all locale entries to default case - // (language in lower case, country in upper case) - // for easier searching - - long nSeqLen = aCompNames.getLength(); - if ( nSeqLen ) - { - sheet::LocalizedName* pArray = aCompNames.getArray(); - for (long i=0; i<nSeqLen; i++) - { - lang::Locale& rLocale = pArray[i].Locale; - rLocale.Language = rLocale.Language.toAsciiLowerCase(); - rLocale.Country = rLocale.Country.toAsciiUpperCase(); - } - } - } - } - - bCompInitialized = sal_True; // also if not successful - } - return aCompNames; -} - -void ScUnoAddInFuncData::SetCompNames( const uno::Sequence< sheet::LocalizedName>& rNew ) -{ - OSL_ENSURE( !bCompInitialized, "SetCompNames after initializing" ); - - aCompNames = rNew; - - // change all locale entries to default case - // (language in lower case, country in upper case) - // for easier searching - - long nSeqLen = aCompNames.getLength(); - if ( nSeqLen ) - { - sheet::LocalizedName* pArray = aCompNames.getArray(); - for (long i=0; i<nSeqLen; i++) - { - lang::Locale& rLocale = pArray[i].Locale; - rLocale.Language = rLocale.Language.toAsciiLowerCase(); - rLocale.Country = rLocale.Country.toAsciiUpperCase(); - } - } - - bCompInitialized = sal_True; -} - -sal_Bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang, String& rRetExcelName ) const -{ - const uno::Sequence<sheet::LocalizedName>& rSequence = GetCompNames(); - long nSeqLen = rSequence.getLength(); - if ( nSeqLen ) - { - const sheet::LocalizedName* pArray = rSequence.getConstArray(); - long i; - - rtl::OUString aLangStr, aCountryStr; - MsLangId::convertLanguageToIsoNames( eDestLang, aLangStr, aCountryStr ); - rtl::OUString aUserLang = aLangStr.toAsciiLowerCase(); - rtl::OUString aUserCountry = aCountryStr.toAsciiUpperCase(); - - // first check for match of both language and country - - for ( i=0; i<nSeqLen; i++) - if ( pArray[i].Locale.Language == aUserLang && - pArray[i].Locale.Country == aUserCountry ) - { - rRetExcelName = pArray[i].Name; - return sal_True; - } - - // second: check only language - - for ( i=0; i<nSeqLen; i++) - if ( pArray[i].Locale.Language == aUserLang ) - { - rRetExcelName = pArray[i].Name; - return sal_True; - } - - // third: #i57772# fall-back to en-US - - if ( eDestLang != LANGUAGE_ENGLISH_US ) - return GetExcelName( LANGUAGE_ENGLISH_US, rRetExcelName ); - - // forth: use first (default) entry - - rRetExcelName = pArray[0].Name; - return sal_True; - } - return false; -} - -void ScUnoAddInFuncData::SetFunction( const uno::Reference< reflection::XIdlMethod>& rNewFunc, const uno::Any& rNewObj ) -{ - xFunction = rNewFunc; - aObject = rNewObj; -} - -void ScUnoAddInFuncData::SetArguments( long nNewCount, const ScAddInArgDesc* pNewDescs ) -{ - delete[] pArgDescs; - - nArgCount = nNewCount; - if ( nArgCount ) - { - pArgDescs = new ScAddInArgDesc[nArgCount]; - for (long i=0; i<nArgCount; i++) - pArgDescs[i] = pNewDescs[i]; - } - else - pArgDescs = NULL; -} - -void ScUnoAddInFuncData::SetCallerPos( long nNewPos ) -{ - nCallerPos = nNewPos; -} - -//------------------------------------------------------------------------ - -ScUnoAddInCollection::ScUnoAddInCollection() : - nFuncCount( 0 ), - ppFuncData( NULL ), - pExactHashMap( NULL ), - pNameHashMap( NULL ), - pLocalHashMap( NULL ), - bInitialized( false ) -{ -} - -ScUnoAddInCollection::~ScUnoAddInCollection() -{ - Clear(); -} - -void ScUnoAddInCollection::Clear() -{ - DELETEZ( pExactHashMap ); - DELETEZ( pNameHashMap ); - DELETEZ( pLocalHashMap ); - if ( ppFuncData ) - { - for ( long i=0; i<nFuncCount; i++ ) - delete ppFuncData[i]; - delete[] ppFuncData; - } - ppFuncData = NULL; - nFuncCount = 0; - - bInitialized = false; -} - -uno::Reference<uno::XComponentContext> getContext(uno::Reference<lang::XMultiServiceFactory> xMSF) -{ - uno::Reference<uno::XComponentContext> xCtx; - try { - uno::Reference<beans::XPropertySet> xPropset(xMSF, uno::UNO_QUERY); - xPropset->getPropertyValue( - ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext"))) >>= xCtx; - } - catch ( uno::Exception & ) { - } - return xCtx; -} - -void ScUnoAddInCollection::Initialize() -{ - OSL_ENSURE( !bInitialized, "Initialize twice?" ); - - uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory(); - uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY ); - if ( xEnAc.is() ) - { - uno::Reference<container::XEnumeration> xEnum = - xEnAc->createContentEnumeration( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SCADDINSUPPLIER_SERVICE)) ); - if ( xEnum.is() ) - { - // loop through all AddIns - while ( xEnum->hasMoreElements() ) - { - uno::Any aAddInAny = xEnum->nextElement(); - - { - uno::Reference<uno::XInterface> xIntFac; - aAddInAny >>= xIntFac; - if ( xIntFac.is() ) - { - // #i59984# try XSingleComponentFactory in addition to (old) XSingleServiceFactory, - // passing the context to the component - - uno::Reference<uno::XInterface> xInterface; - uno::Reference<uno::XComponentContext> xCtx = getContext(xManager); - uno::Reference<lang::XSingleComponentFactory> xCFac( xIntFac, uno::UNO_QUERY ); - if (xCtx.is() && xCFac.is()) - { - xInterface = xCFac->createInstanceWithContext(xCtx); - if (xInterface.is()) - ReadFromAddIn( xInterface ); - } - - if (!xInterface.is()) - { - uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY ); - if ( xFac.is() ) - { - xInterface = xFac->createInstance(); - if (xInterface.is()) - ReadFromAddIn( xInterface ); - } - } - } - } - } - } - } - - // ReadConfiguration is called after looking at the AddIn implementations. - // Duplicated are skipped (by using the service information, they don't have to be updated again - // when argument information is needed). - ReadConfiguration(); - - bInitialized = sal_True; // with or without functions -} -// ----------------------------------------------------------------------------- - -sal_uInt16 lcl_GetCategory( const String& rName ) -{ - static const sal_Char* aFuncNames[SC_FUNCGROUP_COUNT] = - { - // array index = ID - 1 (ID starts at 1) - // all upper case - "Database", // ID_FUNCTION_GRP_DATABASE - "Date&Time", // ID_FUNCTION_GRP_DATETIME - "Financial", // ID_FUNCTION_GRP_FINANZ - "Information", // ID_FUNCTION_GRP_INFO - "Logical", // ID_FUNCTION_GRP_LOGIC - "Mathematical", // ID_FUNCTION_GRP_MATH - "Matrix", // ID_FUNCTION_GRP_MATRIX - "Statistical", // ID_FUNCTION_GRP_STATISTIC - "Spreadsheet", // ID_FUNCTION_GRP_TABLE - "Text", // ID_FUNCTION_GRP_TEXT - "Add-In" // ID_FUNCTION_GRP_ADDINS - }; - for (sal_uInt16 i=0; i<SC_FUNCGROUP_COUNT; i++) - if ( rName.EqualsAscii( aFuncNames[i] ) ) - return i+1; // IDs start at 1 - - return ID_FUNCTION_GRP_ADDINS; // if not found, use Add-In group -} - - -#define CFGPATH_ADDINS "Office.CalcAddIns/AddInInfo" -#define CFGSTR_ADDINFUNCTIONS "AddInFunctions" - -#define CFG_FUNCPROP_DISPLAYNAME 0 -#define CFG_FUNCPROP_DESCRIPTION 1 -#define CFG_FUNCPROP_CATEGORY 2 -#define CFG_FUNCPROP_COUNT 3 -#define CFGSTR_DISPLAYNAME "DisplayName" -#define CFGSTR_DESCRIPTION "Description" -#define CFGSTR_CATEGORY "Category" -// CategoryDisplayName is ignored for now - -#define CFGSTR_COMPATIBILITYNAME "CompatibilityName" -#define CFGSTR_PARAMETERS "Parameters" - - -void ScUnoAddInCollection::ReadConfiguration() -{ - // called only from Initialize - - ScAddInCfg& rAddInConfig = SC_MOD()->GetAddInCfg(); - - // additional, temporary config item for the compatibility names - ScLinkConfigItem aAllLocalesConfig( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGPATH_ADDINS )), CONFIG_MODE_ALL_LOCALES ); - // CommitLink is not used (only reading values) - - const rtl::OUString sSlash('/'); - - // get the list of add-ins (services) - rtl::OUString aEmptyString; - uno::Sequence<rtl::OUString> aServiceNames = rAddInConfig.GetNodeNames( aEmptyString ); - - sal_Int32 nServiceCount = aServiceNames.getLength(); - for ( sal_Int32 nService = 0; nService < nServiceCount; nService++ ) - { - rtl::OUString aServiceName = aServiceNames[nService]; - ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName ); - - rtl::OUString aFunctionsPath = aServiceName; - aFunctionsPath += sSlash; - aFunctionsPath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_ADDINFUNCTIONS) ); - - uno::Sequence<rtl::OUString> aFunctionNames = rAddInConfig.GetNodeNames( aFunctionsPath ); - sal_Int32 nNewCount = aFunctionNames.getLength(); - - // allocate pointers - - long nOld = nFuncCount; - nFuncCount = nNewCount+nOld; - if ( nOld ) - { - ScUnoAddInFuncData** ppNew = new ScUnoAddInFuncData*[nFuncCount]; - for (long i=0; i<nOld; i++) - ppNew[i] = ppFuncData[i]; - delete[] ppFuncData; - ppFuncData = ppNew; - } - else - ppFuncData = new ScUnoAddInFuncData*[nFuncCount]; - - //! TODO: adjust bucket count? - if ( !pExactHashMap ) - pExactHashMap = new ScAddInHashMap; - if ( !pNameHashMap ) - pNameHashMap = new ScAddInHashMap; - if ( !pLocalHashMap ) - pLocalHashMap = new ScAddInHashMap; - - //! get the function information in a single call for all functions? - - const rtl::OUString* pFuncNameArray = aFunctionNames.getConstArray(); - for ( sal_Int32 nFuncPos = 0; nFuncPos < nNewCount; nFuncPos++ ) - { - ppFuncData[nFuncPos+nOld] = NULL; - - // stored function name: (service name).(function) - String aFuncName( aServiceName ); - aFuncName += '.'; - aFuncName += String( pFuncNameArray[nFuncPos] ); - - // skip the function if already known (read from old AddIn service) - - if ( pExactHashMap->find( aFuncName ) == pExactHashMap->end() ) - { - rtl::OUString aLocalName; - rtl::OUString aDescription; - sal_uInt16 nCategory = ID_FUNCTION_GRP_ADDINS; - - // get direct information on the function - - rtl::OUString aFuncPropPath = aFunctionsPath; - aFuncPropPath += sSlash; - aFuncPropPath += pFuncNameArray[nFuncPos]; - aFuncPropPath += sSlash; - - uno::Sequence<rtl::OUString> aFuncPropNames(CFG_FUNCPROP_COUNT); - rtl::OUString* pNameArray = aFuncPropNames.getArray(); - pNameArray[CFG_FUNCPROP_DISPLAYNAME] = aFuncPropPath; - pNameArray[CFG_FUNCPROP_DISPLAYNAME] += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_DISPLAYNAME) ); - pNameArray[CFG_FUNCPROP_DESCRIPTION] = aFuncPropPath; - pNameArray[CFG_FUNCPROP_DESCRIPTION] += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_DESCRIPTION )); - pNameArray[CFG_FUNCPROP_CATEGORY] = aFuncPropPath; - pNameArray[CFG_FUNCPROP_CATEGORY] += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_CATEGORY) ); - - uno::Sequence<uno::Any> aFuncProperties = rAddInConfig.GetProperties( aFuncPropNames ); - if ( aFuncProperties.getLength() == CFG_FUNCPROP_COUNT ) - { - aFuncProperties[CFG_FUNCPROP_DISPLAYNAME] >>= aLocalName; - aFuncProperties[CFG_FUNCPROP_DESCRIPTION] >>= aDescription; - - rtl::OUString aCategoryName; - aFuncProperties[CFG_FUNCPROP_CATEGORY] >>= aCategoryName; - nCategory = lcl_GetCategory( aCategoryName ); - } - - // get compatibility names - - uno::Sequence<sheet::LocalizedName> aCompNames; - - rtl::OUString aCompPath = aFuncPropPath; - aCompPath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_COMPATIBILITYNAME )); - uno::Sequence<rtl::OUString> aCompPropNames( &aCompPath, 1 ); - - uno::Sequence<uno::Any> aCompProperties = aAllLocalesConfig.GetProperties( aCompPropNames ); - if ( aCompProperties.getLength() == 1 ) - { - uno::Sequence<beans::PropertyValue> aLocalEntries; - if ( aCompProperties[0] >>= aLocalEntries ) - { - sal_Int32 nLocaleCount = aLocalEntries.getLength(); - aCompNames.realloc( nLocaleCount ); - const beans::PropertyValue* pConfigArray = aLocalEntries.getConstArray(); - sheet::LocalizedName* pCompArray = aCompNames.getArray(); - - for ( sal_Int32 nLocale = 0; nLocale < nLocaleCount; nLocale++ ) - { - const sal_Unicode cLocaleSep = '-'; // separator in configuration locale strings - - // PropertyValue name is the locale (convert from string to Locale struct) - - const rtl::OUString& rLocaleStr = pConfigArray[nLocale].Name; - lang::Locale& rLocale = pCompArray[nLocale].Locale; - sal_Int32 nSepPos = rLocaleStr.indexOf( cLocaleSep ); - if ( nSepPos >= 0 ) - { - rLocale.Language = rLocaleStr.copy( 0, nSepPos ); - rLocale.Country = rLocaleStr.copy( nSepPos+1 ); - } - else - rLocale.Language = rLocaleStr; // leave country empty (default ctor from sequence) - - // PropertyValue value is the localized value (string in this case) - - pConfigArray[nLocale].Value >>= pCompArray[nLocale].Name; - } - } - } - - // get argument info - - ScAddInArgDesc* pVisibleArgs = NULL; - long nVisibleCount = 0; - long nCallerPos = SC_CALLERPOS_NONE; - - rtl::OUString aArgumentsPath = aFuncPropPath; - aArgumentsPath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_PARAMETERS) ); - - uno::Sequence<rtl::OUString> aArgumentNames = rAddInConfig.GetNodeNames( aArgumentsPath ); - sal_Int32 nArgumentCount = aArgumentNames.getLength(); - if ( nArgumentCount ) - { - // get DisplayName and Description for each argument - uno::Sequence<rtl::OUString> aArgPropNames( nArgumentCount * 2 ); - rtl::OUString* pPropNameArray = aArgPropNames.getArray(); - - sal_Int32 nArgument; - sal_Int32 nIndex = 0; - const rtl::OUString* pArgNameArray = aArgumentNames.getConstArray(); - for ( nArgument = 0; nArgument < nArgumentCount; nArgument++ ) - { - rtl::OUString aOneArgPath = aArgumentsPath; - aOneArgPath += sSlash; - aOneArgPath += pArgNameArray[nArgument]; - aOneArgPath += sSlash; - - pPropNameArray[nIndex] = aOneArgPath; - pPropNameArray[nIndex++] += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_DISPLAYNAME )); - pPropNameArray[nIndex] = aOneArgPath; - pPropNameArray[nIndex++] += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CFGSTR_DESCRIPTION )); - } - - uno::Sequence<uno::Any> aArgProperties = rAddInConfig.GetProperties( aArgPropNames ); - if ( aArgProperties.getLength() == aArgPropNames.getLength() ) - { - const uno::Any* pPropArray = aArgProperties.getConstArray(); - rtl::OUString sDisplayName; - rtl::OUString sDescription; - - ScAddInArgDesc aDesc; - aDesc.eType = SC_ADDINARG_NONE; // arg type is not in configuration - aDesc.bOptional = false; - - nVisibleCount = nArgumentCount; - pVisibleArgs = new ScAddInArgDesc[nVisibleCount]; - - nIndex = 0; - for ( nArgument = 0; nArgument < nArgumentCount; nArgument++ ) - { - pPropArray[nIndex++] >>= sDisplayName; - pPropArray[nIndex++] >>= sDescription; - - aDesc.aInternalName = pArgNameArray[nArgument]; - aDesc.aName = sDisplayName; - aDesc.aDescription = sDescription; - - pVisibleArgs[nArgument] = aDesc; - } - } - } - - rtl::OString sHelpId = aHelpIdGenerator.GetHelpId( pFuncNameArray[nFuncPos] ); - - uno::Reference<reflection::XIdlMethod> xFunc; // remains empty - uno::Any aObject; // also empty - - // create and insert into the array - - ScUnoAddInFuncData* pData = new ScUnoAddInFuncData( - aFuncName, aLocalName, aDescription, - nCategory, sHelpId, - xFunc, aObject, - nVisibleCount, pVisibleArgs, nCallerPos ); - - pData->SetCompNames( aCompNames ); - - ppFuncData[nFuncPos+nOld] = pData; - - pExactHashMap->insert( - ScAddInHashMap::value_type( - pData->GetOriginalName(), - pData ) ); - pNameHashMap->insert( - ScAddInHashMap::value_type( - pData->GetUpperName(), - pData ) ); - pLocalHashMap->insert( - ScAddInHashMap::value_type( - pData->GetUpperLocal(), - pData ) ); - - delete[] pVisibleArgs; - } - } - } -} - -void ScUnoAddInCollection::LoadComponent( const ScUnoAddInFuncData& rFuncData ) -{ - String aFullName = rFuncData.GetOriginalName(); - xub_StrLen nPos = aFullName.SearchBackward( (sal_Unicode) '.' ); - if ( nPos != STRING_NOTFOUND && nPos > 0 ) - { - String aServiceName = aFullName.Copy( 0, nPos ); - - uno::Reference<lang::XMultiServiceFactory> xServiceFactory = comphelper::getProcessServiceFactory(); - uno::Reference<uno::XInterface> xInterface( xServiceFactory->createInstance( aServiceName ) ); - - if (xInterface.is()) - UpdateFromAddIn( xInterface, aServiceName ); - } -} - -sal_Bool ScUnoAddInCollection::GetExcelName( const String& rCalcName, - LanguageType eDestLang, String& rRetExcelName ) -{ - const ScUnoAddInFuncData* pFuncData = GetFuncData( rCalcName ); - if ( pFuncData ) - return pFuncData->GetExcelName( eDestLang, rRetExcelName); - return false; -} - -sal_Bool ScUnoAddInCollection::GetCalcName( const String& rExcelName, String& rRetCalcName ) -{ - if (!bInitialized) - Initialize(); - - String aUpperCmp = rExcelName; - ScGlobal::pCharClass->toUpper(aUpperCmp); - - for (long i=0; i<nFuncCount; i++) - { - ScUnoAddInFuncData* pFuncData = ppFuncData[i]; - if ( pFuncData ) - { - const uno::Sequence<sheet::LocalizedName>& rSequence = pFuncData->GetCompNames(); - long nSeqLen = rSequence.getLength(); - if ( nSeqLen ) - { - const sheet::LocalizedName* pArray = rSequence.getConstArray(); - for ( long nName=0; nName<nSeqLen; nName++) - if ( ScGlobal::pCharClass->upper( pArray[nName].Name ) == aUpperCmp ) - { - //! store upper case for comparing? - - // use the first function that has this name for any language - rRetCalcName = pFuncData->GetOriginalName(); - return sal_True; - } - } - } - } - return false; -} - -inline sal_Bool IsTypeName( const rtl::OUString& rName, const uno::Type& rType ) -{ - return rName == rType.getTypeName(); -} - -sal_Bool lcl_ValidReturnType( const uno::Reference<reflection::XIdlClass>& xClass ) -{ - // this must match with ScUnoAddInCall::SetResult - - if ( !xClass.is() ) return false; - - switch (xClass->getTypeClass()) - { - case uno::TypeClass_ANY: // variable type - case uno::TypeClass_ENUM: //! ??? - case uno::TypeClass_BOOLEAN: - case uno::TypeClass_CHAR: - case uno::TypeClass_BYTE: - case uno::TypeClass_SHORT: - case uno::TypeClass_UNSIGNED_SHORT: - case uno::TypeClass_LONG: - case uno::TypeClass_UNSIGNED_LONG: - case uno::TypeClass_FLOAT: - case uno::TypeClass_DOUBLE: - case uno::TypeClass_STRING: - return sal_True; // values or string - - case uno::TypeClass_INTERFACE: - { - // return type XInterface may contain a XVolatileResult - //! XIdlClass needs getType() method! - - rtl::OUString sName = xClass->getName(); - return ( - IsTypeName( sName, getCppuType((uno::Reference<sheet::XVolatileResult>*)0) ) || - IsTypeName( sName, getCppuType((uno::Reference<uno::XInterface>*)0) ) ); - } - - default: - { - // nested sequences for arrays - //! XIdlClass needs getType() method! - - rtl::OUString sName = xClass->getName(); - return ( - IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<sal_Int32> >*)0) ) || - IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) ) || - IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) ) || - IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) ) ); - } - } - return false; -} - -ScAddInArgumentType lcl_GetArgType( const uno::Reference<reflection::XIdlClass>& xClass ) -{ - if (!xClass.is()) - return SC_ADDINARG_NONE; - - uno::TypeClass eType = xClass->getTypeClass(); - - if ( eType == uno::TypeClass_LONG ) //! other integer types? - return SC_ADDINARG_INTEGER; - - if ( eType == uno::TypeClass_DOUBLE ) - return SC_ADDINARG_DOUBLE; - - if ( eType == uno::TypeClass_STRING ) - return SC_ADDINARG_STRING; - - //! XIdlClass needs getType() method! - rtl::OUString sName = xClass->getName(); - - if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<sal_Int32> >*)0) )) - return SC_ADDINARG_INTEGER_ARRAY; - - if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) )) - return SC_ADDINARG_DOUBLE_ARRAY; - - if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) )) - return SC_ADDINARG_STRING_ARRAY; - - if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) )) - return SC_ADDINARG_MIXED_ARRAY; - - if (IsTypeName( sName, getCppuType((uno::Any*)0) )) - return SC_ADDINARG_VALUE_OR_ARRAY; - - if (IsTypeName( sName, getCppuType((uno::Reference<table::XCellRange>*)0) )) - return SC_ADDINARG_CELLRANGE; - - if (IsTypeName( sName, getCppuType((uno::Reference<beans::XPropertySet>*)0) )) - return SC_ADDINARG_CALLER; - - if (IsTypeName( sName, getCppuType((uno::Sequence<uno::Any>*)0) )) - return SC_ADDINARG_VARARGS; - - return SC_ADDINARG_NONE; -} - -void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>& xInterface ) -{ - uno::Reference<sheet::XAddIn> xAddIn( xInterface, uno::UNO_QUERY ); - uno::Reference<lang::XServiceName> xName( xInterface, uno::UNO_QUERY ); - if ( xAddIn.is() && xName.is() ) - { - // AddIns must use the language for which the office is installed - LanguageType eOfficeLang = Application::GetSettings().GetUILanguage(); - - lang::Locale aLocale( MsLangId::convertLanguageToLocale( eOfficeLang )); - xAddIn->setLocale( aLocale ); - - String aServiceName = String( xName->getServiceName() ); - ScUnoAddInHelpIdGenerator aHelpIdGenerator( xName->getServiceName() ); - - //! pass XIntrospection to ReadFromAddIn - - uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory(); - if ( xManager.is() ) - { - uno::Reference<beans::XIntrospection> xIntro( - xManager->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.beans.Introspection" ))), - uno::UNO_QUERY ); - if ( xIntro.is() ) - { - uno::Any aObject; - aObject <<= xAddIn; - uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject); - if (xAcc.is()) - { - uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods = - xAcc->getMethods( beans::MethodConcept::ALL ); - long nNewCount = aMethods.getLength(); - if ( nNewCount ) - { - long nOld = nFuncCount; - nFuncCount = nNewCount+nOld; - if ( nOld ) - { - ScUnoAddInFuncData** ppNew = new ScUnoAddInFuncData*[nFuncCount]; - for (long i=0; i<nOld; i++) - ppNew[i] = ppFuncData[i]; - delete[] ppFuncData; - ppFuncData = ppNew; - } - else - ppFuncData = new ScUnoAddInFuncData*[nFuncCount]; - - //! TODO: adjust bucket count? - if ( !pExactHashMap ) - pExactHashMap = new ScAddInHashMap; - if ( !pNameHashMap ) - pNameHashMap = new ScAddInHashMap; - if ( !pLocalHashMap ) - pLocalHashMap = new ScAddInHashMap; - - const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray(); - for (long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++) - { - ppFuncData[nFuncPos+nOld] = NULL; - - uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos]; - if (xFunc.is()) - { - // leave out internal functions - uno::Reference<reflection::XIdlClass> xClass = - xFunc->getDeclaringClass(); - sal_Bool bSkip = sal_True; - if ( xClass.is() ) - { - //! XIdlClass needs getType() method! - rtl::OUString sName = xClass->getName(); - bSkip = ( - IsTypeName( sName, - getCppuType((uno::Reference<uno::XInterface>*)0) ) || - IsTypeName( sName, - getCppuType((uno::Reference<reflection::XIdlClassProvider>*)0) ) || - IsTypeName( sName, - getCppuType((uno::Reference<lang::XServiceName>*)0) ) || - IsTypeName( sName, - getCppuType((uno::Reference<lang::XServiceInfo>*)0) ) || - IsTypeName( sName, - getCppuType((uno::Reference<sheet::XAddIn>*)0) ) ); - } - if (!bSkip) - { - uno::Reference<reflection::XIdlClass> xReturn = - xFunc->getReturnType(); - if ( !lcl_ValidReturnType( xReturn ) ) - bSkip = sal_True; - } - if (!bSkip) - { - rtl::OUString aFuncU = xFunc->getName(); - - // stored function name: (service name).(function) - String aFuncName = aServiceName; - aFuncName += '.'; - aFuncName += String( aFuncU ); - - sal_Bool bValid = sal_True; - long nVisibleCount = 0; - long nCallerPos = SC_CALLERPOS_NONE; - - uno::Sequence<reflection::ParamInfo> aParams = - xFunc->getParameterInfos(); - long nParamCount = aParams.getLength(); - const reflection::ParamInfo* pParArr = aParams.getConstArray(); - long nParamPos; - for (nParamPos=0; nParamPos<nParamCount; nParamPos++) - { - if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN ) - bValid = false; - uno::Reference<reflection::XIdlClass> xParClass = - pParArr[nParamPos].aType; - ScAddInArgumentType eArgType = lcl_GetArgType( xParClass ); - if ( eArgType == SC_ADDINARG_NONE ) - bValid = false; - else if ( eArgType == SC_ADDINARG_CALLER ) - nCallerPos = nParamPos; - else - ++nVisibleCount; - } - if (bValid) - { - sal_uInt16 nCategory = lcl_GetCategory( - String( - xAddIn->getProgrammaticCategoryName( - aFuncU ) ) ); - - rtl::OString sHelpId = aHelpIdGenerator.GetHelpId( aFuncU ); - - rtl::OUString aLocalU; - try - { - aLocalU = xAddIn-> - getDisplayFunctionName( aFuncU ); - } - catch(uno::Exception&) - { - aLocalU = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "###" )); - } - String aLocalName = String( aLocalU ); - - rtl::OUString aDescU; - try - { - aDescU = xAddIn-> - getFunctionDescription( aFuncU ); - } - catch(uno::Exception&) - { - aDescU = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "###" )); - } - String aDescription = String( aDescU ); - - ScAddInArgDesc* pVisibleArgs = NULL; - if ( nVisibleCount > 0 ) - { - ScAddInArgDesc aDesc; - pVisibleArgs = new ScAddInArgDesc[nVisibleCount]; - long nDestPos = 0; - for (nParamPos=0; nParamPos<nParamCount; nParamPos++) - { - uno::Reference<reflection::XIdlClass> xParClass = - pParArr[nParamPos].aType; - ScAddInArgumentType eArgType = lcl_GetArgType( xParClass ); - if ( eArgType != SC_ADDINARG_CALLER ) - { - rtl::OUString aArgName; - try - { - aArgName = xAddIn-> - getDisplayArgumentName( aFuncU, nParamPos ); - } - catch(uno::Exception&) - { - aArgName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "###" )); - } - rtl::OUString aArgDesc; - try - { - aArgDesc = xAddIn-> - getArgumentDescription( aFuncU, nParamPos ); - } - catch(uno::Exception&) - { - aArgName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "###" )); - } - - sal_Bool bOptional = - ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY || - eArgType == SC_ADDINARG_VARARGS ); - - aDesc.eType = eArgType; - aDesc.aName = String( aArgName ); - aDesc.aDescription = String( aArgDesc ); - aDesc.bOptional = bOptional; - //! initialize aInternalName only from config? - aDesc.aInternalName = pParArr[nParamPos].aName; - - pVisibleArgs[nDestPos++] = aDesc; - } - } - OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" ); - } - - ppFuncData[nFuncPos+nOld] = new ScUnoAddInFuncData( - aFuncName, aLocalName, aDescription, - nCategory, sHelpId, - xFunc, aObject, - nVisibleCount, pVisibleArgs, nCallerPos ); - - const ScUnoAddInFuncData* pData = - ppFuncData[nFuncPos+nOld]; - pExactHashMap->insert( - ScAddInHashMap::value_type( - pData->GetOriginalName(), - pData ) ); - pNameHashMap->insert( - ScAddInHashMap::value_type( - pData->GetUpperName(), - pData ) ); - pLocalHashMap->insert( - ScAddInHashMap::value_type( - pData->GetUpperLocal(), - pData ) ); - - delete[] pVisibleArgs; - } - } - } - } - } - } - } - } - } -} - -void lcl_UpdateFunctionList( ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData ) -{ - ::rtl::OUString aCompare = rFuncData.GetUpperLocal(); // as used in FillFunctionDescFromData - - sal_uLong nCount = rFunctionList.GetCount(); - for (sal_uLong nPos=0; nPos<nCount; nPos++) - { - const ScFuncDesc* pDesc = rFunctionList.GetFunction( nPos ); - if ( pDesc && pDesc->pFuncName && *pDesc->pFuncName == aCompare ) - { - ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc) ); - break; - } - } -} - -const ScAddInArgDesc* lcl_FindArgDesc( const ScUnoAddInFuncData& rFuncData, const String& rArgIntName ) -{ - long nArgCount = rFuncData.GetArgumentCount(); - const ScAddInArgDesc* pArguments = rFuncData.GetArguments(); - for (long nPos=0; nPos<nArgCount; nPos++) - { - if ( pArguments[nPos].aInternalName == rArgIntName ) - return &pArguments[nPos]; - } - return NULL; -} - -void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface>& xInterface, - const String& rServiceName ) -{ - uno::Reference<lang::XLocalizable> xLoc( xInterface, uno::UNO_QUERY ); - if ( xLoc.is() ) // optional in new add-ins - { - LanguageType eOfficeLang = Application::GetSettings().GetUILanguage(); - lang::Locale aLocale( MsLangId::convertLanguageToLocale( eOfficeLang )); - xLoc->setLocale( aLocale ); - } - - // if function list was already initialized, it must be updated - - ScFunctionList* pFunctionList = NULL; - if ( ScGlobal::HasStarCalcFunctionList() ) - pFunctionList = ScGlobal::GetStarCalcFunctionList(); - - // only get the function information from Introspection - - uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory(); - if ( xManager.is() ) - { - uno::Reference<beans::XIntrospection> xIntro( - xManager->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.beans.Introspection" ))), - uno::UNO_QUERY ); - if ( xIntro.is() ) - { - uno::Any aObject; - aObject <<= xInterface; - uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject); - if (xAcc.is()) - { - uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods = - xAcc->getMethods( beans::MethodConcept::ALL ); - long nMethodCount = aMethods.getLength(); - const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray(); - for (long nFuncPos=0; nFuncPos<nMethodCount; nFuncPos++) - { - uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos]; - if (xFunc.is()) - { - rtl::OUString aFuncU = xFunc->getName(); - - // stored function name: (service name).(function) - String aFuncName = rServiceName; - aFuncName += '.'; - aFuncName += String( aFuncU ); - - // internal names are skipped because no FuncData exists - ScUnoAddInFuncData* pOldData = const_cast<ScUnoAddInFuncData*>( GetFuncData( aFuncName ) ); - if ( pOldData ) - { - // Create new (complete) argument info. - // As in ReadFromAddIn, the reflection information is authoritative. - // Local names and descriptions from pOldData are looked up using the - // internal argument name. - - sal_Bool bValid = sal_True; - long nVisibleCount = 0; - long nCallerPos = SC_CALLERPOS_NONE; - - uno::Sequence<reflection::ParamInfo> aParams = - xFunc->getParameterInfos(); - long nParamCount = aParams.getLength(); - const reflection::ParamInfo* pParArr = aParams.getConstArray(); - long nParamPos; - for (nParamPos=0; nParamPos<nParamCount; nParamPos++) - { - if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN ) - bValid = false; - uno::Reference<reflection::XIdlClass> xParClass = - pParArr[nParamPos].aType; - ScAddInArgumentType eArgType = lcl_GetArgType( xParClass ); - if ( eArgType == SC_ADDINARG_NONE ) - bValid = false; - else if ( eArgType == SC_ADDINARG_CALLER ) - nCallerPos = nParamPos; - else - ++nVisibleCount; - } - if (bValid) - { - ScAddInArgDesc* pVisibleArgs = NULL; - if ( nVisibleCount > 0 ) - { - ScAddInArgDesc aDesc; - pVisibleArgs = new ScAddInArgDesc[nVisibleCount]; - long nDestPos = 0; - for (nParamPos=0; nParamPos<nParamCount; nParamPos++) - { - uno::Reference<reflection::XIdlClass> xParClass = - pParArr[nParamPos].aType; - ScAddInArgumentType eArgType = lcl_GetArgType( xParClass ); - if ( eArgType != SC_ADDINARG_CALLER ) - { - const ScAddInArgDesc* pOldArgDesc = - lcl_FindArgDesc( *pOldData, pParArr[nParamPos].aName ); - if ( pOldArgDesc ) - { - aDesc.aName = pOldArgDesc->aName; - aDesc.aDescription = pOldArgDesc->aDescription; - } - else - aDesc.aName = aDesc.aDescription = String::CreateFromAscii( "###" ); - - sal_Bool bOptional = - ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY || - eArgType == SC_ADDINARG_VARARGS ); - - aDesc.eType = eArgType; - aDesc.bOptional = bOptional; - //! initialize aInternalName only from config? - aDesc.aInternalName = pParArr[nParamPos].aName; - - pVisibleArgs[nDestPos++] = aDesc; - } - } - OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" ); - } - - pOldData->SetFunction( xFunc, aObject ); - pOldData->SetArguments( nVisibleCount, pVisibleArgs ); - pOldData->SetCallerPos( nCallerPos ); - - if ( pFunctionList ) - lcl_UpdateFunctionList( *pFunctionList, *pOldData ); - - delete[] pVisibleArgs; - } - } - } - } - } - } - } -} - -String ScUnoAddInCollection::FindFunction( const String& rUpperName, sal_Bool bLocalFirst ) -{ - if (!bInitialized) - Initialize(); - - if (nFuncCount == 0) - return EMPTY_STRING; - - if ( bLocalFirst ) - { - // first scan all local names (used for entering formulas) - - ScAddInHashMap::const_iterator iLook( pLocalHashMap->find( rUpperName ) ); - if ( iLook != pLocalHashMap->end() ) - return iLook->second->GetOriginalName(); - } - else - { - // first scan international names (used when calling a function) - //! before that, check for exact match??? - - ScAddInHashMap::const_iterator iLook( pNameHashMap->find( rUpperName ) ); - if ( iLook != pNameHashMap->end() ) - return iLook->second->GetOriginalName(); - - // after that, scan all local names (to allow replacing old AddIns with Uno) - - iLook = pLocalHashMap->find( rUpperName ); - if ( iLook != pLocalHashMap->end() ) - return iLook->second->GetOriginalName(); - } - - return EMPTY_STRING; -} - -const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( const String& rName, bool bComplete ) -{ - if (!bInitialized) - Initialize(); - - // rName must be the exact internal name - - ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) ); - if ( iLook != pExactHashMap->end() ) - { - const ScUnoAddInFuncData* pFuncData = iLook->second; - - if ( bComplete && !pFuncData->GetFunction().is() ) //! extra flag? - LoadComponent( *pFuncData ); - - return pFuncData; - } - - return NULL; -} - -const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( long nIndex ) -{ - if (!bInitialized) - Initialize(); - - if (nIndex < nFuncCount) - return ppFuncData[nIndex]; - return NULL; -} - -void ScUnoAddInCollection::LocalizeString( String& rName ) -{ - if (!bInitialized) - Initialize(); - - // modify rName - input: exact name - - ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) ); - if ( iLook != pExactHashMap->end() ) - rName = iLook->second->GetUpperLocal(); //! upper? -} - - -long ScUnoAddInCollection::GetFuncCount() -{ - if (!bInitialized) - Initialize(); - - return nFuncCount; -} - -sal_Bool ScUnoAddInCollection::FillFunctionDesc( long nFunc, ScFuncDesc& rDesc ) -{ - if (!bInitialized) - Initialize(); - - if (nFunc >= nFuncCount || !ppFuncData[nFunc]) - return false; - - const ScUnoAddInFuncData& rFuncData = *ppFuncData[nFunc]; - - return FillFunctionDescFromData( rFuncData, rDesc ); -} - -sal_Bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc ) -{ - rDesc.Clear(); - - sal_Bool bIncomplete = !rFuncData.GetFunction().is(); //! extra flag? - - long nArgCount = rFuncData.GetArgumentCount(); - if ( nArgCount > USHRT_MAX ) - return false; - - if ( bIncomplete ) - nArgCount = 0; // if incomplete, fill without argument info (no wrong order) - - // nFIndex is set from outside - - rDesc.pFuncName = new ::rtl::OUString( rFuncData.GetUpperLocal() ); //! upper? - rDesc.nCategory = rFuncData.GetCategory(); - rDesc.sHelpId = rFuncData.GetHelpId(); - - String aDesc = rFuncData.GetDescription(); - if (!aDesc.Len()) - aDesc = rFuncData.GetLocalName(); // use name if no description is available - rDesc.pFuncDesc = new ::rtl::OUString( aDesc ); - - // AddInArgumentType_CALLER is already left out in FuncData - - rDesc.nArgCount = (sal_uInt16)nArgCount; - if ( nArgCount ) - { - sal_Bool bMultiple = false; - const ScAddInArgDesc* pArgs = rFuncData.GetArguments(); - - rDesc.ppDefArgNames = new ::rtl::OUString*[nArgCount]; - rDesc.ppDefArgDescs = new ::rtl::OUString*[nArgCount]; - rDesc.pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgCount]; - for ( long nArg=0; nArg<nArgCount; nArg++ ) - { - rDesc.ppDefArgNames[nArg] = new ::rtl::OUString( pArgs[nArg].aName ); - rDesc.ppDefArgDescs[nArg] = new ::rtl::OUString( pArgs[nArg].aDescription ); - rDesc.pDefArgFlags[nArg].bOptional = pArgs[nArg].bOptional; - rDesc.pDefArgFlags[nArg].bSuppress = false; - - // no empty names... - if ( rDesc.ppDefArgNames[nArg]->getLength() == 0 ) - { - String aDefName( RTL_CONSTASCII_USTRINGPARAM("arg") ); - aDefName += String::CreateFromInt32( nArg+1 ); - *rDesc.ppDefArgNames[nArg] = aDefName; - } - - // last argument repeated? - if ( nArg+1 == nArgCount && ( pArgs[nArg].eType == SC_ADDINARG_VARARGS ) ) - bMultiple = sal_True; - } - - if ( bMultiple ) - rDesc.nArgCount += VAR_ARGS - 1; // VAR_ARGS means just one repeated arg - } - - rDesc.bIncomplete = bIncomplete; - - return sal_True; -} - - -//------------------------------------------------------------------------ - -ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection& rColl, const String& rName, - long nParamCount ) : - bValidCount( false ), - nErrCode( errNoCode ), // before function was called - bHasString( sal_True ), - fValue( 0.0 ), - xMatrix( NULL ) -{ - pFuncData = rColl.GetFuncData( rName, true ); // need fully initialized data - OSL_ENSURE( pFuncData, "Function Data missing" ); - if ( pFuncData ) - { - long nDescCount = pFuncData->GetArgumentCount(); - const ScAddInArgDesc* pArgs = pFuncData->GetArguments(); - - // is aVarArg sequence needed? - if ( nParamCount >= nDescCount && nDescCount > 0 && - pArgs[nDescCount-1].eType == SC_ADDINARG_VARARGS ) - { - long nVarCount = nParamCount - ( nDescCount - 1 ); // size of last argument - aVarArg.realloc( nVarCount ); - bValidCount = sal_True; - } - else if ( nParamCount <= nDescCount ) - { - // all args behind nParamCount must be optional - bValidCount = sal_True; - for (long i=nParamCount; i<nDescCount; i++) - if ( !pArgs[i].bOptional ) - bValidCount = false; - } - // else invalid (too many arguments) - - if ( bValidCount ) - aArgs.realloc( nDescCount ); // sequence must always match function signature - } -} - -ScUnoAddInCall::~ScUnoAddInCall() -{ - // pFuncData is deleted with ScUnoAddInCollection -} - -sal_Bool ScUnoAddInCall::ValidParamCount() -{ - return bValidCount; -} - -ScAddInArgumentType ScUnoAddInCall::GetArgType( long nPos ) -{ - if ( pFuncData ) - { - long nCount = pFuncData->GetArgumentCount(); - const ScAddInArgDesc* pArgs = pFuncData->GetArguments(); - - // if last arg is sequence, use "any" type - if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS ) - return SC_ADDINARG_VALUE_OR_ARRAY; - - if ( nPos < nCount ) - return pArgs[nPos].eType; - } - return SC_ADDINARG_VALUE_OR_ARRAY; //! error code !!!! -} - -sal_Bool ScUnoAddInCall::NeedsCaller() const -{ - return pFuncData && pFuncData->GetCallerPos() != SC_CALLERPOS_NONE; -} - -void ScUnoAddInCall::SetCaller( const uno::Reference<uno::XInterface>& rInterface ) -{ - xCaller = rInterface; -} - -void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell* pObjSh ) -{ - if (pObjSh) - { - uno::Reference<uno::XInterface> xInt( pObjSh->GetBaseModel(), uno::UNO_QUERY ); - SetCaller( xInt ); - } -} - -void ScUnoAddInCall::SetParam( long nPos, const uno::Any& rValue ) -{ - if ( pFuncData ) - { - long nCount = pFuncData->GetArgumentCount(); - const ScAddInArgDesc* pArgs = pFuncData->GetArguments(); - if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS ) - { - long nVarPos = nPos-(nCount-1); - if ( nVarPos < aVarArg.getLength() ) - aVarArg.getArray()[nVarPos] = rValue; - else - { - OSL_FAIL("wrong argument number"); - } - } - else if ( nPos < aArgs.getLength() ) - aArgs.getArray()[nPos] = rValue; - else - { - OSL_FAIL("wrong argument number"); - } - } -} - -void ScUnoAddInCall::ExecuteCall() -{ - if ( !pFuncData ) - return; - - long nCount = pFuncData->GetArgumentCount(); - const ScAddInArgDesc* pArgs = pFuncData->GetArguments(); - if ( nCount > 0 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS ) - { - // insert aVarArg as last argument - //! after inserting caller (to prevent copying twice)? - - OSL_ENSURE( aArgs.getLength() == nCount, "wrong argument count" ); - aArgs.getArray()[nCount-1] <<= aVarArg; - } - - if ( pFuncData->GetCallerPos() != SC_CALLERPOS_NONE ) - { - uno::Any aCallerAny; - aCallerAny <<= xCaller; - - long nUserLen = aArgs.getLength(); - long nCallPos = pFuncData->GetCallerPos(); - if (nCallPos>nUserLen) // should not happen - { - OSL_FAIL("wrong CallPos"); - nCallPos = nUserLen; - } - - long nDestLen = nUserLen + 1; - uno::Sequence<uno::Any> aRealArgs( nDestLen ); - uno::Any* pDest = aRealArgs.getArray(); - - const uno::Any* pSource = aArgs.getConstArray(); - long nSrcPos = 0; - - for ( long nDestPos = 0; nDestPos < nDestLen; nDestPos++ ) - { - if ( nDestPos == nCallPos ) - pDest[nDestPos] = aCallerAny; - else - pDest[nDestPos] = pSource[nSrcPos++]; - } - - ExecuteCallWithArgs( aRealArgs ); - } - else - ExecuteCallWithArgs( aArgs ); -} - -void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs) -{ - // rCallArgs may not match argument descriptions (because of caller) - - uno::Reference<reflection::XIdlMethod> xFunction; - uno::Any aObject; - if ( pFuncData ) - { - xFunction = pFuncData->GetFunction(); - aObject = pFuncData->GetObject(); - } - - if ( xFunction.is() ) - { - uno::Any aAny; - nErrCode = 0; - - try - { - aAny = xFunction->invoke( aObject, rCallArgs ); - } - catch(lang::IllegalArgumentException&) - { - nErrCode = errIllegalArgument; - } - - catch(reflection::InvocationTargetException& rWrapped) - { - if ( rWrapped.TargetException.getValueType().equals( - getCppuType( (lang::IllegalArgumentException*)0 ) ) ) - nErrCode = errIllegalArgument; - else if ( rWrapped.TargetException.getValueType().equals( - getCppuType( (sheet::NoConvergenceException*)0 ) ) ) - nErrCode = errNoConvergence; - else - nErrCode = errNoValue; - } - - catch(uno::Exception&) - { - nErrCode = errNoValue; - } - - if (!nErrCode) - SetResult( aAny ); // convert result to Calc types - } -} - -void ScUnoAddInCall::SetResult( const uno::Any& rNewRes ) -{ - nErrCode = 0; - xVarRes = NULL; - - // Reflection* pRefl = rNewRes.getReflection(); - - uno::TypeClass eClass = rNewRes.getValueTypeClass(); - uno::Type aType = rNewRes.getValueType(); - switch (eClass) - { - case uno::TypeClass_VOID: - nErrCode = NOTAVAILABLE; // #NA - break; - - case uno::TypeClass_ENUM: - case uno::TypeClass_BOOLEAN: - case uno::TypeClass_CHAR: - case uno::TypeClass_BYTE: - case uno::TypeClass_SHORT: - case uno::TypeClass_UNSIGNED_SHORT: - case uno::TypeClass_LONG: - case uno::TypeClass_UNSIGNED_LONG: - case uno::TypeClass_FLOAT: - case uno::TypeClass_DOUBLE: - { - uno::TypeClass eMyClass; - ScApiTypeConversion::ConvertAnyToDouble( fValue, eMyClass, rNewRes); - bHasString = false; - } - break; - - case uno::TypeClass_STRING: - { - rtl::OUString aUStr; - rNewRes >>= aUStr; - aString = String( aUStr ); - bHasString = sal_True; - } - break; - - case uno::TypeClass_INTERFACE: - { - //! directly extract XVolatileResult from any? - uno::Reference<uno::XInterface> xInterface; - rNewRes >>= xInterface; - if ( xInterface.is() ) - xVarRes = uno::Reference<sheet::XVolatileResult>( xInterface, uno::UNO_QUERY ); - - if (!xVarRes.is()) - nErrCode = errNoValue; // unknown interface - } - break; - - default: - if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int32> > *)0 ) ) ) - { - const uno::Sequence< uno::Sequence<sal_Int32> >* pRowSeq = NULL; - - //! use pointer from any! - uno::Sequence< uno::Sequence<sal_Int32> > aSequence; - if ( rNewRes >>= aSequence ) - pRowSeq = &aSequence; - - if ( pRowSeq ) - { - long nRowCount = pRowSeq->getLength(); - const uno::Sequence<sal_Int32>* pRowArr = pRowSeq->getConstArray(); - long nMaxColCount = 0; - long nCol, nRow; - for (nRow=0; nRow<nRowCount; nRow++) - { - long nTmp = pRowArr[nRow].getLength(); - if ( nTmp > nMaxColCount ) - nMaxColCount = nTmp; - } - if ( nMaxColCount && nRowCount ) - { - xMatrix = new ScMatrix( - static_cast<SCSIZE>(nMaxColCount), - static_cast<SCSIZE>(nRowCount) ); - for (nRow=0; nRow<nRowCount; nRow++) - { - long nColCount = pRowArr[nRow].getLength(); - const sal_Int32* pColArr = pRowArr[nRow].getConstArray(); - for (nCol=0; nCol<nColCount; nCol++) - xMatrix->PutDouble( pColArr[nCol], - static_cast<SCSIZE>(nCol), - static_cast<SCSIZE>(nRow) ); - for (nCol=nColCount; nCol<nMaxColCount; nCol++) - xMatrix->PutDouble( 0.0, - static_cast<SCSIZE>(nCol), - static_cast<SCSIZE>(nRow) ); - } - } - } - } - else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) ) - { - const uno::Sequence< uno::Sequence<double> >* pRowSeq = NULL; - - //! use pointer from any! - uno::Sequence< uno::Sequence<double> > aSequence; - if ( rNewRes >>= aSequence ) - pRowSeq = &aSequence; - - if ( pRowSeq ) - { - long nRowCount = pRowSeq->getLength(); - const uno::Sequence<double>* pRowArr = pRowSeq->getConstArray(); - long nMaxColCount = 0; - long nCol, nRow; - for (nRow=0; nRow<nRowCount; nRow++) - { - long nTmp = pRowArr[nRow].getLength(); - if ( nTmp > nMaxColCount ) - nMaxColCount = nTmp; - } - if ( nMaxColCount && nRowCount ) - { - xMatrix = new ScMatrix( - static_cast<SCSIZE>(nMaxColCount), - static_cast<SCSIZE>(nRowCount) ); - for (nRow=0; nRow<nRowCount; nRow++) - { - long nColCount = pRowArr[nRow].getLength(); - const double* pColArr = pRowArr[nRow].getConstArray(); - for (nCol=0; nCol<nColCount; nCol++) - xMatrix->PutDouble( pColArr[nCol], - static_cast<SCSIZE>(nCol), - static_cast<SCSIZE>(nRow) ); - for (nCol=nColCount; nCol<nMaxColCount; nCol++) - xMatrix->PutDouble( 0.0, - static_cast<SCSIZE>(nCol), - static_cast<SCSIZE>(nRow) ); - } - } - } - } - else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) ) - { - const uno::Sequence< uno::Sequence<rtl::OUString> >* pRowSeq = NULL; - - //! use pointer from any! - uno::Sequence< uno::Sequence<rtl::OUString> > aSequence; - if ( rNewRes >>= aSequence ) - pRowSeq = &aSequence; - - if ( pRowSeq ) - { - long nRowCount = pRowSeq->getLength(); - const uno::Sequence<rtl::OUString>* pRowArr = pRowSeq->getConstArray(); - long nMaxColCount = 0; - long nCol, nRow; - for (nRow=0; nRow<nRowCount; nRow++) - { - long nTmp = pRowArr[nRow].getLength(); - if ( nTmp > nMaxColCount ) - nMaxColCount = nTmp; - } - if ( nMaxColCount && nRowCount ) - { - xMatrix = new ScMatrix( - static_cast<SCSIZE>(nMaxColCount), - static_cast<SCSIZE>(nRowCount) ); - for (nRow=0; nRow<nRowCount; nRow++) - { - long nColCount = pRowArr[nRow].getLength(); - const rtl::OUString* pColArr = pRowArr[nRow].getConstArray(); - for (nCol=0; nCol<nColCount; nCol++) - xMatrix->PutString( String( pColArr[nCol] ), - static_cast<SCSIZE>(nCol), - static_cast<SCSIZE>(nRow) ); - for (nCol=nColCount; nCol<nMaxColCount; nCol++) - xMatrix->PutString( EMPTY_STRING, - static_cast<SCSIZE>(nCol), - static_cast<SCSIZE>(nRow) ); - } - } - } - } - else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) ) - { - xMatrix = ScSequenceToMatrix::CreateMixedMatrix( rNewRes ); - } - - if (!xMatrix) // no array found - nErrCode = errNoValue; //! code for error in return type??? - } -} - - - -//------------------------------------------------------------------------ - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |