Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / funcdesc.cxx
blob66c32348576910bbe91360315e2729fb2a57bfc4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "funcdesc.hxx"
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"
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>
37 #include <numeric>
38 #include <boost/scoped_ptr.hpp>
40 class ScFuncRes : public Resource
42 public:
43 ScFuncRes( ResId&, ScFuncDesc*, bool & rbSuppressed );
45 private:
46 sal_uInt16 GetNum();
50 class ScResourcePublisher : public Resource
52 private:
53 void FreeResource() { Resource::FreeResource(); }
54 public:
55 ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {}
56 ~ScResourcePublisher() { FreeResource(); }
57 bool IsAvailableRes( const ResId& rId ) const
58 { return Resource::IsAvailableRes( rId ); }
62 //========================================================================
63 // class ScFuncDesc:
64 //========================================================================
66 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 bHasSuppressedArgs(false)
79 ScFuncDesc::~ScFuncDesc()
81 Clear();
84 void ScFuncDesc::Clear()
86 sal_uInt16 nArgs = nArgCount;
87 if (nArgs >= PAIRED_VAR_ARGS)
88 nArgs -= PAIRED_VAR_ARGS - 2;
89 else if (nArgs >= VAR_ARGS)
90 nArgs -= VAR_ARGS - 1;
91 if (nArgs)
93 for (sal_uInt16 i=0; i<nArgs; i++ )
95 delete ppDefArgNames[i];
96 delete ppDefArgDescs[i];
98 delete [] ppDefArgNames;
99 delete [] ppDefArgDescs;
100 delete [] pDefArgFlags;
102 nArgCount = 0;
103 ppDefArgNames = NULL;
104 ppDefArgDescs = NULL;
105 pDefArgFlags = NULL;
107 delete pFuncName;
108 pFuncName = NULL;
110 delete pFuncDesc;
111 pFuncDesc = NULL;
113 nFIndex = 0;
114 nCategory = 0;
115 sHelpId = OString();
116 bIncomplete = false;
117 bHasSuppressedArgs = false;
120 OUString ScFuncDesc::GetParamList() const
122 OUString sep(ScCompiler::GetNativeSymbol(ocSep));
124 OUStringBuffer aSig;
126 if ( nArgCount > 0 )
128 if ( nArgCount < VAR_ARGS )
130 sal_uInt16 nLastSuppressed = nArgCount;
131 sal_uInt16 nLastAdded = nArgCount;
132 for ( sal_uInt16 i=0; i<nArgCount; i++ )
134 if (pDefArgFlags[i].bSuppress)
135 nLastSuppressed = i;
136 else
138 nLastAdded = i;
139 aSig.append(*(ppDefArgNames[i]));
140 if ( i != nArgCount-1 )
142 aSig.append(sep);
143 aSig.appendAscii( " " );
147 // If only suppressed parameters follow the last added parameter,
148 // remove one "; "
149 if (nLastSuppressed < nArgCount && nLastAdded < nLastSuppressed &&
150 aSig.getLength() >= 2)
151 aSig.setLength(aSig.getLength() - 2);
153 else if ( nArgCount < PAIRED_VAR_ARGS)
155 sal_uInt16 nFix = nArgCount - VAR_ARGS;
156 for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
158 if (!pDefArgFlags[nArg].bSuppress)
160 aSig.append(*(ppDefArgNames[nArg]));
161 aSig.append(sep);
162 aSig.appendAscii( " " );
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 aSig.append(*(ppDefArgNames[nFix]));
170 aSig.append('1');
171 aSig.append(sep);
172 aSig.append(' ');
173 aSig.append(*(ppDefArgNames[nFix]));
174 aSig.append('2');
175 aSig.append(sep);
176 aSig.appendAscii(" ... ");
178 else
180 sal_uInt16 nFix = nArgCount - PAIRED_VAR_ARGS;
181 for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
183 if (!pDefArgFlags[nArg].bSuppress)
185 aSig.append(*(ppDefArgNames[nArg]));
186 aSig.append(sep);
187 aSig.appendAscii( " " );
191 aSig.append(*(ppDefArgNames[nFix]));
192 aSig.append('1');
193 aSig.appendAscii( ", " );
194 aSig.append(*(ppDefArgNames[nFix+1]));
195 aSig.append('1');
196 aSig.append(sep);
197 aSig.appendAscii( " " );
198 aSig.append(*(ppDefArgNames[nFix]));
199 aSig.append('2');
200 aSig.appendAscii( ", " );
201 aSig.append(*(ppDefArgNames[nFix+1]));
202 aSig.append('2');
203 aSig.append(sep);
204 aSig.appendAscii( " ... " );
208 return aSig.makeStringAndClear();
211 OUString ScFuncDesc::getSignature() const
213 OUStringBuffer aSig;
215 if(pFuncName)
217 aSig.append(*pFuncName);
219 OUString aParamList = GetParamList();
220 if( !aParamList.isEmpty() )
222 aSig.appendAscii( "( " );
223 aSig.append(aParamList);
224 // U+00A0 (NBSP) prevents automatic line break
225 aSig.append( static_cast< sal_Unicode >(0xA0) );
226 aSig.appendAscii( ")" );
228 else
229 aSig.appendAscii( "()" );
231 return aSig.makeStringAndClear();
234 OUString ScFuncDesc::getFormula( const ::std::vector< OUString >& _aArguments ) const
236 OUString sep = ScCompiler::GetNativeSymbol(ocSep);
238 OUStringBuffer aFormula;
240 if(pFuncName)
242 aFormula.append( *pFuncName );
244 aFormula.appendAscii( "(" );
245 ::std::vector< OUString >::const_iterator aIter = _aArguments.begin();
246 ::std::vector< OUString >::const_iterator aEnd = _aArguments.end();
248 if ( nArgCount > 0 && aIter != aEnd )
250 bool bLastArg = aIter->isEmpty();
252 while( aIter != aEnd && !bLastArg )
254 aFormula.append( *(aIter) );
255 if ( aIter != (aEnd-1) )
257 bLastArg = (aIter+1)->isEmpty();
258 if ( !bLastArg )
259 aFormula.append( sep );
262 ++aIter;
266 aFormula.appendAscii( ")" );
268 return aFormula.makeStringAndClear();
271 sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
273 if (!bHasSuppressedArgs || !pDefArgFlags)
274 return nArgCount;
276 sal_uInt16 nArgs = nArgCount;
277 if (nArgs >= PAIRED_VAR_ARGS)
278 nArgs -= PAIRED_VAR_ARGS - 2;
279 else if (nArgs >= VAR_ARGS)
280 nArgs -= VAR_ARGS - 1;
281 sal_uInt16 nCount = nArgs;
282 for (sal_uInt16 i=0; i < nArgs; ++i)
284 if (pDefArgFlags[i].bSuppress)
285 --nCount;
287 if (nArgCount >= PAIRED_VAR_ARGS)
288 nCount += PAIRED_VAR_ARGS - 2;
289 else if (nArgCount >= VAR_ARGS)
290 nCount += VAR_ARGS - 1;
291 return nCount;
294 OUString ScFuncDesc::getFunctionName() const
296 OUString sRet;
297 if ( pFuncName )
298 sRet = *pFuncName;
299 return sRet;
302 const formula::IFunctionCategory* ScFuncDesc::getCategory() const
304 return ScGlobal::GetStarCalcFunctionMgr()->getCategory(nCategory);
307 OUString ScFuncDesc::getDescription() const
309 OUString sRet;
310 if ( pFuncDesc )
311 sRet = *pFuncDesc;
312 return sRet;
315 xub_StrLen ScFuncDesc::getSuppressedArgumentCount() const
317 return GetSuppressedArgCount();
320 void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const
322 if (!bHasSuppressedArgs || !pDefArgFlags)
324 _rArguments.resize( nArgCount);
325 ::std::vector<sal_uInt16>::iterator iter = _rArguments.begin();
326 sal_uInt16 value = 0;
327 while (iter != _rArguments.end())
328 *iter++ = value++;
331 _rArguments.reserve( nArgCount);
332 sal_uInt16 nArgs = nArgCount;
333 if (nArgs >= PAIRED_VAR_ARGS)
334 nArgs -= PAIRED_VAR_ARGS - 2;
335 else if (nArgs >= VAR_ARGS)
336 nArgs -= VAR_ARGS - 1;
337 for (sal_uInt16 i=0; i < nArgs; ++i)
339 if (!pDefArgFlags[i].bSuppress)
340 _rArguments.push_back(i);
344 void ScFuncDesc::initArgumentInfo() const
346 // get the full argument description
347 // (add-in has to be instantiated to get the type information)
349 if ( bIncomplete && pFuncName )
351 ScUnoAddInCollection& rAddIns = *ScGlobal::GetAddInCollection();
352 OUString aIntName(rAddIns.FindFunction( *pFuncName, true )); // pFuncName is upper-case
354 if ( !aIntName.isEmpty() )
356 // GetFuncData with bComplete=true loads the component and updates
357 // the global function list if needed.
359 rAddIns.GetFuncData( aIntName, true );
362 if ( bIncomplete )
364 OSL_FAIL( "couldn't initialize add-in function" );
365 const_cast<ScFuncDesc*>(this)->bIncomplete = false; // even if there was an error, don't try again
370 OString ScFuncDesc::getHelpId() const
372 return sHelpId;
375 sal_uInt32 ScFuncDesc::getParameterCount() const
377 return nArgCount;
380 OUString ScFuncDesc::getParameterName(sal_uInt32 _nPos) const
382 return *(ppDefArgNames[_nPos]);
385 OUString ScFuncDesc::getParameterDescription(sal_uInt32 _nPos) const
387 return *(ppDefArgDescs[_nPos]);
390 bool ScFuncDesc::isParameterOptional(sal_uInt32 _nPos) const
392 return pDefArgFlags[_nPos].bOptional;
395 bool ScFuncDesc::compareByName(const ScFuncDesc* a, const ScFuncDesc* b)
397 return (ScGlobal::GetCaseCollator()->compareString(*a->pFuncName, *b->pFuncName ) < 0);
400 //===================================================================
401 // class ScFunctionList:
402 //===================================================================
404 ScFunctionList::ScFunctionList() :
405 nMaxFuncNameLen ( 0 )
407 ScFuncDesc* pDesc = NULL;
408 xub_StrLen nStrLen = 0;
409 ::std::list<ScFuncDesc*> tmpFuncList;
410 sal_uInt16 nDescBlock[] =
412 RID_SC_FUNCTION_DESCRIPTIONS1,
413 RID_SC_FUNCTION_DESCRIPTIONS2
416 for (sal_uInt16 k = 0; k < SAL_N_ELEMENTS(nDescBlock); ++k)
418 SAL_WNODEPRECATED_DECLARATIONS_PUSH
419 ::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 for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
427 ScResId aRes(i);
428 aRes.SetRT(RSC_RESOURCE);
429 // Sub resource of OpCode available?
430 if (pBlock->IsAvailableRes(aRes))
432 pDesc = new ScFuncDesc;
433 bool bSuppressed = false;
434 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 if (bSuppressed)
439 delete pDesc;
440 else
442 pDesc->nFIndex = i;
443 tmpFuncList.push_back(pDesc);
445 nStrLen = (*(pDesc->pFuncName)).getLength();
446 if (nStrLen > nMaxFuncNameLen)
447 nMaxFuncNameLen = nStrLen;
453 sal_uInt16 nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions
455 // Interpretation of AddIn list
456 OUString aDefArgNameValue = "value";
457 OUString aDefArgNameString = "string";
458 OUString aDefArgNameValues = "values";
459 OUString aDefArgNameStrings = "strings";
460 OUString aDefArgNameCells = "cells";
461 OUString aDefArgNameNone = "none";
462 OUString aDefArgDescValue = "a value";
463 OUString aDefArgDescString = "a string";
464 OUString aDefArgDescValues = "array of values";
465 OUString aDefArgDescStrings = "array of strings";
466 OUString aDefArgDescCells = "range of cells";
467 OUString aDefArgDescNone = "none";
469 OUString aArgName, aArgDesc;
470 const FuncCollection& rFuncColl = *ScGlobal::GetFuncCollection();
471 FuncCollection::const_iterator it = rFuncColl.begin(), itEnd = rFuncColl.end();
472 for (; it != itEnd; ++it)
474 const FuncData* pAddInFuncData = it->second;
475 pDesc = new ScFuncDesc;
476 sal_uInt16 nArgs = pAddInFuncData->GetParamCount() - 1;
477 pAddInFuncData->getParamDesc( aArgName, aArgDesc, 0 );
478 pDesc->nFIndex = nNextId++; // ??? OpCode vergeben
479 pDesc->nCategory = ID_FUNCTION_GRP_ADDINS;
480 pDesc->pFuncName = new OUString(pAddInFuncData->GetInternalName().toAsciiUpperCase());
482 OUStringBuffer aBuf(aArgDesc);
483 aBuf.append('\n');
484 aBuf.appendAscii("( AddIn: ");
485 aBuf.append(pAddInFuncData->GetModuleName());
486 aBuf.appendAscii(" )");
487 pDesc->pFuncDesc = new OUString(aBuf.makeStringAndClear());
489 pDesc->nArgCount = nArgs;
490 if (nArgs)
492 pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
493 pDesc->ppDefArgNames = new OUString*[nArgs];
494 pDesc->ppDefArgDescs = new OUString*[nArgs];
495 for (sal_uInt16 j = 0; j < nArgs; ++j)
497 pDesc->pDefArgFlags[j].bOptional = false;
498 pDesc->pDefArgFlags[j].bSuppress = false;
499 pAddInFuncData->getParamDesc( aArgName, aArgDesc, j+1 );
500 if ( !aArgName.isEmpty() )
501 pDesc->ppDefArgNames[j] = new OUString( aArgName );
502 else
504 switch (pAddInFuncData->GetParamType(j+1))
506 case PTR_DOUBLE:
507 pDesc->ppDefArgNames[j] = new OUString( aDefArgNameValue );
508 break;
509 case PTR_STRING:
510 pDesc->ppDefArgNames[j] = new OUString( aDefArgNameString );
511 break;
512 case PTR_DOUBLE_ARR:
513 pDesc->ppDefArgNames[j] = new OUString( aDefArgNameValues );
514 break;
515 case PTR_STRING_ARR:
516 pDesc->ppDefArgNames[j] = new OUString( aDefArgNameStrings );
517 break;
518 case PTR_CELL_ARR:
519 pDesc->ppDefArgNames[j] = new OUString( aDefArgNameCells );
520 break;
521 default:
522 pDesc->ppDefArgNames[j] = new OUString( aDefArgNameNone );
523 break;
526 if ( !aArgDesc.isEmpty() )
527 pDesc->ppDefArgDescs[j] = new OUString( aArgDesc );
528 else
530 switch (pAddInFuncData->GetParamType(j+1))
532 case PTR_DOUBLE:
533 pDesc->ppDefArgDescs[j] = new OUString( aDefArgDescValue );
534 break;
535 case PTR_STRING:
536 pDesc->ppDefArgDescs[j] = new OUString( aDefArgDescString );
537 break;
538 case PTR_DOUBLE_ARR:
539 pDesc->ppDefArgDescs[j] = new OUString( aDefArgDescValues );
540 break;
541 case PTR_STRING_ARR:
542 pDesc->ppDefArgDescs[j] = new OUString( aDefArgDescStrings );
543 break;
544 case PTR_CELL_ARR:
545 pDesc->ppDefArgDescs[j] = new OUString( aDefArgDescCells );
546 break;
547 default:
548 pDesc->ppDefArgDescs[j] = new OUString( aDefArgDescNone );
549 break;
555 tmpFuncList.push_back(pDesc);
556 nStrLen = (*(pDesc->pFuncName)).getLength();
557 if ( nStrLen > nMaxFuncNameLen)
558 nMaxFuncNameLen = nStrLen;
561 // StarOne AddIns
563 ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
564 long nUnoCount = pUnoAddIns->GetFuncCount();
565 for (long nFunc=0; nFunc<nUnoCount; nFunc++)
567 pDesc = new ScFuncDesc;
568 pDesc->nFIndex = nNextId++;
570 if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
572 tmpFuncList.push_back(pDesc);
573 nStrLen = (*(pDesc->pFuncName)).getLength();
574 if (nStrLen > nMaxFuncNameLen)
575 nMaxFuncNameLen = nStrLen;
577 else
578 delete pDesc;
581 //Move list to vector for better random access performance
582 ::std::vector<const ScFuncDesc*> tmp(tmpFuncList.begin(), tmpFuncList.end());
583 tmpFuncList.clear();
584 aFunctionList.swap(tmp);
586 //Initialize iterator
587 aFunctionListIter = aFunctionList.end();
590 ScFunctionList::~ScFunctionList()
592 const ScFuncDesc* pDesc = First();
593 while (pDesc)
595 delete pDesc;
596 pDesc = Next();
600 const ScFuncDesc* ScFunctionList::First()
602 const ScFuncDesc* pDesc = NULL;
603 aFunctionListIter = aFunctionList.begin();
604 if(aFunctionListIter != aFunctionList.end())
605 pDesc = *aFunctionListIter;
607 return pDesc;
610 const ScFuncDesc* ScFunctionList::Next()
612 const ScFuncDesc* pDesc = NULL;
613 if(aFunctionListIter != aFunctionList.end())
615 if((++aFunctionListIter) != aFunctionList.end())
616 pDesc = *aFunctionListIter;
618 return pDesc;
621 const ScFuncDesc* ScFunctionList::GetFunction( sal_uInt32 nIndex ) const
623 const ScFuncDesc* pDesc = NULL;
624 if(nIndex < aFunctionList.size())
625 pDesc = aFunctionList.at(nIndex);
627 return pDesc;
630 //===================================================================
631 // class ScFunctionCategory:
632 //===================================================================
634 sal_uInt32 ScFunctionCategory::getCount() const
636 return m_pCategory->size();
639 const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const
641 return m_pMgr;
644 OUString ScFunctionCategory::getName() const
646 if ( m_sName.isEmpty() )
647 m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1);
648 return m_sName;
651 const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const
653 const ScFuncDesc* pDesc = NULL;
654 if(_nPos < m_pCategory->size())
655 pDesc = m_pCategory->at(_nPos);
656 return pDesc;
659 sal_uInt32 ScFunctionCategory::getNumber() const
661 return m_nCategory;
664 //========================================================================
665 // class ScFunctionMgr:
666 //========================================================================
668 ScFunctionMgr::ScFunctionMgr() :
669 pFuncList( ScGlobal::GetStarCalcFunctionList() )
671 OSL_ENSURE( pFuncList, "Functionlist not found." );
672 sal_uInt32 catCount[MAX_FUNCCAT] = {0};
674 aCatLists[0] = new ::std::vector<const ScFuncDesc*>();
675 aCatLists[0]->reserve(pFuncList->GetCount());
677 // Retrieve all functions, store in cumulative ("All") category, and count
678 // number of functions in each category
679 for(const ScFuncDesc* pDesc = pFuncList->First(); pDesc; pDesc = pFuncList->Next())
681 OSL_ENSURE((pDesc->nCategory) < MAX_FUNCCAT, "Unknown category");
682 if ((pDesc->nCategory) < MAX_FUNCCAT)
683 ++catCount[pDesc->nCategory];
684 aCatLists[0]->push_back(pDesc);
687 // Sort functions in cumulative category by name
688 ::std::sort(aCatLists[0]->begin(), aCatLists[0]->end(), ScFuncDesc::compareByName);
690 // Allocate correct amount of space for categories
691 for (sal_uInt16 i = 1; i < MAX_FUNCCAT; ++i)
693 aCatLists[i] = new ::std::vector<const ScFuncDesc*>();
694 aCatLists[i]->reserve(catCount[i]);
697 // Fill categories with the corresponding functions (still sorted by name)
698 for(::std::vector<const ScFuncDesc*>::iterator iter = aCatLists[0]->begin(); iter!=aCatLists[0]->end(); ++iter)
700 if (((*iter)->nCategory) < MAX_FUNCCAT)
701 aCatLists[(*iter)->nCategory]->push_back(*iter);
704 // Initialize iterators
705 pCurCatListIter = aCatLists[0]->end();
706 pCurCatListEnd = aCatLists[0]->end();
709 ScFunctionMgr::~ScFunctionMgr()
711 for (sal_uInt16 i = 0; i < MAX_FUNCCAT; ++i)
712 delete aCatLists[i];
715 const ScFuncDesc* ScFunctionMgr::Get( const OUString& rFName ) const
717 const ScFuncDesc* pDesc = NULL;
718 if (rFName.getLength() <= pFuncList->GetMaxFuncNameLen())
720 ::boost::scoped_ptr<ScFuncDesc> dummy(new ScFuncDesc);
721 dummy->pFuncName = new OUString(rFName);
722 ::std::vector<const ScFuncDesc*>::iterator lower =
723 ::std::lower_bound(aCatLists[0]->begin(), aCatLists[0]->end(),
724 static_cast<const ScFuncDesc*>(dummy.get()), ScFuncDesc::compareByName);
726 if(rFName.equalsIgnoreAsciiCase(*(*lower)->pFuncName))
727 pDesc = *lower;
729 return pDesc;
732 const ScFuncDesc* ScFunctionMgr::Get( sal_uInt16 nFIndex ) const
734 const ScFuncDesc* pDesc;
735 for (pDesc = First(0); pDesc; pDesc = Next())
736 if (pDesc->nFIndex == nFIndex)
737 break;
738 return pDesc;
741 const ScFuncDesc* ScFunctionMgr::First( sal_uInt16 nCategory ) const
743 OSL_ENSURE( nCategory < MAX_FUNCCAT, "Unknown category" );
744 const ScFuncDesc* pDesc = NULL;
745 if ( nCategory < MAX_FUNCCAT )
747 pCurCatListIter = aCatLists[nCategory]->begin();
748 pCurCatListEnd = aCatLists[nCategory]->end();
749 pDesc = *pCurCatListIter;
751 else
753 pCurCatListIter = aCatLists[0]->end();
754 pCurCatListEnd = aCatLists[0]->end();
756 return pDesc;
759 const ScFuncDesc* ScFunctionMgr::Next() const
761 const ScFuncDesc* pDesc = NULL;
762 if ( pCurCatListIter != pCurCatListEnd )
764 if ( (++pCurCatListIter) != pCurCatListEnd )
766 pDesc = *pCurCatListIter;
769 return pDesc;
772 sal_uInt32 ScFunctionMgr::getCount() const
774 return MAX_FUNCCAT - 1;
777 const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const
779 formula::IFunctionCategory* pRet = NULL;
780 if ( nCategory < (MAX_FUNCCAT-1) )
782 pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all"
784 return pRet;
787 const formula::IFunctionDescription* ScFunctionMgr::getFunctionByName(const OUString& _sFunctionName) const
789 return Get(_sFunctionName);
792 void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const
794 const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions();
795 sal_uInt16 nLRUFuncCount = std::min( rAppOpt.GetLRUFuncListCount(), (sal_uInt16)LRU_MAX );
796 sal_uInt16* pLRUListIds = rAppOpt.GetLRUFuncList();
798 if ( pLRUListIds )
800 for (sal_uInt16 i = 0; i < nLRUFuncCount; ++i)
801 _rLastRUFunctions.push_back( Get( pLRUListIds[i] ) );
805 OUString ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber )
807 if ( _nCategoryNumber > SC_FUNCGROUP_COUNT )
809 OSL_FAIL("Invalid category number!");
810 return OUString();
813 SAL_WNODEPRECATED_DECLARATIONS_PUSH
814 ::std::auto_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) );
815 SAL_WNODEPRECATED_DECLARATIONS_POP
816 return SC_RESSTR(static_cast<sal_uInt16>(_nCategoryNumber));
819 sal_Unicode ScFunctionMgr::getSingleToken(const formula::IFunctionManager::EToken _eToken) const
821 switch(_eToken)
823 case eOk:
824 return ScCompiler::GetNativeSymbolChar(ocOpen);
825 case eClose:
826 return ScCompiler::GetNativeSymbolChar(ocClose);
827 case eSep:
828 return ScCompiler::GetNativeSymbolChar(ocSep);
829 case eArrayOpen:
830 return ScCompiler::GetNativeSymbolChar(ocArrayOpen);
831 case eArrayClose:
832 return ScCompiler::GetNativeSymbolChar(ocArrayClose);
834 return 0;
837 //========================================================================
838 // class ScFuncRes:
839 //========================================================================
841 ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
842 : Resource(aRes)
844 rbSuppressed = (bool)GetNum();
845 pDesc->nCategory = GetNum();
846 pDesc->sHelpId = ReadByteStringRes();
847 pDesc->nArgCount = GetNum();
848 sal_uInt16 nArgs = pDesc->nArgCount;
849 if (nArgs >= PAIRED_VAR_ARGS)
850 nArgs -= PAIRED_VAR_ARGS - 2;
851 else if (nArgs >= VAR_ARGS)
852 nArgs -= VAR_ARGS - 1;
853 if (nArgs)
855 pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
856 for (sal_uInt16 i = 0; i < nArgs; ++i)
858 pDesc->pDefArgFlags[i].bOptional = (bool)GetNum();
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 sal_uInt16 nSuppressed = GetNum();
864 if (nSuppressed)
866 if (nSuppressed > nArgs)
868 OSL_TRACE( "ScFuncRes: suppressed parameters count mismatch on OpCode %u: suppressed %d > params %d",
869 aRes.GetId(), (int)nSuppressed, (int)nArgs);
870 nSuppressed = nArgs; // sanitize
872 for (sal_uInt16 i = 0; i < nSuppressed; ++i)
874 sal_uInt16 nParam = GetNum();
875 if (nParam < nArgs)
877 if (pDesc->nArgCount >= PAIRED_VAR_ARGS && nParam >= nArgs-2)
879 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);
882 else if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1)
884 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);
887 else
889 pDesc->pDefArgFlags[nParam].bSuppress = true;
890 pDesc->bHasSuppressedArgs = true;
893 else
895 OSL_TRACE( "ScFuncRes: suppressed parameter exceeds count on OpCode %u: param %d >= args %d",
896 aRes.GetId(), (int)nParam, (int)nArgs);
901 pDesc->pFuncName = new OUString( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId())));
902 pDesc->pFuncDesc = new OUString( SC_RESSTR(1) );
904 if (nArgs)
906 pDesc->ppDefArgNames = new OUString*[nArgs];
907 pDesc->ppDefArgDescs = new OUString*[nArgs];
908 for (sal_uInt16 i = 0; i < nArgs; ++i)
910 pDesc->ppDefArgNames[i] = new OUString(SC_RESSTR(2*(i+1) ));
911 pDesc->ppDefArgDescs[i] = new OUString(SC_RESSTR(2*(i+1)+1));
915 FreeResource();
918 sal_uInt16 ScFuncRes::GetNum()
920 return ReadShortRes();
923 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */