1*c25918c1SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*c25918c1SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*c25918c1SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*c25918c1SAndrew Rist * distributed with this work for additional information
6*c25918c1SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*c25918c1SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*c25918c1SAndrew Rist * "License"); you may not use this file except in compliance
9*c25918c1SAndrew Rist * with the License. You may obtain a copy of the License at
10*c25918c1SAndrew Rist *
11*c25918c1SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*c25918c1SAndrew Rist *
13*c25918c1SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*c25918c1SAndrew Rist * software distributed under the License is distributed on an
15*c25918c1SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c25918c1SAndrew Rist * KIND, either express or implied. See the License for the
17*c25918c1SAndrew Rist * specific language governing permissions and limitations
18*c25918c1SAndrew Rist * under the License.
19*c25918c1SAndrew Rist *
20*c25918c1SAndrew Rist *************************************************************/
21*c25918c1SAndrew Rist
22*c25918c1SAndrew Rist
23cdf0e10cSrcweir #include "precompiled_formula.hxx"
24cdf0e10cSrcweir
25cdf0e10cSrcweir #include "formula/formulahelper.hxx"
26cdf0e10cSrcweir #include <unotools/charclass.hxx>
27cdf0e10cSrcweir #include <unotools/syslocale.hxx>
28cdf0e10cSrcweir
29cdf0e10cSrcweir namespace formula
30cdf0e10cSrcweir {
31cdf0e10cSrcweir
32cdf0e10cSrcweir namespace
33cdf0e10cSrcweir {
34cdf0e10cSrcweir //============================================================================
35cdf0e10cSrcweir class OEmptyFunctionDescription : public IFunctionDescription
36cdf0e10cSrcweir {
37cdf0e10cSrcweir public:
OEmptyFunctionDescription()38cdf0e10cSrcweir OEmptyFunctionDescription(){}
~OEmptyFunctionDescription()39cdf0e10cSrcweir virtual ~OEmptyFunctionDescription(){}
40cdf0e10cSrcweir
getFunctionName() const41cdf0e10cSrcweir virtual ::rtl::OUString getFunctionName() const { return ::rtl::OUString(); }
getCategory() const42cdf0e10cSrcweir virtual const IFunctionCategory* getCategory() const { return NULL; }
getDescription() const43cdf0e10cSrcweir virtual ::rtl::OUString getDescription() const { return ::rtl::OUString(); }
getSuppressedArgumentCount() const44cdf0e10cSrcweir virtual xub_StrLen getSuppressedArgumentCount() const { return 0; }
getFormula(const::std::vector<::rtl::OUString> &) const45cdf0e10cSrcweir virtual ::rtl::OUString getFormula(const ::std::vector< ::rtl::OUString >& ) const { return ::rtl::OUString(); }
fillVisibleArgumentMapping(::std::vector<sal_uInt16> &) const46cdf0e10cSrcweir virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& ) const {}
initArgumentInfo() const47cdf0e10cSrcweir virtual void initArgumentInfo() const {}
getSignature() const48cdf0e10cSrcweir virtual ::rtl::OUString getSignature() const { return ::rtl::OUString(); }
getHelpId() const49cdf0e10cSrcweir virtual rtl::OString getHelpId() const { return ""; }
getParameterCount() const50cdf0e10cSrcweir virtual sal_uInt32 getParameterCount() const { return 0; }
getParameterName(sal_uInt32) const51cdf0e10cSrcweir virtual ::rtl::OUString getParameterName(sal_uInt32 ) const { return ::rtl::OUString(); }
getParameterDescription(sal_uInt32) const52cdf0e10cSrcweir virtual ::rtl::OUString getParameterDescription(sal_uInt32 ) const { return ::rtl::OUString(); }
isParameterOptional(sal_uInt32) const53cdf0e10cSrcweir virtual bool isParameterOptional(sal_uInt32 ) const { return sal_False; }
54cdf0e10cSrcweir };
55cdf0e10cSrcweir }
56cdf0e10cSrcweir //===================================================================
57cdf0e10cSrcweir // class FormulaHelper - statische Methoden
58cdf0e10cSrcweir //===================================================================
59cdf0e10cSrcweir
60cdf0e10cSrcweir #define FUNC_NOTFOUND 0xffff
61cdf0e10cSrcweir
FormulaHelper(const IFunctionManager * _pFunctionManager)62cdf0e10cSrcweir FormulaHelper::FormulaHelper(const IFunctionManager* _pFunctionManager)
63cdf0e10cSrcweir :m_pSysLocale(new SvtSysLocale)
64cdf0e10cSrcweir ,m_pFunctionManager(_pFunctionManager)
65cdf0e10cSrcweir ,open(_pFunctionManager->getSingleToken(IFunctionManager::eOk))
66cdf0e10cSrcweir ,close(_pFunctionManager->getSingleToken(IFunctionManager::eClose))
67cdf0e10cSrcweir ,sep(_pFunctionManager->getSingleToken(IFunctionManager::eSep))
68cdf0e10cSrcweir ,arrayOpen(_pFunctionManager->getSingleToken(IFunctionManager::eArrayOpen))
69cdf0e10cSrcweir ,arrayClose(_pFunctionManager->getSingleToken(IFunctionManager::eArrayClose))
70cdf0e10cSrcweir {
71cdf0e10cSrcweir m_pCharClass = m_pSysLocale->GetCharClassPtr();
72cdf0e10cSrcweir }
GetNextFunc(const String & rFormula,sal_Bool bBack,xub_StrLen & rFStart,xub_StrLen * pFEnd,const IFunctionDescription ** ppFDesc,::std::vector<::rtl::OUString> * pArgs) const73cdf0e10cSrcweir sal_Bool FormulaHelper::GetNextFunc( const String& rFormula,
74cdf0e10cSrcweir sal_Bool bBack,
75cdf0e10cSrcweir xub_StrLen& rFStart, // Ein- und Ausgabe
76cdf0e10cSrcweir xub_StrLen* pFEnd, // = NULL
77cdf0e10cSrcweir const IFunctionDescription** ppFDesc, // = NULL
78cdf0e10cSrcweir ::std::vector< ::rtl::OUString>* pArgs ) const // = NULL
79cdf0e10cSrcweir {
80cdf0e10cSrcweir sal_Bool bFound = sal_False;
81cdf0e10cSrcweir xub_StrLen nOldStart = rFStart;
82cdf0e10cSrcweir String aFname;
83cdf0e10cSrcweir
84cdf0e10cSrcweir rFStart = GetFunctionStart( rFormula, rFStart, bBack, ppFDesc ? &aFname : NULL );
85cdf0e10cSrcweir bFound = ( rFStart != FUNC_NOTFOUND );
86cdf0e10cSrcweir
87cdf0e10cSrcweir if ( bFound )
88cdf0e10cSrcweir {
89cdf0e10cSrcweir if ( pFEnd )
90cdf0e10cSrcweir *pFEnd = GetFunctionEnd( rFormula, rFStart );
91cdf0e10cSrcweir
92cdf0e10cSrcweir if ( ppFDesc )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir *ppFDesc = NULL;
95cdf0e10cSrcweir const ::rtl::OUString sTemp( aFname );
96cdf0e10cSrcweir const sal_uInt32 nCategoryCount = m_pFunctionManager->getCount();
97cdf0e10cSrcweir for(sal_uInt32 j= 0; j < nCategoryCount && !*ppFDesc; ++j)
98cdf0e10cSrcweir {
99cdf0e10cSrcweir const IFunctionCategory* pCategory = m_pFunctionManager->getCategory(j);
100cdf0e10cSrcweir const sal_uInt32 nCount = pCategory->getCount();
101cdf0e10cSrcweir for(sal_uInt32 i = 0 ; i < nCount; ++i)
102cdf0e10cSrcweir {
103cdf0e10cSrcweir const IFunctionDescription* pCurrent = pCategory->getFunction(i);
104cdf0e10cSrcweir if ( pCurrent->getFunctionName().equalsIgnoreAsciiCase(sTemp) )
105cdf0e10cSrcweir {
106cdf0e10cSrcweir *ppFDesc = pCurrent;
107cdf0e10cSrcweir break;
108cdf0e10cSrcweir }
109cdf0e10cSrcweir } // for(sal_uInt32 i = 0 ; i < nCount; ++i)
110cdf0e10cSrcweir }
111cdf0e10cSrcweir if ( *ppFDesc && pArgs )
112cdf0e10cSrcweir {
113cdf0e10cSrcweir GetArgStrings( *pArgs,rFormula, rFStart, static_cast<sal_uInt16>((*ppFDesc)->getParameterCount() ));
114cdf0e10cSrcweir }
115cdf0e10cSrcweir else
116cdf0e10cSrcweir {
117cdf0e10cSrcweir static OEmptyFunctionDescription s_aFunctionDescription;
118cdf0e10cSrcweir *ppFDesc = &s_aFunctionDescription;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir }
121cdf0e10cSrcweir }
122cdf0e10cSrcweir else
123cdf0e10cSrcweir rFStart = nOldStart;
124cdf0e10cSrcweir
125cdf0e10cSrcweir return bFound;
126cdf0e10cSrcweir }
127cdf0e10cSrcweir
128cdf0e10cSrcweir //------------------------------------------------------------------------
129cdf0e10cSrcweir
FillArgStrings(const String & rFormula,xub_StrLen nFuncPos,sal_uInt16 nArgs,::std::vector<::rtl::OUString> & _rArgs) const130cdf0e10cSrcweir void FormulaHelper::FillArgStrings( const String& rFormula,
131cdf0e10cSrcweir xub_StrLen nFuncPos,
132cdf0e10cSrcweir sal_uInt16 nArgs,
133cdf0e10cSrcweir ::std::vector< ::rtl::OUString >& _rArgs ) const
134cdf0e10cSrcweir {
135cdf0e10cSrcweir xub_StrLen nStart = 0;
136cdf0e10cSrcweir xub_StrLen nEnd = 0;
137cdf0e10cSrcweir sal_uInt16 i;
138cdf0e10cSrcweir sal_Bool bLast = sal_False;
139cdf0e10cSrcweir
140cdf0e10cSrcweir for ( i=0; i<nArgs && !bLast; i++ )
141cdf0e10cSrcweir {
142cdf0e10cSrcweir nStart = GetArgStart( rFormula, nFuncPos, i );
143cdf0e10cSrcweir
144cdf0e10cSrcweir if ( i+1<nArgs ) // letztes Argument?
145cdf0e10cSrcweir {
146cdf0e10cSrcweir nEnd = GetArgStart( rFormula, nFuncPos, i+1 );
147cdf0e10cSrcweir
148cdf0e10cSrcweir if ( nEnd != nStart )
149cdf0e10cSrcweir _rArgs.push_back(rFormula.Copy( nStart, nEnd-1-nStart ));
150cdf0e10cSrcweir else
151cdf0e10cSrcweir _rArgs.push_back(String()), bLast = sal_True;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir else
154cdf0e10cSrcweir {
155cdf0e10cSrcweir nEnd = GetFunctionEnd( rFormula, nFuncPos )-1;
156cdf0e10cSrcweir if ( nStart < nEnd )
157cdf0e10cSrcweir _rArgs.push_back( rFormula.Copy( nStart, nEnd-nStart ) );
158cdf0e10cSrcweir else
159cdf0e10cSrcweir _rArgs.push_back(String());
160cdf0e10cSrcweir }
161cdf0e10cSrcweir }
162cdf0e10cSrcweir
163cdf0e10cSrcweir if ( bLast )
164cdf0e10cSrcweir for ( ; i<nArgs; i++ )
165cdf0e10cSrcweir _rArgs.push_back(String());
166cdf0e10cSrcweir }
167cdf0e10cSrcweir
168cdf0e10cSrcweir //------------------------------------------------------------------------
169cdf0e10cSrcweir
GetArgStrings(::std::vector<::rtl::OUString> & _rArgs,const String & rFormula,xub_StrLen nFuncPos,sal_uInt16 nArgs) const170cdf0e10cSrcweir void FormulaHelper::GetArgStrings( ::std::vector< ::rtl::OUString >& _rArgs
171cdf0e10cSrcweir ,const String& rFormula,
172cdf0e10cSrcweir xub_StrLen nFuncPos,
173cdf0e10cSrcweir sal_uInt16 nArgs ) const
174cdf0e10cSrcweir {
175cdf0e10cSrcweir if (nArgs)
176cdf0e10cSrcweir {
177cdf0e10cSrcweir FillArgStrings( rFormula, nFuncPos, nArgs, _rArgs );
178cdf0e10cSrcweir }
179cdf0e10cSrcweir }
180cdf0e10cSrcweir
181cdf0e10cSrcweir //------------------------------------------------------------------------
182cdf0e10cSrcweir
IsFormulaText(const CharClass * _pCharClass,const String & rStr,xub_StrLen nPos)183cdf0e10cSrcweir inline sal_Bool IsFormulaText( const CharClass* _pCharClass,const String& rStr, xub_StrLen nPos )
184cdf0e10cSrcweir {
185cdf0e10cSrcweir if( _pCharClass->isLetterNumeric( rStr, nPos ) )
186cdf0e10cSrcweir return sal_True;
187cdf0e10cSrcweir else
188cdf0e10cSrcweir { // In internationalized versions function names may contain a dot
189cdf0e10cSrcweir // and in every version also an underscore... ;-)
190cdf0e10cSrcweir sal_Unicode c = rStr.GetChar(nPos);
191cdf0e10cSrcweir return c == '.' || c == '_';
192cdf0e10cSrcweir }
193cdf0e10cSrcweir
194cdf0e10cSrcweir }
195cdf0e10cSrcweir
GetFunctionStart(const String & rFormula,xub_StrLen nStart,sal_Bool bBack,String * pFuncName) const196cdf0e10cSrcweir xub_StrLen FormulaHelper::GetFunctionStart( const String& rFormula,
197cdf0e10cSrcweir xub_StrLen nStart,
198cdf0e10cSrcweir sal_Bool bBack,
199cdf0e10cSrcweir String* pFuncName ) const
200cdf0e10cSrcweir {
201cdf0e10cSrcweir xub_StrLen nStrLen = rFormula.Len();
202cdf0e10cSrcweir
203cdf0e10cSrcweir if ( nStrLen < nStart )
204cdf0e10cSrcweir return nStart;
205cdf0e10cSrcweir
206cdf0e10cSrcweir xub_StrLen nFStart = FUNC_NOTFOUND;
207cdf0e10cSrcweir xub_StrLen nParPos = nStart;
208cdf0e10cSrcweir
209cdf0e10cSrcweir sal_Bool bRepeat, bFound;
210cdf0e10cSrcweir do
211cdf0e10cSrcweir {
212cdf0e10cSrcweir bFound = sal_False;
213cdf0e10cSrcweir bRepeat = sal_False;
214cdf0e10cSrcweir
215cdf0e10cSrcweir if ( bBack )
216cdf0e10cSrcweir {
217cdf0e10cSrcweir while ( !bFound && (nParPos > 0) )
218cdf0e10cSrcweir {
219cdf0e10cSrcweir if ( rFormula.GetChar(nParPos) == '"' )
220cdf0e10cSrcweir {
221cdf0e10cSrcweir nParPos--;
222cdf0e10cSrcweir while ( (nParPos > 0) && rFormula.GetChar(nParPos) != '"' )
223cdf0e10cSrcweir nParPos--;
224cdf0e10cSrcweir if (nParPos > 0)
225cdf0e10cSrcweir nParPos--;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir else if ( (bFound = ( rFormula.GetChar(nParPos) == '(' ) ) == sal_False )
228cdf0e10cSrcweir nParPos--;
229cdf0e10cSrcweir }
230cdf0e10cSrcweir }
231cdf0e10cSrcweir else
232cdf0e10cSrcweir {
233cdf0e10cSrcweir while ( !bFound && (nParPos < nStrLen) )
234cdf0e10cSrcweir {
235cdf0e10cSrcweir if ( rFormula.GetChar(nParPos) == '"' )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir nParPos++;
238cdf0e10cSrcweir while ( (nParPos < nStrLen) && rFormula.GetChar(nParPos) != '"' )
239cdf0e10cSrcweir nParPos++;
240cdf0e10cSrcweir nParPos++;
241cdf0e10cSrcweir }
242cdf0e10cSrcweir else if ( (bFound = ( rFormula.GetChar(nParPos) == '(' ) ) == sal_False )
243cdf0e10cSrcweir nParPos++;
244cdf0e10cSrcweir }
245cdf0e10cSrcweir }
246cdf0e10cSrcweir
247cdf0e10cSrcweir if ( bFound && (nParPos > 0) )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir nFStart = nParPos-1;
250cdf0e10cSrcweir
251cdf0e10cSrcweir while ( (nFStart > 0) && IsFormulaText(m_pCharClass, rFormula, nFStart ))
252cdf0e10cSrcweir nFStart--;
253cdf0e10cSrcweir }
254cdf0e10cSrcweir
255cdf0e10cSrcweir nFStart++;
256cdf0e10cSrcweir
257cdf0e10cSrcweir if ( bFound )
258cdf0e10cSrcweir {
259cdf0e10cSrcweir if ( IsFormulaText( m_pCharClass,rFormula, nFStart ) )
260cdf0e10cSrcweir {
261cdf0e10cSrcweir // Funktion gefunden
262cdf0e10cSrcweir if ( pFuncName )
263cdf0e10cSrcweir *pFuncName = rFormula.Copy( nFStart, nParPos-nFStart );
264cdf0e10cSrcweir }
265cdf0e10cSrcweir else // Klammern ohne Funktion -> weitersuchen
266cdf0e10cSrcweir {
267cdf0e10cSrcweir bRepeat = sal_True;
268cdf0e10cSrcweir if ( !bBack )
269cdf0e10cSrcweir nParPos++;
270cdf0e10cSrcweir else if (nParPos > 0)
271cdf0e10cSrcweir nParPos--;
272cdf0e10cSrcweir else
273cdf0e10cSrcweir bRepeat = sal_False;
274cdf0e10cSrcweir }
275cdf0e10cSrcweir }
276cdf0e10cSrcweir else // keine Klammern gefunden
277cdf0e10cSrcweir {
278cdf0e10cSrcweir nFStart = FUNC_NOTFOUND;
279cdf0e10cSrcweir if ( pFuncName )
280cdf0e10cSrcweir pFuncName->Erase();
281cdf0e10cSrcweir }
282cdf0e10cSrcweir }
283cdf0e10cSrcweir while(bRepeat);
284cdf0e10cSrcweir
285cdf0e10cSrcweir return nFStart;
286cdf0e10cSrcweir }
287cdf0e10cSrcweir
288cdf0e10cSrcweir //------------------------------------------------------------------------
289cdf0e10cSrcweir
GetFunctionEnd(const String & rStr,xub_StrLen nStart) const290cdf0e10cSrcweir xub_StrLen FormulaHelper::GetFunctionEnd( const String& rStr, xub_StrLen nStart ) const
291cdf0e10cSrcweir {
292cdf0e10cSrcweir xub_StrLen nStrLen = rStr.Len();
293cdf0e10cSrcweir
294cdf0e10cSrcweir if ( nStrLen < nStart )
295cdf0e10cSrcweir return nStart;
296cdf0e10cSrcweir
297cdf0e10cSrcweir short nParCount = 0;
298cdf0e10cSrcweir bool bInArray = false;
299cdf0e10cSrcweir sal_Bool bFound = sal_False;
300cdf0e10cSrcweir
301cdf0e10cSrcweir while ( !bFound && (nStart < nStrLen) )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir sal_Unicode c = rStr.GetChar(nStart);
304cdf0e10cSrcweir
305cdf0e10cSrcweir if ( c == '"' )
306cdf0e10cSrcweir {
307cdf0e10cSrcweir nStart++;
308cdf0e10cSrcweir while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
309cdf0e10cSrcweir nStart++;
310cdf0e10cSrcweir }
311cdf0e10cSrcweir else if ( c == open )
312cdf0e10cSrcweir nParCount++;
313cdf0e10cSrcweir else if ( c == close )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir nParCount--;
316cdf0e10cSrcweir if ( nParCount == 0 )
317cdf0e10cSrcweir bFound = sal_True;
318cdf0e10cSrcweir else if ( nParCount < 0 )
319cdf0e10cSrcweir {
320cdf0e10cSrcweir bFound = sal_True;
321cdf0e10cSrcweir nStart--; // einen zu weit gelesen
322cdf0e10cSrcweir }
323cdf0e10cSrcweir }
324cdf0e10cSrcweir else if ( c == arrayOpen )
325cdf0e10cSrcweir {
326cdf0e10cSrcweir bInArray = true;
327cdf0e10cSrcweir }
328cdf0e10cSrcweir else if ( c == arrayClose )
329cdf0e10cSrcweir {
330cdf0e10cSrcweir bInArray = false;
331cdf0e10cSrcweir }
332cdf0e10cSrcweir else if ( c == sep )
333cdf0e10cSrcweir {
334cdf0e10cSrcweir if ( !bInArray && nParCount == 0 )
335cdf0e10cSrcweir {
336cdf0e10cSrcweir bFound = sal_True;
337cdf0e10cSrcweir nStart--; // einen zu weit gelesen
338cdf0e10cSrcweir }
339cdf0e10cSrcweir }
340cdf0e10cSrcweir nStart++; // hinter gefundene Position stellen
341cdf0e10cSrcweir }
342cdf0e10cSrcweir
343cdf0e10cSrcweir return nStart;
344cdf0e10cSrcweir }
345cdf0e10cSrcweir
346cdf0e10cSrcweir //------------------------------------------------------------------
347cdf0e10cSrcweir
GetArgStart(const String & rStr,xub_StrLen nStart,sal_uInt16 nArg) const348cdf0e10cSrcweir xub_StrLen FormulaHelper::GetArgStart( const String& rStr, xub_StrLen nStart, sal_uInt16 nArg ) const
349cdf0e10cSrcweir {
350cdf0e10cSrcweir xub_StrLen nStrLen = rStr.Len();
351cdf0e10cSrcweir
352cdf0e10cSrcweir if ( nStrLen < nStart )
353cdf0e10cSrcweir return nStart;
354cdf0e10cSrcweir
355cdf0e10cSrcweir short nParCount = 0;
356cdf0e10cSrcweir bool bInArray = false;
357cdf0e10cSrcweir sal_Bool bFound = sal_False;
358cdf0e10cSrcweir
359cdf0e10cSrcweir while ( !bFound && (nStart < nStrLen) )
360cdf0e10cSrcweir {
361cdf0e10cSrcweir sal_Unicode c = rStr.GetChar(nStart);
362cdf0e10cSrcweir
363cdf0e10cSrcweir if ( c == '"' )
364cdf0e10cSrcweir {
365cdf0e10cSrcweir nStart++;
366cdf0e10cSrcweir while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
367cdf0e10cSrcweir nStart++;
368cdf0e10cSrcweir }
369cdf0e10cSrcweir else if ( c == open )
370cdf0e10cSrcweir {
371cdf0e10cSrcweir bFound = ( nArg == 0 );
372cdf0e10cSrcweir nParCount++;
373cdf0e10cSrcweir }
374cdf0e10cSrcweir else if ( c == close )
375cdf0e10cSrcweir {
376cdf0e10cSrcweir nParCount--;
377cdf0e10cSrcweir bFound = ( nParCount == 0 );
378cdf0e10cSrcweir }
379cdf0e10cSrcweir else if ( c == arrayOpen )
380cdf0e10cSrcweir {
381cdf0e10cSrcweir bInArray = true;
382cdf0e10cSrcweir }
383cdf0e10cSrcweir else if ( c == arrayClose )
384cdf0e10cSrcweir {
385cdf0e10cSrcweir bInArray = false;
386cdf0e10cSrcweir }
387cdf0e10cSrcweir else if ( c == sep )
388cdf0e10cSrcweir {
389cdf0e10cSrcweir if ( !bInArray && nParCount == 1 )
390cdf0e10cSrcweir {
391cdf0e10cSrcweir nArg--;
392cdf0e10cSrcweir bFound = ( nArg == 0 );
393cdf0e10cSrcweir }
394cdf0e10cSrcweir }
395cdf0e10cSrcweir nStart++;
396cdf0e10cSrcweir }
397cdf0e10cSrcweir
398cdf0e10cSrcweir return nStart;
399cdf0e10cSrcweir }
400cdf0e10cSrcweir // =============================================================================
401cdf0e10cSrcweir } // formula
402cdf0e10cSrcweir // =============================================================================
403