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