xref: /AOO41X/main/formula/source/ui/dlg/FormulaHelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir #include "precompiled_formula.hxx"
28*cdf0e10cSrcweir 
29*cdf0e10cSrcweir #include "formula/formulahelper.hxx"
30*cdf0e10cSrcweir #include <unotools/charclass.hxx>
31*cdf0e10cSrcweir #include <unotools/syslocale.hxx>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir namespace formula
34*cdf0e10cSrcweir {
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir     namespace
37*cdf0e10cSrcweir     {
38*cdf0e10cSrcweir         //============================================================================
39*cdf0e10cSrcweir         class OEmptyFunctionDescription : public IFunctionDescription
40*cdf0e10cSrcweir         {
41*cdf0e10cSrcweir         public:
42*cdf0e10cSrcweir             OEmptyFunctionDescription(){}
43*cdf0e10cSrcweir             virtual ~OEmptyFunctionDescription(){}
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir             virtual ::rtl::OUString getFunctionName() const { return ::rtl::OUString(); }
46*cdf0e10cSrcweir             virtual const IFunctionCategory* getCategory() const { return NULL; }
47*cdf0e10cSrcweir             virtual ::rtl::OUString getDescription() const { return ::rtl::OUString(); }
48*cdf0e10cSrcweir             virtual xub_StrLen getSuppressedArgumentCount() const { return 0; }
49*cdf0e10cSrcweir             virtual ::rtl::OUString getFormula(const ::std::vector< ::rtl::OUString >& ) const { return ::rtl::OUString(); }
50*cdf0e10cSrcweir             virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& ) const {}
51*cdf0e10cSrcweir             virtual void initArgumentInfo()  const {}
52*cdf0e10cSrcweir             virtual ::rtl::OUString getSignature() const { return ::rtl::OUString(); }
53*cdf0e10cSrcweir             virtual rtl::OString getHelpId() const { return ""; }
54*cdf0e10cSrcweir             virtual sal_uInt32 getParameterCount() const { return 0; }
55*cdf0e10cSrcweir             virtual ::rtl::OUString getParameterName(sal_uInt32 ) const { return ::rtl::OUString(); }
56*cdf0e10cSrcweir             virtual ::rtl::OUString getParameterDescription(sal_uInt32 ) const { return ::rtl::OUString(); }
57*cdf0e10cSrcweir             virtual bool isParameterOptional(sal_uInt32 ) const { return sal_False; }
58*cdf0e10cSrcweir         };
59*cdf0e10cSrcweir     }
60*cdf0e10cSrcweir //===================================================================
61*cdf0e10cSrcweir //	class FormulaHelper - statische Methoden
62*cdf0e10cSrcweir //===================================================================
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir #define FUNC_NOTFOUND 0xffff
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir FormulaHelper::FormulaHelper(const IFunctionManager* _pFunctionManager)
67*cdf0e10cSrcweir     :m_pSysLocale(new SvtSysLocale)
68*cdf0e10cSrcweir     ,m_pFunctionManager(_pFunctionManager)
69*cdf0e10cSrcweir     ,open(_pFunctionManager->getSingleToken(IFunctionManager::eOk))
70*cdf0e10cSrcweir     ,close(_pFunctionManager->getSingleToken(IFunctionManager::eClose))
71*cdf0e10cSrcweir     ,sep(_pFunctionManager->getSingleToken(IFunctionManager::eSep))
72*cdf0e10cSrcweir     ,arrayOpen(_pFunctionManager->getSingleToken(IFunctionManager::eArrayOpen))
73*cdf0e10cSrcweir     ,arrayClose(_pFunctionManager->getSingleToken(IFunctionManager::eArrayClose))
74*cdf0e10cSrcweir {
75*cdf0e10cSrcweir     m_pCharClass = m_pSysLocale->GetCharClassPtr();
76*cdf0e10cSrcweir }
77*cdf0e10cSrcweir sal_Bool FormulaHelper::GetNextFunc( const String&	rFormula,
78*cdf0e10cSrcweir 								 sal_Bool			bBack,
79*cdf0e10cSrcweir 								 xub_StrLen&	rFStart,   // Ein- und Ausgabe
80*cdf0e10cSrcweir 								 xub_StrLen*	pFEnd, 	   // = NULL
81*cdf0e10cSrcweir 								 const IFunctionDescription**	ppFDesc,   // = NULL
82*cdf0e10cSrcweir                                  ::std::vector< ::rtl::OUString>*	pArgs )  const // = NULL
83*cdf0e10cSrcweir {
84*cdf0e10cSrcweir 	sal_Bool		bFound = sal_False;
85*cdf0e10cSrcweir 	xub_StrLen	nOldStart = rFStart;
86*cdf0e10cSrcweir 	String		aFname;
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir 	rFStart = GetFunctionStart( rFormula, rFStart, bBack, ppFDesc ? &aFname : NULL );
89*cdf0e10cSrcweir 	bFound  = ( rFStart != FUNC_NOTFOUND );
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir 	if ( bFound )
92*cdf0e10cSrcweir 	{
93*cdf0e10cSrcweir 		if ( pFEnd )
94*cdf0e10cSrcweir 			*pFEnd = GetFunctionEnd( rFormula, rFStart );
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir 		if ( ppFDesc )
97*cdf0e10cSrcweir 		{
98*cdf0e10cSrcweir             *ppFDesc = NULL;
99*cdf0e10cSrcweir             const ::rtl::OUString sTemp( aFname );
100*cdf0e10cSrcweir             const sal_uInt32 nCategoryCount = m_pFunctionManager->getCount();
101*cdf0e10cSrcweir             for(sal_uInt32 j= 0; j < nCategoryCount && !*ppFDesc; ++j)
102*cdf0e10cSrcweir             {
103*cdf0e10cSrcweir                 const IFunctionCategory* pCategory = m_pFunctionManager->getCategory(j);
104*cdf0e10cSrcweir                 const sal_uInt32 nCount = pCategory->getCount();
105*cdf0e10cSrcweir                 for(sal_uInt32 i = 0 ; i < nCount; ++i)
106*cdf0e10cSrcweir                 {
107*cdf0e10cSrcweir                     const IFunctionDescription* pCurrent = pCategory->getFunction(i);
108*cdf0e10cSrcweir 	                if ( pCurrent->getFunctionName().equalsIgnoreAsciiCase(sTemp) )
109*cdf0e10cSrcweir                     {
110*cdf0e10cSrcweir                         *ppFDesc = pCurrent;
111*cdf0e10cSrcweir                         break;
112*cdf0e10cSrcweir                     }
113*cdf0e10cSrcweir                 } // for(sal_uInt32 i = 0 ; i < nCount; ++i)
114*cdf0e10cSrcweir             }
115*cdf0e10cSrcweir 			if ( *ppFDesc && pArgs )
116*cdf0e10cSrcweir 			{
117*cdf0e10cSrcweir 				GetArgStrings( *pArgs,rFormula, rFStart, static_cast<sal_uInt16>((*ppFDesc)->getParameterCount() ));
118*cdf0e10cSrcweir 			}
119*cdf0e10cSrcweir             else
120*cdf0e10cSrcweir             {
121*cdf0e10cSrcweir                 static OEmptyFunctionDescription s_aFunctionDescription;
122*cdf0e10cSrcweir                 *ppFDesc = &s_aFunctionDescription;
123*cdf0e10cSrcweir             }
124*cdf0e10cSrcweir 		}
125*cdf0e10cSrcweir 	}
126*cdf0e10cSrcweir 	else
127*cdf0e10cSrcweir 		rFStart = nOldStart;
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir 	return bFound;
130*cdf0e10cSrcweir }
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir //------------------------------------------------------------------------
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir void FormulaHelper::FillArgStrings( const String&	rFormula,
135*cdf0e10cSrcweir 									xub_StrLen		nFuncPos,
136*cdf0e10cSrcweir 									sal_uInt16			nArgs,
137*cdf0e10cSrcweir 									::std::vector< ::rtl::OUString >& _rArgs ) const
138*cdf0e10cSrcweir {
139*cdf0e10cSrcweir 	xub_StrLen	nStart	= 0;
140*cdf0e10cSrcweir 	xub_StrLen	nEnd	= 0;
141*cdf0e10cSrcweir 	sal_uInt16		i;
142*cdf0e10cSrcweir 	sal_Bool		bLast	= sal_False;
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir 	for ( i=0; i<nArgs && !bLast; i++ )
145*cdf0e10cSrcweir 	{
146*cdf0e10cSrcweir 		nStart = GetArgStart( rFormula, nFuncPos, i );
147*cdf0e10cSrcweir 
148*cdf0e10cSrcweir 		if ( i+1<nArgs ) // letztes Argument?
149*cdf0e10cSrcweir 		{
150*cdf0e10cSrcweir 			nEnd = GetArgStart( rFormula, nFuncPos, i+1 );
151*cdf0e10cSrcweir 
152*cdf0e10cSrcweir 			if ( nEnd != nStart )
153*cdf0e10cSrcweir                 _rArgs.push_back(rFormula.Copy( nStart, nEnd-1-nStart ));
154*cdf0e10cSrcweir 			else
155*cdf0e10cSrcweir 				_rArgs.push_back(String()), bLast = sal_True;
156*cdf0e10cSrcweir 		}
157*cdf0e10cSrcweir 		else
158*cdf0e10cSrcweir 		{
159*cdf0e10cSrcweir 			nEnd = GetFunctionEnd( rFormula, nFuncPos )-1;
160*cdf0e10cSrcweir 			if ( nStart < nEnd )
161*cdf0e10cSrcweir 				_rArgs.push_back( rFormula.Copy( nStart, nEnd-nStart ) );
162*cdf0e10cSrcweir 			else
163*cdf0e10cSrcweir 				_rArgs.push_back(String());
164*cdf0e10cSrcweir 		}
165*cdf0e10cSrcweir 	}
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir 	if ( bLast )
168*cdf0e10cSrcweir 		for ( ; i<nArgs; i++ )
169*cdf0e10cSrcweir 			_rArgs.push_back(String());
170*cdf0e10cSrcweir }
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir //------------------------------------------------------------------------
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir void FormulaHelper::GetArgStrings( ::std::vector< ::rtl::OUString >& _rArgs
175*cdf0e10cSrcweir                                       ,const String& rFormula,
176*cdf0e10cSrcweir 									   xub_StrLen nFuncPos,
177*cdf0e10cSrcweir 									   sal_uInt16 nArgs ) const
178*cdf0e10cSrcweir {
179*cdf0e10cSrcweir 	if (nArgs)
180*cdf0e10cSrcweir 	{
181*cdf0e10cSrcweir 		FillArgStrings( rFormula, nFuncPos, nArgs, _rArgs );
182*cdf0e10cSrcweir 	}
183*cdf0e10cSrcweir }
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir //------------------------------------------------------------------------
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir inline sal_Bool IsFormulaText( const CharClass* _pCharClass,const String& rStr, xub_StrLen nPos )
188*cdf0e10cSrcweir {
189*cdf0e10cSrcweir 	if( _pCharClass->isLetterNumeric( rStr, nPos ) )
190*cdf0e10cSrcweir 		return sal_True;
191*cdf0e10cSrcweir 	else
192*cdf0e10cSrcweir 	{	// In internationalized versions function names may contain a dot
193*cdf0e10cSrcweir 		//  and in every version also an underscore... ;-)
194*cdf0e10cSrcweir 		sal_Unicode c = rStr.GetChar(nPos);
195*cdf0e10cSrcweir 		return c == '.' || c == '_';
196*cdf0e10cSrcweir 	}
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir }
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir xub_StrLen FormulaHelper::GetFunctionStart( const String&	rFormula,
201*cdf0e10cSrcweir 										xub_StrLen		nStart,
202*cdf0e10cSrcweir 										sal_Bool			bBack,
203*cdf0e10cSrcweir 										String*			pFuncName ) const
204*cdf0e10cSrcweir {
205*cdf0e10cSrcweir 	xub_StrLen nStrLen = rFormula.Len();
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir 	if ( nStrLen < nStart )
208*cdf0e10cSrcweir 		return nStart;
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir 	xub_StrLen	nFStart = FUNC_NOTFOUND;
211*cdf0e10cSrcweir 	xub_StrLen	nParPos	= nStart;
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir 	sal_Bool bRepeat, bFound;
214*cdf0e10cSrcweir 	do
215*cdf0e10cSrcweir 	{
216*cdf0e10cSrcweir 		bFound  = sal_False;
217*cdf0e10cSrcweir 		bRepeat = sal_False;
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir 		if ( bBack )
220*cdf0e10cSrcweir 		{
221*cdf0e10cSrcweir 			while ( !bFound && (nParPos > 0) )
222*cdf0e10cSrcweir 			{
223*cdf0e10cSrcweir 				if ( rFormula.GetChar(nParPos) == '"' )
224*cdf0e10cSrcweir 				{
225*cdf0e10cSrcweir 					nParPos--;
226*cdf0e10cSrcweir 					while ( (nParPos > 0) && rFormula.GetChar(nParPos) != '"' )
227*cdf0e10cSrcweir 						nParPos--;
228*cdf0e10cSrcweir 					if (nParPos > 0)
229*cdf0e10cSrcweir 						nParPos--;
230*cdf0e10cSrcweir 				}
231*cdf0e10cSrcweir                 else if ( (bFound = ( rFormula.GetChar(nParPos) == '(' ) ) == sal_False )
232*cdf0e10cSrcweir 					nParPos--;
233*cdf0e10cSrcweir 			}
234*cdf0e10cSrcweir 		}
235*cdf0e10cSrcweir 		else
236*cdf0e10cSrcweir 		{
237*cdf0e10cSrcweir 			while ( !bFound && (nParPos < nStrLen) )
238*cdf0e10cSrcweir 			{
239*cdf0e10cSrcweir 				if ( rFormula.GetChar(nParPos) == '"' )
240*cdf0e10cSrcweir 				{
241*cdf0e10cSrcweir 					nParPos++;
242*cdf0e10cSrcweir 					while ( (nParPos < nStrLen) && rFormula.GetChar(nParPos) != '"' )
243*cdf0e10cSrcweir 						nParPos++;
244*cdf0e10cSrcweir 					nParPos++;
245*cdf0e10cSrcweir 				}
246*cdf0e10cSrcweir                 else if ( (bFound = ( rFormula.GetChar(nParPos) == '(' ) ) == sal_False )
247*cdf0e10cSrcweir 					nParPos++;
248*cdf0e10cSrcweir 			}
249*cdf0e10cSrcweir 		}
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir 		if ( bFound && (nParPos > 0) )
252*cdf0e10cSrcweir 		{
253*cdf0e10cSrcweir 			nFStart = nParPos-1;
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir 			while ( (nFStart > 0) && IsFormulaText(m_pCharClass, rFormula, nFStart ))
256*cdf0e10cSrcweir 				nFStart--;
257*cdf0e10cSrcweir 		}
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir 		nFStart++;
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir 		if ( bFound )
262*cdf0e10cSrcweir 		{
263*cdf0e10cSrcweir 			if ( IsFormulaText( m_pCharClass,rFormula, nFStart ) )
264*cdf0e10cSrcweir 			{
265*cdf0e10cSrcweir 									//	Funktion gefunden
266*cdf0e10cSrcweir 				if ( pFuncName )
267*cdf0e10cSrcweir 					*pFuncName = rFormula.Copy( nFStart, nParPos-nFStart );
268*cdf0e10cSrcweir 			}
269*cdf0e10cSrcweir 			else					// Klammern ohne Funktion -> weitersuchen
270*cdf0e10cSrcweir 			{
271*cdf0e10cSrcweir 				bRepeat = sal_True;
272*cdf0e10cSrcweir 				if ( !bBack )
273*cdf0e10cSrcweir 					nParPos++;
274*cdf0e10cSrcweir 				else if (nParPos > 0)
275*cdf0e10cSrcweir 					nParPos--;
276*cdf0e10cSrcweir 				else
277*cdf0e10cSrcweir 					bRepeat = sal_False;
278*cdf0e10cSrcweir 			}
279*cdf0e10cSrcweir 		}
280*cdf0e10cSrcweir 		else						// keine Klammern gefunden
281*cdf0e10cSrcweir 		{
282*cdf0e10cSrcweir 			nFStart = FUNC_NOTFOUND;
283*cdf0e10cSrcweir 			if ( pFuncName )
284*cdf0e10cSrcweir 				pFuncName->Erase();
285*cdf0e10cSrcweir 		}
286*cdf0e10cSrcweir 	}
287*cdf0e10cSrcweir 	while(bRepeat);
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir 	return nFStart;
290*cdf0e10cSrcweir }
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir //------------------------------------------------------------------------
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir xub_StrLen	FormulaHelper::GetFunctionEnd( const String& rStr, xub_StrLen nStart ) const
295*cdf0e10cSrcweir {
296*cdf0e10cSrcweir 	xub_StrLen nStrLen = rStr.Len();
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir 	if ( nStrLen < nStart )
299*cdf0e10cSrcweir 		return nStart;
300*cdf0e10cSrcweir 
301*cdf0e10cSrcweir 	short	nParCount = 0;
302*cdf0e10cSrcweir     bool    bInArray = false;
303*cdf0e10cSrcweir 	sal_Bool	bFound = sal_False;
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir 	while ( !bFound && (nStart < nStrLen) )
306*cdf0e10cSrcweir 	{
307*cdf0e10cSrcweir 		sal_Unicode c = rStr.GetChar(nStart);
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir 		if ( c == '"' )
310*cdf0e10cSrcweir 		{
311*cdf0e10cSrcweir 			nStart++;
312*cdf0e10cSrcweir 			while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
313*cdf0e10cSrcweir 				nStart++;
314*cdf0e10cSrcweir 		}
315*cdf0e10cSrcweir 		else if ( c == open )
316*cdf0e10cSrcweir 			nParCount++;
317*cdf0e10cSrcweir 		else if ( c == close )
318*cdf0e10cSrcweir 		{
319*cdf0e10cSrcweir 			nParCount--;
320*cdf0e10cSrcweir 			if ( nParCount == 0 )
321*cdf0e10cSrcweir 				bFound = sal_True;
322*cdf0e10cSrcweir 			else if ( nParCount < 0 )
323*cdf0e10cSrcweir 			{
324*cdf0e10cSrcweir 				bFound = sal_True;
325*cdf0e10cSrcweir 				nStart--;	// einen zu weit gelesen
326*cdf0e10cSrcweir 			}
327*cdf0e10cSrcweir 		}
328*cdf0e10cSrcweir         else if ( c == arrayOpen )
329*cdf0e10cSrcweir         {
330*cdf0e10cSrcweir             bInArray = true;
331*cdf0e10cSrcweir         }
332*cdf0e10cSrcweir         else if ( c == arrayClose )
333*cdf0e10cSrcweir         {
334*cdf0e10cSrcweir             bInArray = false;
335*cdf0e10cSrcweir         }
336*cdf0e10cSrcweir 		else if ( c == sep )
337*cdf0e10cSrcweir 		{
338*cdf0e10cSrcweir 			if ( !bInArray && nParCount == 0 )
339*cdf0e10cSrcweir 			{
340*cdf0e10cSrcweir 				bFound = sal_True;
341*cdf0e10cSrcweir 				nStart--;	// einen zu weit gelesen
342*cdf0e10cSrcweir 			}
343*cdf0e10cSrcweir 		}
344*cdf0e10cSrcweir 		nStart++; // hinter gefundene Position stellen
345*cdf0e10cSrcweir 	}
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir 	return nStart;
348*cdf0e10cSrcweir }
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir //------------------------------------------------------------------
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir xub_StrLen FormulaHelper::GetArgStart( const String& rStr, xub_StrLen nStart, sal_uInt16 nArg ) const
353*cdf0e10cSrcweir {
354*cdf0e10cSrcweir 	xub_StrLen nStrLen = rStr.Len();
355*cdf0e10cSrcweir 
356*cdf0e10cSrcweir 	if ( nStrLen < nStart )
357*cdf0e10cSrcweir 		return nStart;
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir 	short	nParCount	= 0;
360*cdf0e10cSrcweir     bool    bInArray    = false;
361*cdf0e10cSrcweir 	sal_Bool	bFound		= sal_False;
362*cdf0e10cSrcweir 
363*cdf0e10cSrcweir 	while ( !bFound && (nStart < nStrLen) )
364*cdf0e10cSrcweir 	{
365*cdf0e10cSrcweir 		sal_Unicode c = rStr.GetChar(nStart);
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir 		if ( c == '"' )
368*cdf0e10cSrcweir 		{
369*cdf0e10cSrcweir 			nStart++;
370*cdf0e10cSrcweir 			while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
371*cdf0e10cSrcweir 				nStart++;
372*cdf0e10cSrcweir 		}
373*cdf0e10cSrcweir 		else if ( c == open )
374*cdf0e10cSrcweir 		{
375*cdf0e10cSrcweir 			bFound = ( nArg == 0 );
376*cdf0e10cSrcweir 			nParCount++;
377*cdf0e10cSrcweir 		}
378*cdf0e10cSrcweir 		else if ( c == close )
379*cdf0e10cSrcweir 		{
380*cdf0e10cSrcweir 			nParCount--;
381*cdf0e10cSrcweir 			bFound = ( nParCount == 0 );
382*cdf0e10cSrcweir 		}
383*cdf0e10cSrcweir         else if ( c == arrayOpen )
384*cdf0e10cSrcweir         {
385*cdf0e10cSrcweir             bInArray = true;
386*cdf0e10cSrcweir         }
387*cdf0e10cSrcweir         else if ( c == arrayClose )
388*cdf0e10cSrcweir         {
389*cdf0e10cSrcweir             bInArray = false;
390*cdf0e10cSrcweir         }
391*cdf0e10cSrcweir 		else if ( c == sep )
392*cdf0e10cSrcweir 		{
393*cdf0e10cSrcweir 			if ( !bInArray && nParCount == 1 )
394*cdf0e10cSrcweir 			{
395*cdf0e10cSrcweir 				nArg--;
396*cdf0e10cSrcweir 				bFound = ( nArg == 0  );
397*cdf0e10cSrcweir 			}
398*cdf0e10cSrcweir 		}
399*cdf0e10cSrcweir 		nStart++;
400*cdf0e10cSrcweir 	}
401*cdf0e10cSrcweir 
402*cdf0e10cSrcweir 	return nStart;
403*cdf0e10cSrcweir }
404*cdf0e10cSrcweir // =============================================================================
405*cdf0e10cSrcweir } // formula
406*cdf0e10cSrcweir // =============================================================================
407