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