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