Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / formula / source / ui / dlg / FormulaHelper.cxx
blobe7874648bb3b8491fe036aa041e24a91be393f53
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 "formula/formulahelper.hxx"
21 #include <unotools/charclass.hxx>
22 #include <unotools/syslocale.hxx>
24 namespace formula
27 namespace
29 //============================================================================
30 class OEmptyFunctionDescription : public IFunctionDescription
32 public:
33 OEmptyFunctionDescription(){}
34 virtual ~OEmptyFunctionDescription(){}
36 virtual ::rtl::OUString getFunctionName() const { return ::rtl::OUString(); }
37 virtual const IFunctionCategory* getCategory() const { return NULL; }
38 virtual ::rtl::OUString getDescription() const { return ::rtl::OUString(); }
39 virtual xub_StrLen getSuppressedArgumentCount() const { return 0; }
40 virtual ::rtl::OUString getFormula(const ::std::vector< ::rtl::OUString >& ) const { return ::rtl::OUString(); }
41 virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& ) const {}
42 virtual void initArgumentInfo() const {}
43 virtual ::rtl::OUString getSignature() const { return ::rtl::OUString(); }
44 virtual rtl::OString getHelpId() const { return ""; }
45 virtual sal_uInt32 getParameterCount() const { return 0; }
46 virtual ::rtl::OUString getParameterName(sal_uInt32 ) const { return ::rtl::OUString(); }
47 virtual ::rtl::OUString getParameterDescription(sal_uInt32 ) const { return ::rtl::OUString(); }
48 virtual bool isParameterOptional(sal_uInt32 ) const { return sal_False; }
51 //===================================================================
52 // class FormulaHelper - static Method
53 //===================================================================
55 #define FUNC_NOTFOUND 0xffff
57 FormulaHelper::FormulaHelper(const IFunctionManager* _pFunctionManager)
58 :m_pSysLocale(new SvtSysLocale)
59 ,m_pFunctionManager(_pFunctionManager)
60 ,open(_pFunctionManager->getSingleToken(IFunctionManager::eOk))
61 ,close(_pFunctionManager->getSingleToken(IFunctionManager::eClose))
62 ,sep(_pFunctionManager->getSingleToken(IFunctionManager::eSep))
63 ,arrayOpen(_pFunctionManager->getSingleToken(IFunctionManager::eArrayOpen))
64 ,arrayClose(_pFunctionManager->getSingleToken(IFunctionManager::eArrayClose))
66 m_pCharClass = m_pSysLocale->GetCharClassPtr();
68 sal_Bool FormulaHelper::GetNextFunc( const String& rFormula,
69 sal_Bool bBack,
70 xub_StrLen& rFStart, // Input and output
71 xub_StrLen* pFEnd, // = NULL
72 const IFunctionDescription** ppFDesc, // = NULL
73 ::std::vector< ::rtl::OUString>* pArgs ) const // = NULL
75 sal_Bool bFound = sal_False;
76 xub_StrLen nOldStart = rFStart;
77 String aFname;
79 rFStart = GetFunctionStart( rFormula, rFStart, bBack, ppFDesc ? &aFname : NULL );
80 bFound = ( rFStart != FUNC_NOTFOUND );
82 if ( bFound )
84 if ( pFEnd )
85 *pFEnd = GetFunctionEnd( rFormula, rFStart );
87 if ( ppFDesc )
89 *ppFDesc = NULL;
90 const ::rtl::OUString sTemp( aFname );
91 const sal_uInt32 nCategoryCount = m_pFunctionManager->getCount();
92 for(sal_uInt32 j= 0; j < nCategoryCount && !*ppFDesc; ++j)
94 const IFunctionCategory* pCategory = m_pFunctionManager->getCategory(j);
95 const sal_uInt32 nCount = pCategory->getCount();
96 for(sal_uInt32 i = 0 ; i < nCount; ++i)
98 const IFunctionDescription* pCurrent = pCategory->getFunction(i);
99 if ( pCurrent->getFunctionName().equalsIgnoreAsciiCase(sTemp) )
101 *ppFDesc = pCurrent;
102 break;
104 }// for(sal_uInt32 i = 0 ; i < nCount; ++i)
106 if ( *ppFDesc && pArgs )
108 GetArgStrings( *pArgs,rFormula, rFStart, static_cast<sal_uInt16>((*ppFDesc)->getParameterCount() ));
110 else
112 static OEmptyFunctionDescription s_aFunctionDescription;
113 *ppFDesc = &s_aFunctionDescription;
117 else
118 rFStart = nOldStart;
120 return bFound;
123 //------------------------------------------------------------------------
125 void FormulaHelper::FillArgStrings( const String& rFormula,
126 xub_StrLen nFuncPos,
127 sal_uInt16 nArgs,
128 ::std::vector< ::rtl::OUString >& _rArgs ) const
130 xub_StrLen nStart = 0;
131 xub_StrLen nEnd = 0;
132 sal_uInt16 i;
133 sal_Bool bLast = sal_False;
135 for ( i=0; i<nArgs && !bLast; i++ )
137 nStart = GetArgStart( rFormula, nFuncPos, i );
139 if ( i+1<nArgs ) // last argument?
141 nEnd = GetArgStart( rFormula, nFuncPos, i+1 );
143 if ( nEnd != nStart )
144 _rArgs.push_back(rFormula.Copy( nStart, nEnd-1-nStart ));
145 else
146 _rArgs.push_back(String()), bLast = sal_True;
148 else
150 nEnd = GetFunctionEnd( rFormula, nFuncPos )-1;
151 if ( nStart < nEnd )
152 _rArgs.push_back( rFormula.Copy( nStart, nEnd-nStart ) );
153 else
154 _rArgs.push_back(String());
158 if ( bLast )
159 for ( ; i<nArgs; i++ )
160 _rArgs.push_back(String());
163 //------------------------------------------------------------------------
165 void FormulaHelper::GetArgStrings( ::std::vector< ::rtl::OUString >& _rArgs
166 ,const String& rFormula,
167 xub_StrLen nFuncPos,
168 sal_uInt16 nArgs ) const
170 if (nArgs)
172 FillArgStrings( rFormula, nFuncPos, nArgs, _rArgs );
176 //------------------------------------------------------------------------
178 inline sal_Bool IsFormulaText( const CharClass* _pCharClass,const String& rStr, xub_StrLen nPos )
180 if( _pCharClass->isLetterNumeric( rStr, nPos ) )
181 return sal_True;
182 else
183 { // In internationalized versions function names may contain a dot
184 // and in every version also an underscore... ;-)
185 sal_Unicode c = rStr.GetChar(nPos);
186 return c == '.' || c == '_';
191 xub_StrLen FormulaHelper::GetFunctionStart( const String& rFormula,
192 xub_StrLen nStart,
193 sal_Bool bBack,
194 String* pFuncName ) const
196 xub_StrLen nStrLen = rFormula.Len();
198 if ( nStrLen < nStart )
199 return nStart;
201 xub_StrLen nFStart = FUNC_NOTFOUND;
202 xub_StrLen nParPos = nStart;
204 sal_Bool bRepeat, bFound;
207 bFound = sal_False;
208 bRepeat = sal_False;
210 if ( bBack )
212 while ( !bFound && (nParPos > 0) )
214 if ( rFormula.GetChar(nParPos) == '"' )
216 nParPos--;
217 while ( (nParPos > 0) && rFormula.GetChar(nParPos) != '"' )
218 nParPos--;
219 if (nParPos > 0)
220 nParPos--;
222 else if ( (bFound = ( rFormula.GetChar(nParPos) == '(' ) ) == sal_False )
223 nParPos--;
226 else
228 while ( !bFound && (nParPos < nStrLen) )
230 if ( rFormula.GetChar(nParPos) == '"' )
232 nParPos++;
233 while ( (nParPos < nStrLen) && rFormula.GetChar(nParPos) != '"' )
234 nParPos++;
235 nParPos++;
237 else if ( (bFound = ( rFormula.GetChar(nParPos) == '(' ) ) == sal_False )
238 nParPos++;
242 if ( bFound && (nParPos > 0) )
244 nFStart = nParPos-1;
246 while ( (nFStart > 0) && IsFormulaText(m_pCharClass, rFormula, nFStart ))
247 nFStart--;
250 nFStart++;
252 if ( bFound )
254 if ( IsFormulaText( m_pCharClass,rFormula, nFStart ) )
256 // Function found
257 if ( pFuncName )
258 *pFuncName = rFormula.Copy( nFStart, nParPos-nFStart );
260 else // Brackets without function -> keep searching
262 bRepeat = sal_True;
263 if ( !bBack )
264 nParPos++;
265 else if (nParPos > 0)
266 nParPos--;
267 else
268 bRepeat = sal_False;
271 else // No brackets found
273 nFStart = FUNC_NOTFOUND;
274 if ( pFuncName )
275 pFuncName->Erase();
278 while(bRepeat);
280 return nFStart;
283 //------------------------------------------------------------------------
285 xub_StrLen FormulaHelper::GetFunctionEnd( const String& rStr, xub_StrLen nStart ) const
287 xub_StrLen nStrLen = rStr.Len();
289 if ( nStrLen < nStart )
290 return nStart;
292 short nParCount = 0;
293 bool bInArray = false;
294 sal_Bool bFound = sal_False;
296 while ( !bFound && (nStart < nStrLen) )
298 sal_Unicode c = rStr.GetChar(nStart);
300 if ( c == '"' )
302 nStart++;
303 while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
304 nStart++;
306 else if ( c == open )
307 nParCount++;
308 else if ( c == close )
310 nParCount--;
311 if ( nParCount == 0 )
312 bFound = sal_True;
313 else if ( nParCount < 0 )
315 bFound = sal_True;
316 nStart--; // read one too far
319 else if ( c == arrayOpen )
321 bInArray = true;
323 else if ( c == arrayClose )
325 bInArray = false;
327 else if ( c == sep )
329 if ( !bInArray && nParCount == 0 )
331 bFound = sal_True;
332 nStart--; // read one too far
335 nStart++; // Set behind found position
338 return nStart;
341 //------------------------------------------------------------------
343 xub_StrLen FormulaHelper::GetArgStart( const String& rStr, xub_StrLen nStart, sal_uInt16 nArg ) const
345 xub_StrLen nStrLen = rStr.Len();
347 if ( nStrLen < nStart )
348 return nStart;
350 short nParCount = 0;
351 bool bInArray = false;
352 sal_Bool bFound = sal_False;
354 while ( !bFound && (nStart < nStrLen) )
356 sal_Unicode c = rStr.GetChar(nStart);
358 if ( c == '"' )
360 nStart++;
361 while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
362 nStart++;
364 else if ( c == open )
366 bFound = ( nArg == 0 );
367 nParCount++;
369 else if ( c == close )
371 nParCount--;
372 bFound = ( nParCount == 0 );
374 else if ( c == arrayOpen )
376 bInArray = true;
378 else if ( c == arrayClose )
380 bInArray = false;
382 else if ( c == sep )
384 if ( !bInArray && nParCount == 1 )
386 nArg--;
387 bFound = ( nArg == 0 );
390 nStart++;
393 return nStart;
395 // =============================================================================
396 } // formula
397 // =============================================================================
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */