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