Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / formula / source / ui / dlg / FormulaHelper.cxx
blobb3c0b4a204bc9482b65b0827247939a5ba90ecf0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <algorithm>
22 #include <formula/formulahelper.hxx>
23 #include <formula/IFunctionDescription.hxx>
24 #include <unotools/charclass.hxx>
25 #include <unotools/syslocale.hxx>
27 namespace formula
30 namespace
33 class OEmptyFunctionDescription : public IFunctionDescription
35 public:
36 OEmptyFunctionDescription(){}
37 virtual ~OEmptyFunctionDescription(){}
39 virtual OUString getFunctionName() const override { return OUString(); }
40 virtual const IFunctionCategory* getCategory() const override { return nullptr; }
41 virtual OUString getDescription() const override { return OUString(); }
42 virtual sal_Int32 getSuppressedArgumentCount() const override { return 0; }
43 virtual OUString getFormula(const ::std::vector< OUString >& ) const override { return OUString(); }
44 virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& ) const override {}
45 virtual void initArgumentInfo() const override {}
46 virtual OUString getSignature() const override { return OUString(); }
47 virtual OString getHelpId() const override { return ""; }
48 virtual bool isHidden() const override { return false; }
49 virtual sal_uInt32 getParameterCount() const override { return 0; }
50 virtual sal_uInt32 getVarArgsStart() const override { return 0; }
51 virtual OUString getParameterName(sal_uInt32 ) const override { return OUString(); }
52 virtual OUString getParameterDescription(sal_uInt32 ) const override { return OUString(); }
53 virtual bool isParameterOptional(sal_uInt32 ) const override { return false; }
57 // class FormulaHelper - static Method
60 #define FUNC_NOTFOUND -1
62 FormulaHelper::FormulaHelper(const IFunctionManager* _pFunctionManager)
63 :m_pSysLocale(new SvtSysLocale)
64 ,m_pFunctionManager(_pFunctionManager)
65 ,open(_pFunctionManager->getSingleToken(IFunctionManager::eOk))
66 ,close(_pFunctionManager->getSingleToken(IFunctionManager::eClose))
67 ,sep(_pFunctionManager->getSingleToken(IFunctionManager::eSep))
68 ,arrayOpen(_pFunctionManager->getSingleToken(IFunctionManager::eArrayOpen))
69 ,arrayClose(_pFunctionManager->getSingleToken(IFunctionManager::eArrayClose))
71 m_pCharClass = m_pSysLocale->GetCharClassPtr();
74 bool FormulaHelper::GetNextFunc( const OUString& rFormula,
75 bool bBack,
76 sal_Int32& rFStart, // Input and output
77 sal_Int32* pFEnd, // = NULL
78 const IFunctionDescription** ppFDesc, // = NULL
79 ::std::vector< OUString>* pArgs ) const // = NULL
81 sal_Int32 nOldStart = rFStart;
82 OUString aFname;
84 rFStart = GetFunctionStart( rFormula, rFStart, bBack, ppFDesc ? &aFname : nullptr );
85 bool bFound = ( rFStart != FUNC_NOTFOUND );
87 if ( bFound )
89 if ( pFEnd )
90 *pFEnd = GetFunctionEnd( rFormula, rFStart );
92 if ( ppFDesc )
94 *ppFDesc = nullptr;
95 const sal_uInt32 nCategoryCount = m_pFunctionManager->getCount();
96 for(sal_uInt32 j= 0; j < nCategoryCount && !*ppFDesc; ++j)
98 const IFunctionCategory* pCategory = m_pFunctionManager->getCategory(j);
99 const sal_uInt32 nCount = pCategory->getCount();
100 for(sal_uInt32 i = 0 ; i < nCount; ++i)
102 const IFunctionDescription* pCurrent = pCategory->getFunction(i);
103 if ( pCurrent->getFunctionName().equalsIgnoreAsciiCase(aFname) )
105 *ppFDesc = pCurrent;
106 break;
108 }// for(sal_uInt32 i = 0 ; i < nCount; ++i)
110 if ( *ppFDesc && pArgs )
112 GetArgStrings( *pArgs,rFormula, rFStart, static_cast<sal_uInt16>((*ppFDesc)->getParameterCount() ));
114 else
116 static OEmptyFunctionDescription s_aFunctionDescription;
117 *ppFDesc = &s_aFunctionDescription;
121 else
122 rFStart = nOldStart;
124 return bFound;
128 void FormulaHelper::FillArgStrings( const OUString& rFormula,
129 sal_Int32 nFuncPos,
130 sal_uInt16 nArgs,
131 ::std::vector< OUString >& _rArgs ) const
133 sal_Int32 nStart = 0;
134 sal_Int32 nEnd = 0;
135 sal_uInt16 i;
136 bool bLast = false;
138 for ( i=0; i<nArgs && !bLast; i++ )
140 nStart = GetArgStart( rFormula, nFuncPos, i );
142 if ( i+1<nArgs ) // last argument?
144 nEnd = GetArgStart( rFormula, nFuncPos, i+1 );
146 if ( nEnd != nStart )
147 _rArgs.push_back(rFormula.copy( nStart, nEnd-1-nStart ));
148 else
150 _rArgs.emplace_back();
151 bLast = true;
154 else
156 nEnd = GetFunctionEnd( rFormula, nFuncPos )-1;
157 if ( nStart < nEnd )
158 _rArgs.push_back( rFormula.copy( nStart, nEnd-nStart ) );
159 else
160 _rArgs.emplace_back();
164 if ( bLast )
165 for ( ; i<nArgs; i++ )
166 _rArgs.emplace_back();
170 void FormulaHelper::GetArgStrings( ::std::vector< OUString >& _rArgs,
171 const OUString& rFormula,
172 sal_Int32 nFuncPos,
173 sal_uInt16 nArgs ) const
175 if (nArgs)
177 FillArgStrings( rFormula, nFuncPos, nArgs, _rArgs );
182 static bool IsFormulaText( const CharClass* _pCharClass,const OUString& rStr, sal_Int32 nPos )
184 if( _pCharClass->isLetterNumeric( rStr, nPos ) )
185 return true;
186 else
187 { // In internationalized versions function names may contain a dot
188 // and in every version also an underscore... ;-)
189 sal_Unicode c = rStr[nPos];
190 return c == '.' || c == '_';
195 sal_Int32 FormulaHelper::GetFunctionStart( const OUString& rFormula,
196 sal_Int32 nStart,
197 bool bBack,
198 OUString* pFuncName ) const
200 sal_Int32 nStrLen = rFormula.getLength();
202 if ( nStrLen < nStart )
203 return nStart;
205 sal_Int32 nFStart = FUNC_NOTFOUND;
206 sal_Int32 nParPos = bBack ? ::std::min( nStart, nStrLen - 1) : nStart;
208 bool bRepeat;
211 bool bFound = false;
212 bRepeat = false;
214 if ( bBack )
216 while ( !bFound && (nParPos > 0) )
218 if ( rFormula[nParPos] == '"' )
220 nParPos--;
221 while ( (nParPos > 0) && rFormula[nParPos] != '"' )
222 nParPos--;
223 if (nParPos > 0)
224 nParPos--;
226 else
228 bFound = rFormula[nParPos] == '(';
229 if ( !bFound )
230 nParPos--;
234 else
236 while ( !bFound && (0 <= nParPos && nParPos < nStrLen) )
238 if ( rFormula[nParPos] == '"' )
240 nParPos++;
241 while ( (nParPos < nStrLen) && rFormula[nParPos] != '"' )
242 nParPos++;
243 nParPos++;
245 else
247 bFound = rFormula[nParPos] == '(';
248 if ( !bFound )
249 nParPos++;
254 if ( bFound && (nParPos > 0) )
256 nFStart = nParPos-1;
258 while ( (nFStart > 0) && IsFormulaText(m_pCharClass, rFormula, nFStart ))
259 nFStart--;
262 nFStart++;
264 if ( bFound )
266 if ( IsFormulaText( m_pCharClass,rFormula, nFStart ) )
268 // Function found
269 if ( pFuncName )
270 *pFuncName = rFormula.copy( nFStart, nParPos-nFStart );
272 else // Brackets without function -> keep searching
274 bRepeat = true;
275 if ( !bBack )
276 nParPos++;
277 else if (nParPos > 0)
278 nParPos--;
279 else
280 bRepeat = false;
283 else // No brackets found
285 nFStart = FUNC_NOTFOUND;
286 if ( pFuncName )
287 pFuncName->clear();
290 while(bRepeat);
292 return nFStart;
296 sal_Int32 FormulaHelper::GetFunctionEnd( const OUString& rStr, sal_Int32 nStart ) const
298 sal_Int32 nStrLen = rStr.getLength();
300 if ( nStrLen < nStart )
301 return nStart;
303 short nParCount = 0;
304 bool bInArray = false;
305 bool bFound = false;
307 while ( !bFound && (nStart < nStrLen) )
309 sal_Unicode c = rStr[nStart];
311 if ( c == '"' )
313 nStart++;
314 while ( (nStart < nStrLen) && rStr[nStart] != '"' )
315 nStart++;
317 else if ( c == open )
318 nParCount++;
319 else if ( c == close )
321 nParCount--;
322 if ( nParCount == 0 )
323 bFound = true;
324 else if ( nParCount < 0 )
326 bFound = true;
327 nStart--; // read one too far
330 else if ( c == arrayOpen )
332 bInArray = true;
334 else if ( c == arrayClose )
336 bInArray = false;
338 else if ( c == sep )
340 if ( !bInArray && nParCount == 0 )
342 bFound = true;
343 nStart--; // read one too far
346 nStart++; // Set behind found position
349 return nStart;
353 sal_Int32 FormulaHelper::GetArgStart( const OUString& rStr, sal_Int32 nStart, sal_uInt16 nArg ) const
355 sal_Int32 nStrLen = rStr.getLength();
357 if ( nStrLen < nStart )
358 return nStart;
360 short nParCount = 0;
361 bool bInArray = false;
362 bool bFound = false;
364 while ( !bFound && (nStart < nStrLen) )
366 sal_Unicode c = rStr[nStart];
368 if ( c == '"' )
370 nStart++;
371 while ( (nStart < nStrLen) && rStr[nStart] != '"' )
372 nStart++;
374 else if ( c == open )
376 bFound = ( nArg == 0 );
377 nParCount++;
379 else if ( c == close )
381 nParCount--;
382 bFound = ( nParCount == 0 );
384 else if ( c == arrayOpen )
386 bInArray = true;
388 else if ( c == arrayClose )
390 bInArray = false;
392 else if ( c == sep )
394 if ( !bInArray && nParCount == 1 )
396 nArg--;
397 bFound = ( nArg == 0 );
400 nStart++;
403 return nStart;
406 } // formula
409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */