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 : :
30 : : #include "funcdesc.hxx"
31 : :
32 : : #include "addincol.hxx"
33 : : #include "appoptio.hxx"
34 : : #include "callform.hxx"
35 : : #include "compiler.hxx"
36 : : #include "global.hxx"
37 : : #include "sc.hrc"
38 : : #include "scmod.hxx"
39 : : #include "scresid.hxx"
40 : :
41 : : #include <rtl/ustring.hxx>
42 : : #include <rtl/ustrbuf.hxx>
43 : : #include <tools/rcid.h>
44 : : #include <tools/resid.hxx>
45 : : #include <unotools/collatorwrapper.hxx>
46 : :
47 : : #include <numeric>
48 : : #include <boost/scoped_ptr.hpp>
49 : :
50 : 1440 : class ScFuncRes : public Resource
51 : : {
52 : : public:
53 : : ScFuncRes( ResId&, ScFuncDesc*, bool & rbSuppressed );
54 : :
55 : : private:
56 : : sal_uInt16 GetNum();
57 : : };
58 : :
59 : :
60 : : class ScResourcePublisher : public Resource
61 : : {
62 : : private:
63 : 43 : void FreeResource() { Resource::FreeResource(); }
64 : : public:
65 : 43 : ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {}
66 [ + - ]: 43 : ~ScResourcePublisher() { FreeResource(); }
67 : 4030 : bool IsAvailableRes( const ResId& rId ) const
68 : 4030 : { return Resource::IsAvailableRes( rId ); }
69 : :
70 : : };
71 : :
72 : : //========================================================================
73 : : // class ScFuncDesc:
74 : : //========================================================================
75 : :
76 : 1738 : ScFuncDesc::ScFuncDesc() :
77 : : pFuncName (NULL),
78 : : pFuncDesc (NULL),
79 : : ppDefArgNames (NULL),
80 : : ppDefArgDescs (NULL),
81 : : pDefArgFlags (NULL),
82 : : nFIndex (0),
83 : : nCategory (0),
84 : : nArgCount (0),
85 : : bIncomplete (false),
86 : 1738 : bHasSuppressedArgs(false)
87 : 1738 : {}
88 : :
89 : 1738 : ScFuncDesc::~ScFuncDesc()
90 : : {
91 : 1738 : Clear();
92 [ - + ]: 3476 : }
93 : :
94 : 1956 : void ScFuncDesc::Clear()
95 : : {
96 : 1956 : sal_uInt16 nArgs = nArgCount;
97 [ + + ]: 1956 : if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1;
98 [ + + ]: 1956 : if (nArgs)
99 : : {
100 [ + + ]: 5138 : for (sal_uInt16 i=0; i<nArgs; i++ )
101 : : {
102 [ + - ]: 3520 : delete ppDefArgNames[i];
103 [ + - ]: 3520 : delete ppDefArgDescs[i];
104 : : }
105 [ + - ]: 1618 : delete [] ppDefArgNames;
106 [ + - ]: 1618 : delete [] ppDefArgDescs;
107 [ + - ]: 1618 : delete [] pDefArgFlags;
108 : : }
109 : 1956 : nArgCount = 0;
110 : 1956 : ppDefArgNames = NULL;
111 : 1956 : ppDefArgDescs = NULL;
112 : 1956 : pDefArgFlags = NULL;
113 : :
114 [ + + ]: 1956 : delete pFuncName;
115 : 1956 : pFuncName = NULL;
116 : :
117 [ + + ]: 1956 : delete pFuncDesc;
118 : 1956 : pFuncDesc = NULL;
119 : :
120 : 1956 : nFIndex = 0;
121 : 1956 : nCategory = 0;
122 : 1956 : sHelpId = rtl::OString();
123 : 1956 : bIncomplete = false;
124 : 1956 : bHasSuppressedArgs = false;
125 : 1956 : }
126 : :
127 : 0 : ::rtl::OUString ScFuncDesc::GetParamList() const
128 : : {
129 [ # # ][ # # ]: 0 : ::rtl::OUString sep(ScCompiler::GetNativeSymbol(ocSep));
130 : :
131 : 0 : ::rtl::OUStringBuffer aSig;
132 : :
133 [ # # ]: 0 : if ( nArgCount > 0 )
134 : : {
135 [ # # ]: 0 : if ( nArgCount < VAR_ARGS )
136 : : {
137 : 0 : sal_uInt16 nLastSuppressed = nArgCount;
138 : 0 : sal_uInt16 nLastAdded = nArgCount;
139 [ # # ]: 0 : for ( sal_uInt16 i=0; i<nArgCount; i++ )
140 : : {
141 [ # # ]: 0 : if (pDefArgFlags[i].bSuppress)
142 : 0 : nLastSuppressed = i;
143 : : else
144 : : {
145 : 0 : nLastAdded = i;
146 [ # # ]: 0 : aSig.append(*(ppDefArgNames[i]));
147 [ # # ]: 0 : if ( i != nArgCount-1 )
148 : : {
149 [ # # ]: 0 : aSig.append(sep);
150 [ # # ]: 0 : aSig.appendAscii( " " );
151 : : }
152 : : }
153 : : }
154 : : // If only suppressed parameters follow the last added parameter,
155 : : // remove one "; "
156 [ # # ]: 0 : if (nLastSuppressed < nArgCount && nLastAdded < nLastSuppressed &&
[ # # # # ]
[ # # ]
157 : 0 : aSig.getLength() >= 2)
158 [ # # ]: 0 : aSig.setLength(aSig.getLength() - 2);
159 : : }
160 : : else
161 : : {
162 : 0 : sal_uInt16 nFix = nArgCount - VAR_ARGS;
163 [ # # ]: 0 : for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
164 : : {
165 [ # # ]: 0 : if (!pDefArgFlags[nArg].bSuppress)
166 : : {
167 [ # # ]: 0 : aSig.append(*(ppDefArgNames[nArg]));
168 [ # # ]: 0 : aSig.append(sep);
169 [ # # ]: 0 : aSig.appendAscii( " " );
170 : : }
171 : : }
172 : : /* NOTE: Currently there are no suppressed var args parameters. If
173 : : * there were, we'd have to cope with it here and above for the fix
174 : : * parameters. For now parameters are always added, so no special
175 : : * treatment of a trailing "; " necessary. */
176 [ # # ]: 0 : aSig.append(*(ppDefArgNames[nFix]));
177 [ # # ]: 0 : aSig.append(sal_Unicode('1'));
178 [ # # ]: 0 : aSig.append(sep);
179 [ # # ]: 0 : aSig.append(sal_Unicode(' '));
180 [ # # ]: 0 : aSig.append(*(ppDefArgNames[nFix]));
181 [ # # ]: 0 : aSig.append(sal_Unicode('2'));
182 [ # # ]: 0 : aSig.append(sep);
183 [ # # ]: 0 : aSig.appendAscii(" ... ");
184 : : }
185 : : }
186 : :
187 [ # # ]: 0 : return aSig.makeStringAndClear();
188 : : }
189 : :
190 : 0 : ::rtl::OUString ScFuncDesc::getSignature() const
191 : : {
192 : 0 : ::rtl::OUStringBuffer aSig;
193 : :
194 [ # # ]: 0 : if(pFuncName)
195 : : {
196 [ # # ]: 0 : aSig.append(*pFuncName);
197 : :
198 [ # # ]: 0 : ::rtl::OUString aParamList = GetParamList();
199 [ # # ]: 0 : if( !aParamList.isEmpty() )
200 : : {
201 [ # # ]: 0 : aSig.appendAscii( "( " );
202 [ # # ]: 0 : aSig.append(aParamList);
203 : : // U+00A0 (NBSP) prevents automatic line break
204 [ # # ]: 0 : aSig.append( static_cast< sal_Unicode >(0xA0) );
205 [ # # ]: 0 : aSig.appendAscii( ")" );
206 : : }
207 : : else
208 [ # # ]: 0 : aSig.appendAscii( "()" );
209 : : }
210 [ # # ]: 0 : return aSig.makeStringAndClear();
211 : : }
212 : :
213 : 0 : ::rtl::OUString ScFuncDesc::getFormula( const ::std::vector< ::rtl::OUString >& _aArguments ) const
214 : : {
215 [ # # ][ # # ]: 0 : ::rtl::OUString sep = ScCompiler::GetNativeSymbol(ocSep);
216 : :
217 : 0 : ::rtl::OUStringBuffer aFormula;
218 : :
219 [ # # ]: 0 : if(pFuncName)
220 : : {
221 [ # # ]: 0 : aFormula.append( *pFuncName );
222 : :
223 [ # # ]: 0 : aFormula.appendAscii( "(" );
224 : 0 : ::std::vector< ::rtl::OUString >::const_iterator aIter = _aArguments.begin();
225 : 0 : ::std::vector< ::rtl::OUString >::const_iterator aEnd = _aArguments.end();
226 : :
227 [ # # ][ # # ]: 0 : if ( nArgCount > 0 && aIter != aEnd )
[ # # ][ # # ]
228 : : {
229 : 0 : bool bLastArg = aIter->isEmpty();
230 : :
231 [ # # ][ # # ]: 0 : while( aIter != aEnd && !bLastArg )
[ # # ][ # # ]
232 : : {
233 [ # # ]: 0 : aFormula.append( *(aIter) );
234 [ # # ][ # # ]: 0 : if ( aIter != (aEnd-1) )
[ # # ]
235 : : {
236 [ # # ]: 0 : bLastArg = (aIter+1)->isEmpty();
237 [ # # ]: 0 : if ( !bLastArg )
238 [ # # ]: 0 : aFormula.append( sep );
239 : : }
240 : :
241 : 0 : ++aIter;
242 : : }
243 : : }
244 : :
245 [ # # ]: 0 : aFormula.appendAscii( ")" );
246 : : }
247 [ # # ]: 0 : return aFormula.makeStringAndClear();
248 : : }
249 : :
250 : 394 : sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
251 : : {
252 [ - + ][ # # ]: 394 : if (!bHasSuppressedArgs || !pDefArgFlags)
253 : 394 : return nArgCount;
254 : :
255 : 0 : sal_uInt16 nArgs = nArgCount;
256 [ # # ]: 0 : if (nArgs >= VAR_ARGS)
257 : 0 : nArgs -= VAR_ARGS - 1;
258 : 0 : sal_uInt16 nCount = nArgs;
259 [ # # ]: 0 : for (sal_uInt16 i=0; i < nArgs; ++i)
260 : : {
261 [ # # ]: 0 : if (pDefArgFlags[i].bSuppress)
262 : 0 : --nCount;
263 : : }
264 [ # # ]: 0 : if (nArgCount >= VAR_ARGS)
265 : 0 : nCount += VAR_ARGS - 1;
266 : 394 : return nCount;
267 : : }
268 : :
269 : 861 : ::rtl::OUString ScFuncDesc::getFunctionName() const
270 : : {
271 : 861 : ::rtl::OUString sRet;
272 [ + - ]: 861 : if ( pFuncName )
273 : 861 : sRet = *pFuncName;
274 : 861 : return sRet;
275 : : }
276 : :
277 : 0 : const formula::IFunctionCategory* ScFuncDesc::getCategory() const
278 : : {
279 : 0 : return ScGlobal::GetStarCalcFunctionMgr()->getCategory(nCategory);
280 : : }
281 : :
282 : 0 : ::rtl::OUString ScFuncDesc::getDescription() const
283 : : {
284 : 0 : ::rtl::OUString sRet;
285 [ # # ]: 0 : if ( pFuncDesc )
286 : 0 : sRet = *pFuncDesc;
287 : 0 : return sRet;
288 : : }
289 : :
290 : 0 : xub_StrLen ScFuncDesc::getSuppressedArgumentCount() const
291 : : {
292 : 0 : return GetSuppressedArgCount();
293 : : }
294 : :
295 : 0 : void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const
296 : : {
297 [ # # ][ # # ]: 0 : if (!bHasSuppressedArgs || !pDefArgFlags)
298 : : {
299 [ # # ]: 0 : _rArguments.resize( nArgCount);
300 : 0 : ::std::vector<sal_uInt16>::iterator iter = _rArguments.begin();
301 : 0 : sal_uInt16 value = 0;
302 [ # # ][ # # ]: 0 : while (iter != _rArguments.end())
303 [ # # ][ # # ]: 0 : *iter++ = value++;
304 : : }
305 : :
306 : 0 : _rArguments.reserve( nArgCount);
307 : 0 : sal_uInt16 nArgs = nArgCount;
308 [ # # ]: 0 : if (nArgs >= VAR_ARGS)
309 : 0 : nArgs -= VAR_ARGS - 1;
310 [ # # ]: 0 : for (sal_uInt16 i=0; i < nArgs; ++i)
311 : : {
312 [ # # ]: 0 : if (!pDefArgFlags[i].bSuppress)
313 [ # # ]: 0 : _rArguments.push_back(i);
314 : : }
315 : 0 : }
316 : :
317 : 402 : void ScFuncDesc::initArgumentInfo() const
318 : : {
319 : : // get the full argument description
320 : : // (add-in has to be instantiated to get the type information)
321 : :
322 [ - + ][ # # ]: 402 : if ( bIncomplete && pFuncName )
323 : : {
324 [ # # ]: 0 : ScUnoAddInCollection& rAddIns = *ScGlobal::GetAddInCollection();
325 [ # # ]: 0 : ::rtl::OUString aIntName(rAddIns.FindFunction( *pFuncName, true )); // pFuncName is upper-case
326 : :
327 [ # # ]: 0 : if ( !aIntName.isEmpty() )
328 : : {
329 : : // GetFuncData with bComplete=true loads the component and updates
330 : : // the global function list if needed.
331 : :
332 [ # # ]: 0 : rAddIns.GetFuncData( aIntName, true );
333 : : }
334 : :
335 [ # # ]: 0 : if ( bIncomplete )
336 : : {
337 : : OSL_FAIL( "couldn't initialize add-in function" );
338 : 0 : const_cast<ScFuncDesc*>(this)->bIncomplete = false; // even if there was an error, don't try again
339 : 0 : }
340 : : }
341 : 402 : }
342 : :
343 : 0 : ::rtl::OString ScFuncDesc::getHelpId() const
344 : : {
345 : 0 : return sHelpId;
346 : : }
347 : :
348 : 0 : sal_uInt32 ScFuncDesc::getParameterCount() const
349 : : {
350 : 0 : return nArgCount;
351 : : }
352 : :
353 : 0 : ::rtl::OUString ScFuncDesc::getParameterName(sal_uInt32 _nPos) const
354 : : {
355 : 0 : return *(ppDefArgNames[_nPos]);
356 : : }
357 : :
358 : 0 : ::rtl::OUString ScFuncDesc::getParameterDescription(sal_uInt32 _nPos) const
359 : : {
360 : 0 : return *(ppDefArgDescs[_nPos]);
361 : : }
362 : :
363 : 0 : bool ScFuncDesc::isParameterOptional(sal_uInt32 _nPos) const
364 : : {
365 : 0 : return pDefArgFlags[_nPos].bOptional;
366 : : }
367 : :
368 : 8463 : bool ScFuncDesc::compareByName(const ScFuncDesc* a, const ScFuncDesc* b)
369 : : {
370 : 8463 : return (ScGlobal::GetCaseCollator()->compareString(*a->pFuncName, *b->pFuncName ) == COMPARE_LESS);
371 : : }
372 : :
373 : : //===================================================================
374 : : // class ScFunctionList:
375 : : //===================================================================
376 : :
377 : 5 : ScFunctionList::ScFunctionList() :
378 : 5 : nMaxFuncNameLen ( 0 )
379 : : {
380 : 5 : ScFuncDesc* pDesc = NULL;
381 : 5 : xub_StrLen nStrLen = 0;
382 [ + - ]: 5 : ::std::list<ScFuncDesc*> tmpFuncList;
383 : : sal_uInt16 nDescBlock[] =
384 : : {
385 : : RID_SC_FUNCTION_DESCRIPTIONS1,
386 : : RID_SC_FUNCTION_DESCRIPTIONS2
387 : 5 : };
388 : :
389 [ + + ]: 15 : for (sal_uInt16 k = 0; k < SAL_N_ELEMENTS(nDescBlock); ++k)
390 : : {
391 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
392 [ + - ][ + - ]: 10 : ::std::auto_ptr<ScResourcePublisher> pBlock( new ScResourcePublisher( ScResId( nDescBlock[k] ) ) );
[ + - ]
393 : : SAL_WNODEPRECATED_DECLARATIONS_POP
394 : : // Browse for all possible OpCodes. This is not the fastest method, but
395 : : // otherwise the sub resources within the resource blocks and the
396 : : // resource blocks themselfs would had to be ordered according to
397 : : // OpCodes, which is utopian..
398 [ + + ]: 4040 : for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
399 : : {
400 [ + - ]: 4030 : ScResId aRes(i);
401 : 4030 : aRes.SetRT(RSC_RESOURCE);
402 : : // Sub resource of OpCode available?
403 [ + + ][ + - ]: 4030 : if (pBlock->IsAvailableRes(aRes))
404 : : {
405 [ + - ]: 1440 : pDesc = new ScFuncDesc;
406 : 1440 : bool bSuppressed = false;
407 [ + - ]: 1440 : ScFuncRes aSubRes( aRes, pDesc, bSuppressed);
408 : : // Instead of dealing with this exceptional case at 1001 places
409 : : // we simply don't add an entirely suppressed function to the
410 : : // list and delete it.
411 [ + + ]: 1440 : if (bSuppressed)
412 [ + - ][ + - ]: 5 : delete pDesc;
413 : : else
414 : : {
415 : 1435 : pDesc->nFIndex = i;
416 [ + - ]: 1435 : tmpFuncList.push_back(pDesc);
417 : :
418 : 1435 : nStrLen = (*(pDesc->pFuncName)).getLength();
419 [ + + ]: 1435 : if (nStrLen > nMaxFuncNameLen)
420 : 40 : nMaxFuncNameLen = nStrLen;
421 : 1440 : }
422 : : }
423 : : }
424 [ + - ]: 10 : }
425 : :
426 : 5 : sal_uInt16 nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions
427 : :
428 : : // Interpretation of AddIn list
429 [ + - ]: 5 : ::rtl::OUString aDefArgNameValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value"));
430 [ + - ]: 5 : ::rtl::OUString aDefArgNameString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string"));
431 [ + - ]: 5 : ::rtl::OUString aDefArgNameValues = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("values"));
432 [ + - ]: 5 : ::rtl::OUString aDefArgNameStrings = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("strings"));
433 [ + - ]: 5 : ::rtl::OUString aDefArgNameCells = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cells"));
434 [ + - ]: 5 : ::rtl::OUString aDefArgNameNone = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("none"));
435 [ + - ]: 5 : ::rtl::OUString aDefArgDescValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a value"));
436 [ + - ]: 5 : ::rtl::OUString aDefArgDescString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a string"));
437 [ + - ]: 5 : ::rtl::OUString aDefArgDescValues = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("array of values"));
438 [ + - ]: 5 : ::rtl::OUString aDefArgDescStrings = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("array of strings"));
439 [ + - ]: 5 : ::rtl::OUString aDefArgDescCells = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("range of cells"));
440 [ + - ]: 5 : ::rtl::OUString aDefArgDescNone = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("none"));
441 : :
442 : 5 : ::rtl::OUString aArgName, aArgDesc;
443 [ + - ]: 5 : const FuncCollection& rFuncColl = *ScGlobal::GetFuncCollection();
444 [ + - ][ + - ]: 5 : FuncCollection::const_iterator it = rFuncColl.begin(), itEnd = rFuncColl.end();
445 [ # # ][ + - ]: 5 : for (; it != itEnd; ++it)
[ - + ]
446 : : {
447 [ # # ]: 0 : const FuncData* pAddInFuncData = it->second;
448 [ # # ]: 0 : pDesc = new ScFuncDesc;
449 : 0 : sal_uInt16 nArgs = pAddInFuncData->GetParamCount() - 1;
450 [ # # ]: 0 : pAddInFuncData->getParamDesc( aArgName, aArgDesc, 0 );
451 : 0 : pDesc->nFIndex = nNextId++; // ??? OpCode vergeben
452 : 0 : pDesc->nCategory = ID_FUNCTION_GRP_ADDINS;
453 [ # # ]: 0 : pDesc->pFuncName = new ::rtl::OUString(pAddInFuncData->GetInternalName());
454 : 0 : pDesc->pFuncName->toAsciiUpperCase();
455 : :
456 [ # # ]: 0 : ::rtl::OUStringBuffer aBuf(aArgDesc);
457 [ # # ]: 0 : aBuf.append(sal_Unicode('\n'));
458 [ # # ]: 0 : aBuf.appendAscii("( AddIn: ");
459 [ # # ][ # # ]: 0 : aBuf.append(pAddInFuncData->GetModuleName());
460 [ # # ]: 0 : aBuf.appendAscii(" )");
461 [ # # ][ # # ]: 0 : pDesc->pFuncDesc = new ::rtl::OUString(aBuf.makeStringAndClear());
462 : :
463 : 0 : pDesc->nArgCount = nArgs;
464 [ # # ]: 0 : if (nArgs)
465 : : {
466 [ # # ][ # # ]: 0 : pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
467 [ # # ]: 0 : pDesc->ppDefArgNames = new ::rtl::OUString*[nArgs];
468 [ # # ]: 0 : pDesc->ppDefArgDescs = new ::rtl::OUString*[nArgs];
469 [ # # ]: 0 : for (sal_uInt16 j = 0; j < nArgs; ++j)
470 : : {
471 : 0 : pDesc->pDefArgFlags[j].bOptional = false;
472 : 0 : pDesc->pDefArgFlags[j].bSuppress = false;
473 [ # # ]: 0 : pAddInFuncData->getParamDesc( aArgName, aArgDesc, j+1 );
474 [ # # ]: 0 : if ( !aArgName.isEmpty() )
475 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aArgName );
476 : : else
477 : : {
478 [ # # # # : 0 : switch (pAddInFuncData->GetParamType(j+1))
# # ]
479 : : {
480 : : case PTR_DOUBLE:
481 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameValue );
482 : 0 : break;
483 : : case PTR_STRING:
484 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameString );
485 : 0 : break;
486 : : case PTR_DOUBLE_ARR:
487 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameValues );
488 : 0 : break;
489 : : case PTR_STRING_ARR:
490 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameStrings );
491 : 0 : break;
492 : : case PTR_CELL_ARR:
493 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameCells );
494 : 0 : break;
495 : : default:
496 [ # # ]: 0 : pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameNone );
497 : 0 : break;
498 : : }
499 : : }
500 [ # # ]: 0 : if ( !aArgDesc.isEmpty() )
501 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aArgDesc );
502 : : else
503 : : {
504 [ # # # # : 0 : switch (pAddInFuncData->GetParamType(j+1))
# # ]
505 : : {
506 : : case PTR_DOUBLE:
507 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescValue );
508 : 0 : break;
509 : : case PTR_STRING:
510 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescString );
511 : 0 : break;
512 : : case PTR_DOUBLE_ARR:
513 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescValues );
514 : 0 : break;
515 : : case PTR_STRING_ARR:
516 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescStrings );
517 : 0 : break;
518 : : case PTR_CELL_ARR:
519 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescCells );
520 : 0 : break;
521 : : default:
522 [ # # ]: 0 : pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescNone );
523 : 0 : break;
524 : : }
525 : : }
526 : : }
527 : : }
528 : :
529 [ # # ]: 0 : tmpFuncList.push_back(pDesc);
530 : 0 : nStrLen = (*(pDesc->pFuncName)).getLength();
531 [ # # ]: 0 : if ( nStrLen > nMaxFuncNameLen)
532 : 0 : nMaxFuncNameLen = nStrLen;
533 : 0 : }
534 : :
535 : : // StarOne AddIns
536 : :
537 [ + - ]: 5 : ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
538 [ + - ]: 5 : long nUnoCount = pUnoAddIns->GetFuncCount();
539 [ + + ]: 303 : for (long nFunc=0; nFunc<nUnoCount; nFunc++)
540 : : {
541 [ + - ]: 298 : pDesc = new ScFuncDesc;
542 : 298 : pDesc->nFIndex = nNextId++;
543 : :
544 [ + + ][ + - ]: 298 : if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
545 : : {
546 [ + - ]: 218 : tmpFuncList.push_back(pDesc);
547 : 218 : nStrLen = (*(pDesc->pFuncName)).getLength();
548 [ - + ]: 218 : if (nStrLen > nMaxFuncNameLen)
549 : 0 : nMaxFuncNameLen = nStrLen;
550 : : }
551 : : else
552 [ + - ][ + - ]: 80 : delete pDesc;
553 : : }
554 : :
555 : : //Move list to vector for better random access performance
556 [ + - ]: 5 : ::std::vector<const ScFuncDesc*> tmp(tmpFuncList.begin(), tmpFuncList.end());
557 : 5 : tmpFuncList.clear();
558 : 5 : aFunctionList.swap(tmp);
559 : :
560 : : //Initialize iterator
561 : 5 : aFunctionListIter = aFunctionList.end();
562 : 5 : }
563 : :
564 : 5 : ScFunctionList::~ScFunctionList()
565 : : {
566 [ + - ]: 5 : const ScFuncDesc* pDesc = First();
567 [ + + ]: 1658 : while (pDesc)
568 : : {
569 [ + - ][ + - ]: 1653 : delete pDesc;
570 [ + - ]: 1653 : pDesc = Next();
571 : : }
572 : 5 : }
573 : :
574 : 8 : const ScFuncDesc* ScFunctionList::First()
575 : : {
576 : 8 : const ScFuncDesc* pDesc = NULL;
577 : 8 : aFunctionListIter = aFunctionList.begin();
578 [ + - ][ + - ]: 8 : if(aFunctionListIter != aFunctionList.end())
579 : 8 : pDesc = *aFunctionListIter;
580 : :
581 : 8 : return pDesc;
582 : : }
583 : :
584 : 2514 : const ScFuncDesc* ScFunctionList::Next()
585 : : {
586 : 2514 : const ScFuncDesc* pDesc = NULL;
587 [ + - ][ + - ]: 2514 : if(aFunctionListIter != aFunctionList.end())
588 : : {
589 [ + - ][ + + ]: 2514 : if((++aFunctionListIter) != aFunctionList.end())
590 : 2506 : pDesc = *aFunctionListIter;
591 : : }
592 : 2514 : return pDesc;
593 : : }
594 : :
595 : 2059 : const ScFuncDesc* ScFunctionList::GetFunction( sal_uInt32 nIndex ) const
596 : : {
597 : 2059 : const ScFuncDesc* pDesc = NULL;
598 [ + - ]: 2059 : if(nIndex < aFunctionList.size())
599 : 2059 : pDesc = aFunctionList.at(nIndex);
600 : :
601 : 2059 : return pDesc;
602 : : }
603 : :
604 : : //===================================================================
605 : : // class ScFunctionCategory:
606 : : //===================================================================
607 : :
608 : 33 : sal_uInt32 ScFunctionCategory::getCount() const
609 : : {
610 : 33 : return m_pCategory->size();
611 : : }
612 : :
613 : 0 : const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const
614 : : {
615 : 0 : return m_pMgr;
616 : : }
617 : :
618 : 33 : ::rtl::OUString ScFunctionCategory::getName() const
619 : : {
620 [ + - ]: 33 : if ( m_sName.isEmpty() )
621 : 33 : m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1);
622 : 33 : return m_sName;
623 : : }
624 : :
625 : 861 : const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const
626 : : {
627 : 861 : const ScFuncDesc* pDesc = NULL;
628 [ + - ]: 861 : if(_nPos < m_pCategory->size())
629 : 861 : pDesc = m_pCategory->at(_nPos);
630 : 861 : return pDesc;
631 : : }
632 : :
633 : 0 : sal_uInt32 ScFunctionCategory::getNumber() const
634 : : {
635 : 0 : return m_nCategory;
636 : : }
637 : :
638 : : //========================================================================
639 : : // class ScFunctionMgr:
640 : : //========================================================================
641 : :
642 : 3 : ScFunctionMgr::ScFunctionMgr() :
643 [ + - ]: 3 : pFuncList( ScGlobal::GetStarCalcFunctionList() )
644 : : {
645 : : OSL_ENSURE( pFuncList, "Functionlist not found." );
646 : 3 : sal_uInt32 catCount[MAX_FUNCCAT] = {0};
647 : :
648 [ + - ][ + - ]: 3 : aCatLists[0] = new ::std::vector<const ScFuncDesc*>();
649 [ + - ]: 3 : aCatLists[0]->reserve(pFuncList->GetCount());
650 : :
651 : : // Retrieve all functions, store in cumulative ("All") category, and count
652 : : // number of functions in each category
653 [ + - ][ + - ]: 864 : for(const ScFuncDesc* pDesc = pFuncList->First(); pDesc; pDesc = pFuncList->Next())
[ + + ]
654 : : {
655 : : OSL_ENSURE((pDesc->nCategory) < MAX_FUNCCAT, "Unknown category");
656 [ + - ]: 861 : if ((pDesc->nCategory) < MAX_FUNCCAT)
657 : 861 : ++catCount[pDesc->nCategory];
658 [ + - ]: 861 : aCatLists[0]->push_back(pDesc);
659 : : }
660 : :
661 : : // Sort functions in cumulative category by name
662 [ + - ]: 3 : ::std::sort(aCatLists[0]->begin(), aCatLists[0]->end(), ScFuncDesc::compareByName);
663 : :
664 : : // Allocate correct amount of space for categories
665 [ + + ]: 36 : for (sal_uInt16 i = 1; i < MAX_FUNCCAT; ++i)
666 : : {
667 [ + - ][ + - ]: 33 : aCatLists[i] = new ::std::vector<const ScFuncDesc*>();
668 [ + - ]: 33 : aCatLists[i]->reserve(catCount[i]);
669 : : }
670 : :
671 : : // Fill categories with the corresponding functions (still sorted by name)
672 [ + - ][ + + ]: 864 : for(::std::vector<const ScFuncDesc*>::iterator iter = aCatLists[0]->begin(); iter!=aCatLists[0]->end(); ++iter)
673 : : {
674 [ + - ]: 861 : if (((*iter)->nCategory) < MAX_FUNCCAT)
675 [ + - ]: 861 : aCatLists[(*iter)->nCategory]->push_back(*iter);
676 : : }
677 : :
678 : : // Initialize iterators
679 : 3 : pCurCatListIter = aCatLists[0]->end();
680 : 3 : pCurCatListEnd = aCatLists[0]->end();
681 : 3 : }
682 : :
683 : 3 : ScFunctionMgr::~ScFunctionMgr()
684 : : {
685 [ + + ]: 39 : for (sal_uInt16 i = 0; i < MAX_FUNCCAT; ++i)
686 [ + - ]: 36 : delete aCatLists[i];
687 [ - + ]: 6 : }
688 : :
689 : 0 : const ScFuncDesc* ScFunctionMgr::Get( const ::rtl::OUString& rFName ) const
690 : : {
691 : 0 : const ScFuncDesc* pDesc = NULL;
692 [ # # ]: 0 : if (rFName.getLength() <= pFuncList->GetMaxFuncNameLen())
693 : : {
694 [ # # ]: 0 : ::boost::scoped_ptr<ScFuncDesc> dummy(new ScFuncDesc);
695 [ # # ]: 0 : dummy->pFuncName = new ::rtl::OUString(rFName);
696 : : ::std::vector<const ScFuncDesc*>::iterator lower =
697 : 0 : ::std::lower_bound(aCatLists[0]->begin(), aCatLists[0]->end(),
698 [ # # ]: 0 : static_cast<const ScFuncDesc*>(dummy.get()), ScFuncDesc::compareByName);
699 : :
700 [ # # ]: 0 : if(rFName.equalsIgnoreAsciiCase(*(*lower)->pFuncName))
701 [ # # ]: 0 : pDesc = *lower;
702 : : }
703 : 0 : return pDesc;
704 : : }
705 : :
706 : 0 : const ScFuncDesc* ScFunctionMgr::Get( sal_uInt16 nFIndex ) const
707 : : {
708 : : const ScFuncDesc* pDesc;
709 [ # # ]: 0 : for (pDesc = First(0); pDesc; pDesc = Next())
710 [ # # ]: 0 : if (pDesc->nFIndex == nFIndex)
711 : 0 : break;
712 : 0 : return pDesc;
713 : : }
714 : :
715 : 0 : const ScFuncDesc* ScFunctionMgr::First( sal_uInt16 nCategory ) const
716 : : {
717 : : OSL_ENSURE( nCategory < MAX_FUNCCAT, "Unbekannte Kategorie" );
718 : 0 : const ScFuncDesc* pDesc = NULL;
719 [ # # ]: 0 : if ( nCategory < MAX_FUNCCAT )
720 : : {
721 : 0 : pCurCatListIter = aCatLists[nCategory]->begin();
722 : 0 : pCurCatListEnd = aCatLists[nCategory]->end();
723 : 0 : pDesc = *pCurCatListIter;
724 : : }
725 : : else
726 : : {
727 : 0 : pCurCatListIter = aCatLists[0]->end();
728 : 0 : pCurCatListEnd = aCatLists[0]->end();
729 : : }
730 : 0 : return pDesc;
731 : : }
732 : :
733 : 0 : const ScFuncDesc* ScFunctionMgr::Next() const
734 : : {
735 : 0 : const ScFuncDesc* pDesc = NULL;
736 [ # # ]: 0 : if ( pCurCatListIter != pCurCatListEnd )
737 : : {
738 [ # # ]: 0 : if ( (++pCurCatListIter) != pCurCatListEnd )
739 : : {
740 : 0 : pDesc = *pCurCatListIter;
741 : : }
742 : : }
743 : 0 : return pDesc;
744 : : }
745 : :
746 : 3 : sal_uInt32 ScFunctionMgr::getCount() const
747 : : {
748 : 3 : return MAX_FUNCCAT - 1;
749 : : }
750 : :
751 : 33 : const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const
752 : : {
753 : 33 : formula::IFunctionCategory* pRet = NULL;
754 [ + - ]: 33 : if ( nCategory < (MAX_FUNCCAT-1) )
755 : : {
756 : 33 : pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all"
757 : : }
758 : 33 : return pRet;
759 : : }
760 : :
761 : 0 : const formula::IFunctionDescription* ScFunctionMgr::getFunctionByName(const ::rtl::OUString& _sFunctionName) const
762 : : {
763 : 0 : return Get(_sFunctionName);
764 : : }
765 : :
766 : 0 : void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const
767 : : {
768 : 0 : const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions();
769 : 0 : sal_uInt16 nLRUFuncCount = Min( rAppOpt.GetLRUFuncListCount(), (sal_uInt16)LRU_MAX );
770 : 0 : sal_uInt16* pLRUListIds = rAppOpt.GetLRUFuncList();
771 : :
772 [ # # ]: 0 : if ( pLRUListIds )
773 : : {
774 [ # # ]: 0 : for (sal_uInt16 i = 0; i < nLRUFuncCount; ++i)
775 [ # # ]: 0 : _rLastRUFunctions.push_back( Get( pLRUListIds[i] ) );
776 : : }
777 : 0 : }
778 : :
779 : 33 : ::rtl::OUString ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber )
780 : : {
781 [ - + ]: 33 : if ( _nCategoryNumber > SC_FUNCGROUP_COUNT )
782 : : {
783 : : OSL_FAIL("Invalid category number!");
784 : 0 : return ::rtl::OUString();
785 : : }
786 : :
787 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
788 [ + - ][ + - ]: 33 : ::std::auto_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) );
[ + - ]
789 : : SAL_WNODEPRECATED_DECLARATIONS_POP
790 [ + - ][ + - ]: 33 : return SC_RESSTR(static_cast<sal_uInt16>(_nCategoryNumber));
[ + - ]
791 : : }
792 : :
793 : 0 : sal_Unicode ScFunctionMgr::getSingleToken(const formula::IFunctionManager::EToken _eToken) const
794 : : {
795 [ # # # # : 0 : switch(_eToken)
# # ]
796 : : {
797 : : case eOk:
798 : 0 : return ScCompiler::GetNativeSymbol(ocOpen).GetChar(0);
799 : : case eClose:
800 : 0 : return ScCompiler::GetNativeSymbol(ocClose).GetChar(0);
801 : : case eSep:
802 : 0 : return ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
803 : : case eArrayOpen:
804 : 0 : return ScCompiler::GetNativeSymbol(ocArrayOpen).GetChar(0);
805 : : case eArrayClose:
806 : 0 : return ScCompiler::GetNativeSymbol(ocArrayClose).GetChar(0);
807 : : }
808 : 0 : return 0;
809 : : }
810 : :
811 : : //========================================================================
812 : : // class ScFuncRes:
813 : : //========================================================================
814 : :
815 : 1440 : ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
816 : 1440 : : Resource(aRes)
817 : : {
818 [ + - ]: 1440 : rbSuppressed = (bool)GetNum();
819 [ + - ]: 1440 : pDesc->nCategory = GetNum();
820 [ + - ]: 1440 : pDesc->sHelpId = ReadByteStringRes();
821 [ + - ]: 1440 : pDesc->nArgCount = GetNum();
822 : 1440 : sal_uInt16 nArgs = pDesc->nArgCount;
823 [ + + ]: 1440 : if (nArgs >= VAR_ARGS)
824 : 185 : nArgs -= VAR_ARGS - 1;
825 [ + + ]: 1440 : if (nArgs)
826 : : {
827 [ + - ][ + + ]: 4310 : pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
828 [ + + ]: 4310 : for (sal_uInt16 i = 0; i < nArgs; ++i)
829 : : {
830 [ + - ]: 2910 : pDesc->pDefArgFlags[i].bOptional = (bool)GetNum();
831 : : }
832 : : }
833 : : // Need to read the value from the resource even if nArgs==0 to advance the
834 : : // resource position pointer, so this can't be in the if(nArgs) block above.
835 [ + - ]: 1440 : sal_uInt16 nSuppressed = GetNum();
836 [ - + ]: 1440 : if (nSuppressed)
837 : : {
838 [ # # ]: 0 : if (nSuppressed > nArgs)
839 : : {
840 : : OSL_TRACE( "ScFuncRes: suppressed parameters count mismatch on OpCode %u: suppressed %d > params %d",
841 : : aRes.GetId(), (int)nSuppressed, (int)nArgs);
842 : 0 : nSuppressed = nArgs; // sanitize
843 : : }
844 [ # # ]: 0 : for (sal_uInt16 i = 0; i < nSuppressed; ++i)
845 : : {
846 [ # # ]: 0 : sal_uInt16 nParam = GetNum();
847 [ # # ]: 0 : if (nParam < nArgs)
848 : : {
849 [ # # ][ # # ]: 0 : if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1)
850 : : {
851 : 0 : OSL_TRACE( "ScFuncRes: VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d == arg %d-1",
852 : : aRes.GetId(), (int)nParam, (int)nArgs);
853 : : }
854 : : else
855 : : {
856 : 0 : pDesc->pDefArgFlags[nParam].bSuppress = true;
857 : 0 : pDesc->bHasSuppressedArgs = true;
858 : : }
859 : : }
860 : : else
861 : : {
862 : : OSL_TRACE( "ScFuncRes: suppressed parameter exceeds count on OpCode %u: param %d >= args %d",
863 : : aRes.GetId(), (int)nParam, (int)nArgs);
864 : : }
865 : : }
866 : : }
867 : :
868 [ + - ][ + - ]: 1440 : pDesc->pFuncName = new ::rtl::OUString( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId())));
[ + - ]
869 [ + - ][ + - ]: 1440 : pDesc->pFuncDesc = new ::rtl::OUString( SC_RESSTR(1) );
[ + - ]
870 : :
871 [ + + ]: 1440 : if (nArgs)
872 : : {
873 [ + - ]: 1400 : pDesc->ppDefArgNames = new ::rtl::OUString*[nArgs];
874 [ + - ]: 1400 : pDesc->ppDefArgDescs = new ::rtl::OUString*[nArgs];
875 [ + + ]: 4310 : for (sal_uInt16 i = 0; i < nArgs; ++i)
876 : : {
877 [ + - ][ + - ]: 2910 : pDesc->ppDefArgNames[i] = new ::rtl::OUString(SC_RESSTR(2*(i+1) ));
[ + - ]
878 [ + - ][ + - ]: 2910 : pDesc->ppDefArgDescs[i] = new ::rtl::OUString(SC_RESSTR(2*(i+1)+1));
[ + - ]
879 : : }
880 : : }
881 : :
882 [ + - ]: 1440 : FreeResource();
883 : 1440 : }
884 : :
885 : 8670 : sal_uInt16 ScFuncRes::GetNum()
886 : : {
887 : 8670 : return ReadShortRes();
888 : : }
889 : :
890 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|