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