1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <comphelper/string.hxx>
22 #include <unotools/syslocale.hxx>
24 #include <svl/zforlist.hxx>
26 #include <svl/zformat.hxx>
27 #include <svl/numuno.hxx>
28 #include <rtl/math.hxx>
29 #include <i18nlangtag/languagetag.hxx>
30 #include <tools/color.hxx>
31 #include <tools/debug.hxx>
32 #include <rtl/ustrbuf.hxx>
34 #include <sax/tools/converter.hxx>
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>
46 #include <boost/ptr_container/ptr_vector.hpp>
47 #include <boost/ptr_container/ptr_set.hpp>
50 using namespace ::com::sun::star
;
51 using namespace ::xmloff::token
;
53 //-------------------------------------------------------------------------
55 struct SvXMLNumFmtEntry
59 sal_Bool bRemoveAfterUse
;
61 SvXMLNumFmtEntry( const OUString
& rN
, sal_uInt32 nK
, sal_Bool bR
) :
62 aName(rN
), nKey(nK
), bRemoveAfterUse(bR
) {}
65 typedef ::boost::ptr_vector
<SvXMLNumFmtEntry
> SvXMLNumFmtEntryArr
;
67 struct SvXMLEmbeddedElement
72 SvXMLEmbeddedElement( sal_Int32 nFP
, const OUString
& rT
) :
73 nFormatPos(nFP
), aText(rT
) {}
75 // comparison operators for PTRARR sorting - sorted by position
76 sal_Bool
operator ==( const SvXMLEmbeddedElement
& r
) const { return nFormatPos
== r
.nFormatPos
; }
77 sal_Bool
operator < ( const SvXMLEmbeddedElement
& r
) const { return nFormatPos
< r
.nFormatPos
; }
80 typedef boost::ptr_set
<SvXMLEmbeddedElement
> SvXMLEmbeddedElementArr
;
82 //-------------------------------------------------------------------------
86 SvNumberFormatter
* pFormatter
;
87 SvXMLTokenMap
* pStylesElemTokenMap
;
88 SvXMLTokenMap
* pStyleElemTokenMap
;
89 SvXMLTokenMap
* pStyleAttrTokenMap
;
90 SvXMLTokenMap
* pStyleElemAttrTokenMap
;
91 LocaleDataWrapper
* pLocaleData
;
92 SvXMLNumFmtEntryArr aNameEntries
;
94 uno::Reference
< uno::XComponentContext
> m_xContext
;
98 SvNumberFormatter
* pFmt
,
99 const uno::Reference
<uno::XComponentContext
>& rxContext
);
102 SvNumberFormatter
* GetNumberFormatter() const { return pFormatter
; }
103 const SvXMLTokenMap
& GetStylesElemTokenMap();
104 const SvXMLTokenMap
& GetStyleElemTokenMap();
105 const SvXMLTokenMap
& GetStyleAttrTokenMap();
106 const SvXMLTokenMap
& GetStyleElemAttrTokenMap();
107 const LocaleDataWrapper
& GetLocaleData( LanguageType nLang
);
108 sal_uInt32
GetKeyForName( const OUString
& rName
);
109 void AddKey( sal_uInt32 nKey
, const OUString
& rName
, sal_Bool bRemoveAfterUse
);
110 void SetUsed( sal_uInt32 nKey
);
111 void RemoveVolatileFormats();
115 struct SvXMLNumberInfo
119 sal_Int32 nExpDigits
;
120 sal_Int32 nNumerDigits
;
121 sal_Int32 nDenomDigits
;
122 sal_Int32 nFracDenominator
;
124 sal_Bool bDecReplace
;
125 sal_Bool bVarDecimals
;
126 double fDisplayFactor
;
127 SvXMLEmbeddedElementArr aEmbeddedElements
;
131 nDecimals
= nInteger
= nExpDigits
= nNumerDigits
= nDenomDigits
= nFracDenominator
= -1;
132 bGrouping
= bDecReplace
= bVarDecimals
= sal_False
;
133 fDisplayFactor
= 1.0;
137 class SvXMLNumFmtElementContext
: public SvXMLImportContext
139 SvXMLNumFormatContext
& rParent
;
141 OUStringBuffer aContent
;
142 SvXMLNumberInfo aNumInfo
;
143 LanguageType nElementLang
;
149 SvXMLNumFmtElementContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
150 const OUString
& rLName
,
151 SvXMLNumFormatContext
& rParentContext
, sal_uInt16 nNewType
,
152 const ::com::sun::star::uno::Reference
<
153 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
154 virtual ~SvXMLNumFmtElementContext();
156 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
157 const OUString
& rLocalName
,
158 const ::com::sun::star::uno::Reference
<
159 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
160 virtual void Characters( const OUString
& rChars
);
161 virtual void EndElement();
163 void AddEmbeddedElement( sal_Int32 nFormatPos
, const OUString
& rContent
);
167 class SvXMLNumFmtEmbeddedTextContext
: public SvXMLImportContext
169 SvXMLNumFmtElementContext
& rParent
;
170 OUStringBuffer aContent
;
171 sal_Int32 nTextPosition
;
174 SvXMLNumFmtEmbeddedTextContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
175 const OUString
& rLName
,
176 SvXMLNumFmtElementContext
& rParentContext
,
177 const ::com::sun::star::uno::Reference
<
178 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
179 virtual ~SvXMLNumFmtEmbeddedTextContext();
181 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
182 const OUString
& rLocalName
,
183 const ::com::sun::star::uno::Reference
<
184 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
185 virtual void Characters( const OUString
& rChars
);
186 virtual void EndElement();
190 class SvXMLNumFmtMapContext
: public SvXMLImportContext
192 SvXMLNumFormatContext
& rParent
;
197 SvXMLNumFmtMapContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
198 const OUString
& rLName
,
199 SvXMLNumFormatContext
& rParentContext
,
200 const ::com::sun::star::uno::Reference
<
201 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
202 virtual ~SvXMLNumFmtMapContext();
204 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
205 const OUString
& rLocalName
,
206 const ::com::sun::star::uno::Reference
<
207 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
208 virtual void Characters( const OUString
& rChars
);
209 virtual void EndElement();
213 class SvXMLNumFmtPropContext
: public SvXMLImportContext
215 SvXMLNumFormatContext
& rParent
;
220 SvXMLNumFmtPropContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
221 const OUString
& rLName
,
222 SvXMLNumFormatContext
& rParentContext
,
223 const ::com::sun::star::uno::Reference
<
224 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
225 virtual ~SvXMLNumFmtPropContext();
227 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
228 const OUString
& rLocalName
,
229 const ::com::sun::star::uno::Reference
<
230 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
231 virtual void Characters( const OUString
& rChars
);
232 virtual void EndElement();
236 //-------------------------------------------------------------------------
238 enum SvXMLStyleTokens
241 XML_TOK_STYLE_FILL_CHARACTER
,
242 XML_TOK_STYLE_NUMBER
,
243 XML_TOK_STYLE_SCIENTIFIC_NUMBER
,
244 XML_TOK_STYLE_FRACTION
,
245 XML_TOK_STYLE_CURRENCY_SYMBOL
,
250 XML_TOK_STYLE_DAY_OF_WEEK
,
251 XML_TOK_STYLE_WEEK_OF_YEAR
,
252 XML_TOK_STYLE_QUARTER
,
255 XML_TOK_STYLE_MINUTES
,
256 XML_TOK_STYLE_SECONDS
,
257 XML_TOK_STYLE_BOOLEAN
,
258 XML_TOK_STYLE_TEXT_CONTENT
,
259 XML_TOK_STYLE_PROPERTIES
,
263 enum SvXMLStyleAttrTokens
265 XML_TOK_STYLE_ATTR_NAME
,
266 XML_TOK_STYLE_ATTR_LANGUAGE
,
267 XML_TOK_STYLE_ATTR_COUNTRY
,
268 XML_TOK_STYLE_ATTR_TITLE
,
269 XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
,
270 XML_TOK_STYLE_ATTR_FORMAT_SOURCE
,
271 XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
,
272 XML_TOK_STYLE_ATTR_VOLATILE
,
273 XML_TOK_STYLE_ATTR_TRANSL_FORMAT
,
274 XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
,
275 XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
,
276 XML_TOK_STYLE_ATTR_TRANSL_STYLE
279 enum SvXMLStyleElemAttrTokens
281 XML_TOK_ELEM_ATTR_DECIMAL_PLACES
,
282 XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
,
283 XML_TOK_ELEM_ATTR_GROUPING
,
284 XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
,
285 XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
,
286 XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE
,
287 XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
,
288 XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
,
289 XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
,
290 XML_TOK_ELEM_ATTR_LANGUAGE
,
291 XML_TOK_ELEM_ATTR_COUNTRY
,
292 XML_TOK_ELEM_ATTR_STYLE
,
293 XML_TOK_ELEM_ATTR_TEXTUAL
,
294 XML_TOK_ELEM_ATTR_CALENDAR
297 //-------------------------------------------------------------------------
303 #define XML_NUMF_COLORCOUNT 10
305 static ColorData aNumFmtStdColors
[XML_NUMF_COLORCOUNT
] =
323 // maps for SvXMLUnitConverter::convertEnum
325 static SvXMLEnumMapEntry aStyleValueMap
[] =
327 { XML_SHORT
, sal_False
},
328 { XML_LONG
, sal_True
},
329 { XML_TOKEN_INVALID
, 0 }
332 static SvXMLEnumMapEntry aFormatSourceMap
[] =
334 { XML_FIXED
, sal_False
},
335 { XML_LANGUAGE
, sal_True
},
336 { XML_TOKEN_INVALID
, 0 }
339 //-------------------------------------------------------------------------
341 struct SvXMLDefaultDateFormat
343 NfIndexTableOffset eFormat
;
344 SvXMLDateElementAttributes eDOW
;
345 SvXMLDateElementAttributes eDay
;
346 SvXMLDateElementAttributes eMonth
;
347 SvXMLDateElementAttributes eYear
;
348 SvXMLDateElementAttributes eHours
;
349 SvXMLDateElementAttributes eMins
;
350 SvXMLDateElementAttributes eSecs
;
354 static SvXMLDefaultDateFormat aDefaultDateFormats
[] =
356 // format day-of-week day month year hours minutes seconds format-source
358 { 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
, sal_True
},
359 { 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
, sal_True
},
360 { 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
, sal_False
},
361 { 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
, sal_False
},
362 { 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
, sal_False
},
363 { 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
, sal_False
},
364 { 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
, sal_False
},
365 { 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
, sal_False
},
366 { 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
, sal_False
},
367 { 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
, sal_False
},
368 { 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
, sal_False
},
369 { 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
, sal_False
},
370 { 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
, sal_True
},
371 { 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
, sal_False
}
374 //-------------------------------------------------------------------------
380 SvXMLNumImpData::SvXMLNumImpData(
381 SvNumberFormatter
* pFmt
,
382 const uno::Reference
<uno::XComponentContext
>& rxContext
)
384 pStylesElemTokenMap(NULL
),
385 pStyleElemTokenMap(NULL
),
386 pStyleAttrTokenMap(NULL
),
387 pStyleElemAttrTokenMap(NULL
),
389 m_xContext(rxContext
)
391 DBG_ASSERT( rxContext
.is(), "got no service manager" );
394 SvXMLNumImpData::~SvXMLNumImpData()
396 delete pStylesElemTokenMap
;
397 delete pStyleElemTokenMap
;
398 delete pStyleAttrTokenMap
;
399 delete pStyleElemAttrTokenMap
;
403 sal_uInt32
SvXMLNumImpData::GetKeyForName( const OUString
& rName
)
405 sal_uInt16 nCount
= aNameEntries
.size();
406 for (sal_uInt16 i
=0; i
<nCount
; i
++)
408 const SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
409 if ( pObj
->aName
== rName
)
410 return pObj
->nKey
; // found
412 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
415 void SvXMLNumImpData::AddKey( sal_uInt32 nKey
, const OUString
& rName
, sal_Bool bRemoveAfterUse
)
417 if ( bRemoveAfterUse
)
419 // if there is already an entry for this key without the bRemoveAfterUse flag,
420 // clear the flag for this entry, too
422 sal_uInt16 nCount
= aNameEntries
.size();
423 for (sal_uInt16 i
=0; i
<nCount
; i
++)
425 SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
426 if ( pObj
->nKey
== nKey
&& !pObj
->bRemoveAfterUse
)
428 bRemoveAfterUse
= sal_False
; // clear flag for new entry
435 // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
439 SvXMLNumFmtEntry
* pObj
= new SvXMLNumFmtEntry( rName
, nKey
, bRemoveAfterUse
);
440 aNameEntries
.push_back( pObj
);
443 void SvXMLNumImpData::SetUsed( sal_uInt32 nKey
)
445 sal_uInt16 nCount
= aNameEntries
.size();
446 for (sal_uInt16 i
=0; i
<nCount
; i
++)
448 SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
449 if ( pObj
->nKey
== nKey
)
451 pObj
->bRemoveAfterUse
= sal_False
; // used -> don't remove
453 // continue searching - there may be several entries for the same key
454 // (with different names), the format must not be deleted if any one of
460 void SvXMLNumImpData::RemoveVolatileFormats()
462 // remove temporary (volatile) formats from NumberFormatter
463 // called at the end of each import (styles and content), so volatile formats
464 // from styles can't be used in content
469 sal_uInt16 nCount
= aNameEntries
.size();
470 for (sal_uInt16 i
=0; i
<nCount
; i
++)
472 const SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
473 if ( pObj
->bRemoveAfterUse
)
475 const SvNumberformat
* pFormat
= pFormatter
->GetEntry(pObj
->nKey
);
476 if (pFormat
&& (pFormat
->GetType() & NUMBERFORMAT_DEFINED
))
477 pFormatter
->DeleteEntry( pObj
->nKey
);
482 const SvXMLTokenMap
& SvXMLNumImpData::GetStylesElemTokenMap()
484 if( !pStylesElemTokenMap
)
486 static SvXMLTokenMapEntry aStylesElemMap
[] =
489 { XML_NAMESPACE_NUMBER
, XML_NUMBER_STYLE
, XML_TOK_STYLES_NUMBER_STYLE
},
490 { XML_NAMESPACE_NUMBER
, XML_CURRENCY_STYLE
, XML_TOK_STYLES_CURRENCY_STYLE
},
491 { XML_NAMESPACE_NUMBER
, XML_PERCENTAGE_STYLE
, XML_TOK_STYLES_PERCENTAGE_STYLE
},
492 { XML_NAMESPACE_NUMBER
, XML_DATE_STYLE
, XML_TOK_STYLES_DATE_STYLE
},
493 { XML_NAMESPACE_NUMBER
, XML_TIME_STYLE
, XML_TOK_STYLES_TIME_STYLE
},
494 { XML_NAMESPACE_NUMBER
, XML_BOOLEAN_STYLE
, XML_TOK_STYLES_BOOLEAN_STYLE
},
495 { XML_NAMESPACE_NUMBER
, XML_TEXT_STYLE
, XML_TOK_STYLES_TEXT_STYLE
},
499 pStylesElemTokenMap
= new SvXMLTokenMap( aStylesElemMap
);
501 return *pStylesElemTokenMap
;
504 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleElemTokenMap()
506 if( !pStyleElemTokenMap
)
508 static SvXMLTokenMapEntry aStyleElemMap
[] =
510 // elements in a style
511 { XML_NAMESPACE_NUMBER
, XML_TEXT
, XML_TOK_STYLE_TEXT
},
512 { XML_NAMESPACE_LO_EXT
, XML_FILL_CHARACTER
, XML_TOK_STYLE_FILL_CHARACTER
},
513 { XML_NAMESPACE_NUMBER
, XML_FILL_CHARACTER
, XML_TOK_STYLE_FILL_CHARACTER
},
514 { XML_NAMESPACE_NUMBER
, XML_NUMBER
, XML_TOK_STYLE_NUMBER
},
515 { XML_NAMESPACE_NUMBER
, XML_SCIENTIFIC_NUMBER
, XML_TOK_STYLE_SCIENTIFIC_NUMBER
},
516 { XML_NAMESPACE_NUMBER
, XML_FRACTION
, XML_TOK_STYLE_FRACTION
},
517 { XML_NAMESPACE_NUMBER
, XML_CURRENCY_SYMBOL
, XML_TOK_STYLE_CURRENCY_SYMBOL
},
518 { XML_NAMESPACE_NUMBER
, XML_DAY
, XML_TOK_STYLE_DAY
},
519 { XML_NAMESPACE_NUMBER
, XML_MONTH
, XML_TOK_STYLE_MONTH
},
520 { XML_NAMESPACE_NUMBER
, XML_YEAR
, XML_TOK_STYLE_YEAR
},
521 { XML_NAMESPACE_NUMBER
, XML_ERA
, XML_TOK_STYLE_ERA
},
522 { XML_NAMESPACE_NUMBER
, XML_DAY_OF_WEEK
, XML_TOK_STYLE_DAY_OF_WEEK
},
523 { XML_NAMESPACE_NUMBER
, XML_WEEK_OF_YEAR
, XML_TOK_STYLE_WEEK_OF_YEAR
},
524 { XML_NAMESPACE_NUMBER
, XML_QUARTER
, XML_TOK_STYLE_QUARTER
},
525 { XML_NAMESPACE_NUMBER
, XML_HOURS
, XML_TOK_STYLE_HOURS
},
526 { XML_NAMESPACE_NUMBER
, XML_AM_PM
, XML_TOK_STYLE_AM_PM
},
527 { XML_NAMESPACE_NUMBER
, XML_MINUTES
, XML_TOK_STYLE_MINUTES
},
528 { XML_NAMESPACE_NUMBER
, XML_SECONDS
, XML_TOK_STYLE_SECONDS
},
529 { XML_NAMESPACE_NUMBER
, XML_BOOLEAN
, XML_TOK_STYLE_BOOLEAN
},
530 { XML_NAMESPACE_NUMBER
, XML_TEXT_CONTENT
, XML_TOK_STYLE_TEXT_CONTENT
},
531 { XML_NAMESPACE_STYLE
, XML_TEXT_PROPERTIES
, XML_TOK_STYLE_PROPERTIES
},
532 { XML_NAMESPACE_STYLE
, XML_MAP
, XML_TOK_STYLE_MAP
},
536 pStyleElemTokenMap
= new SvXMLTokenMap( aStyleElemMap
);
538 return *pStyleElemTokenMap
;
541 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleAttrTokenMap()
543 if( !pStyleAttrTokenMap
)
545 static SvXMLTokenMapEntry aStyleAttrMap
[] =
547 // attributes for a style
548 { XML_NAMESPACE_STYLE
, XML_NAME
, XML_TOK_STYLE_ATTR_NAME
},
549 { XML_NAMESPACE_NUMBER
, XML_LANGUAGE
, XML_TOK_STYLE_ATTR_LANGUAGE
},
550 { XML_NAMESPACE_NUMBER
, XML_COUNTRY
, XML_TOK_STYLE_ATTR_COUNTRY
},
551 { XML_NAMESPACE_NUMBER
, XML_TITLE
, XML_TOK_STYLE_ATTR_TITLE
},
552 { XML_NAMESPACE_NUMBER
, XML_AUTOMATIC_ORDER
, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
},
553 { XML_NAMESPACE_NUMBER
, XML_FORMAT_SOURCE
, XML_TOK_STYLE_ATTR_FORMAT_SOURCE
},
554 { XML_NAMESPACE_NUMBER
, XML_TRUNCATE_ON_OVERFLOW
, XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
},
555 { XML_NAMESPACE_STYLE
, XML_VOLATILE
, XML_TOK_STYLE_ATTR_VOLATILE
},
556 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_FORMAT
, XML_TOK_STYLE_ATTR_TRANSL_FORMAT
},
557 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_LANGUAGE
, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
},
558 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_COUNTRY
, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
},
559 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_STYLE
, XML_TOK_STYLE_ATTR_TRANSL_STYLE
},
563 pStyleAttrTokenMap
= new SvXMLTokenMap( aStyleAttrMap
);
565 return *pStyleAttrTokenMap
;
568 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleElemAttrTokenMap()
570 if( !pStyleElemAttrTokenMap
)
572 static SvXMLTokenMapEntry aStyleElemAttrMap
[] =
574 // attributes for an element within a style
575 { XML_NAMESPACE_NUMBER
, XML_DECIMAL_PLACES
, XML_TOK_ELEM_ATTR_DECIMAL_PLACES
},
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_NUMBER
, XML_MIN_NUMERATOR_DIGITS
, XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
},
583 { XML_NAMESPACE_NUMBER
, XML_MIN_DENOMINATOR_DIGITS
, XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
},
584 { XML_NAMESPACE_NUMBER
, XML_LANGUAGE
, XML_TOK_ELEM_ATTR_LANGUAGE
},
585 { XML_NAMESPACE_NUMBER
, XML_COUNTRY
, XML_TOK_ELEM_ATTR_COUNTRY
},
586 { XML_NAMESPACE_NUMBER
, XML_STYLE
, XML_TOK_ELEM_ATTR_STYLE
},
587 { XML_NAMESPACE_NUMBER
, XML_TEXTUAL
, XML_TOK_ELEM_ATTR_TEXTUAL
},
588 { XML_NAMESPACE_NUMBER
, XML_CALENDAR
, XML_TOK_ELEM_ATTR_CALENDAR
},
592 pStyleElemAttrTokenMap
= new SvXMLTokenMap( aStyleElemAttrMap
);
594 return *pStyleElemAttrTokenMap
;
597 const LocaleDataWrapper
& SvXMLNumImpData::GetLocaleData( LanguageType nLang
)
600 pLocaleData
= new LocaleDataWrapper(
601 pFormatter
? pFormatter
->GetComponentContext() : m_xContext
,
602 LanguageTag( nLang
) );
604 pLocaleData
->setLanguageTag( LanguageTag( nLang
) );
608 //-------------------------------------------------------------------------
611 // SvXMLNumFmtMapContext
614 SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport
& rImport
,
615 sal_uInt16 nPrfx
, const OUString
& rLName
,
616 SvXMLNumFormatContext
& rParentContext
,
617 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
618 SvXMLImportContext( rImport
, nPrfx
, rLName
),
619 rParent( rParentContext
)
621 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
622 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
624 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
625 OUString sValue
= xAttrList
->getValueByIndex( i
);
627 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
628 if ( nPrefix
== XML_NAMESPACE_STYLE
)
630 if ( IsXMLToken( aLocalName
, XML_CONDITION
) )
632 else if ( IsXMLToken( aLocalName
, XML_APPLY_STYLE_NAME
) )
638 SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext()
642 SvXMLImportContext
* SvXMLNumFmtMapContext::CreateChildContext(
643 sal_uInt16 nPrfx
, const OUString
& rLName
,
644 const uno::Reference
<xml::sax::XAttributeList
>& )
646 // no elements supported - use default context
647 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
650 void SvXMLNumFmtMapContext::Characters( const OUString
& )
654 void SvXMLNumFmtMapContext::EndElement()
656 rParent
.AddCondition( sCondition
, sName
);
659 //-------------------------------------------------------------------------
662 // SvXMLNumFmtPropContext
665 SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport
& rImport
,
666 sal_uInt16 nPrfx
, const OUString
& rLName
,
667 SvXMLNumFormatContext
& rParentContext
,
668 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
669 SvXMLImportContext( rImport
, nPrfx
, rLName
),
670 rParent( rParentContext
),
673 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
674 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
676 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
677 OUString sValue
= xAttrList
->getValueByIndex( i
);
679 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
680 if ( nPrefix
== XML_NAMESPACE_FO
&& IsXMLToken( aLocalName
, XML_COLOR
) )
682 bColSet
= ::sax::Converter::convertColor( m_nColor
, sValue
);
687 SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext()
691 SvXMLImportContext
* SvXMLNumFmtPropContext::CreateChildContext(
692 sal_uInt16 nPrfx
, const OUString
& rLName
,
693 const uno::Reference
<xml::sax::XAttributeList
>& )
695 // no elements supported - use default context
696 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
699 void SvXMLNumFmtPropContext::Characters( const OUString
& )
703 void SvXMLNumFmtPropContext::EndElement()
706 rParent
.AddColor( m_nColor
);
709 //-------------------------------------------------------------------------
712 // SvXMLNumFmtEmbeddedTextContext
715 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
),
725 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
726 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
728 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
729 OUString sValue
= xAttrList
->getValueByIndex( i
);
731 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
732 if ( nPrefix
== XML_NAMESPACE_NUMBER
&& IsXMLToken( aLocalName
, XML_POSITION
) )
734 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
735 nTextPosition
= nAttrVal
;
740 SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext()
744 SvXMLImportContext
* SvXMLNumFmtEmbeddedTextContext::CreateChildContext(
745 sal_uInt16 nPrfx
, const OUString
& rLName
,
746 const uno::Reference
<xml::sax::XAttributeList
>& )
748 // no elements supported - use default context
749 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
752 void SvXMLNumFmtEmbeddedTextContext::Characters( const OUString
& rChars
)
754 aContent
.append( rChars
);
757 void SvXMLNumFmtEmbeddedTextContext::EndElement()
759 rParent
.AddEmbeddedElement( nTextPosition
, aContent
.makeStringAndClear() );
762 //-------------------------------------------------------------------------
764 static sal_Bool
lcl_ValidChar( sal_Unicode cChar
, const SvXMLNumFormatContext
& rParent
)
766 sal_uInt16 nFormatType
= rParent
.GetType();
768 // Treat space equal to non-breaking space separator.
769 const sal_Unicode cNBSP
= 0x00A0;
771 if ( ( nFormatType
== XML_TOK_STYLES_NUMBER_STYLE
||
772 nFormatType
== XML_TOK_STYLES_CURRENCY_STYLE
||
773 nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
) &&
774 (cChar
== (cTS
= rParent
.GetLocaleData().getNumThousandSep()[0]) ||
775 (cChar
== ' ' && cTS
== cNBSP
)) )
777 // #i22394# Extra occurrences of thousands separator must be quoted, so they
778 // aren't mis-interpreted as display-factor.
779 // This must be limited to the format types that can contain a number element,
780 // because the same character can be a date separator that should not be quoted
783 return sal_False
; // force quotes
786 // see ImpSvNumberformatScan::Next_Symbol
794 return sal_True
; // for all format types
796 // percent sign must be used without quotes for percentage styles only
797 if ( nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
&& cChar
== '%' )
800 // don't put quotes around single parentheses (often used for negative numbers)
801 if ( ( nFormatType
== XML_TOK_STYLES_NUMBER_STYLE
||
802 nFormatType
== XML_TOK_STYLES_CURRENCY_STYLE
||
803 nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
) &&
804 ( cChar
== '(' || cChar
== ')' ) )
810 static void lcl_EnquoteIfNecessary( OUStringBuffer
& rContent
, const SvXMLNumFormatContext
& rParent
)
812 sal_Bool bQuote
= sal_True
;
813 sal_Int32 nLength
= rContent
.getLength();
815 if ( ( nLength
== 1 &&
816 lcl_ValidChar( rContent
[0], rParent
) ) ||
818 lcl_ValidChar( rContent
[0], rParent
) &&
819 rContent
[1] == ' ' ) )
821 // don't quote single separator characters like space or percent,
822 // or separator characters followed by space (used in date formats)
825 else if ( rParent
.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE
&& nLength
> 1 )
827 // the percent character in percentage styles must be left out of quoting
828 // (one occurrence is enough even if there are several percent characters in the string)
830 OUString
aString( rContent
.getStr() );
831 sal_Int32 nPos
= aString
.indexOf( (sal_Unicode
) '%' );
834 if ( nPos
+ 1 < nLength
)
836 if ( nPos
+ 2 == nLength
&& lcl_ValidChar( rContent
[nPos
+ 1], rParent
) )
838 // single character that doesn't need quoting
842 // quote text behind percent character
843 rContent
.insert( nPos
+ 1, (sal_Unicode
) '"' );
844 rContent
.append( (sal_Unicode
) '"' );
849 if ( nPos
== 1 && lcl_ValidChar( rContent
[0], rParent
) )
851 // single character that doesn't need quoting
855 // quote text before percent character
856 rContent
.insert( nPos
, (sal_Unicode
) '"' );
857 rContent
.insert( 0, (sal_Unicode
) '"' );
862 // else: normal quoting (below)
867 // #i55469# quotes in the string itself have to be escaped
868 bool bEscape
= ( rContent
.indexOf( (sal_Unicode
) '"' ) >= 0 );
871 // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
872 // and a quote to resume quoting.
873 OUString
aInsert( "\"\\\"" );
876 while ( nPos
< rContent
.getLength() )
878 if ( rContent
[nPos
] == (sal_Unicode
) '"' )
880 rContent
.insert( nPos
, aInsert
);
881 nPos
+= aInsert
.getLength();
887 // quote string literals
888 rContent
.insert( 0, (sal_Unicode
) '"' );
889 rContent
.append( (sal_Unicode
) '"' );
891 // remove redundant double quotes at start or end
894 if ( rContent
.getLength() > 2 &&
895 rContent
[0] == (sal_Unicode
) '"' &&
896 rContent
[1] == (sal_Unicode
) '"' )
898 rContent
.remove(0, 2);
901 sal_Int32 nLen
= rContent
.getLength();
903 rContent
[nLen
- 1] == (sal_Unicode
) '"' &&
904 rContent
[nLen
- 2] == (sal_Unicode
) '"' )
906 rContent
.truncate(nLen
- 2);
913 // SvXMLNumFmtElementContext
916 const sal_Int32 MAX_SECOND_DIGITS
= 20; // fdo#58539 & gnome#627420: limit number of digits during import
918 SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport
& rImport
,
919 sal_uInt16 nPrfx
, const OUString
& rLName
,
920 SvXMLNumFormatContext
& rParentContext
, sal_uInt16 nNewType
,
921 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
922 SvXMLImportContext( rImport
, nPrfx
, rLName
),
923 rParent( rParentContext
),
925 nElementLang( LANGUAGE_SYSTEM
),
927 bTextual( sal_False
)
929 OUString sLanguage
, sCountry
;
931 bool bAttrBool(false);
932 sal_uInt16 nAttrEnum
;
935 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
936 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
938 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
939 OUString sValue
= xAttrList
->getValueByIndex( i
);
941 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
943 const SvXMLTokenMap
& rTokenMap
= rParent
.GetData()->GetStyleElemAttrTokenMap();
944 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, aLocalName
);
948 case XML_TOK_ELEM_ATTR_DECIMAL_PLACES
:
949 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
950 aNumInfo
.nDecimals
= std::min
<sal_Int32
>(nAttrVal
, MAX_SECOND_DIGITS
);
952 case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
:
953 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
954 aNumInfo
.nInteger
= nAttrVal
;
956 case XML_TOK_ELEM_ATTR_GROUPING
:
957 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
958 aNumInfo
.bGrouping
= bAttrBool
;
960 case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
:
961 if (::sax::Converter::convertDouble( fAttrDouble
, sValue
))
962 aNumInfo
.fDisplayFactor
= fAttrDouble
;
964 case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
:
965 if ( !sValue
.isEmpty() )
966 aNumInfo
.bDecReplace
= sal_True
; // only a default string is supported
968 aNumInfo
.bVarDecimals
= sal_True
; // empty replacement string: variable decimals
970 case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
:
971 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
972 aNumInfo
.nExpDigits
= nAttrVal
;
974 case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
:
975 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
976 aNumInfo
.nNumerDigits
= nAttrVal
;
978 case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
:
979 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
980 aNumInfo
.nDenomDigits
= nAttrVal
;
982 case XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE
:
983 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
984 aNumInfo
.nFracDenominator
= nAttrVal
;
986 case XML_TOK_ELEM_ATTR_LANGUAGE
:
989 case XML_TOK_ELEM_ATTR_COUNTRY
:
992 case XML_TOK_ELEM_ATTR_STYLE
:
993 if ( SvXMLUnitConverter::convertEnum( nAttrEnum
, sValue
, aStyleValueMap
) )
994 bLong
= (sal_Bool
) nAttrEnum
;
996 case XML_TOK_ELEM_ATTR_TEXTUAL
:
997 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
998 bTextual
= bAttrBool
;
1000 case XML_TOK_ELEM_ATTR_CALENDAR
:
1006 if ( !sLanguage
.isEmpty() || !sCountry
.isEmpty() )
1008 nElementLang
= LanguageTag( sLanguage
, sCountry
).getLanguageType( false);
1009 if ( nElementLang
== LANGUAGE_DONTKNOW
)
1010 nElementLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1014 SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext()
1018 SvXMLImportContext
* SvXMLNumFmtElementContext::CreateChildContext(
1019 sal_uInt16 nPrfx
, const OUString
& rLName
,
1020 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
)
1022 // only number:number supports number:embedded-text child element
1024 if ( nType
== XML_TOK_STYLE_NUMBER
&&
1025 nPrfx
== XML_NAMESPACE_NUMBER
&& IsXMLToken( rLName
, XML_EMBEDDED_TEXT
) )
1027 return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx
, rLName
, *this, xAttrList
);
1030 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
1033 void SvXMLNumFmtElementContext::Characters( const OUString
& rChars
)
1035 aContent
.append( rChars
);
1038 void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos
, const OUString
& rContent
)
1040 if ( !rContent
.isEmpty() )
1042 SvXMLEmbeddedElement
* pObj
= new SvXMLEmbeddedElement( nFormatPos
, rContent
);
1043 if ( !aNumInfo
.aEmbeddedElements
.insert( pObj
).second
)
1045 // there's already an element at this position - append text to existing element
1048 for (SvXMLEmbeddedElementArr::iterator it
= aNumInfo
.aEmbeddedElements
.begin();
1049 it
!= aNumInfo
.aEmbeddedElements
.end(); ++it
)
1052 if ( pObj
->nFormatPos
== nFormatPos
)
1054 pObj
->aText
+= rContent
;
1062 void SvXMLNumFmtElementContext::EndElement()
1064 sal_Bool bEffLong
= bLong
;
1067 case XML_TOK_STYLE_TEXT
:
1068 if ( rParent
.HasLongDoW() &&
1069 aContent
.toString().equals(rParent
.GetLocaleData().getLongDateDayOfWeekSep()) )
1071 // skip separator constant after long day of week
1072 // (NF_KEY_NNNN contains the separator)
1074 if ( rParent
.ReplaceNfKeyword( NF_KEY_NNN
, NF_KEY_NNNN
) )
1076 aContent
= OUStringBuffer();
1079 rParent
.SetHasLongDoW( sal_False
); // only once
1081 if ( aContent
.getLength() )
1083 lcl_EnquoteIfNecessary( aContent
, rParent
);
1084 rParent
.AddToCode( aContent
.makeStringAndClear() );
1088 case XML_TOK_STYLE_NUMBER
:
1089 rParent
.AddNumber( aNumInfo
);
1092 case XML_TOK_STYLE_CURRENCY_SYMBOL
:
1093 rParent
.AddCurrency( aContent
.makeStringAndClear(), nElementLang
);
1096 case XML_TOK_STYLE_TEXT_CONTENT
:
1097 rParent
.AddToCode( (sal_Unicode
)'@');
1099 case XML_TOK_STYLE_FILL_CHARACTER
:
1100 if ( aContent
.getLength() )
1102 rParent
.AddToCode( (sal_Unicode
)'*' );
1103 rParent
.AddToCode( aContent
[0] );
1106 case XML_TOK_STYLE_BOOLEAN
:
1107 // ignored - only default boolean format is supported
1110 case XML_TOK_STYLE_DAY
:
1111 rParent
.UpdateCalendar( sCalendar
);
1112 //! I18N doesn't provide SYSTEM or extended date information yet
1114 rParent
.AddNfKeyword(
1115 sal::static_int_cast
< sal_uInt16
>(
1116 bEffLong
? NF_KEY_DD
: NF_KEY_D
) );
1118 case XML_TOK_STYLE_MONTH
:
1119 rParent
.UpdateCalendar( sCalendar
);
1120 //! I18N doesn't provide SYSTEM or extended date information yet
1122 rParent
.AddNfKeyword(
1123 sal::static_int_cast
< sal_uInt16
>(
1125 ? ( bEffLong
? NF_KEY_MMMM
: NF_KEY_MMM
)
1126 : ( bEffLong
? NF_KEY_MM
: NF_KEY_M
) ) );
1128 case XML_TOK_STYLE_YEAR
:
1129 rParent
.UpdateCalendar( sCalendar
);
1130 //! I18N doesn't provide SYSTEM or extended date information yet
1131 // Y after G (era) is replaced by E
1132 if ( rParent
.HasEra() )
1133 rParent
.AddNfKeyword(
1134 sal::static_int_cast
< sal_uInt16
>(
1135 bEffLong
? NF_KEY_EEC
: NF_KEY_EC
) );
1137 rParent
.AddNfKeyword(
1138 sal::static_int_cast
< sal_uInt16
>(
1139 bEffLong
? NF_KEY_YYYY
: NF_KEY_YY
) );
1141 case XML_TOK_STYLE_ERA
:
1142 rParent
.UpdateCalendar( sCalendar
);
1143 //! I18N doesn't provide SYSTEM or extended date information yet
1144 rParent
.AddNfKeyword(
1145 sal::static_int_cast
< sal_uInt16
>(
1146 bEffLong
? NF_KEY_GGG
: NF_KEY_G
) );
1147 // HasEra flag is set
1149 case XML_TOK_STYLE_DAY_OF_WEEK
:
1150 rParent
.UpdateCalendar( sCalendar
);
1151 //! I18N doesn't provide SYSTEM or extended date information yet
1152 rParent
.AddNfKeyword(
1153 sal::static_int_cast
< sal_uInt16
>(
1154 bEffLong
? NF_KEY_NNNN
: NF_KEY_NN
) );
1156 case XML_TOK_STYLE_WEEK_OF_YEAR
:
1157 rParent
.UpdateCalendar( sCalendar
);
1158 rParent
.AddNfKeyword( NF_KEY_WW
);
1160 case XML_TOK_STYLE_QUARTER
:
1161 rParent
.UpdateCalendar( sCalendar
);
1162 rParent
.AddNfKeyword(
1163 sal::static_int_cast
< sal_uInt16
>(
1164 bEffLong
? NF_KEY_QQ
: NF_KEY_Q
) );
1166 case XML_TOK_STYLE_HOURS
:
1167 rParent
.AddNfKeyword(
1168 sal::static_int_cast
< sal_uInt16
>(
1169 bEffLong
? NF_KEY_HH
: NF_KEY_H
) );
1171 case XML_TOK_STYLE_AM_PM
:
1173 rParent
.AddNfKeyword( NF_KEY_AMPM
);
1175 case XML_TOK_STYLE_MINUTES
:
1176 rParent
.AddNfKeyword(
1177 sal::static_int_cast
< sal_uInt16
>(
1178 bEffLong
? NF_KEY_MMI
: NF_KEY_MI
) );
1180 case XML_TOK_STYLE_SECONDS
:
1181 rParent
.AddNfKeyword(
1182 sal::static_int_cast
< sal_uInt16
>(
1183 bEffLong
? NF_KEY_SS
: NF_KEY_S
) );
1184 if ( aNumInfo
.nDecimals
> 0 )
1186 // manually add the decimal places
1187 rParent
.AddToCode(rParent
.GetLocaleData().getNumDecimalSep());
1188 for (sal_Int32 i
=0; i
<aNumInfo
.nDecimals
; i
++)
1190 rParent
.AddToCode( (sal_Unicode
)'0');
1195 case XML_TOK_STYLE_FRACTION
:
1197 if ( aNumInfo
.nInteger
>= 0 )
1199 // add integer part only if min-integer-digits attribute is there
1200 aNumInfo
.nDecimals
= 0;
1201 rParent
.AddNumber( aNumInfo
); // number without decimals
1202 rParent
.AddToCode( (sal_Unicode
)' ' );
1205 //! build string and add at once
1208 for (i
=0; i
<aNumInfo
.nNumerDigits
; i
++)
1210 rParent
.AddToCode( (sal_Unicode
)'?' );
1212 rParent
.AddToCode( (sal_Unicode
)'/' );
1213 if ( aNumInfo
.nFracDenominator
> 0 )
1215 rParent
.AddToCode( OUString::valueOf( aNumInfo
.nFracDenominator
) );
1219 for (i
=0; i
<aNumInfo
.nDenomDigits
; i
++)
1221 rParent
.AddToCode( (sal_Unicode
)'?');
1227 case XML_TOK_STYLE_SCIENTIFIC_NUMBER
:
1229 rParent
.AddNumber( aNumInfo
); // simple number
1231 rParent
.AddToCode( OUString("E+") );
1232 for (sal_Int32 i
=0; i
<aNumInfo
.nExpDigits
; i
++)
1234 rParent
.AddToCode( (sal_Unicode
)'0' );
1240 OSL_FAIL("invalid element ID");
1244 //-------------------------------------------------------------------------
1246 sal_uInt16
SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW
,
1247 SvXMLDateElementAttributes eDay
, SvXMLDateElementAttributes eMonth
,
1248 SvXMLDateElementAttributes eYear
, SvXMLDateElementAttributes eHours
,
1249 SvXMLDateElementAttributes eMins
, SvXMLDateElementAttributes eSecs
,
1252 const sal_uInt16 nCount
= sizeof(aDefaultDateFormats
) / sizeof(SvXMLDefaultDateFormat
);
1253 for (sal_uInt16 nPos
=0; nPos
<nCount
; nPos
++)
1255 const SvXMLDefaultDateFormat
& rEntry
= aDefaultDateFormats
[nPos
];
1256 if ( bSystem
== rEntry
.bSystem
&&
1257 ( eDOW
== rEntry
.eDOW
|| ( rEntry
.eDOW
== XML_DEA_ANY
&& eDOW
!= XML_DEA_NONE
) ) &&
1258 ( eDay
== rEntry
.eDay
|| ( rEntry
.eDay
== XML_DEA_ANY
&& eDay
!= XML_DEA_NONE
) ) &&
1259 ( eMonth
== rEntry
.eMonth
|| ( rEntry
.eMonth
== XML_DEA_ANY
&& eMonth
!= XML_DEA_NONE
) ) &&
1260 ( eYear
== rEntry
.eYear
|| ( rEntry
.eYear
== XML_DEA_ANY
&& eYear
!= XML_DEA_NONE
) ) &&
1261 ( eHours
== rEntry
.eHours
|| ( rEntry
.eHours
== XML_DEA_ANY
&& eHours
!= XML_DEA_NONE
) ) &&
1262 ( eMins
== rEntry
.eMins
|| ( rEntry
.eMins
== XML_DEA_ANY
&& eMins
!= XML_DEA_NONE
) ) &&
1263 ( eSecs
== rEntry
.eSecs
|| ( rEntry
.eSecs
== XML_DEA_ANY
&& eSecs
!= XML_DEA_NONE
) ) )
1265 return sal::static_int_cast
< sal_uInt16
>(rEntry
.eFormat
);
1269 return NF_INDEX_TABLE_ENTRIES
; // invalid
1272 //-------------------------------------------------------------------------
1275 // SvXMLNumFormatContext
1278 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport
& rImport
,
1279 sal_uInt16 nPrfx
, const OUString
& rLName
,
1280 SvXMLNumImpData
* pNewData
, sal_uInt16 nNewType
,
1281 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
1282 SvXMLStylesContext
& rStyles
) :
1283 SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
),
1285 pStyles( &rStyles
),
1289 nFormatLang( LANGUAGE_SYSTEM
),
1290 bAutoOrder( sal_False
),
1291 bFromSystem( sal_False
),
1292 bTruncate( sal_True
),
1293 bAutoDec( sal_False
),
1294 bAutoInt( sal_False
),
1295 bHasExtraText( sal_False
),
1296 bHasLongDoW( sal_False
),
1297 bHasEra( sal_False
),
1298 bHasDateTime( sal_False
),
1299 bRemoveAfterUse( sal_False
),
1300 eDateDOW( XML_DEA_NONE
),
1301 eDateDay( XML_DEA_NONE
),
1302 eDateMonth( XML_DEA_NONE
),
1303 eDateYear( XML_DEA_NONE
),
1304 eDateHours( XML_DEA_NONE
),
1305 eDateMins( XML_DEA_NONE
),
1306 eDateSecs( XML_DEA_NONE
),
1307 bDateNoDefault( sal_False
)
1309 OUString sLanguage
, sCountry
;
1310 ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr
;
1311 bool bAttrBool(false);
1312 sal_uInt16 nAttrEnum
;
1314 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
1315 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
1317 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
1318 OUString sValue
= xAttrList
->getValueByIndex( i
);
1319 OUString aLocalName
;
1320 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
1322 const SvXMLTokenMap
& rTokenMap
= pData
->GetStyleAttrTokenMap();
1323 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, aLocalName
);
1326 case XML_TOK_STYLE_ATTR_NAME
:
1328 case XML_TOK_STYLE_ATTR_LANGUAGE
:
1331 case XML_TOK_STYLE_ATTR_COUNTRY
:
1334 case XML_TOK_STYLE_ATTR_TITLE
:
1335 sFormatTitle
= sValue
;
1337 case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
:
1338 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
1339 bAutoOrder
= bAttrBool
;
1341 case XML_TOK_STYLE_ATTR_FORMAT_SOURCE
:
1342 if ( SvXMLUnitConverter::convertEnum( nAttrEnum
, sValue
, aFormatSourceMap
) )
1343 bFromSystem
= (sal_Bool
) nAttrEnum
;
1345 case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
:
1346 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
1347 bTruncate
= bAttrBool
;
1349 case XML_TOK_STYLE_ATTR_VOLATILE
:
1350 // volatile formats can be removed after importing
1351 // if not used in other styles
1352 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
1353 bRemoveAfterUse
= bAttrBool
;
1355 case XML_TOK_STYLE_ATTR_TRANSL_FORMAT
:
1356 aNatNumAttr
.Format
= sValue
;
1358 case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
:
1359 aNatNumAttr
.Locale
.Language
= sValue
;
1361 case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
:
1362 aNatNumAttr
.Locale
.Country
= sValue
;
1364 case XML_TOK_STYLE_ATTR_TRANSL_STYLE
:
1365 aNatNumAttr
.Style
= sValue
;
1370 if ( !sLanguage
.isEmpty() || !sCountry
.isEmpty() )
1372 nFormatLang
= LanguageTag( sLanguage
, sCountry
).getLanguageType( false);
1373 if ( nFormatLang
== LANGUAGE_DONTKNOW
)
1374 nFormatLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1377 if ( !aNatNumAttr
.Format
.isEmpty() )
1379 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1382 sal_Int32 nNatNum
= pFormatter
->GetNatNum()->convertFromXmlAttributes( aNatNumAttr
);
1383 aFormatCode
.append( "[NatNum" );
1384 aFormatCode
.append( nNatNum
, 10 );
1386 LanguageType eLang
= LanguageTag( aNatNumAttr
.Locale
).getLanguageType( false);
1387 if ( eLang
== LANGUAGE_DONTKNOW
)
1388 eLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1389 if ( eLang
!= nFormatLang
&& eLang
!= LANGUAGE_SYSTEM
)
1391 aFormatCode
.append( "][$-" );
1392 // language code in upper hex:
1393 aFormatCode
.append(OUString::valueOf(sal_Int32(eLang
), 16).toAsciiUpperCase());
1395 aFormatCode
.append( sal_Unicode(']') );
1400 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport
& rImport
,
1401 sal_uInt16 nPrfx
, const OUString
& rLName
,
1402 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
1403 const sal_Int32 nTempKey
,
1404 SvXMLStylesContext
& rStyles
) :
1405 SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
, XML_STYLE_FAMILY_DATA_STYLE
),
1407 pStyles( &rStyles
),
1411 nFormatLang( LANGUAGE_SYSTEM
),
1412 bAutoOrder( sal_False
),
1413 bFromSystem( sal_False
),
1414 bTruncate( sal_True
),
1415 bAutoDec( sal_False
),
1416 bAutoInt( sal_False
),
1417 bHasExtraText( sal_False
),
1418 bHasLongDoW( sal_False
),
1419 bHasEra( sal_False
),
1420 bHasDateTime( sal_False
),
1421 bRemoveAfterUse( sal_False
),
1422 eDateDOW( XML_DEA_NONE
),
1423 eDateDay( XML_DEA_NONE
),
1424 eDateMonth( XML_DEA_NONE
),
1425 eDateYear( XML_DEA_NONE
),
1426 eDateHours( XML_DEA_NONE
),
1427 eDateMins( XML_DEA_NONE
),
1428 eDateSecs( XML_DEA_NONE
),
1429 bDateNoDefault( sal_False
)
1431 SetAttribute(XML_NAMESPACE_STYLE
, GetXMLToken(XML_NAME
), rLName
);
1434 SvXMLNumFormatContext::~SvXMLNumFormatContext()
1438 SvXMLImportContext
* SvXMLNumFormatContext::CreateChildContext(
1439 sal_uInt16 nPrfx
, const OUString
& rLName
,
1440 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
)
1442 SvXMLImportContext
* pContext
= NULL
;
1444 const SvXMLTokenMap
& rTokenMap
= pData
->GetStyleElemTokenMap();
1445 sal_uInt16 nToken
= rTokenMap
.Get( nPrfx
, rLName
);
1448 case XML_TOK_STYLE_TEXT
:
1449 case XML_TOK_STYLE_FILL_CHARACTER
:
1450 case XML_TOK_STYLE_NUMBER
:
1451 case XML_TOK_STYLE_SCIENTIFIC_NUMBER
:
1452 case XML_TOK_STYLE_FRACTION
:
1453 case XML_TOK_STYLE_CURRENCY_SYMBOL
:
1454 case XML_TOK_STYLE_DAY
:
1455 case XML_TOK_STYLE_MONTH
:
1456 case XML_TOK_STYLE_YEAR
:
1457 case XML_TOK_STYLE_ERA
:
1458 case XML_TOK_STYLE_DAY_OF_WEEK
:
1459 case XML_TOK_STYLE_WEEK_OF_YEAR
:
1460 case XML_TOK_STYLE_QUARTER
:
1461 case XML_TOK_STYLE_HOURS
:
1462 case XML_TOK_STYLE_AM_PM
:
1463 case XML_TOK_STYLE_MINUTES
:
1464 case XML_TOK_STYLE_SECONDS
:
1465 case XML_TOK_STYLE_BOOLEAN
:
1466 case XML_TOK_STYLE_TEXT_CONTENT
:
1467 pContext
= new SvXMLNumFmtElementContext( GetImport(), nPrfx
, rLName
,
1468 *this, nToken
, xAttrList
);
1471 case XML_TOK_STYLE_PROPERTIES
:
1472 pContext
= new SvXMLNumFmtPropContext( GetImport(), nPrfx
, rLName
,
1475 case XML_TOK_STYLE_MAP
:
1477 // SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
1478 // so there's no need for an extra flag
1479 pContext
= new SvXMLNumFmtMapContext( GetImport(), nPrfx
, rLName
,
1486 pContext
= new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
1490 sal_Int32
SvXMLNumFormatContext::GetKey()
1494 if (bRemoveAfterUse
)
1496 // format is used -> don't remove
1497 bRemoveAfterUse
= sal_False
;
1499 pData
->SetUsed(nKey
);
1501 // Add to import's list of keys now - CreateAndInsert didn't add
1502 // the style if bRemoveAfterUse was set.
1503 GetImport().AddNumberStyle( nKey
, GetName() );
1509 // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
1510 bRemoveAfterUse
= sal_False
;
1511 CreateAndInsert(sal_True
);
1516 sal_Int32
SvXMLNumFormatContext::PrivateGetKey()
1518 // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
1524 CreateAndInsert(sal_True
);
1529 sal_Int32
SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference
< com::sun::star::util::XNumberFormatsSupplier
>& xFormatsSupplier
)
1533 SvNumberFormatter
* pFormatter
= NULL
;
1534 SvNumberFormatsSupplierObj
* pObj
=
1535 SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier
);
1537 pFormatter
= pObj
->GetNumberFormatter();
1540 return CreateAndInsert( pFormatter
);
1548 void SvXMLNumFormatContext::CreateAndInsert(sal_Bool
/*bOverwrite*/)
1551 CreateAndInsert(pData
->GetNumberFormatter());
1554 sal_Int32
SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter
* pFormatter
)
1558 OSL_FAIL("no number formatter");
1562 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1564 for (sal_uInt32 i
= 0; i
< aMyConditions
.size(); i
++)
1566 SvXMLNumFormatContext
* pStyle
= (SvXMLNumFormatContext
*)pStyles
->FindStyleChildContext(
1567 XML_STYLE_FAMILY_DATA_STYLE
, aMyConditions
[i
].sMapName
, sal_False
);
1570 if ((pStyle
->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag
1575 if ( !aFormatCode
.getLength() )
1577 // insert empty format as empty string (with quotes)
1578 // #93901# this check has to be done before inserting the conditions
1579 aFormatCode
.appendAscii("\"\""); // ""
1582 aFormatCode
.insert( 0, aConditions
.makeStringAndClear() );
1583 OUString sFormat
= aFormatCode
.makeStringAndClear();
1585 // test special cases
1587 if ( bAutoDec
) // automatic decimal places
1589 // #99391# adjust only if the format contains no text elements, no conditions
1590 // and no color definition (detected by the '[' at the start)
1592 if ( nType
== XML_TOK_STYLES_NUMBER_STYLE
&& !bHasExtraText
&&
1593 aMyConditions
.empty() && sFormat
.toChar() != (sal_Unicode
)'[' )
1594 nIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1596 if ( bAutoInt
) // automatic integer digits
1598 //! only if two decimal places was set?
1600 if ( nType
== XML_TOK_STYLES_NUMBER_STYLE
&& !bHasExtraText
&&
1601 aMyConditions
.empty() && sFormat
.toChar() != (sal_Unicode
)'[' )
1602 nIndex
= pFormatter
->GetFormatIndex( NF_NUMBER_SYSTEM
, nFormatLang
);
1605 // boolean is always the builtin boolean format
1606 // (no other boolean formats are implemented)
1607 if ( nType
== XML_TOK_STYLES_BOOLEAN_STYLE
)
1608 nIndex
= pFormatter
->GetFormatIndex( NF_BOOLEAN
, nFormatLang
);
1610 // check for default date formats
1611 if ( nType
== XML_TOK_STYLES_DATE_STYLE
&& bAutoOrder
&& !bDateNoDefault
)
1613 NfIndexTableOffset eFormat
= (NfIndexTableOffset
) SvXMLNumFmtDefaults::GetDefaultDateFormat(
1614 eDateDOW
, eDateDay
, eDateMonth
, eDateYear
,
1615 eDateHours
, eDateMins
, eDateSecs
, bFromSystem
);
1616 if ( eFormat
< NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS
)
1618 // #109651# if a date format has the automatic-order attribute and
1619 // contains exactly the elements of one of the default date formats,
1620 // use that default format, with the element order and separators
1621 // from the current locale settings
1623 nIndex
= pFormatter
->GetFormatIndex( eFormat
, nFormatLang
);
1627 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
&& !sFormat
.isEmpty() )
1629 // insert by format string
1631 OUString
aFormatStr( sFormat
);
1632 nIndex
= pFormatter
->GetEntryKey( aFormatStr
, nFormatLang
);
1633 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1635 sal_Int32 nErrPos
= 0;
1637 sal_Bool bOk
= pFormatter
->PutEntry( aFormatStr
, nErrPos
, l_nType
, nIndex
, nFormatLang
);
1638 if ( !bOk
&& nErrPos
== 0 && aFormatStr
!= sFormat
)
1640 // if the string was modified by PutEntry, look for an existing format
1641 // with the modified string
1642 nIndex
= pFormatter
->GetEntryKey( aFormatStr
, nFormatLang
);
1643 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1647 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1651 //! I18N doesn't provide SYSTEM or extended date information yet
1652 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&& !bAutoOrder
)
1654 // use fixed-order formats instead of SYS... if bAutoOrder is false
1655 // (only if the format strings are equal for the locale)
1657 NfIndexTableOffset eOffset
= pFormatter
->GetIndexTableOffset( nIndex
);
1658 if ( eOffset
== NF_DATE_SYS_DMMMYYYY
)
1660 sal_uInt32 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_DIN_DMMMYYYY
, nFormatLang
);
1661 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nIndex
);
1662 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewIndex
);
1663 if ( pOldEntry
&& pNewEntry
&& pOldEntry
->GetFormatstring() == pNewEntry
->GetFormatstring() )
1666 else if ( eOffset
== NF_DATE_SYS_DMMMMYYYY
)
1668 sal_uInt32 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY
, nFormatLang
);
1669 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nIndex
);
1670 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewIndex
);
1671 if ( pOldEntry
&& pNewEntry
&& pOldEntry
->GetFormatstring() == pNewEntry
->GetFormatstring() )
1676 if ((nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) && !sFormatTitle
.isEmpty())
1678 SvNumberformat
* pFormat
= const_cast<SvNumberformat
*>(pFormatter
->GetEntry( nIndex
));
1681 pFormat
->SetComment(sFormatTitle
);
1685 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1687 OSL_FAIL("invalid number format");
1688 nIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1691 pData
->AddKey( nIndex
, GetName(), bRemoveAfterUse
);
1694 // Add to import's list of keys (shared between styles and content import)
1695 // only if not volatile - formats are removed from NumberFormatter at the
1696 // end of each import (in SvXMLNumFmtHelper dtor).
1697 // If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there.
1699 if (!bRemoveAfterUse
)
1700 GetImport().AddNumberStyle( nKey
, GetName() );
1705 void SvXMLNumFormatContext::Finish( sal_Bool bOverwrite
)
1707 SvXMLStyleContext::Finish( bOverwrite
);
1710 const LocaleDataWrapper
& SvXMLNumFormatContext::GetLocaleData() const
1712 return pData
->GetLocaleData( nFormatLang
);
1715 void SvXMLNumFormatContext::AddToCode( sal_Unicode c
)
1717 aFormatCode
.append( c
);
1718 bHasExtraText
= sal_True
;
1721 void SvXMLNumFormatContext::AddToCode( const OUString
& rString
)
1723 aFormatCode
.append( rString
);
1724 bHasExtraText
= sal_True
;
1727 void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo
& rInfo
)
1729 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1733 // store special conditions
1734 bAutoDec
= ( rInfo
.nDecimals
< 0 );
1735 bAutoInt
= ( rInfo
.nInteger
< 0 );
1737 sal_uInt16 nPrec
= 0;
1738 sal_uInt16 nLeading
= 0;
1739 if ( rInfo
.nDecimals
>= 0 ) // < 0 : Default
1740 nPrec
= (sal_uInt16
) rInfo
.nDecimals
;
1741 if ( rInfo
.nInteger
>= 0 ) // < 0 : Default
1742 nLeading
= (sal_uInt16
) rInfo
.nInteger
;
1746 if ( nType
== XML_TOK_STYLES_CURRENCY_STYLE
)
1748 // for currency formats, "automatic decimals" is used for the automatic
1749 // currency format with (fixed) decimals from the locale settings
1751 const LocaleDataWrapper
& rLoc
= pData
->GetLocaleData( nFormatLang
);
1752 nPrec
= rLoc
.getCurrDigits();
1756 // for other types, "automatic decimals" means dynamic determination of
1757 // decimals, as achieved with the "general" keyword
1759 aFormatCode
.append( pFormatter
->GetStandardName( nFormatLang
) );
1768 sal_uInt16 nGenPrec
= nPrec
;
1769 if ( rInfo
.bDecReplace
|| rInfo
.bVarDecimals
)
1770 nGenPrec
= 0; // generate format without decimals...
1772 sal_Bool bGrouping
= rInfo
.bGrouping
;
1773 sal_uInt16 nEmbeddedCount
= rInfo
.aEmbeddedElements
.size();
1774 if ( nEmbeddedCount
)
1775 bGrouping
= sal_False
; // grouping and embedded characters can't be used together
1777 sal_uInt32 nStdIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1778 OUStringBuffer aNumStr
= pFormatter
->GenerateFormat( nStdIndex
, nFormatLang
,
1779 bGrouping
, sal_False
, nGenPrec
, nLeading
);
1781 if ( rInfo
.nExpDigits
>= 0 && nLeading
== 0 && !bGrouping
&& nEmbeddedCount
== 0 )
1783 // #i43959# For scientific numbers, "#" in the integer part forces a digit,
1784 // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
1786 aNumStr
.stripStart((sal_Unicode
)'#');
1789 if ( nEmbeddedCount
)
1791 // insert embedded strings into number string
1792 // only the integer part is supported
1793 // nZeroPos is the string position where format position 0 is inserted
1795 sal_Int32 nZeroPos
= aNumStr
.indexOf( pData
->GetLocaleData( nFormatLang
).getNumDecimalSep() );
1798 nZeroPos
= aNumStr
.getLength();
1801 // aEmbeddedElements is sorted - last entry has the largest position (leftmost)
1802 const SvXMLEmbeddedElement
* pLastObj
= &*rInfo
.aEmbeddedElements
.rbegin();
1803 sal_Int32 nLastFormatPos
= pLastObj
->nFormatPos
;
1804 if ( nLastFormatPos
>= nZeroPos
)
1806 // add '#' characters so all embedded texts are really embedded in digits
1807 // (there always has to be a digit before the leftmost embedded text)
1809 sal_Int32 nAddCount
= nLastFormatPos
+ 1 - nZeroPos
;
1810 for(sal_Int32 index
= 0; index
< nAddCount
; ++index
)
1812 aNumStr
.insert(0, (sal_Unicode
)'#');
1814 nZeroPos
= nZeroPos
+ nAddCount
;
1817 // aEmbeddedElements is sorted with ascending positions - loop is from right to left
1818 for (SvXMLEmbeddedElementArr::const_iterator it
= rInfo
.aEmbeddedElements
.begin();
1819 it
!= rInfo
.aEmbeddedElements
.end(); ++it
)
1821 const SvXMLEmbeddedElement
* pObj
= &*it
;
1822 sal_Int32 nFormatPos
= pObj
->nFormatPos
;
1823 sal_Int32 nInsertPos
= nZeroPos
- nFormatPos
;
1824 if ( nFormatPos
>= 0 && nInsertPos
>= 0 )
1826 // #107805# always quote embedded strings - even space would otherwise
1827 // be recognized as thousands separator in French.
1829 aNumStr
.insert(nInsertPos
, '"');
1830 aNumStr
.insert(nInsertPos
, pObj
->aText
);
1831 aNumStr
.insert(nInsertPos
, '"');
1836 aFormatCode
.append( aNumStr
.makeStringAndClear() );
1838 if ( ( rInfo
.bDecReplace
|| rInfo
.bVarDecimals
) && nPrec
) // add decimal replacement (dashes)
1840 // add dashes for explicit decimal replacement, # for variable decimals
1841 sal_Unicode cAdd
= rInfo
.bDecReplace
? '-' : '#';
1843 aFormatCode
.append( pData
->GetLocaleData( nFormatLang
).getNumDecimalSep() );
1844 for ( sal_uInt16 i
=0; i
<nPrec
; i
++)
1845 aFormatCode
.append( cAdd
);
1848 // add extra thousands separators for display factor
1850 if ( rInfo
.fDisplayFactor
!= 1.0 && rInfo
.fDisplayFactor
> 0.0 )
1852 // test for 1.0 is just for optimization - nSepCount would be 0
1854 // one separator for each factor of 1000
1855 sal_Int32 nSepCount
= (sal_Int32
) ::rtl::math::round( log10(rInfo
.fDisplayFactor
) / 3.0 );
1856 if ( nSepCount
> 0 )
1858 OUString aSep
= pData
->GetLocaleData( nFormatLang
).getNumThousandSep();
1859 for ( sal_Int32 i
=0; i
<nSepCount
; i
++ )
1860 aFormatCode
.append( aSep
);
1865 void SvXMLNumFormatContext::AddCurrency( const OUString
& rContent
, LanguageType nLang
)
1867 sal_Bool bAutomatic
= sal_False
;
1868 OUString aSymbol
= rContent
;
1869 if ( aSymbol
.isEmpty())
1871 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1874 pFormatter
->ChangeIntl( nFormatLang
);
1875 OUString sCurString
, sDummy
;
1876 pFormatter
->GetCompatibilityCurrency( sCurString
, sDummy
);
1877 aSymbol
= sCurString
;
1879 bAutomatic
= sal_True
;
1882 else if ( nLang
== LANGUAGE_SYSTEM
&& aSymbol
.compareToAscii("CCC") == 0 )
1884 // "CCC" is used for automatic long symbol
1885 bAutomatic
= sal_True
;
1890 // remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
1891 // otherwise the currency symbol isn't recognized (#94048#)
1893 sal_Int32 nLength
= aFormatCode
.getLength();
1894 if ( nLength
> 1 && aFormatCode
[nLength
- 1] == '"' )
1896 // find start of quoted string
1897 // When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
1898 // they must be handled here, too.
1900 sal_Int32 nFirst
= nLength
- 2;
1901 while ( nFirst
>= 0 && aFormatCode
[nFirst
] != '"' )
1905 // remove both quotes from aFormatCode
1906 OUString aOld
= aFormatCode
.makeStringAndClear();
1908 aFormatCode
.append( aOld
.copy( 0, nFirst
) );
1909 if ( nLength
> nFirst
+ 2 )
1910 aFormatCode
.append( aOld
.copy( nFirst
+ 1, nLength
- nFirst
- 2 ) );
1916 aFormatCode
.appendAscii( "[$" ); // intro for "new" currency symbols
1918 aFormatCode
.append( aSymbol
);
1922 if ( nLang
!= LANGUAGE_SYSTEM
)
1924 // '-' sign and language code in hex:
1925 aFormatCode
.append( (sal_Unicode
) '-' );
1926 aFormatCode
.append(OUString::valueOf(sal_Int32(nLang
), 16).toAsciiUpperCase());
1929 aFormatCode
.append( (sal_Unicode
) ']' ); // end of "new" currency symbol
1933 void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex
)
1935 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1939 if ( nIndex
== NF_KEY_G
|| nIndex
== NF_KEY_GG
|| nIndex
== NF_KEY_GGG
)
1942 if ( nIndex
== NF_KEY_NNNN
)
1944 nIndex
= NF_KEY_NNN
;
1945 bHasLongDoW
= sal_True
; // to remove string constant with separator
1948 OUString sKeyword
= pFormatter
->GetKeyword( nFormatLang
, nIndex
);
1950 if ( nIndex
== NF_KEY_H
|| nIndex
== NF_KEY_HH
||
1951 nIndex
== NF_KEY_MI
|| nIndex
== NF_KEY_MMI
||
1952 nIndex
== NF_KEY_S
|| nIndex
== NF_KEY_SS
)
1954 if ( !bTruncate
&& !bHasDateTime
)
1956 // with truncate-on-overflow = false, add "[]" to first time part
1957 aFormatCode
.append( (sal_Unicode
)'[' );
1958 aFormatCode
.append( sKeyword
);
1959 aFormatCode
.append( (sal_Unicode
)']' );
1963 aFormatCode
.append( sKeyword
);
1965 bHasDateTime
= sal_True
;
1969 aFormatCode
.append( sKeyword
);
1971 // collect the date elements that the format contains, to recognize default date formats
1974 case NF_KEY_NN
: eDateDOW
= XML_DEA_SHORT
; break;
1976 case NF_KEY_NNNN
: eDateDOW
= XML_DEA_LONG
; break;
1977 case NF_KEY_D
: eDateDay
= XML_DEA_SHORT
; break;
1978 case NF_KEY_DD
: eDateDay
= XML_DEA_LONG
; break;
1979 case NF_KEY_M
: eDateMonth
= XML_DEA_SHORT
; break;
1980 case NF_KEY_MM
: eDateMonth
= XML_DEA_LONG
; break;
1981 case NF_KEY_MMM
: eDateMonth
= XML_DEA_TEXTSHORT
; break;
1982 case NF_KEY_MMMM
: eDateMonth
= XML_DEA_TEXTLONG
; break;
1983 case NF_KEY_YY
: eDateYear
= XML_DEA_SHORT
; break;
1984 case NF_KEY_YYYY
: eDateYear
= XML_DEA_LONG
; break;
1985 case NF_KEY_H
: eDateHours
= XML_DEA_SHORT
; break;
1986 case NF_KEY_HH
: eDateHours
= XML_DEA_LONG
; break;
1987 case NF_KEY_MI
: eDateMins
= XML_DEA_SHORT
; break;
1988 case NF_KEY_MMI
: eDateMins
= XML_DEA_LONG
; break;
1989 case NF_KEY_S
: eDateSecs
= XML_DEA_SHORT
; break;
1990 case NF_KEY_SS
: eDateSecs
= XML_DEA_LONG
; break;
1992 case NF_KEY_AMPM
: break; // AM/PM may or may not be in date/time formats -> ignore by itself
1994 bDateNoDefault
= sal_True
; // any other element -> no default format
1998 static sal_Bool
lcl_IsAtEnd( OUStringBuffer
& rBuffer
, const OUString
& rToken
)
2000 sal_Int32 nBufLen
= rBuffer
.getLength();
2001 sal_Int32 nTokLen
= rToken
.getLength();
2003 if ( nTokLen
> nBufLen
)
2006 sal_Int32 nStartPos
= nBufLen
- nTokLen
;
2007 for ( sal_Int32 nTokPos
= 0; nTokPos
< nTokLen
; nTokPos
++ )
2008 if ( rToken
[ nTokPos
] != rBuffer
[nStartPos
+ nTokPos
] )
2014 sal_Bool
SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld
, sal_uInt16 nNew
)
2016 // replaces one keyword with another if it is found at the end of the code
2018 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2022 OUString sOldStr
= pFormatter
->GetKeyword( nFormatLang
, nOld
);
2023 if ( lcl_IsAtEnd( aFormatCode
, sOldStr
) )
2025 // remove old keyword
2026 aFormatCode
.setLength( aFormatCode
.getLength() - sOldStr
.getLength() );
2029 OUString sNewStr
= pFormatter
->GetKeyword( nFormatLang
, nNew
);
2030 aFormatCode
.append( sNewStr
);
2032 return sal_True
; // changed
2034 return sal_False
; // not found
2037 void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex
)
2039 OUString rApplyName
= aMyConditions
[nIndex
].sMapName
;
2040 OUString rCondition
= aMyConditions
[nIndex
].sCondition
;
2041 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2042 sal_uInt32 l_nKey
= pData
->GetKeyForName( rApplyName
);
2043 OUString
sValue("value()"); //! define constant
2044 sal_Int32 nValLen
= sValue
.getLength();
2046 if ( pFormatter
&& l_nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&&
2047 rCondition
.copy( 0, nValLen
) == sValue
)
2049 //! test for valid conditions
2050 //! test for default conditions
2052 OUString sRealCond
= rCondition
.copy( nValLen
, rCondition
.getLength() - nValLen
);
2053 sal_Bool bDefaultCond
= sal_False
;
2055 //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
2056 //! allow blanks in conditions
2057 sal_Bool bFirstCond
= ( aConditions
.getLength() == 0 );
2058 if ( bFirstCond
&& aMyConditions
.size() == 1 && sRealCond
.compareToAscii( ">=0" ) == 0 )
2059 bDefaultCond
= sal_True
;
2061 if ( nType
== XML_TOK_STYLES_TEXT_STYLE
&& nIndex
== 2 )
2063 // The third condition in a number format with a text part can only be
2064 // "all other numbers", the condition string must be empty.
2065 bDefaultCond
= sal_True
;
2071 sal_Int32 nPos
= sRealCond
.indexOf( "!=" );
2074 sRealCond
= sRealCond
.replaceAt( nPos
, 2, "<>" );
2077 nPos
= sRealCond
.indexOf( '.' );
2080 // #i8026# #103991# localize decimal separator
2081 const OUString
& rDecSep
= GetLocaleData().getNumDecimalSep();
2082 if ( rDecSep
.getLength() > 1 || rDecSep
[0] != '.' )
2084 sRealCond
= sRealCond
.replaceAt( nPos
, 1, rDecSep
);
2087 aConditions
.append( (sal_Unicode
) '[' );
2088 aConditions
.append( sRealCond
);
2089 aConditions
.append( (sal_Unicode
) ']' );
2092 const SvNumberformat
* pFormat
= pFormatter
->GetEntry(l_nKey
);
2094 aConditions
.append( OUString( pFormat
->GetFormatstring() ) );
2096 aConditions
.append( (sal_Unicode
) ';' );
2100 void SvXMLNumFormatContext::AddCondition( const OUString
& rCondition
, const OUString
& rApplyName
)
2102 MyCondition aCondition
;
2103 aCondition
.sCondition
= rCondition
;
2104 aCondition
.sMapName
= rApplyName
;
2105 aMyConditions
.push_back(aCondition
);
2108 void SvXMLNumFormatContext::AddColor( sal_uInt32
const nColor
)
2110 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2114 OUStringBuffer aColName
;
2115 for ( sal_uInt16 i
=0; i
<XML_NUMF_COLORCOUNT
; i
++ )
2116 if (nColor
== aNumFmtStdColors
[i
])
2118 aColName
= OUString( pFormatter
->GetKeyword( nFormatLang
, sal::static_int_cast
< sal_uInt16
>(NF_KEY_FIRSTCOLOR
+ i
) ) );
2122 if ( aColName
.getLength() )
2124 aColName
.insert( 0, (sal_Unicode
) '[' );
2125 aColName
.append( (sal_Unicode
) ']' );
2126 aFormatCode
.insert( 0, aColName
.makeStringAndClear() );
2130 void SvXMLNumFormatContext::UpdateCalendar( const OUString
& rNewCalendar
)
2132 if ( rNewCalendar
!= sCalendar
)
2134 sCalendar
= rNewCalendar
;
2135 if ( !sCalendar
.isEmpty() )
2137 aFormatCode
.appendAscii( "[~" ); // intro for calendar code
2138 aFormatCode
.append( sCalendar
);
2139 aFormatCode
.append( (sal_Unicode
) ']' ); // end of "new" currency symbolcalendar code
2144 sal_Bool
SvXMLNumFormatContext::IsSystemLanguage()
2146 return nFormatLang
== LANGUAGE_SYSTEM
;
2149 //-------------------------------------------------------------------------
2152 // SvXMLNumFmtHelper
2155 SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2156 const uno::Reference
<util::XNumberFormatsSupplier
>& rSupp
,
2157 const uno::Reference
<uno::XComponentContext
>& rxContext
)
2159 DBG_ASSERT( rxContext
.is(), "got no service manager" );
2161 SvNumberFormatter
* pFormatter
= NULL
;
2162 SvNumberFormatsSupplierObj
* pObj
=
2163 SvNumberFormatsSupplierObj::getImplementation( rSupp
);
2165 pFormatter
= pObj
->GetNumberFormatter();
2167 pData
= new SvXMLNumImpData( pFormatter
, rxContext
);
2170 SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2171 SvNumberFormatter
* pNumberFormatter
,
2172 const uno::Reference
<uno::XComponentContext
>& rxContext
)
2174 DBG_ASSERT( rxContext
.is(), "got no service manager" );
2176 pData
= new SvXMLNumImpData( pNumberFormatter
, rxContext
);
2179 SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
2181 // remove temporary (volatile) formats from NumberFormatter
2182 pData
->RemoveVolatileFormats();
2187 SvXMLStyleContext
* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport
& rImport
,
2188 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
2189 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
2190 SvXMLStylesContext
& rStyles
)
2192 SvXMLStyleContext
* pContext
= NULL
;
2194 const SvXMLTokenMap
& rTokenMap
= pData
->GetStylesElemTokenMap();
2195 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, rLocalName
);
2198 case XML_TOK_STYLES_NUMBER_STYLE
:
2199 case XML_TOK_STYLES_CURRENCY_STYLE
:
2200 case XML_TOK_STYLES_PERCENTAGE_STYLE
:
2201 case XML_TOK_STYLES_DATE_STYLE
:
2202 case XML_TOK_STYLES_TIME_STYLE
:
2203 case XML_TOK_STYLES_BOOLEAN_STYLE
:
2204 case XML_TOK_STYLES_TEXT_STYLE
:
2205 pContext
= new SvXMLNumFormatContext( rImport
, nPrefix
, rLocalName
,
2206 pData
, nToken
, xAttrList
, rStyles
);
2210 // return NULL if not a data style, caller must handle other elements
2214 const SvXMLTokenMap
& SvXMLNumFmtHelper::GetStylesElemTokenMap()
2216 return pData
->GetStylesElemTokenMap();
2219 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */