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