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

Generated by: LCOV version 1.11