xref: /trunk/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