LCOV - code coverage report
Current view: top level - sc/source/core/data - funcdesc.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 201 466 43.1 %
Date: 2014-04-11 Functions: 29 50 58.0 %
Legend: Lines: hit not hit

          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        1077 : 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          17 :     void FreeResource() { Resource::FreeResource(); }
      54             : public:
      55          17 :     ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {}
      56          17 :     ~ScResourcePublisher() { FreeResource(); }
      57        2820 :     bool IsAvailableRes( const ResId& rId ) const
      58        2820 :                         { return Resource::IsAvailableRes( rId ); }
      59             : 
      60             : };
      61             : 
      62             : 
      63             : // class ScFuncDesc:
      64             : 
      65             : 
      66        1423 : ScFuncDesc::ScFuncDesc() :
      67             :         pFuncName       (NULL),
      68             :         pFuncDesc       (NULL),
      69             :         pDefArgFlags    (NULL),
      70             :         nFIndex         (0),
      71             :         nCategory       (0),
      72             :         nArgCount       (0),
      73             :         bIncomplete     (false),
      74        1423 :         bHasSuppressedArgs(false)
      75        1423 : {}
      76             : 
      77        4269 : ScFuncDesc::~ScFuncDesc()
      78             : {
      79        1423 :     Clear();
      80        2846 : }
      81             : 
      82        1649 : void ScFuncDesc::Clear()
      83             : {
      84        1649 :     sal_uInt16 nArgs = nArgCount;
      85        1649 :     if (nArgs >= PAIRED_VAR_ARGS)
      86           9 :         nArgs -= PAIRED_VAR_ARGS - 2;
      87        1640 :     else if (nArgs >= VAR_ARGS)
      88         142 :         nArgs -= VAR_ARGS - 1;
      89        1649 :     if (nArgs)
      90             :     {
      91        1279 :         delete [] pDefArgFlags;
      92             :     }
      93        1649 :     nArgCount = 0;
      94        1649 :     maDefArgNames.clear();
      95        1649 :     maDefArgDescs.clear();
      96        1649 :     pDefArgFlags = NULL;
      97             : 
      98        1649 :     delete pFuncName;
      99        1649 :     pFuncName = NULL;
     100             : 
     101        1649 :     delete pFuncDesc;
     102        1649 :     pFuncDesc = NULL;
     103             : 
     104        1649 :     nFIndex = 0;
     105        1649 :     nCategory = 0;
     106        1649 :     sHelpId = OString();
     107        1649 :     bIncomplete = false;
     108        1649 :     bHasSuppressedArgs = false;
     109        1649 : }
     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         470 : sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
     257             : {
     258         470 :     if (!bHasSuppressedArgs || !pDefArgFlags)
     259         470 :         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         359 : OUString ScFuncDesc::getFunctionName() const
     280             : {
     281         359 :     OUString sRet;
     282         359 :     if ( pFuncName )
     283         359 :         sRet = *pFuncName;
     284         359 :     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         478 : 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         478 :     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         478 : }
     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        3768 : bool ScFuncDesc::compareByName(const ScFuncDesc* a, const ScFuncDesc* b)
     381             : {
     382        3768 :     return (ScGlobal::GetCaseCollator()->compareString(*a->pFuncName, *b->pFuncName ) < 0);
     383             : }
     384             : 
     385             : 
     386             : // class ScFunctionList:
     387             : 
     388             : 
     389           3 : ScFunctionList::ScFunctionList() :
     390           3 :         nMaxFuncNameLen ( 0 )
     391             : {
     392           3 :     ScFuncDesc* pDesc = NULL;
     393           3 :     sal_Int32 nStrLen = 0;
     394           3 :     ::std::list<ScFuncDesc*> tmpFuncList;
     395             :     sal_uInt16 nDescBlock[] =
     396             :     {
     397             :         RID_SC_FUNCTION_DESCRIPTIONS1,
     398             :         RID_SC_FUNCTION_DESCRIPTIONS2
     399           3 :     };
     400             : 
     401           9 :     for (sal_uInt16 k = 0; k < SAL_N_ELEMENTS(nDescBlock); ++k)
     402             :     {
     403           6 :         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        2826 :         for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
     409             :         {
     410        2820 :             ScResId aRes(i);
     411        2820 :             aRes.SetRT(RSC_RESOURCE);
     412             :             // Sub resource of OpCode available?
     413        2820 :             if (pBlock->IsAvailableRes(aRes))
     414             :             {
     415        1077 :                 pDesc = new ScFuncDesc;
     416        1077 :                 bool bSuppressed = false;
     417        1077 :                 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        1077 :                 if (bSuppressed)
     422           0 :                     delete pDesc;
     423             :                 else
     424             :                 {
     425        1077 :                     pDesc->nFIndex = i;
     426        1077 :                     tmpFuncList.push_back(pDesc);
     427             : 
     428        1077 :                     nStrLen = (*(pDesc->pFuncName)).getLength();
     429        1077 :                     if (nStrLen > nMaxFuncNameLen)
     430          21 :                         nMaxFuncNameLen = nStrLen;
     431        1077 :                 }
     432             :             }
     433             :         }
     434           6 :     }
     435             : 
     436           3 :     sal_uInt16 nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions
     437             : 
     438             :     // Interpretation of AddIn list
     439           6 :     OUString aDefArgNameValue   = "value";
     440           6 :     OUString aDefArgNameString  = "string";
     441           6 :     OUString aDefArgNameValues  = "values";
     442           6 :     OUString aDefArgNameStrings = "strings";
     443           6 :     OUString aDefArgNameCells   = "cells";
     444           6 :     OUString aDefArgNameNone    = "none";
     445           6 :     OUString aDefArgDescValue   = "a value";
     446           6 :     OUString aDefArgDescString  = "a string";
     447           6 :     OUString aDefArgDescValues  = "array of values";
     448           6 :     OUString aDefArgDescStrings = "array of strings";
     449           6 :     OUString aDefArgDescCells   = "range of cells";
     450           6 :     OUString aDefArgDescNone    = "none";
     451             : 
     452           6 :     OUString aArgName, aArgDesc;
     453           3 :     const FuncCollection& rFuncColl = *ScGlobal::GetFuncCollection();
     454           3 :     FuncCollection::const_iterator it = rFuncColl.begin(), itEnd = rFuncColl.end();
     455           3 :     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           3 :     ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
     549           3 :     long nUnoCount = pUnoAddIns->GetFuncCount();
     550         349 :     for (long nFunc=0; nFunc<nUnoCount; nFunc++)
     551             :     {
     552         346 :         pDesc = new ScFuncDesc;
     553         346 :         pDesc->nFIndex = nNextId++;
     554             : 
     555         346 :         if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
     556             :         {
     557         226 :             tmpFuncList.push_back(pDesc);
     558         226 :             nStrLen = (*(pDesc->pFuncName)).getLength();
     559         226 :             if (nStrLen > nMaxFuncNameLen)
     560           0 :                 nMaxFuncNameLen = nStrLen;
     561             :         }
     562             :         else
     563         120 :             delete pDesc;
     564             :     }
     565             : 
     566             :     //Move list to vector for better random access performance
     567           3 :     ::std::vector<const ScFuncDesc*> tmp(tmpFuncList.begin(), tmpFuncList.end());
     568           3 :     tmpFuncList.clear();
     569           3 :     aFunctionList.swap(tmp);
     570             : 
     571             :     //Initialize iterator
     572           6 :     aFunctionListIter = aFunctionList.end();
     573           3 : }
     574             : 
     575           6 : ScFunctionList::~ScFunctionList()
     576             : {
     577           3 :     const ScFuncDesc* pDesc = First();
     578        1309 :     while (pDesc)
     579             :     {
     580        1303 :         delete pDesc;
     581        1303 :         pDesc = Next();
     582             :     }
     583           3 : }
     584             : 
     585           4 : const ScFuncDesc* ScFunctionList::First()
     586             : {
     587           4 :     const ScFuncDesc* pDesc = NULL;
     588           4 :     aFunctionListIter = aFunctionList.begin();
     589           4 :     if(aFunctionListIter != aFunctionList.end())
     590           4 :         pDesc = *aFunctionListIter;
     591             : 
     592           4 :     return pDesc;
     593             : }
     594             : 
     595        1662 : const ScFuncDesc* ScFunctionList::Next()
     596             : {
     597        1662 :     const ScFuncDesc* pDesc = NULL;
     598        1662 :     if(aFunctionListIter != aFunctionList.end())
     599             :     {
     600        1662 :         if((++aFunctionListIter) != aFunctionList.end())
     601        1658 :             pDesc = *aFunctionListIter;
     602             :     }
     603        1662 :     return pDesc;
     604             : }
     605             : 
     606        2480 : const ScFuncDesc* ScFunctionList::GetFunction( sal_uInt32 nIndex ) const
     607             : {
     608        2480 :     const ScFuncDesc* pDesc = NULL;
     609        2480 :     if(nIndex < aFunctionList.size())
     610        2480 :         pDesc = aFunctionList.at(nIndex);
     611             : 
     612        2480 :     return pDesc;
     613             : }
     614             : 
     615             : 
     616             : // class ScFunctionCategory:
     617             : 
     618             : 
     619          11 : sal_uInt32 ScFunctionCategory::getCount() const
     620             : {
     621          11 :     return m_pCategory->size();
     622             : }
     623             : 
     624           0 : const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const
     625             : {
     626           0 :     return m_pMgr;
     627             : }
     628             : 
     629          11 : OUString ScFunctionCategory::getName() const
     630             : {
     631          11 :     if ( m_sName.isEmpty() )
     632          11 :         m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1);
     633          11 :     return m_sName;
     634             : }
     635             : 
     636         359 : const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const
     637             : {
     638         359 :     const ScFuncDesc* pDesc = NULL;
     639         359 :     if(_nPos < m_pCategory->size())
     640         359 :         pDesc = m_pCategory->at(_nPos);
     641         359 :     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           1 : ScFunctionMgr::ScFunctionMgr() :
     654           1 :     pFuncList( ScGlobal::GetStarCalcFunctionList() )
     655             : {
     656             :     OSL_ENSURE( pFuncList, "Functionlist not found." );
     657           1 :     sal_uInt32 catCount[MAX_FUNCCAT] = {0};
     658             : 
     659           1 :     aCatLists[0] = new ::std::vector<const ScFuncDesc*>();
     660           1 :     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         360 :     for(const ScFuncDesc* pDesc = pFuncList->First(); pDesc; pDesc = pFuncList->Next())
     665             :     {
     666             :         OSL_ENSURE((pDesc->nCategory) < MAX_FUNCCAT, "Unknown category");
     667         359 :         if ((pDesc->nCategory) < MAX_FUNCCAT)
     668         359 :             ++catCount[pDesc->nCategory];
     669         359 :         aCatLists[0]->push_back(pDesc);
     670             :     }
     671             : 
     672             :     // Sort functions in cumulative category by name
     673           1 :     ::std::sort(aCatLists[0]->begin(), aCatLists[0]->end(), ScFuncDesc::compareByName);
     674             : 
     675             :     // Allocate correct amount of space for categories
     676          12 :     for (sal_uInt16 i = 1; i < MAX_FUNCCAT; ++i)
     677             :     {
     678          11 :         aCatLists[i] = new ::std::vector<const ScFuncDesc*>();
     679          11 :         aCatLists[i]->reserve(catCount[i]);
     680             :     }
     681             : 
     682             :     // Fill categories with the corresponding functions (still sorted by name)
     683         360 :     for(::std::vector<const ScFuncDesc*>::iterator iter = aCatLists[0]->begin(); iter!=aCatLists[0]->end(); ++iter)
     684             :     {
     685         359 :         if (((*iter)->nCategory) < MAX_FUNCCAT)
     686         359 :             aCatLists[(*iter)->nCategory]->push_back(*iter);
     687             :     }
     688             : 
     689             :     // Initialize iterators
     690           1 :     pCurCatListIter = aCatLists[0]->end();
     691           1 :     pCurCatListEnd = aCatLists[0]->end();
     692           1 : }
     693             : 
     694           3 : ScFunctionMgr::~ScFunctionMgr()
     695             : {
     696          13 :     for (sal_uInt16 i = 0; i < MAX_FUNCCAT; ++i)
     697          12 :         delete aCatLists[i];
     698           2 : }
     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           1 : sal_uInt32 ScFunctionMgr::getCount() const
     758             : {
     759           1 :     return MAX_FUNCCAT - 1;
     760             : }
     761             : 
     762          11 : const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const
     763             : {
     764          11 :     formula::IFunctionCategory* pRet = NULL;
     765          11 :     if ( nCategory < (MAX_FUNCCAT-1) )
     766             :     {
     767          11 :          pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all"
     768             :     }
     769          11 :     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          11 : OUString ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber )
     791             : {
     792          11 :     if ( _nCategoryNumber > SC_FUNCGROUP_COUNT )
     793             :     {
     794             :         OSL_FAIL("Invalid category number!");
     795           0 :         return OUString();
     796             :     }
     797             : 
     798          11 :     boost::scoped_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) );
     799          11 :     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        1077 : ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
     825        1077 :  : Resource(aRes)
     826             : {
     827        1077 :     rbSuppressed = (bool)GetNum();
     828        1077 :     pDesc->nCategory = GetNum();
     829        1077 :     pDesc->sHelpId = ReadByteStringRes();
     830        1077 :     pDesc->nArgCount = GetNum();
     831        1077 :     sal_uInt16 nArgs = pDesc->nArgCount;
     832        1077 :     if (nArgs >= PAIRED_VAR_ARGS)
     833           9 :         nArgs -= PAIRED_VAR_ARGS - 2;
     834        1068 :     else if (nArgs >= VAR_ARGS)
     835         132 :         nArgs -= VAR_ARGS - 1;
     836        1077 :     if (nArgs)
     837             :     {
     838        1053 :         pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
     839        3354 :         for (sal_uInt16 i = 0; i < nArgs; ++i)
     840             :         {
     841        2301 :             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        1077 :     sal_uInt16 nSuppressed = GetNum();
     847        1077 :     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        1077 :     pDesc->pFuncName = new OUString( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId())));
     885        1077 :     pDesc->pFuncDesc = new OUString( SC_RESSTR(1) );
     886             : 
     887        1077 :     if (nArgs)
     888             :     {
     889        1053 :         pDesc->maDefArgNames.clear();
     890        1053 :         pDesc->maDefArgNames.resize(nArgs);
     891        1053 :         pDesc->maDefArgDescs.clear();
     892        1053 :         pDesc->maDefArgDescs.resize(nArgs);
     893        3354 :         for (sal_uInt16 i = 0; i < nArgs; ++i)
     894             :         {
     895        2301 :             pDesc->maDefArgNames[i] = SC_RESSTR(2*(i+1)  );
     896        2301 :             pDesc->maDefArgDescs[i] = SC_RESSTR(2*(i+1)+1);
     897             :         }
     898             :     }
     899             : 
     900        1077 :     FreeResource();
     901        1077 : }
     902             : 
     903        6609 : sal_uInt16 ScFuncRes::GetNum()
     904             : {
     905        6609 :     return ReadShortRes();
     906             : }
     907             : 
     908             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10