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

Generated by: LCOV version 1.10