Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License. You may obtain a copy of the License at
8 : : * http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * The Initial Developer of the Original Code is
16 : : * Albert Thuswaldner <albert.thuswaldner@gmail.com>
17 : : * Portions created by the Initial Developer are Copyright (C) 2012 the
18 : : * Initial Developer. All Rights Reserved.
19 : : *
20 : : * Contributor(s):
21 : : *
22 : : * Alternatively, the contents of this file may be used under the terms of
23 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : : * instead of those above.
27 : : */
28 : :
29 : : #include <com/sun/star/uno/Any.hxx>
30 : : #include <com/sun/star/uno/Sequence.hxx>
31 : : #include <com/sun/star/lang/Locale.hpp>
32 : : #include <com/sun/star/i18n/LocaleDataItem.hpp>
33 : :
34 : : #include "formulaopt.hxx"
35 : : #include "miscuno.hxx"
36 : : #include "global.hxx"
37 : :
38 : : using namespace utl;
39 : : using namespace com::sun::star::uno;
40 : : using ::com::sun::star::lang::Locale;
41 : : using ::com::sun::star::i18n::LocaleDataItem;
42 : : using ::rtl::OUString;
43 : :
44 : : // -----------------------------------------------------------------------
45 : :
46 [ # # ][ # # ]: 0 : TYPEINIT1(ScTpFormulaItem, SfxPoolItem);
47 : :
48 : : // -----------------------------------------------------------------------
49 : :
50 : 51 : ScFormulaOptions::ScFormulaOptions()
51 : : {
52 [ + - ]: 51 : SetDefaults();
53 : 51 : }
54 : :
55 : 412 : ScFormulaOptions::ScFormulaOptions( const ScFormulaOptions& rCpy ) :
56 : : bUseEnglishFuncName ( rCpy.bUseEnglishFuncName ),
57 : : eFormulaGrammar ( rCpy.eFormulaGrammar ),
58 : : aCalcConfig(rCpy.aCalcConfig),
59 : : aFormulaSepArg ( rCpy.aFormulaSepArg ),
60 : : aFormulaSepArrayRow ( rCpy.aFormulaSepArrayRow ),
61 : 412 : aFormulaSepArrayCol ( rCpy.aFormulaSepArrayCol )
62 : : {
63 : 412 : }
64 : :
65 : 430 : ScFormulaOptions::~ScFormulaOptions()
66 : : {
67 : 430 : }
68 : :
69 : 51 : void ScFormulaOptions::SetDefaults()
70 : : {
71 : 51 : bUseEnglishFuncName = false;
72 : 51 : eFormulaGrammar = ::formula::FormulaGrammar::GRAM_NATIVE;
73 : :
74 : : // unspecified means use the current formula syntax.
75 : 51 : aCalcConfig.reset();
76 : :
77 : 51 : ResetFormulaSeparators();
78 : 51 : }
79 : :
80 : 51 : void ScFormulaOptions::ResetFormulaSeparators()
81 : : {
82 : 51 : GetDefaultFormulaSeparators(aFormulaSepArg, aFormulaSepArrayCol, aFormulaSepArrayRow);
83 : 51 : }
84 : :
85 : 51 : void ScFormulaOptions::GetDefaultFormulaSeparators(
86 : : rtl::OUString& rSepArg, rtl::OUString& rSepArrayCol, rtl::OUString& rSepArrayRow)
87 : : {
88 : : // Defaults to the old separator values.
89 : 51 : rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
90 : 51 : rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
91 : 51 : rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM("|"));
92 : :
93 : 51 : const Locale& rLocale = *ScGlobal::GetLocale();
94 : 51 : const OUString& rLang = rLocale.Language;
95 [ - + ]: 51 : if (rLang.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ru")))
96 : : // Don't do automatic guess for these languages, and fall back to
97 : : // the old separator set.
98 : 0 : return;
99 : :
100 : 51 : const LocaleDataWrapper& rLocaleData = GetLocaleDataWrapper();
101 : 51 : const OUString& rDecSep = rLocaleData.getNumDecimalSep();
102 : 51 : const OUString& rListSep = rLocaleData.getListSep();
103 : :
104 [ - + ][ - + ]: 51 : if (rDecSep.isEmpty() || rListSep.isEmpty())
[ + - ]
105 : : // Something is wrong. Stick with the default separators.
106 : 0 : return;
107 : :
108 : 51 : sal_Unicode cDecSep = rDecSep.getStr()[0];
109 : 51 : sal_Unicode cListSep = rListSep.getStr()[0];
110 : :
111 : : // Excel by default uses system's list separator as the parameter
112 : : // separator, which in English locales is a comma. However, OOo's list
113 : : // separator value is set to ';' for all English locales. Because of this
114 : : // discrepancy, we will hardcode the separator value here, for now.
115 [ + - ]: 51 : if (cDecSep == sal_Unicode('.'))
116 : 51 : cListSep = sal_Unicode(',');
117 : :
118 : : // Special case for de_CH locale.
119 [ - + ][ # # ]: 51 : if (rLocale.Language.equalsAsciiL("de", 2) && rLocale.Country.equalsAsciiL("CH", 2))
[ - + ]
120 : 0 : cListSep = sal_Unicode(';');
121 : :
122 : : // by default, the parameter separator equals the locale-specific
123 : : // list separator.
124 : 51 : rSepArg = OUString(cListSep);
125 : :
126 [ # # ][ - + ]: 51 : if (cDecSep == cListSep && cDecSep != sal_Unicode(';'))
127 : : // if the decimal and list separators are equal, set the
128 : : // parameter separator to be ';', unless they are both
129 : : // semicolon in which case don't change the decimal separator.
130 : 0 : rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
131 : :
132 : 51 : rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(","));
133 [ - + ]: 51 : if (cDecSep == sal_Unicode(','))
134 : 0 : rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM("."));
135 : 51 : rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
136 : : }
137 : :
138 : 51 : const LocaleDataWrapper& ScFormulaOptions::GetLocaleDataWrapper()
139 : : {
140 : 51 : return *ScGlobal::pLocaleData;
141 : : }
142 : :
143 : 0 : ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
144 : : {
145 : 0 : bUseEnglishFuncName = rCpy.bUseEnglishFuncName;
146 : 0 : eFormulaGrammar = rCpy.eFormulaGrammar;
147 : 0 : aCalcConfig = rCpy.aCalcConfig;
148 : 0 : aFormulaSepArg = rCpy.aFormulaSepArg;
149 : 0 : aFormulaSepArrayRow = rCpy.aFormulaSepArrayRow;
150 : 0 : aFormulaSepArrayCol = rCpy.aFormulaSepArrayCol;
151 : 0 : return *this;
152 : : }
153 : :
154 : 0 : bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const
155 : : {
156 : : return bUseEnglishFuncName == rOpt.bUseEnglishFuncName
157 : : && eFormulaGrammar == rOpt.eFormulaGrammar
158 : 0 : && aCalcConfig == rOpt.aCalcConfig
159 : 0 : && aFormulaSepArg == rOpt.aFormulaSepArg
160 : 0 : && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow
161 [ # # ][ # # : 0 : && aFormulaSepArrayCol == rOpt.aFormulaSepArrayCol;
# # # # #
# ][ # # ]
162 : : }
163 : :
164 : 0 : bool ScFormulaOptions::operator!=( const ScFormulaOptions& rOpt ) const
165 : : {
166 : 0 : return !(operator==(rOpt));
167 : : }
168 : :
169 : : // -----------------------------------------------------------------------
170 : :
171 : :
172 : 0 : ScTpFormulaItem::ScTpFormulaItem( sal_uInt16 nWhichP, const ScFormulaOptions& rOpt ) :
173 : : SfxPoolItem ( nWhichP ),
174 [ # # ]: 0 : theOptions ( rOpt )
175 : : {
176 : 0 : }
177 : :
178 : 0 : ScTpFormulaItem::ScTpFormulaItem( const ScTpFormulaItem& rItem ) :
179 : : SfxPoolItem ( rItem ),
180 [ # # ]: 0 : theOptions ( rItem.theOptions )
181 : : {
182 : 0 : }
183 : :
184 [ # # ]: 0 : ScTpFormulaItem::~ScTpFormulaItem()
185 : : {
186 [ # # ]: 0 : }
187 : :
188 : 0 : String ScTpFormulaItem::GetValueText() const
189 : : {
190 [ # # ]: 0 : return rtl::OUString("ScTpFormulaItem");
191 : : }
192 : :
193 : 0 : int ScTpFormulaItem::operator==( const SfxPoolItem& rItem ) const
194 : : {
195 : : OSL_ENSURE( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
196 : :
197 : 0 : const ScTpFormulaItem& rPItem = (const ScTpFormulaItem&)rItem;
198 : 0 : return ( theOptions == rPItem.theOptions );
199 : : }
200 : :
201 : 0 : SfxPoolItem* ScTpFormulaItem::Clone( SfxItemPool * ) const
202 : : {
203 [ # # ]: 0 : return new ScTpFormulaItem( *this );
204 : : }
205 : :
206 : : // -----------------------------------------------------------------------
207 : :
208 : : #define CFGPATH_FORMULA "Office.Calc/Formula"
209 : :
210 : : #define SCFORMULAOPT_GRAMMAR 0
211 : : #define SCFORMULAOPT_ENGLISH_FUNCNAME 1
212 : : #define SCFORMULAOPT_SEP_ARG 2
213 : : #define SCFORMULAOPT_SEP_ARRAY_ROW 3
214 : : #define SCFORMULAOPT_SEP_ARRAY_COL 4
215 : : #define SCFORMULAOPT_STRING_REF_SYNTAX 5
216 : : #define SCFORMULAOPT_EMPTY_STRING_AS_ZERO 6
217 : : #define SCFORMULAOPT_COUNT 7
218 : :
219 : 51 : Sequence<OUString> ScFormulaCfg::GetPropertyNames()
220 : : {
221 : : static const char* aPropNames[] =
222 : : {
223 : : "Syntax/Grammar", // SCFORMULAOPT_GRAMMAR
224 : : "Syntax/EnglishFunctionName", // SCFORMULAOPT_ENGLISH_FUNCNAME
225 : : "Syntax/SeparatorArg", // SCFORMULAOPT_SEP_ARG
226 : : "Syntax/SeparatorArrayRow", // SCFORMULAOPT_SEP_ARRAY_ROW
227 : : "Syntax/SeparatorArrayCol", // SCFORMULAOPT_SEP_ARRAY_COL
228 : : "Syntax/StringRefAddressSyntax", // SCFORMULAOPT_STRING_REF_SYNTAX
229 : : "Syntax/EmptyStringAsZero", // SCFORMULAOPT_EMPTY_STRING_AS_ZERO
230 : : };
231 : 51 : Sequence<OUString> aNames(SCFORMULAOPT_COUNT);
232 [ + - ]: 51 : OUString* pNames = aNames.getArray();
233 [ + + ]: 408 : for (int i = 0; i < SCFORMULAOPT_COUNT; ++i)
234 : 357 : pNames[i] = OUString::createFromAscii(aPropNames[i]);
235 : :
236 : 51 : return aNames;
237 : : }
238 : :
239 : 51 : ScFormulaCfg::ScFormulaCfg() :
240 [ + - ][ + - ]: 51 : ConfigItem( OUString(RTL_CONSTASCII_USTRINGPARAM( CFGPATH_FORMULA )) )
241 : : {
242 [ + - ]: 51 : Sequence<OUString> aNames = GetPropertyNames();
243 [ + - ]: 51 : Sequence<Any> aValues = GetProperties(aNames);
244 : 51 : const Any* pValues = aValues.getConstArray();
245 : : OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
246 [ + - ]: 51 : if(aValues.getLength() == aNames.getLength())
247 : : {
248 : 51 : sal_Int32 nIntVal = 0;
249 [ + + ]: 408 : for(int nProp = 0; nProp < aNames.getLength(); nProp++)
250 : : {
251 [ + + ]: 357 : if(pValues[nProp].hasValue())
252 : : {
253 [ - + + + : 255 : switch(nProp)
+ - + - ]
254 : : {
255 : : case SCFORMULAOPT_GRAMMAR:
256 : : {
257 : : // Get default value in case this option is not set.
258 : 0 : ::formula::FormulaGrammar::Grammar eGram = GetFormulaSyntax();
259 : :
260 : : do
261 : : {
262 [ # # ]: 0 : if (!(pValues[nProp] >>= nIntVal))
263 : : // extractino failed.
264 : 0 : break;
265 : :
266 [ # # # # ]: 0 : switch (nIntVal)
267 : : {
268 : : case 0: // Calc A1
269 : 0 : eGram = ::formula::FormulaGrammar::GRAM_NATIVE;
270 : 0 : break;
271 : : case 1: // Excel A1
272 : 0 : eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1;
273 : 0 : break;
274 : : case 2: // Excel R1C1
275 : 0 : eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1;
276 : 0 : break;
277 : : default:
278 : : ;
279 : : }
280 : : }
281 : : while (false);
282 : 0 : SetFormulaSyntax(eGram);
283 : : }
284 : 0 : break;
285 : : case SCFORMULAOPT_ENGLISH_FUNCNAME:
286 : : {
287 : 51 : sal_Bool bEnglish = false;
288 [ + - ]: 51 : if (pValues[nProp] >>= bEnglish)
289 : 51 : SetUseEnglishFuncName(bEnglish);
290 : : }
291 : 51 : break;
292 : : case SCFORMULAOPT_SEP_ARG:
293 : : {
294 : 51 : OUString aSep;
295 [ - + ][ - + ]: 51 : if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
[ + - ]
296 : 51 : SetFormulaSepArg(aSep);
297 : : }
298 : 51 : break;
299 : : case SCFORMULAOPT_SEP_ARRAY_ROW:
300 : : {
301 : 51 : OUString aSep;
302 [ - + ][ - + ]: 51 : if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
[ + - ]
303 : 51 : SetFormulaSepArrayRow(aSep);
304 : : }
305 : 51 : break;
306 : : case SCFORMULAOPT_SEP_ARRAY_COL:
307 : : {
308 : 51 : OUString aSep;
309 [ - + ][ - + ]: 51 : if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
[ + - ]
310 : 51 : SetFormulaSepArrayCol(aSep);
311 : : }
312 : 51 : break;
313 : : case SCFORMULAOPT_STRING_REF_SYNTAX:
314 : : {
315 : : // Get default value in case this option is not set.
316 : 0 : ::formula::FormulaGrammar::AddressConvention eConv = GetCalcConfig().meStringRefAddressSyntax;
317 : :
318 : : do
319 : : {
320 [ # # ]: 0 : if (!(pValues[nProp] >>= nIntVal))
321 : : // extractino failed.
322 : 0 : break;
323 : :
324 [ # # # # : 0 : switch (nIntVal)
# ]
325 : : {
326 : : case -1: // Same as the formula grammar.
327 : 0 : eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
328 : 0 : break;
329 : : case 0: // Calc A1
330 : 0 : eConv = formula::FormulaGrammar::CONV_OOO;
331 : 0 : break;
332 : : case 1: // Excel A1
333 : 0 : eConv = formula::FormulaGrammar::CONV_XL_A1;
334 : 0 : break;
335 : : case 2: // Excel R1C1
336 : 0 : eConv = formula::FormulaGrammar::CONV_XL_R1C1;
337 : 0 : break;
338 : : default:
339 : : ;
340 : : }
341 : : }
342 : : while (false);
343 : 0 : GetCalcConfig().meStringRefAddressSyntax = eConv;
344 : : }
345 : 0 : break;
346 : : case SCFORMULAOPT_EMPTY_STRING_AS_ZERO:
347 : : {
348 : 51 : sal_Bool bVal = GetCalcConfig().mbEmptyStringAsZero;
349 : 51 : pValues[nProp] >>= bVal;
350 : 51 : GetCalcConfig().mbEmptyStringAsZero = bVal;
351 : : }
352 : 255 : break;
353 : : default:
354 : : ;
355 : : }
356 : : }
357 : : }
358 [ + - ][ + - ]: 51 : }
359 : 51 : }
360 : :
361 : 0 : void ScFormulaCfg::Commit()
362 : : {
363 [ # # ]: 0 : Sequence<OUString> aNames = GetPropertyNames();
364 [ # # ]: 0 : Sequence<Any> aValues(aNames.getLength());
365 [ # # ]: 0 : Any* pValues = aValues.getArray();
366 : :
367 [ # # ]: 0 : for (int nProp = 0; nProp < aNames.getLength(); ++nProp)
368 : : {
369 [ # # # # : 0 : switch (nProp)
# # # # ]
370 : : {
371 : : case SCFORMULAOPT_GRAMMAR :
372 : : {
373 : 0 : sal_Int32 nVal = 0;
374 [ # # # ]: 0 : switch (GetFormulaSyntax())
375 : : {
376 : 0 : case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1: nVal = 1; break;
377 : 0 : case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1: nVal = 2; break;
378 : 0 : default: break;
379 : : }
380 [ # # ]: 0 : pValues[nProp] <<= nVal;
381 : : }
382 : 0 : break;
383 : : case SCFORMULAOPT_ENGLISH_FUNCNAME:
384 : : {
385 : 0 : sal_Bool b = GetUseEnglishFuncName();
386 [ # # ]: 0 : pValues[nProp] <<= b;
387 : : }
388 : 0 : break;
389 : : case SCFORMULAOPT_SEP_ARG:
390 [ # # ]: 0 : pValues[nProp] <<= GetFormulaSepArg();
391 : 0 : break;
392 : : case SCFORMULAOPT_SEP_ARRAY_ROW:
393 [ # # ]: 0 : pValues[nProp] <<= GetFormulaSepArrayRow();
394 : 0 : break;
395 : : case SCFORMULAOPT_SEP_ARRAY_COL:
396 [ # # ]: 0 : pValues[nProp] <<= GetFormulaSepArrayCol();
397 : 0 : break;
398 : : case SCFORMULAOPT_STRING_REF_SYNTAX:
399 : : {
400 : 0 : sal_Int32 nVal = -1;
401 [ # # # # ]: 0 : switch (GetCalcConfig().meStringRefAddressSyntax)
402 : : {
403 : 0 : case ::formula::FormulaGrammar::CONV_OOO: nVal = 0; break;
404 : 0 : case ::formula::FormulaGrammar::CONV_XL_A1: nVal = 1; break;
405 : 0 : case ::formula::FormulaGrammar::CONV_XL_R1C1: nVal = 2; break;
406 : 0 : default: break;
407 : : }
408 [ # # ]: 0 : pValues[nProp] <<= nVal;
409 : : }
410 : 0 : break;
411 : : case SCFORMULAOPT_EMPTY_STRING_AS_ZERO:
412 : : {
413 : 0 : sal_Bool bVal = GetCalcConfig().mbEmptyStringAsZero;
414 [ # # ]: 0 : pValues[nProp] <<= bVal;
415 : : }
416 : 0 : break;
417 : : default:
418 : : ;
419 : : }
420 : : }
421 [ # # ][ # # ]: 0 : PutProperties(aNames, aValues);
[ # # ]
422 : 0 : }
423 : :
424 : 0 : void ScFormulaCfg::SetOptions( const ScFormulaOptions& rNew )
425 : : {
426 : 0 : *(ScFormulaOptions*)this = rNew;
427 : 0 : SetModified();
428 : 0 : }
429 : :
430 : 0 : void ScFormulaCfg::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {}
431 : :
432 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|