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 4 : ScFormulaOptions::ScFormulaOptions()
51 : {
52 4 : SetDefaults();
53 4 : }
54 :
55 71 : 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 : aFormulaSepArrayCol ( rCpy.aFormulaSepArrayCol ),
62 : meOOXMLRecalc ( rCpy.meOOXMLRecalc ),
63 71 : meODFRecalc ( rCpy.meODFRecalc )
64 : {
65 71 : }
66 :
67 71 : ScFormulaOptions::~ScFormulaOptions()
68 : {
69 71 : }
70 :
71 4 : void ScFormulaOptions::SetDefaults()
72 : {
73 4 : bUseEnglishFuncName = false;
74 4 : eFormulaGrammar = ::formula::FormulaGrammar::GRAM_NATIVE;
75 4 : meOOXMLRecalc = RECALC_ASK;
76 4 : meODFRecalc = RECALC_ASK;
77 :
78 : // unspecified means use the current formula syntax.
79 4 : aCalcConfig.reset();
80 :
81 4 : ResetFormulaSeparators();
82 4 : }
83 :
84 4 : void ScFormulaOptions::ResetFormulaSeparators()
85 : {
86 4 : GetDefaultFormulaSeparators(aFormulaSepArg, aFormulaSepArrayCol, aFormulaSepArrayRow);
87 4 : }
88 :
89 4 : void ScFormulaOptions::GetDefaultFormulaSeparators(
90 : rtl::OUString& rSepArg, rtl::OUString& rSepArrayCol, rtl::OUString& rSepArrayRow)
91 : {
92 : // Defaults to the old separator values.
93 4 : rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
94 4 : rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
95 4 : rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM("|"));
96 :
97 4 : const Locale& rLocale = *ScGlobal::GetLocale();
98 4 : const OUString& rLang = rLocale.Language;
99 4 : if (rLang.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ru")))
100 : // Don't do automatic guess for these languages, and fall back to
101 : // the old separator set.
102 0 : return;
103 :
104 4 : const LocaleDataWrapper& rLocaleData = GetLocaleDataWrapper();
105 4 : const OUString& rDecSep = rLocaleData.getNumDecimalSep();
106 4 : const OUString& rListSep = rLocaleData.getListSep();
107 :
108 4 : if (rDecSep.isEmpty() || rListSep.isEmpty())
109 : // Something is wrong. Stick with the default separators.
110 0 : return;
111 :
112 4 : sal_Unicode cDecSep = rDecSep.getStr()[0];
113 4 : sal_Unicode cListSep = rListSep.getStr()[0];
114 :
115 : // Excel by default uses system's list separator as the parameter
116 : // separator, which in English locales is a comma. However, OOo's list
117 : // separator value is set to ';' for all English locales. Because of this
118 : // discrepancy, we will hardcode the separator value here, for now.
119 4 : if (cDecSep == sal_Unicode('.'))
120 4 : cListSep = sal_Unicode(',');
121 :
122 : // Special case for de_CH locale.
123 4 : if (rLocale.Language.equalsAsciiL("de", 2) && rLocale.Country.equalsAsciiL("CH", 2))
124 0 : cListSep = sal_Unicode(';');
125 :
126 : // by default, the parameter separator equals the locale-specific
127 : // list separator.
128 4 : rSepArg = OUString(cListSep);
129 :
130 4 : if (cDecSep == cListSep && cDecSep != sal_Unicode(';'))
131 : // if the decimal and list separators are equal, set the
132 : // parameter separator to be ';', unless they are both
133 : // semicolon in which case don't change the decimal separator.
134 0 : rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
135 :
136 4 : rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(","));
137 4 : if (cDecSep == sal_Unicode(','))
138 0 : rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM("."));
139 4 : rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
140 : }
141 :
142 4 : const LocaleDataWrapper& ScFormulaOptions::GetLocaleDataWrapper()
143 : {
144 4 : return *ScGlobal::pLocaleData;
145 : }
146 :
147 0 : ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
148 : {
149 0 : bUseEnglishFuncName = rCpy.bUseEnglishFuncName;
150 0 : eFormulaGrammar = rCpy.eFormulaGrammar;
151 0 : aCalcConfig = rCpy.aCalcConfig;
152 0 : aFormulaSepArg = rCpy.aFormulaSepArg;
153 0 : aFormulaSepArrayRow = rCpy.aFormulaSepArrayRow;
154 0 : aFormulaSepArrayCol = rCpy.aFormulaSepArrayCol;
155 0 : meOOXMLRecalc = rCpy.meOOXMLRecalc;
156 0 : meODFRecalc = rCpy.meODFRecalc;
157 0 : return *this;
158 : }
159 :
160 0 : bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const
161 : {
162 : return bUseEnglishFuncName == rOpt.bUseEnglishFuncName
163 : && eFormulaGrammar == rOpt.eFormulaGrammar
164 0 : && aCalcConfig == rOpt.aCalcConfig
165 0 : && aFormulaSepArg == rOpt.aFormulaSepArg
166 0 : && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow
167 0 : && aFormulaSepArrayCol == rOpt.aFormulaSepArrayCol
168 : && meOOXMLRecalc == rOpt.meOOXMLRecalc
169 0 : && meODFRecalc == rOpt.meODFRecalc;
170 : }
171 :
172 0 : bool ScFormulaOptions::operator!=( const ScFormulaOptions& rOpt ) const
173 : {
174 0 : return !(operator==(rOpt));
175 : }
176 :
177 : // -----------------------------------------------------------------------
178 :
179 :
180 0 : ScTpFormulaItem::ScTpFormulaItem( sal_uInt16 nWhichP, const ScFormulaOptions& rOpt ) :
181 : SfxPoolItem ( nWhichP ),
182 0 : theOptions ( rOpt )
183 : {
184 0 : }
185 :
186 0 : ScTpFormulaItem::ScTpFormulaItem( const ScTpFormulaItem& rItem ) :
187 : SfxPoolItem ( rItem ),
188 0 : theOptions ( rItem.theOptions )
189 : {
190 0 : }
191 :
192 0 : ScTpFormulaItem::~ScTpFormulaItem()
193 : {
194 0 : }
195 :
196 0 : String ScTpFormulaItem::GetValueText() const
197 : {
198 0 : return rtl::OUString("ScTpFormulaItem");
199 : }
200 :
201 0 : int ScTpFormulaItem::operator==( const SfxPoolItem& rItem ) const
202 : {
203 : OSL_ENSURE( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
204 :
205 0 : const ScTpFormulaItem& rPItem = (const ScTpFormulaItem&)rItem;
206 0 : return ( theOptions == rPItem.theOptions );
207 : }
208 :
209 0 : SfxPoolItem* ScTpFormulaItem::Clone( SfxItemPool * ) const
210 : {
211 0 : return new ScTpFormulaItem( *this );
212 : }
213 :
214 : // -----------------------------------------------------------------------
215 :
216 : #define CFGPATH_FORMULA "Office.Calc/Formula"
217 :
218 : #define SCFORMULAOPT_GRAMMAR 0
219 : #define SCFORMULAOPT_ENGLISH_FUNCNAME 1
220 : #define SCFORMULAOPT_SEP_ARG 2
221 : #define SCFORMULAOPT_SEP_ARRAY_ROW 3
222 : #define SCFORMULAOPT_SEP_ARRAY_COL 4
223 : #define SCFORMULAOPT_STRING_REF_SYNTAX 5
224 : #define SCFORMULAOPT_EMPTY_STRING_AS_ZERO 6
225 : #define SCFORMULAOPT_OOXML_RECALC 7
226 : #define SCFORMULAOPT_ODF_RECALC 8
227 : #define SCFORMULAOPT_COUNT 9
228 :
229 4 : Sequence<OUString> ScFormulaCfg::GetPropertyNames()
230 : {
231 : static const char* aPropNames[] =
232 : {
233 : "Syntax/Grammar", // SCFORMULAOPT_GRAMMAR
234 : "Syntax/EnglishFunctionName", // SCFORMULAOPT_ENGLISH_FUNCNAME
235 : "Syntax/SeparatorArg", // SCFORMULAOPT_SEP_ARG
236 : "Syntax/SeparatorArrayRow", // SCFORMULAOPT_SEP_ARRAY_ROW
237 : "Syntax/SeparatorArrayCol", // SCFORMULAOPT_SEP_ARRAY_COL
238 : "Syntax/StringRefAddressSyntax", // SCFORMULAOPT_STRING_REF_SYNTAX
239 : "Syntax/EmptyStringAsZero", // SCFORMULAOPT_EMPTY_STRING_AS_ZERO
240 : "Load/OOXMLRecalcMode", // SCFORMULAOPT_OOXML_RECALC
241 : "Load/ODFRecalcMode", // SCFORMULAOPT_ODF_RECALC
242 : };
243 4 : Sequence<OUString> aNames(SCFORMULAOPT_COUNT);
244 4 : OUString* pNames = aNames.getArray();
245 40 : for (int i = 0; i < SCFORMULAOPT_COUNT; ++i)
246 36 : pNames[i] = OUString::createFromAscii(aPropNames[i]);
247 :
248 4 : return aNames;
249 : }
250 :
251 4 : ScFormulaCfg::ScFormulaCfg() :
252 4 : ConfigItem( OUString(RTL_CONSTASCII_USTRINGPARAM( CFGPATH_FORMULA )) )
253 : {
254 4 : Sequence<OUString> aNames = GetPropertyNames();
255 4 : Sequence<Any> aValues = GetProperties(aNames);
256 4 : const Any* pValues = aValues.getConstArray();
257 : OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
258 4 : if(aValues.getLength() == aNames.getLength())
259 : {
260 4 : sal_Int32 nIntVal = 0;
261 40 : for(int nProp = 0; nProp < aNames.getLength(); nProp++)
262 : {
263 36 : if(pValues[nProp].hasValue())
264 : {
265 28 : switch(nProp)
266 : {
267 : case SCFORMULAOPT_GRAMMAR:
268 : {
269 : // Get default value in case this option is not set.
270 0 : ::formula::FormulaGrammar::Grammar eGram = GetFormulaSyntax();
271 :
272 : do
273 : {
274 0 : if (!(pValues[nProp] >>= nIntVal))
275 : // extractino failed.
276 0 : break;
277 :
278 0 : switch (nIntVal)
279 : {
280 : case 0: // Calc A1
281 0 : eGram = ::formula::FormulaGrammar::GRAM_NATIVE;
282 0 : break;
283 : case 1: // Excel A1
284 0 : eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1;
285 0 : break;
286 : case 2: // Excel R1C1
287 0 : eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1;
288 0 : break;
289 : default:
290 : ;
291 : }
292 : }
293 : while (false);
294 0 : SetFormulaSyntax(eGram);
295 : }
296 0 : break;
297 : case SCFORMULAOPT_ENGLISH_FUNCNAME:
298 : {
299 4 : sal_Bool bEnglish = false;
300 4 : if (pValues[nProp] >>= bEnglish)
301 4 : SetUseEnglishFuncName(bEnglish);
302 : }
303 4 : break;
304 : case SCFORMULAOPT_SEP_ARG:
305 : {
306 4 : OUString aSep;
307 4 : if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
308 0 : SetFormulaSepArg(aSep);
309 : }
310 4 : break;
311 : case SCFORMULAOPT_SEP_ARRAY_ROW:
312 : {
313 4 : OUString aSep;
314 4 : if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
315 0 : SetFormulaSepArrayRow(aSep);
316 : }
317 4 : break;
318 : case SCFORMULAOPT_SEP_ARRAY_COL:
319 : {
320 4 : OUString aSep;
321 4 : if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
322 0 : SetFormulaSepArrayCol(aSep);
323 : }
324 4 : break;
325 : case SCFORMULAOPT_STRING_REF_SYNTAX:
326 : {
327 : // Get default value in case this option is not set.
328 0 : ::formula::FormulaGrammar::AddressConvention eConv = GetCalcConfig().meStringRefAddressSyntax;
329 :
330 : do
331 : {
332 0 : if (!(pValues[nProp] >>= nIntVal))
333 : // extractino failed.
334 0 : break;
335 :
336 0 : switch (nIntVal)
337 : {
338 : case -1: // Same as the formula grammar.
339 0 : eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
340 0 : break;
341 : case 0: // Calc A1
342 0 : eConv = formula::FormulaGrammar::CONV_OOO;
343 0 : break;
344 : case 1: // Excel A1
345 0 : eConv = formula::FormulaGrammar::CONV_XL_A1;
346 0 : break;
347 : case 2: // Excel R1C1
348 0 : eConv = formula::FormulaGrammar::CONV_XL_R1C1;
349 0 : break;
350 : default:
351 : ;
352 : }
353 : }
354 : while (false);
355 0 : GetCalcConfig().meStringRefAddressSyntax = eConv;
356 : }
357 0 : break;
358 : case SCFORMULAOPT_EMPTY_STRING_AS_ZERO:
359 : {
360 4 : sal_Bool bVal = GetCalcConfig().mbEmptyStringAsZero;
361 4 : pValues[nProp] >>= bVal;
362 4 : GetCalcConfig().mbEmptyStringAsZero = bVal;
363 : }
364 4 : break;
365 : case SCFORMULAOPT_OOXML_RECALC:
366 : {
367 4 : ScRecalcOptions eOpt = RECALC_ASK;
368 4 : if (pValues[nProp] >>= nIntVal)
369 : {
370 4 : switch (nIntVal)
371 : {
372 : case 0:
373 0 : eOpt = RECALC_ALWAYS;
374 0 : break;
375 : case 1:
376 4 : eOpt = RECALC_NEVER;
377 4 : break;
378 : case 2:
379 0 : eOpt = RECALC_ASK;
380 0 : break;
381 : default:
382 : SAL_WARN("sc", "unknown ooxml recalc option!");
383 : }
384 : }
385 :
386 4 : SetOOXMLRecalcOptions(eOpt);
387 : }
388 4 : break;
389 : case SCFORMULAOPT_ODF_RECALC:
390 : {
391 4 : ScRecalcOptions eOpt = RECALC_ASK;
392 4 : if (pValues[nProp] >>= nIntVal)
393 : {
394 4 : switch (nIntVal)
395 : {
396 : case 0:
397 0 : eOpt = RECALC_ALWAYS;
398 0 : break;
399 : case 1:
400 4 : eOpt = RECALC_NEVER;
401 4 : break;
402 : case 2:
403 0 : eOpt = RECALC_ASK;
404 0 : break;
405 : default:
406 : SAL_WARN("sc", "unknown odf recalc option!");
407 : }
408 : }
409 :
410 4 : SetODFRecalcOptions(eOpt);
411 : }
412 4 : break;
413 : default:
414 : ;
415 : }
416 : }
417 : }
418 4 : }
419 4 : }
420 :
421 0 : void ScFormulaCfg::Commit()
422 : {
423 0 : Sequence<OUString> aNames = GetPropertyNames();
424 0 : Sequence<Any> aValues(aNames.getLength());
425 0 : Any* pValues = aValues.getArray();
426 :
427 0 : for (int nProp = 0; nProp < aNames.getLength(); ++nProp)
428 : {
429 0 : switch (nProp)
430 : {
431 : case SCFORMULAOPT_GRAMMAR :
432 : {
433 0 : sal_Int32 nVal = 0;
434 0 : switch (GetFormulaSyntax())
435 : {
436 0 : case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1: nVal = 1; break;
437 0 : case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1: nVal = 2; break;
438 0 : default: break;
439 : }
440 0 : pValues[nProp] <<= nVal;
441 : }
442 0 : break;
443 : case SCFORMULAOPT_ENGLISH_FUNCNAME:
444 : {
445 0 : sal_Bool b = GetUseEnglishFuncName();
446 0 : pValues[nProp] <<= b;
447 : }
448 0 : break;
449 : case SCFORMULAOPT_SEP_ARG:
450 0 : pValues[nProp] <<= GetFormulaSepArg();
451 0 : break;
452 : case SCFORMULAOPT_SEP_ARRAY_ROW:
453 0 : pValues[nProp] <<= GetFormulaSepArrayRow();
454 0 : break;
455 : case SCFORMULAOPT_SEP_ARRAY_COL:
456 0 : pValues[nProp] <<= GetFormulaSepArrayCol();
457 0 : break;
458 : case SCFORMULAOPT_STRING_REF_SYNTAX:
459 : {
460 0 : sal_Int32 nVal = -1;
461 0 : switch (GetCalcConfig().meStringRefAddressSyntax)
462 : {
463 0 : case ::formula::FormulaGrammar::CONV_OOO: nVal = 0; break;
464 0 : case ::formula::FormulaGrammar::CONV_XL_A1: nVal = 1; break;
465 0 : case ::formula::FormulaGrammar::CONV_XL_R1C1: nVal = 2; break;
466 0 : default: break;
467 : }
468 0 : pValues[nProp] <<= nVal;
469 : }
470 0 : break;
471 : case SCFORMULAOPT_EMPTY_STRING_AS_ZERO:
472 : {
473 0 : sal_Bool bVal = GetCalcConfig().mbEmptyStringAsZero;
474 0 : pValues[nProp] <<= bVal;
475 : }
476 0 : break;
477 : case SCFORMULAOPT_OOXML_RECALC:
478 : {
479 0 : sal_Int32 nVal = 2;
480 0 : switch (GetOOXMLRecalcOptions())
481 : {
482 : case RECALC_ALWAYS:
483 0 : nVal = 0;
484 0 : break;
485 : case RECALC_NEVER:
486 0 : nVal = 1;
487 0 : break;
488 : case RECALC_ASK:
489 0 : nVal = 2;
490 0 : break;
491 : }
492 :
493 0 : pValues[nProp] <<= nVal;
494 : }
495 0 : break;
496 : case SCFORMULAOPT_ODF_RECALC:
497 : {
498 0 : sal_Int32 nVal = 2;
499 0 : switch (GetODFRecalcOptions())
500 : {
501 : case RECALC_ALWAYS:
502 0 : nVal = 0;
503 0 : break;
504 : case RECALC_NEVER:
505 0 : nVal = 1;
506 0 : break;
507 : case RECALC_ASK:
508 0 : nVal = 2;
509 0 : break;
510 : }
511 :
512 0 : pValues[nProp] <<= nVal;
513 : }
514 0 : break;
515 : default:
516 : ;
517 : }
518 : }
519 0 : PutProperties(aNames, aValues);
520 0 : }
521 :
522 0 : void ScFormulaCfg::SetOptions( const ScFormulaOptions& rNew )
523 : {
524 0 : *(ScFormulaOptions*)this = rNew;
525 0 : SetModified();
526 0 : }
527 :
528 0 : void ScFormulaCfg::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {}
529 :
530 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|