xref: /trunk/main/formula/source/ui/dlg/FormulaHelper.cxx (revision c25918c1c543b2e4817410a4e7739607dba55e06)
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
10cdf0e10cSrcweir  *
11*c25918c1SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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:
38cdf0e10cSrcweir             OEmptyFunctionDescription(){}
39cdf0e10cSrcweir             virtual ~OEmptyFunctionDescription(){}
40cdf0e10cSrcweir 
41cdf0e10cSrcweir             virtual ::rtl::OUString getFunctionName() const { return ::rtl::OUString(); }
42cdf0e10cSrcweir             virtual const IFunctionCategory* getCategory() const { return NULL; }
43cdf0e10cSrcweir             virtual ::rtl::OUString getDescription() const { return ::rtl::OUString(); }
44cdf0e10cSrcweir             virtual xub_StrLen getSuppressedArgumentCount() const { return 0; }
45cdf0e10cSrcweir             virtual ::rtl::OUString getFormula(const ::std::vector< ::rtl::OUString >& ) const { return ::rtl::OUString(); }
46cdf0e10cSrcweir             virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& ) const {}
47cdf0e10cSrcweir             virtual void initArgumentInfo()  const {}
48cdf0e10cSrcweir             virtual ::rtl::OUString getSignature() const { return ::rtl::OUString(); }
49cdf0e10cSrcweir             virtual rtl::OString getHelpId() const { return ""; }
50cdf0e10cSrcweir             virtual sal_uInt32 getParameterCount() const { return 0; }
51cdf0e10cSrcweir             virtual ::rtl::OUString getParameterName(sal_uInt32 ) const { return ::rtl::OUString(); }
52cdf0e10cSrcweir             virtual ::rtl::OUString getParameterDescription(sal_uInt32 ) const { return ::rtl::OUString(); }
53cdf0e10cSrcweir             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 
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 }
73cdf0e10cSrcweir 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 
130cdf0e10cSrcweir 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 
170cdf0e10cSrcweir 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 
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 
196cdf0e10cSrcweir 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 
290cdf0e10cSrcweir 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 
348cdf0e10cSrcweir 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