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