1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: addincol.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 #include <comphelper/processfactory.hxx>
37 #include <tools/debug.hxx>
38 #include <i18npool/mslangid.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vos/xception.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <unotools/charclass.hxx>
44 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
45 #include <com/sun/star/lang/XServiceName.hpp>
46 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
48 #include <com/sun/star/reflection/XIdlClass.hpp>
49 #include <com/sun/star/reflection/XIdlClassProvider.hpp>
50 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
51 #include <com/sun/star/beans/XIntrospection.hpp>
52 #include <com/sun/star/beans/MethodConcept.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include <com/sun/star/table/XCellRange.hpp>
55 #include <com/sun/star/lang/Locale.hpp>
56 #include <com/sun/star/sheet/XCompatibilityNames.hpp>
58 #include "addincol.hxx"
59 #include "addinhelpid.hxx"
60 #include "compiler.hxx"
61 #include "scmatrix.hxx"
62 #include "addinlis.hxx"
63 #include "formula/errorcodes.hxx"
64 #include "scfuncs.hrc"
65 #include "optutil.hxx"
66 #include "addincfg.hxx"
68 #include "rangeseq.hxx"
69 #include "funcdesc.hxx"
71 using namespace com::sun::star
;
73 //------------------------------------------------------------------------
75 #define SC_CALLERPOS_NONE (-1)
77 #define SCADDINSUPPLIER_SERVICE "com.sun.star.sheet.AddIn"
79 //------------------------------------------------------------------------
84 //------------------------------------------------------------------------
86 ScUnoAddInFuncData::ScUnoAddInFuncData( const String
& rNam
, const String
& rLoc
,
88 USHORT nCat
, USHORT nHelp
,
89 const uno::Reference
<reflection::XIdlMethod
>& rFunc
,
91 long nAC
, const ScAddInArgDesc
* pAD
,
93 aOriginalName( rNam
),
97 aDescription( rDesc
),
104 bCompInitialized( FALSE
)
108 pArgDescs
= new ScAddInArgDesc
[nArgCount
];
109 for (long i
=0; i
<nArgCount
; i
++)
110 pArgDescs
[i
] = pAD
[i
];
115 ScGlobal::pCharClass
->toUpper(aUpperName
);
116 ScGlobal::pCharClass
->toUpper(aUpperLocal
);
119 ScUnoAddInFuncData::~ScUnoAddInFuncData()
124 const uno::Sequence
<sheet::LocalizedName
>& ScUnoAddInFuncData::GetCompNames() const
126 if ( !bCompInitialized
)
128 // read sequence of compatibility names on demand
130 uno::Reference
<sheet::XAddIn
> xAddIn
;
131 if ( aObject
>>= xAddIn
)
133 uno::Reference
<sheet::XCompatibilityNames
> xComp( xAddIn
, uno::UNO_QUERY
);
134 if ( xComp
.is() && xFunction
.is() )
136 rtl::OUString aMethodName
= xFunction
->getName();
137 aCompNames
= xComp
->getCompatibilityNames( aMethodName
);
139 // change all locale entries to default case
140 // (language in lower case, country in upper case)
141 // for easier searching
143 long nSeqLen
= aCompNames
.getLength();
146 sheet::LocalizedName
* pArray
= aCompNames
.getArray();
147 for (long i
=0; i
<nSeqLen
; i
++)
149 lang::Locale
& rLocale
= pArray
[i
].Locale
;
150 rLocale
.Language
= rLocale
.Language
.toAsciiLowerCase();
151 rLocale
.Country
= rLocale
.Country
.toAsciiUpperCase();
157 bCompInitialized
= TRUE
; // also if not successful
162 void ScUnoAddInFuncData::SetCompNames( const uno::Sequence
< sheet::LocalizedName
>& rNew
)
164 DBG_ASSERT( !bCompInitialized
, "SetCompNames after initializing" );
168 // change all locale entries to default case
169 // (language in lower case, country in upper case)
170 // for easier searching
172 long nSeqLen
= aCompNames
.getLength();
175 sheet::LocalizedName
* pArray
= aCompNames
.getArray();
176 for (long i
=0; i
<nSeqLen
; i
++)
178 lang::Locale
& rLocale
= pArray
[i
].Locale
;
179 rLocale
.Language
= rLocale
.Language
.toAsciiLowerCase();
180 rLocale
.Country
= rLocale
.Country
.toAsciiUpperCase();
184 bCompInitialized
= TRUE
;
187 BOOL
ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang
, String
& rRetExcelName
) const
189 const uno::Sequence
<sheet::LocalizedName
>& rSequence
= GetCompNames();
190 long nSeqLen
= rSequence
.getLength();
193 const sheet::LocalizedName
* pArray
= rSequence
.getConstArray();
196 rtl::OUString aLangStr
, aCountryStr
;
197 MsLangId::convertLanguageToIsoNames( eDestLang
, aLangStr
, aCountryStr
);
198 rtl::OUString aUserLang
= aLangStr
.toAsciiLowerCase();
199 rtl::OUString aUserCountry
= aCountryStr
.toAsciiUpperCase();
201 // first check for match of both language and country
203 for ( i
=0; i
<nSeqLen
; i
++)
204 if ( pArray
[i
].Locale
.Language
== aUserLang
&&
205 pArray
[i
].Locale
.Country
== aUserCountry
)
207 rRetExcelName
= pArray
[i
].Name
;
211 // second: check only language
213 for ( i
=0; i
<nSeqLen
; i
++)
214 if ( pArray
[i
].Locale
.Language
== aUserLang
)
216 rRetExcelName
= pArray
[i
].Name
;
220 // third: #i57772# fall-back to en-US
222 if ( eDestLang
!= LANGUAGE_ENGLISH_US
)
223 return GetExcelName( LANGUAGE_ENGLISH_US
, rRetExcelName
);
225 // forth: use first (default) entry
227 rRetExcelName
= pArray
[0].Name
;
233 void ScUnoAddInFuncData::SetFunction( const uno::Reference
< reflection::XIdlMethod
>& rNewFunc
, const uno::Any
& rNewObj
)
235 xFunction
= rNewFunc
;
239 void ScUnoAddInFuncData::SetArguments( long nNewCount
, const ScAddInArgDesc
* pNewDescs
)
243 nArgCount
= nNewCount
;
246 pArgDescs
= new ScAddInArgDesc
[nArgCount
];
247 for (long i
=0; i
<nArgCount
; i
++)
248 pArgDescs
[i
] = pNewDescs
[i
];
254 void ScUnoAddInFuncData::SetCallerPos( long nNewPos
)
256 nCallerPos
= nNewPos
;
259 //------------------------------------------------------------------------
261 ScUnoAddInCollection::ScUnoAddInCollection() :
264 pExactHashMap( NULL
),
265 pNameHashMap( NULL
),
266 pLocalHashMap( NULL
),
267 bInitialized( FALSE
)
271 ScUnoAddInCollection::~ScUnoAddInCollection()
276 void ScUnoAddInCollection::Clear()
278 DELETEZ( pExactHashMap
);
279 DELETEZ( pNameHashMap
);
280 DELETEZ( pLocalHashMap
);
283 for ( long i
=0; i
<nFuncCount
; i
++ )
284 delete ppFuncData
[i
];
290 bInitialized
= FALSE
;
293 uno::Reference
<uno::XComponentContext
> getContext(uno::Reference
<lang::XMultiServiceFactory
> xMSF
)
295 uno::Reference
<uno::XComponentContext
> xCtx
;
297 uno::Reference
<beans::XPropertySet
> xPropset(xMSF
, uno::UNO_QUERY
);
298 xPropset
->getPropertyValue(
299 ::rtl::OUString::createFromAscii("DefaultContext")) >>= xCtx
;
301 catch ( uno::Exception
& ) {
306 void ScUnoAddInCollection::Initialize()
308 DBG_ASSERT( !bInitialized
, "Initialize twice?" );
310 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
311 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
314 uno::Reference
<container::XEnumeration
> xEnum
=
315 xEnAc
->createContentEnumeration(
316 rtl::OUString::createFromAscii(SCADDINSUPPLIER_SERVICE
) );
319 // loop through all AddIns
320 while ( xEnum
->hasMoreElements() )
322 uno::Any aAddInAny
= xEnum
->nextElement();
323 //? if ( aAddInAny.getReflection()->getTypeClass() == uno::TypeClass_INTERFACE )
325 uno::Reference
<uno::XInterface
> xIntFac
;
326 aAddInAny
>>= xIntFac
;
329 // #i59984# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
330 // passing the context to the component
332 uno::Reference
<uno::XInterface
> xInterface
;
333 uno::Reference
<uno::XComponentContext
> xCtx
= getContext(xManager
);
334 uno::Reference
<lang::XSingleComponentFactory
> xCFac( xIntFac
, uno::UNO_QUERY
);
335 if (xCtx
.is() && xCFac
.is())
337 xInterface
= xCFac
->createInstanceWithContext(xCtx
);
339 ReadFromAddIn( xInterface
);
342 if (!xInterface
.is())
344 uno::Reference
<lang::XSingleServiceFactory
> xFac( xIntFac
, uno::UNO_QUERY
);
347 xInterface
= xFac
->createInstance();
349 ReadFromAddIn( xInterface
);
358 // ReadConfiguration is called after looking at the AddIn implementations.
359 // Duplicated are skipped (by using the service information, they don't have to be updated again
360 // when argument information is needed).
363 bInitialized
= TRUE
; // with or without functions
365 // -----------------------------------------------------------------------------
367 USHORT
lcl_GetCategory( const String
& rName
)
369 static const sal_Char
* aFuncNames
[SC_FUNCGROUP_COUNT
] =
371 // array index = ID - 1 (ID starts at 1)
373 "Database", // ID_FUNCTION_GRP_DATABASE
374 "Date&Time", // ID_FUNCTION_GRP_DATETIME
375 "Financial", // ID_FUNCTION_GRP_FINANZ
376 "Information", // ID_FUNCTION_GRP_INFO
377 "Logical", // ID_FUNCTION_GRP_LOGIC
378 "Mathematical", // ID_FUNCTION_GRP_MATH
379 "Matrix", // ID_FUNCTION_GRP_MATRIX
380 "Statistical", // ID_FUNCTION_GRP_STATISTIC
381 "Spreadsheet", // ID_FUNCTION_GRP_TABLE
382 "Text", // ID_FUNCTION_GRP_TEXT
383 "Add-In" // ID_FUNCTION_GRP_ADDINS
385 for (USHORT i
=0; i
<SC_FUNCGROUP_COUNT
; i
++)
386 if ( rName
.EqualsAscii( aFuncNames
[i
] ) )
387 return i
+1; // IDs start at 1
389 return ID_FUNCTION_GRP_ADDINS
; // if not found, use Add-In group
393 #define CFGPATH_ADDINS "Office.CalcAddIns/AddInInfo"
394 #define CFGSTR_ADDINFUNCTIONS "AddInFunctions"
396 #define CFG_FUNCPROP_DISPLAYNAME 0
397 #define CFG_FUNCPROP_DESCRIPTION 1
398 #define CFG_FUNCPROP_CATEGORY 2
399 #define CFG_FUNCPROP_COUNT 3
400 #define CFGSTR_DISPLAYNAME "DisplayName"
401 #define CFGSTR_DESCRIPTION "Description"
402 #define CFGSTR_CATEGORY "Category"
403 // CategoryDisplayName is ignored for now
405 #define CFGSTR_COMPATIBILITYNAME "CompatibilityName"
406 #define CFGSTR_PARAMETERS "Parameters"
409 void ScUnoAddInCollection::ReadConfiguration()
411 // called only from Initialize
413 ScAddInCfg
& rAddInConfig
= SC_MOD()->GetAddInCfg();
415 // additional, temporary config item for the compatibility names
416 ScLinkConfigItem
aAllLocalesConfig( rtl::OUString::createFromAscii( CFGPATH_ADDINS
), CONFIG_MODE_ALL_LOCALES
);
417 // CommitLink is not used (only reading values)
419 const rtl::OUString
sSlash('/');
421 // get the list of add-ins (services)
422 rtl::OUString aEmptyString
;
423 uno::Sequence
<rtl::OUString
> aServiceNames
= rAddInConfig
.GetNodeNames( aEmptyString
);
425 sal_Int32 nServiceCount
= aServiceNames
.getLength();
426 for ( sal_Int32 nService
= 0; nService
< nServiceCount
; nService
++ )
428 rtl::OUString aServiceName
= aServiceNames
[nService
];
429 ScUnoAddInHelpIdGenerator
aHelpIdGenerator( aServiceName
);
431 rtl::OUString aFunctionsPath
= aServiceName
;
432 aFunctionsPath
+= sSlash
;
433 aFunctionsPath
+= rtl::OUString::createFromAscii( CFGSTR_ADDINFUNCTIONS
);
435 uno::Sequence
<rtl::OUString
> aFunctionNames
= rAddInConfig
.GetNodeNames( aFunctionsPath
);
436 sal_Int32 nNewCount
= aFunctionNames
.getLength();
440 long nOld
= nFuncCount
;
441 nFuncCount
= nNewCount
+nOld
;
444 ScUnoAddInFuncData
** ppNew
= new ScUnoAddInFuncData
*[nFuncCount
];
445 for (long i
=0; i
<nOld
; i
++)
446 ppNew
[i
] = ppFuncData
[i
];
451 ppFuncData
= new ScUnoAddInFuncData
*[nFuncCount
];
453 //! TODO: adjust bucket count?
454 if ( !pExactHashMap
)
455 pExactHashMap
= new ScAddInHashMap
;
457 pNameHashMap
= new ScAddInHashMap
;
458 if ( !pLocalHashMap
)
459 pLocalHashMap
= new ScAddInHashMap
;
461 //! get the function information in a single call for all functions?
463 const rtl::OUString
* pFuncNameArray
= aFunctionNames
.getConstArray();
464 for ( sal_Int32 nFuncPos
= 0; nFuncPos
< nNewCount
; nFuncPos
++ )
466 ppFuncData
[nFuncPos
+nOld
] = NULL
;
468 // stored function name: (service name).(function)
469 String
aFuncName( aServiceName
);
471 aFuncName
+= String( pFuncNameArray
[nFuncPos
] );
473 // skip the function if already known (read from old AddIn service)
475 if ( pExactHashMap
->find( aFuncName
) == pExactHashMap
->end() )
477 rtl::OUString aLocalName
;
478 rtl::OUString aDescription
;
479 USHORT nCategory
= ID_FUNCTION_GRP_ADDINS
;
481 // get direct information on the function
483 rtl::OUString aFuncPropPath
= aFunctionsPath
;
484 aFuncPropPath
+= sSlash
;
485 aFuncPropPath
+= pFuncNameArray
[nFuncPos
];
486 aFuncPropPath
+= sSlash
;
488 uno::Sequence
<rtl::OUString
> aFuncPropNames(CFG_FUNCPROP_COUNT
);
489 rtl::OUString
* pNameArray
= aFuncPropNames
.getArray();
490 pNameArray
[CFG_FUNCPROP_DISPLAYNAME
] = aFuncPropPath
;
491 pNameArray
[CFG_FUNCPROP_DISPLAYNAME
] += rtl::OUString::createFromAscii( CFGSTR_DISPLAYNAME
);
492 pNameArray
[CFG_FUNCPROP_DESCRIPTION
] = aFuncPropPath
;
493 pNameArray
[CFG_FUNCPROP_DESCRIPTION
] += rtl::OUString::createFromAscii( CFGSTR_DESCRIPTION
);
494 pNameArray
[CFG_FUNCPROP_CATEGORY
] = aFuncPropPath
;
495 pNameArray
[CFG_FUNCPROP_CATEGORY
] += rtl::OUString::createFromAscii( CFGSTR_CATEGORY
);
497 uno::Sequence
<uno::Any
> aFuncProperties
= rAddInConfig
.GetProperties( aFuncPropNames
);
498 if ( aFuncProperties
.getLength() == CFG_FUNCPROP_COUNT
)
500 aFuncProperties
[CFG_FUNCPROP_DISPLAYNAME
] >>= aLocalName
;
501 aFuncProperties
[CFG_FUNCPROP_DESCRIPTION
] >>= aDescription
;
503 rtl::OUString aCategoryName
;
504 aFuncProperties
[CFG_FUNCPROP_CATEGORY
] >>= aCategoryName
;
505 nCategory
= lcl_GetCategory( aCategoryName
);
508 // get compatibility names
510 uno::Sequence
<sheet::LocalizedName
> aCompNames
;
512 rtl::OUString aCompPath
= aFuncPropPath
;
513 aCompPath
+= rtl::OUString::createFromAscii( CFGSTR_COMPATIBILITYNAME
);
514 uno::Sequence
<rtl::OUString
> aCompPropNames( &aCompPath
, 1 );
516 uno::Sequence
<uno::Any
> aCompProperties
= aAllLocalesConfig
.GetProperties( aCompPropNames
);
517 if ( aCompProperties
.getLength() == 1 )
519 uno::Sequence
<beans::PropertyValue
> aLocalEntries
;
520 if ( aCompProperties
[0] >>= aLocalEntries
)
522 sal_Int32 nLocaleCount
= aLocalEntries
.getLength();
523 aCompNames
.realloc( nLocaleCount
);
524 const beans::PropertyValue
* pConfigArray
= aLocalEntries
.getConstArray();
525 sheet::LocalizedName
* pCompArray
= aCompNames
.getArray();
527 for ( sal_Int32 nLocale
= 0; nLocale
< nLocaleCount
; nLocale
++ )
529 const sal_Unicode cLocaleSep
= '-'; // separator in configuration locale strings
531 // PropertyValue name is the locale (convert from string to Locale struct)
533 const rtl::OUString
& rLocaleStr
= pConfigArray
[nLocale
].Name
;
534 lang::Locale
& rLocale
= pCompArray
[nLocale
].Locale
;
535 sal_Int32 nSepPos
= rLocaleStr
.indexOf( cLocaleSep
);
538 rLocale
.Language
= rLocaleStr
.copy( 0, nSepPos
);
539 rLocale
.Country
= rLocaleStr
.copy( nSepPos
+1 );
542 rLocale
.Language
= rLocaleStr
; // leave country empty (default ctor from sequence)
544 // PropertyValue value is the localized value (string in this case)
546 pConfigArray
[nLocale
].Value
>>= pCompArray
[nLocale
].Name
;
553 ScAddInArgDesc
* pVisibleArgs
= NULL
;
554 long nVisibleCount
= 0;
555 long nCallerPos
= SC_CALLERPOS_NONE
;
557 rtl::OUString aArgumentsPath
= aFuncPropPath
;
558 aArgumentsPath
+= rtl::OUString::createFromAscii( CFGSTR_PARAMETERS
);
560 uno::Sequence
<rtl::OUString
> aArgumentNames
= rAddInConfig
.GetNodeNames( aArgumentsPath
);
561 sal_Int32 nArgumentCount
= aArgumentNames
.getLength();
562 if ( nArgumentCount
)
564 // get DisplayName and Description for each argument
565 uno::Sequence
<rtl::OUString
> aArgPropNames( nArgumentCount
* 2 );
566 rtl::OUString
* pPropNameArray
= aArgPropNames
.getArray();
569 sal_Int32 nIndex
= 0;
570 const rtl::OUString
* pArgNameArray
= aArgumentNames
.getConstArray();
571 for ( nArgument
= 0; nArgument
< nArgumentCount
; nArgument
++ )
573 rtl::OUString aOneArgPath
= aArgumentsPath
;
574 aOneArgPath
+= sSlash
;
575 aOneArgPath
+= pArgNameArray
[nArgument
];
576 aOneArgPath
+= sSlash
;
578 pPropNameArray
[nIndex
] = aOneArgPath
;
579 pPropNameArray
[nIndex
++] += rtl::OUString::createFromAscii( CFGSTR_DISPLAYNAME
);
580 pPropNameArray
[nIndex
] = aOneArgPath
;
581 pPropNameArray
[nIndex
++] += rtl::OUString::createFromAscii( CFGSTR_DESCRIPTION
);
584 uno::Sequence
<uno::Any
> aArgProperties
= rAddInConfig
.GetProperties( aArgPropNames
);
585 if ( aArgProperties
.getLength() == aArgPropNames
.getLength() )
587 const uno::Any
* pPropArray
= aArgProperties
.getConstArray();
588 rtl::OUString sDisplayName
;
589 rtl::OUString sDescription
;
591 ScAddInArgDesc aDesc
;
592 aDesc
.eType
= SC_ADDINARG_NONE
; // arg type is not in configuration
593 aDesc
.bOptional
= FALSE
;
595 nVisibleCount
= nArgumentCount
;
596 pVisibleArgs
= new ScAddInArgDesc
[nVisibleCount
];
599 for ( nArgument
= 0; nArgument
< nArgumentCount
; nArgument
++ )
601 pPropArray
[nIndex
++] >>= sDisplayName
;
602 pPropArray
[nIndex
++] >>= sDescription
;
604 aDesc
.aInternalName
= pArgNameArray
[nArgument
];
605 aDesc
.aName
= sDisplayName
;
606 aDesc
.aDescription
= sDescription
;
608 pVisibleArgs
[nArgument
] = aDesc
;
613 USHORT nHelpId
= aHelpIdGenerator
.GetHelpId( pFuncNameArray
[nFuncPos
] );
615 uno::Reference
<reflection::XIdlMethod
> xFunc
; // remains empty
616 uno::Any aObject
; // also empty
618 // create and insert into the array
620 ScUnoAddInFuncData
* pData
= new ScUnoAddInFuncData(
621 aFuncName
, aLocalName
, aDescription
,
624 nVisibleCount
, pVisibleArgs
, nCallerPos
);
626 pData
->SetCompNames( aCompNames
);
628 ppFuncData
[nFuncPos
+nOld
] = pData
;
630 pExactHashMap
->insert(
631 ScAddInHashMap::value_type(
632 pData
->GetOriginalName(),
634 pNameHashMap
->insert(
635 ScAddInHashMap::value_type(
636 pData
->GetUpperName(),
638 pLocalHashMap
->insert(
639 ScAddInHashMap::value_type(
640 pData
->GetUpperLocal(),
643 delete[] pVisibleArgs
;
649 void ScUnoAddInCollection::LoadComponent( const ScUnoAddInFuncData
& rFuncData
)
651 String aFullName
= rFuncData
.GetOriginalName();
652 xub_StrLen nPos
= aFullName
.SearchBackward( (sal_Unicode
) '.' );
653 if ( nPos
!= STRING_NOTFOUND
&& nPos
> 0 )
655 String aServiceName
= aFullName
.Copy( 0, nPos
);
657 uno::Reference
<lang::XMultiServiceFactory
> xServiceFactory
= comphelper::getProcessServiceFactory();
658 uno::Reference
<uno::XInterface
> xInterface( xServiceFactory
->createInstance( aServiceName
) );
661 UpdateFromAddIn( xInterface
, aServiceName
);
665 BOOL
ScUnoAddInCollection::GetExcelName( const String
& rCalcName
,
666 LanguageType eDestLang
, String
& rRetExcelName
)
668 const ScUnoAddInFuncData
* pFuncData
= GetFuncData( rCalcName
);
670 return pFuncData
->GetExcelName( eDestLang
, rRetExcelName
);
674 BOOL
ScUnoAddInCollection::GetCalcName( const String
& rExcelName
, String
& rRetCalcName
)
679 String aUpperCmp
= rExcelName
;
680 ScGlobal::pCharClass
->toUpper(aUpperCmp
);
682 for (long i
=0; i
<nFuncCount
; i
++)
684 ScUnoAddInFuncData
* pFuncData
= ppFuncData
[i
];
687 const uno::Sequence
<sheet::LocalizedName
>& rSequence
= pFuncData
->GetCompNames();
688 long nSeqLen
= rSequence
.getLength();
691 const sheet::LocalizedName
* pArray
= rSequence
.getConstArray();
692 for ( long nName
=0; nName
<nSeqLen
; nName
++)
693 if ( ScGlobal::pCharClass
->upper( pArray
[nName
].Name
) == aUpperCmp
)
695 //! store upper case for comparing?
697 // use the first function that has this name for any language
698 rRetCalcName
= pFuncData
->GetOriginalName();
707 inline BOOL
IsTypeName( const rtl::OUString
& rName
, const uno::Type
& rType
)
709 return rName
== rType
.getTypeName();
712 BOOL
lcl_ValidReturnType( const uno::Reference
<reflection::XIdlClass
>& xClass
)
714 // this must match with ScUnoAddInCall::SetResult
716 if ( !xClass
.is() ) return FALSE
;
718 switch (xClass
->getTypeClass())
720 // case uno::TypeClass_VOID:
723 case uno::TypeClass_ANY
: // variable type
724 case uno::TypeClass_ENUM
: //! ???
725 case uno::TypeClass_BOOLEAN
:
726 case uno::TypeClass_CHAR
:
727 case uno::TypeClass_BYTE
:
728 case uno::TypeClass_SHORT
:
729 case uno::TypeClass_UNSIGNED_SHORT
:
730 case uno::TypeClass_LONG
:
731 case uno::TypeClass_UNSIGNED_LONG
:
732 case uno::TypeClass_FLOAT
:
733 case uno::TypeClass_DOUBLE
:
734 case uno::TypeClass_STRING
:
735 return TRUE
; // values or string
737 case uno::TypeClass_INTERFACE
:
739 // return type XInterface may contain a XVolatileResult
740 //! XIdlClass needs getType() method!
742 rtl::OUString sName
= xClass
->getName();
744 IsTypeName( sName
, getCppuType((uno::Reference
<sheet::XVolatileResult
>*)0) ) ||
745 IsTypeName( sName
, getCppuType((uno::Reference
<uno::XInterface
>*)0) ) );
750 // nested sequences for arrays
751 //! XIdlClass needs getType() method!
753 rtl::OUString sName
= xClass
->getName();
755 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<INT32
> >*)0) ) ||
756 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<double> >*)0) ) ||
757 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<rtl::OUString
> >*)0) ) ||
758 IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<uno::Any
> >*)0) ) );
764 ScAddInArgumentType
lcl_GetArgType( const uno::Reference
<reflection::XIdlClass
>& xClass
)
767 return SC_ADDINARG_NONE
;
769 uno::TypeClass eType
= xClass
->getTypeClass();
771 if ( eType
== uno::TypeClass_LONG
) //! other integer types?
772 return SC_ADDINARG_INTEGER
;
774 if ( eType
== uno::TypeClass_DOUBLE
)
775 return SC_ADDINARG_DOUBLE
;
777 if ( eType
== uno::TypeClass_STRING
)
778 return SC_ADDINARG_STRING
;
780 //! XIdlClass needs getType() method!
781 rtl::OUString sName
= xClass
->getName();
783 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<INT32
> >*)0) ))
784 return SC_ADDINARG_INTEGER_ARRAY
;
786 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<double> >*)0) ))
787 return SC_ADDINARG_DOUBLE_ARRAY
;
789 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<rtl::OUString
> >*)0) ))
790 return SC_ADDINARG_STRING_ARRAY
;
792 if (IsTypeName( sName
, getCppuType((uno::Sequence
< uno::Sequence
<uno::Any
> >*)0) ))
793 return SC_ADDINARG_MIXED_ARRAY
;
795 if (IsTypeName( sName
, getCppuType((uno::Any
*)0) ))
796 return SC_ADDINARG_VALUE_OR_ARRAY
;
798 if (IsTypeName( sName
, getCppuType((uno::Reference
<table::XCellRange
>*)0) ))
799 return SC_ADDINARG_CELLRANGE
;
801 if (IsTypeName( sName
, getCppuType((uno::Reference
<beans::XPropertySet
>*)0) ))
802 return SC_ADDINARG_CALLER
;
804 if (IsTypeName( sName
, getCppuType((uno::Sequence
<uno::Any
>*)0) ))
805 return SC_ADDINARG_VARARGS
;
807 return SC_ADDINARG_NONE
;
810 void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference
<uno::XInterface
>& xInterface
)
812 uno::Reference
<sheet::XAddIn
> xAddIn( xInterface
, uno::UNO_QUERY
);
813 uno::Reference
<lang::XServiceName
> xName( xInterface
, uno::UNO_QUERY
);
814 if ( xAddIn
.is() && xName
.is() )
816 // AddIns must use the language for which the office is installed
817 LanguageType eOfficeLang
= Application::GetSettings().GetUILanguage();
819 lang::Locale
aLocale( MsLangId::convertLanguageToLocale( eOfficeLang
));
820 xAddIn
->setLocale( aLocale
);
822 String aServiceName
= String( xName
->getServiceName() );
823 ScUnoAddInHelpIdGenerator
aHelpIdGenerator( xName
->getServiceName() );
825 //! pass XIntrospection to ReadFromAddIn
827 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
830 uno::Reference
<beans::XIntrospection
> xIntro(
831 xManager
->createInstance(rtl::OUString::createFromAscii(
832 "com.sun.star.beans.Introspection" )),
838 uno::Reference
<beans::XIntrospectionAccess
> xAcc
= xIntro
->inspect(aObject
);
841 uno::Sequence
< uno::Reference
<reflection::XIdlMethod
> > aMethods
=
842 xAcc
->getMethods( beans::MethodConcept::ALL
);
843 long nNewCount
= aMethods
.getLength();
846 long nOld
= nFuncCount
;
847 nFuncCount
= nNewCount
+nOld
;
850 ScUnoAddInFuncData
** ppNew
= new ScUnoAddInFuncData
*[nFuncCount
];
851 for (long i
=0; i
<nOld
; i
++)
852 ppNew
[i
] = ppFuncData
[i
];
857 ppFuncData
= new ScUnoAddInFuncData
*[nFuncCount
];
859 //! TODO: adjust bucket count?
860 if ( !pExactHashMap
)
861 pExactHashMap
= new ScAddInHashMap
;
863 pNameHashMap
= new ScAddInHashMap
;
864 if ( !pLocalHashMap
)
865 pLocalHashMap
= new ScAddInHashMap
;
867 const uno::Reference
<reflection::XIdlMethod
>* pArray
= aMethods
.getConstArray();
868 for (long nFuncPos
=0; nFuncPos
<nNewCount
; nFuncPos
++)
870 ppFuncData
[nFuncPos
+nOld
] = NULL
;
872 uno::Reference
<reflection::XIdlMethod
> xFunc
= pArray
[nFuncPos
];
875 // leave out internal functions
876 uno::Reference
<reflection::XIdlClass
> xClass
=
877 xFunc
->getDeclaringClass();
881 //! XIdlClass needs getType() method!
882 rtl::OUString sName
= xClass
->getName();
885 getCppuType((uno::Reference
<uno::XInterface
>*)0) ) ||
887 getCppuType((uno::Reference
<reflection::XIdlClassProvider
>*)0) ) ||
889 getCppuType((uno::Reference
<lang::XServiceName
>*)0) ) ||
891 getCppuType((uno::Reference
<lang::XServiceInfo
>*)0) ) ||
893 getCppuType((uno::Reference
<sheet::XAddIn
>*)0) ) );
897 uno::Reference
<reflection::XIdlClass
> xReturn
=
898 xFunc
->getReturnType();
899 if ( !lcl_ValidReturnType( xReturn
) )
904 rtl::OUString aFuncU
= xFunc
->getName();
906 // stored function name: (service name).(function)
907 String aFuncName
= aServiceName
;
909 aFuncName
+= String( aFuncU
);
912 long nVisibleCount
= 0;
913 long nCallerPos
= SC_CALLERPOS_NONE
;
915 uno::Sequence
<reflection::ParamInfo
> aParams
=
916 xFunc
->getParameterInfos();
917 long nParamCount
= aParams
.getLength();
918 const reflection::ParamInfo
* pParArr
= aParams
.getConstArray();
920 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
922 if ( pParArr
[nParamPos
].aMode
!= reflection::ParamMode_IN
)
924 uno::Reference
<reflection::XIdlClass
> xParClass
=
925 pParArr
[nParamPos
].aType
;
926 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
927 if ( eArgType
== SC_ADDINARG_NONE
)
929 else if ( eArgType
== SC_ADDINARG_CALLER
)
930 nCallerPos
= nParamPos
;
936 USHORT nCategory
= lcl_GetCategory(
938 xAddIn
->getProgrammaticCategoryName(
941 USHORT nHelpId
= aHelpIdGenerator
.GetHelpId( aFuncU
);
943 rtl::OUString aLocalU
;
947 getDisplayFunctionName( aFuncU
);
949 catch(uno::Exception
&)
951 aLocalU
= rtl::OUString::createFromAscii( "###" );
953 String aLocalName
= String( aLocalU
);
955 rtl::OUString aDescU
;
959 getFunctionDescription( aFuncU
);
961 catch(uno::Exception
&)
963 aDescU
= rtl::OUString::createFromAscii( "###" );
965 String aDescription
= String( aDescU
);
967 ScAddInArgDesc
* pVisibleArgs
= NULL
;
968 if ( nVisibleCount
> 0 )
970 ScAddInArgDesc aDesc
;
971 pVisibleArgs
= new ScAddInArgDesc
[nVisibleCount
];
973 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
975 uno::Reference
<reflection::XIdlClass
> xParClass
=
976 pParArr
[nParamPos
].aType
;
977 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
978 if ( eArgType
!= SC_ADDINARG_CALLER
)
980 rtl::OUString aArgName
;
984 getDisplayArgumentName( aFuncU
, nParamPos
);
986 catch(uno::Exception
&)
988 aArgName
= rtl::OUString::createFromAscii( "###" );
990 rtl::OUString aArgDesc
;
994 getArgumentDescription( aFuncU
, nParamPos
);
996 catch(uno::Exception
&)
998 aArgName
= rtl::OUString::createFromAscii( "###" );
1002 ( eArgType
== SC_ADDINARG_VALUE_OR_ARRAY
||
1003 eArgType
== SC_ADDINARG_VARARGS
);
1005 aDesc
.eType
= eArgType
;
1006 aDesc
.aName
= String( aArgName
);
1007 aDesc
.aDescription
= String( aArgDesc
);
1008 aDesc
.bOptional
= bOptional
;
1009 //! initialize aInternalName only from config?
1010 aDesc
.aInternalName
= pParArr
[nParamPos
].aName
;
1012 pVisibleArgs
[nDestPos
++] = aDesc
;
1015 DBG_ASSERT( nDestPos
==nVisibleCount
, "wrong count" );
1018 ppFuncData
[nFuncPos
+nOld
] = new ScUnoAddInFuncData(
1019 aFuncName
, aLocalName
, aDescription
,
1022 nVisibleCount
, pVisibleArgs
, nCallerPos
);
1024 const ScUnoAddInFuncData
* pData
=
1025 ppFuncData
[nFuncPos
+nOld
];
1026 pExactHashMap
->insert(
1027 ScAddInHashMap::value_type(
1028 pData
->GetOriginalName(),
1030 pNameHashMap
->insert(
1031 ScAddInHashMap::value_type(
1032 pData
->GetUpperName(),
1034 pLocalHashMap
->insert(
1035 ScAddInHashMap::value_type(
1036 pData
->GetUpperLocal(),
1039 delete[] pVisibleArgs
;
1051 void lcl_UpdateFunctionList( ScFunctionList
& rFunctionList
, const ScUnoAddInFuncData
& rFuncData
)
1053 String aCompare
= rFuncData
.GetUpperLocal(); // as used in FillFunctionDescFromData
1055 ULONG nCount
= rFunctionList
.GetCount();
1056 for (ULONG nPos
=0; nPos
<nCount
; nPos
++)
1058 const ScFuncDesc
* pDesc
= rFunctionList
.GetFunction( nPos
);
1059 if ( pDesc
&& pDesc
->pFuncName
&& *pDesc
->pFuncName
== aCompare
)
1061 ScUnoAddInCollection::FillFunctionDescFromData( rFuncData
, *const_cast<ScFuncDesc
*>(pDesc
) );
1067 const ScAddInArgDesc
* lcl_FindArgDesc( const ScUnoAddInFuncData
& rFuncData
, const String
& rArgIntName
)
1069 long nArgCount
= rFuncData
.GetArgumentCount();
1070 const ScAddInArgDesc
* pArguments
= rFuncData
.GetArguments();
1071 for (long nPos
=0; nPos
<nArgCount
; nPos
++)
1073 if ( pArguments
[nPos
].aInternalName
== rArgIntName
)
1074 return &pArguments
[nPos
];
1079 void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference
<uno::XInterface
>& xInterface
,
1080 const String
& rServiceName
)
1082 uno::Reference
<lang::XLocalizable
> xLoc( xInterface
, uno::UNO_QUERY
);
1083 if ( xLoc
.is() ) // optional in new add-ins
1085 LanguageType eOfficeLang
= Application::GetSettings().GetUILanguage();
1086 lang::Locale
aLocale( MsLangId::convertLanguageToLocale( eOfficeLang
));
1087 xLoc
->setLocale( aLocale
);
1090 // if function list was already initialized, it must be updated
1092 ScFunctionList
* pFunctionList
= NULL
;
1093 if ( ScGlobal::HasStarCalcFunctionList() )
1094 pFunctionList
= ScGlobal::GetStarCalcFunctionList();
1096 // only get the function information from Introspection
1098 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
1099 if ( xManager
.is() )
1101 uno::Reference
<beans::XIntrospection
> xIntro(
1102 xManager
->createInstance(rtl::OUString::createFromAscii(
1103 "com.sun.star.beans.Introspection" )),
1108 aObject
<<= xInterface
;
1109 uno::Reference
<beans::XIntrospectionAccess
> xAcc
= xIntro
->inspect(aObject
);
1112 uno::Sequence
< uno::Reference
<reflection::XIdlMethod
> > aMethods
=
1113 xAcc
->getMethods( beans::MethodConcept::ALL
);
1114 long nMethodCount
= aMethods
.getLength();
1115 const uno::Reference
<reflection::XIdlMethod
>* pArray
= aMethods
.getConstArray();
1116 for (long nFuncPos
=0; nFuncPos
<nMethodCount
; nFuncPos
++)
1118 uno::Reference
<reflection::XIdlMethod
> xFunc
= pArray
[nFuncPos
];
1121 rtl::OUString aFuncU
= xFunc
->getName();
1123 // stored function name: (service name).(function)
1124 String aFuncName
= rServiceName
;
1126 aFuncName
+= String( aFuncU
);
1128 // internal names are skipped because no FuncData exists
1129 ScUnoAddInFuncData
* pOldData
= const_cast<ScUnoAddInFuncData
*>( GetFuncData( aFuncName
) );
1132 // Create new (complete) argument info.
1133 // As in ReadFromAddIn, the reflection information is authoritative.
1134 // Local names and descriptions from pOldData are looked up using the
1135 // internal argument name.
1138 long nVisibleCount
= 0;
1139 long nCallerPos
= SC_CALLERPOS_NONE
;
1141 uno::Sequence
<reflection::ParamInfo
> aParams
=
1142 xFunc
->getParameterInfos();
1143 long nParamCount
= aParams
.getLength();
1144 const reflection::ParamInfo
* pParArr
= aParams
.getConstArray();
1146 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
1148 if ( pParArr
[nParamPos
].aMode
!= reflection::ParamMode_IN
)
1150 uno::Reference
<reflection::XIdlClass
> xParClass
=
1151 pParArr
[nParamPos
].aType
;
1152 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
1153 if ( eArgType
== SC_ADDINARG_NONE
)
1155 else if ( eArgType
== SC_ADDINARG_CALLER
)
1156 nCallerPos
= nParamPos
;
1162 ScAddInArgDesc
* pVisibleArgs
= NULL
;
1163 if ( nVisibleCount
> 0 )
1165 ScAddInArgDesc aDesc
;
1166 pVisibleArgs
= new ScAddInArgDesc
[nVisibleCount
];
1168 for (nParamPos
=0; nParamPos
<nParamCount
; nParamPos
++)
1170 uno::Reference
<reflection::XIdlClass
> xParClass
=
1171 pParArr
[nParamPos
].aType
;
1172 ScAddInArgumentType eArgType
= lcl_GetArgType( xParClass
);
1173 if ( eArgType
!= SC_ADDINARG_CALLER
)
1175 const ScAddInArgDesc
* pOldArgDesc
=
1176 lcl_FindArgDesc( *pOldData
, pParArr
[nParamPos
].aName
);
1179 aDesc
.aName
= pOldArgDesc
->aName
;
1180 aDesc
.aDescription
= pOldArgDesc
->aDescription
;
1183 aDesc
.aName
= aDesc
.aDescription
= String::CreateFromAscii( "###" );
1186 ( eArgType
== SC_ADDINARG_VALUE_OR_ARRAY
||
1187 eArgType
== SC_ADDINARG_VARARGS
);
1189 aDesc
.eType
= eArgType
;
1190 aDesc
.bOptional
= bOptional
;
1191 //! initialize aInternalName only from config?
1192 aDesc
.aInternalName
= pParArr
[nParamPos
].aName
;
1194 pVisibleArgs
[nDestPos
++] = aDesc
;
1197 DBG_ASSERT( nDestPos
==nVisibleCount
, "wrong count" );
1200 pOldData
->SetFunction( xFunc
, aObject
);
1201 pOldData
->SetArguments( nVisibleCount
, pVisibleArgs
);
1202 pOldData
->SetCallerPos( nCallerPos
);
1204 if ( pFunctionList
)
1205 lcl_UpdateFunctionList( *pFunctionList
, *pOldData
);
1207 delete[] pVisibleArgs
;
1217 String
ScUnoAddInCollection::FindFunction( const String
& rUpperName
, BOOL bLocalFirst
)
1222 if (nFuncCount
== 0)
1223 return EMPTY_STRING
;
1227 // first scan all local names (used for entering formulas)
1229 ScAddInHashMap::const_iterator
iLook( pLocalHashMap
->find( rUpperName
) );
1230 if ( iLook
!= pLocalHashMap
->end() )
1231 return iLook
->second
->GetOriginalName();
1234 // after that, scan international names (really?)
1236 iLook
= pNameHashMap
->find( rUpperName
);
1237 if ( iLook
!= pNameHashMap
->end() )
1238 return iLook
->second
->GetOriginalName();
1243 // first scan international names (used when calling a function)
1244 //! before that, check for exact match???
1246 ScAddInHashMap::const_iterator
iLook( pNameHashMap
->find( rUpperName
) );
1247 if ( iLook
!= pNameHashMap
->end() )
1248 return iLook
->second
->GetOriginalName();
1250 // after that, scan all local names (to allow replacing old AddIns with Uno)
1252 iLook
= pLocalHashMap
->find( rUpperName
);
1253 if ( iLook
!= pLocalHashMap
->end() )
1254 return iLook
->second
->GetOriginalName();
1257 return EMPTY_STRING
;
1260 const ScUnoAddInFuncData
* ScUnoAddInCollection::GetFuncData( const String
& rName
, bool bComplete
)
1265 // rName must be the exact internal name
1267 ScAddInHashMap::const_iterator
iLook( pExactHashMap
->find( rName
) );
1268 if ( iLook
!= pExactHashMap
->end() )
1270 const ScUnoAddInFuncData
* pFuncData
= iLook
->second
;
1272 if ( bComplete
&& !pFuncData
->GetFunction().is() ) //! extra flag?
1273 LoadComponent( *pFuncData
);
1281 const ScUnoAddInFuncData
* ScUnoAddInCollection::GetFuncData( long nIndex
)
1286 if (nIndex
< nFuncCount
)
1287 return ppFuncData
[nIndex
];
1291 void ScUnoAddInCollection::LocalizeString( String
& rName
)
1296 // modify rName - input: exact name
1298 ScAddInHashMap::const_iterator
iLook( pExactHashMap
->find( rName
) );
1299 if ( iLook
!= pExactHashMap
->end() )
1300 rName
= iLook
->second
->GetUpperLocal(); //! upper?
1304 long ScUnoAddInCollection::GetFuncCount()
1312 BOOL
ScUnoAddInCollection::FillFunctionDesc( long nFunc
, ScFuncDesc
& rDesc
)
1317 if (nFunc
>= nFuncCount
|| !ppFuncData
[nFunc
])
1320 const ScUnoAddInFuncData
& rFuncData
= *ppFuncData
[nFunc
];
1322 return FillFunctionDescFromData( rFuncData
, rDesc
);
1326 BOOL
ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData
& rFuncData
, ScFuncDesc
& rDesc
)
1330 BOOL bIncomplete
= !rFuncData
.GetFunction().is(); //! extra flag?
1332 long nArgCount
= rFuncData
.GetArgumentCount();
1333 if ( nArgCount
> USHRT_MAX
)
1337 nArgCount
= 0; // if incomplete, fill without argument info (no wrong order)
1339 // nFIndex is set from outside
1341 rDesc
.pFuncName
= new String( rFuncData
.GetUpperLocal() ); //! upper?
1342 rDesc
.nCategory
= rFuncData
.GetCategory();
1343 rDesc
.nHelpId
= rFuncData
.GetHelpId();
1345 String aDesc
= rFuncData
.GetDescription();
1347 aDesc
= rFuncData
.GetLocalName(); // use name if no description is available
1348 rDesc
.pFuncDesc
= new String( aDesc
);
1350 // AddInArgumentType_CALLER is already left out in FuncData
1352 rDesc
.nArgCount
= (USHORT
)nArgCount
;
1355 BOOL bMultiple
= FALSE
;
1356 const ScAddInArgDesc
* pArgs
= rFuncData
.GetArguments();
1358 rDesc
.ppDefArgNames
= new String
*[nArgCount
];
1359 rDesc
.ppDefArgDescs
= new String
*[nArgCount
];
1360 rDesc
.pDefArgFlags
= new ScFuncDesc::ParameterFlags
[nArgCount
];
1361 for ( long nArg
=0; nArg
<nArgCount
; nArg
++ )
1363 rDesc
.ppDefArgNames
[nArg
] = new String( pArgs
[nArg
].aName
);
1364 rDesc
.ppDefArgDescs
[nArg
] = new String( pArgs
[nArg
].aDescription
);
1365 rDesc
.pDefArgFlags
[nArg
].bOptional
= pArgs
[nArg
].bOptional
;
1366 rDesc
.pDefArgFlags
[nArg
].bSuppress
= false;
1368 // no empty names...
1369 if ( rDesc
.ppDefArgNames
[nArg
]->Len() == 0 )
1371 String
aDefName( RTL_CONSTASCII_USTRINGPARAM("arg") );
1372 aDefName
+= String::CreateFromInt32( nArg
+1 );
1373 *rDesc
.ppDefArgNames
[nArg
] = aDefName
;
1376 // last argument repeated?
1377 if ( nArg
+1 == nArgCount
&& ( pArgs
[nArg
].eType
== SC_ADDINARG_VARARGS
) )
1382 rDesc
.nArgCount
+= VAR_ARGS
- 1; // VAR_ARGS means just one repeated arg
1385 rDesc
.bIncomplete
= bIncomplete
;
1391 //------------------------------------------------------------------------
1393 ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection
& rColl
, const String
& rName
,
1394 long nParamCount
) :
1395 bValidCount( FALSE
),
1396 nErrCode( errNoCode
), // before function was called
1401 pFuncData
= rColl
.GetFuncData( rName
, true ); // need fully initialized data
1402 DBG_ASSERT( pFuncData
, "Function Data missing" );
1405 long nDescCount
= pFuncData
->GetArgumentCount();
1406 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1408 // is aVarArg sequence needed?
1409 if ( nParamCount
>= nDescCount
&& nDescCount
> 0 &&
1410 pArgs
[nDescCount
-1].eType
== SC_ADDINARG_VARARGS
)
1412 long nVarCount
= nParamCount
- ( nDescCount
- 1 ); // size of last argument
1413 aVarArg
.realloc( nVarCount
);
1416 else if ( nParamCount
<= nDescCount
)
1418 // all args behind nParamCount must be optional
1420 for (long i
=nParamCount
; i
<nDescCount
; i
++)
1421 if ( !pArgs
[i
].bOptional
)
1422 bValidCount
= FALSE
;
1424 // else invalid (too many arguments)
1427 aArgs
.realloc( nDescCount
); // sequence must always match function signature
1431 ScUnoAddInCall::~ScUnoAddInCall()
1433 // pFuncData is deleted with ScUnoAddInCollection
1436 BOOL
ScUnoAddInCall::ValidParamCount()
1441 ScAddInArgumentType
ScUnoAddInCall::GetArgType( long nPos
)
1445 long nCount
= pFuncData
->GetArgumentCount();
1446 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1448 // if last arg is sequence, use "any" type
1449 if ( nCount
> 0 && nPos
>= nCount
-1 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1450 return SC_ADDINARG_VALUE_OR_ARRAY
;
1452 if ( nPos
< nCount
)
1453 return pArgs
[nPos
].eType
;
1455 return SC_ADDINARG_VALUE_OR_ARRAY
; //! error code !!!!
1458 BOOL
ScUnoAddInCall::NeedsCaller() const
1460 return pFuncData
&& pFuncData
->GetCallerPos() != SC_CALLERPOS_NONE
;
1463 void ScUnoAddInCall::SetCaller( const uno::Reference
<uno::XInterface
>& rInterface
)
1465 xCaller
= rInterface
;
1468 void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell
* pObjSh
)
1472 uno::Reference
<uno::XInterface
> xInt( pObjSh
->GetBaseModel(), uno::UNO_QUERY
);
1477 void ScUnoAddInCall::SetParam( long nPos
, const uno::Any
& rValue
)
1481 long nCount
= pFuncData
->GetArgumentCount();
1482 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1483 if ( nCount
> 0 && nPos
>= nCount
-1 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1485 long nVarPos
= nPos
-(nCount
-1);
1486 if ( nVarPos
< aVarArg
.getLength() )
1487 aVarArg
.getArray()[nVarPos
] = rValue
;
1490 DBG_ERROR("wrong argument number");
1493 else if ( nPos
< aArgs
.getLength() )
1494 aArgs
.getArray()[nPos
] = rValue
;
1497 DBG_ERROR("wrong argument number");
1502 void ScUnoAddInCall::ExecuteCall()
1507 long nCount
= pFuncData
->GetArgumentCount();
1508 const ScAddInArgDesc
* pArgs
= pFuncData
->GetArguments();
1509 if ( nCount
> 0 && pArgs
[nCount
-1].eType
== SC_ADDINARG_VARARGS
)
1511 // insert aVarArg as last argument
1512 //! after inserting caller (to prevent copying twice)?
1514 DBG_ASSERT( aArgs
.getLength() == nCount
, "wrong argument count" );
1515 aArgs
.getArray()[nCount
-1] <<= aVarArg
;
1518 if ( pFuncData
->GetCallerPos() != SC_CALLERPOS_NONE
)
1520 uno::Any aCallerAny
;
1521 aCallerAny
<<= xCaller
;
1523 long nUserLen
= aArgs
.getLength();
1524 long nCallPos
= pFuncData
->GetCallerPos();
1525 if (nCallPos
>nUserLen
) // should not happen
1527 DBG_ERROR("wrong CallPos");
1528 nCallPos
= nUserLen
;
1531 long nDestLen
= nUserLen
+ 1;
1532 uno::Sequence
<uno::Any
> aRealArgs( nDestLen
);
1533 uno::Any
* pDest
= aRealArgs
.getArray();
1535 const uno::Any
* pSource
= aArgs
.getConstArray();
1538 for ( long nDestPos
= 0; nDestPos
< nDestLen
; nDestPos
++ )
1540 if ( nDestPos
== nCallPos
)
1541 pDest
[nDestPos
] = aCallerAny
;
1543 pDest
[nDestPos
] = pSource
[nSrcPos
++];
1546 ExecuteCallWithArgs( aRealArgs
);
1549 ExecuteCallWithArgs( aArgs
);
1552 void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence
<uno::Any
>& rCallArgs
)
1554 // rCallArgs may not match argument descriptions (because of caller)
1556 uno::Reference
<reflection::XIdlMethod
> xFunction
;
1560 xFunction
= pFuncData
->GetFunction();
1561 aObject
= pFuncData
->GetObject();
1564 if ( xFunction
.is() )
1571 aAny
= xFunction
->invoke( aObject
, rCallArgs
);
1573 catch(lang::IllegalArgumentException
&)
1575 nErrCode
= errIllegalArgument
;
1578 catch(FloatingPointException
&)
1580 nErrCode
= errIllegalFPOperation
;
1583 catch(reflection::InvocationTargetException
& rWrapped
)
1585 if ( rWrapped
.TargetException
.getValueType().equals(
1586 getCppuType( (lang::IllegalArgumentException
*)0 ) ) )
1587 nErrCode
= errIllegalArgument
;
1589 nErrCode
= errNoValue
;
1591 catch(uno::Exception
&)
1593 nErrCode
= errNoValue
;
1597 SetResult( aAny
); // convert result to Calc types
1601 void ScUnoAddInCall::SetResult( const uno::Any
& rNewRes
)
1606 // Reflection* pRefl = rNewRes.getReflection();
1608 uno::TypeClass eClass
= rNewRes
.getValueTypeClass();
1609 uno::Type aType
= rNewRes
.getValueType();
1612 case uno::TypeClass_VOID
:
1613 nErrCode
= NOTAVAILABLE
; // #NA
1616 case uno::TypeClass_ENUM
:
1617 case uno::TypeClass_BOOLEAN
:
1618 case uno::TypeClass_CHAR
:
1619 case uno::TypeClass_BYTE
:
1620 case uno::TypeClass_SHORT
:
1621 case uno::TypeClass_UNSIGNED_SHORT
:
1622 case uno::TypeClass_LONG
:
1623 case uno::TypeClass_UNSIGNED_LONG
:
1624 case uno::TypeClass_FLOAT
:
1625 case uno::TypeClass_DOUBLE
:
1627 uno::TypeClass eMyClass
;
1628 ScApiTypeConversion::ConvertAnyToDouble( fValue
, eMyClass
, rNewRes
);
1633 case uno::TypeClass_STRING
:
1635 rtl::OUString aUStr
;
1637 aString
= String( aUStr
);
1642 case uno::TypeClass_INTERFACE
:
1644 //! directly extract XVolatileResult from any?
1645 uno::Reference
<uno::XInterface
> xInterface
;
1646 rNewRes
>>= xInterface
;
1647 if ( xInterface
.is() )
1648 xVarRes
= uno::Reference
<sheet::XVolatileResult
>( xInterface
, uno::UNO_QUERY
);
1651 nErrCode
= errNoValue
; // unknown interface
1656 if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<INT32
> > *)0 ) ) )
1658 const uno::Sequence
< uno::Sequence
<INT32
> >* pRowSeq
= NULL
;
1660 //! use pointer from any!
1661 uno::Sequence
< uno::Sequence
<INT32
> > aSequence
;
1662 if ( rNewRes
>>= aSequence
)
1663 pRowSeq
= &aSequence
;
1667 long nRowCount
= pRowSeq
->getLength();
1668 const uno::Sequence
<INT32
>* pRowArr
= pRowSeq
->getConstArray();
1669 long nMaxColCount
= 0;
1671 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1673 long nTmp
= pRowArr
[nRow
].getLength();
1674 if ( nTmp
> nMaxColCount
)
1675 nMaxColCount
= nTmp
;
1677 if ( nMaxColCount
&& nRowCount
)
1679 xMatrix
= new ScMatrix(
1680 static_cast<SCSIZE
>(nMaxColCount
),
1681 static_cast<SCSIZE
>(nRowCount
) );
1682 ScMatrix
* pMatrix
= xMatrix
;
1683 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1685 long nColCount
= pRowArr
[nRow
].getLength();
1686 const INT32
* pColArr
= pRowArr
[nRow
].getConstArray();
1687 for (nCol
=0; nCol
<nColCount
; nCol
++)
1688 pMatrix
->PutDouble( pColArr
[nCol
],
1689 static_cast<SCSIZE
>(nCol
),
1690 static_cast<SCSIZE
>(nRow
) );
1691 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1692 pMatrix
->PutDouble( 0.0,
1693 static_cast<SCSIZE
>(nCol
),
1694 static_cast<SCSIZE
>(nRow
) );
1699 else if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<double> > *)0 ) ) )
1701 const uno::Sequence
< uno::Sequence
<double> >* pRowSeq
= NULL
;
1703 //! use pointer from any!
1704 uno::Sequence
< uno::Sequence
<double> > aSequence
;
1705 if ( rNewRes
>>= aSequence
)
1706 pRowSeq
= &aSequence
;
1710 long nRowCount
= pRowSeq
->getLength();
1711 const uno::Sequence
<double>* pRowArr
= pRowSeq
->getConstArray();
1712 long nMaxColCount
= 0;
1714 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1716 long nTmp
= pRowArr
[nRow
].getLength();
1717 if ( nTmp
> nMaxColCount
)
1718 nMaxColCount
= nTmp
;
1720 if ( nMaxColCount
&& nRowCount
)
1722 xMatrix
= new ScMatrix(
1723 static_cast<SCSIZE
>(nMaxColCount
),
1724 static_cast<SCSIZE
>(nRowCount
) );
1725 ScMatrix
* pMatrix
= xMatrix
;
1726 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1728 long nColCount
= pRowArr
[nRow
].getLength();
1729 const double* pColArr
= pRowArr
[nRow
].getConstArray();
1730 for (nCol
=0; nCol
<nColCount
; nCol
++)
1731 pMatrix
->PutDouble( pColArr
[nCol
],
1732 static_cast<SCSIZE
>(nCol
),
1733 static_cast<SCSIZE
>(nRow
) );
1734 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1735 pMatrix
->PutDouble( 0.0,
1736 static_cast<SCSIZE
>(nCol
),
1737 static_cast<SCSIZE
>(nRow
) );
1742 else if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<rtl::OUString
> > *)0 ) ) )
1744 const uno::Sequence
< uno::Sequence
<rtl::OUString
> >* pRowSeq
= NULL
;
1746 //! use pointer from any!
1747 uno::Sequence
< uno::Sequence
<rtl::OUString
> > aSequence
;
1748 if ( rNewRes
>>= aSequence
)
1749 pRowSeq
= &aSequence
;
1753 long nRowCount
= pRowSeq
->getLength();
1754 const uno::Sequence
<rtl::OUString
>* pRowArr
= pRowSeq
->getConstArray();
1755 long nMaxColCount
= 0;
1757 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1759 long nTmp
= pRowArr
[nRow
].getLength();
1760 if ( nTmp
> nMaxColCount
)
1761 nMaxColCount
= nTmp
;
1763 if ( nMaxColCount
&& nRowCount
)
1765 xMatrix
= new ScMatrix(
1766 static_cast<SCSIZE
>(nMaxColCount
),
1767 static_cast<SCSIZE
>(nRowCount
) );
1768 ScMatrix
* pMatrix
= xMatrix
;
1769 for (nRow
=0; nRow
<nRowCount
; nRow
++)
1771 long nColCount
= pRowArr
[nRow
].getLength();
1772 const rtl::OUString
* pColArr
= pRowArr
[nRow
].getConstArray();
1773 for (nCol
=0; nCol
<nColCount
; nCol
++)
1774 pMatrix
->PutString( String( pColArr
[nCol
] ),
1775 static_cast<SCSIZE
>(nCol
),
1776 static_cast<SCSIZE
>(nRow
) );
1777 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
1778 pMatrix
->PutString( EMPTY_STRING
,
1779 static_cast<SCSIZE
>(nCol
),
1780 static_cast<SCSIZE
>(nRow
) );
1785 else if ( aType
.equals( getCppuType( (uno::Sequence
< uno::Sequence
<uno::Any
> > *)0 ) ) )
1787 xMatrix
= ScSequenceToMatrix::CreateMixedMatrix( rNewRes
);
1790 if (!xMatrix
) // no array found
1791 nErrCode
= errNoValue
; //! code for error in return type???
1797 //------------------------------------------------------------------------