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