diff options
-rw-r--r-- | sc/inc/funcdesc.hxx | 176 | ||||
-rw-r--r-- | sc/source/core/data/funcdesc.cxx | 858 | ||||
-rw-r--r-- | sc/source/core/data/global.cxx | 809 | ||||
-rw-r--r-- | sc/source/core/data/makefile.mk | 1 |
4 files changed, 1001 insertions, 843 deletions
diff --git a/sc/inc/funcdesc.hxx b/sc/inc/funcdesc.hxx index 6187121e7640..ecebacba2006 100644 --- a/sc/inc/funcdesc.hxx +++ b/sc/inc/funcdesc.hxx @@ -34,39 +34,160 @@ * global.cxx */ +#include "scfuncs.hrc" + #include <tools/list.hxx> -#include <tools/string.hxx> #include <formula/IFunctionDescription.hxx> +#include <sal/types.h> +#include <rtl/ustring.hxx> #define MAX_FUNCCAT 12 /* maximum number of categories for functions */ +class ScFuncDesc; +class ScFunctionList; +class ScFunctionCategory; +class ScFunctionMgr; + +/** + Stores and generates human readable descriptions for spreadsheet-functions, + e.g. functions used in formulas in calc +*/ class ScFuncDesc : public formula::IFunctionDescription { public: + ScFuncDesc(); + virtual ~ScFuncDesc(); - virtual ::rtl::OUString getFunctionName() const ; + /** + Clears the object + + Deletes all objets referenced by the pointers in the class, + sets pointers to NULL, and all numerical variables to 0 + */ + void Clear(); + + /** + Fills a mapping with indexes for non-suppressed arguments + + Fills mapping from visible arguments to real arguments, e.g. if of 4 + parameters the second one is suppressed {0,2,3}. For VAR_ARGS + parameters only one element is added to the end of the sequence. + + @param _rArgumens + Vector, which the indices are written to + */ + virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const ; + + /** + Returns the category of the function + + @return the category of the function + */ virtual const formula::IFunctionCategory* getCategory() const ; + + /** + Returns the description of the function + + @return the description of the function, or an empty OUString if there is no description + */ virtual ::rtl::OUString getDescription() const ; - // GetSuppressedArgCount - virtual xub_StrLen getSuppressedArgumentCount() const ; - /** Returns the function signature with parameters from the passed string array. */ + + /** + Returns the function signature with parameters from the passed string array. + + @return function signature with parameters + */ virtual ::rtl::OUString getFormula(const ::std::vector< ::rtl::OUString >& _aArguments) const ; - // GetVisibleArgMapping - /** Returns mapping from visible arguments to real arguments, e.g. if of 4 - parameters the second one is suppressed {0,2,3}. For VAR_ARGS - parameters only one element is added to the end of the sequence. */ - virtual void fillVisibleArgumentMapping(::std::vector<USHORT>& _rArguments) const ; - virtual void initArgumentInfo() const; - /** Returns the full function signature: "FUNCTIONNAME( parameter list )". */ - virtual ::rtl::OUString getSignature() const ; + + /** + Returns the name of the function + + @return the name of the function, or an empty OUString if there is no name + */ + virtual ::rtl::OUString getFunctionName() const ; + + /** + Returns the help id of the function + + @return help id of the function + */ virtual long getHelpId() const ; - // parameter + /** + Returns number of arguments + + @return help id of the function + */ virtual sal_uInt32 getParameterCount() const ; - virtual ::rtl::OUString getParameterName(sal_uInt32 _nPos) const ; + + /** + Returns description of parameter at given position + + @param _nPos + Position of the parameter + + @return OUString description of the parameter + */ virtual ::rtl::OUString getParameterDescription(sal_uInt32 _nPos) const ; + + /** + Returns name of parameter at given position + + @param _nPos + Position of the parameter + + @return OUString name of the parameter + */ + virtual ::rtl::OUString getParameterName(sal_uInt32 _nPos) const ; + + /** + Returns list of all parameter names + + @return OUString containing separated list of all parameter names + */ + ::rtl::OUString GetParamList() const; + + /** + Returns the full function signature + + @return OUString of the form "FUNCTIONNAME( parameter list )" + */ + virtual ::rtl::OUString getSignature() const ; + + /** + Returns the number of non-suppressed arguments + + In case there are variable arguments the number of fixed non-suppressed + arguments plus VAR_ARGS, same as for nArgCount (variable arguments can't + be suppressed). The two functions are equal apart from return type and + name. + + @return number of non-suppressed arguments + */ + sal_uInt16 GetSuppressedArgCount() const; + virtual xub_StrLen getSuppressedArgumentCount() const ; + + /** + Requests function data from AddInCollection + + Logs error message on failure for debugging purposes + */ + virtual void initArgumentInfo() const; + + /** + Returns true if parameter at given position is optional + + @param _nPos + Position of the parameter + + @return true if optional, false if not optional + */ virtual bool isParameterOptional(sal_uInt32 _nPos) const ; + + /** + Stores whether a parameter is optional or suppressed + */ struct ParameterFlags { bool bOptional :1; // Parameter is optional @@ -76,35 +197,22 @@ public: }; - ScFuncDesc(); - virtual ~ScFuncDesc(); - - void Clear(); - - /** Returns a semicolon separated list of all parameter names. */ - ::rtl::OUString GetParamList () const; - - - - /** Returns the number of non-suppressed arguments. In case there are - variable arguments the number of fixed non-suppressed arguments plus - VAR_ARGS, same as for nArgCount (variable arguments can't be - suppressed). */ - USHORT GetSuppressedArgCount() const; ::rtl::OUString *pFuncName; // Function name ::rtl::OUString *pFuncDesc; // Description of function ::rtl::OUString **ppDefArgNames; // Parameter name(s) ::rtl::OUString **ppDefArgDescs; // Description(s) of parameter(s) ParameterFlags *pDefArgFlags; // Flags for each parameter - USHORT nFIndex; // Unique function index - USHORT nCategory; // Function category - USHORT nArgCount; // All parameter count, suppressed and unsuppressed - USHORT nHelpId; // HelpID of function + sal_uInt16 nFIndex; // Unique function index + sal_uInt16 nCategory; // Function category + sal_uInt16 nArgCount; // All parameter count, suppressed and unsuppressed + sal_uInt16 nHelpId; // HelpId of function bool bIncomplete :1; // Incomplete argument info (set for add-in info from configuration) bool bHasSuppressedArgs :1; // Whether there is any suppressed parameter. }; + + //============================================================================ class ScFunctionList diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx new file mode 100644 index 000000000000..d0e29c4dc5aa --- /dev/null +++ b/sc/source/core/data/funcdesc.cxx @@ -0,0 +1,858 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "funcdesc.hxx" + +#include "addincol.hxx" +#include "appoptio.hxx" +#include "callform.hxx" +#include "compiler.hxx" +#include "global.hxx" +#include "sc.hrc" +#include "scmod.hxx" +#include "scresid.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/list.hxx> +#include <tools/rcid.h> +#include <tools/resid.hxx> +#include <tools/string.hxx> +#include <unotools/collatorwrapper.hxx> + +#include <numeric> + +class ScFuncRes : public Resource +{ +public: + ScFuncRes( ResId&, ScFuncDesc*, bool & rbSuppressed ); + +private: + USHORT GetNum(); +}; + + +class ScResourcePublisher : public Resource +{ +private: + void FreeResource() { Resource::FreeResource(); } +public: + ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {} + ~ScResourcePublisher() { FreeResource(); } + BOOL IsAvailableRes( const ResId& rId ) const + { return Resource::IsAvailableRes( rId ); } + +}; + +//======================================================================== +// class ScFuncDesc: + +ScFuncDesc::ScFuncDesc() : + pFuncName (NULL), + pFuncDesc (NULL), + ppDefArgNames (NULL), + ppDefArgDescs (NULL), + pDefArgFlags (NULL), + nFIndex (0), + nCategory (0), + nArgCount (0), + nHelpId (0), + bIncomplete (false), + bHasSuppressedArgs(false) +{} + +//------------------------------------------------------------------------ + +ScFuncDesc::~ScFuncDesc() +{ + Clear(); +} + +//------------------------------------------------------------------------ + +void ScFuncDesc::Clear() +{ + sal_uInt16 nArgs = nArgCount; + if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1; + if (nArgs) + { + for (sal_uInt16 i=0; i<nArgs; i++ ) + { + delete ppDefArgNames[i]; + delete ppDefArgDescs[i]; + } + delete [] ppDefArgNames; + delete [] ppDefArgDescs; + delete [] pDefArgFlags; + } + nArgCount = 0; + ppDefArgNames = NULL; + ppDefArgDescs = NULL; + pDefArgFlags = NULL; + + delete pFuncName; + pFuncName = NULL; + + delete pFuncDesc; + pFuncDesc = NULL; + + nFIndex = 0; + nCategory = 0; + nHelpId = 0; + bIncomplete = false; + bHasSuppressedArgs = false; +} + +//------------------------------------------------------------------------ + +::rtl::OUString ScFuncDesc::GetParamList() const +{ + ::rtl::OUString sep(ScCompiler::GetNativeSymbol(ocSep)); + + ::rtl::OUStringBuffer aSig; + + if ( nArgCount > 0 ) + { + if ( nArgCount < VAR_ARGS ) + { + sal_uInt16 nLastSuppressed = nArgCount; + sal_uInt16 nLastAdded = nArgCount; + for ( sal_uInt16 i=0; i<nArgCount; i++ ) + { + if (pDefArgFlags[i].bSuppress) + nLastSuppressed = i; + else + { + nLastAdded = i; + aSig.append(*(ppDefArgNames[i])); + if ( i != nArgCount-1 ) + { + aSig.append(sep); + aSig.appendAscii( " " ); + } + } + } + // If only suppressed parameters follow the last added parameter, + // remove one "; " + if (nLastSuppressed < nArgCount && nLastAdded < nLastSuppressed && + aSig.getLength() >= 2) + aSig.setLength(aSig.getLength() - 2); + } + else + { + sal_uInt16 nFix = nArgCount - VAR_ARGS; + for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ ) + { + if (!pDefArgFlags[nArg].bSuppress) + { + aSig.append(*(ppDefArgNames[nArg])); + aSig.append(sep); + aSig.appendAscii( " " ); + } + } + /* NOTE: Currently there are no suppressed var args parameters. If + * there were, we'd have to cope with it here and above for the fix + * parameters. For now parameters are always added, so no special + * treatment of a trailing "; " necessary. */ + aSig.append(*(ppDefArgNames[nFix])); + aSig.append(sal_Unicode('1')); + aSig.append(sep); + aSig.append(sal_Unicode(' ')); + aSig.append(*(ppDefArgNames[nFix])); + aSig.append(sal_Unicode('2')); + aSig.append(sep); + aSig.appendAscii(" ... "); + } + } + + return aSig.makeStringAndClear(); +} + +//------------------------------------------------------------------------ + +::rtl::OUString ScFuncDesc::getSignature() const +{ + ::rtl::OUStringBuffer aSig; + + if(pFuncName) + { + aSig.append(*pFuncName); + + ::rtl::OUString aParamList = GetParamList(); + if( aParamList.getLength() ) + { + aSig.appendAscii( "( " ); + aSig.append(aParamList); + // U+00A0 (NBSP) prevents automatic line break + aSig.append( static_cast< sal_Unicode >(0xA0) ); + aSig.appendAscii( ")" ); + } + else + aSig.appendAscii( "()" ); + } + return aSig.makeStringAndClear(); +} + +//------------------------------------------------------------------------ + +::rtl::OUString ScFuncDesc::getFormula( const ::std::vector< ::rtl::OUString >& _aArguments ) const +{ + const String& sep = ScCompiler::GetNativeSymbol(ocSep); + + ::rtl::OUStringBuffer aFormula; + + if(pFuncName) + { + aFormula.append( *pFuncName ); + + aFormula.appendAscii( "(" ); + ::std::vector< ::rtl::OUString >::const_iterator aIter = _aArguments.begin(); + ::std::vector< ::rtl::OUString >::const_iterator aEnd = _aArguments.end(); + + if ( nArgCount > 0 && aIter != aEnd ) + { + BOOL bLastArg = ( aIter->getLength() == 0 ); + + while( aIter != aEnd && !bLastArg ) + { + aFormula.append( *(aIter) ); + if ( aIter != (aEnd-1) ) + { + bLastArg = !( (aIter+1)->getLength() > 0 ); + if ( !bLastArg ) + aFormula.append( sep ); + } + + ++aIter; + } + } + + aFormula.appendAscii( ")" ); + } + return aFormula.makeStringAndClear(); +} + +//------------------------------------------------------------------------ + +sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const +{ + if (!bHasSuppressedArgs || !pDefArgFlags) + return nArgCount; + + sal_uInt16 nArgs = nArgCount; + if (nArgs >= VAR_ARGS) + nArgs -= VAR_ARGS - 1; + sal_uInt16 nCount = nArgs; + for (sal_uInt16 i=0; i < nArgs; ++i) + { + if (pDefArgFlags[i].bSuppress) + --nCount; + } + if (nArgCount >= VAR_ARGS) + nCount += VAR_ARGS - 1; + return nCount; +} + +//------------------------------------------------------------------------ + +::rtl::OUString ScFuncDesc::getFunctionName() const +{ + ::rtl::OUString sRet; + if ( pFuncName ) + sRet = *pFuncName; + return sRet; +} +// ----------------------------------------------------------------------------- +const formula::IFunctionCategory* ScFuncDesc::getCategory() const +{ + return ScGlobal::GetStarCalcFunctionMgr()->getCategory(nCategory); +} +// ----------------------------------------------------------------------------- +::rtl::OUString ScFuncDesc::getDescription() const +{ + ::rtl::OUString sRet; + if ( pFuncDesc ) + sRet = *pFuncDesc; + return sRet; +} +// ----------------------------------------------------------------------------- +// GetSuppressedArgCount +xub_StrLen ScFuncDesc::getSuppressedArgumentCount() const +{ + return GetSuppressedArgCount(); +} +// ----------------------------------------------------------------------------- +// +void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const +{ + if (!bHasSuppressedArgs || !pDefArgFlags) + { + _rArguments.resize( nArgCount); + ::std::iota( _rArguments.begin(), _rArguments.end(), 0); + } + + _rArguments.reserve( nArgCount); + sal_uInt16 nArgs = nArgCount; + if (nArgs >= VAR_ARGS) + nArgs -= VAR_ARGS - 1; + for (sal_uInt16 i=0; i < nArgs; ++i) + { + if (!pDefArgFlags[i].bSuppress) + _rArguments.push_back(i); + } +} +// ----------------------------------------------------------------------------- +void ScFuncDesc::initArgumentInfo() const +{ + // get the full argument description + // (add-in has to be instantiated to get the type information) + + if ( bIncomplete && pFuncName ) + { + ScUnoAddInCollection& rAddIns = *ScGlobal::GetAddInCollection(); + String aIntName = rAddIns.FindFunction( *pFuncName, TRUE ); // pFuncName is upper-case + + if ( aIntName.Len() ) + { + // GetFuncData with bComplete=true loads the component and updates + // the global function list if needed. + + rAddIns.GetFuncData( aIntName, true ); + } + + if ( bIncomplete ) + { + DBG_ERRORFILE( "couldn't initialize add-in function" ); + const_cast<ScFuncDesc*>(this)->bIncomplete = FALSE; // even if there was an error, don't try again + } + } +} +// ----------------------------------------------------------------------------- +long ScFuncDesc::getHelpId() const +{ + return (long)nHelpId; +} +// ----------------------------------------------------------------------------- + +// parameter +sal_uInt32 ScFuncDesc::getParameterCount() const +{ + return nArgCount; +} +// ----------------------------------------------------------------------------- +::rtl::OUString ScFuncDesc::getParameterName(sal_uInt32 _nPos) const +{ + return *(ppDefArgNames[_nPos]); +} +// ----------------------------------------------------------------------------- +::rtl::OUString ScFuncDesc::getParameterDescription(sal_uInt32 _nPos) const +{ + return *(ppDefArgDescs[_nPos]); +} +// ----------------------------------------------------------------------------- +bool ScFuncDesc::isParameterOptional(sal_uInt32 _nPos) const +{ + return pDefArgFlags[_nPos].bOptional; +} +// ----------------------------------------------------------------------------- + + + +//=================================================================== +// class ScFunctionList: +//=================================================================== + +ScFunctionList::ScFunctionList() : + nMaxFuncNameLen ( 0 ) +{ + ScFuncDesc* pDesc = NULL; + xub_StrLen nStrLen = 0; + FuncCollection* pFuncColl; + USHORT i,j; + USHORT nDescBlock[] = + { + RID_SC_FUNCTION_DESCRIPTIONS1, + RID_SC_FUNCTION_DESCRIPTIONS2 + }; + + aFunctionList.Clear(); + + for ( USHORT k = 0; k < SAL_N_ELEMENTS(nDescBlock); k++ ) + { + ::std::auto_ptr<ScResourcePublisher> pBlock( new ScResourcePublisher( ScResId( nDescBlock[k] ) ) ); + // Browse for all possible OpCodes. This is not the fastest method, but + // otherwise the sub resources within the resource blocks and the + // resource blocks themselfs would had to be ordered according to + // OpCodes, which is utopian.. + for (i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++) + { + ScResId aRes(i); + aRes.SetRT(RSC_RESOURCE); + // Sub resource of OpCode available? + if (pBlock->IsAvailableRes(aRes)) + { + pDesc = new ScFuncDesc; + bool bSuppressed = false; + ScFuncRes aSubRes( aRes, pDesc, bSuppressed); + // Instead of dealing with this exceptional case at 1001 places + // we simply don't add an entirely suppressed function to the + // list and delete it. + if (bSuppressed) + delete pDesc; + else + { + pDesc->nFIndex = i; + aFunctionList.Insert( pDesc, LIST_APPEND ); + + nStrLen = (*(pDesc->pFuncName)).getLength(); + if (nStrLen > nMaxFuncNameLen) + nMaxFuncNameLen = nStrLen; + } + } + } + } + + USHORT nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions + + // Auswertung AddIn-Liste + String aDefArgNameValue(RTL_CONSTASCII_USTRINGPARAM("value")); + String aDefArgNameString(RTL_CONSTASCII_USTRINGPARAM("string")); + String aDefArgNameValues(RTL_CONSTASCII_USTRINGPARAM("values")); + String aDefArgNameStrings(RTL_CONSTASCII_USTRINGPARAM("strings")); + String aDefArgNameCells(RTL_CONSTASCII_USTRINGPARAM("cells")); + String aDefArgNameNone(RTL_CONSTASCII_USTRINGPARAM("none")); + String aDefArgDescValue(RTL_CONSTASCII_USTRINGPARAM("a value")); + String aDefArgDescString(RTL_CONSTASCII_USTRINGPARAM("a string")); + String aDefArgDescValues(RTL_CONSTASCII_USTRINGPARAM("array of values")); + String aDefArgDescStrings(RTL_CONSTASCII_USTRINGPARAM("array of strings")); + String aDefArgDescCells(RTL_CONSTASCII_USTRINGPARAM("range of cells")); + String aDefArgDescNone(RTL_CONSTASCII_USTRINGPARAM("none")); + String aArgName, aArgDesc; + pFuncColl = ScGlobal::GetFuncCollection(); + for (i = 0; i < pFuncColl->GetCount(); i++) + { + pDesc = new ScFuncDesc; + FuncData *pAddInFuncData = (FuncData*)pFuncColl->At(i); + USHORT nArgs = pAddInFuncData->GetParamCount() - 1; + pAddInFuncData->GetParamDesc( aArgName, aArgDesc, 0 ); + pDesc->nFIndex = nNextId++; // ??? OpCode vergeben + pDesc->nCategory = ID_FUNCTION_GRP_ADDINS; + pDesc->pFuncName = new ::rtl::OUString(pAddInFuncData->GetInternalName()); + pDesc->pFuncName->toAsciiUpperCase(); + + ::rtl::OUStringBuffer aBuf(aArgDesc); + aBuf.append(sal_Unicode('\n')); + aBuf.appendAscii("( AddIn: "); + aBuf.append(pAddInFuncData->GetModuleName()); + aBuf.appendAscii(" )"); + pDesc->pFuncDesc = new ::rtl::OUString(aBuf.makeStringAndClear()); + + pDesc->nArgCount = nArgs; + if (nArgs) + { + pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs]; + pDesc->ppDefArgNames = new ::rtl::OUString*[nArgs]; + pDesc->ppDefArgDescs = new ::rtl::OUString*[nArgs]; + for (j = 0; j < nArgs; j++) + { + pDesc->pDefArgFlags[j].bOptional = false; + pDesc->pDefArgFlags[j].bSuppress = false; + pAddInFuncData->GetParamDesc( aArgName, aArgDesc, j+1 ); + if ( aArgName.Len() ) + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aArgName ); + else + { + switch (pAddInFuncData->GetParamType(j+1)) + { + case PTR_DOUBLE: + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameValue ); + break; + case PTR_STRING: + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameString ); + break; + case PTR_DOUBLE_ARR: + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameValues ); + break; + case PTR_STRING_ARR: + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameStrings ); + break; + case PTR_CELL_ARR: + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameCells ); + break; + default: + pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameNone ); + break; + } + } + if ( aArgDesc.Len() ) + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aArgDesc ); + else + { + switch (pAddInFuncData->GetParamType(j+1)) + { + case PTR_DOUBLE: + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescValue ); + break; + case PTR_STRING: + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescString ); + break; + case PTR_DOUBLE_ARR: + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescValues ); + break; + case PTR_STRING_ARR: + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescStrings ); + break; + case PTR_CELL_ARR: + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescCells ); + break; + default: + pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescNone ); + break; + } + } + } + } + + aFunctionList.Insert(pDesc, LIST_APPEND); + nStrLen = (*(pDesc->pFuncName)).getLength(); + if ( nStrLen > nMaxFuncNameLen) + nMaxFuncNameLen = nStrLen; + } + + // StarOne AddIns + + ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection(); + long nUnoCount = pUnoAddIns->GetFuncCount(); + for (long nFunc=0; nFunc<nUnoCount; nFunc++) + { + pDesc = new ScFuncDesc; + pDesc->nFIndex = nNextId++; + + if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) ) + { + aFunctionList.Insert(pDesc, LIST_APPEND); + nStrLen = (*(pDesc->pFuncName)).getLength(); + if (nStrLen > nMaxFuncNameLen) + nMaxFuncNameLen = nStrLen; + } + else + delete pDesc; + } +} + +//------------------------------------------------------------------------ + +ScFunctionList::~ScFunctionList() +{ + const ScFuncDesc* pDesc = First(); + while (pDesc) + { + delete pDesc; + pDesc = Next(); + } +} + + + + +// ----------------------------------------------------------------------------- +sal_uInt32 ScFunctionCategory::getCount() const +{ + return m_pCategory->Count(); +} +// ----------------------------------------------------------------------------- +const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const +{ + return m_pMgr; +} +// ----------------------------------------------------------------------------- +::rtl::OUString ScFunctionCategory::getName() const +{ + if ( !m_sName.getLength() ) + m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1); + return m_sName; +} +// ----------------------------------------------------------------------------- +const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const +{ + const ScFuncDesc* pDesc = NULL; + sal_uInt32 i = 0; + for (pDesc = (const ScFuncDesc*)m_pCategory->First(); i < _nPos && pDesc; pDesc = (const ScFuncDesc*)m_pCategory->Next(),++i) + ; + return pDesc; +} +// ----------------------------------------------------------------------------- +sal_uInt32 ScFunctionCategory::getNumber() const +{ + return m_nCategory; +} +// ----------------------------------------------------------------------------- + + +//======================================================================== +// class ScFunctionMgr: + +ScFunctionMgr::ScFunctionMgr() + : pFuncList ( ScGlobal::GetStarCalcFunctionList() ), + pCurCatList ( NULL ) +{ + DBG_ASSERT( pFuncList, "Funktionsliste nicht gefunden." ); + ULONG nCount = pFuncList->GetCount(); + const ScFuncDesc* pDesc; + List* pRootList; + ULONG n; + + for ( USHORT i=0; i<MAX_FUNCCAT; i++ ) // Kategorie-Listen erstellen + aCatLists[i] = new List; + + pRootList = aCatLists[0]; // Gesamtliste ("Alle") erstellen + CollatorWrapper* pCaseCollator = ScGlobal::GetCaseCollator(); + for ( n=0; n<nCount; n++ ) + { + ULONG nTmpCnt=0; + pDesc = pFuncList->GetFunction(n); + for (nTmpCnt = 0; nTmpCnt < n; nTmpCnt++) + { + // ist zwar case-sensitiv, aber Umlaute muessen richtig einsortiert werden + + const ScFuncDesc* pTmpDesc = (const ScFuncDesc*)pRootList->GetObject(nTmpCnt); + if ( pCaseCollator->compareString(*pDesc->pFuncName, *pTmpDesc->pFuncName ) == COMPARE_LESS ) + break; + } + pRootList->Insert((void*)pDesc, nTmpCnt); // Einsortieren + } + + for ( n=0; n<nCount; n++ ) // in Gruppenlisten kopieren + { + pDesc = (const ScFuncDesc*)pRootList->GetObject(n); + DBG_ASSERT((pDesc->nCategory) < MAX_FUNCCAT, "Unbekannte Kategorie"); + if ((pDesc->nCategory) < MAX_FUNCCAT) + aCatLists[pDesc->nCategory]->Insert((void*)pDesc, LIST_APPEND); + } +} + +//------------------------------------------------------------------------ + +ScFunctionMgr::~ScFunctionMgr() +{ + for (USHORT i = 0; i < MAX_FUNCCAT; i++) + delete aCatLists[i]; +// delete pFuncList; // Macht spaeter die App +} + +//------------------------------------------------------------------------ + +const ScFuncDesc* ScFunctionMgr::Get( const ::rtl::OUString& rFName ) const +{ + const ScFuncDesc* pDesc = NULL; + if (rFName.getLength() <= pFuncList->GetMaxFuncNameLen()) + for (pDesc = First(0); pDesc; pDesc = Next()) + if (rFName.equalsIgnoreAsciiCase(*pDesc->pFuncName)) + break; + return pDesc; +} + +//------------------------------------------------------------------------ + +const ScFuncDesc* ScFunctionMgr::Get( USHORT nFIndex ) const +{ + const ScFuncDesc* pDesc; + for (pDesc = First(0); pDesc; pDesc = Next()) + if (pDesc->nFIndex == nFIndex) + break; + return pDesc; +} + +//------------------------------------------------------------------------ + +const ScFuncDesc* ScFunctionMgr::First( USHORT nCategory ) const +{ + DBG_ASSERT( nCategory < MAX_FUNCCAT, "Unbekannte Kategorie" ); + + if ( nCategory < MAX_FUNCCAT ) + { + pCurCatList = aCatLists[nCategory]; + return (const ScFuncDesc*)pCurCatList->First(); + } + else + { + pCurCatList = NULL; + return NULL; + } +} + +//------------------------------------------------------------------------ + +const ScFuncDesc* ScFunctionMgr::Next() const +{ + if ( pCurCatList ) + return (const ScFuncDesc*)pCurCatList->Next(); + else + return NULL; +} +sal_uInt32 ScFunctionMgr::getCount() const +{ + return MAX_FUNCCAT - 1; +} +const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const +{ + formula::IFunctionCategory* pRet = NULL; + if ( nCategory < (MAX_FUNCCAT-1) ) + { + pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all" + } + return pRet; +} +// ----------------------------------------------------------------------------- +const formula::IFunctionDescription* ScFunctionMgr::getFunctionByName(const ::rtl::OUString& _sFunctionName) const +{ + return Get(_sFunctionName); +} +// ----------------------------------------------------------------------------- +void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const +{ +#define LRU_MAX 10 + + const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions(); + USHORT nLRUFuncCount = Min( rAppOpt.GetLRUFuncListCount(), (USHORT)LRU_MAX ); + USHORT* pLRUListIds = rAppOpt.GetLRUFuncList(); + + if ( pLRUListIds ) + { + for ( USHORT i=0; i<nLRUFuncCount; i++ ) + _rLastRUFunctions.push_back( Get( pLRUListIds[i] ) ); + } +} +// ----------------------------------------------------------------------------- +::rtl::OUString ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber ) +{ + if ( _nCategoryNumber > SC_FUNCGROUP_COUNT ) + { + DBG_ERROR("Invalid category number!"); + return ::rtl::OUString(); + } + + ::std::auto_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) ); + return ResId::toString(ScResId((USHORT)_nCategoryNumber)); +} +sal_Unicode ScFunctionMgr::getSingleToken(const formula::IFunctionManager::EToken _eToken) const +{ + switch(_eToken) + { + case eOk: + return ScCompiler::GetNativeSymbol(ocOpen).GetChar(0); + case eClose: + return ScCompiler::GetNativeSymbol(ocClose).GetChar(0); + case eSep: + return ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + case eArrayOpen: + return ScCompiler::GetNativeSymbol(ocArrayOpen).GetChar(0); + case eArrayClose: + return ScCompiler::GetNativeSymbol(ocArrayClose).GetChar(0); + } + return 0; +} + +ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed ) + : Resource(aRes) +{ + rbSuppressed = (bool)GetNum(); + pDesc->nCategory = GetNum(); + pDesc->nHelpId = GetNum() + 32768; //! Hack, see scfuncs.src + pDesc->nArgCount = GetNum(); + USHORT nArgs = pDesc->nArgCount; + if (nArgs >= VAR_ARGS) + nArgs -= VAR_ARGS - 1; + if (nArgs) + { + pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs]; + for (USHORT i = 0; i < nArgs; i++) + { + pDesc->pDefArgFlags[i].bOptional = (bool)GetNum(); + } + } + // Need to read the value from the resource even if nArgs==0 to advance the + // resource position pointer, so this can't be in the if(nArgs) block above. + USHORT nSuppressed = GetNum(); + if (nSuppressed) + { + if (nSuppressed > nArgs) + { + DBG_ERROR3( "ScFuncRes: suppressed parameters count mismatch on OpCode %u: suppressed %d > params %d", + aRes.GetId(), (int)nSuppressed, (int)nArgs); + nSuppressed = nArgs; // sanitize + } + for (USHORT i=0; i < nSuppressed; ++i) + { + USHORT nParam = GetNum(); + if (nParam < nArgs) + { + if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1) + { + DBG_ERROR3( "ScFuncRes: VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d == arg %d-1", + aRes.GetId(), (int)nParam, (int)nArgs); + } + else + { + pDesc->pDefArgFlags[nParam].bSuppress = true; + pDesc->bHasSuppressedArgs = true; + } + } + else + { + DBG_ERROR3( "ScFuncRes: suppressed parameter exceeds count on OpCode %u: param %d >= args %d", + aRes.GetId(), (int)nParam, (int)nArgs); + } + } + } + + pDesc->pFuncName = new ::rtl::OUString( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId()))); + pDesc->pFuncDesc = new ::rtl::OUString( ResId::toString(ScResId(1))); + + if (nArgs) + { + pDesc->ppDefArgNames = new ::rtl::OUString*[nArgs]; + pDesc->ppDefArgDescs = new ::rtl::OUString*[nArgs]; + for (USHORT i = 0; i < nArgs; i++) + { + pDesc->ppDefArgNames[i] = new ::rtl::OUString(ResId::toString(ScResId(2*(i+1) ))); + pDesc->ppDefArgDescs[i] = new ::rtl::OUString(ResId::toString(ScResId(2*(i+1)+1))); + } + } + + FreeResource(); +} + +//------------------------------------------------------------------------ + +USHORT ScFuncRes::GetNum() +{ + return ReadShortRes(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx index e64b5b5164bb..e768e7c6bd24 100644 --- a/sc/source/core/data/global.cxx +++ b/sc/source/core/data/global.cxx @@ -1096,818 +1096,9 @@ void ScGlobal::AddLanguage( SfxItemSet& rSet, SvNumberFormatter& rFormatter ) } - - - -//=================================================================== -// class ScFunctionList: -//=================================================================== - -//=================================================================== -// class ScFuncRes -// fuer temporaere Objekte zum Holen der Resourcen - -class ScFuncRes : public Resource -{ -public: - ScFuncRes( ResId&, ScFuncDesc*, bool & rbSuppressed ); - -private: - USHORT GetNum(); -}; - //-------------------------------------------------------------------- -ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed ) - : Resource(aRes) -{ - rbSuppressed = (bool)GetNum(); - pDesc->nCategory = GetNum(); - pDesc->nHelpId = GetNum() + 32768; //! Hack, see scfuncs.src - pDesc->nArgCount = GetNum(); - USHORT nArgs = pDesc->nArgCount; - if (nArgs >= VAR_ARGS) - nArgs -= VAR_ARGS - 1; - if (nArgs) - { - pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs]; - for (USHORT i = 0; i < nArgs; i++) - { - pDesc->pDefArgFlags[i].bOptional = (bool)GetNum(); - } - } - // Need to read the value from the resource even if nArgs==0 to advance the - // resource position pointer, so this can't be in the if(nArgs) block above. - USHORT nSuppressed = GetNum(); - if (nSuppressed) - { - if (nSuppressed > nArgs) - { - DBG_ERROR3( "ScFuncRes: suppressed parameters count mismatch on OpCode %u: suppressed %d > params %d", - aRes.GetId(), (int)nSuppressed, (int)nArgs); - nSuppressed = nArgs; // sanitize - } - for (USHORT i=0; i < nSuppressed; ++i) - { - USHORT nParam = GetNum(); - if (nParam < nArgs) - { - if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1) - { - DBG_ERROR3( "ScFuncRes: VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d == arg %d-1", - aRes.GetId(), (int)nParam, (int)nArgs); - } - else - { - pDesc->pDefArgFlags[nParam].bSuppress = true; - pDesc->bHasSuppressedArgs = true; - } - } - else - { - DBG_ERROR3( "ScFuncRes: suppressed parameter exceeds count on OpCode %u: param %d >= args %d", - aRes.GetId(), (int)nParam, (int)nArgs); - } - } - } - - pDesc->pFuncName = new ::rtl::OUString( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId()))); - pDesc->pFuncDesc = new ::rtl::OUString( ResId::toString(ScResId(1))); - - if (nArgs) - { - pDesc->ppDefArgNames = new ::rtl::OUString*[nArgs]; - pDesc->ppDefArgDescs = new ::rtl::OUString*[nArgs]; - for (USHORT i = 0; i < nArgs; i++) - { - pDesc->ppDefArgNames[i] = new ::rtl::OUString(ResId::toString(ScResId(2*(i+1) ))); - pDesc->ppDefArgDescs[i] = new ::rtl::OUString(ResId::toString(ScResId(2*(i+1)+1))); - } - } - - FreeResource(); -} - -//------------------------------------------------------------------------ - -USHORT ScFuncRes::GetNum() -{ - return ReadShortRes(); -} - -//========================================================================= - -// um an die protected von Resource ranzukommen -class ScResourcePublisher : public Resource -{ -private: - void FreeResource() { Resource::FreeResource(); } -public: - ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {} - ~ScResourcePublisher() { FreeResource(); } - BOOL IsAvailableRes( const ResId& rId ) const - { return Resource::IsAvailableRes( rId ); } - -}; - - -ScFunctionList::ScFunctionList() : - nMaxFuncNameLen ( 0 ) -{ - ScFuncDesc* pDesc = NULL; - xub_StrLen nStrLen = 0; - FuncCollection* pFuncColl; - USHORT i,j; - USHORT nDescBlock[] = - { - RID_SC_FUNCTION_DESCRIPTIONS1, - RID_SC_FUNCTION_DESCRIPTIONS2 - }; - - aFunctionList.Clear(); - - for ( USHORT k = 0; k < SAL_N_ELEMENTS(nDescBlock); k++ ) - { - ::std::auto_ptr<ScResourcePublisher> pBlock( new ScResourcePublisher( ScResId( nDescBlock[k] ) ) ); - // Browse for all possible OpCodes. This is not the fastest method, but - // otherwise the sub resources within the resource blocks and the - // resource blocks themselfs would had to be ordered according to - // OpCodes, which is utopian.. - for (i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++) - { - ScResId aRes(i); - aRes.SetRT(RSC_RESOURCE); - // Sub resource of OpCode available? - if (pBlock->IsAvailableRes(aRes)) - { - pDesc = new ScFuncDesc; - bool bSuppressed = false; - ScFuncRes aSubRes( aRes, pDesc, bSuppressed); - // Instead of dealing with this exceptional case at 1001 places - // we simply don't add an entirely suppressed function to the - // list and delete it. - if (bSuppressed) - delete pDesc; - else - { - pDesc->nFIndex = i; - aFunctionList.Insert( pDesc, LIST_APPEND ); - - nStrLen = (*(pDesc->pFuncName)).getLength(); - if (nStrLen > nMaxFuncNameLen) - nMaxFuncNameLen = nStrLen; - } - } - } - } - - USHORT nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions - - // Auswertung AddIn-Liste - String aDefArgNameValue(RTL_CONSTASCII_USTRINGPARAM("value")); - String aDefArgNameString(RTL_CONSTASCII_USTRINGPARAM("string")); - String aDefArgNameValues(RTL_CONSTASCII_USTRINGPARAM("values")); - String aDefArgNameStrings(RTL_CONSTASCII_USTRINGPARAM("strings")); - String aDefArgNameCells(RTL_CONSTASCII_USTRINGPARAM("cells")); - String aDefArgNameNone(RTL_CONSTASCII_USTRINGPARAM("none")); - String aDefArgDescValue(RTL_CONSTASCII_USTRINGPARAM("a value")); - String aDefArgDescString(RTL_CONSTASCII_USTRINGPARAM("a string")); - String aDefArgDescValues(RTL_CONSTASCII_USTRINGPARAM("array of values")); - String aDefArgDescStrings(RTL_CONSTASCII_USTRINGPARAM("array of strings")); - String aDefArgDescCells(RTL_CONSTASCII_USTRINGPARAM("range of cells")); - String aDefArgDescNone(RTL_CONSTASCII_USTRINGPARAM("none")); - String aArgName, aArgDesc; - pFuncColl = ScGlobal::GetFuncCollection(); - for (i = 0; i < pFuncColl->GetCount(); i++) - { - pDesc = new ScFuncDesc; - FuncData *pAddInFuncData = (FuncData*)pFuncColl->At(i); - USHORT nArgs = pAddInFuncData->GetParamCount() - 1; - pAddInFuncData->GetParamDesc( aArgName, aArgDesc, 0 ); - pDesc->nFIndex = nNextId++; // ??? OpCode vergeben - pDesc->nCategory = ID_FUNCTION_GRP_ADDINS; - pDesc->pFuncName = new ::rtl::OUString(pAddInFuncData->GetInternalName()); - pDesc->pFuncName->toAsciiUpperCase(); - - OUStringBuffer aBuf(aArgDesc); - aBuf.append(sal_Unicode('\n')); - aBuf.appendAscii("( AddIn: "); - aBuf.append(pAddInFuncData->GetModuleName()); - aBuf.appendAscii(" )"); - pDesc->pFuncDesc = new OUString(aBuf.makeStringAndClear()); - - pDesc->nArgCount = nArgs; - if (nArgs) - { - pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs]; - pDesc->ppDefArgNames = new ::rtl::OUString*[nArgs]; - pDesc->ppDefArgDescs = new ::rtl::OUString*[nArgs]; - for (j = 0; j < nArgs; j++) - { - pDesc->pDefArgFlags[j].bOptional = false; - pDesc->pDefArgFlags[j].bSuppress = false; - pAddInFuncData->GetParamDesc( aArgName, aArgDesc, j+1 ); - if ( aArgName.Len() ) - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aArgName ); - else - { - switch (pAddInFuncData->GetParamType(j+1)) - { - case PTR_DOUBLE: - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameValue ); - break; - case PTR_STRING: - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameString ); - break; - case PTR_DOUBLE_ARR: - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameValues ); - break; - case PTR_STRING_ARR: - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameStrings ); - break; - case PTR_CELL_ARR: - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameCells ); - break; - default: - pDesc->ppDefArgNames[j] = new ::rtl::OUString( aDefArgNameNone ); - break; - } - } - if ( aArgDesc.Len() ) - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aArgDesc ); - else - { - switch (pAddInFuncData->GetParamType(j+1)) - { - case PTR_DOUBLE: - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescValue ); - break; - case PTR_STRING: - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescString ); - break; - case PTR_DOUBLE_ARR: - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescValues ); - break; - case PTR_STRING_ARR: - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescStrings ); - break; - case PTR_CELL_ARR: - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescCells ); - break; - default: - pDesc->ppDefArgDescs[j] = new ::rtl::OUString( aDefArgDescNone ); - break; - } - } - } - } - - aFunctionList.Insert(pDesc, LIST_APPEND); - nStrLen = (*(pDesc->pFuncName)).getLength(); - if ( nStrLen > nMaxFuncNameLen) - nMaxFuncNameLen = nStrLen; - } - - // StarOne AddIns - - ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection(); - long nUnoCount = pUnoAddIns->GetFuncCount(); - for (long nFunc=0; nFunc<nUnoCount; nFunc++) - { - pDesc = new ScFuncDesc; - pDesc->nFIndex = nNextId++; - - if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) ) - { - aFunctionList.Insert(pDesc, LIST_APPEND); - nStrLen = (*(pDesc->pFuncName)).getLength(); - if (nStrLen > nMaxFuncNameLen) - nMaxFuncNameLen = nStrLen; - } - else - delete pDesc; - } -} - -//------------------------------------------------------------------------ - -ScFunctionList::~ScFunctionList() -{ - const ScFuncDesc* pDesc = First(); - while (pDesc) - { - delete pDesc; - pDesc = Next(); - } -} - - -//======================================================================== -// class ScFuncDesc: - -ScFuncDesc::ScFuncDesc() : - pFuncName (NULL), - pFuncDesc (NULL), - ppDefArgNames (NULL), - ppDefArgDescs (NULL), - pDefArgFlags (NULL), - nFIndex (0), - nCategory (0), - nArgCount (0), - nHelpId (0), - bIncomplete (false), - bHasSuppressedArgs(false) -{} - -//------------------------------------------------------------------------ - -ScFuncDesc::~ScFuncDesc() -{ - Clear(); -} - -//------------------------------------------------------------------------ - -void ScFuncDesc::Clear() -{ - USHORT nArgs = nArgCount; - if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1; - if (nArgs) - { - for (USHORT i=0; i<nArgs; i++ ) - { - delete ppDefArgNames[i]; - delete ppDefArgDescs[i]; - } - delete [] ppDefArgNames; - delete [] ppDefArgDescs; - delete [] pDefArgFlags; - } - nArgCount = 0; - ppDefArgNames = NULL; - ppDefArgDescs = NULL; - pDefArgFlags = NULL; - - delete pFuncName; - pFuncName = NULL; - - delete pFuncDesc; - pFuncDesc = NULL; - - nFIndex = 0; - nCategory = 0; - nHelpId = 0; - bIncomplete = false; - bHasSuppressedArgs = false; -} - -//------------------------------------------------------------------------ - -::rtl::OUString ScFuncDesc::GetParamList() const -{ - ::rtl::OUString sep(ScCompiler::GetNativeSymbol(ocSep)); - - ::rtl::OUStringBuffer aSig; - - if ( nArgCount > 0 ) - { - if ( nArgCount < VAR_ARGS ) - { - USHORT nLastSuppressed = nArgCount; - USHORT nLastAdded = nArgCount; - for ( USHORT i=0; i<nArgCount; i++ ) - { - if (pDefArgFlags[i].bSuppress) - nLastSuppressed = i; - else - { - nLastAdded = i; - aSig.append(*(ppDefArgNames[i])); - if ( i != nArgCount-1 ) - { - aSig.append(sep); - aSig.appendAscii( " " ); - } - } - } - // If only suppressed parameters follow the last added parameter, - // remove one "; " - if (nLastSuppressed < nArgCount && nLastAdded < nLastSuppressed && - aSig.getLength() >= 2) - aSig.setLength(aSig.getLength() - 2); - } - else - { - USHORT nFix = nArgCount - VAR_ARGS; - for ( USHORT nArg = 0; nArg < nFix; nArg++ ) - { - if (!pDefArgFlags[nArg].bSuppress) - { - aSig.append(*(ppDefArgNames[nArg])); - aSig.append(sep); - aSig.appendAscii( " " ); - } - } - /* NOTE: Currently there are no suppressed var args parameters. If - * there were, we'd have to cope with it here and above for the fix - * parameters. For now parameters are always added, so no special - * treatment of a trailing "; " necessary. */ - aSig.append(*(ppDefArgNames[nFix])); - aSig.append(sal_Unicode('1')); - aSig.append(sep); - aSig.append(sal_Unicode(' ')); - aSig.append(*(ppDefArgNames[nFix])); - aSig.append(sal_Unicode('2')); - aSig.append(sep); - aSig.appendAscii(" ... "); - } - } - - return aSig.makeStringAndClear(); -} - -//------------------------------------------------------------------------ - -::rtl::OUString ScFuncDesc::getSignature() const -{ - ::rtl::OUStringBuffer aSig; - - if(pFuncName) - { - aSig.append(*pFuncName); - - ::rtl::OUString aParamList = GetParamList(); - if( aParamList.getLength() ) - { - aSig.appendAscii( "( " ); - aSig.append(aParamList); - // U+00A0 (NBSP) prevents automatic line break - aSig.append( static_cast< sal_Unicode >(0xA0) ); - aSig.appendAscii( ")" ); - } - else - aSig.appendAscii( "()" ); - } - return aSig.makeStringAndClear(); -} - -//------------------------------------------------------------------------ - -::rtl::OUString ScFuncDesc::getFormula( const ::std::vector< ::rtl::OUString >& _aArguments ) const -{ - const String& sep = ScCompiler::GetNativeSymbol(ocSep); - - ::rtl::OUStringBuffer aFormula; - - if(pFuncName) - { - aFormula.append( *pFuncName ); - - aFormula.appendAscii( "(" ); - ::std::vector< ::rtl::OUString >::const_iterator aIter = _aArguments.begin(); - ::std::vector< ::rtl::OUString >::const_iterator aEnd = _aArguments.end(); - - if ( nArgCount > 0 && aIter != aEnd ) - { - BOOL bLastArg = ( aIter->getLength() == 0 ); - - while( aIter != aEnd && !bLastArg ) - { - aFormula.append( *(aIter) ); - if ( aIter != (aEnd-1) ) - { - bLastArg = !( (aIter+1)->getLength() > 0 ); - if ( !bLastArg ) - aFormula.append( sep ); - } - - ++aIter; - } - } - - aFormula.appendAscii( ")" ); - } - return aFormula.makeStringAndClear(); -} - -//------------------------------------------------------------------------ - -USHORT ScFuncDesc::GetSuppressedArgCount() const -{ - if (!bHasSuppressedArgs || !pDefArgFlags) - return nArgCount; - - USHORT nArgs = nArgCount; - if (nArgs >= VAR_ARGS) - nArgs -= VAR_ARGS - 1; - USHORT nCount = nArgs; - for (USHORT i=0; i < nArgs; ++i) - { - if (pDefArgFlags[i].bSuppress) - --nCount; - } - if (nArgCount >= VAR_ARGS) - nCount += VAR_ARGS - 1; - return nCount; -} - -//------------------------------------------------------------------------ - -::rtl::OUString ScFuncDesc::getFunctionName() const -{ - ::rtl::OUString sRet; - if ( pFuncName ) - sRet = *pFuncName; - return sRet; -} -// ----------------------------------------------------------------------------- -const formula::IFunctionCategory* ScFuncDesc::getCategory() const -{ - return ScGlobal::GetStarCalcFunctionMgr()->getCategory(nCategory); -} -// ----------------------------------------------------------------------------- -::rtl::OUString ScFuncDesc::getDescription() const -{ - ::rtl::OUString sRet; - if ( pFuncDesc ) - sRet = *pFuncDesc; - return sRet; -} -// ----------------------------------------------------------------------------- -// GetSuppressedArgCount -xub_StrLen ScFuncDesc::getSuppressedArgumentCount() const -{ - return GetSuppressedArgCount(); -} -// ----------------------------------------------------------------------------- -// -void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<USHORT>& _rArguments) const -{ - if (!bHasSuppressedArgs || !pDefArgFlags) - { - _rArguments.resize( nArgCount); - ::std::iota( _rArguments.begin(), _rArguments.end(), 0); - } - - _rArguments.reserve( nArgCount); - USHORT nArgs = nArgCount; - if (nArgs >= VAR_ARGS) - nArgs -= VAR_ARGS - 1; - for (USHORT i=0; i < nArgs; ++i) - { - if (!pDefArgFlags[i].bSuppress) - _rArguments.push_back(i); - } -} -// ----------------------------------------------------------------------------- -void ScFuncDesc::initArgumentInfo() const -{ - // get the full argument description - // (add-in has to be instantiated to get the type information) - - if ( bIncomplete && pFuncName ) - { - ScUnoAddInCollection& rAddIns = *ScGlobal::GetAddInCollection(); - String aIntName = rAddIns.FindFunction( *pFuncName, TRUE ); // pFuncName is upper-case - - if ( aIntName.Len() ) - { - // GetFuncData with bComplete=true loads the component and updates - // the global function list if needed. - - rAddIns.GetFuncData( aIntName, true ); - } - - if ( bIncomplete ) - { - DBG_ERRORFILE( "couldn't initialize add-in function" ); - const_cast<ScFuncDesc*>(this)->bIncomplete = FALSE; // even if there was an error, don't try again - } - } -} -// ----------------------------------------------------------------------------- -long ScFuncDesc::getHelpId() const -{ - return nHelpId; -} -// ----------------------------------------------------------------------------- - -// parameter -sal_uInt32 ScFuncDesc::getParameterCount() const -{ - return nArgCount; -} -// ----------------------------------------------------------------------------- -::rtl::OUString ScFuncDesc::getParameterName(sal_uInt32 _nPos) const -{ - return *(ppDefArgNames[_nPos]); -} -// ----------------------------------------------------------------------------- -::rtl::OUString ScFuncDesc::getParameterDescription(sal_uInt32 _nPos) const -{ - return *(ppDefArgDescs[_nPos]); -} -// ----------------------------------------------------------------------------- -bool ScFuncDesc::isParameterOptional(sal_uInt32 _nPos) const -{ - return pDefArgFlags[_nPos].bOptional; -} -// ----------------------------------------------------------------------------- -//======================================================================== -// class ScFunctionMgr: - -ScFunctionMgr::ScFunctionMgr() - : pFuncList ( ScGlobal::GetStarCalcFunctionList() ), - pCurCatList ( NULL ) -{ - DBG_ASSERT( pFuncList, "Funktionsliste nicht gefunden." ); - ULONG nCount = pFuncList->GetCount(); - const ScFuncDesc* pDesc; - List* pRootList; - ULONG n; - - for ( USHORT i=0; i<MAX_FUNCCAT; i++ ) // Kategorie-Listen erstellen - aCatLists[i] = new List; - - pRootList = aCatLists[0]; // Gesamtliste ("Alle") erstellen - CollatorWrapper* pCaseCollator = ScGlobal::GetCaseCollator(); - for ( n=0; n<nCount; n++ ) - { - ULONG nTmpCnt=0; - pDesc = pFuncList->GetFunction(n); - for (nTmpCnt = 0; nTmpCnt < n; nTmpCnt++) - { - // ist zwar case-sensitiv, aber Umlaute muessen richtig einsortiert werden - - const ScFuncDesc* pTmpDesc = (const ScFuncDesc*)pRootList->GetObject(nTmpCnt); - if ( pCaseCollator->compareString(*pDesc->pFuncName, *pTmpDesc->pFuncName ) == COMPARE_LESS ) - break; - } - pRootList->Insert((void*)pDesc, nTmpCnt); // Einsortieren - } - - for ( n=0; n<nCount; n++ ) // in Gruppenlisten kopieren - { - pDesc = (const ScFuncDesc*)pRootList->GetObject(n); - DBG_ASSERT((pDesc->nCategory) < MAX_FUNCCAT, "Unbekannte Kategorie"); - if ((pDesc->nCategory) < MAX_FUNCCAT) - aCatLists[pDesc->nCategory]->Insert((void*)pDesc, LIST_APPEND); - } -} -//------------------------------------------------------------------------ - -ScFunctionMgr::~ScFunctionMgr() -{ - for (USHORT i = 0; i < MAX_FUNCCAT; i++) - delete aCatLists[i]; -// delete pFuncList; // Macht spaeter die App -} - -//------------------------------------------------------------------------ - -const ScFuncDesc* ScFunctionMgr::Get( const ::rtl::OUString& rFName ) const -{ - const ScFuncDesc* pDesc = NULL; - if (rFName.getLength() <= pFuncList->GetMaxFuncNameLen()) - for (pDesc = First(0); pDesc; pDesc = Next()) - if (rFName.equalsIgnoreAsciiCase(*pDesc->pFuncName)) - break; - return pDesc; -} - -//------------------------------------------------------------------------ - -const ScFuncDesc* ScFunctionMgr::Get( USHORT nFIndex ) const -{ - const ScFuncDesc* pDesc; - for (pDesc = First(0); pDesc; pDesc = Next()) - if (pDesc->nFIndex == nFIndex) - break; - return pDesc; -} - -//------------------------------------------------------------------------ - -const ScFuncDesc* ScFunctionMgr::First( USHORT nCategory ) const -{ - DBG_ASSERT( nCategory < MAX_FUNCCAT, "Unbekannte Kategorie" ); - - if ( nCategory < MAX_FUNCCAT ) - { - pCurCatList = aCatLists[nCategory]; - return (const ScFuncDesc*)pCurCatList->First(); - } - else - { - pCurCatList = NULL; - return NULL; - } -} - -//------------------------------------------------------------------------ - -const ScFuncDesc* ScFunctionMgr::Next() const -{ - if ( pCurCatList ) - return (const ScFuncDesc*)pCurCatList->Next(); - else - return NULL; -} -sal_uInt32 ScFunctionMgr::getCount() const -{ - return MAX_FUNCCAT - 1; -} -const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const -{ - formula::IFunctionCategory* pRet = NULL; - if ( nCategory < (MAX_FUNCCAT-1) ) - { - pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all" - } - return pRet; -} -// ----------------------------------------------------------------------------- -const formula::IFunctionDescription* ScFunctionMgr::getFunctionByName(const ::rtl::OUString& _sFunctionName) const -{ - return Get(_sFunctionName); -} -// ----------------------------------------------------------------------------- -void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const -{ -#define LRU_MAX 10 - - const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions(); - USHORT nLRUFuncCount = Min( rAppOpt.GetLRUFuncListCount(), (USHORT)LRU_MAX ); - USHORT* pLRUListIds = rAppOpt.GetLRUFuncList(); - - if ( pLRUListIds ) - { - for ( USHORT i=0; i<nLRUFuncCount; i++ ) - _rLastRUFunctions.push_back( Get( pLRUListIds[i] ) ); - } -} -// ----------------------------------------------------------------------------- -::rtl::OUString ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber ) -{ - if ( _nCategoryNumber > SC_FUNCGROUP_COUNT ) - { - DBG_ERROR("Invalid category number!"); - return ::rtl::OUString(); - } - - ::std::auto_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) ); - return ResId::toString(ScResId((USHORT)_nCategoryNumber)); -} -sal_Unicode ScFunctionMgr::getSingleToken(const formula::IFunctionManager::EToken _eToken) const -{ - switch(_eToken) - { - case eOk: - return ScCompiler::GetNativeSymbol(ocOpen).GetChar(0); - case eClose: - return ScCompiler::GetNativeSymbol(ocClose).GetChar(0); - case eSep: - return ScCompiler::GetNativeSymbol(ocSep).GetChar(0); - case eArrayOpen: - return ScCompiler::GetNativeSymbol(ocArrayOpen).GetChar(0); - case eArrayClose: - return ScCompiler::GetNativeSymbol(ocArrayClose).GetChar(0); - } - return 0; -} -// ----------------------------------------------------------------------------- -sal_uInt32 ScFunctionCategory::getCount() const -{ - return m_pCategory->Count(); -} -// ----------------------------------------------------------------------------- -const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const -{ - return m_pMgr; -} -// ----------------------------------------------------------------------------- -::rtl::OUString ScFunctionCategory::getName() const -{ - if ( !m_sName.getLength() ) - m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1); - return m_sName; -} -// ----------------------------------------------------------------------------- -const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const -{ - const ScFuncDesc* pDesc = NULL; - sal_uInt32 i = 0; - for (pDesc = (const ScFuncDesc*)m_pCategory->First(); i < _nPos && pDesc; pDesc = (const ScFuncDesc*)m_pCategory->Next(),++i) - ; - return pDesc; -} -// ----------------------------------------------------------------------------- -sal_uInt32 ScFunctionCategory::getNumber() const -{ - return m_nCategory; -} -// ----------------------------------------------------------------------------- //------------------------------------------------------------------------ diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk index 8ad87c34c1f8..efb3fca9e14e 100644 --- a/sc/source/core/data/makefile.mk +++ b/sc/source/core/data/makefile.mk @@ -90,6 +90,7 @@ EXCEPTIONSFILES= \ $(SLO)$/drawpage.obj \ $(SLO)$/drwlayer.obj \ $(SLO)$/fillinfo.obj \ + $(SLO)$/funcdesc.obj \ $(SLO)$/global.obj \ $(SLO)$/global2.obj \ $(SLO)$/globalx.obj \ |