1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <formula/formulahelper.hxx>
23 #include <formula/IFunctionDescription.hxx>
24 #include <unotools/charclass.hxx>
25 #include <unotools/syslocale.hxx>
33 class OEmptyFunctionDescription
: public IFunctionDescription
36 OEmptyFunctionDescription(){}
37 virtual ~OEmptyFunctionDescription(){}
39 virtual OUString
getFunctionName() const override
{ return OUString(); }
40 virtual const IFunctionCategory
* getCategory() const override
{ return nullptr; }
41 virtual OUString
getDescription() const override
{ return OUString(); }
42 virtual sal_Int32
getSuppressedArgumentCount() const override
{ return 0; }
43 virtual OUString
getFormula(const ::std::vector
< OUString
>& ) const override
{ return OUString(); }
44 virtual void fillVisibleArgumentMapping(::std::vector
<sal_uInt16
>& ) const override
{}
45 virtual void initArgumentInfo() const override
{}
46 virtual OUString
getSignature() const override
{ return OUString(); }
47 virtual OString
getHelpId() const override
{ return ""; }
48 virtual bool isHidden() const override
{ return false; }
49 virtual sal_uInt32
getParameterCount() const override
{ return 0; }
50 virtual sal_uInt32
getVarArgsStart() const override
{ return 0; }
51 virtual OUString
getParameterName(sal_uInt32
) const override
{ return OUString(); }
52 virtual OUString
getParameterDescription(sal_uInt32
) const override
{ return OUString(); }
53 virtual bool isParameterOptional(sal_uInt32
) const override
{ return false; }
57 // class FormulaHelper - static Method
60 #define FUNC_NOTFOUND -1
62 FormulaHelper::FormulaHelper(const IFunctionManager
* _pFunctionManager
)
63 :m_pSysLocale(new SvtSysLocale
)
64 ,m_pFunctionManager(_pFunctionManager
)
65 ,open(_pFunctionManager
->getSingleToken(IFunctionManager::eOk
))
66 ,close(_pFunctionManager
->getSingleToken(IFunctionManager::eClose
))
67 ,sep(_pFunctionManager
->getSingleToken(IFunctionManager::eSep
))
68 ,arrayOpen(_pFunctionManager
->getSingleToken(IFunctionManager::eArrayOpen
))
69 ,arrayClose(_pFunctionManager
->getSingleToken(IFunctionManager::eArrayClose
))
71 m_pCharClass
= m_pSysLocale
->GetCharClassPtr();
74 bool FormulaHelper::GetNextFunc( const OUString
& rFormula
,
76 sal_Int32
& rFStart
, // Input and output
77 sal_Int32
* pFEnd
, // = NULL
78 const IFunctionDescription
** ppFDesc
, // = NULL
79 ::std::vector
< OUString
>* pArgs
) const // = NULL
81 sal_Int32 nOldStart
= rFStart
;
84 rFStart
= GetFunctionStart( rFormula
, rFStart
, bBack
, ppFDesc
? &aFname
: nullptr );
85 bool bFound
= ( rFStart
!= FUNC_NOTFOUND
);
90 *pFEnd
= GetFunctionEnd( rFormula
, rFStart
);
95 const sal_uInt32 nCategoryCount
= m_pFunctionManager
->getCount();
96 for(sal_uInt32 j
= 0; j
< nCategoryCount
&& !*ppFDesc
; ++j
)
98 const IFunctionCategory
* pCategory
= m_pFunctionManager
->getCategory(j
);
99 const sal_uInt32 nCount
= pCategory
->getCount();
100 for(sal_uInt32 i
= 0 ; i
< nCount
; ++i
)
102 const IFunctionDescription
* pCurrent
= pCategory
->getFunction(i
);
103 if ( pCurrent
->getFunctionName().equalsIgnoreAsciiCase(aFname
) )
108 }// for(sal_uInt32 i = 0 ; i < nCount; ++i)
110 if ( *ppFDesc
&& pArgs
)
112 GetArgStrings( *pArgs
,rFormula
, rFStart
, static_cast<sal_uInt16
>((*ppFDesc
)->getParameterCount() ));
116 static OEmptyFunctionDescription s_aFunctionDescription
;
117 *ppFDesc
= &s_aFunctionDescription
;
128 void FormulaHelper::FillArgStrings( const OUString
& rFormula
,
131 ::std::vector
< OUString
>& _rArgs
) const
133 sal_Int32 nStart
= 0;
138 for ( i
=0; i
<nArgs
&& !bLast
; i
++ )
140 nStart
= GetArgStart( rFormula
, nFuncPos
, i
);
142 if ( i
+1<nArgs
) // last argument?
144 nEnd
= GetArgStart( rFormula
, nFuncPos
, i
+1 );
146 if ( nEnd
!= nStart
)
147 _rArgs
.push_back(rFormula
.copy( nStart
, nEnd
-1-nStart
));
150 _rArgs
.emplace_back();
156 nEnd
= GetFunctionEnd( rFormula
, nFuncPos
)-1;
158 _rArgs
.push_back( rFormula
.copy( nStart
, nEnd
-nStart
) );
160 _rArgs
.emplace_back();
165 for ( ; i
<nArgs
; i
++ )
166 _rArgs
.emplace_back();
170 void FormulaHelper::GetArgStrings( ::std::vector
< OUString
>& _rArgs
,
171 const OUString
& rFormula
,
173 sal_uInt16 nArgs
) const
177 FillArgStrings( rFormula
, nFuncPos
, nArgs
, _rArgs
);
182 static bool IsFormulaText( const CharClass
* _pCharClass
,const OUString
& rStr
, sal_Int32 nPos
)
184 if( _pCharClass
->isLetterNumeric( rStr
, nPos
) )
187 { // In internationalized versions function names may contain a dot
188 // and in every version also an underscore... ;-)
189 sal_Unicode c
= rStr
[nPos
];
190 return c
== '.' || c
== '_';
195 sal_Int32
FormulaHelper::GetFunctionStart( const OUString
& rFormula
,
198 OUString
* pFuncName
) const
200 sal_Int32 nStrLen
= rFormula
.getLength();
202 if ( nStrLen
< nStart
)
205 sal_Int32 nFStart
= FUNC_NOTFOUND
;
206 sal_Int32 nParPos
= bBack
? ::std::min( nStart
, nStrLen
- 1) : nStart
;
216 while ( !bFound
&& (nParPos
> 0) )
218 if ( rFormula
[nParPos
] == '"' )
221 while ( (nParPos
> 0) && rFormula
[nParPos
] != '"' )
228 bFound
= rFormula
[nParPos
] == '(';
236 while ( !bFound
&& (0 <= nParPos
&& nParPos
< nStrLen
) )
238 if ( rFormula
[nParPos
] == '"' )
241 while ( (nParPos
< nStrLen
) && rFormula
[nParPos
] != '"' )
247 bFound
= rFormula
[nParPos
] == '(';
254 if ( bFound
&& (nParPos
> 0) )
258 while ( (nFStart
> 0) && IsFormulaText(m_pCharClass
, rFormula
, nFStart
))
266 if ( IsFormulaText( m_pCharClass
,rFormula
, nFStart
) )
270 *pFuncName
= rFormula
.copy( nFStart
, nParPos
-nFStart
);
272 else // Brackets without function -> keep searching
277 else if (nParPos
> 0)
283 else // No brackets found
285 nFStart
= FUNC_NOTFOUND
;
296 sal_Int32
FormulaHelper::GetFunctionEnd( const OUString
& rStr
, sal_Int32 nStart
) const
298 sal_Int32 nStrLen
= rStr
.getLength();
300 if ( nStrLen
< nStart
)
304 bool bInArray
= false;
307 while ( !bFound
&& (nStart
< nStrLen
) )
309 sal_Unicode c
= rStr
[nStart
];
314 while ( (nStart
< nStrLen
) && rStr
[nStart
] != '"' )
317 else if ( c
== open
)
319 else if ( c
== close
)
322 if ( nParCount
== 0 )
324 else if ( nParCount
< 0 )
327 nStart
--; // read one too far
330 else if ( c
== arrayOpen
)
334 else if ( c
== arrayClose
)
340 if ( !bInArray
&& nParCount
== 0 )
343 nStart
--; // read one too far
346 nStart
++; // Set behind found position
353 sal_Int32
FormulaHelper::GetArgStart( const OUString
& rStr
, sal_Int32 nStart
, sal_uInt16 nArg
) const
355 sal_Int32 nStrLen
= rStr
.getLength();
357 if ( nStrLen
< nStart
)
361 bool bInArray
= false;
364 while ( !bFound
&& (nStart
< nStrLen
) )
366 sal_Unicode c
= rStr
[nStart
];
371 while ( (nStart
< nStrLen
) && rStr
[nStart
] != '"' )
374 else if ( c
== open
)
376 bFound
= ( nArg
== 0 );
379 else if ( c
== close
)
382 bFound
= ( nParCount
== 0 );
384 else if ( c
== arrayOpen
)
388 else if ( c
== arrayClose
)
394 if ( !bInArray
&& nParCount
== 1 )
397 bFound
= ( nArg
== 0 );
409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */