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