Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 : #include <unotools/syslocale.hxx>
22 :
23 : #include <svl/zforlist.hxx>
24 :
25 : #include <svl/zformat.hxx>
26 : #include <svl/numuno.hxx>
27 : #include <rtl/math.hxx>
28 : #include <i18nlangtag/languagetag.hxx>
29 : #include <tools/color.hxx>
30 : #include <tools/debug.hxx>
31 : #include <osl/diagnose.h>
32 : #include <rtl/ustrbuf.hxx>
33 :
34 : #include <sax/tools/converter.hxx>
35 :
36 : #include <xmloff/xmlnumfi.hxx>
37 : #include <xmloff/xmltkmap.hxx>
38 : #include <xmloff/xmlnmspe.hxx>
39 : #include <xmloff/xmlictxt.hxx>
40 : #include <xmloff/xmlimp.hxx>
41 : #include <xmloff/xmluconv.hxx>
42 : #include <xmloff/nmspmap.hxx>
43 : #include <xmloff/families.hxx>
44 : #include <xmloff/xmltoken.hxx>
45 : #include <xmloff/languagetagodf.hxx>
46 :
47 : #include <boost/ptr_container/ptr_vector.hpp>
48 : #include <boost/ptr_container/ptr_set.hpp>
49 :
50 : using namespace ::com::sun::star;
51 : using namespace ::xmloff::token;
52 :
53 1942 : struct SvXMLNumFmtEntry
54 : {
55 : OUString aName;
56 : sal_uInt32 nKey;
57 : bool bRemoveAfterUse;
58 :
59 1942 : SvXMLNumFmtEntry( const OUString& rN, sal_uInt32 nK, bool bR ) :
60 1942 : aName(rN), nKey(nK), bRemoveAfterUse(bR) {}
61 : };
62 :
63 : typedef ::boost::ptr_vector<SvXMLNumFmtEntry> SvXMLNumFmtEntryArr;
64 :
65 0 : struct SvXMLEmbeddedElement
66 : {
67 : sal_Int32 nFormatPos;
68 : OUString aText;
69 :
70 0 : SvXMLEmbeddedElement( sal_Int32 nFP, const OUString& rT ) :
71 0 : nFormatPos(nFP), aText(rT) {}
72 :
73 0 : bool operator < ( const SvXMLEmbeddedElement& r ) const { return nFormatPos < r.nFormatPos; }
74 : };
75 :
76 : typedef boost::ptr_set<SvXMLEmbeddedElement> SvXMLEmbeddedElementArr;
77 :
78 : class SvXMLNumImpData
79 : {
80 : SvNumberFormatter* pFormatter;
81 : SvXMLTokenMap* pStylesElemTokenMap;
82 : SvXMLTokenMap* pStyleElemTokenMap;
83 : SvXMLTokenMap* pStyleAttrTokenMap;
84 : SvXMLTokenMap* pStyleElemAttrTokenMap;
85 : LocaleDataWrapper* pLocaleData;
86 : SvXMLNumFmtEntryArr aNameEntries;
87 :
88 : uno::Reference< uno::XComponentContext > m_xContext;
89 :
90 : public:
91 : SvXMLNumImpData(
92 : SvNumberFormatter* pFmt,
93 : const uno::Reference<uno::XComponentContext>& rxContext );
94 : ~SvXMLNumImpData();
95 :
96 5357 : SvNumberFormatter* GetNumberFormatter() const { return pFormatter; }
97 : const SvXMLTokenMap& GetStylesElemTokenMap();
98 : const SvXMLTokenMap& GetStyleElemTokenMap();
99 : const SvXMLTokenMap& GetStyleAttrTokenMap();
100 : const SvXMLTokenMap& GetStyleElemAttrTokenMap();
101 : const LocaleDataWrapper& GetLocaleData( LanguageType nLang );
102 : sal_uInt32 GetKeyForName( const OUString& rName );
103 : void AddKey( sal_uInt32 nKey, const OUString& rName, bool bRemoveAfterUse );
104 : void SetUsed( sal_uInt32 nKey );
105 : void RemoveVolatileFormats();
106 : };
107 :
108 5173 : struct SvXMLNumberInfo
109 : {
110 : sal_Int32 nDecimals;
111 : sal_Int32 nInteger;
112 : sal_Int32 nExpDigits;
113 : sal_Int32 nExpInterval;
114 : sal_Int32 nNumerDigits;
115 : sal_Int32 nDenomDigits;
116 : sal_Int32 nFracDenominator;
117 : sal_Int32 nMinDecimalDigits;
118 : bool bGrouping;
119 : bool bDecReplace;
120 : bool bExpSign;
121 : double fDisplayFactor;
122 : SvXMLEmbeddedElementArr aEmbeddedElements;
123 :
124 5173 : SvXMLNumberInfo()
125 5173 : {
126 : nDecimals = nInteger = nExpDigits = nExpInterval = nNumerDigits = nDenomDigits =
127 5173 : nFracDenominator = nMinDecimalDigits = -1;
128 5173 : bGrouping = bDecReplace = false;
129 5173 : bExpSign = true;
130 5173 : fDisplayFactor = 1.0;
131 5173 : }
132 : };
133 :
134 : class SvXMLNumFmtElementContext : public SvXMLImportContext
135 : {
136 : SvXMLNumFormatContext& rParent;
137 : sal_uInt16 nType;
138 : OUStringBuffer aContent;
139 : SvXMLNumberInfo aNumInfo;
140 : LanguageType nElementLang;
141 : bool bLong;
142 : bool bTextual;
143 : OUString sCalendar;
144 :
145 : public:
146 : SvXMLNumFmtElementContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
147 : const OUString& rLName,
148 : SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType,
149 : const ::com::sun::star::uno::Reference<
150 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
151 : virtual ~SvXMLNumFmtElementContext();
152 :
153 : virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
154 : const OUString& rLocalName,
155 : const ::com::sun::star::uno::Reference<
156 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
157 : virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
158 : virtual void EndElement() SAL_OVERRIDE;
159 :
160 : void AddEmbeddedElement( sal_Int32 nFormatPos, const OUString& rContent );
161 : };
162 :
163 : class SvXMLNumFmtEmbeddedTextContext : public SvXMLImportContext
164 : {
165 : SvXMLNumFmtElementContext& rParent;
166 : OUStringBuffer aContent;
167 : sal_Int32 nTextPosition;
168 :
169 : public:
170 : SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
171 : const OUString& rLName,
172 : SvXMLNumFmtElementContext& rParentContext,
173 : const ::com::sun::star::uno::Reference<
174 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
175 : virtual ~SvXMLNumFmtEmbeddedTextContext();
176 :
177 : virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
178 : const OUString& rLocalName,
179 : const ::com::sun::star::uno::Reference<
180 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
181 : virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
182 : virtual void EndElement() SAL_OVERRIDE;
183 : };
184 :
185 : class SvXMLNumFmtMapContext : public SvXMLImportContext
186 : {
187 : SvXMLNumFormatContext& rParent;
188 : OUString sCondition;
189 : OUString sName;
190 :
191 : public:
192 : SvXMLNumFmtMapContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
193 : const OUString& rLName,
194 : SvXMLNumFormatContext& rParentContext,
195 : const ::com::sun::star::uno::Reference<
196 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
197 : virtual ~SvXMLNumFmtMapContext();
198 :
199 : virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
200 : const OUString& rLocalName,
201 : const ::com::sun::star::uno::Reference<
202 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
203 : virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
204 : virtual void EndElement() SAL_OVERRIDE;
205 : };
206 :
207 : class SvXMLNumFmtPropContext : public SvXMLImportContext
208 : {
209 : SvXMLNumFormatContext& rParent;
210 : sal_Int32 m_nColor;
211 : bool bColSet;
212 :
213 : public:
214 : SvXMLNumFmtPropContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
215 : const OUString& rLName,
216 : SvXMLNumFormatContext& rParentContext,
217 : const ::com::sun::star::uno::Reference<
218 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
219 : virtual ~SvXMLNumFmtPropContext();
220 :
221 : virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
222 : const OUString& rLocalName,
223 : const ::com::sun::star::uno::Reference<
224 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
225 : virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
226 : virtual void EndElement() SAL_OVERRIDE;
227 : };
228 :
229 : enum SvXMLStyleTokens
230 : {
231 : XML_TOK_STYLE_TEXT,
232 : XML_TOK_STYLE_FILL_CHARACTER,
233 : XML_TOK_STYLE_NUMBER,
234 : XML_TOK_STYLE_SCIENTIFIC_NUMBER,
235 : XML_TOK_STYLE_FRACTION,
236 : XML_TOK_STYLE_CURRENCY_SYMBOL,
237 : XML_TOK_STYLE_DAY,
238 : XML_TOK_STYLE_MONTH,
239 : XML_TOK_STYLE_YEAR,
240 : XML_TOK_STYLE_ERA,
241 : XML_TOK_STYLE_DAY_OF_WEEK,
242 : XML_TOK_STYLE_WEEK_OF_YEAR,
243 : XML_TOK_STYLE_QUARTER,
244 : XML_TOK_STYLE_HOURS,
245 : XML_TOK_STYLE_AM_PM,
246 : XML_TOK_STYLE_MINUTES,
247 : XML_TOK_STYLE_SECONDS,
248 : XML_TOK_STYLE_BOOLEAN,
249 : XML_TOK_STYLE_TEXT_CONTENT,
250 : XML_TOK_STYLE_PROPERTIES,
251 : XML_TOK_STYLE_MAP
252 : };
253 :
254 : enum SvXMLStyleAttrTokens
255 : {
256 : XML_TOK_STYLE_ATTR_NAME,
257 : XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG,
258 : XML_TOK_STYLE_ATTR_LANGUAGE,
259 : XML_TOK_STYLE_ATTR_SCRIPT,
260 : XML_TOK_STYLE_ATTR_COUNTRY,
261 : XML_TOK_STYLE_ATTR_TITLE,
262 : XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER,
263 : XML_TOK_STYLE_ATTR_FORMAT_SOURCE,
264 : XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW,
265 : XML_TOK_STYLE_ATTR_VOLATILE,
266 : XML_TOK_STYLE_ATTR_TRANSL_FORMAT,
267 : XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG,
268 : XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE,
269 : XML_TOK_STYLE_ATTR_TRANSL_SCRIPT,
270 : XML_TOK_STYLE_ATTR_TRANSL_COUNTRY,
271 : XML_TOK_STYLE_ATTR_TRANSL_STYLE
272 : };
273 :
274 : enum SvXMLStyleElemAttrTokens
275 : {
276 : XML_TOK_ELEM_ATTR_DECIMAL_PLACES,
277 : XML_TOK_ELEM_ATTR_MIN_DECIMAL_DIGITS,
278 : XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS,
279 : XML_TOK_ELEM_ATTR_GROUPING,
280 : XML_TOK_ELEM_ATTR_DISPLAY_FACTOR,
281 : XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT,
282 : XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE,
283 : XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS,
284 : XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL,
285 : XML_TOK_ELEM_ATTR_EXPONENT_SIGN,
286 : XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS,
287 : XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS,
288 : XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG,
289 : XML_TOK_ELEM_ATTR_LANGUAGE,
290 : XML_TOK_ELEM_ATTR_SCRIPT,
291 : XML_TOK_ELEM_ATTR_COUNTRY,
292 : XML_TOK_ELEM_ATTR_STYLE,
293 : XML_TOK_ELEM_ATTR_TEXTUAL,
294 : XML_TOK_ELEM_ATTR_CALENDAR
295 : };
296 :
297 :
298 : // standard colors
299 :
300 :
301 : #define XML_NUMF_COLORCOUNT 10
302 :
303 : static const ColorData aNumFmtStdColors[XML_NUMF_COLORCOUNT] =
304 : {
305 : COL_BLACK,
306 : COL_LIGHTBLUE,
307 : COL_LIGHTGREEN,
308 : COL_LIGHTCYAN,
309 : COL_LIGHTRED,
310 : COL_LIGHTMAGENTA,
311 : COL_BROWN,
312 : COL_GRAY,
313 : COL_YELLOW,
314 : COL_WHITE
315 : };
316 :
317 :
318 : // token maps
319 :
320 :
321 : // maps for SvXMLUnitConverter::convertEnum
322 :
323 : static const SvXMLEnumMapEntry aStyleValueMap[] =
324 : {
325 : { XML_SHORT, sal_uInt16(false) },
326 : { XML_LONG, sal_uInt16(true) },
327 : { XML_TOKEN_INVALID, 0 }
328 : };
329 :
330 : static const SvXMLEnumMapEntry aFormatSourceMap[] =
331 : {
332 : { XML_FIXED, sal_uInt16(false) },
333 : { XML_LANGUAGE, sal_uInt16(true) },
334 : { XML_TOKEN_INVALID, 0 }
335 : };
336 :
337 : struct SvXMLDefaultDateFormat
338 : {
339 : NfIndexTableOffset eFormat;
340 : SvXMLDateElementAttributes eDOW;
341 : SvXMLDateElementAttributes eDay;
342 : SvXMLDateElementAttributes eMonth;
343 : SvXMLDateElementAttributes eYear;
344 : SvXMLDateElementAttributes eHours;
345 : SvXMLDateElementAttributes eMins;
346 : SvXMLDateElementAttributes eSecs;
347 : bool bSystem;
348 : };
349 :
350 : static const SvXMLDefaultDateFormat aDefaultDateFormats[] =
351 : {
352 : // format day-of-week day month year hours minutes seconds format-source
353 :
354 : { NF_DATE_SYSTEM_SHORT, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, true },
355 : { NF_DATE_SYSTEM_LONG, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, true },
356 : { NF_DATE_SYS_MMYY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
357 : { NF_DATE_SYS_DDMMM, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_TEXTSHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
358 : { NF_DATE_SYS_DDMMYYYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
359 : { NF_DATE_SYS_DDMMYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
360 : { NF_DATE_SYS_DMMMYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
361 : { NF_DATE_SYS_DMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
362 : { NF_DATE_SYS_DMMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
363 : { NF_DATE_SYS_NNDMMMYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
364 : { NF_DATE_SYS_NNDMMMMYYYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
365 : { NF_DATE_SYS_NNNNDMMMMYYYY, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
366 : { NF_DATETIME_SYSTEM_SHORT_HHMM, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, true },
367 : { NF_DATETIME_SYS_DDMMYYYY_HHMMSS, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, false }
368 : };
369 :
370 :
371 : // SvXMLNumImpData
372 :
373 :
374 1289 : SvXMLNumImpData::SvXMLNumImpData(
375 : SvNumberFormatter* pFmt,
376 : const uno::Reference<uno::XComponentContext>& rxContext )
377 : : pFormatter(pFmt),
378 : pStylesElemTokenMap(NULL),
379 : pStyleElemTokenMap(NULL),
380 : pStyleAttrTokenMap(NULL),
381 : pStyleElemAttrTokenMap(NULL),
382 : pLocaleData(NULL),
383 1289 : m_xContext(rxContext)
384 : {
385 : DBG_ASSERT( rxContext.is(), "got no service manager" );
386 1289 : }
387 :
388 2578 : SvXMLNumImpData::~SvXMLNumImpData()
389 : {
390 1289 : delete pStylesElemTokenMap;
391 1289 : delete pStyleElemTokenMap;
392 1289 : delete pStyleAttrTokenMap;
393 1289 : delete pStyleElemAttrTokenMap;
394 1289 : delete pLocaleData;
395 1289 : }
396 :
397 636 : sal_uInt32 SvXMLNumImpData::GetKeyForName( const OUString& rName )
398 : {
399 636 : sal_uInt16 nCount = aNameEntries.size();
400 42458 : for (sal_uInt16 i=0; i<nCount; i++)
401 : {
402 42458 : const SvXMLNumFmtEntry* pObj = &aNameEntries[i];
403 42458 : if ( pObj->aName == rName )
404 636 : return pObj->nKey; // found
405 : }
406 0 : return NUMBERFORMAT_ENTRY_NOT_FOUND;
407 : }
408 :
409 1942 : void SvXMLNumImpData::AddKey( sal_uInt32 nKey, const OUString& rName, bool bRemoveAfterUse )
410 : {
411 1942 : if ( bRemoveAfterUse )
412 : {
413 : // if there is already an entry for this key without the bRemoveAfterUse flag,
414 : // clear the flag for this entry, too
415 :
416 636 : sal_uInt16 nCount = aNameEntries.size();
417 40089 : for (sal_uInt16 i=0; i<nCount; i++)
418 : {
419 39482 : SvXMLNumFmtEntry* pObj = &aNameEntries[i];
420 39482 : if ( pObj->nKey == nKey && !pObj->bRemoveAfterUse )
421 : {
422 29 : bRemoveAfterUse = false; // clear flag for new entry
423 29 : break;
424 : }
425 : }
426 : }
427 : else
428 : {
429 : // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
430 1306 : SetUsed( nKey );
431 : }
432 :
433 1942 : SvXMLNumFmtEntry* pObj = new SvXMLNumFmtEntry( rName, nKey, bRemoveAfterUse );
434 1942 : aNameEntries.push_back( pObj );
435 1942 : }
436 :
437 1306 : void SvXMLNumImpData::SetUsed( sal_uInt32 nKey )
438 : {
439 1306 : sal_uInt16 nCount = aNameEntries.size();
440 50033 : for (sal_uInt16 i=0; i<nCount; i++)
441 : {
442 48727 : SvXMLNumFmtEntry* pObj = &aNameEntries[i];
443 48727 : if ( pObj->nKey == nKey )
444 : {
445 12 : pObj->bRemoveAfterUse = false; // used -> don't remove
446 :
447 : // continue searching - there may be several entries for the same key
448 : // (with different names), the format must not be deleted if any one of
449 : // them is used
450 : }
451 : }
452 1306 : }
453 :
454 1289 : void SvXMLNumImpData::RemoveVolatileFormats()
455 : {
456 : // remove temporary (volatile) formats from NumberFormatter
457 : // called at the end of each import (styles and content), so volatile formats
458 : // from styles can't be used in content
459 :
460 1289 : if ( !pFormatter )
461 1289 : return;
462 :
463 1289 : sal_uInt16 nCount = aNameEntries.size();
464 3231 : for (sal_uInt16 i=0; i<nCount; i++)
465 : {
466 1942 : const SvXMLNumFmtEntry* pObj = &aNameEntries[i];
467 1942 : if ( pObj->bRemoveAfterUse )
468 : {
469 606 : const SvNumberformat* pFormat = pFormatter->GetEntry(pObj->nKey);
470 606 : if (pFormat && (pFormat->GetType() & css::util::NumberFormat::DEFINED))
471 492 : pFormatter->DeleteEntry( pObj->nKey );
472 : }
473 : }
474 : }
475 :
476 24769 : const SvXMLTokenMap& SvXMLNumImpData::GetStylesElemTokenMap()
477 : {
478 24769 : if( !pStylesElemTokenMap )
479 : {
480 : static const SvXMLTokenMapEntry aStylesElemMap[] =
481 : {
482 : // style elements
483 : { XML_NAMESPACE_NUMBER, XML_NUMBER_STYLE, XML_TOK_STYLES_NUMBER_STYLE },
484 : { XML_NAMESPACE_NUMBER, XML_CURRENCY_STYLE, XML_TOK_STYLES_CURRENCY_STYLE },
485 : { XML_NAMESPACE_NUMBER, XML_PERCENTAGE_STYLE, XML_TOK_STYLES_PERCENTAGE_STYLE },
486 : { XML_NAMESPACE_NUMBER, XML_DATE_STYLE, XML_TOK_STYLES_DATE_STYLE },
487 : { XML_NAMESPACE_NUMBER, XML_TIME_STYLE, XML_TOK_STYLES_TIME_STYLE },
488 : { XML_NAMESPACE_NUMBER, XML_BOOLEAN_STYLE, XML_TOK_STYLES_BOOLEAN_STYLE },
489 : { XML_NAMESPACE_NUMBER, XML_TEXT_STYLE, XML_TOK_STYLES_TEXT_STYLE },
490 : XML_TOKEN_MAP_END
491 : };
492 :
493 1260 : pStylesElemTokenMap = new SvXMLTokenMap( aStylesElemMap );
494 : }
495 24769 : return *pStylesElemTokenMap;
496 : }
497 :
498 6114 : const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemTokenMap()
499 : {
500 6114 : if( !pStyleElemTokenMap )
501 : {
502 : static const SvXMLTokenMapEntry aStyleElemMap[] =
503 : {
504 : // elements in a style
505 : { XML_NAMESPACE_LO_EXT, XML_TEXT, XML_TOK_STYLE_TEXT },
506 : { XML_NAMESPACE_NUMBER, XML_TEXT, XML_TOK_STYLE_TEXT },
507 : { XML_NAMESPACE_LO_EXT, XML_FILL_CHARACTER, XML_TOK_STYLE_FILL_CHARACTER },
508 : { XML_NAMESPACE_NUMBER, XML_FILL_CHARACTER, XML_TOK_STYLE_FILL_CHARACTER },
509 : { XML_NAMESPACE_NUMBER, XML_NUMBER, XML_TOK_STYLE_NUMBER },
510 : { XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER, XML_TOK_STYLE_SCIENTIFIC_NUMBER },
511 : { XML_NAMESPACE_NUMBER, XML_FRACTION, XML_TOK_STYLE_FRACTION },
512 : { XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL, XML_TOK_STYLE_CURRENCY_SYMBOL },
513 : { XML_NAMESPACE_NUMBER, XML_DAY, XML_TOK_STYLE_DAY },
514 : { XML_NAMESPACE_NUMBER, XML_MONTH, XML_TOK_STYLE_MONTH },
515 : { XML_NAMESPACE_NUMBER, XML_YEAR, XML_TOK_STYLE_YEAR },
516 : { XML_NAMESPACE_NUMBER, XML_ERA, XML_TOK_STYLE_ERA },
517 : { XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK, XML_TOK_STYLE_DAY_OF_WEEK },
518 : { XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR, XML_TOK_STYLE_WEEK_OF_YEAR },
519 : { XML_NAMESPACE_NUMBER, XML_QUARTER, XML_TOK_STYLE_QUARTER },
520 : { XML_NAMESPACE_NUMBER, XML_HOURS, XML_TOK_STYLE_HOURS },
521 : { XML_NAMESPACE_NUMBER, XML_AM_PM, XML_TOK_STYLE_AM_PM },
522 : { XML_NAMESPACE_NUMBER, XML_MINUTES, XML_TOK_STYLE_MINUTES },
523 : { XML_NAMESPACE_NUMBER, XML_SECONDS, XML_TOK_STYLE_SECONDS },
524 : { XML_NAMESPACE_NUMBER, XML_BOOLEAN, XML_TOK_STYLE_BOOLEAN },
525 : { XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT, XML_TOK_STYLE_TEXT_CONTENT },
526 : { XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES, XML_TOK_STYLE_PROPERTIES },
527 : { XML_NAMESPACE_STYLE, XML_MAP, XML_TOK_STYLE_MAP },
528 : XML_TOKEN_MAP_END
529 : };
530 :
531 314 : pStyleElemTokenMap = new SvXMLTokenMap( aStyleElemMap );
532 : }
533 6114 : return *pStyleElemTokenMap;
534 : }
535 :
536 3579 : const SvXMLTokenMap& SvXMLNumImpData::GetStyleAttrTokenMap()
537 : {
538 3579 : if( !pStyleAttrTokenMap )
539 : {
540 : static const SvXMLTokenMapEntry aStyleAttrMap[] =
541 : {
542 : // attributes for a style
543 : { XML_NAMESPACE_STYLE, XML_NAME, XML_TOK_STYLE_ATTR_NAME },
544 : { XML_NAMESPACE_NUMBER, XML_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG, },
545 : { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_STYLE_ATTR_LANGUAGE },
546 : { XML_NAMESPACE_NUMBER, XML_SCRIPT, XML_TOK_STYLE_ATTR_SCRIPT },
547 : { XML_NAMESPACE_NUMBER, XML_COUNTRY, XML_TOK_STYLE_ATTR_COUNTRY },
548 : { XML_NAMESPACE_NUMBER, XML_TITLE, XML_TOK_STYLE_ATTR_TITLE },
549 : { XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER },
550 : { XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE, XML_TOK_STYLE_ATTR_FORMAT_SOURCE },
551 : { XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW, XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW },
552 : { XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TOK_STYLE_ATTR_VOLATILE },
553 : { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT, XML_TOK_STYLE_ATTR_TRANSL_FORMAT },
554 : // not defined in ODF { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG },
555 : { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE },
556 : // not defined in ODF { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_SCRIPT, XML_TOK_STYLE_ATTR_TRANSL_SCRIPT },
557 : { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY },
558 : { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE, XML_TOK_STYLE_ATTR_TRANSL_STYLE },
559 : XML_TOKEN_MAP_END
560 : };
561 :
562 314 : pStyleAttrTokenMap = new SvXMLTokenMap( aStyleAttrMap );
563 : }
564 3579 : return *pStyleAttrTokenMap;
565 : }
566 :
567 5338 : const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemAttrTokenMap()
568 : {
569 5338 : if( !pStyleElemAttrTokenMap )
570 : {
571 : static const SvXMLTokenMapEntry aStyleElemAttrMap[] =
572 : {
573 : // attributes for an element within a style
574 : { XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES, XML_TOK_ELEM_ATTR_DECIMAL_PLACES },
575 : { XML_NAMESPACE_LO_EXT, XML_MIN_DECIMAL_DIGITS, XML_TOK_ELEM_ATTR_MIN_DECIMAL_DIGITS },
576 : { XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS, XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS },
577 : { XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TOK_ELEM_ATTR_GROUPING },
578 : { XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, XML_TOK_ELEM_ATTR_DISPLAY_FACTOR },
579 : { XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT, XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT },
580 : { XML_NAMESPACE_NUMBER, XML_DENOMINATOR_VALUE, XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE },
581 : { XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS, XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS },
582 : { XML_NAMESPACE_LO_EXT, XML_EXPONENT_INTERVAL, XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL },
583 : { XML_NAMESPACE_NUMBER, XML_EXPONENT_INTERVAL, XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL },
584 : { XML_NAMESPACE_LO_EXT, XML_EXPONENT_SIGN, XML_TOK_ELEM_ATTR_EXPONENT_SIGN },
585 : { XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS, XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS },
586 : { XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS, XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS },
587 : { XML_NAMESPACE_NUMBER, XML_RFC_LANGUAGE_TAG, XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG },
588 : { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_ELEM_ATTR_LANGUAGE },
589 : { XML_NAMESPACE_NUMBER, XML_SCRIPT, XML_TOK_ELEM_ATTR_SCRIPT },
590 : { XML_NAMESPACE_NUMBER, XML_COUNTRY, XML_TOK_ELEM_ATTR_COUNTRY },
591 : { XML_NAMESPACE_NUMBER, XML_STYLE, XML_TOK_ELEM_ATTR_STYLE },
592 : { XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TOK_ELEM_ATTR_TEXTUAL },
593 : { XML_NAMESPACE_NUMBER, XML_CALENDAR, XML_TOK_ELEM_ATTR_CALENDAR },
594 : XML_TOKEN_MAP_END
595 : };
596 :
597 312 : pStyleElemAttrTokenMap = new SvXMLTokenMap( aStyleElemAttrMap );
598 : }
599 5338 : return *pStyleElemAttrTokenMap;
600 : }
601 :
602 1187 : const LocaleDataWrapper& SvXMLNumImpData::GetLocaleData( LanguageType nLang )
603 : {
604 1187 : if ( !pLocaleData )
605 : pLocaleData = new LocaleDataWrapper(
606 : pFormatter ? pFormatter->GetComponentContext() : m_xContext,
607 204 : LanguageTag( nLang ) );
608 : else
609 983 : pLocaleData->setLanguageTag( LanguageTag( nLang ) );
610 1187 : return *pLocaleData;
611 : }
612 :
613 :
614 : // SvXMLNumFmtMapContext
615 :
616 :
617 636 : SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport& rImport,
618 : sal_uInt16 nPrfx, const OUString& rLName,
619 : SvXMLNumFormatContext& rParentContext,
620 : const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
621 : SvXMLImportContext( rImport, nPrfx, rLName ),
622 636 : rParent( rParentContext )
623 : {
624 636 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
625 1908 : for( sal_Int16 i=0; i < nAttrCount; i++ )
626 : {
627 1272 : OUString sAttrName = xAttrList->getNameByIndex( i );
628 2544 : OUString sValue = xAttrList->getValueByIndex( i );
629 2544 : OUString aLocalName;
630 1272 : sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
631 1272 : if ( nPrefix == XML_NAMESPACE_STYLE )
632 : {
633 1272 : if ( IsXMLToken( aLocalName, XML_CONDITION) )
634 636 : sCondition = sValue;
635 636 : else if ( IsXMLToken( aLocalName, XML_APPLY_STYLE_NAME) )
636 636 : sName = sValue;
637 : }
638 1272 : }
639 636 : }
640 :
641 1272 : SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext()
642 : {
643 1272 : }
644 :
645 0 : SvXMLImportContext* SvXMLNumFmtMapContext::CreateChildContext(
646 : sal_uInt16 nPrfx, const OUString& rLName,
647 : const uno::Reference<xml::sax::XAttributeList>& )
648 : {
649 : // no elements supported - use default context
650 0 : return new SvXMLImportContext( GetImport(), nPrfx, rLName );
651 : }
652 :
653 0 : void SvXMLNumFmtMapContext::Characters( const OUString& )
654 : {
655 0 : }
656 :
657 636 : void SvXMLNumFmtMapContext::EndElement()
658 : {
659 636 : rParent.AddCondition( sCondition, sName );
660 636 : }
661 :
662 :
663 : // SvXMLNumFmtPropContext
664 :
665 :
666 305 : SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport& rImport,
667 : sal_uInt16 nPrfx, const OUString& rLName,
668 : SvXMLNumFormatContext& rParentContext,
669 : const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
670 : SvXMLImportContext( rImport, nPrfx, rLName ),
671 : rParent( rParentContext ),
672 : m_nColor( 0 ),
673 305 : bColSet( false )
674 : {
675 305 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
676 610 : for( sal_Int16 i=0; i < nAttrCount; i++ )
677 : {
678 305 : OUString sAttrName = xAttrList->getNameByIndex( i );
679 610 : OUString sValue = xAttrList->getValueByIndex( i );
680 610 : OUString aLocalName;
681 305 : sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
682 305 : if ( nPrefix == XML_NAMESPACE_FO && IsXMLToken( aLocalName, XML_COLOR ) )
683 : {
684 305 : bColSet = ::sax::Converter::convertColor( m_nColor, sValue );
685 : }
686 305 : }
687 305 : }
688 :
689 610 : SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext()
690 : {
691 610 : }
692 :
693 0 : SvXMLImportContext* SvXMLNumFmtPropContext::CreateChildContext(
694 : sal_uInt16 nPrfx, const OUString& rLName,
695 : const uno::Reference<xml::sax::XAttributeList>& )
696 : {
697 : // no elements supported - use default context
698 0 : return new SvXMLImportContext( GetImport(), nPrfx, rLName );
699 : }
700 :
701 0 : void SvXMLNumFmtPropContext::Characters( const OUString& )
702 : {
703 0 : }
704 :
705 305 : void SvXMLNumFmtPropContext::EndElement()
706 : {
707 305 : if (bColSet)
708 305 : rParent.AddColor( m_nColor );
709 305 : }
710 :
711 :
712 : // SvXMLNumFmtEmbeddedTextContext
713 :
714 :
715 0 : SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport,
716 : sal_uInt16 nPrfx, const OUString& rLName,
717 : SvXMLNumFmtElementContext& rParentContext,
718 : const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
719 : SvXMLImportContext( rImport, nPrfx, rLName ),
720 : rParent( rParentContext ),
721 0 : nTextPosition( 0 )
722 : {
723 : sal_Int32 nAttrVal;
724 :
725 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
726 0 : for( sal_Int16 i=0; i < nAttrCount; i++ )
727 : {
728 0 : OUString sAttrName = xAttrList->getNameByIndex( i );
729 0 : OUString sValue = xAttrList->getValueByIndex( i );
730 0 : OUString aLocalName;
731 0 : sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
732 0 : if ( nPrefix == XML_NAMESPACE_NUMBER && IsXMLToken( aLocalName, XML_POSITION ) )
733 : {
734 0 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
735 0 : nTextPosition = nAttrVal;
736 : }
737 0 : }
738 0 : }
739 :
740 0 : SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext()
741 : {
742 0 : }
743 :
744 0 : SvXMLImportContext* SvXMLNumFmtEmbeddedTextContext::CreateChildContext(
745 : sal_uInt16 nPrfx, const OUString& rLName,
746 : const uno::Reference<xml::sax::XAttributeList>& )
747 : {
748 : // no elements supported - use default context
749 0 : return new SvXMLImportContext( GetImport(), nPrfx, rLName );
750 : }
751 :
752 0 : void SvXMLNumFmtEmbeddedTextContext::Characters( const OUString& rChars )
753 : {
754 0 : aContent.append( rChars );
755 0 : }
756 :
757 0 : void SvXMLNumFmtEmbeddedTextContext::EndElement()
758 : {
759 0 : rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() );
760 0 : }
761 :
762 1823 : static bool lcl_ValidChar( sal_Unicode cChar, const SvXMLNumFormatContext& rParent )
763 : {
764 1823 : sal_uInt16 nFormatType = rParent.GetType();
765 :
766 : // Treat space equal to non-breaking space separator.
767 1823 : const sal_Unicode cNBSP = 0x00A0;
768 : sal_Unicode cTS;
769 3088 : if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE ||
770 712 : nFormatType == XML_TOK_STYLES_CURRENCY_STYLE ||
771 2993 : nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) &&
772 2306 : (cChar == (cTS = rParent.GetLocaleData().getNumThousandSep()[0]) ||
773 453 : (cChar == ' ' && cTS == cNBSP)) )
774 : {
775 : // #i22394# Extra occurrences of thousands separator must be quoted, so they
776 : // aren't mis-interpreted as display-factor.
777 : // This must be limited to the format types that can contain a number element,
778 : // because the same character can be a date separator that should not be quoted
779 : // in date formats.
780 :
781 17 : return false; // force quotes
782 : }
783 :
784 : // see ImpSvNumberformatScan::Next_Symbol
785 1806 : if ( cChar == ' ' ||
786 732 : cChar == '-' ||
787 544 : cChar == '/' ||
788 520 : cChar == '.' ||
789 506 : cChar == ',' ||
790 315 : cChar == ':' ||
791 : cChar == '\'' )
792 1491 : return true; // for all format types
793 :
794 : // percent sign must be used without quotes for percentage styles only
795 315 : if ( nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE && cChar == '%' )
796 42 : return true;
797 :
798 : // don't put quotes around single parentheses (often used for negative numbers)
799 273 : if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE ||
800 11 : nFormatType == XML_TOK_STYLES_CURRENCY_STYLE ||
801 262 : nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) &&
802 157 : ( cChar == '(' || cChar == ')' ) )
803 214 : return true;
804 :
805 59 : return false;
806 : }
807 :
808 2031 : static void lcl_EnquoteIfNecessary( OUStringBuffer& rContent, const SvXMLNumFormatContext& rParent )
809 : {
810 2031 : bool bQuote = true;
811 2031 : sal_Int32 nLength = rContent.getLength();
812 :
813 3675 : if ( ( nLength == 1 &&
814 4100 : lcl_ValidChar( rContent[0], rParent ) ) ||
815 179 : ( nLength == 2 &&
816 328 : lcl_ValidChar( rContent[0], rParent ) &&
817 149 : rContent[1] == ' ' ) )
818 : {
819 : // don't quote single separator characters like space or percent,
820 : // or separator characters followed by space (used in date formats)
821 1636 : bQuote = false;
822 : }
823 395 : else if ( rParent.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE && nLength > 1 )
824 : {
825 : // the percent character in percentage styles must be left out of quoting
826 : // (one occurrence is enough even if there are several percent characters in the string)
827 :
828 0 : OUString aString( rContent.getStr() );
829 0 : sal_Int32 nPos = aString.indexOf( '%' );
830 0 : if ( nPos >= 0 )
831 : {
832 0 : if ( nPos + 1 < nLength )
833 : {
834 0 : if ( nPos + 2 == nLength && lcl_ValidChar( rContent[nPos + 1], rParent ) )
835 : {
836 : // single character that doesn't need quoting
837 : }
838 : else
839 : {
840 : // quote text behind percent character
841 0 : rContent.insert( nPos + 1, '"' );
842 0 : rContent.append( '"' );
843 : }
844 : }
845 0 : if ( nPos > 0 )
846 : {
847 0 : if ( nPos == 1 && lcl_ValidChar( rContent[0], rParent ) )
848 : {
849 : // single character that doesn't need quoting
850 : }
851 : else
852 : {
853 : // quote text before percent character
854 0 : rContent.insert( nPos, '"' );
855 0 : rContent.insert( 0, '"' );
856 : }
857 : }
858 0 : bQuote = false;
859 0 : }
860 : // else: normal quoting (below)
861 : }
862 :
863 2031 : if ( bQuote )
864 : {
865 : // #i55469# quotes in the string itself have to be escaped
866 395 : bool bEscape = ( rContent.indexOf( '"' ) >= 0 );
867 395 : if ( bEscape )
868 : {
869 : // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
870 : // and a quote to resume quoting.
871 44 : OUString aInsert( "\"\\\"" );
872 :
873 44 : sal_Int32 nPos = 0;
874 244 : while ( nPos < rContent.getLength() )
875 : {
876 156 : if ( rContent[nPos] == '"' )
877 : {
878 44 : rContent.insert( nPos, aInsert );
879 44 : nPos += aInsert.getLength();
880 : }
881 156 : ++nPos;
882 44 : }
883 : }
884 :
885 : // quote string literals
886 395 : rContent.insert( 0, '"' );
887 395 : rContent.append( '"' );
888 :
889 : // remove redundant double quotes at start or end
890 395 : if ( bEscape )
891 : {
892 132 : if ( rContent.getLength() > 2 &&
893 88 : rContent[0] == '"' &&
894 44 : rContent[1] == '"' )
895 : {
896 0 : rContent.remove(0, 2);
897 : }
898 :
899 44 : sal_Int32 nLen = rContent.getLength();
900 88 : if ( nLen > 2 &&
901 88 : rContent[nLen - 1] == '"' &&
902 44 : rContent[nLen - 2] == '"' )
903 : {
904 44 : rContent.truncate(nLen - 2);
905 : }
906 : }
907 : }
908 2031 : }
909 :
910 :
911 : // SvXMLNumFmtElementContext
912 :
913 :
914 : const sal_Int32 MAX_SECOND_DIGITS = 20; // fdo#58539 & gnome#627420: limit number of digits during import
915 :
916 5173 : SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
917 : sal_uInt16 nPrfx, const OUString& rLName,
918 : SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType,
919 : const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
920 : SvXMLImportContext( rImport, nPrfx, rLName ),
921 : rParent( rParentContext ),
922 : nType( nNewType ),
923 : nElementLang( LANGUAGE_SYSTEM ),
924 : bLong( false ),
925 5173 : bTextual( false )
926 : {
927 5173 : LanguageTagODF aLanguageTagODF;
928 : sal_Int32 nAttrVal;
929 5173 : bool bAttrBool(false);
930 5173 : bool bVarDecimals = false;
931 : sal_uInt16 nAttrEnum;
932 : double fAttrDouble;
933 :
934 5173 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
935 10511 : for( sal_Int16 i=0; i < nAttrCount; i++ )
936 : {
937 5338 : OUString sAttrName = xAttrList->getNameByIndex( i );
938 10676 : OUString sValue = xAttrList->getValueByIndex( i );
939 10676 : OUString aLocalName;
940 5338 : sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
941 :
942 5338 : const SvXMLTokenMap& rTokenMap = rParent.GetData()->GetStyleElemAttrTokenMap();
943 5338 : sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
944 :
945 5338 : switch (nToken)
946 : {
947 : case XML_TOK_ELEM_ATTR_DECIMAL_PLACES:
948 1218 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
949 1218 : aNumInfo.nDecimals = std::min<sal_Int32>(nAttrVal, MAX_SECOND_DIGITS);
950 1218 : break;
951 : case XML_TOK_ELEM_ATTR_MIN_DECIMAL_DIGITS:
952 121 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
953 121 : aNumInfo.nMinDecimalDigits = nAttrVal;
954 121 : break;
955 : case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS:
956 1488 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
957 1488 : aNumInfo.nInteger = nAttrVal;
958 1488 : break;
959 : case XML_TOK_ELEM_ATTR_GROUPING:
960 959 : if (::sax::Converter::convertBool( bAttrBool, sValue ))
961 959 : aNumInfo.bGrouping = bAttrBool;
962 959 : break;
963 : case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR:
964 16 : if (::sax::Converter::convertDouble( fAttrDouble, sValue ))
965 16 : aNumInfo.fDisplayFactor = fAttrDouble;
966 16 : break;
967 : case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT:
968 3 : if ( !sValue.isEmpty() )
969 2 : aNumInfo.bDecReplace = true; // only a default string is supported
970 : else
971 1 : bVarDecimals = true; // empty replacement string: variable decimals
972 3 : break;
973 : case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS:
974 37 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
975 37 : aNumInfo.nExpDigits = nAttrVal;
976 37 : break;
977 : case XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL:
978 4 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
979 4 : aNumInfo.nExpInterval = nAttrVal;
980 4 : break;
981 : case XML_TOK_ELEM_ATTR_EXPONENT_SIGN:
982 3 : if (::sax::Converter::convertBool( bAttrBool, sValue ))
983 3 : aNumInfo.bExpSign = bAttrBool;
984 3 : break;
985 : case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS:
986 7 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
987 7 : aNumInfo.nNumerDigits = nAttrVal;
988 7 : break;
989 : case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS:
990 7 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
991 7 : aNumInfo.nDenomDigits = nAttrVal;
992 7 : break;
993 : case XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE:
994 0 : if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
995 0 : aNumInfo.nFracDenominator = nAttrVal;
996 0 : break;
997 : case XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG:
998 0 : aLanguageTagODF.maRfcLanguageTag = sValue;
999 0 : break;
1000 : case XML_TOK_ELEM_ATTR_LANGUAGE:
1001 453 : aLanguageTagODF.maLanguage = sValue;
1002 453 : break;
1003 : case XML_TOK_ELEM_ATTR_SCRIPT:
1004 0 : aLanguageTagODF.maScript = sValue;
1005 0 : break;
1006 : case XML_TOK_ELEM_ATTR_COUNTRY:
1007 453 : aLanguageTagODF.maCountry = sValue;
1008 453 : break;
1009 : case XML_TOK_ELEM_ATTR_STYLE:
1010 487 : if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aStyleValueMap ) )
1011 487 : bLong = (bool) nAttrEnum;
1012 487 : break;
1013 : case XML_TOK_ELEM_ATTR_TEXTUAL:
1014 74 : if (::sax::Converter::convertBool( bAttrBool, sValue ))
1015 74 : bTextual = bAttrBool;
1016 74 : break;
1017 : case XML_TOK_ELEM_ATTR_CALENDAR:
1018 8 : sCalendar = sValue;
1019 8 : break;
1020 : }
1021 5338 : }
1022 5173 : if ( aNumInfo.nMinDecimalDigits == -1)
1023 : {
1024 5052 : if ( bVarDecimals )
1025 1 : aNumInfo.nMinDecimalDigits = 0;
1026 : else
1027 5051 : aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
1028 : }
1029 :
1030 5173 : if ( !aLanguageTagODF.isEmpty() )
1031 : {
1032 453 : nElementLang = aLanguageTagODF.getLanguageTag().getLanguageType( false);
1033 453 : if ( nElementLang == LANGUAGE_DONTKNOW )
1034 0 : nElementLang = LANGUAGE_SYSTEM; //! error handling for unknown locales?
1035 5173 : }
1036 5173 : }
1037 :
1038 10346 : SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext()
1039 : {
1040 10346 : }
1041 :
1042 0 : SvXMLImportContext* SvXMLNumFmtElementContext::CreateChildContext(
1043 : sal_uInt16 nPrfx, const OUString& rLName,
1044 : const uno::Reference<xml::sax::XAttributeList>& xAttrList )
1045 : {
1046 : // only number:number supports number:embedded-text child element
1047 :
1048 0 : if ( nType == XML_TOK_STYLE_NUMBER &&
1049 0 : nPrfx == XML_NAMESPACE_NUMBER && IsXMLToken( rLName, XML_EMBEDDED_TEXT ) )
1050 : {
1051 0 : return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx, rLName, *this, xAttrList );
1052 : }
1053 : else
1054 0 : return new SvXMLImportContext( GetImport(), nPrfx, rLName );
1055 : }
1056 :
1057 2660 : void SvXMLNumFmtElementContext::Characters( const OUString& rChars )
1058 : {
1059 2660 : aContent.append( rChars );
1060 2660 : }
1061 :
1062 0 : void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos, const OUString& rContent )
1063 : {
1064 0 : if ( !rContent.isEmpty() )
1065 : {
1066 0 : SvXMLEmbeddedElement* pObj = new SvXMLEmbeddedElement( nFormatPos, rContent );
1067 0 : if ( !aNumInfo.aEmbeddedElements.insert( pObj ).second )
1068 : {
1069 : // there's already an element at this position - append text to existing element
1070 :
1071 0 : delete pObj;
1072 0 : for (SvXMLEmbeddedElementArr::iterator it = aNumInfo.aEmbeddedElements.begin();
1073 0 : it != aNumInfo.aEmbeddedElements.end(); ++it)
1074 : {
1075 0 : pObj = &*it;
1076 0 : if ( pObj->nFormatPos == nFormatPos )
1077 : {
1078 0 : pObj->aText += rContent;
1079 0 : break;
1080 : }
1081 : }
1082 : }
1083 : }
1084 0 : }
1085 :
1086 5173 : void SvXMLNumFmtElementContext::EndElement()
1087 : {
1088 5173 : bool bEffLong = bLong;
1089 5173 : switch (nType)
1090 : {
1091 : case XML_TOK_STYLE_TEXT:
1092 6119 : if ( rParent.HasLongDoW() &&
1093 2053 : aContent.toString().equals(rParent.GetLocaleData().getLongDateDayOfWeekSep()) )
1094 : {
1095 : // skip separator constant after long day of week
1096 : // (NF_KEY_NNNN contains the separator)
1097 :
1098 5 : if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) )
1099 : {
1100 5 : aContent = OUStringBuffer();
1101 : }
1102 :
1103 5 : rParent.SetHasLongDoW( false ); // only once
1104 : }
1105 2038 : if ( !aContent.isEmpty() )
1106 : {
1107 2031 : lcl_EnquoteIfNecessary( aContent, rParent );
1108 2031 : rParent.AddToCode( aContent.makeStringAndClear() );
1109 : }
1110 2038 : break;
1111 :
1112 : case XML_TOK_STYLE_NUMBER:
1113 1444 : rParent.AddNumber( aNumInfo );
1114 1444 : break;
1115 :
1116 : case XML_TOK_STYLE_CURRENCY_SYMBOL:
1117 571 : rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
1118 571 : break;
1119 :
1120 : case XML_TOK_STYLE_TEXT_CONTENT:
1121 74 : rParent.AddToCode( '@');
1122 74 : break;
1123 : case XML_TOK_STYLE_FILL_CHARACTER:
1124 111 : if ( !aContent.isEmpty() )
1125 : {
1126 111 : rParent.AddToCode( '*' );
1127 111 : rParent.AddToCode( aContent[0] );
1128 : }
1129 111 : break;
1130 : case XML_TOK_STYLE_BOOLEAN:
1131 : // ignored - only default boolean format is supported
1132 13 : break;
1133 :
1134 : case XML_TOK_STYLE_DAY:
1135 165 : rParent.UpdateCalendar( sCalendar );
1136 : //! I18N doesn't provide SYSTEM or extended date information yet
1137 :
1138 : rParent.AddNfKeyword(
1139 : sal::static_int_cast< sal_uInt16 >(
1140 165 : bEffLong ? NF_KEY_DD : NF_KEY_D ) );
1141 165 : break;
1142 : case XML_TOK_STYLE_MONTH:
1143 186 : rParent.UpdateCalendar( sCalendar );
1144 : //! I18N doesn't provide SYSTEM or extended date information yet
1145 :
1146 : rParent.AddNfKeyword(
1147 : sal::static_int_cast< sal_uInt16 >(
1148 : bTextual
1149 : ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
1150 186 : : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
1151 186 : break;
1152 : case XML_TOK_STYLE_YEAR:
1153 158 : rParent.UpdateCalendar( sCalendar );
1154 : //! I18N doesn't provide SYSTEM or extended date information yet
1155 : // Y after G (era) is replaced by E
1156 158 : if ( rParent.HasEra() )
1157 : rParent.AddNfKeyword(
1158 : sal::static_int_cast< sal_uInt16 >(
1159 2 : bEffLong ? NF_KEY_EEC : NF_KEY_EC ) );
1160 : else
1161 : rParent.AddNfKeyword(
1162 : sal::static_int_cast< sal_uInt16 >(
1163 156 : bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
1164 158 : break;
1165 : case XML_TOK_STYLE_ERA:
1166 2 : rParent.UpdateCalendar( sCalendar );
1167 : //! I18N doesn't provide SYSTEM or extended date information yet
1168 : rParent.AddNfKeyword(
1169 : sal::static_int_cast< sal_uInt16 >(
1170 2 : bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
1171 : // HasEra flag is set
1172 2 : break;
1173 : case XML_TOK_STYLE_DAY_OF_WEEK:
1174 12 : rParent.UpdateCalendar( sCalendar );
1175 : //! I18N doesn't provide SYSTEM or extended date information yet
1176 : rParent.AddNfKeyword(
1177 : sal::static_int_cast< sal_uInt16 >(
1178 12 : bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
1179 12 : break;
1180 : case XML_TOK_STYLE_WEEK_OF_YEAR:
1181 0 : rParent.UpdateCalendar( sCalendar );
1182 0 : rParent.AddNfKeyword( NF_KEY_WW );
1183 0 : break;
1184 : case XML_TOK_STYLE_QUARTER:
1185 0 : rParent.UpdateCalendar( sCalendar );
1186 : rParent.AddNfKeyword(
1187 : sal::static_int_cast< sal_uInt16 >(
1188 0 : bEffLong ? NF_KEY_QQ : NF_KEY_Q ) );
1189 0 : break;
1190 : case XML_TOK_STYLE_HOURS:
1191 : rParent.AddNfKeyword(
1192 : sal::static_int_cast< sal_uInt16 >(
1193 108 : bEffLong ? NF_KEY_HH : NF_KEY_H ) );
1194 108 : break;
1195 : case XML_TOK_STYLE_AM_PM:
1196 : //! short/long?
1197 36 : rParent.AddNfKeyword( NF_KEY_AMPM );
1198 36 : break;
1199 : case XML_TOK_STYLE_MINUTES:
1200 : rParent.AddNfKeyword(
1201 : sal::static_int_cast< sal_uInt16 >(
1202 132 : bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
1203 132 : break;
1204 : case XML_TOK_STYLE_SECONDS:
1205 : rParent.AddNfKeyword(
1206 : sal::static_int_cast< sal_uInt16 >(
1207 79 : bEffLong ? NF_KEY_SS : NF_KEY_S ) );
1208 79 : if ( aNumInfo.nDecimals > 0 )
1209 : {
1210 : // manually add the decimal places
1211 12 : rParent.AddToCode(rParent.GetLocaleData().getNumDecimalSep());
1212 24 : for (sal_Int32 i=0; i<aNumInfo.nDecimals; i++)
1213 : {
1214 12 : rParent.AddToCode( '0');
1215 : }
1216 : }
1217 79 : break;
1218 :
1219 : case XML_TOK_STYLE_FRACTION:
1220 : {
1221 7 : if ( aNumInfo.nInteger >= 0 )
1222 : {
1223 : // add integer part only if min-integer-digits attribute is there
1224 7 : aNumInfo.nDecimals = 0;
1225 7 : rParent.AddNumber( aNumInfo ); // number without decimals
1226 7 : rParent.AddToCode( ' ' );
1227 : }
1228 :
1229 : //! build string and add at once
1230 :
1231 : sal_Int32 i;
1232 17 : for (i=0; i<aNumInfo.nNumerDigits; i++)
1233 : {
1234 10 : rParent.AddToCode( '?' );
1235 : }
1236 7 : rParent.AddToCode( '/' );
1237 7 : if ( aNumInfo.nFracDenominator > 0 )
1238 : {
1239 0 : rParent.AddToCode( OUString::number( aNumInfo.nFracDenominator ) );
1240 : }
1241 : else
1242 : {
1243 17 : for (i=0; i<aNumInfo.nDenomDigits; i++)
1244 : {
1245 10 : rParent.AddToCode( '?');
1246 : }
1247 : }
1248 : }
1249 7 : break;
1250 :
1251 : case XML_TOK_STYLE_SCIENTIFIC_NUMBER:
1252 : {
1253 : // exponential interval for engineering notation
1254 37 : if( !aNumInfo.bGrouping && aNumInfo.nExpInterval > aNumInfo.nInteger )
1255 : {
1256 0 : for (sal_Int32 i=aNumInfo.nInteger; i<aNumInfo.nExpInterval; i++)
1257 : {
1258 0 : rParent.AddToCode( '#' );
1259 : }
1260 : }
1261 37 : rParent.AddNumber( aNumInfo ); // simple number
1262 :
1263 37 : if ( aNumInfo.bExpSign )
1264 37 : rParent.AddToCode( OUString("E+") );
1265 : else
1266 0 : rParent.AddToCode( OUString("E") );
1267 103 : for (sal_Int32 i=0; i<aNumInfo.nExpDigits; i++)
1268 : {
1269 66 : rParent.AddToCode( '0' );
1270 : }
1271 : }
1272 37 : break;
1273 :
1274 : default:
1275 : OSL_FAIL("invalid element ID");
1276 : }
1277 5173 : }
1278 :
1279 293 : sal_uInt16 SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW,
1280 : SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth,
1281 : SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours,
1282 : SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs,
1283 : bool bSystem )
1284 : {
1285 : static const sal_uInt16 nCount = sizeof(aDefaultDateFormats) / sizeof(SvXMLDefaultDateFormat);
1286 1888 : for (sal_uInt16 nPos=0; nPos<nCount; nPos++)
1287 : {
1288 1854 : const SvXMLDefaultDateFormat& rEntry = aDefaultDateFormats[nPos];
1289 3092 : if ( bSystem == rEntry.bSystem &&
1290 2476 : ( eDOW == rEntry.eDOW || ( rEntry.eDOW == XML_DEA_ANY && eDOW != XML_DEA_NONE ) ) &&
1291 2186 : ( eDay == rEntry.eDay || ( rEntry.eDay == XML_DEA_ANY && eDay != XML_DEA_NONE ) ) &&
1292 1318 : ( eMonth == rEntry.eMonth || ( rEntry.eMonth == XML_DEA_ANY && eMonth != XML_DEA_NONE ) ) &&
1293 646 : ( eYear == rEntry.eYear || ( rEntry.eYear == XML_DEA_ANY && eYear != XML_DEA_NONE ) ) &&
1294 570 : ( eHours == rEntry.eHours || ( rEntry.eHours == XML_DEA_ANY && eHours != XML_DEA_NONE ) ) &&
1295 518 : ( eMins == rEntry.eMins || ( rEntry.eMins == XML_DEA_ANY && eMins != XML_DEA_NONE ) ) &&
1296 259 : ( eSecs == rEntry.eSecs || ( rEntry.eSecs == XML_DEA_ANY && eSecs != XML_DEA_NONE ) ) )
1297 : {
1298 259 : return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat);
1299 : }
1300 : }
1301 :
1302 34 : return NF_INDEX_TABLE_ENTRIES; // invalid
1303 : }
1304 :
1305 :
1306 : // SvXMLNumFormatContext
1307 :
1308 :
1309 1946 : SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
1310 : sal_uInt16 nPrfx, const OUString& rLName,
1311 : SvXMLNumImpData* pNewData, sal_uInt16 nNewType,
1312 : const uno::Reference<xml::sax::XAttributeList>& xAttrList,
1313 : SvXMLStylesContext& rStyles ) :
1314 : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList ),
1315 : pData( pNewData ),
1316 : pStyles( &rStyles ),
1317 : aMyConditions(),
1318 : nType( nNewType ),
1319 : nKey(-1),
1320 : nFormatLang( LANGUAGE_SYSTEM ),
1321 : bAutoOrder( false ),
1322 : bFromSystem( false ),
1323 : bTruncate( true ),
1324 : bAutoDec( false ),
1325 : bAutoInt( false ),
1326 : bHasExtraText( false ),
1327 : bHasLongDoW( false ),
1328 : bHasEra( false ),
1329 : bHasDateTime( false ),
1330 : bRemoveAfterUse( false ),
1331 : eDateDOW( XML_DEA_NONE ),
1332 : eDateDay( XML_DEA_NONE ),
1333 : eDateMonth( XML_DEA_NONE ),
1334 : eDateYear( XML_DEA_NONE ),
1335 : eDateHours( XML_DEA_NONE ),
1336 : eDateMins( XML_DEA_NONE ),
1337 : eDateSecs( XML_DEA_NONE ),
1338 1946 : bDateNoDefault( false )
1339 : {
1340 1946 : LanguageTagODF aLanguageTagODF;
1341 3892 : OUString sNatNumAttrScript, sNatNumAttrRfcLanguageTag;
1342 3892 : ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr;
1343 1946 : bool bAttrBool(false);
1344 : sal_uInt16 nAttrEnum;
1345 :
1346 1946 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1347 5525 : for( sal_Int16 i=0; i < nAttrCount; i++ )
1348 : {
1349 3579 : OUString sAttrName = xAttrList->getNameByIndex( i );
1350 7158 : OUString sValue = xAttrList->getValueByIndex( i );
1351 7158 : OUString aLocalName;
1352 3579 : sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
1353 :
1354 3579 : const SvXMLTokenMap& rTokenMap = pData->GetStyleAttrTokenMap();
1355 3579 : sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
1356 3579 : switch (nToken)
1357 : {
1358 : case XML_TOK_STYLE_ATTR_NAME:
1359 1946 : break;
1360 : case XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG:
1361 0 : aLanguageTagODF.maRfcLanguageTag = sValue;
1362 0 : break;
1363 : case XML_TOK_STYLE_ATTR_LANGUAGE:
1364 428 : aLanguageTagODF.maLanguage = sValue;
1365 428 : break;
1366 : case XML_TOK_STYLE_ATTR_SCRIPT:
1367 0 : aLanguageTagODF.maScript = sValue;
1368 0 : break;
1369 : case XML_TOK_STYLE_ATTR_COUNTRY:
1370 428 : aLanguageTagODF.maCountry = sValue;
1371 428 : break;
1372 : case XML_TOK_STYLE_ATTR_TITLE:
1373 0 : sFormatTitle = sValue;
1374 0 : break;
1375 : case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER:
1376 104 : if (::sax::Converter::convertBool( bAttrBool, sValue ))
1377 104 : bAutoOrder = bAttrBool;
1378 104 : break;
1379 : case XML_TOK_STYLE_ATTR_FORMAT_SOURCE:
1380 2 : if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aFormatSourceMap ) )
1381 2 : bFromSystem = (bool) nAttrEnum;
1382 2 : break;
1383 : case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW:
1384 12 : if (::sax::Converter::convertBool( bAttrBool, sValue ))
1385 12 : bTruncate = bAttrBool;
1386 12 : break;
1387 : case XML_TOK_STYLE_ATTR_VOLATILE:
1388 : // volatile formats can be removed after importing
1389 : // if not used in other styles
1390 636 : if (::sax::Converter::convertBool( bAttrBool, sValue ))
1391 636 : bRemoveAfterUse = bAttrBool;
1392 636 : break;
1393 : case XML_TOK_STYLE_ATTR_TRANSL_FORMAT:
1394 1 : aNatNumAttr.Format = sValue;
1395 1 : break;
1396 : case XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG:
1397 0 : sNatNumAttrRfcLanguageTag = sValue;
1398 0 : break;
1399 : case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE:
1400 1 : aNatNumAttr.Locale.Language = sValue;
1401 1 : break;
1402 : case XML_TOK_STYLE_ATTR_TRANSL_SCRIPT:
1403 0 : sNatNumAttrScript = sValue;
1404 0 : break;
1405 : case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY:
1406 1 : aNatNumAttr.Locale.Country = sValue;
1407 1 : break;
1408 : case XML_TOK_STYLE_ATTR_TRANSL_STYLE:
1409 1 : aNatNumAttr.Style = sValue;
1410 1 : break;
1411 : }
1412 3579 : }
1413 :
1414 1946 : if (!aLanguageTagODF.isEmpty())
1415 : {
1416 428 : nFormatLang = aLanguageTagODF.getLanguageTag().getLanguageType( false);
1417 428 : if ( nFormatLang == LANGUAGE_DONTKNOW )
1418 0 : nFormatLang = LANGUAGE_SYSTEM; //! error handling for unknown locales?
1419 : }
1420 :
1421 1946 : if ( !aNatNumAttr.Format.isEmpty() )
1422 : {
1423 1 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
1424 1 : if ( pFormatter )
1425 : {
1426 : LanguageTag aLanguageTag( sNatNumAttrRfcLanguageTag, aNatNumAttr.Locale.Language,
1427 1 : sNatNumAttrScript, aNatNumAttr.Locale.Country);
1428 1 : aNatNumAttr.Locale = aLanguageTag.getLocale( false);
1429 :
1430 1 : sal_Int32 nNatNum = pFormatter->GetNatNum()->convertFromXmlAttributes( aNatNumAttr );
1431 1 : aFormatCode.append( "[NatNum" );
1432 1 : aFormatCode.append( nNatNum, 10 );
1433 :
1434 1 : LanguageType eLang = aLanguageTag.getLanguageType( false);
1435 1 : if ( eLang == LANGUAGE_DONTKNOW )
1436 0 : eLang = LANGUAGE_SYSTEM; //! error handling for unknown locales?
1437 1 : if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM )
1438 : {
1439 0 : aFormatCode.append( "][$-" );
1440 : // language code in upper hex:
1441 0 : aFormatCode.append(OUString::number(eLang, 16).toAsciiUpperCase());
1442 : }
1443 1 : aFormatCode.append( ']' );
1444 : }
1445 1946 : }
1446 1946 : }
1447 :
1448 901 : SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
1449 : sal_uInt16 nPrfx, const OUString& rLName,
1450 : const uno::Reference<xml::sax::XAttributeList>& xAttrList,
1451 : const sal_Int32 nTempKey,
1452 : SvXMLStylesContext& rStyles ) :
1453 : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, XML_STYLE_FAMILY_DATA_STYLE ),
1454 : pData( NULL ),
1455 : pStyles( &rStyles ),
1456 : aMyConditions(),
1457 : nType( 0 ),
1458 : nKey(nTempKey),
1459 : nFormatLang( LANGUAGE_SYSTEM ),
1460 : bAutoOrder( false ),
1461 : bFromSystem( false ),
1462 : bTruncate( true ),
1463 : bAutoDec( false ),
1464 : bAutoInt( false ),
1465 : bHasExtraText( false ),
1466 : bHasLongDoW( false ),
1467 : bHasEra( false ),
1468 : bHasDateTime( false ),
1469 : bRemoveAfterUse( false ),
1470 : eDateDOW( XML_DEA_NONE ),
1471 : eDateDay( XML_DEA_NONE ),
1472 : eDateMonth( XML_DEA_NONE ),
1473 : eDateYear( XML_DEA_NONE ),
1474 : eDateHours( XML_DEA_NONE ),
1475 : eDateMins( XML_DEA_NONE ),
1476 : eDateSecs( XML_DEA_NONE ),
1477 901 : bDateNoDefault( false )
1478 : {
1479 901 : SetAttribute(XML_NAMESPACE_STYLE, GetXMLToken(XML_NAME), rLName);
1480 901 : }
1481 :
1482 5692 : SvXMLNumFormatContext::~SvXMLNumFormatContext()
1483 : {
1484 5692 : }
1485 :
1486 6114 : SvXMLImportContext* SvXMLNumFormatContext::CreateChildContext(
1487 : sal_uInt16 nPrfx, const OUString& rLName,
1488 : const uno::Reference<xml::sax::XAttributeList>& xAttrList )
1489 : {
1490 6114 : SvXMLImportContext* pContext = NULL;
1491 :
1492 6114 : const SvXMLTokenMap& rTokenMap = pData->GetStyleElemTokenMap();
1493 6114 : sal_uInt16 nToken = rTokenMap.Get( nPrfx, rLName );
1494 6114 : switch (nToken)
1495 : {
1496 : case XML_TOK_STYLE_TEXT:
1497 : case XML_TOK_STYLE_FILL_CHARACTER:
1498 : case XML_TOK_STYLE_NUMBER:
1499 : case XML_TOK_STYLE_SCIENTIFIC_NUMBER:
1500 : case XML_TOK_STYLE_FRACTION:
1501 : case XML_TOK_STYLE_CURRENCY_SYMBOL:
1502 : case XML_TOK_STYLE_DAY:
1503 : case XML_TOK_STYLE_MONTH:
1504 : case XML_TOK_STYLE_YEAR:
1505 : case XML_TOK_STYLE_ERA:
1506 : case XML_TOK_STYLE_DAY_OF_WEEK:
1507 : case XML_TOK_STYLE_WEEK_OF_YEAR:
1508 : case XML_TOK_STYLE_QUARTER:
1509 : case XML_TOK_STYLE_HOURS:
1510 : case XML_TOK_STYLE_AM_PM:
1511 : case XML_TOK_STYLE_MINUTES:
1512 : case XML_TOK_STYLE_SECONDS:
1513 : case XML_TOK_STYLE_BOOLEAN:
1514 : case XML_TOK_STYLE_TEXT_CONTENT:
1515 5173 : pContext = new SvXMLNumFmtElementContext( GetImport(), nPrfx, rLName,
1516 5173 : *this, nToken, xAttrList );
1517 5173 : break;
1518 :
1519 : case XML_TOK_STYLE_PROPERTIES:
1520 305 : pContext = new SvXMLNumFmtPropContext( GetImport(), nPrfx, rLName,
1521 305 : *this, xAttrList );
1522 305 : break;
1523 : case XML_TOK_STYLE_MAP:
1524 : {
1525 : // SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
1526 : // so there's no need for an extra flag
1527 636 : pContext = new SvXMLNumFmtMapContext( GetImport(), nPrfx, rLName,
1528 636 : *this, xAttrList );
1529 : }
1530 636 : break;
1531 : }
1532 :
1533 6114 : if( !pContext )
1534 0 : pContext = new SvXMLImportContext( GetImport(), nPrfx, rLName );
1535 6114 : return pContext;
1536 : }
1537 :
1538 985 : sal_Int32 SvXMLNumFormatContext::GetKey()
1539 : {
1540 985 : if (nKey > -1)
1541 : {
1542 580 : if (bRemoveAfterUse)
1543 : {
1544 : // format is used -> don't remove
1545 0 : bRemoveAfterUse = false;
1546 0 : if (pData)
1547 0 : pData->SetUsed(nKey);
1548 :
1549 : // Add to import's list of keys now - CreateAndInsert didn't add
1550 : // the style if bRemoveAfterUse was set.
1551 0 : GetImport().AddNumberStyle( nKey, GetName() );
1552 : }
1553 580 : return nKey;
1554 : }
1555 : else
1556 : {
1557 : // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
1558 405 : bRemoveAfterUse = false;
1559 405 : CreateAndInsert(true);
1560 405 : return nKey;
1561 : }
1562 : }
1563 :
1564 636 : sal_Int32 SvXMLNumFormatContext::PrivateGetKey()
1565 : {
1566 : // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
1567 :
1568 636 : if (nKey > -1)
1569 622 : return nKey;
1570 : else
1571 : {
1572 14 : CreateAndInsert(true);
1573 14 : return nKey;
1574 : }
1575 : }
1576 :
1577 0 : sal_Int32 SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier >& xFormatsSupplier )
1578 : {
1579 0 : if (nKey <= -1)
1580 : {
1581 0 : SvNumberFormatter* pFormatter = NULL;
1582 : SvNumberFormatsSupplierObj* pObj =
1583 0 : SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier );
1584 0 : if (pObj)
1585 0 : pFormatter = pObj->GetNumberFormatter();
1586 :
1587 0 : if ( pFormatter )
1588 0 : return CreateAndInsert( pFormatter );
1589 : else
1590 0 : return -1;
1591 : }
1592 : else
1593 0 : return nKey;
1594 : }
1595 :
1596 1942 : void SvXMLNumFormatContext::CreateAndInsert(bool /*bOverwrite*/)
1597 : {
1598 1942 : if (!(nKey > -1))
1599 1942 : CreateAndInsert(pData->GetNumberFormatter());
1600 1942 : }
1601 :
1602 1942 : sal_Int32 SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
1603 : {
1604 1942 : if (!pFormatter)
1605 : {
1606 : OSL_FAIL("no number formatter");
1607 0 : return -1;
1608 : }
1609 :
1610 1942 : sal_uInt32 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
1611 :
1612 2578 : for (size_t i = 0; i < aMyConditions.size(); i++)
1613 : {
1614 : SvXMLNumFormatContext* pStyle = const_cast<SvXMLNumFormatContext*>( static_cast<const SvXMLNumFormatContext *>(pStyles->FindStyleChildContext(
1615 636 : XML_STYLE_FAMILY_DATA_STYLE, aMyConditions[i].sMapName, false)));
1616 636 : if (pStyle)
1617 : {
1618 636 : if ((pStyle->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag
1619 636 : AddCondition(i);
1620 : }
1621 : }
1622 :
1623 1942 : if ( aFormatCode.isEmpty() )
1624 : {
1625 : // insert empty format as empty string (with quotes)
1626 : // #93901# this check has to be done before inserting the conditions
1627 13 : aFormatCode.appendAscii("\"\""); // ""
1628 : }
1629 :
1630 1942 : aFormatCode.insert( 0, aConditions.makeStringAndClear() );
1631 1942 : OUString sFormat = aFormatCode.makeStringAndClear();
1632 :
1633 : // test special cases
1634 :
1635 1942 : if ( bAutoDec ) // automatic decimal places
1636 : {
1637 : // #99391# adjust only if the format contains no text elements, no conditions
1638 : // and no color definition (detected by the '[' at the start)
1639 :
1640 1091 : if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText &&
1641 813 : aMyConditions.empty() && sFormat.toChar() != '[' )
1642 269 : nIndex = pFormatter->GetStandardIndex( nFormatLang );
1643 : }
1644 1942 : if ( bAutoInt ) // automatic integer digits
1645 : {
1646 : //! only if two decimal places was set?
1647 :
1648 0 : if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText &&
1649 0 : aMyConditions.empty() && sFormat.toChar() != '[' )
1650 0 : nIndex = pFormatter->GetFormatIndex( NF_NUMBER_SYSTEM, nFormatLang );
1651 : }
1652 :
1653 : // boolean is always the builtin boolean format
1654 : // (no other boolean formats are implemented)
1655 1942 : if ( nType == XML_TOK_STYLES_BOOLEAN_STYLE )
1656 13 : nIndex = pFormatter->GetFormatIndex( NF_BOOLEAN, nFormatLang );
1657 :
1658 : // check for default date formats
1659 1942 : if ( nType == XML_TOK_STYLES_DATE_STYLE && bAutoOrder && !bDateNoDefault )
1660 : {
1661 : NfIndexTableOffset eFormat = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat(
1662 : eDateDOW, eDateDay, eDateMonth, eDateYear,
1663 102 : eDateHours, eDateMins, eDateSecs, bFromSystem );
1664 102 : if ( eFormat < NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS )
1665 : {
1666 : // #109651# if a date format has the automatic-order attribute and
1667 : // contains exactly the elements of one of the default date formats,
1668 : // use that default format, with the element order and separators
1669 : // from the current locale settings
1670 :
1671 68 : nIndex = pFormatter->GetFormatIndex( eFormat, nFormatLang );
1672 : }
1673 : }
1674 :
1675 1942 : if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND && !sFormat.isEmpty() )
1676 : {
1677 : // insert by format string
1678 :
1679 1592 : OUString aFormatStr( sFormat );
1680 1592 : nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang );
1681 1592 : if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
1682 : {
1683 1163 : sal_Int32 nErrPos = 0;
1684 1163 : short l_nType = 0;
1685 1163 : bool bOk = pFormatter->PutEntry( aFormatStr, nErrPos, l_nType, nIndex, nFormatLang );
1686 1163 : if ( !bOk && nErrPos == 0 && aFormatStr != sFormat )
1687 : {
1688 : // if the string was modified by PutEntry, look for an existing format
1689 : // with the modified string
1690 1 : nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang );
1691 1 : if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND )
1692 1 : bOk = true;
1693 : }
1694 1163 : if (!bOk)
1695 2 : nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
1696 1592 : }
1697 : }
1698 :
1699 : //! I18N doesn't provide SYSTEM or extended date information yet
1700 1942 : if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !bAutoOrder )
1701 : {
1702 : // use fixed-order formats instead of SYS... if bAutoOrder is false
1703 : // (only if the format strings are equal for the locale)
1704 :
1705 1838 : NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex );
1706 1838 : if ( eOffset == NF_DATE_SYS_DMMMYYYY )
1707 : {
1708 0 : sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMYYYY, nFormatLang );
1709 0 : const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
1710 0 : const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
1711 0 : if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
1712 0 : nIndex = nNewIndex;
1713 : }
1714 1838 : else if ( eOffset == NF_DATE_SYS_DMMMMYYYY )
1715 : {
1716 0 : sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY, nFormatLang );
1717 0 : const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
1718 0 : const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
1719 0 : if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
1720 0 : nIndex = nNewIndex;
1721 : }
1722 : }
1723 :
1724 1942 : if ((nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND) && !sFormatTitle.isEmpty())
1725 : {
1726 0 : SvNumberformat* pFormat = const_cast<SvNumberformat*>(pFormatter->GetEntry( nIndex ));
1727 0 : if (pFormat)
1728 : {
1729 0 : pFormat->SetComment(sFormatTitle);
1730 : }
1731 : }
1732 :
1733 1942 : if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
1734 : {
1735 : OSL_FAIL("invalid number format");
1736 2 : nIndex = pFormatter->GetStandardIndex( nFormatLang );
1737 : }
1738 :
1739 1942 : pData->AddKey( nIndex, GetName(), bRemoveAfterUse );
1740 1942 : nKey = nIndex;
1741 :
1742 : // Add to import's list of keys (shared between styles and content import)
1743 : // only if not volatile - formats are removed from NumberFormatter at the
1744 : // end of each import (in SvXMLNumFmtHelper dtor).
1745 : // If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there.
1746 :
1747 1942 : if (!bRemoveAfterUse)
1748 1306 : GetImport().AddNumberStyle( nKey, GetName() );
1749 :
1750 1942 : return nKey;
1751 : }
1752 :
1753 1525 : void SvXMLNumFormatContext::Finish( bool bOverwrite )
1754 : {
1755 1525 : SvXMLStyleContext::Finish( bOverwrite );
1756 1525 : }
1757 :
1758 1170 : const LocaleDataWrapper& SvXMLNumFormatContext::GetLocaleData() const
1759 : {
1760 1170 : return pData->GetLocaleData( nFormatLang );
1761 : }
1762 :
1763 408 : void SvXMLNumFormatContext::AddToCode( sal_Unicode c )
1764 : {
1765 408 : aFormatCode.append( c );
1766 408 : bHasExtraText = true;
1767 408 : }
1768 :
1769 2080 : void SvXMLNumFormatContext::AddToCode( const OUString& rString )
1770 : {
1771 2080 : aFormatCode.append( rString );
1772 2080 : bHasExtraText = true;
1773 2080 : }
1774 :
1775 1488 : void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
1776 : {
1777 1488 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
1778 1488 : if (!pFormatter)
1779 275 : return;
1780 :
1781 : // store special conditions
1782 1488 : bAutoDec = ( rInfo.nDecimals < 0 );
1783 1488 : bAutoInt = ( rInfo.nInteger < 0 );
1784 :
1785 1488 : sal_uInt16 nPrec = 0;
1786 1488 : sal_uInt16 nLeading = 0;
1787 1488 : if ( rInfo.nDecimals >= 0 ) // < 0 : Default
1788 1213 : nPrec = (sal_uInt16) rInfo.nDecimals;
1789 1488 : if ( rInfo.nInteger >= 0 ) // < 0 : Default
1790 1488 : nLeading = (sal_uInt16) rInfo.nInteger;
1791 :
1792 1488 : if ( bAutoDec )
1793 : {
1794 275 : if ( nType == XML_TOK_STYLES_CURRENCY_STYLE )
1795 : {
1796 : // for currency formats, "automatic decimals" is used for the automatic
1797 : // currency format with (fixed) decimals from the locale settings
1798 :
1799 0 : const LocaleDataWrapper& rLoc = pData->GetLocaleData( nFormatLang );
1800 0 : nPrec = rLoc.getCurrDigits();
1801 : }
1802 : else
1803 : {
1804 : // for other types, "automatic decimals" means dynamic determination of
1805 : // decimals, as achieved with the "general" keyword
1806 :
1807 275 : aFormatCode.append( pFormatter->GetStandardName( nFormatLang ) );
1808 275 : return;
1809 : }
1810 : }
1811 1213 : if ( bAutoInt )
1812 : {
1813 : //!...
1814 : }
1815 :
1816 1213 : sal_uInt16 nGenPrec = nPrec;
1817 1213 : if ( rInfo.nMinDecimalDigits >= 0 )
1818 1206 : nGenPrec = rInfo.nMinDecimalDigits;
1819 1213 : if ( rInfo.bDecReplace )
1820 2 : nGenPrec = 0; // generate format without decimals...
1821 :
1822 1213 : bool bGrouping = rInfo.bGrouping;
1823 1213 : sal_uInt16 nEmbeddedCount = rInfo.aEmbeddedElements.size();
1824 1213 : if ( nEmbeddedCount )
1825 0 : bGrouping = false; // grouping and embedded characters can't be used together
1826 :
1827 1213 : sal_uInt32 nStdIndex = pFormatter->GetStandardIndex( nFormatLang );
1828 : OUStringBuffer aNumStr = pFormatter->GenerateFormat( nStdIndex, nFormatLang,
1829 1213 : bGrouping, false, nGenPrec, nLeading );
1830 :
1831 1213 : if ( rInfo.nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 )
1832 : {
1833 : // #i43959# For scientific numbers, "#" in the integer part forces a digit,
1834 : // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
1835 :
1836 0 : aNumStr.stripStart('#');
1837 : }
1838 :
1839 1213 : if ( bGrouping && rInfo.nExpInterval > rInfo.nInteger )
1840 : {
1841 0 : sal_Int32 nIndex = 0;
1842 0 : sal_Int32 nDigits = rInfo.nInteger;
1843 0 : sal_Int32 nIntegerEnd = aNumStr.indexOf( pFormatter->GetNumDecimalSep() );
1844 0 : if ( nIntegerEnd < 0 )
1845 0 : nIntegerEnd = aNumStr.getLength();
1846 0 : while ( nIndex >= 0 && nIndex < nIntegerEnd )
1847 : {
1848 0 : if ( ( nIndex = aNumStr.indexOf( '#', nIndex ) ) >= 0 )
1849 : {
1850 0 : nDigits ++;
1851 0 : nIndex ++;
1852 : }
1853 : else
1854 0 : nIndex = -1;
1855 : }
1856 0 : while ( rInfo.nExpInterval > nDigits )
1857 : {
1858 0 : nDigits++;
1859 0 : aNumStr.insert( 0, '#' );
1860 : }
1861 : }
1862 :
1863 1213 : if ( nEmbeddedCount )
1864 : {
1865 : // insert embedded strings into number string
1866 : // only the integer part is supported
1867 : // nZeroPos is the string position where format position 0 is inserted
1868 :
1869 0 : sal_Int32 nZeroPos = aNumStr.indexOf( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() );
1870 0 : if ( nZeroPos < 0 )
1871 : {
1872 0 : nZeroPos = aNumStr.getLength();
1873 : }
1874 :
1875 : // aEmbeddedElements is sorted - last entry has the largest position (leftmost)
1876 0 : const SvXMLEmbeddedElement* pLastObj = &*rInfo.aEmbeddedElements.rbegin();
1877 0 : sal_Int32 nLastFormatPos = pLastObj->nFormatPos;
1878 0 : if ( nLastFormatPos >= nZeroPos )
1879 : {
1880 : // add '#' characters so all embedded texts are really embedded in digits
1881 : // (there always has to be a digit before the leftmost embedded text)
1882 :
1883 0 : sal_Int32 nAddCount = nLastFormatPos + 1 - nZeroPos;
1884 0 : for(sal_Int32 index = 0; index < nAddCount; ++index)
1885 : {
1886 0 : aNumStr.insert(0, '#');
1887 : }
1888 0 : nZeroPos = nZeroPos + nAddCount;
1889 : }
1890 :
1891 : // aEmbeddedElements is sorted with ascending positions - loop is from right to left
1892 0 : for (SvXMLEmbeddedElementArr::const_iterator it = rInfo.aEmbeddedElements.begin();
1893 0 : it != rInfo.aEmbeddedElements.end(); ++it)
1894 : {
1895 0 : const SvXMLEmbeddedElement* pObj = &*it;
1896 0 : sal_Int32 nFormatPos = pObj->nFormatPos;
1897 0 : sal_Int32 nInsertPos = nZeroPos - nFormatPos;
1898 0 : if ( nFormatPos >= 0 && nInsertPos >= 0 )
1899 : {
1900 : // #107805# always quote embedded strings - even space would otherwise
1901 : // be recognized as thousands separator in French.
1902 :
1903 0 : aNumStr.insert(nInsertPos, '"');
1904 0 : aNumStr.insert(nInsertPos, pObj->aText);
1905 0 : aNumStr.insert(nInsertPos, '"');
1906 : }
1907 : }
1908 : }
1909 :
1910 1213 : aFormatCode.append( aNumStr.makeStringAndClear() );
1911 :
1912 1213 : if ( ( rInfo.bDecReplace || rInfo.nMinDecimalDigits < rInfo.nDecimals ) && nPrec ) // add decimal replacement (dashes)
1913 : {
1914 : // add dashes for explicit decimal replacement, # for variable decimals
1915 3 : sal_Unicode cAdd = rInfo.bDecReplace ? '-' : '#';
1916 :
1917 3 : if ( rInfo.nMinDecimalDigits == 0 )
1918 1 : aFormatCode.append( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() );
1919 5 : for ( sal_uInt16 i=rInfo.nMinDecimalDigits; i<nPrec; i++)
1920 2 : aFormatCode.append( cAdd );
1921 : }
1922 :
1923 : // add extra thousands separators for display factor
1924 :
1925 1213 : if ( rInfo.fDisplayFactor != 1.0 && rInfo.fDisplayFactor > 0.0 )
1926 : {
1927 : // test for 1.0 is just for optimization - nSepCount would be 0
1928 :
1929 : // one separator for each factor of 1000
1930 16 : sal_Int32 nSepCount = (sal_Int32) ::rtl::math::round( log10(rInfo.fDisplayFactor) / 3.0 );
1931 16 : if ( nSepCount > 0 )
1932 : {
1933 16 : OUString aSep = pData->GetLocaleData( nFormatLang ).getNumThousandSep();
1934 32 : for ( sal_Int32 i=0; i<nSepCount; i++ )
1935 32 : aFormatCode.append( aSep );
1936 : }
1937 1213 : }
1938 : }
1939 :
1940 571 : void SvXMLNumFormatContext::AddCurrency( const OUString& rContent, LanguageType nLang )
1941 : {
1942 571 : bool bAutomatic = false;
1943 571 : OUString aSymbol = rContent;
1944 571 : if ( aSymbol.isEmpty())
1945 : {
1946 102 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
1947 102 : if ( pFormatter )
1948 : {
1949 102 : pFormatter->ChangeIntl( nFormatLang );
1950 204 : OUString sCurString, sDummy;
1951 102 : pFormatter->GetCompatibilityCurrency( sCurString, sDummy );
1952 102 : aSymbol = sCurString;
1953 :
1954 204 : bAutomatic = true;
1955 : }
1956 : }
1957 469 : else if ( nLang == LANGUAGE_SYSTEM && aSymbol == "CCC" )
1958 : {
1959 : // "CCC" is used for automatic long symbol
1960 0 : bAutomatic = true;
1961 : }
1962 :
1963 571 : if ( bAutomatic )
1964 : {
1965 : // remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
1966 : // otherwise the currency symbol isn't recognized (#94048#)
1967 :
1968 102 : sal_Int32 nLength = aFormatCode.getLength();
1969 102 : if ( nLength > 1 && aFormatCode[nLength - 1] == '"' )
1970 : {
1971 : // find start of quoted string
1972 : // When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
1973 : // they must be handled here, too.
1974 :
1975 0 : sal_Int32 nFirst = nLength - 2;
1976 0 : while ( nFirst >= 0 && aFormatCode[nFirst] != '"' )
1977 0 : --nFirst;
1978 0 : if ( nFirst >= 0 )
1979 : {
1980 : // remove both quotes from aFormatCode
1981 0 : OUString aOld = aFormatCode.makeStringAndClear();
1982 0 : if ( nFirst > 0 )
1983 0 : aFormatCode.append( aOld.copy( 0, nFirst ) );
1984 0 : if ( nLength > nFirst + 2 )
1985 0 : aFormatCode.append( aOld.copy( nFirst + 1, nLength - nFirst - 2 ) );
1986 : }
1987 : }
1988 : }
1989 :
1990 571 : if (!bAutomatic)
1991 469 : aFormatCode.appendAscii( "[$" ); // intro for "new" currency symbols
1992 :
1993 571 : aFormatCode.append( aSymbol );
1994 :
1995 571 : if (!bAutomatic)
1996 : {
1997 469 : if ( nLang != LANGUAGE_SYSTEM )
1998 : {
1999 : // '-' sign and language code in hex:
2000 453 : aFormatCode.append("-" + OUString::number(sal_Int32(nLang), 16).toAsciiUpperCase());
2001 : }
2002 :
2003 469 : aFormatCode.append( ']' ); // end of "new" currency symbol
2004 571 : }
2005 571 : }
2006 :
2007 878 : void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex )
2008 : {
2009 878 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
2010 878 : if (!pFormatter)
2011 878 : return;
2012 :
2013 878 : if ( nIndex == NF_KEY_G || nIndex == NF_KEY_GG || nIndex == NF_KEY_GGG )
2014 2 : bHasEra = true;
2015 :
2016 878 : if ( nIndex == NF_KEY_NNNN )
2017 : {
2018 5 : nIndex = NF_KEY_NNN;
2019 5 : bHasLongDoW = true; // to remove string constant with separator
2020 : }
2021 :
2022 878 : OUString sKeyword = pFormatter->GetKeyword( nFormatLang, nIndex );
2023 :
2024 878 : if ( nIndex == NF_KEY_H || nIndex == NF_KEY_HH ||
2025 770 : nIndex == NF_KEY_MI || nIndex == NF_KEY_MMI ||
2026 638 : nIndex == NF_KEY_S || nIndex == NF_KEY_SS )
2027 : {
2028 319 : if ( !bTruncate && !bHasDateTime )
2029 : {
2030 : // with truncate-on-overflow = false, add "[]" to first time part
2031 12 : aFormatCode.append("[" + sKeyword + "]");
2032 : }
2033 : else
2034 : {
2035 307 : aFormatCode.append( sKeyword );
2036 : }
2037 319 : bHasDateTime = true;
2038 : }
2039 : else
2040 : {
2041 559 : aFormatCode.append( sKeyword );
2042 : }
2043 : // collect the date elements that the format contains, to recognize default date formats
2044 878 : switch ( nIndex )
2045 : {
2046 7 : case NF_KEY_NN: eDateDOW = XML_DEA_SHORT; break;
2047 : case NF_KEY_NNN:
2048 5 : case NF_KEY_NNNN: eDateDOW = XML_DEA_LONG; break;
2049 97 : case NF_KEY_D: eDateDay = XML_DEA_SHORT; break;
2050 68 : case NF_KEY_DD: eDateDay = XML_DEA_LONG; break;
2051 52 : case NF_KEY_M: eDateMonth = XML_DEA_SHORT; break;
2052 60 : case NF_KEY_MM: eDateMonth = XML_DEA_LONG; break;
2053 60 : case NF_KEY_MMM: eDateMonth = XML_DEA_TEXTSHORT; break;
2054 14 : case NF_KEY_MMMM: eDateMonth = XML_DEA_TEXTLONG; break;
2055 59 : case NF_KEY_YY: eDateYear = XML_DEA_SHORT; break;
2056 97 : case NF_KEY_YYYY: eDateYear = XML_DEA_LONG; break;
2057 77 : case NF_KEY_H: eDateHours = XML_DEA_SHORT; break;
2058 31 : case NF_KEY_HH: eDateHours = XML_DEA_LONG; break;
2059 0 : case NF_KEY_MI: eDateMins = XML_DEA_SHORT; break;
2060 132 : case NF_KEY_MMI: eDateMins = XML_DEA_LONG; break;
2061 0 : case NF_KEY_S: eDateSecs = XML_DEA_SHORT; break;
2062 79 : case NF_KEY_SS: eDateSecs = XML_DEA_LONG; break;
2063 : case NF_KEY_AP:
2064 36 : case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself
2065 : default:
2066 4 : bDateNoDefault = true; // any other element -> no default format
2067 878 : }
2068 : }
2069 :
2070 5 : static bool lcl_IsAtEnd( OUStringBuffer& rBuffer, const OUString& rToken )
2071 : {
2072 5 : sal_Int32 nBufLen = rBuffer.getLength();
2073 5 : sal_Int32 nTokLen = rToken.getLength();
2074 :
2075 5 : if ( nTokLen > nBufLen )
2076 0 : return false;
2077 :
2078 5 : sal_Int32 nStartPos = nBufLen - nTokLen;
2079 20 : for ( sal_Int32 nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
2080 15 : if ( rToken[ nTokPos ] != rBuffer[nStartPos + nTokPos] )
2081 0 : return false;
2082 :
2083 5 : return true;
2084 : }
2085 :
2086 5 : bool SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld, sal_uInt16 nNew )
2087 : {
2088 : // replaces one keyword with another if it is found at the end of the code
2089 :
2090 5 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
2091 5 : if (!pFormatter)
2092 0 : return false;
2093 :
2094 5 : OUString sOldStr = pFormatter->GetKeyword( nFormatLang, nOld );
2095 5 : if ( lcl_IsAtEnd( aFormatCode, sOldStr ) )
2096 : {
2097 : // remove old keyword
2098 5 : aFormatCode.setLength( aFormatCode.getLength() - sOldStr.getLength() );
2099 :
2100 : // add new keyword
2101 5 : OUString sNewStr = pFormatter->GetKeyword( nFormatLang, nNew );
2102 5 : aFormatCode.append( sNewStr );
2103 :
2104 5 : return true; // changed
2105 : }
2106 0 : return false; // not found
2107 : }
2108 :
2109 636 : void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex )
2110 : {
2111 636 : OUString rApplyName = aMyConditions[nIndex].sMapName;
2112 1272 : OUString rCondition = aMyConditions[nIndex].sCondition;
2113 636 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
2114 636 : sal_uInt32 l_nKey = pData->GetKeyForName( rApplyName );
2115 1272 : OUString sValue("value()"); //! define constant
2116 636 : sal_Int32 nValLen = sValue.getLength();
2117 :
2118 2544 : if ( pFormatter && l_nKey != NUMBERFORMAT_ENTRY_NOT_FOUND &&
2119 2544 : rCondition.copy( 0, nValLen ) == sValue )
2120 : {
2121 : //! test for valid conditions
2122 : //! test for default conditions
2123 :
2124 636 : OUString sRealCond = rCondition.copy( nValLen, rCondition.getLength() - nValLen );
2125 636 : bool bDefaultCond = false;
2126 :
2127 : //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
2128 : //! allow blanks in conditions
2129 636 : if ( aConditions.isEmpty() && aMyConditions.size() == 1 && sRealCond == ">=0" )
2130 381 : bDefaultCond = true;
2131 :
2132 636 : if ( nType == XML_TOK_STYLES_TEXT_STYLE && nIndex == 2 )
2133 : {
2134 : // The third condition in a number format with a text part can only be
2135 : // "all other numbers", the condition string must be empty.
2136 67 : bDefaultCond = true;
2137 : }
2138 :
2139 636 : if (!bDefaultCond)
2140 : {
2141 : // Convert != to <>
2142 188 : sal_Int32 nPos = sRealCond.indexOf( "!=" );
2143 188 : if ( nPos >= 0 )
2144 : {
2145 2 : sRealCond = sRealCond.replaceAt( nPos, 2, "<>" );
2146 : }
2147 :
2148 188 : nPos = sRealCond.indexOf( '.' );
2149 188 : if ( nPos >= 0 )
2150 : {
2151 : // #i8026# #103991# localize decimal separator
2152 0 : const OUString& rDecSep = GetLocaleData().getNumDecimalSep();
2153 0 : if ( rDecSep.getLength() > 1 || rDecSep[0] != '.' )
2154 : {
2155 0 : sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep );
2156 : }
2157 : }
2158 188 : aConditions.append("[" + sRealCond + "]");
2159 : }
2160 :
2161 636 : const SvNumberformat* pFormat = pFormatter->GetEntry(l_nKey);
2162 636 : if ( pFormat )
2163 636 : aConditions.append( OUString( pFormat->GetFormatstring() ) );
2164 :
2165 636 : aConditions.append( ';' );
2166 636 : }
2167 636 : }
2168 :
2169 636 : void SvXMLNumFormatContext::AddCondition( const OUString& rCondition, const OUString& rApplyName )
2170 : {
2171 636 : MyCondition aCondition;
2172 636 : aCondition.sCondition = rCondition;
2173 636 : aCondition.sMapName = rApplyName;
2174 636 : aMyConditions.push_back(aCondition);
2175 636 : }
2176 :
2177 305 : void SvXMLNumFormatContext::AddColor( sal_uInt32 const nColor )
2178 : {
2179 305 : SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
2180 305 : if (!pFormatter)
2181 305 : return;
2182 :
2183 305 : OUStringBuffer aColName;
2184 1469 : for ( sal_uInt16 i=0; i<XML_NUMF_COLORCOUNT; i++ )
2185 1469 : if (nColor == aNumFmtStdColors[i])
2186 : {
2187 305 : aColName = OUString( pFormatter->GetKeyword( nFormatLang, sal::static_int_cast< sal_uInt16 >(NF_KEY_FIRSTCOLOR + i) ) );
2188 305 : break;
2189 : }
2190 :
2191 305 : if ( !aColName.isEmpty() )
2192 : {
2193 305 : aColName.insert( 0, '[' );
2194 305 : aColName.append( ']' );
2195 305 : aFormatCode.insert( 0, aColName.makeStringAndClear() );
2196 305 : }
2197 : }
2198 :
2199 523 : void SvXMLNumFormatContext::UpdateCalendar( const OUString& rNewCalendar )
2200 : {
2201 523 : if ( rNewCalendar != sCalendar )
2202 : {
2203 2 : sCalendar = rNewCalendar;
2204 2 : if ( !sCalendar.isEmpty() )
2205 : {
2206 2 : aFormatCode.appendAscii( "[~" ); // intro for calendar code
2207 2 : aFormatCode.append( sCalendar );
2208 2 : aFormatCode.append( ']' ); // end of "new" currency symbolcalendar code
2209 : }
2210 : }
2211 523 : }
2212 :
2213 16 : bool SvXMLNumFormatContext::IsSystemLanguage()
2214 : {
2215 16 : return nFormatLang == LANGUAGE_SYSTEM;
2216 : }
2217 :
2218 :
2219 : // SvXMLNumFmtHelper
2220 :
2221 :
2222 1067 : SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2223 : const uno::Reference<util::XNumberFormatsSupplier>& rSupp,
2224 : const uno::Reference<uno::XComponentContext>& rxContext )
2225 : {
2226 : DBG_ASSERT( rxContext.is(), "got no service manager" );
2227 :
2228 1067 : SvNumberFormatter* pFormatter = NULL;
2229 : SvNumberFormatsSupplierObj* pObj =
2230 1067 : SvNumberFormatsSupplierObj::getImplementation( rSupp );
2231 1067 : if (pObj)
2232 1067 : pFormatter = pObj->GetNumberFormatter();
2233 :
2234 1067 : pData = new SvXMLNumImpData( pFormatter, rxContext );
2235 1067 : }
2236 :
2237 222 : SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2238 : SvNumberFormatter* pNumberFormatter,
2239 : const uno::Reference<uno::XComponentContext>& rxContext )
2240 : {
2241 : DBG_ASSERT( rxContext.is(), "got no service manager" );
2242 :
2243 222 : pData = new SvXMLNumImpData( pNumberFormatter, rxContext );
2244 222 : }
2245 :
2246 1289 : SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
2247 : {
2248 : // remove temporary (volatile) formats from NumberFormatter
2249 1289 : pData->RemoveVolatileFormats();
2250 :
2251 1289 : delete pData;
2252 1289 : }
2253 :
2254 21802 : SvXMLStyleContext* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport& rImport,
2255 : sal_uInt16 nPrefix, const OUString& rLocalName,
2256 : const uno::Reference<xml::sax::XAttributeList>& xAttrList,
2257 : SvXMLStylesContext& rStyles )
2258 : {
2259 21802 : SvXMLStyleContext* pContext = NULL;
2260 :
2261 21802 : const SvXMLTokenMap& rTokenMap = pData->GetStylesElemTokenMap();
2262 21802 : sal_uInt16 nToken = rTokenMap.Get( nPrefix, rLocalName );
2263 21802 : switch (nToken)
2264 : {
2265 : case XML_TOK_STYLES_NUMBER_STYLE:
2266 : case XML_TOK_STYLES_CURRENCY_STYLE:
2267 : case XML_TOK_STYLES_PERCENTAGE_STYLE:
2268 : case XML_TOK_STYLES_DATE_STYLE:
2269 : case XML_TOK_STYLES_TIME_STYLE:
2270 : case XML_TOK_STYLES_BOOLEAN_STYLE:
2271 : case XML_TOK_STYLES_TEXT_STYLE:
2272 : pContext = new SvXMLNumFormatContext( rImport, nPrefix, rLocalName,
2273 1944 : pData, nToken, xAttrList, rStyles );
2274 1944 : break;
2275 : }
2276 :
2277 : // return NULL if not a data style, caller must handle other elements
2278 21802 : return pContext;
2279 : }
2280 :
2281 2967 : const SvXMLTokenMap& SvXMLNumFmtHelper::GetStylesElemTokenMap()
2282 : {
2283 2967 : return pData->GetStylesElemTokenMap();
2284 : }
2285 :
2286 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|