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/.
12 #include <com/sun/star/uno/Any.hxx>
13 #include <com/sun/star/uno/Sequence.hxx>
14 #include <com/sun/star/lang/Locale.hpp>
15 #include <com/sun/star/i18n/LocaleDataItem.hpp>
16 #include <osl/diagnose.h>
18 #include "formulaopt.hxx"
19 #include "miscuno.hxx"
21 #include "formulagroup.hxx"
24 using namespace com::sun::star::uno
;
25 namespace lang
= ::com::sun::star::lang
;
26 using ::com::sun::star::i18n::LocaleDataItem
;
28 TYPEINIT1(ScTpFormulaItem
, SfxPoolItem
);
30 ScFormulaOptions::ScFormulaOptions()
35 ScFormulaOptions::ScFormulaOptions( const ScFormulaOptions
& rCpy
) :
36 bUseEnglishFuncName ( rCpy
.bUseEnglishFuncName
),
37 eFormulaGrammar ( rCpy
.eFormulaGrammar
),
38 aCalcConfig(rCpy
.aCalcConfig
),
39 aFormulaSepArg ( rCpy
.aFormulaSepArg
),
40 aFormulaSepArrayRow ( rCpy
.aFormulaSepArrayRow
),
41 aFormulaSepArrayCol ( rCpy
.aFormulaSepArrayCol
),
42 meOOXMLRecalc ( rCpy
.meOOXMLRecalc
),
43 meODFRecalc ( rCpy
.meODFRecalc
)
47 ScFormulaOptions::~ScFormulaOptions()
51 void ScFormulaOptions::SetDefaults()
53 bUseEnglishFuncName
= false;
54 eFormulaGrammar
= ::formula::FormulaGrammar::GRAM_NATIVE
;
55 meOOXMLRecalc
= RECALC_ASK
;
56 meODFRecalc
= RECALC_ASK
;
58 // unspecified means use the current formula syntax.
61 ResetFormulaSeparators();
64 void ScFormulaOptions::ResetFormulaSeparators()
66 GetDefaultFormulaSeparators(aFormulaSepArg
, aFormulaSepArrayCol
, aFormulaSepArrayRow
);
69 void ScFormulaOptions::GetDefaultFormulaSeparators(
70 OUString
& rSepArg
, OUString
& rSepArrayCol
, OUString
& rSepArrayRow
)
72 // Defaults to the old separator values.
77 const lang::Locale
& rLocale
= *ScGlobal::GetLocale();
78 const OUString
& rLang
= rLocale
.Language
;
80 // Don't do automatic guess for these languages, and fall back to
81 // the old separator set.
84 const LocaleDataWrapper
& rLocaleData
= GetLocaleDataWrapper();
85 const OUString
& rDecSep
= rLocaleData
.getNumDecimalSep();
86 const OUString
& rListSep
= rLocaleData
.getListSep();
88 if (rDecSep
.isEmpty() || rListSep
.isEmpty())
89 // Something is wrong. Stick with the default separators.
92 sal_Unicode cDecSep
= rDecSep
[0];
93 sal_Unicode cListSep
= rListSep
[0];
95 // Excel by default uses system's list separator as the parameter
96 // separator, which in English locales is a comma. However, OOo's list
97 // separator value is set to ';' for all English locales. Because of this
98 // discrepancy, we will hardcode the separator value here, for now.
102 // Special case for de_CH locale.
103 if (rLocale
.Language
== "de" && rLocale
.Country
== "CH")
106 // by default, the parameter separator equals the locale-specific
108 rSepArg
= OUString(cListSep
);
110 if (cDecSep
== cListSep
&& cDecSep
!= ';')
111 // if the decimal and list separators are equal, set the
112 // parameter separator to be ';', unless they are both
113 // semicolon in which case don't change the decimal separator.
122 const LocaleDataWrapper
& ScFormulaOptions::GetLocaleDataWrapper()
124 return *ScGlobal::pLocaleData
;
127 ScFormulaOptions
& ScFormulaOptions::operator=( const ScFormulaOptions
& rCpy
)
129 bUseEnglishFuncName
= rCpy
.bUseEnglishFuncName
;
130 eFormulaGrammar
= rCpy
.eFormulaGrammar
;
131 aCalcConfig
= rCpy
.aCalcConfig
;
132 aFormulaSepArg
= rCpy
.aFormulaSepArg
;
133 aFormulaSepArrayRow
= rCpy
.aFormulaSepArrayRow
;
134 aFormulaSepArrayCol
= rCpy
.aFormulaSepArrayCol
;
135 meOOXMLRecalc
= rCpy
.meOOXMLRecalc
;
136 meODFRecalc
= rCpy
.meODFRecalc
;
140 bool ScFormulaOptions::operator==( const ScFormulaOptions
& rOpt
) const
142 return bUseEnglishFuncName
== rOpt
.bUseEnglishFuncName
143 && eFormulaGrammar
== rOpt
.eFormulaGrammar
144 && aCalcConfig
== rOpt
.aCalcConfig
145 && aFormulaSepArg
== rOpt
.aFormulaSepArg
146 && aFormulaSepArrayRow
== rOpt
.aFormulaSepArrayRow
147 && aFormulaSepArrayCol
== rOpt
.aFormulaSepArrayCol
148 && meOOXMLRecalc
== rOpt
.meOOXMLRecalc
149 && meODFRecalc
== rOpt
.meODFRecalc
;
152 bool ScFormulaOptions::operator!=( const ScFormulaOptions
& rOpt
) const
154 return !(operator==(rOpt
));
157 ScTpFormulaItem::ScTpFormulaItem( sal_uInt16 nWhichP
, const ScFormulaOptions
& rOpt
) :
158 SfxPoolItem ( nWhichP
),
163 ScTpFormulaItem::ScTpFormulaItem( const ScTpFormulaItem
& rItem
) :
164 SfxPoolItem ( rItem
),
165 theOptions ( rItem
.theOptions
)
169 ScTpFormulaItem::~ScTpFormulaItem()
173 bool ScTpFormulaItem::operator==( const SfxPoolItem
& rItem
) const
175 assert(SfxPoolItem::operator==(rItem
));
177 const ScTpFormulaItem
& rPItem
= static_cast<const ScTpFormulaItem
&>(rItem
);
178 return ( theOptions
== rPItem
.theOptions
);
181 SfxPoolItem
* ScTpFormulaItem::Clone( SfxItemPool
* ) const
183 return new ScTpFormulaItem( *this );
186 #define CFGPATH_FORMULA "Office.Calc/Formula"
188 #define SCFORMULAOPT_GRAMMAR 0
189 #define SCFORMULAOPT_ENGLISH_FUNCNAME 1
190 #define SCFORMULAOPT_SEP_ARG 2
191 #define SCFORMULAOPT_SEP_ARRAY_ROW 3
192 #define SCFORMULAOPT_SEP_ARRAY_COL 4
193 #define SCFORMULAOPT_STRING_REF_SYNTAX 5
194 #define SCFORMULAOPT_STRING_CONVERSION 6
195 #define SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO 7
196 #define SCFORMULAOPT_OOXML_RECALC 8
197 #define SCFORMULAOPT_ODF_RECALC 9
198 #define SCFORMULAOPT_OPENCL_AUTOSELECT 10
199 #define SCFORMULAOPT_OPENCL_DEVICE 11
200 #define SCFORMULAOPT_OPENCL_SUBSET_ONLY 12
201 #define SCFORMULAOPT_OPENCL_MIN_SIZE 13
202 #define SCFORMULAOPT_OPENCL_SUBSET_OPS 14
203 #define SCFORMULAOPT_COUNT 15
205 Sequence
<OUString
> ScFormulaCfg::GetPropertyNames()
207 static const char* aPropNames
[] =
209 "Syntax/Grammar", // SCFORMULAOPT_GRAMMAR
210 "Syntax/EnglishFunctionName", // SCFORMULAOPT_ENGLISH_FUNCNAME
211 "Syntax/SeparatorArg", // SCFORMULAOPT_SEP_ARG
212 "Syntax/SeparatorArrayRow", // SCFORMULAOPT_SEP_ARRAY_ROW
213 "Syntax/SeparatorArrayCol", // SCFORMULAOPT_SEP_ARRAY_COL
214 "Syntax/StringRefAddressSyntax", // SCFORMULAOPT_STRING_REF_SYNTAX
215 "Syntax/StringConversion", // SCFORMULAOPT_STRING_CONVERSION
216 "Syntax/EmptyStringAsZero", // SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO
217 "Load/OOXMLRecalcMode", // SCFORMULAOPT_OOXML_RECALC
218 "Load/ODFRecalcMode", // SCFORMULAOPT_ODF_RECALC
219 "Calculation/OpenCLAutoSelect", // SCFORMULAOPT_OPENCL_AUTOSELECT
220 "Calculation/OpenCLDevice", // SCFORMULAOPT_OPENCL_DEVICE
221 "Calculation/OpenCLSubsetOnly", // SCFORMULAOPT_OPENCL_SUBSET_ONLY
222 "Calculation/OpenCLMinimumDataSize", // SCFORMULAOPT_OPENCL_MIN_SIZE
223 "Calculation/OpenCLSubsetOpCodes", // SCFORMULAOPT_OPENCL_SUBSET_OPS
225 Sequence
<OUString
> aNames(SCFORMULAOPT_COUNT
);
226 OUString
* pNames
= aNames
.getArray();
227 for (int i
= 0; i
< SCFORMULAOPT_COUNT
; ++i
)
228 pNames
[i
] = OUString::createFromAscii(aPropNames
[i
]);
233 ScFormulaCfg::PropsToIds
ScFormulaCfg::GetPropNamesToId()
235 Sequence
<OUString
> aPropNames
= GetPropertyNames();
236 static sal_uInt16 aVals
[] = {
237 SCFORMULAOPT_GRAMMAR
,
238 SCFORMULAOPT_ENGLISH_FUNCNAME
,
239 SCFORMULAOPT_SEP_ARG
,
240 SCFORMULAOPT_SEP_ARRAY_ROW
,
241 SCFORMULAOPT_SEP_ARRAY_COL
,
242 SCFORMULAOPT_STRING_REF_SYNTAX
,
243 SCFORMULAOPT_STRING_CONVERSION
,
244 SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO
,
245 SCFORMULAOPT_OOXML_RECALC
,
246 SCFORMULAOPT_ODF_RECALC
,
247 SCFORMULAOPT_OPENCL_AUTOSELECT
,
248 SCFORMULAOPT_OPENCL_DEVICE
,
249 SCFORMULAOPT_OPENCL_SUBSET_ONLY
,
250 SCFORMULAOPT_OPENCL_MIN_SIZE
,
251 SCFORMULAOPT_OPENCL_SUBSET_OPS
,
253 OSL_ENSURE( SAL_N_ELEMENTS(aVals
) == aPropNames
.getLength(), "Properties and ids are out of Sync");
254 PropsToIds aPropIdMap
;
255 for ( sal_uInt16 i
=0; i
<aPropNames
.getLength(); ++i
)
256 aPropIdMap
[aPropNames
[i
]] = aVals
[ i
];
260 ScFormulaCfg::ScFormulaCfg() :
261 ConfigItem( OUString( CFGPATH_FORMULA
) )
263 Sequence
<OUString
> aNames
= GetPropertyNames();
264 UpdateFromProperties( aNames
);
265 EnableNotification( aNames
);
268 void ScFormulaCfg::UpdateFromProperties( const Sequence
<OUString
>& aNames
)
270 Sequence
<Any
> aValues
= GetProperties(aNames
);
271 const Any
* pValues
= aValues
.getConstArray();
272 OSL_ENSURE(aValues
.getLength() == aNames
.getLength(), "GetProperties failed");
273 PropsToIds aPropMap
= GetPropNamesToId();
274 if(aValues
.getLength() == aNames
.getLength())
276 sal_Int32 nIntVal
= 0;
277 for(int nProp
= 0; nProp
< aNames
.getLength(); nProp
++)
279 PropsToIds::iterator it_end
= aPropMap
.end();
280 PropsToIds::iterator it
= aPropMap
.find( aNames
[nProp
] );
281 if(pValues
[nProp
].hasValue() && it
!= it_end
)
285 case SCFORMULAOPT_GRAMMAR
:
287 // Get default value in case this option is not set.
288 ::formula::FormulaGrammar::Grammar eGram
= GetFormulaSyntax();
292 if (!(pValues
[nProp
] >>= nIntVal
))
293 // extractino failed.
299 eGram
= ::formula::FormulaGrammar::GRAM_NATIVE
;
302 eGram
= ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1
;
304 case 2: // Excel R1C1
305 eGram
= ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1
;
312 SetFormulaSyntax(eGram
);
315 case SCFORMULAOPT_ENGLISH_FUNCNAME
:
317 bool bEnglish
= false;
318 if (pValues
[nProp
] >>= bEnglish
)
319 SetUseEnglishFuncName(bEnglish
);
322 case SCFORMULAOPT_SEP_ARG
:
325 if ((pValues
[nProp
] >>= aSep
) && !aSep
.isEmpty())
326 SetFormulaSepArg(aSep
);
329 case SCFORMULAOPT_SEP_ARRAY_ROW
:
332 if ((pValues
[nProp
] >>= aSep
) && !aSep
.isEmpty())
333 SetFormulaSepArrayRow(aSep
);
336 case SCFORMULAOPT_SEP_ARRAY_COL
:
339 if ((pValues
[nProp
] >>= aSep
) && !aSep
.isEmpty())
340 SetFormulaSepArrayCol(aSep
);
343 case SCFORMULAOPT_STRING_REF_SYNTAX
:
345 // Get default value in case this option is not set.
346 ::formula::FormulaGrammar::AddressConvention eConv
= GetCalcConfig().meStringRefAddressSyntax
;
350 if (!(pValues
[nProp
] >>= nIntVal
))
351 // extraction failed.
356 case -1: // Same as the formula grammar.
357 eConv
= formula::FormulaGrammar::CONV_UNSPECIFIED
;
360 eConv
= formula::FormulaGrammar::CONV_OOO
;
363 eConv
= formula::FormulaGrammar::CONV_XL_A1
;
365 case 2: // Excel R1C1
366 eConv
= formula::FormulaGrammar::CONV_XL_R1C1
;
373 GetCalcConfig().meStringRefAddressSyntax
= eConv
;
376 case SCFORMULAOPT_STRING_CONVERSION
:
378 // Get default value in case this option is not set.
379 ScCalcConfig::StringConversion eConv
= GetCalcConfig().meStringConversion
;
383 if (!(pValues
[nProp
] >>= nIntVal
))
384 // extraction failed.
390 eConv
= ScCalcConfig::StringConversion::ILLEGAL
;
393 eConv
= ScCalcConfig::StringConversion::ZERO
;
396 eConv
= ScCalcConfig::StringConversion::UNAMBIGUOUS
;
399 eConv
= ScCalcConfig::StringConversion::LOCALE
;
402 SAL_WARN("sc", "unknown string conversion option!");
406 GetCalcConfig().meStringConversion
= eConv
;
409 case SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO
:
411 bool bVal
= GetCalcConfig().mbEmptyStringAsZero
;
412 pValues
[nProp
] >>= bVal
;
413 GetCalcConfig().mbEmptyStringAsZero
= bVal
;
416 case SCFORMULAOPT_OOXML_RECALC
:
418 ScRecalcOptions eOpt
= RECALC_ASK
;
419 if (pValues
[nProp
] >>= nIntVal
)
424 eOpt
= RECALC_ALWAYS
;
433 SAL_WARN("sc", "unknown ooxml recalc option!");
437 SetOOXMLRecalcOptions(eOpt
);
440 case SCFORMULAOPT_ODF_RECALC
:
442 ScRecalcOptions eOpt
= RECALC_ASK
;
443 if (pValues
[nProp
] >>= nIntVal
)
448 eOpt
= RECALC_ALWAYS
;
457 SAL_WARN("sc", "unknown odf recalc option!");
461 SetODFRecalcOptions(eOpt
);
464 case SCFORMULAOPT_OPENCL_AUTOSELECT
:
466 bool bVal
= GetCalcConfig().mbOpenCLAutoSelect
;
467 pValues
[nProp
] >>= bVal
;
468 GetCalcConfig().mbOpenCLAutoSelect
= bVal
;
471 case SCFORMULAOPT_OPENCL_DEVICE
:
473 OUString aOpenCLDevice
= GetCalcConfig().maOpenCLDevice
;
474 pValues
[nProp
] >>= aOpenCLDevice
;
475 GetCalcConfig().maOpenCLDevice
= aOpenCLDevice
;
478 case SCFORMULAOPT_OPENCL_SUBSET_ONLY
:
480 bool bVal
= GetCalcConfig().mbOpenCLSubsetOnly
;
481 pValues
[nProp
] >>= bVal
;
482 GetCalcConfig().mbOpenCLSubsetOnly
= bVal
;
485 case SCFORMULAOPT_OPENCL_MIN_SIZE
:
487 sal_Int32 nVal
= GetCalcConfig().mnOpenCLMinimumFormulaGroupSize
;
488 pValues
[nProp
] >>= nVal
;
489 GetCalcConfig().mnOpenCLMinimumFormulaGroupSize
= nVal
;
492 case SCFORMULAOPT_OPENCL_SUBSET_OPS
:
494 OUString sVal
= ScOpCodeSetToSymbolicString(GetCalcConfig().maOpenCLSubsetOpCodes
);
495 pValues
[nProp
] >>= sVal
;
496 GetCalcConfig().maOpenCLSubsetOpCodes
= ScStringToOpCodeSet(sVal
);
505 void ScFormulaCfg::ImplCommit()
507 Sequence
<OUString
> aNames
= GetPropertyNames();
508 Sequence
<Any
> aValues(aNames
.getLength());
509 Any
* pValues
= aValues
.getArray();
510 bool bSetOpenCL
= false;
512 for (int nProp
= 0; nProp
< aNames
.getLength(); ++nProp
)
516 case SCFORMULAOPT_GRAMMAR
:
519 switch (GetFormulaSyntax())
521 case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1
: nVal
= 1; break;
522 case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1
: nVal
= 2; break;
525 pValues
[nProp
] <<= nVal
;
528 case SCFORMULAOPT_ENGLISH_FUNCNAME
:
530 bool b
= GetUseEnglishFuncName();
531 pValues
[nProp
] <<= b
;
534 case SCFORMULAOPT_SEP_ARG
:
535 pValues
[nProp
] <<= GetFormulaSepArg();
537 case SCFORMULAOPT_SEP_ARRAY_ROW
:
538 pValues
[nProp
] <<= GetFormulaSepArrayRow();
540 case SCFORMULAOPT_SEP_ARRAY_COL
:
541 pValues
[nProp
] <<= GetFormulaSepArrayCol();
543 case SCFORMULAOPT_STRING_REF_SYNTAX
:
546 switch (GetCalcConfig().meStringRefAddressSyntax
)
548 case ::formula::FormulaGrammar::CONV_OOO
: nVal
= 0; break;
549 case ::formula::FormulaGrammar::CONV_XL_A1
: nVal
= 1; break;
550 case ::formula::FormulaGrammar::CONV_XL_R1C1
: nVal
= 2; break;
553 pValues
[nProp
] <<= nVal
;
556 case SCFORMULAOPT_STRING_CONVERSION
:
559 switch (GetCalcConfig().meStringConversion
)
561 case ScCalcConfig::StringConversion::ILLEGAL
: nVal
= 0; break;
562 case ScCalcConfig::StringConversion::ZERO
: nVal
= 1; break;
563 case ScCalcConfig::StringConversion::UNAMBIGUOUS
: nVal
= 2; break;
564 case ScCalcConfig::StringConversion::LOCALE
: nVal
= 3; break;
566 pValues
[nProp
] <<= nVal
;
569 case SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO
:
571 bool bVal
= GetCalcConfig().mbEmptyStringAsZero
;
572 pValues
[nProp
] <<= bVal
;
575 case SCFORMULAOPT_OOXML_RECALC
:
578 switch (GetOOXMLRecalcOptions())
591 pValues
[nProp
] <<= nVal
;
594 case SCFORMULAOPT_ODF_RECALC
:
597 switch (GetODFRecalcOptions())
610 pValues
[nProp
] <<= nVal
;
613 case SCFORMULAOPT_OPENCL_AUTOSELECT
:
615 bool bVal
= GetCalcConfig().mbOpenCLAutoSelect
;
616 pValues
[nProp
] <<= bVal
;
620 case SCFORMULAOPT_OPENCL_DEVICE
:
622 OUString aOpenCLDevice
= GetCalcConfig().maOpenCLDevice
;
623 pValues
[nProp
] <<= aOpenCLDevice
;
627 case SCFORMULAOPT_OPENCL_SUBSET_ONLY
:
629 bool bVal
= GetCalcConfig().mbOpenCLSubsetOnly
;
630 pValues
[nProp
] <<= bVal
;
633 case SCFORMULAOPT_OPENCL_MIN_SIZE
:
635 sal_Int32 nVal
= GetCalcConfig().mnOpenCLMinimumFormulaGroupSize
;
636 pValues
[nProp
] <<= nVal
;
639 case SCFORMULAOPT_OPENCL_SUBSET_OPS
:
641 OUString sVal
= ScOpCodeSetToSymbolicString(GetCalcConfig().maOpenCLSubsetOpCodes
);
642 pValues
[nProp
] <<= sVal
;
647 #if !HAVE_FEATURE_OPENCL
651 sc::FormulaGroupInterpreter::switchOpenCLDevice(
652 GetCalcConfig().maOpenCLDevice
, GetCalcConfig().mbOpenCLAutoSelect
);
654 PutProperties(aNames
, aValues
);
657 void ScFormulaCfg::SetOptions( const ScFormulaOptions
& rNew
)
659 *(ScFormulaOptions
*)this = rNew
;
663 void ScFormulaCfg::Notify( const ::com::sun::star::uno::Sequence
< OUString
>& rNames
)
665 UpdateFromProperties( rNames
);
668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */