xref: /trunk/main/sc/source/core/tool/addincol.cxx (revision a845386b)
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 }
756 
lcl_GetArgType(const uno::Reference<reflection::XIdlClass> & xClass)757 ScAddInArgumentType lcl_GetArgType( const uno::Reference<reflection::XIdlClass>& xClass )
758 {
759     if (!xClass.is())
760         return SC_ADDINARG_NONE;
761 
762     uno::TypeClass eType = xClass->getTypeClass();
763 
764     if ( eType == uno::TypeClass_LONG )             //! other integer types?
765         return SC_ADDINARG_INTEGER;
766 
767     if ( eType == uno::TypeClass_DOUBLE )
768         return SC_ADDINARG_DOUBLE;
769 
770     if ( eType == uno::TypeClass_STRING )
771         return SC_ADDINARG_STRING;
772 
773     //! XIdlClass needs getType() method!
774     rtl::OUString sName = xClass->getName();
775 
776     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<sal_Int32> >*)0) ))
777         return SC_ADDINARG_INTEGER_ARRAY;
778 
779     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) ))
780         return SC_ADDINARG_DOUBLE_ARRAY;
781 
782     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) ))
783         return SC_ADDINARG_STRING_ARRAY;
784 
785     if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) ))
786         return SC_ADDINARG_MIXED_ARRAY;
787 
788     if (IsTypeName( sName, getCppuType((uno::Any*)0) ))
789         return SC_ADDINARG_VALUE_OR_ARRAY;
790 
791     if (IsTypeName( sName, getCppuType((uno::Reference<table::XCellRange>*)0) ))
792         return SC_ADDINARG_CELLRANGE;
793 
794     if (IsTypeName( sName, getCppuType((uno::Reference<beans::XPropertySet>*)0) ))
795         return SC_ADDINARG_CALLER;
796 
797     if (IsTypeName( sName, getCppuType((uno::Sequence<uno::Any>*)0) ))
798         return SC_ADDINARG_VARARGS;
799 
800     return SC_ADDINARG_NONE;
801 }
802 
ReadFromAddIn(const uno::Reference<uno::XInterface> & xInterface)803 void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>& xInterface )
804 {
805     uno::Reference<sheet::XAddIn> xAddIn( xInterface, uno::UNO_QUERY );
806     uno::Reference<lang::XServiceName> xName( xInterface, uno::UNO_QUERY );
807     if ( xAddIn.is() && xName.is() )
808     {
809         //  AddIns must use the language for which the office is installed
810         LanguageType eOfficeLang = Application::GetSettings().GetUILanguage();
811 
812         lang::Locale aLocale( MsLangId::convertLanguageToLocale( eOfficeLang ));
813         xAddIn->setLocale( aLocale );
814 
815         String aServiceName = String( xName->getServiceName() );
816         ScUnoAddInHelpIdGenerator aHelpIdGenerator( xName->getServiceName() );
817 
818         //! pass XIntrospection to ReadFromAddIn
819 
820         uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
821         if ( xManager.is() )
822         {
823             uno::Reference<beans::XIntrospection> xIntro(
824                                     xManager->createInstance(rtl::OUString::createFromAscii(
825                                         "com.sun.star.beans.Introspection" )),
826                                     uno::UNO_QUERY );
827             if ( xIntro.is() )
828             {
829                 uno::Any aObject;
830                 aObject <<= xAddIn;
831                 uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
832                 if (xAcc.is())
833                 {
834                     uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
835                             xAcc->getMethods( beans::MethodConcept::ALL );
836                     long nNewCount = aMethods.getLength();
837                     if ( nNewCount )
838                     {
839                         long nOld = nFuncCount;
840                         nFuncCount = nNewCount+nOld;
841                         if ( nOld )
842                         {
843                             ScUnoAddInFuncData** ppNew = new ScUnoAddInFuncData*[nFuncCount];
844                             for (long i=0; i<nOld; i++)
845                                 ppNew[i] = ppFuncData[i];
846                             delete[] ppFuncData;
847                             ppFuncData = ppNew;
848                         }
849                         else
850                             ppFuncData = new ScUnoAddInFuncData*[nFuncCount];
851 
852                         //! TODO: adjust bucket count?
853                         if ( !pExactHashMap )
854                             pExactHashMap = new ScAddInHashMap;
855                         if ( !pNameHashMap )
856                             pNameHashMap = new ScAddInHashMap;
857                         if ( !pLocalHashMap )
858                             pLocalHashMap = new ScAddInHashMap;
859 
860                         const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
861                         for (long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++)
862                         {
863                             ppFuncData[nFuncPos+nOld] = NULL;
864 
865                             uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
866                             if (xFunc.is())
867                             {
868                                 //  leave out internal functions
869                                 uno::Reference<reflection::XIdlClass> xClass =
870                                                 xFunc->getDeclaringClass();
871                                 sal_Bool bSkip = sal_True;
872                                 if ( xClass.is() )
873                                 {
874                                     //! XIdlClass needs getType() method!
875                                     rtl::OUString sName = xClass->getName();
876                                     bSkip = (
877                                         IsTypeName( sName,
878                                             getCppuType((uno::Reference<uno::XInterface>*)0) ) ||
879                                         IsTypeName( sName,
880                                             getCppuType((uno::Reference<reflection::XIdlClassProvider>*)0) ) ||
881                                         IsTypeName( sName,
882                                             getCppuType((uno::Reference<lang::XServiceName>*)0) ) ||
883                                         IsTypeName( sName,
884                                             getCppuType((uno::Reference<lang::XServiceInfo>*)0) ) ||
885                                         IsTypeName( sName,
886                                             getCppuType((uno::Reference<sheet::XAddIn>*)0) ) );
887                                 }
888                                 if (!bSkip)
889                                 {
890                                     uno::Reference<reflection::XIdlClass> xReturn =
891                                                 xFunc->getReturnType();
892                                     if ( !lcl_ValidReturnType( xReturn ) )
893                                         bSkip = sal_True;
894                                 }
895                                 if (!bSkip)
896                                 {
897                                     rtl::OUString aFuncU = xFunc->getName();
898 
899                                     // stored function name: (service name).(function)
900                                     String aFuncName = aServiceName;
901                                     aFuncName += '.';
902                                     aFuncName += String( aFuncU );
903 
904                                     sal_Bool bValid = sal_True;
905                                     long nVisibleCount = 0;
906                                     long nCallerPos = SC_CALLERPOS_NONE;
907 
908                                     uno::Sequence<reflection::ParamInfo> aParams =
909                                             xFunc->getParameterInfos();
910                                     long nParamCount = aParams.getLength();
911                                     const reflection::ParamInfo* pParArr = aParams.getConstArray();
912                                     long nParamPos;
913                                     for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
914                                     {
915                                         if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
916                                             bValid = sal_False;
917                                         uno::Reference<reflection::XIdlClass> xParClass =
918                                                     pParArr[nParamPos].aType;
919                                         ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
920                                         if ( eArgType == SC_ADDINARG_NONE )
921                                             bValid = sal_False;
922                                         else if ( eArgType == SC_ADDINARG_CALLER )
923                                             nCallerPos = nParamPos;
924                                         else
925                                             ++nVisibleCount;
926                                     }
927                                     if (bValid)
928                                     {
929                                         sal_uInt16 nCategory = lcl_GetCategory(
930                                             String(
931                                             xAddIn->getProgrammaticCategoryName(
932                                             aFuncU ) ) );
933 
934                                         rtl::OString sHelpId = aHelpIdGenerator.GetHelpId( aFuncU );
935 
936                                         rtl::OUString aLocalU;
937                                         try
938                                         {
939                                             aLocalU = xAddIn->
940                                                 getDisplayFunctionName( aFuncU );
941                                         }
942                                         catch(uno::Exception&)
943                                         {
944                                             aLocalU = rtl::OUString::createFromAscii( "###" );
945                                         }
946                                         String aLocalName = String( aLocalU );
947 
948                                         rtl::OUString aDescU;
949                                         try
950                                         {
951                                             aDescU = xAddIn->
952                                                 getFunctionDescription( aFuncU );
953                                         }
954                                         catch(uno::Exception&)
955                                         {
956                                             aDescU = rtl::OUString::createFromAscii( "###" );
957                                         }
958                                         String aDescription = String( aDescU );
959 
960                                         ScAddInArgDesc* pVisibleArgs = NULL;
961                                         if ( nVisibleCount > 0 )
962                                         {
963                                             ScAddInArgDesc aDesc;
964                                             pVisibleArgs = new ScAddInArgDesc[nVisibleCount];
965                                             long nDestPos = 0;
966                                             for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
967                                             {
968                                                 uno::Reference<reflection::XIdlClass> xParClass =
969                                                     pParArr[nParamPos].aType;
970                                                 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
971                                                 if ( eArgType != SC_ADDINARG_CALLER )
972                                                 {
973                                                     rtl::OUString aArgName;
974                                                     try
975                                                     {
976                                                         aArgName = xAddIn->
977                                                             getDisplayArgumentName( aFuncU, nParamPos );
978                                                     }
979                                                     catch(uno::Exception&)
980                                                     {
981                                                         aArgName = rtl::OUString::createFromAscii( "###" );
982                                                     }
983                                                     rtl::OUString aArgDesc;
984                                                     try
985                                                     {
986                                                         aArgDesc = xAddIn->
987                                                             getArgumentDescription( aFuncU, nParamPos );
988                                                     }
989                                                     catch(uno::Exception&)
990                                                     {
991                                                         aArgName = rtl::OUString::createFromAscii( "###" );
992                                                     }
993 
994                                                     sal_Bool bOptional =
995                                                         ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
996                                                           eArgType == SC_ADDINARG_VARARGS );
997 
998                                                     aDesc.eType = eArgType;
999                                                     aDesc.aName = String( aArgName );
1000                                                     aDesc.aDescription = String( aArgDesc );
1001                                                     aDesc.bOptional = bOptional;
1002                                                     //! initialize aInternalName only from config?
1003                                                     aDesc.aInternalName = pParArr[nParamPos].aName;
1004 
1005                                                     pVisibleArgs[nDestPos++] = aDesc;
1006                                                 }
1007                                             }
1008                                             DBG_ASSERT( nDestPos==nVisibleCount, "wrong count" );
1009                                         }
1010 
1011                                         ppFuncData[nFuncPos+nOld] = new ScUnoAddInFuncData(
1012                                             aFuncName, aLocalName, aDescription,
1013                                             nCategory, sHelpId,
1014                                             xFunc, aObject,
1015                                             nVisibleCount, pVisibleArgs, nCallerPos );
1016 
1017                                         const ScUnoAddInFuncData* pData =
1018                                             ppFuncData[nFuncPos+nOld];
1019                                         pExactHashMap->insert(
1020                                                 ScAddInHashMap::value_type(
1021                                                     pData->GetOriginalName(),
1022                                                     pData ) );
1023                                         pNameHashMap->insert(
1024                                                 ScAddInHashMap::value_type(
1025                                                     pData->GetUpperName(),
1026                                                     pData ) );
1027                                         pLocalHashMap->insert(
1028                                                 ScAddInHashMap::value_type(
1029                                                     pData->GetUpperLocal(),
1030                                                     pData ) );
1031 
1032                                         delete[] pVisibleArgs;
1033                                     }
1034                                 }
1035                             }
1036                         }
1037                     }
1038                 }
1039             }
1040         }
1041     }
1042 }
1043 
lcl_UpdateFunctionList(ScFunctionList & rFunctionList,const ScUnoAddInFuncData & rFuncData)1044 void lcl_UpdateFunctionList( ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData )
1045 {
1046     String aCompare = rFuncData.GetUpperLocal();    // as used in FillFunctionDescFromData
1047 
1048     sal_uLong nCount = rFunctionList.GetCount();
1049     for (sal_uLong nPos=0; nPos<nCount; nPos++)
1050     {
1051         const ScFuncDesc* pDesc = rFunctionList.GetFunction( nPos );
1052         if ( pDesc && pDesc->pFuncName && *pDesc->pFuncName == aCompare )
1053         {
1054             ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc) );
1055             break;
1056         }
1057     }
1058 }
1059 
lcl_FindArgDesc(const ScUnoAddInFuncData & rFuncData,const String & rArgIntName)1060 const ScAddInArgDesc* lcl_FindArgDesc( const ScUnoAddInFuncData& rFuncData, const String& rArgIntName )
1061 {
1062     long nArgCount = rFuncData.GetArgumentCount();
1063     const ScAddInArgDesc* pArguments = rFuncData.GetArguments();
1064     for (long nPos=0; nPos<nArgCount; nPos++)
1065     {
1066         if ( pArguments[nPos].aInternalName == rArgIntName )
1067             return &pArguments[nPos];
1068     }
1069     return NULL;
1070 }
1071 
UpdateFromAddIn(const uno::Reference<uno::XInterface> & xInterface,const String & rServiceName)1072 void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface>& xInterface,
1073                                             const String& rServiceName )
1074 {
1075     uno::Reference<lang::XLocalizable> xLoc( xInterface, uno::UNO_QUERY );
1076     if ( xLoc.is() )        // optional in new add-ins
1077     {
1078         LanguageType eOfficeLang = Application::GetSettings().GetUILanguage();
1079         lang::Locale aLocale( MsLangId::convertLanguageToLocale( eOfficeLang ));
1080         xLoc->setLocale( aLocale );
1081     }
1082 
1083     // if function list was already initialized, it must be updated
1084 
1085     ScFunctionList* pFunctionList = NULL;
1086     if ( ScGlobal::HasStarCalcFunctionList() )
1087         pFunctionList = ScGlobal::GetStarCalcFunctionList();
1088 
1089     // only get the function information from Introspection
1090 
1091     uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
1092     if ( xManager.is() )
1093     {
1094         uno::Reference<beans::XIntrospection> xIntro(
1095                                 xManager->createInstance(rtl::OUString::createFromAscii(
1096                                     "com.sun.star.beans.Introspection" )),
1097                                 uno::UNO_QUERY );
1098         if ( xIntro.is() )
1099         {
1100             uno::Any aObject;
1101             aObject <<= xInterface;
1102             uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
1103             if (xAcc.is())
1104             {
1105                 uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
1106                         xAcc->getMethods( beans::MethodConcept::ALL );
1107                 long nMethodCount = aMethods.getLength();
1108                 const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
1109                 for (long nFuncPos=0; nFuncPos<nMethodCount; nFuncPos++)
1110                 {
1111                     uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
1112                     if (xFunc.is())
1113                     {
1114                         rtl::OUString aFuncU = xFunc->getName();
1115 
1116                         // stored function name: (service name).(function)
1117                         String aFuncName = rServiceName;
1118                         aFuncName += '.';
1119                         aFuncName += String( aFuncU );
1120 
1121                         // internal names are skipped because no FuncData exists
1122                         ScUnoAddInFuncData* pOldData = const_cast<ScUnoAddInFuncData*>( GetFuncData( aFuncName ) );
1123                         if ( pOldData )
1124                         {
1125                             // Create new (complete) argument info.
1126                             // As in ReadFromAddIn, the reflection information is authoritative.
1127                             // Local names and descriptions from pOldData are looked up using the
1128                             // internal argument name.
1129 
1130                             sal_Bool bValid = sal_True;
1131                             long nVisibleCount = 0;
1132                             long nCallerPos = SC_CALLERPOS_NONE;
1133 
1134                             uno::Sequence<reflection::ParamInfo> aParams =
1135                                     xFunc->getParameterInfos();
1136                             long nParamCount = aParams.getLength();
1137                             const reflection::ParamInfo* pParArr = aParams.getConstArray();
1138                             long nParamPos;
1139                             for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
1140                             {
1141                                 if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
1142                                     bValid = sal_False;
1143                                 uno::Reference<reflection::XIdlClass> xParClass =
1144                                             pParArr[nParamPos].aType;
1145                                 ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
1146                                 if ( eArgType == SC_ADDINARG_NONE )
1147                                     bValid = sal_False;
1148                                 else if ( eArgType == SC_ADDINARG_CALLER )
1149                                     nCallerPos = nParamPos;
1150                                 else
1151                                     ++nVisibleCount;
1152                             }
1153                             if (bValid)
1154                             {
1155                                 ScAddInArgDesc* pVisibleArgs = NULL;
1156                                 if ( nVisibleCount > 0 )
1157                                 {
1158                                     ScAddInArgDesc aDesc;
1159                                     pVisibleArgs = new ScAddInArgDesc[nVisibleCount];
1160                                     long nDestPos = 0;
1161                                     for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
1162                                     {
1163                                         uno::Reference<reflection::XIdlClass> xParClass =
1164                                             pParArr[nParamPos].aType;
1165                                         ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
1166                                         if ( eArgType != SC_ADDINARG_CALLER )
1167                                         {
1168                                             const ScAddInArgDesc* pOldArgDesc =
1169                                                 lcl_FindArgDesc( *pOldData, pParArr[nParamPos].aName );
1170                                             if ( pOldArgDesc )
1171                                             {
1172                                                 aDesc.aName = pOldArgDesc->aName;
1173                                                 aDesc.aDescription = pOldArgDesc->aDescription;
1174                                             }
1175                                             else
1176                                                 aDesc.aName = aDesc.aDescription = String::CreateFromAscii( "###" );
1177 
1178                                             sal_Bool bOptional =
1179                                                 ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
1180                                                   eArgType == SC_ADDINARG_VARARGS );
1181 
1182                                             aDesc.eType = eArgType;
1183                                             aDesc.bOptional = bOptional;
1184                                             //! initialize aInternalName only from config?
1185                                             aDesc.aInternalName = pParArr[nParamPos].aName;
1186 
1187                                             pVisibleArgs[nDestPos++] = aDesc;
1188                                         }
1189                                     }
1190                                     DBG_ASSERT( nDestPos==nVisibleCount, "wrong count" );
1191                                 }
1192 
1193                                 pOldData->SetFunction( xFunc, aObject );
1194                                 pOldData->SetArguments( nVisibleCount, pVisibleArgs );
1195                                 pOldData->SetCallerPos( nCallerPos );
1196 
1197                                 if ( pFunctionList )
1198                                     lcl_UpdateFunctionList( *pFunctionList, *pOldData );
1199 
1200                                 delete[] pVisibleArgs;
1201                             }
1202                         }
1203                     }
1204                 }
1205             }
1206         }
1207     }
1208 }
1209 
FindFunction(const String & rUpperName,sal_Bool bLocalFirst)1210 String ScUnoAddInCollection::FindFunction( const String& rUpperName, sal_Bool bLocalFirst )
1211 {
1212     if (!bInitialized)
1213         Initialize();
1214 
1215     if (nFuncCount == 0)
1216         return EMPTY_STRING;
1217 
1218     if ( bLocalFirst )
1219     {
1220         //  first scan all local names (used for entering formulas)
1221 
1222         ScAddInHashMap::const_iterator iLook( pLocalHashMap->find( rUpperName ) );
1223         if ( iLook != pLocalHashMap->end() )
1224             return iLook->second->GetOriginalName();
1225 
1226 #if 0
1227         //  after that, scan international names (really?)
1228 
1229         iLook = pNameHashMap->find( rUpperName );
1230         if ( iLook != pNameHashMap->end() )
1231             return iLook->second->GetOriginalName();
1232 #endif
1233     }
1234     else
1235     {
1236         //  first scan international names (used when calling a function)
1237         //! before that, check for exact match???
1238 
1239         ScAddInHashMap::const_iterator iLook( pNameHashMap->find( rUpperName ) );
1240         if ( iLook != pNameHashMap->end() )
1241             return iLook->second->GetOriginalName();
1242 
1243         //  after that, scan all local names (to allow replacing old AddIns with Uno)
1244 
1245         iLook = pLocalHashMap->find( rUpperName );
1246         if ( iLook != pLocalHashMap->end() )
1247             return iLook->second->GetOriginalName();
1248     }
1249 
1250     return EMPTY_STRING;
1251 }
1252 
GetFuncData(const String & rName,bool bComplete)1253 const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( const String& rName, bool bComplete )
1254 {
1255     if (!bInitialized)
1256         Initialize();
1257 
1258     //  rName must be the exact internal name
1259 
1260     ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
1261     if ( iLook != pExactHashMap->end() )
1262     {
1263         const ScUnoAddInFuncData* pFuncData = iLook->second;
1264 
1265         if ( bComplete && !pFuncData->GetFunction().is() )           //! extra flag?
1266             LoadComponent( *pFuncData );
1267 
1268         return pFuncData;
1269     }
1270 
1271     return NULL;
1272 }
1273 
GetFuncData(long nIndex)1274 const ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( long nIndex )
1275 {
1276     if (!bInitialized)
1277         Initialize();
1278 
1279     if (nIndex < nFuncCount)
1280         return ppFuncData[nIndex];
1281     return NULL;
1282 }
1283 
LocalizeString(String & rName)1284 void ScUnoAddInCollection::LocalizeString( String& rName )
1285 {
1286     if (!bInitialized)
1287         Initialize();
1288 
1289     //  modify rName - input: exact name
1290 
1291     ScAddInHashMap::const_iterator iLook( pExactHashMap->find( rName ) );
1292     if ( iLook != pExactHashMap->end() )
1293         rName = iLook->second->GetUpperLocal();         //! upper?
1294 }
1295 
1296 
GetFuncCount()1297 long ScUnoAddInCollection::GetFuncCount()
1298 {
1299     if (!bInitialized)
1300         Initialize();
1301 
1302     return nFuncCount;
1303 }
1304 
FillFunctionDesc(long nFunc,ScFuncDesc & rDesc)1305 sal_Bool ScUnoAddInCollection::FillFunctionDesc( long nFunc, ScFuncDesc& rDesc )
1306 {
1307     if (!bInitialized)
1308         Initialize();
1309 
1310     if (nFunc >= nFuncCount || !ppFuncData[nFunc])
1311         return sal_False;
1312 
1313     const ScUnoAddInFuncData& rFuncData = *ppFuncData[nFunc];
1314 
1315     return FillFunctionDescFromData( rFuncData, rDesc );
1316 }
1317 
1318 // static
FillFunctionDescFromData(const ScUnoAddInFuncData & rFuncData,ScFuncDesc & rDesc)1319 sal_Bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc )
1320 {
1321     rDesc.Clear();
1322 
1323     sal_Bool bIncomplete = !rFuncData.GetFunction().is();       //! extra flag?
1324 
1325     long nArgCount = rFuncData.GetArgumentCount();
1326     if ( nArgCount > USHRT_MAX )
1327         return sal_False;
1328 
1329     if ( bIncomplete )
1330         nArgCount = 0;      // if incomplete, fill without argument info (no wrong order)
1331 
1332     // nFIndex is set from outside
1333 
1334     rDesc.pFuncName = new String( rFuncData.GetUpperLocal() );     //! upper?
1335     rDesc.nCategory = rFuncData.GetCategory();
1336     rDesc.sHelpId = rFuncData.GetHelpId();
1337 
1338     String aDesc = rFuncData.GetDescription();
1339     if (!aDesc.Len())
1340         aDesc = rFuncData.GetLocalName();      // use name if no description is available
1341     rDesc.pFuncDesc = new String( aDesc );
1342 
1343     // AddInArgumentType_CALLER is already left out in FuncData
1344 
1345     rDesc.nArgCount = (sal_uInt16)nArgCount;
1346     if ( nArgCount )
1347     {
1348         sal_Bool bMultiple = sal_False;
1349         const ScAddInArgDesc* pArgs = rFuncData.GetArguments();
1350 
1351         rDesc.ppDefArgNames = new String*[nArgCount];
1352         rDesc.ppDefArgDescs = new String*[nArgCount];
1353         rDesc.pDefArgFlags   = new ScFuncDesc::ParameterFlags[nArgCount];
1354         for ( long nArg=0; nArg<nArgCount; nArg++ )
1355         {
1356             rDesc.ppDefArgNames[nArg] = new String( pArgs[nArg].aName );
1357             rDesc.ppDefArgDescs[nArg] = new String( pArgs[nArg].aDescription );
1358             rDesc.pDefArgFlags[nArg].bOptional = pArgs[nArg].bOptional;
1359             rDesc.pDefArgFlags[nArg].bSuppress = false;
1360 
1361             // no empty names...
1362             if ( rDesc.ppDefArgNames[nArg]->Len() == 0 )
1363             {
1364                 String aDefName( RTL_CONSTASCII_USTRINGPARAM("arg") );
1365                 aDefName += String::CreateFromInt32( nArg+1 );
1366                 *rDesc.ppDefArgNames[nArg] = aDefName;
1367             }
1368 
1369             //  last argument repeated?
1370             if ( nArg+1 == nArgCount && ( pArgs[nArg].eType == SC_ADDINARG_VARARGS ) )
1371                 bMultiple = sal_True;
1372         }
1373 
1374         if ( bMultiple )
1375             rDesc.nArgCount += VAR_ARGS - 1;    // VAR_ARGS means just one repeated arg
1376     }
1377 
1378     rDesc.bIncomplete = bIncomplete;
1379 
1380     return sal_True;
1381 }
1382 
1383 
1384 //------------------------------------------------------------------------
1385 
ScUnoAddInCall(ScUnoAddInCollection & rColl,const String & rName,long nParamCount)1386 ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection& rColl, const String& rName,
1387                                 long nParamCount ) :
1388     bValidCount( sal_False ),
1389     nErrCode( errNoCode ),      // before function was called
1390     bHasString( sal_True ),
1391     fValue( 0.0 ),
1392     xMatrix( NULL )
1393 {
1394     pFuncData = rColl.GetFuncData( rName, true );           // need fully initialized data
1395     DBG_ASSERT( pFuncData, "Function Data missing" );
1396     if ( pFuncData )
1397     {
1398         long nDescCount = pFuncData->GetArgumentCount();
1399         const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1400 
1401         //  is aVarArg sequence needed?
1402         if ( nParamCount >= nDescCount && nDescCount > 0 &&
1403              pArgs[nDescCount-1].eType == SC_ADDINARG_VARARGS )
1404         {
1405             long nVarCount = nParamCount - ( nDescCount - 1 );  // size of last argument
1406             aVarArg.realloc( nVarCount );
1407             bValidCount = sal_True;
1408         }
1409         else if ( nParamCount <= nDescCount )
1410         {
1411             //  all args behind nParamCount must be optional
1412             bValidCount = sal_True;
1413             for (long i=nParamCount; i<nDescCount; i++)
1414                 if ( !pArgs[i].bOptional )
1415                     bValidCount = sal_False;
1416         }
1417         // else invalid (too many arguments)
1418 
1419         if ( bValidCount )
1420             aArgs.realloc( nDescCount );    // sequence must always match function signature
1421     }
1422 }
1423 
~ScUnoAddInCall()1424 ScUnoAddInCall::~ScUnoAddInCall()
1425 {
1426     // pFuncData is deleted with ScUnoAddInCollection
1427 }
1428 
ValidParamCount()1429 sal_Bool ScUnoAddInCall::ValidParamCount()
1430 {
1431     return bValidCount;
1432 }
1433 
GetArgType(long nPos)1434 ScAddInArgumentType ScUnoAddInCall::GetArgType( long nPos )
1435 {
1436     if ( pFuncData )
1437     {
1438         long nCount = pFuncData->GetArgumentCount();
1439         const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1440 
1441         // if last arg is sequence, use "any" type
1442         if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1443             return SC_ADDINARG_VALUE_OR_ARRAY;
1444 
1445         if ( nPos < nCount )
1446             return pArgs[nPos].eType;
1447     }
1448     return SC_ADDINARG_VALUE_OR_ARRAY;      //! error code !!!!
1449 }
1450 
NeedsCaller() const1451 sal_Bool ScUnoAddInCall::NeedsCaller() const
1452 {
1453     return pFuncData && pFuncData->GetCallerPos() != SC_CALLERPOS_NONE;
1454 }
1455 
SetCaller(const uno::Reference<uno::XInterface> & rInterface)1456 void ScUnoAddInCall::SetCaller( const uno::Reference<uno::XInterface>& rInterface )
1457 {
1458     xCaller = rInterface;
1459 }
1460 
SetCallerFromObjectShell(SfxObjectShell * pObjSh)1461 void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell* pObjSh )
1462 {
1463     if (pObjSh)
1464     {
1465         uno::Reference<uno::XInterface> xInt( pObjSh->GetBaseModel(), uno::UNO_QUERY );
1466         SetCaller( xInt );
1467     }
1468 }
1469 
SetParam(long nPos,const uno::Any & rValue)1470 void ScUnoAddInCall::SetParam( long nPos, const uno::Any& rValue )
1471 {
1472     if ( pFuncData )
1473     {
1474         long nCount = pFuncData->GetArgumentCount();
1475         const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1476         if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1477         {
1478             long nVarPos = nPos-(nCount-1);
1479             if ( nVarPos < aVarArg.getLength() )
1480                 aVarArg.getArray()[nVarPos] = rValue;
1481             else
1482             {
1483                 DBG_ERROR("wrong argument number");
1484             }
1485         }
1486         else if ( nPos < aArgs.getLength() )
1487             aArgs.getArray()[nPos] = rValue;
1488         else
1489         {
1490             DBG_ERROR("wrong argument number");
1491         }
1492     }
1493 }
1494 
ExecuteCall()1495 void ScUnoAddInCall::ExecuteCall()
1496 {
1497     if ( !pFuncData )
1498         return;
1499 
1500     long nCount = pFuncData->GetArgumentCount();
1501     const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
1502     if ( nCount > 0 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
1503     {
1504         //  insert aVarArg as last argument
1505         //! after inserting caller (to prevent copying twice)?
1506 
1507         DBG_ASSERT( aArgs.getLength() == nCount, "wrong argument count" );
1508         aArgs.getArray()[nCount-1] <<= aVarArg;
1509     }
1510 
1511     if ( pFuncData->GetCallerPos() != SC_CALLERPOS_NONE )
1512     {
1513         uno::Any aCallerAny;
1514         aCallerAny <<= xCaller;
1515 
1516         long nUserLen = aArgs.getLength();
1517         long nCallPos = pFuncData->GetCallerPos();
1518         if (nCallPos>nUserLen)                          // should not happen
1519         {
1520             DBG_ERROR("wrong CallPos");
1521             nCallPos = nUserLen;
1522         }
1523 
1524         long nDestLen = nUserLen + 1;
1525         uno::Sequence<uno::Any> aRealArgs( nDestLen );
1526         uno::Any* pDest = aRealArgs.getArray();
1527 
1528         const uno::Any* pSource = aArgs.getConstArray();
1529         long nSrcPos = 0;
1530 
1531         for ( long nDestPos = 0; nDestPos < nDestLen; nDestPos++ )
1532         {
1533             if ( nDestPos == nCallPos )
1534                 pDest[nDestPos] = aCallerAny;
1535             else
1536                 pDest[nDestPos] = pSource[nSrcPos++];
1537         }
1538 
1539         ExecuteCallWithArgs( aRealArgs );
1540     }
1541     else
1542         ExecuteCallWithArgs( aArgs );
1543 }
1544 
ExecuteCallWithArgs(uno::Sequence<uno::Any> & rCallArgs)1545 void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs)
1546 {
1547     //  rCallArgs may not match argument descriptions (because of caller)
1548 
1549     uno::Reference<reflection::XIdlMethod> xFunction;
1550     uno::Any aObject;
1551     if ( pFuncData )
1552     {
1553         xFunction = pFuncData->GetFunction();
1554         aObject = pFuncData->GetObject();
1555     }
1556 
1557     if ( xFunction.is() )
1558     {
1559         uno::Any aAny;
1560         nErrCode = 0;
1561 
1562         try
1563         {
1564             aAny = xFunction->invoke( aObject, rCallArgs );
1565         }
1566         catch(lang::IllegalArgumentException&)
1567         {
1568             nErrCode = errIllegalArgument;
1569         }
1570 #if 0
1571         catch(FloatingPointException&)
1572         {
1573             nErrCode = errIllegalFPOperation;
1574         }
1575 #endif
1576 		catch(reflection::InvocationTargetException& rWrapped)
1577 		{
1578 			if ( rWrapped.TargetException.getValueType().equals(
1579 					getCppuType( (lang::IllegalArgumentException*)0 ) ) )
1580 				nErrCode = errIllegalArgument;
1581             else if ( rWrapped.TargetException.getValueType().equals(
1582                     getCppuType( (sheet::NoConvergenceException*)0 ) ) )
1583                 nErrCode = errNoConvergence;
1584 			else
1585 	            nErrCode = errNoValue;
1586 		}
1587 
1588         catch(uno::Exception&)
1589         {
1590             nErrCode = errNoValue;
1591         }
1592 
1593         if (!nErrCode)
1594             SetResult( aAny );      // convert result to Calc types
1595     }
1596 }
1597 
SetResult(const uno::Any & rNewRes)1598 void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
1599 {
1600     nErrCode = 0;
1601     xVarRes = NULL;
1602 
1603     // Reflection* pRefl = rNewRes.getReflection();
1604 
1605     uno::TypeClass eClass = rNewRes.getValueTypeClass();
1606     uno::Type aType = rNewRes.getValueType();
1607     switch (eClass)
1608     {
1609         case uno::TypeClass_VOID:
1610             nErrCode = NOTAVAILABLE;         // #NA
1611             break;
1612 
1613         case uno::TypeClass_ENUM:
1614         case uno::TypeClass_BOOLEAN:
1615         case uno::TypeClass_CHAR:
1616         case uno::TypeClass_BYTE:
1617         case uno::TypeClass_SHORT:
1618         case uno::TypeClass_UNSIGNED_SHORT:
1619         case uno::TypeClass_LONG:
1620         case uno::TypeClass_UNSIGNED_LONG:
1621         case uno::TypeClass_FLOAT:
1622         case uno::TypeClass_DOUBLE:
1623             {
1624                 uno::TypeClass eMyClass;
1625                 ScApiTypeConversion::ConvertAnyToDouble( fValue, eMyClass, rNewRes);
1626                 bHasString = sal_False;
1627             }
1628             break;
1629 
1630         case uno::TypeClass_STRING:
1631             {
1632                 rtl::OUString aUStr;
1633                 rNewRes >>= aUStr;
1634                 aString = String( aUStr );
1635                 bHasString = sal_True;
1636             }
1637             break;
1638 
1639         case uno::TypeClass_INTERFACE:
1640             {
1641                 //! directly extract XVolatileResult from any?
1642                 uno::Reference<uno::XInterface> xInterface;
1643                 rNewRes >>= xInterface;
1644                 if ( xInterface.is() )
1645                     xVarRes = uno::Reference<sheet::XVolatileResult>( xInterface, uno::UNO_QUERY );
1646 
1647                 if (!xVarRes.is())
1648                     nErrCode = errNoValue;          // unknown interface
1649             }
1650             break;
1651 
1652         default:
1653             if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int32> > *)0 ) ) )
1654             {
1655                 const uno::Sequence< uno::Sequence<sal_Int32> >* pRowSeq = NULL;
1656 
1657                 //! use pointer from any!
1658                 uno::Sequence< uno::Sequence<sal_Int32> > aSequence;
1659                 if ( rNewRes >>= aSequence )
1660                     pRowSeq = &aSequence;
1661 
1662                 if ( pRowSeq )
1663                 {
1664                     long nRowCount = pRowSeq->getLength();
1665                     const uno::Sequence<sal_Int32>* pRowArr = pRowSeq->getConstArray();
1666                     long nMaxColCount = 0;
1667                     long nCol, nRow;
1668                     for (nRow=0; nRow<nRowCount; nRow++)
1669                     {
1670                         long nTmp = pRowArr[nRow].getLength();
1671                         if ( nTmp > nMaxColCount )
1672                             nMaxColCount = nTmp;
1673                     }
1674                     if ( nMaxColCount && nRowCount )
1675                     {
1676                         xMatrix = new ScMatrix(
1677                                 static_cast<SCSIZE>(nMaxColCount),
1678                                 static_cast<SCSIZE>(nRowCount) );
1679                         ScMatrix* pMatrix = xMatrix;
1680                         for (nRow=0; nRow<nRowCount; nRow++)
1681                         {
1682                             long nColCount = pRowArr[nRow].getLength();
1683                             const sal_Int32* pColArr = pRowArr[nRow].getConstArray();
1684                             for (nCol=0; nCol<nColCount; nCol++)
1685                                 pMatrix->PutDouble( pColArr[nCol],
1686                                         static_cast<SCSIZE>(nCol),
1687                                         static_cast<SCSIZE>(nRow) );
1688                             for (nCol=nColCount; nCol<nMaxColCount; nCol++)
1689                                 pMatrix->PutDouble( 0.0,
1690                                         static_cast<SCSIZE>(nCol),
1691                                         static_cast<SCSIZE>(nRow) );
1692                         }
1693                     }
1694                 }
1695             }
1696             else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) )
1697             {
1698                 const uno::Sequence< uno::Sequence<double> >* pRowSeq = NULL;
1699 
1700                 //! use pointer from any!
1701                 uno::Sequence< uno::Sequence<double> > aSequence;
1702                 if ( rNewRes >>= aSequence )
1703                     pRowSeq = &aSequence;
1704 
1705                 if ( pRowSeq )
1706                 {
1707                     long nRowCount = pRowSeq->getLength();
1708                     const uno::Sequence<double>* pRowArr = pRowSeq->getConstArray();
1709                     long nMaxColCount = 0;
1710                     long nCol, nRow;
1711                     for (nRow=0; nRow<nRowCount; nRow++)
1712                     {
1713                         long nTmp = pRowArr[nRow].getLength();
1714                         if ( nTmp > nMaxColCount )
1715                             nMaxColCount = nTmp;
1716                     }
1717                     if ( nMaxColCount && nRowCount )
1718                     {
1719                         xMatrix = new ScMatrix(
1720                                 static_cast<SCSIZE>(nMaxColCount),
1721                                 static_cast<SCSIZE>(nRowCount) );
1722                         ScMatrix* pMatrix = xMatrix;
1723                         for (nRow=0; nRow<nRowCount; nRow++)
1724                         {
1725                             long nColCount = pRowArr[nRow].getLength();
1726                             const double* pColArr = pRowArr[nRow].getConstArray();
1727                             for (nCol=0; nCol<nColCount; nCol++)
1728                                 pMatrix->PutDouble( pColArr[nCol],
1729                                         static_cast<SCSIZE>(nCol),
1730                                         static_cast<SCSIZE>(nRow) );
1731                             for (nCol=nColCount; nCol<nMaxColCount; nCol++)
1732                                 pMatrix->PutDouble( 0.0,
1733                                         static_cast<SCSIZE>(nCol),
1734                                         static_cast<SCSIZE>(nRow) );
1735                         }
1736                     }
1737                 }
1738             }
1739             else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) )
1740             {
1741                 const uno::Sequence< uno::Sequence<rtl::OUString> >* pRowSeq = NULL;
1742 
1743                 //! use pointer from any!
1744                 uno::Sequence< uno::Sequence<rtl::OUString> > aSequence;
1745                 if ( rNewRes >>= aSequence )
1746                     pRowSeq = &aSequence;
1747 
1748                 if ( pRowSeq )
1749                 {
1750                     long nRowCount = pRowSeq->getLength();
1751                     const uno::Sequence<rtl::OUString>* pRowArr = pRowSeq->getConstArray();
1752                     long nMaxColCount = 0;
1753                     long nCol, nRow;
1754                     for (nRow=0; nRow<nRowCount; nRow++)
1755                     {
1756                         long nTmp = pRowArr[nRow].getLength();
1757                         if ( nTmp > nMaxColCount )
1758                             nMaxColCount = nTmp;
1759                     }
1760                     if ( nMaxColCount && nRowCount )
1761                     {
1762                         xMatrix = new ScMatrix(
1763                                 static_cast<SCSIZE>(nMaxColCount),
1764                                 static_cast<SCSIZE>(nRowCount) );
1765                         ScMatrix* pMatrix = xMatrix;
1766                         for (nRow=0; nRow<nRowCount; nRow++)
1767                         {
1768                             long nColCount = pRowArr[nRow].getLength();
1769                             const rtl::OUString* pColArr = pRowArr[nRow].getConstArray();
1770                             for (nCol=0; nCol<nColCount; nCol++)
1771                                 pMatrix->PutString( String( pColArr[nCol] ),
1772                                     static_cast<SCSIZE>(nCol),
1773                                     static_cast<SCSIZE>(nRow) );
1774                             for (nCol=nColCount; nCol<nMaxColCount; nCol++)
1775                                 pMatrix->PutString( EMPTY_STRING,
1776                                         static_cast<SCSIZE>(nCol),
1777                                         static_cast<SCSIZE>(nRow) );
1778                         }
1779                     }
1780                 }
1781             }
1782             else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) )
1783             {
1784                 xMatrix = ScSequenceToMatrix::CreateMixedMatrix( rNewRes );
1785             }
1786 
1787             if (!xMatrix)                       // no array found
1788                 nErrCode = errNoValue;          //! code for error in return type???
1789     }
1790 }
1791 
1792 
1793 
1794 //------------------------------------------------------------------------
1795 
1796 
1797 
1798