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