LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/tool - addincol.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 263 872 30.2 %
Date: 2012-12-27 Functions: 14 42 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <comphelper/processfactory.hxx>
      21             : #include <i18npool/languagetag.hxx>
      22             : #include <vcl/svapp.hxx>
      23             : #include <sfx2/objsh.hxx>
      24             : #include <unotools/charclass.hxx>
      25             : 
      26             : #include <com/sun/star/container/XContentEnumerationAccess.hpp>
      27             : #include <com/sun/star/lang/XServiceName.hpp>
      28             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      29             : #include <com/sun/star/lang/XSingleComponentFactory.hpp>
      30             : #include <com/sun/star/reflection/XIdlClass.hpp>
      31             : #include <com/sun/star/beans/XIntrospectionAccess.hpp>
      32             : #include <com/sun/star/beans/Introspection.hpp>
      33             : #include <com/sun/star/beans/MethodConcept.hpp>
      34             : #include <com/sun/star/beans/XPropertySet.hpp>
      35             : #include <com/sun/star/table/XCellRange.hpp>
      36             : #include <com/sun/star/lang/Locale.hpp>
      37             : #include <com/sun/star/sheet/XCompatibilityNames.hpp>
      38             : #include <com/sun/star/sheet/NoConvergenceException.hpp>
      39             : 
      40             : #include "addincol.hxx"
      41             : #include "addinhelpid.hxx"
      42             : #include "compiler.hxx"
      43             : #include "scmatrix.hxx"
      44             : #include "addinlis.hxx"
      45             : #include "formula/errorcodes.hxx"
      46             : #include "scfuncs.hrc"
      47             : #include "optutil.hxx"
      48             : #include "addincfg.hxx"
      49             : #include "scmod.hxx"
      50             : #include "rangeseq.hxx"
      51             : #include "funcdesc.hxx"
      52             : 
      53             : using namespace com::sun::star;
      54             : 
      55             : //------------------------------------------------------------------------
      56             : 
      57             : #define SC_CALLERPOS_NONE   (-1)
      58             : 
      59             : #define SCADDINSUPPLIER_SERVICE "com.sun.star.sheet.AddIn"
      60             : 
      61             : //------------------------------------------------------------------------
      62             : 
      63             : 
      64             : 
      65             : 
      66             : //------------------------------------------------------------------------
      67             : 
      68         327 : ScUnoAddInFuncData::ScUnoAddInFuncData( const ::rtl::OUString& rNam, const ::rtl::OUString& rLoc,
      69             :                                         const ::rtl::OUString& rDesc,
      70             :                                         sal_uInt16 nCat, const rtl::OString& sHelp,
      71             :                                         const uno::Reference<reflection::XIdlMethod>& rFunc,
      72             :                                         const uno::Any& rO,
      73             :                                         long nAC, const ScAddInArgDesc* pAD,
      74             :                                         long nCP ) :
      75             :     aOriginalName( rNam ),
      76             :     aLocalName( rLoc ),
      77             :     aUpperName( rNam ),
      78             :     aUpperLocal( rLoc ),
      79             :     aDescription( rDesc ),
      80             :     xFunction( rFunc ),
      81             :     aObject( rO ),
      82             :     nArgCount( nAC ),
      83             :     nCallerPos( nCP ),
      84             :     nCategory( nCat ),
      85             :     sHelpId( sHelp ),
      86         327 :     bCompInitialized( false )
      87             : {
      88         327 :     if ( nArgCount )
      89             :     {
      90         327 :         pArgDescs = new ScAddInArgDesc[nArgCount];
      91        1242 :         for (long i=0; i<nArgCount; i++)
      92         915 :             pArgDescs[i] = pAD[i];
      93             :     }
      94             :     else
      95           0 :         pArgDescs = NULL;
      96             : 
      97         327 :     aUpperName = ScGlobal::pCharClass->uppercase(aUpperName);
      98         327 :     aUpperLocal = ScGlobal::pCharClass->uppercase(aUpperLocal);
      99         327 : }
     100             : 
     101           0 : ScUnoAddInFuncData::~ScUnoAddInFuncData()
     102             : {
     103           0 :     delete[] pArgDescs;
     104           0 : }
     105             : 
     106         109 : const uno::Sequence<sheet::LocalizedName>& ScUnoAddInFuncData::GetCompNames() const
     107             : {
     108         109 :     if ( !bCompInitialized )
     109             :     {
     110             :         //  read sequence of compatibility names on demand
     111             : 
     112         109 :         uno::Reference<sheet::XAddIn> xAddIn;
     113         109 :         if ( aObject >>= xAddIn )
     114             :         {
     115         109 :             uno::Reference<sheet::XCompatibilityNames> xComp( xAddIn, uno::UNO_QUERY );
     116         109 :             if ( xComp.is() && xFunction.is() )
     117             :             {
     118         109 :                 rtl::OUString aMethodName = xFunction->getName();
     119         109 :                 aCompNames = xComp->getCompatibilityNames( aMethodName );
     120             : 
     121             :                 //  change all locale entries to default case
     122             :                 //  (language in lower case, country in upper case)
     123             :                 //  for easier searching
     124             : 
     125         109 :                 long nSeqLen = aCompNames.getLength();
     126         109 :                 if ( nSeqLen )
     127             :                 {
     128         109 :                     sheet::LocalizedName* pArray = aCompNames.getArray();
     129         327 :                     for (long i=0; i<nSeqLen; i++)
     130             :                     {
     131         218 :                         lang::Locale& rLocale = pArray[i].Locale;
     132         218 :                         rLocale.Language = rLocale.Language.toAsciiLowerCase();
     133         218 :                         rLocale.Country  = rLocale.Country.toAsciiUpperCase();
     134             :                     }
     135         109 :                 }
     136         109 :             }
     137             :         }
     138             : 
     139         109 :         bCompInitialized = sal_True;        // also if not successful
     140             :     }
     141         109 :     return aCompNames;
     142             : }
     143             : 
     144           0 : void ScUnoAddInFuncData::SetCompNames( const uno::Sequence< sheet::LocalizedName>& rNew )
     145             : {
     146             :     OSL_ENSURE( !bCompInitialized, "SetCompNames after initializing" );
     147             : 
     148           0 :     aCompNames = rNew;
     149             : 
     150             :     //  change all locale entries to default case
     151             :     //  (language in lower case, country in upper case)
     152             :     //  for easier searching
     153             : 
     154           0 :     long nSeqLen = aCompNames.getLength();
     155           0 :     if ( nSeqLen )
     156             :     {
     157           0 :         sheet::LocalizedName* pArray = aCompNames.getArray();
     158           0 :         for (long i=0; i<nSeqLen; i++)
     159             :         {
     160           0 :             lang::Locale& rLocale = pArray[i].Locale;
     161           0 :             rLocale.Language = rLocale.Language.toAsciiLowerCase();
     162           0 :             rLocale.Country  = rLocale.Country.toAsciiUpperCase();
     163             :         }
     164             :     }
     165             : 
     166           0 :     bCompInitialized = sal_True;
     167           0 : }
     168             : 
     169         109 : sal_Bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang, ::rtl::OUString& rRetExcelName ) const
     170             : {
     171         109 :     const uno::Sequence<sheet::LocalizedName>& rSequence = GetCompNames();
     172         109 :     long nSeqLen = rSequence.getLength();
     173         109 :     if ( nSeqLen )
     174             :     {
     175         109 :         const sheet::LocalizedName* pArray = rSequence.getConstArray();
     176             :         long i;
     177             : 
     178             :         /* FIXME-BCP47: we may want to handle language tags here as well. */
     179         109 :         rtl::OUString aLangStr, aCountryStr;
     180         109 :         LanguageTag( eDestLang ).getIsoLanguageCountry( aLangStr, aCountryStr );
     181         109 :         rtl::OUString aUserLang = aLangStr.toAsciiLowerCase();
     182         109 :         rtl::OUString aUserCountry = aCountryStr.toAsciiUpperCase();
     183             : 
     184             :         //  first check for match of both language and country
     185             : 
     186         218 :         for ( i=0; i<nSeqLen; i++)
     187         327 :             if ( pArray[i].Locale.Language == aUserLang &&
     188         109 :                     pArray[i].Locale.Country  == aUserCountry )
     189             :             {
     190         109 :                 rRetExcelName = pArray[i].Name;
     191         109 :                 return sal_True;
     192             :             }
     193             : 
     194             :         //  second: check only language
     195             : 
     196           0 :         for ( i=0; i<nSeqLen; i++)
     197           0 :             if ( pArray[i].Locale.Language == aUserLang )
     198             :             {
     199           0 :                 rRetExcelName = pArray[i].Name;
     200           0 :                 return sal_True;
     201             :             }
     202             : 
     203             :         // third: #i57772# fall-back to en-US
     204             : 
     205           0 :         if ( eDestLang != LANGUAGE_ENGLISH_US )
     206           0 :             return GetExcelName( LANGUAGE_ENGLISH_US, rRetExcelName );
     207             : 
     208             :         //  forth: use first (default) entry
     209             : 
     210           0 :         rRetExcelName = pArray[0].Name;
     211           0 :         return sal_True;
     212             :     }
     213           0 :     return false;
     214             : }
     215             : 
     216           0 : void ScUnoAddInFuncData::SetFunction( const uno::Reference< reflection::XIdlMethod>& rNewFunc, const uno::Any& rNewObj )
     217             : {
     218           0 :     xFunction = rNewFunc;
     219           0 :     aObject = rNewObj;
     220           0 : }
     221             : 
     222           0 : void ScUnoAddInFuncData::SetArguments( long nNewCount, const ScAddInArgDesc* pNewDescs )
     223             : {
     224           0 :     delete[] pArgDescs;
     225             : 
     226           0 :     nArgCount = nNewCount;
     227           0 :     if ( nArgCount )
     228             :     {
     229           0 :         pArgDescs = new ScAddInArgDesc[nArgCount];
     230           0 :         for (long i=0; i<nArgCount; i++)
     231           0 :             pArgDescs[i] = pNewDescs[i];
     232             :     }
     233             :     else
     234           0 :         pArgDescs = NULL;
     235           0 : }
     236             : 
     237           0 : void ScUnoAddInFuncData::SetCallerPos( long nNewPos )
     238             : {
     239           0 :     nCallerPos = nNewPos;
     240           0 : }
     241             : 
     242             : //------------------------------------------------------------------------
     243             : 
     244           4 : ScUnoAddInCollection::ScUnoAddInCollection() :
     245             :     nFuncCount( 0 ),
     246             :     ppFuncData( NULL ),
     247             :     pExactHashMap( NULL ),
     248             :     pNameHashMap( NULL ),
     249             :     pLocalHashMap( NULL ),
     250           4 :     bInitialized( false )
     251             : {
     252           4 : }
     253             : 
     254           0 : ScUnoAddInCollection::~ScUnoAddInCollection()
     255             : {
     256           0 :     Clear();
     257           0 : }
     258             : 
     259           0 : void ScUnoAddInCollection::Clear()
     260             : {
     261           0 :     DELETEZ( pExactHashMap );
     262           0 :     DELETEZ( pNameHashMap );
     263           0 :     DELETEZ( pLocalHashMap );
     264           0 :     if ( ppFuncData )
     265             :     {
     266           0 :         for ( long i=0; i<nFuncCount; i++ )
     267           0 :             delete ppFuncData[i];
     268           0 :         delete[] ppFuncData;
     269             :     }
     270           0 :     ppFuncData = NULL;
     271           0 :     nFuncCount = 0;
     272             : 
     273           0 :     bInitialized = false;
     274           0 : }
     275             : 
     276           4 : void ScUnoAddInCollection::Initialize()
     277             : {
     278             :     OSL_ENSURE( !bInitialized, "Initialize twice?" );
     279             : 
     280           4 :     uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
     281           4 :     uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
     282           4 :     if ( xEnAc.is() )
     283             :     {
     284             :         uno::Reference<container::XEnumeration> xEnum =
     285           4 :                         xEnAc->createContentEnumeration(
     286           4 :                             rtl::OUString(SCADDINSUPPLIER_SERVICE) );
     287           4 :         if ( xEnum.is() )
     288             :         {
     289             :             //  loop through all AddIns
     290          14 :             while ( xEnum->hasMoreElements() )
     291             :             {
     292           6 :                 uno::Any aAddInAny = xEnum->nextElement();
     293             : 
     294             :                 {
     295           6 :                     uno::Reference<uno::XInterface> xIntFac;
     296           6 :                     aAddInAny >>= xIntFac;
     297           6 :                     if ( xIntFac.is() )
     298             :                     {
     299             :                         // #i59984# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
     300             :                         // passing the context to the component
     301             : 
     302           6 :                         uno::Reference<uno::XInterface> xInterface;
     303             :                         uno::Reference<uno::XComponentContext> xCtx(
     304           6 :                             comphelper::getComponentContext(xManager));
     305           6 :                         uno::Reference<lang::XSingleComponentFactory> xCFac( xIntFac, uno::UNO_QUERY );
     306           6 :                         if (xCFac.is())
     307             :                         {
     308           6 :                             xInterface = xCFac->createInstanceWithContext(xCtx);
     309           6 :                             if (xInterface.is())
     310           6 :                                 ReadFromAddIn( xInterface );
     311             :                         }
     312             : 
     313           6 :                         if (!xInterface.is())
     314             :                         {
     315           0 :                             uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
     316           0 :                             if ( xFac.is() )
     317             :                             {
     318           0 :                                 xInterface = xFac->createInstance();
     319           0 :                                 if (xInterface.is())
     320           0 :                                     ReadFromAddIn( xInterface );
     321           0 :                             }
     322           6 :                         }
     323           6 :                     }
     324             :                 }
     325           6 :             }
     326           4 :         }
     327             :     }
     328             : 
     329             :     // ReadConfiguration is called after looking at the AddIn implementations.
     330             :     // Duplicated are skipped (by using the service information, they don't have to be updated again
     331             :     // when argument information is needed).
     332           4 :     ReadConfiguration();
     333             : 
     334           4 :     bInitialized = sal_True;        // with or without functions
     335           4 : }
     336             : // -----------------------------------------------------------------------------
     337             : 
     338         327 : static sal_uInt16 lcl_GetCategory( const ::rtl::OUString& rName )
     339             : {
     340             :     static const sal_Char* aFuncNames[SC_FUNCGROUP_COUNT] =
     341             :     {
     342             :         //  array index = ID - 1 (ID starts at 1)
     343             :         //  all upper case
     344             :         "Database",         // ID_FUNCTION_GRP_DATABASE
     345             :         "Date&Time",        // ID_FUNCTION_GRP_DATETIME
     346             :         "Financial",        // ID_FUNCTION_GRP_FINANZ
     347             :         "Information",      // ID_FUNCTION_GRP_INFO
     348             :         "Logical",          // ID_FUNCTION_GRP_LOGIC
     349             :         "Mathematical",     // ID_FUNCTION_GRP_MATH
     350             :         "Matrix",           // ID_FUNCTION_GRP_MATRIX
     351             :         "Statistical",      // ID_FUNCTION_GRP_STATISTIC
     352             :         "Spreadsheet",      // ID_FUNCTION_GRP_TABLE
     353             :         "Text",             // ID_FUNCTION_GRP_TEXT
     354             :         "Add-In"            // ID_FUNCTION_GRP_ADDINS
     355             :     };
     356        2337 :     for (sal_uInt16 i=0; i<SC_FUNCGROUP_COUNT; i++)
     357        2193 :         if ( rName.equalsAscii( aFuncNames[i] ) )
     358         183 :             return i+1;                             // IDs start at 1
     359             : 
     360         144 :     return ID_FUNCTION_GRP_ADDINS;  // if not found, use Add-In group
     361             : }
     362             : 
     363             : 
     364             : #define CFGPATH_ADDINS              "Office.CalcAddIns/AddInInfo"
     365             : #define CFGSTR_ADDINFUNCTIONS       "AddInFunctions"
     366             : 
     367             : #define CFG_FUNCPROP_DISPLAYNAME    0
     368             : #define CFG_FUNCPROP_DESCRIPTION    1
     369             : #define CFG_FUNCPROP_CATEGORY       2
     370             : #define CFG_FUNCPROP_COUNT          3
     371             : #define CFGSTR_DISPLAYNAME          "DisplayName"
     372             : #define CFGSTR_DESCRIPTION          "Description"
     373             : #define CFGSTR_CATEGORY             "Category"
     374             : // CategoryDisplayName is ignored for now
     375             : 
     376             : #define CFGSTR_COMPATIBILITYNAME    "CompatibilityName"
     377             : #define CFGSTR_PARAMETERS           "Parameters"
     378             : 
     379             : 
     380           4 : void ScUnoAddInCollection::ReadConfiguration()
     381             : {
     382             :     // called only from Initialize
     383             : 
     384           4 :     ScAddInCfg& rAddInConfig = SC_MOD()->GetAddInCfg();
     385             : 
     386             :     // additional, temporary config item for the compatibility names
     387           4 :     ScLinkConfigItem aAllLocalesConfig( rtl::OUString(CFGPATH_ADDINS), CONFIG_MODE_ALL_LOCALES );
     388             :     // CommitLink is not used (only reading values)
     389             : 
     390           4 :     const rtl::OUString sSlash('/');
     391             : 
     392             :     // get the list of add-ins (services)
     393           4 :     rtl::OUString aEmptyString;
     394           4 :     uno::Sequence<rtl::OUString> aServiceNames = rAddInConfig.GetNodeNames( aEmptyString );
     395             : 
     396           4 :     sal_Int32 nServiceCount = aServiceNames.getLength();
     397           4 :     for ( sal_Int32 nService = 0; nService < nServiceCount; nService++ )
     398             :     {
     399           0 :         rtl::OUString aServiceName = aServiceNames[nService];
     400           0 :         ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName );
     401             : 
     402           0 :         rtl::OUString aFunctionsPath = aServiceName;
     403           0 :         aFunctionsPath += sSlash;
     404           0 :         aFunctionsPath += rtl::OUString(CFGSTR_ADDINFUNCTIONS);
     405             : 
     406           0 :         uno::Sequence<rtl::OUString> aFunctionNames = rAddInConfig.GetNodeNames( aFunctionsPath );
     407           0 :         sal_Int32 nNewCount = aFunctionNames.getLength();
     408             : 
     409             :         // allocate pointers
     410             : 
     411           0 :         long nOld = nFuncCount;
     412           0 :         nFuncCount = nNewCount+nOld;
     413           0 :         if ( nOld )
     414             :         {
     415           0 :             ScUnoAddInFuncData** ppNew = new ScUnoAddInFuncData*[nFuncCount];
     416           0 :             for (long i=0; i<nOld; i++)
     417           0 :                 ppNew[i] = ppFuncData[i];
     418           0 :             delete[] ppFuncData;
     419           0 :             ppFuncData = ppNew;
     420             :         }
     421             :         else
     422           0 :             ppFuncData = new ScUnoAddInFuncData*[nFuncCount];
     423             : 
     424             :         //! TODO: adjust bucket count?
     425           0 :         if ( !pExactHashMap )
     426           0 :             pExactHashMap = new ScAddInHashMap;
     427           0 :         if ( !pNameHashMap )
     428           0 :             pNameHashMap = new ScAddInHashMap;
     429           0 :         if ( !pLocalHashMap )
     430           0 :             pLocalHashMap = new ScAddInHashMap;
     431             : 
     432             :         //! get the function information in a single call for all functions?
     433             : 
     434           0 :         const rtl::OUString* pFuncNameArray = aFunctionNames.getConstArray();
     435           0 :         for ( sal_Int32 nFuncPos = 0; nFuncPos < nNewCount; nFuncPos++ )
     436             :         {
     437           0 :             ppFuncData[nFuncPos+nOld] = NULL;
     438             : 
     439             :             // stored function name: (service name).(function)
     440           0 :             rtl::OUStringBuffer aFuncNameBuffer( aServiceName.getLength()+1+pFuncNameArray[nFuncPos].getLength());
     441           0 :             aFuncNameBuffer.append(aServiceName);
     442           0 :             aFuncNameBuffer.append('.');
     443           0 :             aFuncNameBuffer.append(pFuncNameArray[nFuncPos]);
     444           0 :             rtl::OUString aFuncName = aFuncNameBuffer.makeStringAndClear();
     445             : 
     446             :             // skip the function if already known (read from old AddIn service)
     447             : 
     448           0 :             if ( pExactHashMap->find( aFuncName ) == pExactHashMap->end() )
     449             :             {
     450           0 :                 rtl::OUString aLocalName;
     451           0 :                 rtl::OUString aDescription;
     452           0 :                 sal_uInt16 nCategory = ID_FUNCTION_GRP_ADDINS;
     453             : 
     454             :                 // get direct information on the function
     455             : 
     456           0 :                 rtl::OUString aFuncPropPath = aFunctionsPath;
     457           0 :                 aFuncPropPath += sSlash;
     458           0 :                 aFuncPropPath += pFuncNameArray[nFuncPos];
     459           0 :                 aFuncPropPath += sSlash;
     460             : 
     461           0 :                 uno::Sequence<rtl::OUString> aFuncPropNames(CFG_FUNCPROP_COUNT);
     462           0 :                 rtl::OUString* pNameArray = aFuncPropNames.getArray();
     463           0 :                 pNameArray[CFG_FUNCPROP_DISPLAYNAME] = aFuncPropPath;
     464           0 :                 pNameArray[CFG_FUNCPROP_DISPLAYNAME] += rtl::OUString(CFGSTR_DISPLAYNAME);
     465           0 :                 pNameArray[CFG_FUNCPROP_DESCRIPTION] = aFuncPropPath;
     466           0 :                 pNameArray[CFG_FUNCPROP_DESCRIPTION] += rtl::OUString(CFGSTR_DESCRIPTION);
     467           0 :                 pNameArray[CFG_FUNCPROP_CATEGORY] = aFuncPropPath;
     468           0 :                 pNameArray[CFG_FUNCPROP_CATEGORY] += rtl::OUString(CFGSTR_CATEGORY);
     469             : 
     470           0 :                 uno::Sequence<uno::Any> aFuncProperties = rAddInConfig.GetProperties( aFuncPropNames );
     471           0 :                 if ( aFuncProperties.getLength() == CFG_FUNCPROP_COUNT )
     472             :                 {
     473           0 :                     aFuncProperties[CFG_FUNCPROP_DISPLAYNAME] >>= aLocalName;
     474           0 :                     aFuncProperties[CFG_FUNCPROP_DESCRIPTION] >>= aDescription;
     475             : 
     476           0 :                     rtl::OUString aCategoryName;
     477           0 :                     aFuncProperties[CFG_FUNCPROP_CATEGORY] >>= aCategoryName;
     478           0 :                     nCategory = lcl_GetCategory( aCategoryName );
     479             :                 }
     480             : 
     481             :                 // get compatibility names
     482             : 
     483           0 :                 uno::Sequence<sheet::LocalizedName> aCompNames;
     484             : 
     485           0 :                 rtl::OUString aCompPath = aFuncPropPath;
     486           0 :                 aCompPath += rtl::OUString(CFGSTR_COMPATIBILITYNAME);
     487           0 :                 uno::Sequence<rtl::OUString> aCompPropNames( &aCompPath, 1 );
     488             : 
     489           0 :                 uno::Sequence<uno::Any> aCompProperties = aAllLocalesConfig.GetProperties( aCompPropNames );
     490           0 :                 if ( aCompProperties.getLength() == 1 )
     491             :                 {
     492           0 :                     uno::Sequence<beans::PropertyValue> aLocalEntries;
     493           0 :                     if ( aCompProperties[0] >>= aLocalEntries )
     494             :                     {
     495           0 :                         sal_Int32 nLocaleCount = aLocalEntries.getLength();
     496           0 :                         aCompNames.realloc( nLocaleCount );
     497           0 :                         const beans::PropertyValue* pConfigArray = aLocalEntries.getConstArray();
     498           0 :                         sheet::LocalizedName* pCompArray = aCompNames.getArray();
     499             : 
     500           0 :                         for ( sal_Int32 nLocale = 0; nLocale < nLocaleCount; nLocale++ )
     501             :                         {
     502           0 :                             const sal_Unicode cLocaleSep = '-';     // separator in configuration locale strings
     503             : 
     504             :                             // PropertyValue name is the locale (convert from string to Locale struct)
     505             : 
     506           0 :                             const rtl::OUString& rLocaleStr = pConfigArray[nLocale].Name;
     507           0 :                             lang::Locale& rLocale = pCompArray[nLocale].Locale;
     508           0 :                             sal_Int32 nSepPos = rLocaleStr.indexOf( cLocaleSep );
     509           0 :                             if ( nSepPos >= 0 )
     510             :                             {
     511           0 :                                 rLocale.Language = rLocaleStr.copy( 0, nSepPos );
     512           0 :                                 rLocale.Country = rLocaleStr.copy( nSepPos+1 );
     513             :                             }
     514             :                             else
     515           0 :                                 rLocale.Language = rLocaleStr;      // leave country empty (default ctor from sequence)
     516             : 
     517             :                             // PropertyValue value is the localized value (string in this case)
     518             : 
     519           0 :                             pConfigArray[nLocale].Value >>= pCompArray[nLocale].Name;
     520             :                         }
     521           0 :                     }
     522             :                 }
     523             : 
     524             :                 // get argument info
     525             : 
     526           0 :                 ScAddInArgDesc* pVisibleArgs = NULL;
     527           0 :                 long nVisibleCount = 0;
     528           0 :                 long nCallerPos = SC_CALLERPOS_NONE;
     529             : 
     530           0 :                 rtl::OUString aArgumentsPath = aFuncPropPath;
     531           0 :                 aArgumentsPath += rtl::OUString(CFGSTR_PARAMETERS);
     532             : 
     533           0 :                 uno::Sequence<rtl::OUString> aArgumentNames = rAddInConfig.GetNodeNames( aArgumentsPath );
     534           0 :                 sal_Int32 nArgumentCount = aArgumentNames.getLength();
     535           0 :                 if ( nArgumentCount )
     536             :                 {
     537             :                     // get DisplayName and Description for each argument
     538           0 :                     uno::Sequence<rtl::OUString> aArgPropNames( nArgumentCount * 2 );
     539           0 :                     rtl::OUString* pPropNameArray = aArgPropNames.getArray();
     540             : 
     541             :                     sal_Int32 nArgument;
     542           0 :                     sal_Int32 nIndex = 0;
     543           0 :                     const rtl::OUString* pArgNameArray = aArgumentNames.getConstArray();
     544           0 :                     for ( nArgument = 0; nArgument < nArgumentCount; nArgument++ )
     545             :                     {
     546           0 :                         rtl::OUString aOneArgPath = aArgumentsPath;
     547           0 :                         aOneArgPath += sSlash;
     548           0 :                         aOneArgPath += pArgNameArray[nArgument];
     549           0 :                         aOneArgPath += sSlash;
     550             : 
     551           0 :                         pPropNameArray[nIndex] = aOneArgPath;
     552           0 :                         pPropNameArray[nIndex++] += rtl::OUString(CFGSTR_DISPLAYNAME);
     553           0 :                         pPropNameArray[nIndex] = aOneArgPath;
     554           0 :                         pPropNameArray[nIndex++] += rtl::OUString(CFGSTR_DESCRIPTION);
     555           0 :                     }
     556             : 
     557           0 :                     uno::Sequence<uno::Any> aArgProperties = rAddInConfig.GetProperties( aArgPropNames );
     558           0 :                     if ( aArgProperties.getLength() == aArgPropNames.getLength() )
     559             :                     {
     560           0 :                         const uno::Any* pPropArray = aArgProperties.getConstArray();
     561           0 :                         rtl::OUString sDisplayName;
     562           0 :                         rtl::OUString sDescription;
     563             : 
     564           0 :                         ScAddInArgDesc aDesc;
     565           0 :                         aDesc.eType = SC_ADDINARG_NONE;     // arg type is not in configuration
     566           0 :                         aDesc.bOptional = false;
     567             : 
     568           0 :                         nVisibleCount = nArgumentCount;
     569           0 :                         pVisibleArgs = new ScAddInArgDesc[nVisibleCount];
     570             : 
     571           0 :                         nIndex = 0;
     572           0 :                         for ( nArgument = 0; nArgument < nArgumentCount; nArgument++ )
     573             :                         {
     574           0 :                             pPropArray[nIndex++] >>= sDisplayName;
     575           0 :                             pPropArray[nIndex++] >>= sDescription;
     576             : 
     577           0 :                             aDesc.aInternalName = pArgNameArray[nArgument];
     578           0 :                             aDesc.aName         = sDisplayName;
     579           0 :                             aDesc.aDescription  = sDescription;
     580             : 
     581           0 :                             pVisibleArgs[nArgument] = aDesc;
     582           0 :                         }
     583           0 :                     }
     584             :                 }
     585             : 
     586           0 :                 rtl::OString sHelpId = aHelpIdGenerator.GetHelpId( pFuncNameArray[nFuncPos] );
     587             : 
     588           0 :                 uno::Reference<reflection::XIdlMethod> xFunc;       // remains empty
     589           0 :                 uno::Any aObject;                                   // also empty
     590             : 
     591             :                 // create and insert into the array
     592             : 
     593             :                 ScUnoAddInFuncData* pData = new ScUnoAddInFuncData(
     594             :                     aFuncName, aLocalName, aDescription,
     595             :                     nCategory, sHelpId,
     596             :                     xFunc, aObject,
     597           0 :                     nVisibleCount, pVisibleArgs, nCallerPos );
     598             : 
     599           0 :                 pData->SetCompNames( aCompNames );
     600             : 
     601           0 :                 ppFuncData[nFuncPos+nOld] = pData;
     602             : 
     603             :                 pExactHashMap->insert(
     604             :                         ScAddInHashMap::value_type(
     605           0 :                             pData->GetOriginalName(),
     606           0 :                             pData ) );
     607             :                 pNameHashMap->insert(
     608             :                         ScAddInHashMap::value_type(
     609           0 :                             pData->GetUpperName(),
     610           0 :                             pData ) );
     611             :                 pLocalHashMap->insert(
     612             :                         ScAddInHashMap::value_type(
     613           0 :                             pData->GetUpperLocal(),
     614           0 :                             pData ) );
     615             : 
     616           0 :                 delete[] pVisibleArgs;
     617             :             }
     618           0 :         }
     619           4 :     }
     620           4 : }
     621             : 
     622           0 : void ScUnoAddInCollection::LoadComponent( const ScUnoAddInFuncData& rFuncData )
     623             : {
     624           0 :     ::rtl::OUString aFullName = rFuncData.GetOriginalName();
     625           0 :     sal_Int32 nPos = aFullName.lastIndexOf( (sal_Unicode) '.' );
     626           0 :     if ( nPos > 0 )
     627             :     {
     628           0 :         ::rtl::OUString aServiceName = aFullName.copy( 0, nPos );
     629             : 
     630           0 :         uno::Reference<lang::XMultiServiceFactory> xServiceFactory = comphelper::getProcessServiceFactory();
     631           0 :         uno::Reference<uno::XInterface> xInterface( xServiceFactory->createInstance( aServiceName ) );
     632             : 
     633           0 :         if (xInterface.is())
     634           0 :             UpdateFromAddIn( xInterface, aServiceName );
     635           0 :     }
     636           0 : }
     637             : 
     638           0 : sal_Bool ScUnoAddInCollection::GetExcelName( const ::rtl::OUString& rCalcName,
     639             :                                         LanguageType eDestLang, ::rtl::OUString& rRetExcelName )
     640             : {
     641           0 :     const ScUnoAddInFuncData* pFuncData = GetFuncData( rCalcName );
     642           0 :     if ( pFuncData )
     643           0 :         return pFuncData->GetExcelName( eDestLang, rRetExcelName);
     644           0 :     return false;
     645             : }
     646             : 
     647           0 : sal_Bool ScUnoAddInCollection::GetCalcName( const ::rtl::OUString& rExcelName, ::rtl::OUString& rRetCalcName )
     648             : {
     649           0 :     if (!bInitialized)
     650           0 :         Initialize();
     651             : 
     652           0 :     rtl::OUString aUpperCmp = ScGlobal::pCharClass->uppercase(rExcelName);
     653             : 
     654           0 :     for (long i=0; i<nFuncCount; i++)
     655             :     {
     656           0 :         ScUnoAddInFuncData* pFuncData = ppFuncData[i];
     657           0 :         if ( pFuncData )
     658             :         {
     659           0 :             const uno::Sequence<sheet::LocalizedName>& rSequence = pFuncData->GetCompNames();
     660           0 :             long nSeqLen = rSequence.getLength();
     661           0 :             if ( nSeqLen )
     662             :             {
     663           0 :                 const sheet::LocalizedName* pArray = rSequence.getConstArray();
     664           0 :                 for ( long nName=0; nName<nSeqLen; nName++)
     665           0 :                     if ( ScGlobal::pCharClass->uppercase( pArray[nName].Name ) == aUpperCmp )
     666             :                     {
     667             :                         //! store upper case for comparing?
     668             : 
     669             :                         //  use the first function that has this name for any language
     670           0 :                         rRetCalcName = pFuncData->GetOriginalName();
     671           0 :                         return sal_True;
     672             :                     }
     673             :             }
     674             :         }
     675             :     }
     676           0 :     return false;
     677             : }
     678             : 
     679        6000 : inline sal_Bool IsTypeName( const rtl::OUString& rName, const uno::Type& rType )
     680             : {
     681        6000 :     return rName == rType.getTypeName();
     682             : }
     683             : 
     684         363 : static sal_Bool lcl_ValidReturnType( const uno::Reference<reflection::XIdlClass>& xClass )
     685             : {
     686             :     //  this must match with ScUnoAddInCall::SetResult
     687             : 
     688         363 :     if ( !xClass.is() ) return false;
     689             : 
     690         363 :     switch (xClass->getTypeClass())
     691             :     {
     692             :         case uno::TypeClass_ANY:                // variable type
     693             :         case uno::TypeClass_ENUM:               //! ???
     694             :         case uno::TypeClass_BOOLEAN:
     695             :         case uno::TypeClass_CHAR:
     696             :         case uno::TypeClass_BYTE:
     697             :         case uno::TypeClass_SHORT:
     698             :         case uno::TypeClass_UNSIGNED_SHORT:
     699             :         case uno::TypeClass_LONG:
     700             :         case uno::TypeClass_UNSIGNED_LONG:
     701             :         case uno::TypeClass_FLOAT:
     702             :         case uno::TypeClass_DOUBLE:
     703             :         case uno::TypeClass_STRING:
     704         327 :             return sal_True;                        // values or string
     705             : 
     706             :         case uno::TypeClass_INTERFACE:
     707             :             {
     708             :                 //  return type XInterface may contain a XVolatileResult
     709             :                 //! XIdlClass needs getType() method!
     710             : 
     711           6 :                 rtl::OUString sName = xClass->getName();
     712             :                 return (
     713           6 :                     IsTypeName( sName, getCppuType((uno::Reference<sheet::XVolatileResult>*)0) ) ||
     714           6 :                     IsTypeName( sName, getCppuType((uno::Reference<uno::XInterface>*)0) ) );
     715             :             }
     716             : 
     717             :         default:
     718             :             {
     719             :                 //  nested sequences for arrays
     720             :                 //! XIdlClass needs getType() method!
     721             : 
     722          30 :                 rtl::OUString sName = xClass->getName();
     723             :                 return (
     724          30 :                     IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<sal_Int32> >*)0) ) ||
     725          30 :                     IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) ) ||
     726          30 :                     IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) ) ||
     727          90 :                     IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) ) );
     728             :             }
     729             :     }
     730             : }
     731             : 
     732        2184 : static ScAddInArgumentType lcl_GetArgType( const uno::Reference<reflection::XIdlClass>& xClass )
     733             : {
     734        2184 :     if (!xClass.is())
     735           0 :         return SC_ADDINARG_NONE;
     736             : 
     737        2184 :     uno::TypeClass eType = xClass->getTypeClass();
     738             : 
     739        2184 :     if ( eType == uno::TypeClass_LONG )             //! other integer types?
     740         756 :         return SC_ADDINARG_INTEGER;
     741             : 
     742        1428 :     if ( eType == uno::TypeClass_DOUBLE )
     743         492 :         return SC_ADDINARG_DOUBLE;
     744             : 
     745         936 :     if ( eType == uno::TypeClass_STRING )
     746         222 :         return SC_ADDINARG_STRING;
     747             : 
     748             :     //! XIdlClass needs getType() method!
     749         714 :     rtl::OUString sName = xClass->getName();
     750             : 
     751         714 :     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<sal_Int32> >*)0) ))
     752          18 :         return SC_ADDINARG_INTEGER_ARRAY;
     753             : 
     754         696 :     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) ))
     755          36 :         return SC_ADDINARG_DOUBLE_ARRAY;
     756             : 
     757         660 :     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) ))
     758          12 :         return SC_ADDINARG_STRING_ARRAY;
     759             : 
     760         648 :     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) ))
     761           0 :         return SC_ADDINARG_MIXED_ARRAY;
     762             : 
     763         648 :     if (IsTypeName( sName, getCppuType((uno::Any*)0) ))
     764         264 :         return SC_ADDINARG_VALUE_OR_ARRAY;
     765             : 
     766         384 :     if (IsTypeName( sName, getCppuType((uno::Reference<table::XCellRange>*)0) ))
     767           0 :         return SC_ADDINARG_CELLRANGE;
     768             : 
     769         384 :     if (IsTypeName( sName, getCppuType((uno::Reference<beans::XPropertySet>*)0) ))
     770         354 :         return SC_ADDINARG_CALLER;
     771             : 
     772          30 :     if (IsTypeName( sName, getCppuType((uno::Sequence<uno::Any>*)0) ))
     773          30 :         return SC_ADDINARG_VARARGS;
     774             : 
     775           0 :     return SC_ADDINARG_NONE;
     776             : }
     777             : 
     778           6 : void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>& xInterface )
     779             : {
     780           6 :     uno::Reference<sheet::XAddIn> xAddIn( xInterface, uno::UNO_QUERY );
     781           6 :     uno::Reference<lang::XServiceName> xName( xInterface, uno::UNO_QUERY );
     782           6 :     if ( xAddIn.is() && xName.is() )
     783             :     {
     784             :         //  AddIns must use the language for which the office is installed
     785           6 :         lang::Locale aLocale( Application::GetSettings().GetUILanguageTag().getLocale());
     786           6 :         xAddIn->setLocale( aLocale );
     787             : 
     788           6 :         ::rtl::OUString aServiceName( xName->getServiceName() );
     789           6 :         ScUnoAddInHelpIdGenerator aHelpIdGenerator( xName->getServiceName() );
     790             : 
     791             :         //! pass XIntrospection to ReadFromAddIn
     792             : 
     793           6 :         uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
     794             : 
     795           6 :         uno::Reference<beans::XIntrospection> xIntro = beans::Introspection::create( xContext );
     796           6 :         uno::Any aObject;
     797           6 :         aObject <<= xAddIn;
     798           6 :         uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
     799           6 :         if (xAcc.is())
     800             :         {
     801             :             uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
     802           6 :                     xAcc->getMethods( beans::MethodConcept::ALL );
     803           6 :             long nNewCount = aMethods.getLength();
     804           6 :             if ( nNewCount )
     805             :             {
     806           6 :                 long nOld = nFuncCount;
     807           6 :                 nFuncCount = nNewCount+nOld;
     808           6 :                 if ( nOld )
     809             :                 {
     810           3 :                     ScUnoAddInFuncData** ppNew = new ScUnoAddInFuncData*[nFuncCount];
     811         366 :                     for (long i=0; i<nOld; i++)
     812         363 :                         ppNew[i] = ppFuncData[i];
     813           3 :                     delete[] ppFuncData;
     814           3 :                     ppFuncData = ppNew;
     815             :                 }
     816             :                 else
     817           3 :                     ppFuncData = new ScUnoAddInFuncData*[nFuncCount];
     818             : 
     819             :                 //! TODO: adjust bucket count?
     820           6 :                 if ( !pExactHashMap )
     821           3 :                     pExactHashMap = new ScAddInHashMap;
     822           6 :                 if ( !pNameHashMap )
     823           3 :                     pNameHashMap = new ScAddInHashMap;
     824           6 :                 if ( !pLocalHashMap )
     825           3 :                     pLocalHashMap = new ScAddInHashMap;
     826             : 
     827           6 :                 const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
     828         453 :                 for (long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++)
     829             :                 {
     830         447 :                     ppFuncData[nFuncPos+nOld] = NULL;
     831             : 
     832         447 :                     uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
     833         447 :                     if (xFunc.is())
     834             :                     {
     835             :                         //  leave out internal functions
     836             :                         uno::Reference<reflection::XIdlClass> xClass =
     837         447 :                                         xFunc->getDeclaringClass();
     838         447 :                         sal_Bool bSkip = sal_True;
     839         447 :                         if ( xClass.is() )
     840             :                         {
     841             :                             //! XIdlClass needs getType() method!
     842         447 :                             rtl::OUString sName = xClass->getName();
     843             :                             bSkip = (
     844             :                                 IsTypeName( sName,
     845         447 :                                     getCppuType((uno::Reference<uno::XInterface>*)0) ) ||
     846             :                                 IsTypeName( sName,
     847         429 :                                     getCppuType((uno::Reference<lang::XServiceName>*)0) ) ||
     848             :                                 IsTypeName( sName,
     849         423 :                                     getCppuType((uno::Reference<lang::XServiceInfo>*)0) ) ||
     850             :                                 IsTypeName( sName,
     851        1299 :                                     getCppuType((uno::Reference<sheet::XAddIn>*)0) ) );
     852             :                         }
     853         447 :                         if (!bSkip)
     854             :                         {
     855             :                             uno::Reference<reflection::XIdlClass> xReturn =
     856         363 :                                         xFunc->getReturnType();
     857         363 :                             if ( !lcl_ValidReturnType( xReturn ) )
     858          36 :                                 bSkip = sal_True;
     859             :                         }
     860         447 :                         if (!bSkip)
     861             :                         {
     862         327 :                             rtl::OUString aFuncU = xFunc->getName();
     863             : 
     864             :                             // stored function name: (service name).(function)
     865         327 :                             rtl::OUStringBuffer aFuncNameBuffer( aServiceName.getLength()+1+aFuncU.getLength());
     866         327 :                             aFuncNameBuffer.append(aServiceName);
     867         327 :                             aFuncNameBuffer.append('.');
     868         327 :                             aFuncNameBuffer.append(aFuncU);
     869         327 :                             rtl::OUString aFuncName = aFuncNameBuffer.makeStringAndClear();
     870             : 
     871         327 :                             sal_Bool bValid = sal_True;
     872         327 :                             long nVisibleCount = 0;
     873         327 :                             long nCallerPos = SC_CALLERPOS_NONE;
     874             : 
     875             :                             uno::Sequence<reflection::ParamInfo> aParams =
     876         327 :                                     xFunc->getParameterInfos();
     877         327 :                             long nParamCount = aParams.getLength();
     878         327 :                             const reflection::ParamInfo* pParArr = aParams.getConstArray();
     879             :                             long nParamPos;
     880        1419 :                             for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
     881             :                             {
     882        1092 :                                 if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
     883           0 :                                     bValid = false;
     884             :                                 uno::Reference<reflection::XIdlClass> xParClass =
     885        1092 :                                             pParArr[nParamPos].aType;
     886        1092 :                                 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
     887        1092 :                                 if ( eArgType == SC_ADDINARG_NONE )
     888           0 :                                     bValid = false;
     889        1092 :                                 else if ( eArgType == SC_ADDINARG_CALLER )
     890         177 :                                     nCallerPos = nParamPos;
     891             :                                 else
     892         915 :                                     ++nVisibleCount;
     893        1092 :                             }
     894         327 :                             if (bValid)
     895             :                             {
     896             :                                 sal_uInt16 nCategory = lcl_GetCategory(
     897         327 :                                         xAddIn->getProgrammaticCategoryName( aFuncU ) );
     898             : 
     899         327 :                                 rtl::OString sHelpId = aHelpIdGenerator.GetHelpId( aFuncU );
     900             : 
     901         327 :                                 ::rtl::OUString aLocalName;
     902             :                                 try
     903             :                                 {
     904         327 :                                     aLocalName = xAddIn->
     905         327 :                                         getDisplayFunctionName( aFuncU );
     906             :                                 }
     907           0 :                                 catch(uno::Exception&)
     908             :                                 {
     909           0 :                                     aLocalName = "###";
     910             :                                 }
     911             : 
     912         327 :                                 ::rtl::OUString aDescription;
     913             :                                 try
     914             :                                 {
     915         327 :                                     aDescription = xAddIn->
     916         327 :                                         getFunctionDescription( aFuncU );
     917             :                                 }
     918           0 :                                 catch(uno::Exception&)
     919             :                                 {
     920           0 :                                     aDescription = "###";
     921             :                                 }
     922             : 
     923         327 :                                 ScAddInArgDesc* pVisibleArgs = NULL;
     924         327 :                                 if ( nVisibleCount > 0 )
     925             :                                 {
     926         327 :                                     ScAddInArgDesc aDesc;
     927         327 :                                     pVisibleArgs = new ScAddInArgDesc[nVisibleCount];
     928         327 :                                     long nDestPos = 0;
     929        1419 :                                     for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
     930             :                                     {
     931             :                                         uno::Reference<reflection::XIdlClass> xParClass =
     932        1092 :                                             pParArr[nParamPos].aType;
     933        1092 :                                         ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
     934        1092 :                                         if ( eArgType != SC_ADDINARG_CALLER )
     935             :                                         {
     936         915 :                                             rtl::OUString aArgName;
     937             :                                             try
     938             :                                             {
     939         915 :                                                 aArgName = xAddIn->
     940         915 :                                                     getDisplayArgumentName( aFuncU, nParamPos );
     941             :                                             }
     942           0 :                                             catch(uno::Exception&)
     943             :                                             {
     944           0 :                                                 aArgName = "###";
     945             :                                             }
     946         915 :                                             rtl::OUString aArgDesc;
     947             :                                             try
     948             :                                             {
     949         915 :                                                 aArgDesc = xAddIn->
     950         915 :                                                     getArgumentDescription( aFuncU, nParamPos );
     951             :                                             }
     952           0 :                                             catch(uno::Exception&)
     953             :                                             {
     954           0 :                                                 aArgName = "###";
     955             :                                             }
     956             : 
     957             :                                             sal_Bool bOptional =
     958             :                                                 ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
     959         915 :                                                   eArgType == SC_ADDINARG_VARARGS );
     960             : 
     961         915 :                                             aDesc.eType = eArgType;
     962         915 :                                             aDesc.aName = aArgName;
     963         915 :                                             aDesc.aDescription = aArgDesc;
     964         915 :                                             aDesc.bOptional = bOptional;
     965             :                                             //! initialize aInternalName only from config?
     966         915 :                                             aDesc.aInternalName = pParArr[nParamPos].aName;
     967             : 
     968         915 :                                             pVisibleArgs[nDestPos++] = aDesc;
     969             :                                         }
     970        1092 :                                     }
     971         327 :                                     OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" );
     972             :                                 }
     973             : 
     974         327 :                                 ppFuncData[nFuncPos+nOld] = new ScUnoAddInFuncData(
     975             :                                     aFuncName, aLocalName, aDescription,
     976             :                                     nCategory, sHelpId,
     977             :                                     xFunc, aObject,
     978         654 :                                     nVisibleCount, pVisibleArgs, nCallerPos );
     979             : 
     980             :                                 const ScUnoAddInFuncData* pData =
     981         327 :                                     ppFuncData[nFuncPos+nOld];
     982             :                                 pExactHashMap->insert(
     983             :                                         ScAddInHashMap::value_type(
     984         327 :                                             pData->GetOriginalName(),
     985         327 :                                             pData ) );
     986             :                                 pNameHashMap->insert(
     987             :                                         ScAddInHashMap::value_type(
     988         327 :                                             pData->GetUpperName(),
     989         327 :                                             pData ) );
     990             :                                 pLocalHashMap->insert(
     991             :                                         ScAddInHashMap::value_type(
     992         327 :                                             pData->GetUpperLocal(),
     993         327 :                                             pData ) );
     994             : 
     995         327 :                                 delete[] pVisibleArgs;
     996         327 :                             }
     997         447 :                         }
     998             :                     }
     999         447 :                 }
    1000           6 :             }
    1001           6 :         }
    1002           6 :     }
    1003           6 : }
    1004             : 
    1005           0 : static void lcl_UpdateFunctionList( ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData )
    1006             : {
    1007           0 :     ::rtl::OUString aCompare = rFuncData.GetUpperLocal();    // as used in FillFunctionDescFromData
    1008             : 
    1009           0 :     sal_uLong nCount = rFunctionList.GetCount();
    1010           0 :     for (sal_uLong nPos=0; nPos<nCount; nPos++)
    1011             :     {
    1012           0 :         const ScFuncDesc* pDesc = rFunctionList.GetFunction( nPos );
    1013           0 :         if ( pDesc && pDesc->pFuncName && *pDesc->pFuncName == aCompare )
    1014             :         {
    1015           0 :             ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc) );
    1016           0 :             break;
    1017             :         }
    1018           0 :     }
    1019           0 : }
    1020             : 
    1021           0 : static const ScAddInArgDesc* lcl_FindArgDesc( const ScUnoAddInFuncData& rFuncData, const ::rtl::OUString& rArgIntName )
    1022             : {
    1023           0 :     long nArgCount = rFuncData.GetArgumentCount();
    1024           0 :     const ScAddInArgDesc* pArguments = rFuncData.GetArguments();
    1025           0 :     for (long nPos=0; nPos<nArgCount; nPos++)
    1026             :     {
    1027           0 :         if ( pArguments[nPos].aInternalName == rArgIntName )
    1028           0 :             return &pArguments[nPos];
    1029             :     }
    1030           0 :     return NULL;
    1031             : }
    1032             : 
    1033           0 : void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface>& xInterface,
    1034             :                                             const ::rtl::OUString& rServiceName )
    1035             : {
    1036           0 :     uno::Reference<lang::XLocalizable> xLoc( xInterface, uno::UNO_QUERY );
    1037           0 :     if ( xLoc.is() )        // optional in new add-ins
    1038             :     {
    1039           0 :         lang::Locale aLocale( Application::GetSettings().GetUILanguageTag().getLocale());
    1040           0 :         xLoc->setLocale( aLocale );
    1041             :     }
    1042             : 
    1043             :     // if function list was already initialized, it must be updated
    1044             : 
    1045           0 :     ScFunctionList* pFunctionList = NULL;
    1046           0 :     if ( ScGlobal::HasStarCalcFunctionList() )
    1047           0 :         pFunctionList = ScGlobal::GetStarCalcFunctionList();
    1048             : 
    1049             :     // only get the function information from Introspection
    1050             : 
    1051           0 :     uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
    1052             : 
    1053           0 :     uno::Reference<beans::XIntrospection> xIntro = beans::Introspection::create(xContext);
    1054           0 :     uno::Any aObject;
    1055           0 :     aObject <<= xInterface;
    1056           0 :     uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
    1057           0 :     if (xAcc.is())
    1058             :     {
    1059             :         uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
    1060           0 :                 xAcc->getMethods( beans::MethodConcept::ALL );
    1061           0 :         long nMethodCount = aMethods.getLength();
    1062           0 :         const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
    1063           0 :         for (long nFuncPos=0; nFuncPos<nMethodCount; nFuncPos++)
    1064             :         {
    1065           0 :             uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
    1066           0 :             if (xFunc.is())
    1067             :             {
    1068           0 :                 rtl::OUString aFuncU = xFunc->getName();
    1069             : 
    1070             :                 // stored function name: (service name).(function)
    1071           0 :                 rtl::OUStringBuffer aFuncNameBuffer( rServiceName.getLength()+1+aFuncU.getLength());
    1072           0 :                 aFuncNameBuffer.append(rServiceName);
    1073           0 :                 aFuncNameBuffer.append('.');
    1074           0 :                 aFuncNameBuffer.append(aFuncU);
    1075           0 :                 rtl::OUString aFuncName = aFuncNameBuffer.makeStringAndClear();
    1076             : 
    1077             :                 // internal names are skipped because no FuncData exists
    1078           0 :                 ScUnoAddInFuncData* pOldData = const_cast<ScUnoAddInFuncData*>( GetFuncData( aFuncName ) );
    1079           0 :                 if ( pOldData )
    1080             :                 {
    1081             :                     // Create new (complete) argument info.
    1082             :                     // As in ReadFromAddIn, the reflection information is authoritative.
    1083             :                     // Local names and descriptions from pOldData are looked up using the
    1084             :                     // internal argument name.
    1085             : 
    1086           0 :                     sal_Bool bValid = sal_True;
    1087           0 :                     long nVisibleCount = 0;
    1088           0 :                     long nCallerPos = SC_CALLERPOS_NONE;
    1089             : 
    1090             :                     uno::Sequence<reflection::ParamInfo> aParams =
    1091           0 :                             xFunc->getParameterInfos();
    1092           0 :                     long nParamCount = aParams.getLength();
    1093           0 :                     const reflection::ParamInfo* pParArr = aParams.getConstArray();
    1094             :                     long nParamPos;
    1095           0 :                     for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
    1096             :                     {
    1097           0 :                         if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
    1098           0 :                             bValid = false;
    1099             :                         uno::Reference<reflection::XIdlClass> xParClass =
    1100           0 :                                     pParArr[nParamPos].aType;
    1101           0 :                         ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
    1102           0 :                         if ( eArgType == SC_ADDINARG_NONE )
    1103           0 :                             bValid = false;
    1104           0 :                         else if ( eArgType == SC_ADDINARG_CALLER )
    1105           0 :                             nCallerPos = nParamPos;
    1106             :                         else
    1107           0 :                             ++nVisibleCount;
    1108           0 :                     }
    1109           0 :                     if (bValid)
    1110             :                     {
    1111           0 :                         ScAddInArgDesc* pVisibleArgs = NULL;
    1112           0 :                         if ( nVisibleCount > 0 )
    1113             :                         {
    1114           0 :                             ScAddInArgDesc aDesc;
    1115           0 :                             pVisibleArgs = new ScAddInArgDesc[nVisibleCount];
    1116           0 :                             long nDestPos = 0;
    1117           0 :                             for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
    1118             :                             {
    1119             :                                 uno::Reference<reflection::XIdlClass> xParClass =
    1120           0 :                                     pParArr[nParamPos].aType;
    1121           0 :                                 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
    1122           0 :                                 if ( eArgType != SC_ADDINARG_CALLER )
    1123             :                                 {
    1124             :                                     const ScAddInArgDesc* pOldArgDesc =
    1125           0 :                                         lcl_FindArgDesc( *pOldData, pParArr[nParamPos].aName );
    1126           0 :                                     if ( pOldArgDesc )
    1127             :                                     {
    1128           0 :                                         aDesc.aName = pOldArgDesc->aName;
    1129           0 :                                         aDesc.aDescription = pOldArgDesc->aDescription;
    1130             :                                     }
    1131             :                                     else
    1132           0 :                                         aDesc.aName = aDesc.aDescription = "###";
    1133             : 
    1134             :                                     sal_Bool bOptional =
    1135             :                                         ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
    1136           0 :                                           eArgType == SC_ADDINARG_VARARGS );
    1137             : 
    1138           0 :                                     aDesc.eType = eArgType;
    1139           0 :                                     aDesc.bOptional = bOptional;
    1140             :                                     //! initialize aInternalName only from config?
    1141           0 :                                     aDesc.aInternalName = pParArr[nParamPos].aName;
    1142             : 
    1143           0 :                                     pVisibleArgs[nDestPos++] = aDesc;
    1144             :                                 }
    1145           0 :                             }
    1146           0 :                             OSL_ENSURE( nDestPos==nVisibleCount, "wrong count" );
    1147             :                         }
    1148             : 
    1149           0 :                         pOldData->SetFunction( xFunc, aObject );
    1150           0 :                         pOldData->SetArguments( nVisibleCount, pVisibleArgs );
    1151           0 :                         pOldData->SetCallerPos( nCallerPos );
    1152             : 
    1153           0 :                         if ( pFunctionList )
    1154           0 :                             lcl_UpdateFunctionList( *pFunctionList, *pOldData );
    1155             : 
    1156           0 :                         delete[] pVisibleArgs;
    1157           0 :                     }
    1158           0 :                 }
    1159             :             }
    1160           0 :         }
    1161           0 :     }
    1162           0 : }
    1163             : 
    1164         136 : ::rtl::OUString ScUnoAddInCollection::FindFunction( const ::rtl::OUString& rUpperName, sal_Bool bLocalFirst )
    1165             : {
    1166         136 :     if (!bInitialized)
    1167           1 :         Initialize();
    1168             : 
    1169         136 :     if (nFuncCount == 0)
    1170          54 :         return EMPTY_OUSTRING;
    1171             : 
    1172          82 :     if ( bLocalFirst )
    1173             :     {
    1174             :         //  first scan all local names (used for entering formulas)
    1175             : 
    1176          82 :         ScAddInHashMap::const_iterator iLook( pLocalHashMap->find( rUpperName ) );
    1177          82 :         if ( iLook != pLocalHashMap->end() )
    1178           0 :             return iLook->second->GetOriginalName();
    1179             :     }
    1180             :     else
    1181             :     {
    1182             :         //  first scan international names (used when calling a function)
    1183             :         //! before that, check for exact match???
    1184             : 
    1185           0 :         ScAddInHashMap::const_iterator iLook( pNameHashMap->find( rUpperName ) );
    1186           0 :         if ( iLook != pNameHashMap->end() )
    1187           0 :             return iLook->second->GetOriginalName();
    1188             : 
    1189             :         //  after that, scan all local names (to allow replacing old AddIns with Uno)
    1190             : 
    1191           0 :         iLook = pLocalHashMap->find( rUpperName );
    1192           0 :         if ( iLook != pLocalHashMap->end() )
    1193           0 :             return iLook->second->GetOriginalName();
    1194             :     }
    1195             : 
    1196          82 :     return EMPTY_OUSTRING;
    1197             : }
    1198             : 
    1199           0 : const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( const ::rtl::OUString& rName, bool bComplete )
    1200             : {
    1201           0 :     if (!bInitialized)
    1202           0 :         Initialize();
    1203             : 
    1204             :     //  rName must be the exact internal name
    1205             : 
    1206           0 :     ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
    1207           0 :     if ( iLook != pExactHashMap->end() )
    1208             :     {
    1209           0 :         const ScUnoAddInFuncData* pFuncData = iLook->second;
    1210             : 
    1211           0 :         if ( bComplete && !pFuncData->GetFunction().is() )           //! extra flag?
    1212           0 :             LoadComponent( *pFuncData );
    1213             : 
    1214           0 :         return pFuncData;
    1215             :     }
    1216             : 
    1217           0 :     return NULL;
    1218             : }
    1219             : 
    1220         596 : const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( long nIndex )
    1221             : {
    1222         596 :     if (!bInitialized)
    1223           0 :         Initialize();
    1224             : 
    1225         596 :     if (nIndex < nFuncCount)
    1226         596 :         return ppFuncData[nIndex];
    1227           0 :     return NULL;
    1228             : }
    1229             : 
    1230           0 : void ScUnoAddInCollection::LocalizeString( ::rtl::OUString& rName )
    1231             : {
    1232           0 :     if (!bInitialized)
    1233           0 :         Initialize();
    1234             : 
    1235             :     //  modify rName - input: exact name
    1236             : 
    1237           0 :     ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
    1238           0 :     if ( iLook != pExactHashMap->end() )
    1239           0 :         rName = iLook->second->GetUpperLocal();         //! upper?
    1240           0 : }
    1241             : 
    1242             : 
    1243           7 : long ScUnoAddInCollection::GetFuncCount()
    1244             : {
    1245           7 :     if (!bInitialized)
    1246           3 :         Initialize();
    1247             : 
    1248           7 :     return nFuncCount;
    1249             : }
    1250             : 
    1251           0 : sal_Bool ScUnoAddInCollection::FillFunctionDesc( long nFunc, ScFuncDesc& rDesc )
    1252             : {
    1253           0 :     if (!bInitialized)
    1254           0 :         Initialize();
    1255             : 
    1256           0 :     if (nFunc >= nFuncCount || !ppFuncData[nFunc])
    1257           0 :         return false;
    1258             : 
    1259           0 :     const ScUnoAddInFuncData& rFuncData = *ppFuncData[nFunc];
    1260             : 
    1261           0 :     return FillFunctionDescFromData( rFuncData, rDesc );
    1262             : }
    1263             : 
    1264           0 : sal_Bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc )
    1265             : {
    1266           0 :     rDesc.Clear();
    1267             : 
    1268           0 :     sal_Bool bIncomplete = !rFuncData.GetFunction().is();       //! extra flag?
    1269             : 
    1270           0 :     long nArgCount = rFuncData.GetArgumentCount();
    1271           0 :     if ( nArgCount > USHRT_MAX )
    1272           0 :         return false;
    1273             : 
    1274           0 :     if ( bIncomplete )
    1275           0 :         nArgCount = 0;      // if incomplete, fill without argument info (no wrong order)
    1276             : 
    1277             :     // nFIndex is set from outside
    1278             : 
    1279           0 :     rDesc.pFuncName = new ::rtl::OUString( rFuncData.GetUpperLocal() );     //! upper?
    1280           0 :     rDesc.nCategory = rFuncData.GetCategory();
    1281           0 :     rDesc.sHelpId = rFuncData.GetHelpId();
    1282             : 
    1283           0 :     ::rtl::OUString aDesc = rFuncData.GetDescription();
    1284           0 :     if (aDesc.isEmpty())
    1285           0 :         aDesc = rFuncData.GetLocalName();      // use name if no description is available
    1286           0 :     rDesc.pFuncDesc = new ::rtl::OUString( aDesc );
    1287             : 
    1288             :     // AddInArgumentType_CALLER is already left out in FuncData
    1289             : 
    1290           0 :     rDesc.nArgCount = (sal_uInt16)nArgCount;
    1291           0 :     if ( nArgCount )
    1292             :     {
    1293           0 :         sal_Bool bMultiple = false;
    1294           0 :         const ScAddInArgDesc* pArgs = rFuncData.GetArguments();
    1295             : 
    1296           0 :         rDesc.ppDefArgNames = new ::rtl::OUString*[nArgCount];
    1297           0 :         rDesc.ppDefArgDescs = new ::rtl::OUString*[nArgCount];
    1298           0 :         rDesc.pDefArgFlags   = new ScFuncDesc::ParameterFlags[nArgCount];
    1299           0 :         for ( long nArg=0; nArg<nArgCount; nArg++ )
    1300             :         {
    1301           0 :             rDesc.ppDefArgNames[nArg] = new ::rtl::OUString( pArgs[nArg].aName );
    1302           0 :             rDesc.ppDefArgDescs[nArg] = new ::rtl::OUString( pArgs[nArg].aDescription );
    1303           0 :             rDesc.pDefArgFlags[nArg].bOptional = pArgs[nArg].bOptional;
    1304           0 :             rDesc.pDefArgFlags[nArg].bSuppress = false;
    1305             : 
    1306             :             // no empty names...
    1307           0 :             if ( rDesc.ppDefArgNames[nArg]->isEmpty() )
    1308             :             {
    1309           0 :                 ::rtl::OUString aDefName("arg");
    1310           0 :                 aDefName += ::rtl::OUString::valueOf( nArg+1 );
    1311           0 :                 *rDesc.ppDefArgNames[nArg] = aDefName;
    1312             :             }
    1313             : 
    1314             :             //  last argument repeated?
    1315           0 :             if ( nArg+1 == nArgCount && ( pArgs[nArg].eType == SC_ADDINARG_VARARGS ) )
    1316           0 :                 bMultiple = sal_True;
    1317             :         }
    1318             : 
    1319           0 :         if ( bMultiple )
    1320           0 :             rDesc.nArgCount += VAR_ARGS - 1;    // VAR_ARGS means just one repeated arg
    1321             :     }
    1322             : 
    1323           0 :     rDesc.bIncomplete = bIncomplete;
    1324             : 
    1325           0 :     return sal_True;
    1326             : }
    1327             : 
    1328             : 
    1329             : //------------------------------------------------------------------------
    1330             : 
    1331           0 : ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection& rColl, const ::rtl::OUString& rName,
    1332             :                                 long nParamCount ) :
    1333             :     bValidCount( false ),
    1334             :     nErrCode( errNoCode ),      // before function was called
    1335             :     bHasString( sal_True ),
    1336             :     fValue( 0.0 ),
    1337           0 :     xMatrix( NULL )
    1338             : {
    1339           0 :     pFuncData = rColl.GetFuncData( rName, true );           // need fully initialized data
    1340             :     OSL_ENSURE( pFuncData, "Function Data missing" );
    1341           0 :     if ( pFuncData )
    1342             :     {
    1343           0 :         long nDescCount = pFuncData->GetArgumentCount();
    1344           0 :         const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
    1345             : 
    1346             :         //  is aVarArg sequence needed?
    1347           0 :         if ( nParamCount >= nDescCount && nDescCount > 0 &&
    1348           0 :              pArgs[nDescCount-1].eType == SC_ADDINARG_VARARGS )
    1349             :         {
    1350           0 :             long nVarCount = nParamCount - ( nDescCount - 1 );  // size of last argument
    1351           0 :             aVarArg.realloc( nVarCount );
    1352           0 :             bValidCount = sal_True;
    1353             :         }
    1354           0 :         else if ( nParamCount <= nDescCount )
    1355             :         {
    1356             :             //  all args behind nParamCount must be optional
    1357           0 :             bValidCount = sal_True;
    1358           0 :             for (long i=nParamCount; i<nDescCount; i++)
    1359           0 :                 if ( !pArgs[i].bOptional )
    1360           0 :                     bValidCount = false;
    1361             :         }
    1362             :         // else invalid (too many arguments)
    1363             : 
    1364           0 :         if ( bValidCount )
    1365           0 :             aArgs.realloc( nDescCount );    // sequence must always match function signature
    1366             :     }
    1367           0 : }
    1368             : 
    1369           0 : ScUnoAddInCall::~ScUnoAddInCall()
    1370             : {
    1371             :     // pFuncData is deleted with ScUnoAddInCollection
    1372           0 : }
    1373             : 
    1374           0 : sal_Bool ScUnoAddInCall::ValidParamCount()
    1375             : {
    1376           0 :     return bValidCount;
    1377             : }
    1378             : 
    1379           0 : ScAddInArgumentType ScUnoAddInCall::GetArgType( long nPos )
    1380             : {
    1381           0 :     if ( pFuncData )
    1382             :     {
    1383           0 :         long nCount = pFuncData->GetArgumentCount();
    1384           0 :         const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
    1385             : 
    1386             :         // if last arg is sequence, use "any" type
    1387           0 :         if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
    1388           0 :             return SC_ADDINARG_VALUE_OR_ARRAY;
    1389             : 
    1390           0 :         if ( nPos < nCount )
    1391           0 :             return pArgs[nPos].eType;
    1392             :     }
    1393           0 :     return SC_ADDINARG_VALUE_OR_ARRAY;      //! error code !!!!
    1394             : }
    1395             : 
    1396           0 : sal_Bool ScUnoAddInCall::NeedsCaller() const
    1397             : {
    1398           0 :     return pFuncData && pFuncData->GetCallerPos() != SC_CALLERPOS_NONE;
    1399             : }
    1400             : 
    1401           0 : void ScUnoAddInCall::SetCaller( const uno::Reference<uno::XInterface>& rInterface )
    1402             : {
    1403           0 :     xCaller = rInterface;
    1404           0 : }
    1405             : 
    1406           0 : void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell* pObjSh )
    1407             : {
    1408           0 :     if (pObjSh)
    1409             :     {
    1410           0 :         uno::Reference<uno::XInterface> xInt( pObjSh->GetBaseModel(), uno::UNO_QUERY );
    1411           0 :         SetCaller( xInt );
    1412             :     }
    1413           0 : }
    1414             : 
    1415           0 : void ScUnoAddInCall::SetParam( long nPos, const uno::Any& rValue )
    1416             : {
    1417           0 :     if ( pFuncData )
    1418             :     {
    1419           0 :         long nCount = pFuncData->GetArgumentCount();
    1420           0 :         const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
    1421           0 :         if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
    1422             :         {
    1423           0 :             long nVarPos = nPos-(nCount-1);
    1424           0 :             if ( nVarPos < aVarArg.getLength() )
    1425           0 :                 aVarArg.getArray()[nVarPos] = rValue;
    1426             :             else
    1427             :             {
    1428             :                 OSL_FAIL("wrong argument number");
    1429           0 :             }
    1430             :         }
    1431           0 :         else if ( nPos < aArgs.getLength() )
    1432           0 :             aArgs.getArray()[nPos] = rValue;
    1433             :         else
    1434             :         {
    1435             :             OSL_FAIL("wrong argument number");
    1436             :         }
    1437             :     }
    1438           0 : }
    1439             : 
    1440           0 : void ScUnoAddInCall::ExecuteCall()
    1441             : {
    1442           0 :     if ( !pFuncData )
    1443           0 :         return;
    1444             : 
    1445           0 :     long nCount = pFuncData->GetArgumentCount();
    1446           0 :     const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
    1447           0 :     if ( nCount > 0 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
    1448             :     {
    1449             :         //  insert aVarArg as last argument
    1450             :         //! after inserting caller (to prevent copying twice)?
    1451             : 
    1452             :         OSL_ENSURE( aArgs.getLength() == nCount, "wrong argument count" );
    1453           0 :         aArgs.getArray()[nCount-1] <<= aVarArg;
    1454             :     }
    1455             : 
    1456           0 :     if ( pFuncData->GetCallerPos() != SC_CALLERPOS_NONE )
    1457             :     {
    1458           0 :         uno::Any aCallerAny;
    1459           0 :         aCallerAny <<= xCaller;
    1460             : 
    1461           0 :         long nUserLen = aArgs.getLength();
    1462           0 :         long nCallPos = pFuncData->GetCallerPos();
    1463           0 :         if (nCallPos>nUserLen)                          // should not happen
    1464             :         {
    1465             :             OSL_FAIL("wrong CallPos");
    1466           0 :             nCallPos = nUserLen;
    1467             :         }
    1468             : 
    1469           0 :         long nDestLen = nUserLen + 1;
    1470           0 :         uno::Sequence<uno::Any> aRealArgs( nDestLen );
    1471           0 :         uno::Any* pDest = aRealArgs.getArray();
    1472             : 
    1473           0 :         const uno::Any* pSource = aArgs.getConstArray();
    1474           0 :         long nSrcPos = 0;
    1475             : 
    1476           0 :         for ( long nDestPos = 0; nDestPos < nDestLen; nDestPos++ )
    1477             :         {
    1478           0 :             if ( nDestPos == nCallPos )
    1479           0 :                 pDest[nDestPos] = aCallerAny;
    1480             :             else
    1481           0 :                 pDest[nDestPos] = pSource[nSrcPos++];
    1482             :         }
    1483             : 
    1484           0 :         ExecuteCallWithArgs( aRealArgs );
    1485             :     }
    1486             :     else
    1487           0 :         ExecuteCallWithArgs( aArgs );
    1488             : }
    1489             : 
    1490           0 : void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs)
    1491             : {
    1492             :     //  rCallArgs may not match argument descriptions (because of caller)
    1493             : 
    1494           0 :     uno::Reference<reflection::XIdlMethod> xFunction;
    1495           0 :     uno::Any aObject;
    1496           0 :     if ( pFuncData )
    1497             :     {
    1498           0 :         xFunction = pFuncData->GetFunction();
    1499           0 :         aObject = pFuncData->GetObject();
    1500             :     }
    1501             : 
    1502           0 :     if ( xFunction.is() )
    1503             :     {
    1504           0 :         uno::Any aAny;
    1505           0 :         nErrCode = 0;
    1506             : 
    1507             :         try
    1508             :         {
    1509           0 :             aAny = xFunction->invoke( aObject, rCallArgs );
    1510             :         }
    1511           0 :         catch(lang::IllegalArgumentException&)
    1512             :         {
    1513           0 :             nErrCode = errIllegalArgument;
    1514             :         }
    1515             : 
    1516           0 :         catch(const reflection::InvocationTargetException& rWrapped)
    1517             :         {
    1518           0 :             if ( rWrapped.TargetException.getValueType().equals(
    1519           0 :                     getCppuType( (lang::IllegalArgumentException*)0 ) ) )
    1520           0 :                 nErrCode = errIllegalArgument;
    1521           0 :             else if ( rWrapped.TargetException.getValueType().equals(
    1522           0 :                     getCppuType( (sheet::NoConvergenceException*)0 ) ) )
    1523           0 :                 nErrCode = errNoConvergence;
    1524             :             else
    1525           0 :                 nErrCode = errNoValue;
    1526             :         }
    1527             : 
    1528           0 :         catch(uno::Exception&)
    1529             :         {
    1530           0 :             nErrCode = errNoValue;
    1531             :         }
    1532             : 
    1533           0 :         if (!nErrCode)
    1534           0 :             SetResult( aAny );      // convert result to Calc types
    1535           0 :     }
    1536           0 : }
    1537             : 
    1538           0 : void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
    1539             : {
    1540           0 :     nErrCode = 0;
    1541           0 :     xVarRes = NULL;
    1542             : 
    1543             :     // Reflection* pRefl = rNewRes.getReflection();
    1544             : 
    1545           0 :     uno::TypeClass eClass = rNewRes.getValueTypeClass();
    1546           0 :     uno::Type aType = rNewRes.getValueType();
    1547           0 :     switch (eClass)
    1548             :     {
    1549             :         case uno::TypeClass_VOID:
    1550           0 :             nErrCode = NOTAVAILABLE;         // #NA
    1551           0 :             break;
    1552             : 
    1553             :         case uno::TypeClass_ENUM:
    1554             :         case uno::TypeClass_BOOLEAN:
    1555             :         case uno::TypeClass_CHAR:
    1556             :         case uno::TypeClass_BYTE:
    1557             :         case uno::TypeClass_SHORT:
    1558             :         case uno::TypeClass_UNSIGNED_SHORT:
    1559             :         case uno::TypeClass_LONG:
    1560             :         case uno::TypeClass_UNSIGNED_LONG:
    1561             :         case uno::TypeClass_FLOAT:
    1562             :         case uno::TypeClass_DOUBLE:
    1563             :             {
    1564             :                 uno::TypeClass eMyClass;
    1565           0 :                 ScApiTypeConversion::ConvertAnyToDouble( fValue, eMyClass, rNewRes);
    1566           0 :                 bHasString = false;
    1567             :             }
    1568           0 :             break;
    1569             : 
    1570             :         case uno::TypeClass_STRING:
    1571             :             {
    1572           0 :                 rNewRes >>= aString;
    1573           0 :                 bHasString = sal_True;
    1574             :             }
    1575           0 :             break;
    1576             : 
    1577             :         case uno::TypeClass_INTERFACE:
    1578             :             {
    1579             :                 //! directly extract XVolatileResult from any?
    1580           0 :                 uno::Reference<uno::XInterface> xInterface;
    1581           0 :                 rNewRes >>= xInterface;
    1582           0 :                 if ( xInterface.is() )
    1583           0 :                     xVarRes = uno::Reference<sheet::XVolatileResult>( xInterface, uno::UNO_QUERY );
    1584             : 
    1585           0 :                 if (!xVarRes.is())
    1586           0 :                     nErrCode = errNoValue;          // unknown interface
    1587             :             }
    1588           0 :             break;
    1589             : 
    1590             :         default:
    1591           0 :             if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int32> > *)0 ) ) )
    1592             :             {
    1593           0 :                 const uno::Sequence< uno::Sequence<sal_Int32> >* pRowSeq = NULL;
    1594             : 
    1595             :                 //! use pointer from any!
    1596           0 :                 uno::Sequence< uno::Sequence<sal_Int32> > aSequence;
    1597           0 :                 if ( rNewRes >>= aSequence )
    1598           0 :                     pRowSeq = &aSequence;
    1599             : 
    1600           0 :                 if ( pRowSeq )
    1601             :                 {
    1602           0 :                     long nRowCount = pRowSeq->getLength();
    1603           0 :                     const uno::Sequence<sal_Int32>* pRowArr = pRowSeq->getConstArray();
    1604           0 :                     long nMaxColCount = 0;
    1605             :                     long nCol, nRow;
    1606           0 :                     for (nRow=0; nRow<nRowCount; nRow++)
    1607             :                     {
    1608           0 :                         long nTmp = pRowArr[nRow].getLength();
    1609           0 :                         if ( nTmp > nMaxColCount )
    1610           0 :                             nMaxColCount = nTmp;
    1611             :                     }
    1612           0 :                     if ( nMaxColCount && nRowCount )
    1613             :                     {
    1614             :                         xMatrix = new ScMatrix(
    1615             :                                 static_cast<SCSIZE>(nMaxColCount),
    1616           0 :                                 static_cast<SCSIZE>(nRowCount), 0.0);
    1617           0 :                         for (nRow=0; nRow<nRowCount; nRow++)
    1618             :                         {
    1619           0 :                             long nColCount = pRowArr[nRow].getLength();
    1620           0 :                             const sal_Int32* pColArr = pRowArr[nRow].getConstArray();
    1621           0 :                             for (nCol=0; nCol<nColCount; nCol++)
    1622           0 :                                 xMatrix->PutDouble( pColArr[nCol],
    1623             :                                         static_cast<SCSIZE>(nCol),
    1624           0 :                                         static_cast<SCSIZE>(nRow) );
    1625           0 :                             for (nCol=nColCount; nCol<nMaxColCount; nCol++)
    1626             :                                 xMatrix->PutDouble( 0.0,
    1627             :                                         static_cast<SCSIZE>(nCol),
    1628           0 :                                         static_cast<SCSIZE>(nRow) );
    1629             :                         }
    1630             :                     }
    1631           0 :                 }
    1632             :             }
    1633           0 :             else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) )
    1634             :             {
    1635           0 :                 const uno::Sequence< uno::Sequence<double> >* pRowSeq = NULL;
    1636             : 
    1637             :                 //! use pointer from any!
    1638           0 :                 uno::Sequence< uno::Sequence<double> > aSequence;
    1639           0 :                 if ( rNewRes >>= aSequence )
    1640           0 :                     pRowSeq = &aSequence;
    1641             : 
    1642           0 :                 if ( pRowSeq )
    1643             :                 {
    1644           0 :                     long nRowCount = pRowSeq->getLength();
    1645           0 :                     const uno::Sequence<double>* pRowArr = pRowSeq->getConstArray();
    1646           0 :                     long nMaxColCount = 0;
    1647             :                     long nCol, nRow;
    1648           0 :                     for (nRow=0; nRow<nRowCount; nRow++)
    1649             :                     {
    1650           0 :                         long nTmp = pRowArr[nRow].getLength();
    1651           0 :                         if ( nTmp > nMaxColCount )
    1652           0 :                             nMaxColCount = nTmp;
    1653             :                     }
    1654           0 :                     if ( nMaxColCount && nRowCount )
    1655             :                     {
    1656             :                         xMatrix = new ScMatrix(
    1657             :                                 static_cast<SCSIZE>(nMaxColCount),
    1658           0 :                                 static_cast<SCSIZE>(nRowCount), 0.0);
    1659           0 :                         for (nRow=0; nRow<nRowCount; nRow++)
    1660             :                         {
    1661           0 :                             long nColCount = pRowArr[nRow].getLength();
    1662           0 :                             const double* pColArr = pRowArr[nRow].getConstArray();
    1663           0 :                             for (nCol=0; nCol<nColCount; nCol++)
    1664           0 :                                 xMatrix->PutDouble( pColArr[nCol],
    1665             :                                         static_cast<SCSIZE>(nCol),
    1666           0 :                                         static_cast<SCSIZE>(nRow) );
    1667           0 :                             for (nCol=nColCount; nCol<nMaxColCount; nCol++)
    1668             :                                 xMatrix->PutDouble( 0.0,
    1669             :                                         static_cast<SCSIZE>(nCol),
    1670           0 :                                         static_cast<SCSIZE>(nRow) );
    1671             :                         }
    1672             :                     }
    1673           0 :                 }
    1674             :             }
    1675           0 :             else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) )
    1676             :             {
    1677           0 :                 const uno::Sequence< uno::Sequence<rtl::OUString> >* pRowSeq = NULL;
    1678             : 
    1679             :                 //! use pointer from any!
    1680           0 :                 uno::Sequence< uno::Sequence<rtl::OUString> > aSequence;
    1681           0 :                 if ( rNewRes >>= aSequence )
    1682           0 :                     pRowSeq = &aSequence;
    1683             : 
    1684           0 :                 if ( pRowSeq )
    1685             :                 {
    1686           0 :                     long nRowCount = pRowSeq->getLength();
    1687           0 :                     const uno::Sequence<rtl::OUString>* pRowArr = pRowSeq->getConstArray();
    1688           0 :                     long nMaxColCount = 0;
    1689             :                     long nCol, nRow;
    1690           0 :                     for (nRow=0; nRow<nRowCount; nRow++)
    1691             :                     {
    1692           0 :                         long nTmp = pRowArr[nRow].getLength();
    1693           0 :                         if ( nTmp > nMaxColCount )
    1694           0 :                             nMaxColCount = nTmp;
    1695             :                     }
    1696           0 :                     if ( nMaxColCount && nRowCount )
    1697             :                     {
    1698             :                         xMatrix = new ScMatrix(
    1699             :                                 static_cast<SCSIZE>(nMaxColCount),
    1700           0 :                                 static_cast<SCSIZE>(nRowCount), 0.0);
    1701           0 :                         for (nRow=0; nRow<nRowCount; nRow++)
    1702             :                         {
    1703           0 :                             long nColCount = pRowArr[nRow].getLength();
    1704           0 :                             const rtl::OUString* pColArr = pRowArr[nRow].getConstArray();
    1705           0 :                             for (nCol=0; nCol<nColCount; nCol++)
    1706           0 :                                 xMatrix->PutString( pColArr[nCol],
    1707             :                                     static_cast<SCSIZE>(nCol),
    1708           0 :                                     static_cast<SCSIZE>(nRow) );
    1709           0 :                             for (nCol=nColCount; nCol<nMaxColCount; nCol++)
    1710           0 :                                 xMatrix->PutString( EMPTY_OUSTRING,
    1711             :                                         static_cast<SCSIZE>(nCol),
    1712           0 :                                         static_cast<SCSIZE>(nRow) );
    1713             :                         }
    1714             :                     }
    1715           0 :                 }
    1716             :             }
    1717           0 :             else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) )
    1718             :             {
    1719           0 :                 xMatrix = ScSequenceToMatrix::CreateMixedMatrix( rNewRes );
    1720             :             }
    1721             : 
    1722           0 :             if (!xMatrix)                       // no array found
    1723           0 :                 nErrCode = errNoValue;          //! code for error in return type???
    1724           0 :     }
    1725           0 : }
    1726             : 
    1727             : 
    1728             : 
    1729             : //------------------------------------------------------------------------
    1730             : 
    1731             : 
    1732             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10