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