1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <unotools/syslocale.hxx>
32 #include <svl/zforlist.hxx>
34 #include <svl/zformat.hxx>
35 #include <svl/numuno.hxx>
36 #include <rtl/math.hxx>
37 #include <i18npool/mslangid.hxx>
38 #include <tools/color.hxx>
39 #include <tools/debug.hxx>
40 #include <rtl/ustrbuf.hxx>
42 #include <sax/tools/converter.hxx>
44 #include <xmloff/xmlnumfi.hxx>
45 #include <xmloff/xmltkmap.hxx>
46 #include "xmloff/xmlnmspe.hxx"
47 #include <xmloff/xmlictxt.hxx>
48 #include <xmloff/xmlimp.hxx>
49 #include <xmloff/xmluconv.hxx>
50 #include <xmloff/nmspmap.hxx>
51 #include <xmloff/families.hxx>
52 #include <xmloff/xmltoken.hxx>
54 #include <boost/ptr_container/ptr_vector.hpp>
55 #include <boost/ptr_container/ptr_set.hpp>
57 using ::rtl::OUString
;
58 using ::rtl::OUStringBuffer
;
60 using namespace ::com::sun::star
;
61 using namespace ::xmloff::token
;
63 //-------------------------------------------------------------------------
65 struct SvXMLNumFmtEntry
69 sal_Bool bRemoveAfterUse
;
71 SvXMLNumFmtEntry( const rtl::OUString
& rN
, sal_uInt32 nK
, sal_Bool bR
) :
72 aName(rN
), nKey(nK
), bRemoveAfterUse(bR
) {}
75 typedef ::boost::ptr_vector
<SvXMLNumFmtEntry
> SvXMLNumFmtEntryArr
;
77 struct SvXMLEmbeddedElement
82 SvXMLEmbeddedElement( sal_Int32 nFP
, const rtl::OUString
& rT
) :
83 nFormatPos(nFP
), aText(rT
) {}
85 // comparison operators for PTRARR sorting - sorted by position
86 sal_Bool
operator ==( const SvXMLEmbeddedElement
& r
) const { return nFormatPos
== r
.nFormatPos
; }
87 sal_Bool
operator < ( const SvXMLEmbeddedElement
& r
) const { return nFormatPos
< r
.nFormatPos
; }
90 typedef boost::ptr_set
<SvXMLEmbeddedElement
> SvXMLEmbeddedElementArr
;
92 //-------------------------------------------------------------------------
96 SvNumberFormatter
* pFormatter
;
97 SvXMLTokenMap
* pStylesElemTokenMap
;
98 SvXMLTokenMap
* pStyleElemTokenMap
;
99 SvXMLTokenMap
* pStyleAttrTokenMap
;
100 SvXMLTokenMap
* pStyleElemAttrTokenMap
;
101 LocaleDataWrapper
* pLocaleData
;
102 SvXMLNumFmtEntryArr aNameEntries
;
104 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> mxServiceFactory
;
108 SvNumberFormatter
* pFmt
,
109 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
);
112 SvNumberFormatter
* GetNumberFormatter() const { return pFormatter
; }
113 const SvXMLTokenMap
& GetStylesElemTokenMap();
114 const SvXMLTokenMap
& GetStyleElemTokenMap();
115 const SvXMLTokenMap
& GetStyleAttrTokenMap();
116 const SvXMLTokenMap
& GetStyleElemAttrTokenMap();
117 const LocaleDataWrapper
& GetLocaleData( LanguageType nLang
);
118 sal_uInt32
GetKeyForName( const rtl::OUString
& rName
);
119 void AddKey( sal_uInt32 nKey
, const rtl::OUString
& rName
, sal_Bool bRemoveAfterUse
);
120 void SetUsed( sal_uInt32 nKey
);
121 void RemoveVolatileFormats();
125 struct SvXMLNumberInfo
129 sal_Int32 nExpDigits
;
130 sal_Int32 nNumerDigits
;
131 sal_Int32 nDenomDigits
;
132 sal_Int32 nFracDenominator
;
134 sal_Bool bDecReplace
;
135 sal_Bool bVarDecimals
;
136 double fDisplayFactor
;
137 SvXMLEmbeddedElementArr aEmbeddedElements
;
141 nDecimals
= nInteger
= nExpDigits
= nNumerDigits
= nDenomDigits
= nFracDenominator
= -1;
142 bGrouping
= bDecReplace
= bVarDecimals
= sal_False
;
143 fDisplayFactor
= 1.0;
147 class SvXMLNumFmtElementContext
: public SvXMLImportContext
149 SvXMLNumFormatContext
& rParent
;
151 rtl::OUStringBuffer aContent
;
152 SvXMLNumberInfo aNumInfo
;
153 LanguageType nElementLang
;
156 rtl::OUString sCalendar
;
159 SvXMLNumFmtElementContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
160 const rtl::OUString
& rLName
,
161 SvXMLNumFormatContext
& rParentContext
, sal_uInt16 nNewType
,
162 const ::com::sun::star::uno::Reference
<
163 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
164 virtual ~SvXMLNumFmtElementContext();
166 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
167 const rtl::OUString
& rLocalName
,
168 const ::com::sun::star::uno::Reference
<
169 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
170 virtual void Characters( const rtl::OUString
& rChars
);
171 virtual void EndElement();
173 void AddEmbeddedElement( sal_Int32 nFormatPos
, const rtl::OUString
& rContent
);
177 class SvXMLNumFmtEmbeddedTextContext
: public SvXMLImportContext
179 SvXMLNumFmtElementContext
& rParent
;
180 rtl::OUStringBuffer aContent
;
181 sal_Int32 nTextPosition
;
184 SvXMLNumFmtEmbeddedTextContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
185 const rtl::OUString
& rLName
,
186 SvXMLNumFmtElementContext
& rParentContext
,
187 const ::com::sun::star::uno::Reference
<
188 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
189 virtual ~SvXMLNumFmtEmbeddedTextContext();
191 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
192 const rtl::OUString
& rLocalName
,
193 const ::com::sun::star::uno::Reference
<
194 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
195 virtual void Characters( const rtl::OUString
& rChars
);
196 virtual void EndElement();
200 class SvXMLNumFmtMapContext
: public SvXMLImportContext
202 SvXMLNumFormatContext
& rParent
;
203 rtl::OUString sCondition
;
207 SvXMLNumFmtMapContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
208 const rtl::OUString
& rLName
,
209 SvXMLNumFormatContext
& rParentContext
,
210 const ::com::sun::star::uno::Reference
<
211 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
212 virtual ~SvXMLNumFmtMapContext();
214 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
215 const rtl::OUString
& rLocalName
,
216 const ::com::sun::star::uno::Reference
<
217 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
218 virtual void Characters( const rtl::OUString
& rChars
);
219 virtual void EndElement();
223 class SvXMLNumFmtPropContext
: public SvXMLImportContext
225 SvXMLNumFormatContext
& rParent
;
230 SvXMLNumFmtPropContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
231 const rtl::OUString
& rLName
,
232 SvXMLNumFormatContext
& rParentContext
,
233 const ::com::sun::star::uno::Reference
<
234 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
235 virtual ~SvXMLNumFmtPropContext();
237 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
238 const rtl::OUString
& rLocalName
,
239 const ::com::sun::star::uno::Reference
<
240 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
241 virtual void Characters( const rtl::OUString
& rChars
);
242 virtual void EndElement();
246 //-------------------------------------------------------------------------
248 enum SvXMLStyleTokens
251 XML_TOK_STYLE_NUMBER
,
252 XML_TOK_STYLE_SCIENTIFIC_NUMBER
,
253 XML_TOK_STYLE_FRACTION
,
254 XML_TOK_STYLE_CURRENCY_SYMBOL
,
259 XML_TOK_STYLE_DAY_OF_WEEK
,
260 XML_TOK_STYLE_WEEK_OF_YEAR
,
261 XML_TOK_STYLE_QUARTER
,
264 XML_TOK_STYLE_MINUTES
,
265 XML_TOK_STYLE_SECONDS
,
266 XML_TOK_STYLE_BOOLEAN
,
267 XML_TOK_STYLE_TEXT_CONTENT
,
268 XML_TOK_STYLE_PROPERTIES
,
272 enum SvXMLStyleAttrTokens
274 XML_TOK_STYLE_ATTR_NAME
,
275 XML_TOK_STYLE_ATTR_LANGUAGE
,
276 XML_TOK_STYLE_ATTR_COUNTRY
,
277 XML_TOK_STYLE_ATTR_TITLE
,
278 XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
,
279 XML_TOK_STYLE_ATTR_FORMAT_SOURCE
,
280 XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
,
281 XML_TOK_STYLE_ATTR_VOLATILE
,
282 XML_TOK_STYLE_ATTR_TRANSL_FORMAT
,
283 XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
,
284 XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
,
285 XML_TOK_STYLE_ATTR_TRANSL_STYLE
288 enum SvXMLStyleElemAttrTokens
290 XML_TOK_ELEM_ATTR_DECIMAL_PLACES
,
291 XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
,
292 XML_TOK_ELEM_ATTR_GROUPING
,
293 XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
,
294 XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
,
295 XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE
,
296 XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
,
297 XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
,
298 XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
,
299 XML_TOK_ELEM_ATTR_LANGUAGE
,
300 XML_TOK_ELEM_ATTR_COUNTRY
,
301 XML_TOK_ELEM_ATTR_STYLE
,
302 XML_TOK_ELEM_ATTR_TEXTUAL
,
303 XML_TOK_ELEM_ATTR_CALENDAR
306 //-------------------------------------------------------------------------
312 #define XML_NUMF_COLORCOUNT 10
314 static ColorData aNumFmtStdColors
[XML_NUMF_COLORCOUNT
] =
332 // maps for SvXMLUnitConverter::convertEnum
334 static SvXMLEnumMapEntry aStyleValueMap
[] =
336 { XML_SHORT
, sal_False
},
337 { XML_LONG
, sal_True
},
338 { XML_TOKEN_INVALID
, 0 }
341 static SvXMLEnumMapEntry aFormatSourceMap
[] =
343 { XML_FIXED
, sal_False
},
344 { XML_LANGUAGE
, sal_True
},
345 { XML_TOKEN_INVALID
, 0 }
348 //-------------------------------------------------------------------------
350 struct SvXMLDefaultDateFormat
352 NfIndexTableOffset eFormat
;
353 SvXMLDateElementAttributes eDOW
;
354 SvXMLDateElementAttributes eDay
;
355 SvXMLDateElementAttributes eMonth
;
356 SvXMLDateElementAttributes eYear
;
357 SvXMLDateElementAttributes eHours
;
358 SvXMLDateElementAttributes eMins
;
359 SvXMLDateElementAttributes eSecs
;
363 static SvXMLDefaultDateFormat aDefaultDateFormats
[] =
365 // format day-of-week day month year hours minutes seconds format-source
367 { 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
},
368 { 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
},
369 { 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
},
370 { 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
},
371 { 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
},
372 { 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
},
373 { 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
},
374 { 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
},
375 { 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
},
376 { 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
},
377 { 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
},
378 { 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
},
379 { 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
},
380 { 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
}
383 //-------------------------------------------------------------------------
389 SvXMLNumImpData::SvXMLNumImpData(
390 SvNumberFormatter
* pFmt
,
391 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
)
393 pStylesElemTokenMap(NULL
),
394 pStyleElemTokenMap(NULL
),
395 pStyleAttrTokenMap(NULL
),
396 pStyleElemAttrTokenMap(NULL
),
399 mxServiceFactory(xServiceFactory
)
401 DBG_ASSERT( mxServiceFactory
.is(), "got no service manager" );
404 SvXMLNumImpData::~SvXMLNumImpData()
406 delete pStylesElemTokenMap
;
407 delete pStyleElemTokenMap
;
408 delete pStyleAttrTokenMap
;
409 delete pStyleElemAttrTokenMap
;
413 sal_uInt32
SvXMLNumImpData::GetKeyForName( const rtl::OUString
& rName
)
415 sal_uInt16 nCount
= aNameEntries
.size();
416 for (sal_uInt16 i
=0; i
<nCount
; i
++)
418 const SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
419 if ( pObj
->aName
== rName
)
420 return pObj
->nKey
; // found
422 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
425 void SvXMLNumImpData::AddKey( sal_uInt32 nKey
, const rtl::OUString
& rName
, sal_Bool bRemoveAfterUse
)
427 if ( bRemoveAfterUse
)
429 // if there is already an entry for this key without the bRemoveAfterUse flag,
430 // clear the flag for this entry, too
432 sal_uInt16 nCount
= aNameEntries
.size();
433 for (sal_uInt16 i
=0; i
<nCount
; i
++)
435 SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
436 if ( pObj
->nKey
== nKey
&& !pObj
->bRemoveAfterUse
)
438 bRemoveAfterUse
= sal_False
; // clear flag for new entry
445 // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
449 SvXMLNumFmtEntry
* pObj
= new SvXMLNumFmtEntry( rName
, nKey
, bRemoveAfterUse
);
450 aNameEntries
.push_back( pObj
);
453 void SvXMLNumImpData::SetUsed( sal_uInt32 nKey
)
455 sal_uInt16 nCount
= aNameEntries
.size();
456 for (sal_uInt16 i
=0; i
<nCount
; i
++)
458 SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
459 if ( pObj
->nKey
== nKey
)
461 pObj
->bRemoveAfterUse
= sal_False
; // used -> don't remove
463 // continue searching - there may be several entries for the same key
464 // (with different names), the format must not be deleted if any one of
470 void SvXMLNumImpData::RemoveVolatileFormats()
472 // remove temporary (volatile) formats from NumberFormatter
473 // called at the end of each import (styles and content), so volatile formats
474 // from styles can't be used in content
479 sal_uInt16 nCount
= aNameEntries
.size();
480 for (sal_uInt16 i
=0; i
<nCount
; i
++)
482 const SvXMLNumFmtEntry
* pObj
= &aNameEntries
[i
];
483 if ( pObj
->bRemoveAfterUse
)
485 const SvNumberformat
* pFormat
= pFormatter
->GetEntry(pObj
->nKey
);
486 if (pFormat
&& (pFormat
->GetType() & NUMBERFORMAT_DEFINED
))
487 pFormatter
->DeleteEntry( pObj
->nKey
);
492 const SvXMLTokenMap
& SvXMLNumImpData::GetStylesElemTokenMap()
494 if( !pStylesElemTokenMap
)
496 static SvXMLTokenMapEntry aStylesElemMap
[] =
499 { XML_NAMESPACE_NUMBER
, XML_NUMBER_STYLE
, XML_TOK_STYLES_NUMBER_STYLE
},
500 { XML_NAMESPACE_NUMBER
, XML_CURRENCY_STYLE
, XML_TOK_STYLES_CURRENCY_STYLE
},
501 { XML_NAMESPACE_NUMBER
, XML_PERCENTAGE_STYLE
, XML_TOK_STYLES_PERCENTAGE_STYLE
},
502 { XML_NAMESPACE_NUMBER
, XML_DATE_STYLE
, XML_TOK_STYLES_DATE_STYLE
},
503 { XML_NAMESPACE_NUMBER
, XML_TIME_STYLE
, XML_TOK_STYLES_TIME_STYLE
},
504 { XML_NAMESPACE_NUMBER
, XML_BOOLEAN_STYLE
, XML_TOK_STYLES_BOOLEAN_STYLE
},
505 { XML_NAMESPACE_NUMBER
, XML_TEXT_STYLE
, XML_TOK_STYLES_TEXT_STYLE
},
509 pStylesElemTokenMap
= new SvXMLTokenMap( aStylesElemMap
);
511 return *pStylesElemTokenMap
;
514 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleElemTokenMap()
516 if( !pStyleElemTokenMap
)
518 static SvXMLTokenMapEntry aStyleElemMap
[] =
520 // elements in a style
521 { XML_NAMESPACE_NUMBER
, XML_TEXT
, XML_TOK_STYLE_TEXT
},
522 { XML_NAMESPACE_NUMBER
, XML_NUMBER
, XML_TOK_STYLE_NUMBER
},
523 { XML_NAMESPACE_NUMBER
, XML_SCIENTIFIC_NUMBER
, XML_TOK_STYLE_SCIENTIFIC_NUMBER
},
524 { XML_NAMESPACE_NUMBER
, XML_FRACTION
, XML_TOK_STYLE_FRACTION
},
525 { XML_NAMESPACE_NUMBER
, XML_CURRENCY_SYMBOL
, XML_TOK_STYLE_CURRENCY_SYMBOL
},
526 { XML_NAMESPACE_NUMBER
, XML_DAY
, XML_TOK_STYLE_DAY
},
527 { XML_NAMESPACE_NUMBER
, XML_MONTH
, XML_TOK_STYLE_MONTH
},
528 { XML_NAMESPACE_NUMBER
, XML_YEAR
, XML_TOK_STYLE_YEAR
},
529 { XML_NAMESPACE_NUMBER
, XML_ERA
, XML_TOK_STYLE_ERA
},
530 { XML_NAMESPACE_NUMBER
, XML_DAY_OF_WEEK
, XML_TOK_STYLE_DAY_OF_WEEK
},
531 { XML_NAMESPACE_NUMBER
, XML_WEEK_OF_YEAR
, XML_TOK_STYLE_WEEK_OF_YEAR
},
532 { XML_NAMESPACE_NUMBER
, XML_QUARTER
, XML_TOK_STYLE_QUARTER
},
533 { XML_NAMESPACE_NUMBER
, XML_HOURS
, XML_TOK_STYLE_HOURS
},
534 { XML_NAMESPACE_NUMBER
, XML_AM_PM
, XML_TOK_STYLE_AM_PM
},
535 { XML_NAMESPACE_NUMBER
, XML_MINUTES
, XML_TOK_STYLE_MINUTES
},
536 { XML_NAMESPACE_NUMBER
, XML_SECONDS
, XML_TOK_STYLE_SECONDS
},
537 { XML_NAMESPACE_NUMBER
, XML_BOOLEAN
, XML_TOK_STYLE_BOOLEAN
},
538 { XML_NAMESPACE_NUMBER
, XML_TEXT_CONTENT
, XML_TOK_STYLE_TEXT_CONTENT
},
539 { XML_NAMESPACE_STYLE
, XML_TEXT_PROPERTIES
, XML_TOK_STYLE_PROPERTIES
},
540 { XML_NAMESPACE_STYLE
, XML_MAP
, XML_TOK_STYLE_MAP
},
544 pStyleElemTokenMap
= new SvXMLTokenMap( aStyleElemMap
);
546 return *pStyleElemTokenMap
;
549 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleAttrTokenMap()
551 if( !pStyleAttrTokenMap
)
553 static SvXMLTokenMapEntry aStyleAttrMap
[] =
555 // attributes for a style
556 { XML_NAMESPACE_STYLE
, XML_NAME
, XML_TOK_STYLE_ATTR_NAME
},
557 { XML_NAMESPACE_NUMBER
, XML_LANGUAGE
, XML_TOK_STYLE_ATTR_LANGUAGE
},
558 { XML_NAMESPACE_NUMBER
, XML_COUNTRY
, XML_TOK_STYLE_ATTR_COUNTRY
},
559 { XML_NAMESPACE_NUMBER
, XML_TITLE
, XML_TOK_STYLE_ATTR_TITLE
},
560 { XML_NAMESPACE_NUMBER
, XML_AUTOMATIC_ORDER
, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
},
561 { XML_NAMESPACE_NUMBER
, XML_FORMAT_SOURCE
, XML_TOK_STYLE_ATTR_FORMAT_SOURCE
},
562 { XML_NAMESPACE_NUMBER
, XML_TRUNCATE_ON_OVERFLOW
, XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
},
563 { XML_NAMESPACE_STYLE
, XML_VOLATILE
, XML_TOK_STYLE_ATTR_VOLATILE
},
564 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_FORMAT
, XML_TOK_STYLE_ATTR_TRANSL_FORMAT
},
565 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_LANGUAGE
, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
},
566 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_COUNTRY
, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
},
567 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_STYLE
, XML_TOK_STYLE_ATTR_TRANSL_STYLE
},
571 pStyleAttrTokenMap
= new SvXMLTokenMap( aStyleAttrMap
);
573 return *pStyleAttrTokenMap
;
576 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleElemAttrTokenMap()
578 if( !pStyleElemAttrTokenMap
)
580 static SvXMLTokenMapEntry aStyleElemAttrMap
[] =
582 // attributes for an element within a style
583 { XML_NAMESPACE_NUMBER
, XML_DECIMAL_PLACES
, XML_TOK_ELEM_ATTR_DECIMAL_PLACES
},
584 { XML_NAMESPACE_NUMBER
, XML_MIN_INTEGER_DIGITS
, XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
},
585 { XML_NAMESPACE_NUMBER
, XML_GROUPING
, XML_TOK_ELEM_ATTR_GROUPING
},
586 { XML_NAMESPACE_NUMBER
, XML_DISPLAY_FACTOR
, XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
},
587 { XML_NAMESPACE_NUMBER
, XML_DECIMAL_REPLACEMENT
, XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
},
588 { XML_NAMESPACE_NUMBER
, XML_DENOMINATOR_VALUE
, XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE
},
589 { XML_NAMESPACE_NUMBER
, XML_MIN_EXPONENT_DIGITS
, XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
},
590 { XML_NAMESPACE_NUMBER
, XML_MIN_NUMERATOR_DIGITS
, XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
},
591 { XML_NAMESPACE_NUMBER
, XML_MIN_DENOMINATOR_DIGITS
, XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
},
592 { XML_NAMESPACE_NUMBER
, XML_LANGUAGE
, XML_TOK_ELEM_ATTR_LANGUAGE
},
593 { XML_NAMESPACE_NUMBER
, XML_COUNTRY
, XML_TOK_ELEM_ATTR_COUNTRY
},
594 { XML_NAMESPACE_NUMBER
, XML_STYLE
, XML_TOK_ELEM_ATTR_STYLE
},
595 { XML_NAMESPACE_NUMBER
, XML_TEXTUAL
, XML_TOK_ELEM_ATTR_TEXTUAL
},
596 { XML_NAMESPACE_NUMBER
, XML_CALENDAR
, XML_TOK_ELEM_ATTR_CALENDAR
},
600 pStyleElemAttrTokenMap
= new SvXMLTokenMap( aStyleElemAttrMap
);
602 return *pStyleElemAttrTokenMap
;
605 const LocaleDataWrapper
& SvXMLNumImpData::GetLocaleData( LanguageType nLang
)
608 pLocaleData
= new LocaleDataWrapper(
609 (pFormatter
? pFormatter
->GetServiceManager() :
611 MsLangId::convertLanguageToLocale( nLang
) );
613 pLocaleData
->setLocale( MsLangId::convertLanguageToLocale( nLang
) );
617 //-------------------------------------------------------------------------
620 // SvXMLNumFmtMapContext
623 SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport
& rImport
,
624 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
625 SvXMLNumFormatContext
& rParentContext
,
626 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
627 SvXMLImportContext( rImport
, nPrfx
, rLName
),
628 rParent( rParentContext
)
630 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
631 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
633 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
634 OUString sValue
= xAttrList
->getValueByIndex( i
);
636 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
637 if ( nPrefix
== XML_NAMESPACE_STYLE
)
639 if ( IsXMLToken( aLocalName
, XML_CONDITION
) )
641 else if ( IsXMLToken( aLocalName
, XML_APPLY_STYLE_NAME
) )
647 SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext()
651 SvXMLImportContext
* SvXMLNumFmtMapContext::CreateChildContext(
652 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
653 const uno::Reference
<xml::sax::XAttributeList
>& )
655 // no elements supported - use default context
656 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
659 void SvXMLNumFmtMapContext::Characters( const rtl::OUString
& )
663 void SvXMLNumFmtMapContext::EndElement()
665 rParent
.AddCondition( sCondition
, sName
);
668 //-------------------------------------------------------------------------
671 // SvXMLNumFmtPropContext
674 SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport
& rImport
,
675 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
676 SvXMLNumFormatContext
& rParentContext
,
677 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
678 SvXMLImportContext( rImport
, nPrfx
, rLName
),
679 rParent( rParentContext
),
682 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
683 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
685 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
686 OUString sValue
= xAttrList
->getValueByIndex( i
);
688 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
689 if ( nPrefix
== XML_NAMESPACE_FO
&& IsXMLToken( aLocalName
, XML_COLOR
) )
691 bColSet
= ::sax::Converter::convertColor( m_nColor
, sValue
);
696 SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext()
700 SvXMLImportContext
* SvXMLNumFmtPropContext::CreateChildContext(
701 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
702 const uno::Reference
<xml::sax::XAttributeList
>& )
704 // no elements supported - use default context
705 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
708 void SvXMLNumFmtPropContext::Characters( const rtl::OUString
& )
712 void SvXMLNumFmtPropContext::EndElement()
715 rParent
.AddColor( m_nColor
);
718 //-------------------------------------------------------------------------
721 // SvXMLNumFmtEmbeddedTextContext
724 SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport
& rImport
,
725 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
726 SvXMLNumFmtElementContext
& rParentContext
,
727 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
728 SvXMLImportContext( rImport
, nPrfx
, rLName
),
729 rParent( rParentContext
),
734 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
735 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
737 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
738 OUString sValue
= xAttrList
->getValueByIndex( i
);
740 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
741 if ( nPrefix
== XML_NAMESPACE_NUMBER
&& IsXMLToken( aLocalName
, XML_POSITION
) )
743 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
744 nTextPosition
= nAttrVal
;
749 SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext()
753 SvXMLImportContext
* SvXMLNumFmtEmbeddedTextContext::CreateChildContext(
754 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
755 const uno::Reference
<xml::sax::XAttributeList
>& )
757 // no elements supported - use default context
758 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
761 void SvXMLNumFmtEmbeddedTextContext::Characters( const rtl::OUString
& rChars
)
763 aContent
.append( rChars
);
766 void SvXMLNumFmtEmbeddedTextContext::EndElement()
768 rParent
.AddEmbeddedElement( nTextPosition
, aContent
.makeStringAndClear() );
771 //-------------------------------------------------------------------------
773 sal_Bool
lcl_ValidChar( sal_Unicode cChar
, const SvXMLNumFormatContext
& rParent
)
775 sal_uInt16 nFormatType
= rParent
.GetType();
777 // Treat space equal to non-breaking space separator.
778 const sal_Unicode cNBSP
= 0x00A0;
780 if ( ( nFormatType
== XML_TOK_STYLES_NUMBER_STYLE
||
781 nFormatType
== XML_TOK_STYLES_CURRENCY_STYLE
||
782 nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
) &&
783 (cChar
== (cTS
= rParent
.GetLocaleData().getNumThousandSep().GetChar(0)) ||
784 (cChar
== ' ' && cTS
== cNBSP
)) )
786 // #i22394# Extra occurrences of thousands separator must be quoted, so they
787 // aren't mis-interpreted as display-factor.
788 // This must be limited to the format types that can contain a number element,
789 // because the same character can be a date separator that should not be quoted
792 return sal_False
; // force quotes
795 // see ImpSvNumberformatScan::Next_Symbol
803 return sal_True
; // for all format types
805 // percent sign must be used without quotes for percentage styles only
806 if ( nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
&& cChar
== '%' )
809 // don't put quotes around single parentheses (often used for negative numbers)
810 if ( ( nFormatType
== XML_TOK_STYLES_NUMBER_STYLE
||
811 nFormatType
== XML_TOK_STYLES_CURRENCY_STYLE
||
812 nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
) &&
813 ( cChar
== '(' || cChar
== ')' ) )
819 void lcl_EnquoteIfNecessary( rtl::OUStringBuffer
& rContent
, const SvXMLNumFormatContext
& rParent
)
821 sal_Bool bQuote
= sal_True
;
822 sal_Int32 nLength
= rContent
.getLength();
824 if ( ( nLength
== 1 &&
825 lcl_ValidChar( rContent
[0], rParent
) ) ||
827 lcl_ValidChar( rContent
[0], rParent
) &&
828 rContent
[1] == ' ' ) )
830 // don't quote single separator characters like space or percent,
831 // or separator characters followed by space (used in date formats)
834 else if ( rParent
.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE
&& nLength
> 1 )
836 // the percent character in percentage styles must be left out of quoting
837 // (one occurrence is enough even if there are several percent characters in the string)
839 rtl::OUString
aString( rContent
.getStr() );
840 sal_Int32 nPos
= aString
.indexOf( (sal_Unicode
) '%' );
843 if ( nPos
+ 1 < nLength
)
845 if ( nPos
+ 2 == nLength
&& lcl_ValidChar( rContent
[nPos
+ 1], rParent
) )
847 // single character that doesn't need quoting
851 // quote text behind percent character
852 rContent
.insert( nPos
+ 1, (sal_Unicode
) '"' );
853 rContent
.append( (sal_Unicode
) '"' );
858 if ( nPos
== 1 && lcl_ValidChar( rContent
[0], rParent
) )
860 // single character that doesn't need quoting
864 // quote text before percent character
865 rContent
.insert( nPos
, (sal_Unicode
) '"' );
866 rContent
.insert( 0, (sal_Unicode
) '"' );
871 // else: normal quoting (below)
876 // #i55469# quotes in the string itself have to be escaped
877 rtl::OUString
aString( rContent
.getStr() );
878 bool bEscape
= ( aString
.indexOf( (sal_Unicode
) '"' ) >= 0 );
881 // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
882 // and a quote to resume quoting.
883 rtl::OUString
aInsert( "\"\\\"" );
886 while ( nPos
< rContent
.getLength() )
888 if ( rContent
[nPos
] == (sal_Unicode
) '"' )
890 rContent
.insert( nPos
, aInsert
);
891 nPos
+= aInsert
.getLength();
897 // quote string literals
898 rContent
.insert( 0, (sal_Unicode
) '"' );
899 rContent
.append( (sal_Unicode
) '"' );
901 // remove redundant double quotes at start or end
904 if ( rContent
.getLength() > 2 &&
905 rContent
[0] == (sal_Unicode
) '"' &&
906 rContent
[1] == (sal_Unicode
) '"' )
908 String
aTrimmed( rContent
.makeStringAndClear().copy(2) );
909 rContent
= rtl::OUStringBuffer( aTrimmed
);
912 sal_Int32 nLen
= rContent
.getLength();
914 rContent
[nLen
- 1] == (sal_Unicode
) '"' &&
915 rContent
[nLen
- 2] == (sal_Unicode
) '"' )
917 String
aTrimmed( rContent
.makeStringAndClear().copy( 0, nLen
- 2 ) );
918 rContent
= rtl::OUStringBuffer( aTrimmed
);
925 // SvXMLNumFmtElementContext
928 SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport
& rImport
,
929 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
930 SvXMLNumFormatContext
& rParentContext
, sal_uInt16 nNewType
,
931 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
932 SvXMLImportContext( rImport
, nPrfx
, rLName
),
933 rParent( rParentContext
),
935 nElementLang( LANGUAGE_SYSTEM
),
937 bTextual( sal_False
)
939 OUString sLanguage
, sCountry
;
941 bool bAttrBool(false);
942 sal_uInt16 nAttrEnum
;
945 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
946 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
948 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
949 OUString sValue
= xAttrList
->getValueByIndex( i
);
951 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
953 const SvXMLTokenMap
& rTokenMap
= rParent
.GetData()->GetStyleElemAttrTokenMap();
954 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, aLocalName
);
958 case XML_TOK_ELEM_ATTR_DECIMAL_PLACES
:
959 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
960 aNumInfo
.nDecimals
= nAttrVal
;
962 case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
:
963 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
964 aNumInfo
.nInteger
= nAttrVal
;
966 case XML_TOK_ELEM_ATTR_GROUPING
:
967 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
968 aNumInfo
.bGrouping
= bAttrBool
;
970 case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
:
971 if (::sax::Converter::convertDouble( fAttrDouble
, sValue
))
972 aNumInfo
.fDisplayFactor
= fAttrDouble
;
974 case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
:
975 if ( !sValue
.isEmpty() )
976 aNumInfo
.bDecReplace
= sal_True
; // only a default string is supported
978 aNumInfo
.bVarDecimals
= sal_True
; // empty replacement string: variable decimals
980 case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
:
981 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
982 aNumInfo
.nExpDigits
= nAttrVal
;
984 case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
:
985 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
986 aNumInfo
.nNumerDigits
= nAttrVal
;
988 case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
:
989 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
990 aNumInfo
.nDenomDigits
= nAttrVal
;
992 case XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE
:
993 if (::sax::Converter::convertNumber( nAttrVal
, sValue
, 0 ))
994 aNumInfo
.nFracDenominator
= nAttrVal
;
996 case XML_TOK_ELEM_ATTR_LANGUAGE
:
999 case XML_TOK_ELEM_ATTR_COUNTRY
:
1002 case XML_TOK_ELEM_ATTR_STYLE
:
1003 if ( SvXMLUnitConverter::convertEnum( nAttrEnum
, sValue
, aStyleValueMap
) )
1004 bLong
= (sal_Bool
) nAttrEnum
;
1006 case XML_TOK_ELEM_ATTR_TEXTUAL
:
1007 if (::sax::Converter::convertBool( bAttrBool
, sValue
))
1008 bTextual
= bAttrBool
;
1010 case XML_TOK_ELEM_ATTR_CALENDAR
:
1016 if ( !sLanguage
.isEmpty() || !sCountry
.isEmpty() )
1018 nElementLang
= MsLangId::convertIsoNamesToLanguage( sLanguage
, sCountry
);
1019 if ( nElementLang
== LANGUAGE_DONTKNOW
)
1020 nElementLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1024 SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext()
1028 SvXMLImportContext
* SvXMLNumFmtElementContext::CreateChildContext(
1029 sal_uInt16 nPrfx
, const rtl::OUString
& rLName
,
1030 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
)
1032 // only number:number supports number:embedded-text child element
1034 if ( nType
== XML_TOK_STYLE_NUMBER
&&
1035 nPrfx
== XML_NAMESPACE_NUMBER
&& IsXMLToken( rLName
, XML_EMBEDDED_TEXT
) )
1037 return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx
, rLName
, *this, xAttrList
);
1040 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
1043 void SvXMLNumFmtElementContext::Characters( const rtl::OUString
& rChars
)
1045 aContent
.append( rChars
);
1048 void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos
, const rtl::OUString
& rContent
)
1050 if ( !rContent
.isEmpty() )
1052 SvXMLEmbeddedElement
* pObj
= new SvXMLEmbeddedElement( nFormatPos
, rContent
);
1053 if ( !aNumInfo
.aEmbeddedElements
.insert( pObj
).second
)
1055 // there's already an element at this position - append text to existing element
1058 for (SvXMLEmbeddedElementArr::iterator it
= aNumInfo
.aEmbeddedElements
.begin();
1059 it
!= aNumInfo
.aEmbeddedElements
.end(); ++it
)
1062 if ( pObj
->nFormatPos
== nFormatPos
)
1064 pObj
->aText
+= rContent
;
1072 void SvXMLNumFmtElementContext::EndElement()
1074 sal_Bool bEffLong
= bLong
;
1077 case XML_TOK_STYLE_TEXT
:
1078 if ( rParent
.HasLongDoW() &&
1079 rParent
.GetLocaleData().getLongDateDayOfWeekSep() ==
1080 String( aContent
.getStr() ) )
1082 // skip separator constant after long day of week
1083 // (NF_KEY_NNNN contains the separator)
1085 if ( rParent
.ReplaceNfKeyword( NF_KEY_NNN
, NF_KEY_NNNN
) )
1087 aContent
= OUStringBuffer();
1090 rParent
.SetHasLongDoW( sal_False
); // only once
1092 if ( aContent
.getLength() )
1094 lcl_EnquoteIfNecessary( aContent
, rParent
);
1095 rParent
.AddToCode( aContent
.makeStringAndClear() );
1099 case XML_TOK_STYLE_NUMBER
:
1100 rParent
.AddNumber( aNumInfo
);
1103 case XML_TOK_STYLE_CURRENCY_SYMBOL
:
1104 rParent
.AddCurrency( aContent
.makeStringAndClear(), nElementLang
);
1107 case XML_TOK_STYLE_TEXT_CONTENT
:
1108 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'@') );
1110 case XML_TOK_STYLE_BOOLEAN
:
1111 // ignored - only default boolean format is supported
1114 case XML_TOK_STYLE_DAY
:
1115 rParent
.UpdateCalendar( sCalendar
);
1116 //! I18N doesn't provide SYSTEM or extended date information yet
1118 rParent
.AddNfKeyword(
1119 sal::static_int_cast
< sal_uInt16
>(
1120 bEffLong
? NF_KEY_DD
: NF_KEY_D
) );
1122 case XML_TOK_STYLE_MONTH
:
1123 rParent
.UpdateCalendar( sCalendar
);
1124 //! I18N doesn't provide SYSTEM or extended date information yet
1126 rParent
.AddNfKeyword(
1127 sal::static_int_cast
< sal_uInt16
>(
1129 ? ( bEffLong
? NF_KEY_MMMM
: NF_KEY_MMM
)
1130 : ( bEffLong
? NF_KEY_MM
: NF_KEY_M
) ) );
1132 case XML_TOK_STYLE_YEAR
:
1133 rParent
.UpdateCalendar( sCalendar
);
1134 //! I18N doesn't provide SYSTEM or extended date information yet
1135 // Y after G (era) is replaced by E
1136 if ( rParent
.HasEra() )
1137 rParent
.AddNfKeyword(
1138 sal::static_int_cast
< sal_uInt16
>(
1139 bEffLong
? NF_KEY_EEC
: NF_KEY_EC
) );
1141 rParent
.AddNfKeyword(
1142 sal::static_int_cast
< sal_uInt16
>(
1143 bEffLong
? NF_KEY_YYYY
: NF_KEY_YY
) );
1145 case XML_TOK_STYLE_ERA
:
1146 rParent
.UpdateCalendar( sCalendar
);
1147 //! I18N doesn't provide SYSTEM or extended date information yet
1148 rParent
.AddNfKeyword(
1149 sal::static_int_cast
< sal_uInt16
>(
1150 bEffLong
? NF_KEY_GGG
: NF_KEY_G
) );
1151 // HasEra flag is set
1153 case XML_TOK_STYLE_DAY_OF_WEEK
:
1154 rParent
.UpdateCalendar( sCalendar
);
1155 //! I18N doesn't provide SYSTEM or extended date information yet
1156 rParent
.AddNfKeyword(
1157 sal::static_int_cast
< sal_uInt16
>(
1158 bEffLong
? NF_KEY_NNNN
: NF_KEY_NN
) );
1160 case XML_TOK_STYLE_WEEK_OF_YEAR
:
1161 rParent
.UpdateCalendar( sCalendar
);
1162 rParent
.AddNfKeyword( NF_KEY_WW
);
1164 case XML_TOK_STYLE_QUARTER
:
1165 rParent
.UpdateCalendar( sCalendar
);
1166 rParent
.AddNfKeyword(
1167 sal::static_int_cast
< sal_uInt16
>(
1168 bEffLong
? NF_KEY_QQ
: NF_KEY_Q
) );
1170 case XML_TOK_STYLE_HOURS
:
1171 rParent
.AddNfKeyword(
1172 sal::static_int_cast
< sal_uInt16
>(
1173 bEffLong
? NF_KEY_HH
: NF_KEY_H
) );
1175 case XML_TOK_STYLE_AM_PM
:
1177 rParent
.AddNfKeyword( NF_KEY_AMPM
);
1179 case XML_TOK_STYLE_MINUTES
:
1180 rParent
.AddNfKeyword(
1181 sal::static_int_cast
< sal_uInt16
>(
1182 bEffLong
? NF_KEY_MMI
: NF_KEY_MI
) );
1184 case XML_TOK_STYLE_SECONDS
:
1185 rParent
.AddNfKeyword(
1186 sal::static_int_cast
< sal_uInt16
>(
1187 bEffLong
? NF_KEY_SS
: NF_KEY_S
) );
1188 if ( aNumInfo
.nDecimals
> 0 )
1190 // manually add the decimal places
1191 const String
& rSep
= rParent
.GetLocaleData().getNumDecimalSep();
1192 for ( xub_StrLen j
=0; j
<rSep
.Len(); j
++ )
1194 rParent
.AddToCode( OUString::valueOf( rSep
.GetChar(j
) ) );
1196 for (sal_Int32 i
=0; i
<aNumInfo
.nDecimals
; i
++)
1197 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'0') );
1201 case XML_TOK_STYLE_FRACTION
:
1203 if ( aNumInfo
.nInteger
>= 0 )
1205 // add integer part only if min-integer-digits attribute is there
1206 aNumInfo
.nDecimals
= 0;
1207 rParent
.AddNumber( aNumInfo
); // number without decimals
1208 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)' ') );
1211 //! build string and add at once
1214 for (i
=0; i
<aNumInfo
.nNumerDigits
; i
++)
1215 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'?') );
1216 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'/') );
1217 if ( aNumInfo
.nFracDenominator
> 0 )
1219 rParent
.AddToCode( OUString::valueOf( aNumInfo
.nFracDenominator
) );
1223 for (i
=0; i
<aNumInfo
.nDenomDigits
; i
++)
1224 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'?') );
1229 case XML_TOK_STYLE_SCIENTIFIC_NUMBER
:
1231 rParent
.AddNumber( aNumInfo
); // simple number
1233 rParent
.AddToCode( OUString("E+") );
1234 for (sal_Int32 i
=0; i
<aNumInfo
.nExpDigits
; i
++)
1235 rParent
.AddToCode( OUString::valueOf((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 rtl::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
= MsLangId::convertIsoNamesToLanguage( sLanguage
, sCountry
);
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
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "[NatNum" ) );
1384 aFormatCode
.append( nNatNum
, 10 );
1386 LanguageType eLang
= MsLangId::convertLocaleToLanguage( aNatNumAttr
.Locale
);
1387 if ( eLang
== LANGUAGE_DONTKNOW
)
1388 eLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1389 if ( eLang
!= nFormatLang
&& eLang
!= LANGUAGE_SYSTEM
)
1391 aFormatCode
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "][$-" ) );
1392 // language code in upper hex:
1393 aFormatCode
.append(rtl::OUString::valueOf(sal_Int32(eLang
), 16).toAsciiUpperCase());
1395 aFormatCode
.append( sal_Unicode(']') );
1400 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport
& rImport
,
1401 sal_uInt16 nPrfx
, const rtl::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 rtl::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_NUMBER
:
1450 case XML_TOK_STYLE_SCIENTIFIC_NUMBER
:
1451 case XML_TOK_STYLE_FRACTION
:
1452 case XML_TOK_STYLE_CURRENCY_SYMBOL
:
1453 case XML_TOK_STYLE_DAY
:
1454 case XML_TOK_STYLE_MONTH
:
1455 case XML_TOK_STYLE_YEAR
:
1456 case XML_TOK_STYLE_ERA
:
1457 case XML_TOK_STYLE_DAY_OF_WEEK
:
1458 case XML_TOK_STYLE_WEEK_OF_YEAR
:
1459 case XML_TOK_STYLE_QUARTER
:
1460 case XML_TOK_STYLE_HOURS
:
1461 case XML_TOK_STYLE_AM_PM
:
1462 case XML_TOK_STYLE_MINUTES
:
1463 case XML_TOK_STYLE_SECONDS
:
1464 case XML_TOK_STYLE_BOOLEAN
:
1465 case XML_TOK_STYLE_TEXT_CONTENT
:
1466 pContext
= new SvXMLNumFmtElementContext( GetImport(), nPrfx
, rLName
,
1467 *this, nToken
, xAttrList
);
1470 case XML_TOK_STYLE_PROPERTIES
:
1471 pContext
= new SvXMLNumFmtPropContext( GetImport(), nPrfx
, rLName
,
1474 case XML_TOK_STYLE_MAP
:
1476 // SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
1477 // so there's no need for an extra flag
1478 pContext
= new SvXMLNumFmtMapContext( GetImport(), nPrfx
, rLName
,
1485 pContext
= new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
1489 sal_Int32
SvXMLNumFormatContext::GetKey()
1493 if (bRemoveAfterUse
)
1495 // format is used -> don't remove
1496 bRemoveAfterUse
= sal_False
;
1498 pData
->SetUsed(nKey
);
1500 // Add to import's list of keys now - CreateAndInsert didn't add
1501 // the style if bRemoveAfterUse was set.
1502 GetImport().AddNumberStyle( nKey
, GetName() );
1508 // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
1509 bRemoveAfterUse
= sal_False
;
1510 CreateAndInsert(sal_True
);
1515 sal_Int32
SvXMLNumFormatContext::PrivateGetKey()
1517 // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
1523 CreateAndInsert(sal_True
);
1528 sal_Int32
SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference
< com::sun::star::util::XNumberFormatsSupplier
>& xFormatsSupplier
)
1532 SvNumberFormatter
* pFormatter
= NULL
;
1533 SvNumberFormatsSupplierObj
* pObj
=
1534 SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier
);
1536 pFormatter
= pObj
->GetNumberFormatter();
1539 return CreateAndInsert( pFormatter
);
1547 void SvXMLNumFormatContext::CreateAndInsert(sal_Bool
/*bOverwrite*/)
1550 CreateAndInsert(pData
->GetNumberFormatter());
1553 sal_Int32
SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter
* pFormatter
)
1557 OSL_FAIL("no number formatter");
1561 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1563 for (sal_uInt32 i
= 0; i
< aMyConditions
.size(); i
++)
1565 SvXMLNumFormatContext
* pStyle
= (SvXMLNumFormatContext
*)pStyles
->FindStyleChildContext(
1566 XML_STYLE_FAMILY_DATA_STYLE
, aMyConditions
[i
].sMapName
, sal_False
);
1569 if ((pStyle
->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag
1574 if ( !aFormatCode
.getLength() )
1576 // insert empty format as empty string (with quotes)
1577 // #93901# this check has to be done before inserting the conditions
1578 aFormatCode
.appendAscii("\"\""); // ""
1581 aFormatCode
.insert( 0, aConditions
.makeStringAndClear() );
1582 OUString sFormat
= aFormatCode
.makeStringAndClear();
1584 // test special cases
1586 if ( bAutoDec
) // automatic decimal places
1588 // #99391# adjust only if the format contains no text elements, no conditions
1589 // and no color definition (detected by the '[' at the start)
1591 if ( nType
== XML_TOK_STYLES_NUMBER_STYLE
&& !bHasExtraText
&&
1592 aMyConditions
.empty() && sFormat
.toChar() != (sal_Unicode
)'[' )
1593 nIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1595 if ( bAutoInt
) // automatic integer digits
1597 //! only if two decimal places was set?
1599 if ( nType
== XML_TOK_STYLES_NUMBER_STYLE
&& !bHasExtraText
&&
1600 aMyConditions
.empty() && sFormat
.toChar() != (sal_Unicode
)'[' )
1601 nIndex
= pFormatter
->GetFormatIndex( NF_NUMBER_SYSTEM
, nFormatLang
);
1604 // boolean is always the builtin boolean format
1605 // (no other boolean formats are implemented)
1606 if ( nType
== XML_TOK_STYLES_BOOLEAN_STYLE
)
1607 nIndex
= pFormatter
->GetFormatIndex( NF_BOOLEAN
, nFormatLang
);
1609 // check for default date formats
1610 if ( nType
== XML_TOK_STYLES_DATE_STYLE
&& bAutoOrder
&& !bDateNoDefault
)
1612 NfIndexTableOffset eFormat
= (NfIndexTableOffset
) SvXMLNumFmtDefaults::GetDefaultDateFormat(
1613 eDateDOW
, eDateDay
, eDateMonth
, eDateYear
,
1614 eDateHours
, eDateMins
, eDateSecs
, bFromSystem
);
1615 if ( eFormat
< NF_INDEX_TABLE_ENTRIES
)
1617 // #109651# if a date format has the automatic-order attribute and
1618 // contains exactly the elements of one of the default date formats,
1619 // use that default format, with the element order and separators
1620 // from the current locale settings
1622 nIndex
= pFormatter
->GetFormatIndex( eFormat
, nFormatLang
);
1626 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
&& !sFormat
.isEmpty() )
1628 // insert by format string
1630 String
aFormatStr( sFormat
);
1631 nIndex
= pFormatter
->GetEntryKey( aFormatStr
, nFormatLang
);
1632 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1634 xub_StrLen nErrPos
= 0;
1636 sal_Bool bOk
= pFormatter
->PutEntry( aFormatStr
, nErrPos
, l_nType
, nIndex
, nFormatLang
);
1637 if ( !bOk
&& nErrPos
== 0 && aFormatStr
!= String(sFormat
) )
1639 // if the string was modified by PutEntry, look for an existing format
1640 // with the modified string
1641 nIndex
= pFormatter
->GetEntryKey( aFormatStr
, nFormatLang
);
1642 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1646 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1650 //! I18N doesn't provide SYSTEM or extended date information yet
1651 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&& !bAutoOrder
)
1653 // use fixed-order formats instead of SYS... if bAutoOrder is false
1654 // (only if the format strings are equal for the locale)
1656 NfIndexTableOffset eOffset
= pFormatter
->GetIndexTableOffset( nIndex
);
1657 if ( eOffset
== NF_DATE_SYS_DMMMYYYY
)
1659 sal_uInt32 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_DIN_DMMMYYYY
, nFormatLang
);
1660 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nIndex
);
1661 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewIndex
);
1662 if ( pOldEntry
&& pNewEntry
&& pOldEntry
->GetFormatstring() == pNewEntry
->GetFormatstring() )
1665 else if ( eOffset
== NF_DATE_SYS_DMMMMYYYY
)
1667 sal_uInt32 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY
, nFormatLang
);
1668 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nIndex
);
1669 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewIndex
);
1670 if ( pOldEntry
&& pNewEntry
&& pOldEntry
->GetFormatstring() == pNewEntry
->GetFormatstring() )
1675 if ((nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) && !sFormatTitle
.isEmpty())
1677 SvNumberformat
* pFormat
= const_cast<SvNumberformat
*>(pFormatter
->GetEntry( nIndex
));
1680 String
sTitle (sFormatTitle
);
1681 pFormat
->SetComment(sTitle
);
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( const rtl::OUString
& rString
)
1717 aFormatCode
.append( rString
);
1718 bHasExtraText
= sal_True
;
1721 void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo
& rInfo
)
1723 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1727 // store special conditions
1728 bAutoDec
= ( rInfo
.nDecimals
< 0 );
1729 bAutoInt
= ( rInfo
.nInteger
< 0 );
1731 sal_uInt16 nPrec
= 0;
1732 sal_uInt16 nLeading
= 0;
1733 if ( rInfo
.nDecimals
>= 0 ) // < 0 : Default
1734 nPrec
= (sal_uInt16
) rInfo
.nDecimals
;
1735 if ( rInfo
.nInteger
>= 0 ) // < 0 : Default
1736 nLeading
= (sal_uInt16
) rInfo
.nInteger
;
1740 if ( nType
== XML_TOK_STYLES_CURRENCY_STYLE
)
1742 // for currency formats, "automatic decimals" is used for the automatic
1743 // currency format with (fixed) decimals from the locale settings
1745 const LocaleDataWrapper
& rLoc
= pData
->GetLocaleData( nFormatLang
);
1746 nPrec
= rLoc
.getCurrDigits();
1750 // for other types, "automatic decimals" means dynamic determination of
1751 // decimals, as achieved with the "general" keyword
1753 aFormatCode
.append( pFormatter
->GetStandardName( nFormatLang
) );
1762 sal_uInt16 nGenPrec
= nPrec
;
1763 if ( rInfo
.bDecReplace
|| rInfo
.bVarDecimals
)
1764 nGenPrec
= 0; // generate format without decimals...
1766 sal_Bool bGrouping
= rInfo
.bGrouping
;
1767 sal_uInt16 nEmbeddedCount
= rInfo
.aEmbeddedElements
.size();
1768 if ( nEmbeddedCount
)
1769 bGrouping
= sal_False
; // grouping and embedded characters can't be used together
1772 sal_uInt32 nStdIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1773 pFormatter
->GenerateFormat( aNumStr
, nStdIndex
, nFormatLang
,
1774 bGrouping
, sal_False
, nGenPrec
, nLeading
);
1776 if ( rInfo
.nExpDigits
>= 0 && nLeading
== 0 && !bGrouping
&& nEmbeddedCount
== 0 )
1778 // #i43959# For scientific numbers, "#" in the integer part forces a digit,
1779 // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
1781 aNumStr
.EraseLeadingChars( (sal_Unicode
)'#' );
1784 if ( nEmbeddedCount
)
1786 // insert embedded strings into number string
1787 // only the integer part is supported
1788 // nZeroPos is the string position where format position 0 is inserted
1790 xub_StrLen nZeroPos
= aNumStr
.Search( pData
->GetLocaleData( nFormatLang
).getNumDecimalSep() );
1791 if ( nZeroPos
== STRING_NOTFOUND
)
1792 nZeroPos
= aNumStr
.Len();
1794 // aEmbeddedElements is sorted - last entry has the largest position (leftmost)
1795 const SvXMLEmbeddedElement
* pLastObj
= &*rInfo
.aEmbeddedElements
.rbegin();
1796 sal_Int32 nLastFormatPos
= pLastObj
->nFormatPos
;
1797 if ( nLastFormatPos
>= nZeroPos
)
1799 // add '#' characters so all embedded texts are really embedded in digits
1800 // (there always has to be a digit before the leftmost embedded text)
1802 xub_StrLen nAddCount
= (xub_StrLen
)nLastFormatPos
+ 1 - nZeroPos
;
1804 aDigitStr
.Fill( nAddCount
, (sal_Unicode
)'#' );
1805 aNumStr
.Insert( aDigitStr
, 0 );
1806 nZeroPos
= nZeroPos
+ nAddCount
;
1809 // aEmbeddedElements is sorted with ascending positions - loop is from right to left
1810 for (SvXMLEmbeddedElementArr::const_iterator it
= rInfo
.aEmbeddedElements
.begin();
1811 it
!= rInfo
.aEmbeddedElements
.end(); ++it
)
1813 const SvXMLEmbeddedElement
* pObj
= &*it
;
1814 sal_Int32 nFormatPos
= pObj
->nFormatPos
;
1815 sal_Int32 nInsertPos
= nZeroPos
- nFormatPos
;
1816 if ( nFormatPos
>= 0 && nInsertPos
>= 0 )
1818 rtl::OUStringBuffer
aContent( pObj
->aText
);
1819 // #107805# always quote embedded strings - even space would otherwise
1820 // be recognized as thousands separator in French.
1821 aContent
.insert( 0, (sal_Unicode
) '"' );
1822 aContent
.append( (sal_Unicode
) '"' );
1824 aNumStr
.Insert( String( aContent
.makeStringAndClear() ), (xub_StrLen
)nInsertPos
);
1829 aFormatCode
.append( aNumStr
);
1831 if ( ( rInfo
.bDecReplace
|| rInfo
.bVarDecimals
) && nPrec
) // add decimal replacement (dashes)
1833 // add dashes for explicit decimal replacement, # for variable decimals
1834 sal_Unicode cAdd
= rInfo
.bDecReplace
? '-' : '#';
1836 aFormatCode
.append( pData
->GetLocaleData( nFormatLang
).getNumDecimalSep() );
1837 for ( sal_uInt16 i
=0; i
<nPrec
; i
++)
1838 aFormatCode
.append( cAdd
);
1841 // add extra thousands separators for display factor
1843 if ( rInfo
.fDisplayFactor
!= 1.0 && rInfo
.fDisplayFactor
> 0.0 )
1845 // test for 1.0 is just for optimization - nSepCount would be 0
1847 // one separator for each factor of 1000
1848 sal_Int32 nSepCount
= (sal_Int32
) ::rtl::math::round( log10(rInfo
.fDisplayFactor
) / 3.0 );
1849 if ( nSepCount
> 0 )
1851 OUString aSep
= pData
->GetLocaleData( nFormatLang
).getNumThousandSep();
1852 for ( sal_Int32 i
=0; i
<nSepCount
; i
++ )
1853 aFormatCode
.append( aSep
);
1858 void SvXMLNumFormatContext::AddCurrency( const rtl::OUString
& rContent
, LanguageType nLang
)
1860 sal_Bool bAutomatic
= sal_False
;
1861 OUString aSymbol
= rContent
;
1862 if ( aSymbol
.isEmpty())
1864 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1867 pFormatter
->ChangeIntl( nFormatLang
);
1868 String sCurString
, sDummy
;
1869 pFormatter
->GetCompatibilityCurrency( sCurString
, sDummy
);
1870 aSymbol
= sCurString
;
1872 bAutomatic
= sal_True
;
1875 else if ( nLang
== LANGUAGE_SYSTEM
&& aSymbol
.compareToAscii("CCC") == 0 )
1877 // "CCC" is used for automatic long symbol
1878 bAutomatic
= sal_True
;
1883 // remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
1884 // otherwise the currency symbol isn't recognized (#94048#)
1886 sal_Int32 nLength
= aFormatCode
.getLength();
1887 if ( nLength
> 1 && aFormatCode
[nLength
- 1] == '"' )
1889 // find start of quoted string
1890 // When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
1891 // they must be handled here, too.
1893 sal_Int32 nFirst
= nLength
- 2;
1894 while ( nFirst
>= 0 && aFormatCode
[nFirst
] != '"' )
1898 // remove both quotes from aFormatCode
1899 rtl::OUString aOld
= aFormatCode
.makeStringAndClear();
1901 aFormatCode
.append( aOld
.copy( 0, nFirst
) );
1902 if ( nLength
> nFirst
+ 2 )
1903 aFormatCode
.append( aOld
.copy( nFirst
+ 1, nLength
- nFirst
- 2 ) );
1909 aFormatCode
.appendAscii( "[$" ); // intro for "new" currency symbols
1911 aFormatCode
.append( aSymbol
);
1915 if ( nLang
!= LANGUAGE_SYSTEM
)
1917 // '-' sign and language code in hex:
1918 aFormatCode
.append( (sal_Unicode
) '-' );
1919 aFormatCode
.append(rtl::OUString::valueOf(sal_Int32(nLang
), 16).toAsciiUpperCase());
1922 aFormatCode
.append( (sal_Unicode
) ']' ); // end of "new" currency symbol
1926 void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex
)
1928 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1932 if ( nIndex
== NF_KEY_G
|| nIndex
== NF_KEY_GG
|| nIndex
== NF_KEY_GGG
)
1935 if ( nIndex
== NF_KEY_NNNN
)
1937 nIndex
= NF_KEY_NNN
;
1938 bHasLongDoW
= sal_True
; // to remove string constant with separator
1941 String sKeyword
= pFormatter
->GetKeyword( nFormatLang
, nIndex
);
1943 if ( nIndex
== NF_KEY_H
|| nIndex
== NF_KEY_HH
||
1944 nIndex
== NF_KEY_MI
|| nIndex
== NF_KEY_MMI
||
1945 nIndex
== NF_KEY_S
|| nIndex
== NF_KEY_SS
)
1947 if ( !bTruncate
&& !bHasDateTime
)
1949 // with truncate-on-overflow = false, add "[]" to first time part
1951 sKeyword
.Insert( (sal_Unicode
) '[', 0 );
1952 sKeyword
.Append( (sal_Unicode
) ']' );
1954 bHasDateTime
= sal_True
;
1957 aFormatCode
.append( sKeyword
);
1959 // collect the date elements that the format contains, to recognize default date formats
1962 case NF_KEY_NN
: eDateDOW
= XML_DEA_SHORT
; break;
1964 case NF_KEY_NNNN
: eDateDOW
= XML_DEA_LONG
; break;
1965 case NF_KEY_D
: eDateDay
= XML_DEA_SHORT
; break;
1966 case NF_KEY_DD
: eDateDay
= XML_DEA_LONG
; break;
1967 case NF_KEY_M
: eDateMonth
= XML_DEA_SHORT
; break;
1968 case NF_KEY_MM
: eDateMonth
= XML_DEA_LONG
; break;
1969 case NF_KEY_MMM
: eDateMonth
= XML_DEA_TEXTSHORT
; break;
1970 case NF_KEY_MMMM
: eDateMonth
= XML_DEA_TEXTLONG
; break;
1971 case NF_KEY_YY
: eDateYear
= XML_DEA_SHORT
; break;
1972 case NF_KEY_YYYY
: eDateYear
= XML_DEA_LONG
; break;
1973 case NF_KEY_H
: eDateHours
= XML_DEA_SHORT
; break;
1974 case NF_KEY_HH
: eDateHours
= XML_DEA_LONG
; break;
1975 case NF_KEY_MI
: eDateMins
= XML_DEA_SHORT
; break;
1976 case NF_KEY_MMI
: eDateMins
= XML_DEA_LONG
; break;
1977 case NF_KEY_S
: eDateSecs
= XML_DEA_SHORT
; break;
1978 case NF_KEY_SS
: eDateSecs
= XML_DEA_LONG
; break;
1980 case NF_KEY_AMPM
: break; // AM/PM may or may not be in date/time formats -> ignore by itself
1982 bDateNoDefault
= sal_True
; // any other element -> no default format
1986 sal_Bool
lcl_IsAtEnd( rtl::OUStringBuffer
& rBuffer
, const String
& rToken
)
1988 sal_Int32 nBufLen
= rBuffer
.getLength();
1989 xub_StrLen nTokLen
= rToken
.Len();
1991 if ( nTokLen
> nBufLen
)
1994 sal_Int32 nStartPos
= nBufLen
- nTokLen
;
1995 for ( xub_StrLen nTokPos
= 0; nTokPos
< nTokLen
; nTokPos
++ )
1996 if ( rToken
.GetChar( nTokPos
) != rBuffer
[nStartPos
+ nTokPos
] )
2002 sal_Bool
SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld
, sal_uInt16 nNew
)
2004 // replaces one keyword with another if it is found at the end of the code
2006 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2010 String sOldStr
= pFormatter
->GetKeyword( nFormatLang
, nOld
);
2011 if ( lcl_IsAtEnd( aFormatCode
, sOldStr
) )
2013 // remove old keyword
2014 aFormatCode
.setLength( aFormatCode
.getLength() - sOldStr
.Len() );
2017 String sNewStr
= pFormatter
->GetKeyword( nFormatLang
, nNew
);
2018 aFormatCode
.append( sNewStr
);
2020 return sal_True
; // changed
2022 return sal_False
; // not found
2025 void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex
)
2027 rtl::OUString rApplyName
= aMyConditions
[nIndex
].sMapName
;
2028 rtl::OUString rCondition
= aMyConditions
[nIndex
].sCondition
;
2029 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2030 sal_uInt32 l_nKey
= pData
->GetKeyForName( rApplyName
);
2031 OUString
sValue("value()"); //! define constant
2032 sal_Int32 nValLen
= sValue
.getLength();
2034 if ( pFormatter
&& l_nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&&
2035 rCondition
.copy( 0, nValLen
) == sValue
)
2037 //! test for valid conditions
2038 //! test for default conditions
2040 OUString sRealCond
= rCondition
.copy( nValLen
, rCondition
.getLength() - nValLen
);
2041 sal_Bool bDefaultCond
= sal_False
;
2043 //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
2044 //! allow blanks in conditions
2045 sal_Bool bFirstCond
= ( aConditions
.getLength() == 0 );
2046 if ( bFirstCond
&& aMyConditions
.size() == 1 && sRealCond
.compareToAscii( ">=0" ) == 0 )
2047 bDefaultCond
= sal_True
;
2049 if ( nType
== XML_TOK_STYLES_TEXT_STYLE
&& nIndex
== 2 )
2051 // The third condition in a number format with a text part can only be
2052 // "all other numbers", the condition string must be empty.
2053 bDefaultCond
= sal_True
;
2058 sal_Int32 nPos
= sRealCond
.indexOf( '.' );
2060 { // #i8026# #103991# localize decimal separator
2061 const String
& rDecSep
= GetLocaleData().getNumDecimalSep();
2062 if ( rDecSep
.Len() > 1 || rDecSep
.GetChar(0) != '.' )
2063 sRealCond
= sRealCond
.replaceAt( nPos
, 1, rDecSep
);
2065 aConditions
.append( (sal_Unicode
) '[' );
2066 aConditions
.append( sRealCond
);
2067 aConditions
.append( (sal_Unicode
) ']' );
2070 const SvNumberformat
* pFormat
= pFormatter
->GetEntry(l_nKey
);
2072 aConditions
.append( OUString( pFormat
->GetFormatstring() ) );
2074 aConditions
.append( (sal_Unicode
) ';' );
2078 void SvXMLNumFormatContext::AddCondition( const rtl::OUString
& rCondition
, const rtl::OUString
& rApplyName
)
2080 MyCondition aCondition
;
2081 aCondition
.sCondition
= rCondition
;
2082 aCondition
.sMapName
= rApplyName
;
2083 aMyConditions
.push_back(aCondition
);
2086 void SvXMLNumFormatContext::AddColor( sal_uInt32
const nColor
)
2088 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2092 OUStringBuffer aColName
;
2093 for ( sal_uInt16 i
=0; i
<XML_NUMF_COLORCOUNT
; i
++ )
2094 if (nColor
== aNumFmtStdColors
[i
])
2096 aColName
= OUString( pFormatter
->GetKeyword( nFormatLang
, sal::static_int_cast
< sal_uInt16
>(NF_KEY_FIRSTCOLOR
+ i
) ) );
2100 if ( aColName
.getLength() )
2102 aColName
.insert( 0, (sal_Unicode
) '[' );
2103 aColName
.append( (sal_Unicode
) ']' );
2104 aFormatCode
.insert( 0, aColName
.makeStringAndClear() );
2108 void SvXMLNumFormatContext::UpdateCalendar( const rtl::OUString
& rNewCalendar
)
2110 if ( rNewCalendar
!= sCalendar
)
2112 sCalendar
= rNewCalendar
;
2113 if ( !sCalendar
.isEmpty() )
2115 aFormatCode
.appendAscii( "[~" ); // intro for calendar code
2116 aFormatCode
.append( sCalendar
);
2117 aFormatCode
.append( (sal_Unicode
) ']' ); // end of "new" currency symbolcalendar code
2122 sal_Bool
SvXMLNumFormatContext::IsSystemLanguage()
2124 return nFormatLang
== LANGUAGE_SYSTEM
;
2127 //-------------------------------------------------------------------------
2130 // SvXMLNumFmtHelper
2133 SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2134 const uno::Reference
<util::XNumberFormatsSupplier
>& rSupp
,
2135 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
)
2136 : mxServiceFactory(xServiceFactory
)
2138 DBG_ASSERT( mxServiceFactory
.is(), "got no service manager" );
2140 SvNumberFormatter
* pFormatter
= NULL
;
2141 SvNumberFormatsSupplierObj
* pObj
=
2142 SvNumberFormatsSupplierObj::getImplementation( rSupp
);
2144 pFormatter
= pObj
->GetNumberFormatter();
2146 pData
= new SvXMLNumImpData( pFormatter
, mxServiceFactory
);
2149 SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2150 SvNumberFormatter
* pNumberFormatter
,
2151 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
)
2152 : mxServiceFactory(xServiceFactory
)
2154 DBG_ASSERT( mxServiceFactory
.is(), "got no service manager" );
2156 pData
= new SvXMLNumImpData( pNumberFormatter
, mxServiceFactory
);
2159 SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
2161 // remove temporary (volatile) formats from NumberFormatter
2162 pData
->RemoveVolatileFormats();
2167 SvXMLStyleContext
* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport
& rImport
,
2168 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
2169 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
2170 SvXMLStylesContext
& rStyles
)
2172 SvXMLStyleContext
* pContext
= NULL
;
2174 const SvXMLTokenMap
& rTokenMap
= pData
->GetStylesElemTokenMap();
2175 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, rLocalName
);
2178 case XML_TOK_STYLES_NUMBER_STYLE
:
2179 case XML_TOK_STYLES_CURRENCY_STYLE
:
2180 case XML_TOK_STYLES_PERCENTAGE_STYLE
:
2181 case XML_TOK_STYLES_DATE_STYLE
:
2182 case XML_TOK_STYLES_TIME_STYLE
:
2183 case XML_TOK_STYLES_BOOLEAN_STYLE
:
2184 case XML_TOK_STYLES_TEXT_STYLE
:
2185 pContext
= new SvXMLNumFormatContext( rImport
, nPrefix
, rLocalName
,
2186 pData
, nToken
, xAttrList
, rStyles
);
2190 // return NULL if not a data style, caller must handle other elements
2194 const SvXMLTokenMap
& SvXMLNumFmtHelper::GetStylesElemTokenMap()
2196 return pData
->GetStylesElemTokenMap();
2199 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */