summaryrefslogtreecommitdiffstats
path: root/formula/source/ui/dlg/FormulaHelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'formula/source/ui/dlg/FormulaHelper.cxx')
-rw-r--r--formula/source/ui/dlg/FormulaHelper.cxx417
1 files changed, 417 insertions, 0 deletions
diff --git a/formula/source/ui/dlg/FormulaHelper.cxx b/formula/source/ui/dlg/FormulaHelper.cxx
new file mode 100644
index 000000000..15d3b411a
--- /dev/null
+++ b/formula/source/ui/dlg/FormulaHelper.cxx
@@ -0,0 +1,417 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+
+#include <formula/formulahelper.hxx>
+#include <formula/IFunctionDescription.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/syslocale.hxx>
+
+namespace formula
+{
+
+ namespace
+ {
+
+ class OEmptyFunctionDescription : public IFunctionDescription
+ {
+ public:
+ OEmptyFunctionDescription(){}
+ virtual ~OEmptyFunctionDescription(){}
+
+ virtual OUString getFunctionName() const override { return OUString(); }
+ virtual const IFunctionCategory* getCategory() const override { return nullptr; }
+ virtual OUString getDescription() const override { return OUString(); }
+ virtual sal_Int32 getSuppressedArgumentCount() const override { return 0; }
+ virtual OUString getFormula(const ::std::vector< OUString >& ) const override { return OUString(); }
+ virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& ) const override {}
+ virtual void initArgumentInfo() const override {}
+ virtual OUString getSignature() const override { return OUString(); }
+ virtual OString getHelpId() const override { return ""; }
+ virtual bool isHidden() const override { return false; }
+ virtual sal_uInt32 getParameterCount() const override { return 0; }
+ virtual sal_uInt32 getVarArgsStart() const override { return 0; }
+ virtual sal_uInt32 getVarArgsLimit() const override { return 0; }
+ virtual OUString getParameterName(sal_uInt32 ) const override { return OUString(); }
+ virtual OUString getParameterDescription(sal_uInt32 ) const override { return OUString(); }
+ virtual bool isParameterOptional(sal_uInt32 ) const override { return false; }
+ };
+ }
+
+// class FormulaHelper - static Method
+
+
+#define FUNC_NOTFOUND -1
+
+FormulaHelper::FormulaHelper(const IFunctionManager* _pFunctionManager)
+ :m_pSysLocale(new SvtSysLocale)
+ ,m_pFunctionManager(_pFunctionManager)
+ ,open(_pFunctionManager->getSingleToken(IFunctionManager::eOk))
+ ,close(_pFunctionManager->getSingleToken(IFunctionManager::eClose))
+ ,sep(_pFunctionManager->getSingleToken(IFunctionManager::eSep))
+ ,arrayOpen(_pFunctionManager->getSingleToken(IFunctionManager::eArrayOpen))
+ ,arrayClose(_pFunctionManager->getSingleToken(IFunctionManager::eArrayClose))
+{
+ m_pCharClass = &m_pSysLocale->GetCharClass();
+}
+
+sal_Int32 FormulaHelper::GetCategoryCount() const
+{
+ return m_pFunctionManager->getCount();
+}
+
+bool FormulaHelper::GetNextFunc( const OUString& rFormula,
+ bool bBack,
+ sal_Int32& rFStart, // Input and output
+ sal_Int32* pFEnd, // = NULL
+ const IFunctionDescription** ppFDesc, // = NULL
+ ::std::vector< OUString>* pArgs ) const // = NULL
+{
+ sal_Int32 nOldStart = rFStart;
+ OUString aFname;
+
+ rFStart = GetFunctionStart( rFormula, rFStart, bBack, ppFDesc ? &aFname : nullptr );
+ bool bFound = ( rFStart != FUNC_NOTFOUND );
+
+ if ( bFound )
+ {
+ if ( pFEnd )
+ *pFEnd = GetFunctionEnd( rFormula, rFStart );
+
+ if ( ppFDesc )
+ {
+ *ppFDesc = nullptr;
+ const sal_uInt32 nCategoryCount = m_pFunctionManager->getCount();
+ for(sal_uInt32 j= 0; j < nCategoryCount && !*ppFDesc; ++j)
+ {
+ const IFunctionCategory* pCategory = m_pFunctionManager->getCategory(j);
+ const sal_uInt32 nCount = pCategory->getCount();
+ for(sal_uInt32 i = 0 ; i < nCount; ++i)
+ {
+ const IFunctionDescription* pCurrent = pCategory->getFunction(i);
+ if ( pCurrent->getFunctionName().equalsIgnoreAsciiCase(aFname) )
+ {
+ *ppFDesc = pCurrent;
+ break;
+ }
+ }// for(sal_uInt32 i = 0 ; i < nCount; ++i)
+ }
+ if ( *ppFDesc && pArgs )
+ {
+ GetArgStrings( *pArgs,rFormula, rFStart, static_cast<sal_uInt16>((*ppFDesc)->getParameterCount() ));
+ }
+ else
+ {
+ static OEmptyFunctionDescription s_aFunctionDescription;
+ *ppFDesc = &s_aFunctionDescription;
+ }
+ }
+ }
+ else
+ rFStart = nOldStart;
+
+ return bFound;
+}
+
+
+void FormulaHelper::FillArgStrings( const OUString& rFormula,
+ sal_Int32 nFuncPos,
+ sal_uInt16 nArgs,
+ ::std::vector< OUString >& _rArgs ) const
+{
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd = 0;
+ sal_uInt16 i;
+ bool bLast = false;
+
+ for ( i=0; i<nArgs && !bLast; i++ )
+ {
+ nStart = GetArgStart( rFormula, nFuncPos, i );
+
+ if ( i+1<nArgs ) // last argument?
+ {
+ nEnd = GetArgStart( rFormula, nFuncPos, i+1 );
+
+ if ( nEnd != nStart )
+ _rArgs.push_back(rFormula.copy( nStart, nEnd-1-nStart ));
+ else
+ {
+ _rArgs.emplace_back();
+ bLast = true;
+ }
+ }
+ else
+ {
+ nEnd = GetFunctionEnd( rFormula, nFuncPos )-1;
+ if ( nStart < nEnd )
+ _rArgs.push_back( rFormula.copy( nStart, nEnd-nStart ) );
+ else
+ _rArgs.emplace_back();
+ }
+ }
+
+ if ( bLast )
+ for ( ; i<nArgs; i++ )
+ _rArgs.emplace_back();
+}
+
+
+void FormulaHelper::GetArgStrings( ::std::vector< OUString >& _rArgs,
+ const OUString& rFormula,
+ sal_Int32 nFuncPos,
+ sal_uInt16 nArgs ) const
+{
+ if (nArgs)
+ {
+ FillArgStrings( rFormula, nFuncPos, nArgs, _rArgs );
+ }
+}
+
+
+static bool IsFormulaText( const CharClass* _pCharClass,const OUString& rStr, sal_Int32 nPos )
+{
+ if( _pCharClass->isLetterNumeric( rStr, nPos ) )
+ return true;
+ else
+ { // In internationalized versions function names may contain a dot
+ // and in every version also an underscore... ;-)
+ sal_Unicode c = rStr[nPos];
+ return c == '.' || c == '_';
+ }
+
+}
+
+sal_Int32 FormulaHelper::GetFunctionStart( const OUString& rFormula,
+ sal_Int32 nStart,
+ bool bBack,
+ OUString* pFuncName ) const
+{
+ sal_Int32 nStrLen = rFormula.getLength();
+
+ if ( nStrLen < nStart )
+ return nStart;
+
+ sal_Int32 nFStart = FUNC_NOTFOUND;
+ sal_Int32 nParPos = bBack ? ::std::min( nStart, nStrLen - 1) : nStart;
+
+ bool bRepeat;
+ do
+ {
+ bool bFound = false;
+ bRepeat = false;
+
+ if ( bBack )
+ {
+ while ( !bFound && (nParPos > 0) )
+ {
+ if ( rFormula[nParPos] == '"' )
+ {
+ nParPos--;
+ while ( (nParPos > 0) && rFormula[nParPos] != '"' )
+ nParPos--;
+ if (nParPos > 0)
+ nParPos--;
+ }
+ else
+ {
+ bFound = rFormula[nParPos] == '(';
+ if ( !bFound )
+ nParPos--;
+ }
+ }
+ }
+ else
+ {
+ while ( !bFound && (0 <= nParPos && nParPos < nStrLen) )
+ {
+ if ( rFormula[nParPos] == '"' )
+ {
+ nParPos++;
+ while ( (nParPos < nStrLen) && rFormula[nParPos] != '"' )
+ nParPos++;
+ nParPos++;
+ }
+ else
+ {
+ bFound = rFormula[nParPos] == '(';
+ if ( !bFound )
+ nParPos++;
+ }
+ }
+ }
+
+ if ( bFound && (nParPos > 0) )
+ {
+ nFStart = nParPos-1;
+
+ while ( (nFStart > 0) && IsFormulaText(m_pCharClass, rFormula, nFStart ))
+ nFStart--;
+ }
+
+ nFStart++;
+
+ if ( bFound )
+ {
+ if ( IsFormulaText( m_pCharClass,rFormula, nFStart ) )
+ {
+ // Function found
+ if ( pFuncName )
+ *pFuncName = rFormula.copy( nFStart, nParPos-nFStart );
+ }
+ else // Brackets without function -> keep searching
+ {
+ bRepeat = true;
+ if ( !bBack )
+ nParPos++;
+ else if (nParPos > 0)
+ nParPos--;
+ else
+ bRepeat = false;
+ }
+ }
+ else // No brackets found
+ {
+ nFStart = FUNC_NOTFOUND;
+ if ( pFuncName )
+ pFuncName->clear();
+ }
+ }
+ while(bRepeat);
+
+ return nFStart;
+}
+
+
+sal_Int32 FormulaHelper::GetFunctionEnd( const OUString& rStr, sal_Int32 nStart ) const
+{
+ sal_Int32 nStrLen = rStr.getLength();
+
+ if ( nStrLen < nStart )
+ return nStart;
+
+ short nParCount = 0;
+ bool bInArray = false;
+ bool bFound = false;
+
+ while ( !bFound && (nStart < nStrLen) )
+ {
+ sal_Unicode c = rStr[nStart];
+
+ if ( c == '"' )
+ {
+ nStart++;
+ while ( (nStart < nStrLen) && rStr[nStart] != '"' )
+ nStart++;
+ }
+ else if ( c == open )
+ nParCount++;
+ else if ( c == close )
+ {
+ nParCount--;
+ if ( nParCount == 0 )
+ bFound = true;
+ else if ( nParCount < 0 )
+ {
+ bFound = true;
+ nStart--; // read one too far
+ }
+ }
+ else if ( c == arrayOpen )
+ {
+ bInArray = true;
+ }
+ else if ( c == arrayClose )
+ {
+ bInArray = false;
+ }
+ else if ( c == sep )
+ {
+ if ( !bInArray && nParCount == 0 )
+ {
+ bFound = true;
+ nStart--; // read one too far
+ }
+ }
+ nStart++; // Set behind found position
+ }
+
+ // nStart > nStrLen can happen if there was an unclosed quote; instead of
+ // checking that in every loop iteration check it once here.
+ return std::min(nStart, nStrLen);
+}
+
+
+sal_Int32 FormulaHelper::GetArgStart( const OUString& rStr, sal_Int32 nStart, sal_uInt16 nArg ) const
+{
+ sal_Int32 nStrLen = rStr.getLength();
+
+ if ( nStrLen < nStart )
+ return nStart;
+
+ short nParCount = 0;
+ bool bInArray = false;
+ bool bFound = false;
+
+ while ( !bFound && (nStart < nStrLen) )
+ {
+ sal_Unicode c = rStr[nStart];
+
+ if ( c == '"' )
+ {
+ nStart++;
+ while ( (nStart < nStrLen) && rStr[nStart] != '"' )
+ nStart++;
+ }
+ else if ( c == open )
+ {
+ bFound = ( nArg == 0 );
+ nParCount++;
+ }
+ else if ( c == close )
+ {
+ nParCount--;
+ bFound = ( nParCount == 0 );
+ }
+ else if ( c == arrayOpen )
+ {
+ bInArray = true;
+ }
+ else if ( c == arrayClose )
+ {
+ bInArray = false;
+ }
+ else if ( c == sep )
+ {
+ if ( !bInArray && nParCount == 1 )
+ {
+ nArg--;
+ bFound = ( nArg == 0 );
+ }
+ }
+ nStart++;
+ }
+
+ return nStart;
+}
+
+} // formula
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */