1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlnumfi.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
34 #include <svtools/syslocale.hxx>
36 #define _ZFORLIST_DECLARE_TABLE
37 #include <svtools/zforlist.hxx>
39 #include <svtools/zformat.hxx>
40 #include <svtools/numuno.hxx>
41 #include <rtl/math.hxx>
42 #include <i18npool/mslangid.hxx>
43 #include <tools/debug.hxx>
44 #include <rtl/ustrbuf.hxx>
47 //#include <comphelper/processfactory.hxx>
49 #include <xmloff/xmlnumfi.hxx>
50 #include <xmloff/xmltkmap.hxx>
51 #include "xmlnmspe.hxx"
52 #include <xmloff/xmlictxt.hxx>
53 #include <xmloff/xmlimp.hxx>
54 #include <xmloff/xmluconv.hxx>
55 #include <xmloff/nmspmap.hxx>
56 #include <xmloff/families.hxx>
57 #include <xmloff/xmltoken.hxx>
59 using ::rtl::OUString
;
60 using ::rtl::OUStringBuffer
;
62 using namespace ::com::sun::star
;
63 using namespace ::xmloff::token
;
65 //-------------------------------------------------------------------------
67 struct SvXMLNumFmtEntry
71 sal_Bool bRemoveAfterUse
;
73 SvXMLNumFmtEntry( const rtl::OUString
& rN
, sal_uInt32 nK
, sal_Bool bR
) :
74 aName(rN
), nKey(nK
), bRemoveAfterUse(bR
) {}
77 typedef SvXMLNumFmtEntry
* SvXMLNumFmtEntryPtr
;
78 SV_DECL_PTRARR_DEL( SvXMLNumFmtEntryArr
, SvXMLNumFmtEntryPtr
, 4, 4 )
80 struct SvXMLEmbeddedElement
85 SvXMLEmbeddedElement( sal_Int32 nFP
, const rtl::OUString
& rT
) :
86 nFormatPos(nFP
), aText(rT
) {}
88 // comparison operators for PTRARR sorting - sorted by position
89 BOOL
operator ==( const SvXMLEmbeddedElement
& r
) const { return nFormatPos
== r
.nFormatPos
; }
90 BOOL
operator < ( const SvXMLEmbeddedElement
& r
) const { return nFormatPos
< r
.nFormatPos
; }
93 typedef SvXMLEmbeddedElement
* SvXMLEmbeddedElementPtr
;
94 SV_DECL_PTRARR_SORT_DEL( SvXMLEmbeddedElementArr
, SvXMLEmbeddedElementPtr
, 0, 4 )
96 //-------------------------------------------------------------------------
100 SvNumberFormatter
* pFormatter
;
101 SvXMLTokenMap
* pStylesElemTokenMap
;
102 SvXMLTokenMap
* pStyleElemTokenMap
;
103 SvXMLTokenMap
* pStyleAttrTokenMap
;
104 SvXMLTokenMap
* pStyleElemAttrTokenMap
;
105 LocaleDataWrapper
* pLocaleData
;
106 SvXMLNumFmtEntryArr aNameEntries
;
109 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> mxServiceFactory
;
113 // SvXMLNumImpData( SvNumberFormatter* pFmt );
115 SvNumberFormatter
* pFmt
,
116 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
);
119 SvNumberFormatter
* GetNumberFormatter() const { return pFormatter
; }
120 const SvXMLTokenMap
& GetStylesElemTokenMap();
121 const SvXMLTokenMap
& GetStyleElemTokenMap();
122 const SvXMLTokenMap
& GetStyleAttrTokenMap();
123 const SvXMLTokenMap
& GetStyleElemAttrTokenMap();
124 const LocaleDataWrapper
& GetLocaleData( LanguageType nLang
);
125 sal_uInt32
GetKeyForName( const rtl::OUString
& rName
);
126 void AddKey( sal_uInt32 nKey
, const rtl::OUString
& rName
, sal_Bool bRemoveAfterUse
);
127 void SetUsed( sal_uInt32 nKey
);
128 void RemoveVolatileFormats();
132 struct SvXMLNumberInfo
136 sal_Int32 nExpDigits
;
137 sal_Int32 nNumerDigits
;
138 sal_Int32 nDenomDigits
;
140 sal_Bool bDecReplace
;
141 sal_Bool bVarDecimals
;
142 double fDisplayFactor
;
143 SvXMLEmbeddedElementArr aEmbeddedElements
;
147 nDecimals
= nInteger
= nExpDigits
= nNumerDigits
= nDenomDigits
= -1;
148 bGrouping
= bDecReplace
= bVarDecimals
= sal_False
;
149 fDisplayFactor
= 1.0;
153 class SvXMLNumFmtElementContext
: public SvXMLImportContext
155 SvXMLNumFormatContext
& rParent
;
157 rtl::OUStringBuffer aContent
;
158 SvXMLNumberInfo aNumInfo
;
159 LanguageType nElementLang
;
162 rtl::OUString sCalendar
;
165 SvXMLNumFmtElementContext( SvXMLImport
& rImport
, USHORT nPrfx
,
166 const rtl::OUString
& rLName
,
167 SvXMLNumFormatContext
& rParentContext
, sal_uInt16 nNewType
,
168 const ::com::sun::star::uno::Reference
<
169 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
170 virtual ~SvXMLNumFmtElementContext();
172 virtual SvXMLImportContext
*CreateChildContext( USHORT nPrefix
,
173 const rtl::OUString
& rLocalName
,
174 const ::com::sun::star::uno::Reference
<
175 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
176 virtual void Characters( const rtl::OUString
& rChars
);
177 virtual void EndElement();
179 void AddEmbeddedElement( sal_Int32 nFormatPos
, const rtl::OUString
& rContent
);
183 class SvXMLNumFmtEmbeddedTextContext
: public SvXMLImportContext
185 SvXMLNumFmtElementContext
& rParent
;
186 rtl::OUStringBuffer aContent
;
187 sal_Int32 nTextPosition
;
190 SvXMLNumFmtEmbeddedTextContext( SvXMLImport
& rImport
, USHORT nPrfx
,
191 const rtl::OUString
& rLName
,
192 SvXMLNumFmtElementContext
& rParentContext
,
193 const ::com::sun::star::uno::Reference
<
194 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
195 virtual ~SvXMLNumFmtEmbeddedTextContext();
197 virtual SvXMLImportContext
*CreateChildContext( USHORT nPrefix
,
198 const rtl::OUString
& rLocalName
,
199 const ::com::sun::star::uno::Reference
<
200 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
201 virtual void Characters( const rtl::OUString
& rChars
);
202 virtual void EndElement();
206 class SvXMLNumFmtMapContext
: public SvXMLImportContext
208 SvXMLNumFormatContext
& rParent
;
209 rtl::OUString sCondition
;
213 SvXMLNumFmtMapContext( SvXMLImport
& rImport
, USHORT nPrfx
,
214 const rtl::OUString
& rLName
,
215 SvXMLNumFormatContext
& rParentContext
,
216 const ::com::sun::star::uno::Reference
<
217 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
218 virtual ~SvXMLNumFmtMapContext();
220 virtual SvXMLImportContext
*CreateChildContext( USHORT nPrefix
,
221 const rtl::OUString
& rLocalName
,
222 const ::com::sun::star::uno::Reference
<
223 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
224 virtual void Characters( const rtl::OUString
& rChars
);
225 virtual void EndElement();
229 class SvXMLNumFmtPropContext
: public SvXMLImportContext
231 SvXMLNumFormatContext
& rParent
;
236 SvXMLNumFmtPropContext( SvXMLImport
& rImport
, USHORT nPrfx
,
237 const rtl::OUString
& rLName
,
238 SvXMLNumFormatContext
& rParentContext
,
239 const ::com::sun::star::uno::Reference
<
240 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
241 virtual ~SvXMLNumFmtPropContext();
243 virtual SvXMLImportContext
*CreateChildContext( USHORT nPrefix
,
244 const rtl::OUString
& rLocalName
,
245 const ::com::sun::star::uno::Reference
<
246 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
247 virtual void Characters( const rtl::OUString
& rChars
);
248 virtual void EndElement();
252 //-------------------------------------------------------------------------
254 enum SvXMLStyleTokens
257 XML_TOK_STYLE_NUMBER
,
258 XML_TOK_STYLE_SCIENTIFIC_NUMBER
,
259 XML_TOK_STYLE_FRACTION
,
260 XML_TOK_STYLE_CURRENCY_SYMBOL
,
265 XML_TOK_STYLE_DAY_OF_WEEK
,
266 XML_TOK_STYLE_WEEK_OF_YEAR
,
267 XML_TOK_STYLE_QUARTER
,
270 XML_TOK_STYLE_MINUTES
,
271 XML_TOK_STYLE_SECONDS
,
272 XML_TOK_STYLE_BOOLEAN
,
273 XML_TOK_STYLE_TEXT_CONTENT
,
274 XML_TOK_STYLE_PROPERTIES
,
278 enum SvXMLStyleAttrTokens
280 XML_TOK_STYLE_ATTR_NAME
,
281 XML_TOK_STYLE_ATTR_LANGUAGE
,
282 XML_TOK_STYLE_ATTR_COUNTRY
,
283 XML_TOK_STYLE_ATTR_TITLE
,
284 XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
,
285 XML_TOK_STYLE_ATTR_FORMAT_SOURCE
,
286 XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
,
287 XML_TOK_STYLE_ATTR_VOLATILE
,
288 XML_TOK_STYLE_ATTR_TRANSL_FORMAT
,
289 XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
,
290 XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
,
291 XML_TOK_STYLE_ATTR_TRANSL_STYLE
294 enum SvXMLStyleElemAttrTokens
296 XML_TOK_ELEM_ATTR_DECIMAL_PLACES
,
297 XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
,
298 XML_TOK_ELEM_ATTR_GROUPING
,
299 XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
,
300 XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
,
301 XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
,
302 XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
,
303 XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
,
304 XML_TOK_ELEM_ATTR_LANGUAGE
,
305 XML_TOK_ELEM_ATTR_COUNTRY
,
306 XML_TOK_ELEM_ATTR_STYLE
,
307 XML_TOK_ELEM_ATTR_TEXTUAL
,
308 XML_TOK_ELEM_ATTR_CALENDAR
311 //-------------------------------------------------------------------------
317 #define XML_NUMF_COLORCOUNT 10
319 static ColorData aNumFmtStdColors
[XML_NUMF_COLORCOUNT
] =
337 // maps for SvXMLUnitConverter::convertEnum
339 static __FAR_DATA SvXMLEnumMapEntry aStyleValueMap
[] =
341 { XML_SHORT
, sal_False
},
342 { XML_LONG
, sal_True
},
343 { XML_TOKEN_INVALID
, 0 }
346 static __FAR_DATA SvXMLEnumMapEntry aFormatSourceMap
[] =
348 { XML_FIXED
, sal_False
},
349 { XML_LANGUAGE
, sal_True
},
350 { XML_TOKEN_INVALID
, 0 }
353 //-------------------------------------------------------------------------
355 struct SvXMLDefaultDateFormat
357 NfIndexTableOffset eFormat
;
358 SvXMLDateElementAttributes eDOW
;
359 SvXMLDateElementAttributes eDay
;
360 SvXMLDateElementAttributes eMonth
;
361 SvXMLDateElementAttributes eYear
;
362 SvXMLDateElementAttributes eHours
;
363 SvXMLDateElementAttributes eMins
;
364 SvXMLDateElementAttributes eSecs
;
368 static __FAR_DATA SvXMLDefaultDateFormat aDefaultDateFormats
[] =
370 // format day-of-week day month year hours minutes seconds format-source
372 { 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
},
373 { 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
},
374 { 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
},
375 { 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
},
376 { 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
},
377 { 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
},
378 { 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
},
379 { 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
},
380 { 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
},
381 { 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
},
382 { 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
},
383 { 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
},
384 { 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
},
385 { 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
}
388 //-------------------------------------------------------------------------
390 SV_IMPL_PTRARR( SvXMLNumFmtEntryArr
, SvXMLNumFmtEntryPtr
);
391 SV_IMPL_OP_PTRARR_SORT( SvXMLEmbeddedElementArr
, SvXMLEmbeddedElementPtr
);
393 //-------------------------------------------------------------------------
400 // SvXMLNumImpData::SvXMLNumImpData( SvNumberFormatter* pFmt ) :
401 SvXMLNumImpData::SvXMLNumImpData(
402 SvNumberFormatter
* pFmt
,
403 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
)
405 pStylesElemTokenMap(NULL
),
406 pStyleElemTokenMap(NULL
),
407 pStyleAttrTokenMap(NULL
),
408 pStyleElemAttrTokenMap(NULL
),
412 mxServiceFactory(xServiceFactory
)
414 DBG_ASSERT( mxServiceFactory
.is(), "got no service manager" );
417 SvXMLNumImpData::~SvXMLNumImpData()
419 delete pStylesElemTokenMap
;
420 delete pStyleElemTokenMap
;
421 delete pStyleAttrTokenMap
;
422 delete pStyleElemAttrTokenMap
;
426 sal_uInt32
SvXMLNumImpData::GetKeyForName( const rtl::OUString
& rName
)
428 USHORT nCount
= aNameEntries
.Count();
429 for (USHORT i
=0; i
<nCount
; i
++)
431 const SvXMLNumFmtEntry
* pObj
= aNameEntries
[i
];
432 if ( pObj
->aName
== rName
)
433 return pObj
->nKey
; // found
435 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
438 void SvXMLNumImpData::AddKey( sal_uInt32 nKey
, const rtl::OUString
& rName
, sal_Bool bRemoveAfterUse
)
440 if ( bRemoveAfterUse
)
442 // if there is already an entry for this key without the bRemoveAfterUse flag,
443 // clear the flag for this entry, too
445 USHORT nCount
= aNameEntries
.Count();
446 for (USHORT i
=0; i
<nCount
; i
++)
448 SvXMLNumFmtEntry
* pObj
= aNameEntries
[i
];
449 if ( pObj
->nKey
== nKey
&& !pObj
->bRemoveAfterUse
)
451 bRemoveAfterUse
= sal_False
; // clear flag for new entry
458 // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
462 SvXMLNumFmtEntry
* pObj
= new SvXMLNumFmtEntry( rName
, nKey
, bRemoveAfterUse
);
463 aNameEntries
.Insert( pObj
, aNameEntries
.Count() );
466 void SvXMLNumImpData::SetUsed( sal_uInt32 nKey
)
468 USHORT nCount
= aNameEntries
.Count();
469 for (USHORT i
=0; i
<nCount
; i
++)
471 SvXMLNumFmtEntry
* pObj
= aNameEntries
[i
];
472 if ( pObj
->nKey
== nKey
)
474 pObj
->bRemoveAfterUse
= sal_False
; // used -> don't remove
476 // continue searching - there may be several entries for the same key
477 // (with different names), the format must not be deleted if any one of
483 void SvXMLNumImpData::RemoveVolatileFormats()
485 // remove temporary (volatile) formats from NumberFormatter
486 // called at the end of each import (styles and content), so volatile formats
487 // from styles can't be used in content
492 USHORT nCount
= aNameEntries
.Count();
493 for (USHORT i
=0; i
<nCount
; i
++)
495 const SvXMLNumFmtEntry
* pObj
= aNameEntries
[i
];
496 if ( pObj
->bRemoveAfterUse
)
498 const SvNumberformat
* pFormat
= pFormatter
->GetEntry(pObj
->nKey
);
499 if (pFormat
&& (pFormat
->GetType() & NUMBERFORMAT_DEFINED
))
500 pFormatter
->DeleteEntry( pObj
->nKey
);
505 const SvXMLTokenMap
& SvXMLNumImpData::GetStylesElemTokenMap()
507 if( !pStylesElemTokenMap
)
509 static __FAR_DATA SvXMLTokenMapEntry aStylesElemMap
[] =
512 { XML_NAMESPACE_NUMBER
, XML_NUMBER_STYLE
, XML_TOK_STYLES_NUMBER_STYLE
},
513 { XML_NAMESPACE_NUMBER
, XML_CURRENCY_STYLE
, XML_TOK_STYLES_CURRENCY_STYLE
},
514 { XML_NAMESPACE_NUMBER
, XML_PERCENTAGE_STYLE
, XML_TOK_STYLES_PERCENTAGE_STYLE
},
515 { XML_NAMESPACE_NUMBER
, XML_DATE_STYLE
, XML_TOK_STYLES_DATE_STYLE
},
516 { XML_NAMESPACE_NUMBER
, XML_TIME_STYLE
, XML_TOK_STYLES_TIME_STYLE
},
517 { XML_NAMESPACE_NUMBER
, XML_BOOLEAN_STYLE
, XML_TOK_STYLES_BOOLEAN_STYLE
},
518 { XML_NAMESPACE_NUMBER
, XML_TEXT_STYLE
, XML_TOK_STYLES_TEXT_STYLE
},
522 pStylesElemTokenMap
= new SvXMLTokenMap( aStylesElemMap
);
524 return *pStylesElemTokenMap
;
527 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleElemTokenMap()
529 if( !pStyleElemTokenMap
)
531 static __FAR_DATA SvXMLTokenMapEntry aStyleElemMap
[] =
533 // elements in a style
534 { XML_NAMESPACE_NUMBER
, XML_TEXT
, XML_TOK_STYLE_TEXT
},
535 { XML_NAMESPACE_NUMBER
, XML_NUMBER
, XML_TOK_STYLE_NUMBER
},
536 { XML_NAMESPACE_NUMBER
, XML_SCIENTIFIC_NUMBER
, XML_TOK_STYLE_SCIENTIFIC_NUMBER
},
537 { XML_NAMESPACE_NUMBER
, XML_FRACTION
, XML_TOK_STYLE_FRACTION
},
538 { XML_NAMESPACE_NUMBER
, XML_CURRENCY_SYMBOL
, XML_TOK_STYLE_CURRENCY_SYMBOL
},
539 { XML_NAMESPACE_NUMBER
, XML_DAY
, XML_TOK_STYLE_DAY
},
540 { XML_NAMESPACE_NUMBER
, XML_MONTH
, XML_TOK_STYLE_MONTH
},
541 { XML_NAMESPACE_NUMBER
, XML_YEAR
, XML_TOK_STYLE_YEAR
},
542 { XML_NAMESPACE_NUMBER
, XML_ERA
, XML_TOK_STYLE_ERA
},
543 { XML_NAMESPACE_NUMBER
, XML_DAY_OF_WEEK
, XML_TOK_STYLE_DAY_OF_WEEK
},
544 { XML_NAMESPACE_NUMBER
, XML_WEEK_OF_YEAR
, XML_TOK_STYLE_WEEK_OF_YEAR
},
545 { XML_NAMESPACE_NUMBER
, XML_QUARTER
, XML_TOK_STYLE_QUARTER
},
546 { XML_NAMESPACE_NUMBER
, XML_HOURS
, XML_TOK_STYLE_HOURS
},
547 { XML_NAMESPACE_NUMBER
, XML_AM_PM
, XML_TOK_STYLE_AM_PM
},
548 { XML_NAMESPACE_NUMBER
, XML_MINUTES
, XML_TOK_STYLE_MINUTES
},
549 { XML_NAMESPACE_NUMBER
, XML_SECONDS
, XML_TOK_STYLE_SECONDS
},
550 { XML_NAMESPACE_NUMBER
, XML_BOOLEAN
, XML_TOK_STYLE_BOOLEAN
},
551 { XML_NAMESPACE_NUMBER
, XML_TEXT_CONTENT
, XML_TOK_STYLE_TEXT_CONTENT
},
552 { XML_NAMESPACE_STYLE
, XML_TEXT_PROPERTIES
, XML_TOK_STYLE_PROPERTIES
},
553 { XML_NAMESPACE_STYLE
, XML_MAP
, XML_TOK_STYLE_MAP
},
557 pStyleElemTokenMap
= new SvXMLTokenMap( aStyleElemMap
);
559 return *pStyleElemTokenMap
;
562 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleAttrTokenMap()
564 if( !pStyleAttrTokenMap
)
566 static __FAR_DATA SvXMLTokenMapEntry aStyleAttrMap
[] =
568 // attributes for a style
569 { XML_NAMESPACE_STYLE
, XML_NAME
, XML_TOK_STYLE_ATTR_NAME
},
570 { XML_NAMESPACE_NUMBER
, XML_LANGUAGE
, XML_TOK_STYLE_ATTR_LANGUAGE
},
571 { XML_NAMESPACE_NUMBER
, XML_COUNTRY
, XML_TOK_STYLE_ATTR_COUNTRY
},
572 { XML_NAMESPACE_NUMBER
, XML_TITLE
, XML_TOK_STYLE_ATTR_TITLE
},
573 { XML_NAMESPACE_NUMBER
, XML_AUTOMATIC_ORDER
, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
},
574 { XML_NAMESPACE_NUMBER
, XML_FORMAT_SOURCE
, XML_TOK_STYLE_ATTR_FORMAT_SOURCE
},
575 { XML_NAMESPACE_NUMBER
, XML_TRUNCATE_ON_OVERFLOW
, XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
},
576 { XML_NAMESPACE_STYLE
, XML_VOLATILE
, XML_TOK_STYLE_ATTR_VOLATILE
},
577 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_FORMAT
, XML_TOK_STYLE_ATTR_TRANSL_FORMAT
},
578 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_LANGUAGE
, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
},
579 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_COUNTRY
, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
},
580 { XML_NAMESPACE_NUMBER
, XML_TRANSLITERATION_STYLE
, XML_TOK_STYLE_ATTR_TRANSL_STYLE
},
584 pStyleAttrTokenMap
= new SvXMLTokenMap( aStyleAttrMap
);
586 return *pStyleAttrTokenMap
;
589 const SvXMLTokenMap
& SvXMLNumImpData::GetStyleElemAttrTokenMap()
591 if( !pStyleElemAttrTokenMap
)
593 static __FAR_DATA SvXMLTokenMapEntry aStyleElemAttrMap
[] =
595 // attributes for an element within a style
596 { XML_NAMESPACE_NUMBER
, XML_DECIMAL_PLACES
, XML_TOK_ELEM_ATTR_DECIMAL_PLACES
},
597 { XML_NAMESPACE_NUMBER
, XML_MIN_INTEGER_DIGITS
, XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
},
598 { XML_NAMESPACE_NUMBER
, XML_GROUPING
, XML_TOK_ELEM_ATTR_GROUPING
},
599 { XML_NAMESPACE_NUMBER
, XML_DISPLAY_FACTOR
, XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
},
600 { XML_NAMESPACE_NUMBER
, XML_DECIMAL_REPLACEMENT
, XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
},
601 { XML_NAMESPACE_NUMBER
, XML_MIN_EXPONENT_DIGITS
, XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
},
602 { XML_NAMESPACE_NUMBER
, XML_MIN_NUMERATOR_DIGITS
, XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
},
603 { XML_NAMESPACE_NUMBER
, XML_MIN_DENOMINATOR_DIGITS
, XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
},
604 { XML_NAMESPACE_NUMBER
, XML_LANGUAGE
, XML_TOK_ELEM_ATTR_LANGUAGE
},
605 { XML_NAMESPACE_NUMBER
, XML_COUNTRY
, XML_TOK_ELEM_ATTR_COUNTRY
},
606 { XML_NAMESPACE_NUMBER
, XML_STYLE
, XML_TOK_ELEM_ATTR_STYLE
},
607 { XML_NAMESPACE_NUMBER
, XML_TEXTUAL
, XML_TOK_ELEM_ATTR_TEXTUAL
},
608 { XML_NAMESPACE_NUMBER
, XML_CALENDAR
, XML_TOK_ELEM_ATTR_CALENDAR
},
612 pStyleElemAttrTokenMap
= new SvXMLTokenMap( aStyleElemAttrMap
);
614 return *pStyleElemAttrTokenMap
;
617 const LocaleDataWrapper
& SvXMLNumImpData::GetLocaleData( LanguageType nLang
)
621 //pLocaleData = new LocaleDataWrapper(
622 // (pFormatter ? pFormatter->GetServiceManager() :
623 // ::comphelper::getProcessServiceFactory()),
624 // MsLangId::convertLanguageToLocale( nLang ) );
625 pLocaleData
= new LocaleDataWrapper(
626 (pFormatter
? pFormatter
->GetServiceManager() :
628 MsLangId::convertLanguageToLocale( nLang
) );
630 pLocaleData
->setLocale( MsLangId::convertLanguageToLocale( nLang
) );
634 //-------------------------------------------------------------------------
637 // SvXMLNumFmtMapContext
640 SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport
& rImport
,
641 USHORT nPrfx
, const rtl::OUString
& rLName
,
642 SvXMLNumFormatContext
& rParentContext
,
643 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
644 SvXMLImportContext( rImport
, nPrfx
, rLName
),
645 rParent( rParentContext
)
647 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
648 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
650 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
651 OUString sValue
= xAttrList
->getValueByIndex( i
);
653 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
654 if ( nPrefix
== XML_NAMESPACE_STYLE
)
656 if ( IsXMLToken( aLocalName
, XML_CONDITION
) )
658 else if ( IsXMLToken( aLocalName
, XML_APPLY_STYLE_NAME
) )
664 SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext()
668 SvXMLImportContext
* SvXMLNumFmtMapContext::CreateChildContext(
669 USHORT nPrfx
, const rtl::OUString
& rLName
,
670 const uno::Reference
<xml::sax::XAttributeList
>& )
672 // no elements supported - use default context
673 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
676 void SvXMLNumFmtMapContext::Characters( const rtl::OUString
& )
680 void SvXMLNumFmtMapContext::EndElement()
682 rParent
.AddCondition( sCondition
, sName
);
685 //-------------------------------------------------------------------------
688 // SvXMLNumFmtPropContext
691 SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport
& rImport
,
692 USHORT nPrfx
, const rtl::OUString
& rLName
,
693 SvXMLNumFormatContext
& rParentContext
,
694 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
695 SvXMLImportContext( rImport
, nPrfx
, rLName
),
696 rParent( rParentContext
),
699 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
700 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
702 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
703 OUString sValue
= xAttrList
->getValueByIndex( i
);
705 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
706 if ( nPrefix
== XML_NAMESPACE_FO
&& IsXMLToken( aLocalName
, XML_COLOR
) )
707 bColSet
= SvXMLUnitConverter::convertColor( aColor
, sValue
);
711 SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext()
715 SvXMLImportContext
* SvXMLNumFmtPropContext::CreateChildContext(
716 USHORT nPrfx
, const rtl::OUString
& rLName
,
717 const uno::Reference
<xml::sax::XAttributeList
>& )
719 // no elements supported - use default context
720 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
723 void SvXMLNumFmtPropContext::Characters( const rtl::OUString
& )
727 void SvXMLNumFmtPropContext::EndElement()
730 rParent
.AddColor( aColor
);
733 //-------------------------------------------------------------------------
736 // SvXMLNumFmtEmbeddedTextContext
739 SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport
& rImport
,
740 USHORT nPrfx
, const rtl::OUString
& rLName
,
741 SvXMLNumFmtElementContext
& rParentContext
,
742 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
743 SvXMLImportContext( rImport
, nPrfx
, rLName
),
744 rParent( rParentContext
),
749 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
750 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
752 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
753 OUString sValue
= xAttrList
->getValueByIndex( i
);
755 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
756 if ( nPrefix
== XML_NAMESPACE_NUMBER
&& IsXMLToken( aLocalName
, XML_POSITION
) )
758 if ( SvXMLUnitConverter::convertNumber( nAttrVal
, sValue
, 0 ) )
759 nTextPosition
= nAttrVal
;
764 SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext()
768 SvXMLImportContext
* SvXMLNumFmtEmbeddedTextContext::CreateChildContext(
769 USHORT nPrfx
, const rtl::OUString
& rLName
,
770 const uno::Reference
<xml::sax::XAttributeList
>& )
772 // no elements supported - use default context
773 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
776 void SvXMLNumFmtEmbeddedTextContext::Characters( const rtl::OUString
& rChars
)
778 aContent
.append( rChars
);
781 void SvXMLNumFmtEmbeddedTextContext::EndElement()
783 rParent
.AddEmbeddedElement( nTextPosition
, aContent
.makeStringAndClear() );
786 //-------------------------------------------------------------------------
788 sal_Bool
lcl_ValidChar( sal_Unicode cChar
, const SvXMLNumFormatContext
& rParent
)
790 sal_uInt16 nFormatType
= rParent
.GetType();
792 // Treat space equal to non-breaking space separator.
793 const sal_Unicode cNBSP
= 0x00A0;
795 if ( ( nFormatType
== XML_TOK_STYLES_NUMBER_STYLE
||
796 nFormatType
== XML_TOK_STYLES_CURRENCY_STYLE
||
797 nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
) &&
798 (cChar
== (cTS
= rParent
.GetLocaleData().getNumThousandSep().GetChar(0)) ||
799 (cChar
== ' ' && cTS
== cNBSP
)) )
801 // #i22394# Extra occurrences of thousands separator must be quoted, so they
802 // aren't mis-interpreted as display-factor.
803 // This must be limited to the format types that can contain a number element,
804 // because the same character can be a date separator that should not be quoted
807 return sal_False
; // force quotes
810 // see ImpSvNumberformatScan::Next_Symbol
818 return sal_True
; // for all format types
820 // percent sign must be used without quotes for percentage styles only
821 if ( nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
&& cChar
== '%' )
824 // don't put quotes around single parentheses (often used for negative numbers)
825 if ( ( nFormatType
== XML_TOK_STYLES_NUMBER_STYLE
||
826 nFormatType
== XML_TOK_STYLES_CURRENCY_STYLE
||
827 nFormatType
== XML_TOK_STYLES_PERCENTAGE_STYLE
) &&
828 ( cChar
== '(' || cChar
== ')' ) )
834 void lcl_EnquoteIfNecessary( rtl::OUStringBuffer
& rContent
, const SvXMLNumFormatContext
& rParent
)
836 sal_Bool bQuote
= sal_True
;
837 sal_Int32 nLength
= rContent
.getLength();
839 if ( ( nLength
== 1 &&
840 lcl_ValidChar( rContent
.charAt(0), rParent
) ) ||
842 lcl_ValidChar( rContent
.charAt(0), rParent
) &&
843 rContent
.charAt(1) == ' ' ) )
845 // don't quote single separator characters like space or percent,
846 // or separator characters followed by space (used in date formats)
849 else if ( rParent
.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE
&& nLength
> 1 )
851 // the percent character in percentage styles must be left out of quoting
852 // (one occurence is enough even if there are several percent characters in the string)
854 rtl::OUString
aString( rContent
.getStr() );
855 sal_Int32 nPos
= aString
.indexOf( (sal_Unicode
) '%' );
858 if ( nPos
+ 1 < nLength
)
860 if ( nPos
+ 2 == nLength
&& lcl_ValidChar( rContent
.charAt(nPos
+ 1), rParent
) )
862 // single character that doesn't need quoting
866 // quote text behind percent character
867 rContent
.insert( nPos
+ 1, (sal_Unicode
) '"' );
868 rContent
.append( (sal_Unicode
) '"' );
873 if ( nPos
== 1 && lcl_ValidChar( rContent
.charAt(0), rParent
) )
875 // single character that doesn't need quoting
879 // quote text before percent character
880 rContent
.insert( nPos
, (sal_Unicode
) '"' );
881 rContent
.insert( 0, (sal_Unicode
) '"' );
886 // else: normal quoting (below)
891 // #i55469# quotes in the string itself have to be escaped
892 rtl::OUString
aString( rContent
.getStr() );
893 bool bEscape
= ( aString
.indexOf( (sal_Unicode
) '"' ) >= 0 );
896 // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
897 // and a quote to resume quoting.
898 rtl::OUString
aInsert( rtl::OUString::createFromAscii( "\"\\\"" ) );
901 while ( nPos
< rContent
.getLength() )
903 if ( rContent
.charAt( nPos
) == (sal_Unicode
) '"' )
905 rContent
.insert( nPos
, aInsert
);
906 nPos
+= aInsert
.getLength();
912 // quote string literals
913 rContent
.insert( 0, (sal_Unicode
) '"' );
914 rContent
.append( (sal_Unicode
) '"' );
916 // remove redundant double quotes at start or end
919 if ( rContent
.getLength() > 2 &&
920 rContent
.charAt(0) == (sal_Unicode
) '"' &&
921 rContent
.charAt(1) == (sal_Unicode
) '"' )
923 String
aTrimmed( rContent
.makeStringAndClear().copy(2) );
924 rContent
= rtl::OUStringBuffer( aTrimmed
);
927 sal_Int32 nLen
= rContent
.getLength();
929 rContent
.charAt(nLen
-1) == (sal_Unicode
) '"' &&
930 rContent
.charAt(nLen
-2) == (sal_Unicode
) '"' )
932 String
aTrimmed( rContent
.makeStringAndClear().copy( 0, nLen
- 2 ) );
933 rContent
= rtl::OUStringBuffer( aTrimmed
);
940 // SvXMLNumFmtElementContext
943 SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport
& rImport
,
944 USHORT nPrfx
, const rtl::OUString
& rLName
,
945 SvXMLNumFormatContext
& rParentContext
, sal_uInt16 nNewType
,
946 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
) :
947 SvXMLImportContext( rImport
, nPrfx
, rLName
),
948 rParent( rParentContext
),
950 nElementLang( LANGUAGE_SYSTEM
),
954 OUString sLanguage
, sCountry
;
957 sal_uInt16 nAttrEnum
;
960 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
961 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
963 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
964 OUString sValue
= xAttrList
->getValueByIndex( i
);
966 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
968 const SvXMLTokenMap
& rTokenMap
= rParent
.GetData()->GetStyleElemAttrTokenMap();
969 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, aLocalName
);
973 case XML_TOK_ELEM_ATTR_DECIMAL_PLACES
:
974 if ( SvXMLUnitConverter::convertNumber( nAttrVal
, sValue
, 0 ) )
975 aNumInfo
.nDecimals
= nAttrVal
;
977 case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS
:
978 if ( SvXMLUnitConverter::convertNumber( nAttrVal
, sValue
, 0 ) )
979 aNumInfo
.nInteger
= nAttrVal
;
981 case XML_TOK_ELEM_ATTR_GROUPING
:
982 if ( SvXMLUnitConverter::convertBool( bAttrBool
, sValue
) )
983 aNumInfo
.bGrouping
= bAttrBool
;
985 case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR
:
986 if ( SvXMLUnitConverter::convertDouble( fAttrDouble
, sValue
) )
987 aNumInfo
.fDisplayFactor
= fAttrDouble
;
989 case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT
:
990 if ( sValue
.getLength() > 0 )
991 aNumInfo
.bDecReplace
= sal_True
; // only a default string is supported
993 aNumInfo
.bVarDecimals
= sal_True
; // empty replacement string: variable decimals
995 case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS
:
996 if ( SvXMLUnitConverter::convertNumber( nAttrVal
, sValue
, 0 ) )
997 aNumInfo
.nExpDigits
= nAttrVal
;
999 case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS
:
1000 if ( SvXMLUnitConverter::convertNumber( nAttrVal
, sValue
, 0 ) )
1001 aNumInfo
.nNumerDigits
= nAttrVal
;
1003 case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS
:
1004 if ( SvXMLUnitConverter::convertNumber( nAttrVal
, sValue
, 0 ) )
1005 aNumInfo
.nDenomDigits
= nAttrVal
;
1007 case XML_TOK_ELEM_ATTR_LANGUAGE
:
1010 case XML_TOK_ELEM_ATTR_COUNTRY
:
1013 case XML_TOK_ELEM_ATTR_STYLE
:
1014 if ( SvXMLUnitConverter::convertEnum( nAttrEnum
, sValue
, aStyleValueMap
) )
1015 bLong
= (sal_Bool
) nAttrEnum
;
1017 case XML_TOK_ELEM_ATTR_TEXTUAL
:
1018 if ( SvXMLUnitConverter::convertBool( bAttrBool
, sValue
) )
1019 bTextual
= bAttrBool
;
1021 case XML_TOK_ELEM_ATTR_CALENDAR
:
1027 if ( sLanguage
.getLength() || sCountry
.getLength() )
1029 nElementLang
= MsLangId::convertIsoNamesToLanguage( sLanguage
, sCountry
);
1030 if ( nElementLang
== LANGUAGE_DONTKNOW
)
1031 nElementLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1035 SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext()
1039 SvXMLImportContext
* SvXMLNumFmtElementContext::CreateChildContext(
1040 USHORT nPrfx
, const rtl::OUString
& rLName
,
1041 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
)
1043 // only number:number supports number:embedded-text child element
1045 if ( nType
== XML_TOK_STYLE_NUMBER
&&
1046 nPrfx
== XML_NAMESPACE_NUMBER
&& IsXMLToken( rLName
, XML_EMBEDDED_TEXT
) )
1048 return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx
, rLName
, *this, xAttrList
);
1051 return new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
1054 void SvXMLNumFmtElementContext::Characters( const rtl::OUString
& rChars
)
1056 aContent
.append( rChars
);
1059 void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos
, const rtl::OUString
& rContent
)
1061 if ( rContent
.getLength() )
1063 SvXMLEmbeddedElement
* pObj
= new SvXMLEmbeddedElement( nFormatPos
, rContent
);
1064 if ( !aNumInfo
.aEmbeddedElements
.Insert( pObj
) )
1066 // there's already an element at this position - append text to existing element
1069 USHORT nElementCount
= aNumInfo
.aEmbeddedElements
.Count();
1070 for (USHORT i
=0; i
<nElementCount
; i
++)
1072 pObj
= aNumInfo
.aEmbeddedElements
[i
];
1073 if ( pObj
->nFormatPos
== nFormatPos
)
1075 pObj
->aText
+= rContent
;
1083 void SvXMLNumFmtElementContext::EndElement()
1085 sal_Bool bEffLong
= bLong
;
1088 case XML_TOK_STYLE_TEXT
:
1089 if ( rParent
.HasLongDoW() &&
1090 rParent
.GetLocaleData().getLongDateDayOfWeekSep() ==
1091 String( aContent
.getStr() ) )
1093 // skip separator constant after long day of week
1094 // (NF_KEY_NNNN contains the separator)
1096 if ( rParent
.ReplaceNfKeyword( NF_KEY_NNN
, NF_KEY_NNNN
) )
1098 //!aContent.setLength(0); //! doesn't work, #76293#
1099 aContent
= OUStringBuffer();
1102 rParent
.SetHasLongDoW( sal_False
); // only once
1104 if ( aContent
.getLength() )
1106 lcl_EnquoteIfNecessary( aContent
, rParent
);
1107 rParent
.AddToCode( aContent
.makeStringAndClear() );
1111 case XML_TOK_STYLE_NUMBER
:
1112 rParent
.AddNumber( aNumInfo
);
1115 case XML_TOK_STYLE_CURRENCY_SYMBOL
:
1116 rParent
.AddCurrency( aContent
.makeStringAndClear(), nElementLang
);
1119 case XML_TOK_STYLE_TEXT_CONTENT
:
1120 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'@') );
1122 case XML_TOK_STYLE_BOOLEAN
:
1123 // ignored - only default boolean format is supported
1126 case XML_TOK_STYLE_DAY
:
1127 rParent
.UpdateCalendar( sCalendar
);
1129 //! I18N doesn't provide SYSTEM or extended date information yet
1130 if ( rParent
.IsFromSystem() )
1131 bEffLong
= SvXMLNumFmtDefaults::IsSystemLongDay( rParent
.GetInternational(), bLong
);
1133 rParent
.AddNfKeyword(
1134 sal::static_int_cast
< sal_uInt16
>(
1135 bEffLong
? NF_KEY_DD
: NF_KEY_D
) );
1137 case XML_TOK_STYLE_MONTH
:
1138 rParent
.UpdateCalendar( sCalendar
);
1140 //! I18N doesn't provide SYSTEM or extended date information yet
1141 if ( rParent
.IsFromSystem() )
1143 bEffLong
= SvXMLNumFmtDefaults::IsSystemLongMonth( rParent
.GetInternational(), bLong
);
1144 bTextual
= SvXMLNumFmtDefaults::IsSystemTextualMonth( rParent
.GetInternational(), bLong
);
1147 rParent
.AddNfKeyword(
1148 sal::static_int_cast
< sal_uInt16
>(
1150 ? ( bEffLong
? NF_KEY_MMMM
: NF_KEY_MMM
)
1151 : ( bEffLong
? NF_KEY_MM
: NF_KEY_M
) ) );
1153 case XML_TOK_STYLE_YEAR
:
1154 rParent
.UpdateCalendar( sCalendar
);
1156 //! I18N doesn't provide SYSTEM or extended date information yet
1157 if ( rParent
.IsFromSystem() )
1158 bEffLong
= SvXMLNumFmtDefaults::IsSystemLongYear( rParent
.GetInternational(), bLong
);
1160 // Y after G (era) is replaced by E
1161 if ( rParent
.HasEra() )
1162 rParent
.AddNfKeyword(
1163 sal::static_int_cast
< sal_uInt16
>(
1164 bEffLong
? NF_KEY_EEC
: NF_KEY_EC
) );
1166 rParent
.AddNfKeyword(
1167 sal::static_int_cast
< sal_uInt16
>(
1168 bEffLong
? NF_KEY_YYYY
: NF_KEY_YY
) );
1170 case XML_TOK_STYLE_ERA
:
1171 rParent
.UpdateCalendar( sCalendar
);
1173 //! I18N doesn't provide SYSTEM or extended date information yet
1174 if ( rParent
.IsFromSystem() )
1175 bEffLong
= SvXMLNumFmtDefaults::IsSystemLongEra( rParent
.GetInternational(), bLong
);
1177 rParent
.AddNfKeyword(
1178 sal::static_int_cast
< sal_uInt16
>(
1179 bEffLong
? NF_KEY_GGG
: NF_KEY_G
) );
1180 // HasEra flag is set
1182 case XML_TOK_STYLE_DAY_OF_WEEK
:
1183 rParent
.UpdateCalendar( sCalendar
);
1185 //! I18N doesn't provide SYSTEM or extended date information yet
1186 if ( rParent
.IsFromSystem() )
1187 bEffLong
= SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( rParent
.GetInternational(), bLong
);
1189 rParent
.AddNfKeyword(
1190 sal::static_int_cast
< sal_uInt16
>(
1191 bEffLong
? NF_KEY_NNNN
: NF_KEY_NN
) );
1193 case XML_TOK_STYLE_WEEK_OF_YEAR
:
1194 rParent
.UpdateCalendar( sCalendar
);
1195 rParent
.AddNfKeyword( NF_KEY_WW
);
1197 case XML_TOK_STYLE_QUARTER
:
1198 rParent
.UpdateCalendar( sCalendar
);
1199 rParent
.AddNfKeyword(
1200 sal::static_int_cast
< sal_uInt16
>(
1201 bEffLong
? NF_KEY_QQ
: NF_KEY_Q
) );
1203 case XML_TOK_STYLE_HOURS
:
1204 rParent
.AddNfKeyword(
1205 sal::static_int_cast
< sal_uInt16
>(
1206 bEffLong
? NF_KEY_HH
: NF_KEY_H
) );
1208 case XML_TOK_STYLE_AM_PM
:
1210 rParent
.AddNfKeyword( NF_KEY_AMPM
);
1212 case XML_TOK_STYLE_MINUTES
:
1213 rParent
.AddNfKeyword(
1214 sal::static_int_cast
< sal_uInt16
>(
1215 bEffLong
? NF_KEY_MMI
: NF_KEY_MI
) );
1217 case XML_TOK_STYLE_SECONDS
:
1218 rParent
.AddNfKeyword(
1219 sal::static_int_cast
< sal_uInt16
>(
1220 bEffLong
? NF_KEY_SS
: NF_KEY_S
) );
1221 if ( aNumInfo
.nDecimals
> 0 )
1223 // manually add the decimal places
1224 const String
& rSep
= rParent
.GetLocaleData().getNumDecimalSep();
1225 for ( xub_StrLen j
=0; j
<rSep
.Len(); j
++ )
1227 rParent
.AddToCode( OUString::valueOf( rSep
.GetChar(j
) ) );
1229 for (sal_Int32 i
=0; i
<aNumInfo
.nDecimals
; i
++)
1230 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'0') );
1234 case XML_TOK_STYLE_FRACTION
:
1236 if ( aNumInfo
.nInteger
>= 0 )
1238 // add integer part only if min-integer-digits attribute is there
1239 aNumInfo
.nDecimals
= 0;
1240 rParent
.AddNumber( aNumInfo
); // number without decimals
1241 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)' ') );
1244 //! build string and add at once
1247 for (i
=0; i
<aNumInfo
.nNumerDigits
; i
++)
1248 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'?') );
1249 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'/') );
1250 for (i
=0; i
<aNumInfo
.nDenomDigits
; i
++)
1251 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'?') );
1255 case XML_TOK_STYLE_SCIENTIFIC_NUMBER
:
1257 rParent
.AddNumber( aNumInfo
); // simple number
1259 rParent
.AddToCode( OUString::createFromAscii( "E+" ) );
1260 for (sal_Int32 i
=0; i
<aNumInfo
.nExpDigits
; i
++)
1261 rParent
.AddToCode( OUString::valueOf((sal_Unicode
)'0') );
1266 DBG_ERROR("invalid element ID");
1270 //-------------------------------------------------------------------------
1272 sal_Bool
SvXMLNumFmtDefaults::IsSystemLongDay( const SvtSysLocale
&, BOOL bLong
)
1274 // TODO: merge system information and defaults into i18n locale data
1276 return bLong
? rIntn
.IsLongDateDayLeadingZero() : rIntn
.IsDateDayLeadingZero();
1282 sal_Bool
SvXMLNumFmtDefaults::IsSystemLongMonth( const SvtSysLocale
&, BOOL bLong
)
1284 // TODO: merge system information and defaults into i18n locale data
1288 MonthFormat eMonth
= rIntn
.GetLongDateMonthFormat();
1289 return ( eMonth
== MONTH_ZERO
|| eMonth
== MONTH_LONG
);
1292 return rIntn
.IsDateMonthLeadingZero();
1298 sal_Bool
SvXMLNumFmtDefaults::IsSystemTextualMonth( const SvtSysLocale
&, BOOL bLong
)
1300 // TODO: merge system information and defaults into i18n locale data
1304 MonthFormat eMonth
= rIntn
.GetLongDateMonthFormat();
1305 return ( eMonth
== MONTH_SHORT
|| eMonth
== MONTH_LONG
);
1314 sal_Bool
SvXMLNumFmtDefaults::IsSystemLongYear( const SvtSysLocale
&, BOOL bLong
)
1316 // TODO: merge system information and defaults into i18n locale data
1318 return bLong
? rIntn
.IsLongDateCentury() : rIntn
.IsDateCentury();
1324 sal_Bool
SvXMLNumFmtDefaults::IsSystemLongEra( const SvtSysLocale
& rSysLoc
, BOOL bLong
)
1326 // TODO: merge system information and defaults into i18n locale data
1327 return IsSystemLongYear( rSysLoc
, bLong
); // no separate setting
1330 sal_Bool
SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( const SvtSysLocale
&, BOOL bLong
)
1332 // TODO: merge system information and defaults into i18n locale data
1334 return ( bLong
&& rIntn
.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG
);
1336 return bLong
&& true;
1340 sal_uInt16
SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW
,
1341 SvXMLDateElementAttributes eDay
, SvXMLDateElementAttributes eMonth
,
1342 SvXMLDateElementAttributes eYear
, SvXMLDateElementAttributes eHours
,
1343 SvXMLDateElementAttributes eMins
, SvXMLDateElementAttributes eSecs
,
1346 const sal_uInt16 nCount
= sizeof(aDefaultDateFormats
) / sizeof(SvXMLDefaultDateFormat
);
1347 for (sal_uInt16 nPos
=0; nPos
<nCount
; nPos
++)
1349 const SvXMLDefaultDateFormat
& rEntry
= aDefaultDateFormats
[nPos
];
1350 if ( bSystem
== rEntry
.bSystem
&&
1351 ( eDOW
== rEntry
.eDOW
|| ( rEntry
.eDOW
== XML_DEA_ANY
&& eDOW
!= XML_DEA_NONE
) ) &&
1352 ( eDay
== rEntry
.eDay
|| ( rEntry
.eDay
== XML_DEA_ANY
&& eDay
!= XML_DEA_NONE
) ) &&
1353 ( eMonth
== rEntry
.eMonth
|| ( rEntry
.eMonth
== XML_DEA_ANY
&& eMonth
!= XML_DEA_NONE
) ) &&
1354 ( eYear
== rEntry
.eYear
|| ( rEntry
.eYear
== XML_DEA_ANY
&& eYear
!= XML_DEA_NONE
) ) &&
1355 ( eHours
== rEntry
.eHours
|| ( rEntry
.eHours
== XML_DEA_ANY
&& eHours
!= XML_DEA_NONE
) ) &&
1356 ( eMins
== rEntry
.eMins
|| ( rEntry
.eMins
== XML_DEA_ANY
&& eMins
!= XML_DEA_NONE
) ) &&
1357 ( eSecs
== rEntry
.eSecs
|| ( rEntry
.eSecs
== XML_DEA_ANY
&& eSecs
!= XML_DEA_NONE
) ) )
1359 return sal::static_int_cast
< sal_uInt16
>(rEntry
.eFormat
);
1363 return NF_INDEX_TABLE_ENTRIES
; // invalid
1366 //-------------------------------------------------------------------------
1369 // SvXMLNumFormatContext
1372 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport
& rImport
,
1373 USHORT nPrfx
, const rtl::OUString
& rLName
,
1374 SvXMLNumImpData
* pNewData
, sal_uInt16 nNewType
,
1375 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
1376 SvXMLStylesContext
& rStyles
) :
1377 SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
),
1379 pStyles( &rStyles
),
1383 nFormatLang( LANGUAGE_SYSTEM
),
1384 bAutoOrder( FALSE
),
1385 bFromSystem( FALSE
),
1389 bHasExtraText( FALSE
),
1390 bHasLongDoW( FALSE
),
1392 bHasDateTime( FALSE
),
1393 bRemoveAfterUse( sal_False
),
1394 eDateDOW( XML_DEA_NONE
),
1395 eDateDay( XML_DEA_NONE
),
1396 eDateMonth( XML_DEA_NONE
),
1397 eDateYear( XML_DEA_NONE
),
1398 eDateHours( XML_DEA_NONE
),
1399 eDateMins( XML_DEA_NONE
),
1400 eDateSecs( XML_DEA_NONE
),
1401 bDateNoDefault( sal_False
)
1403 OUString sLanguage
, sCountry
;
1404 ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr
;
1406 sal_uInt16 nAttrEnum
;
1408 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
1409 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
1411 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
1412 OUString sValue
= xAttrList
->getValueByIndex( i
);
1413 OUString aLocalName
;
1414 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().GetKeyByAttrName( sAttrName
, &aLocalName
);
1416 const SvXMLTokenMap
& rTokenMap
= pData
->GetStyleAttrTokenMap();
1417 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, aLocalName
);
1420 case XML_TOK_STYLE_ATTR_NAME
:
1423 case XML_TOK_STYLE_ATTR_LANGUAGE
:
1426 case XML_TOK_STYLE_ATTR_COUNTRY
:
1429 case XML_TOK_STYLE_ATTR_TITLE
:
1430 sFormatTitle
= sValue
;
1432 case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER
:
1433 if ( SvXMLUnitConverter::convertBool( bAttrBool
, sValue
) )
1434 bAutoOrder
= bAttrBool
;
1436 case XML_TOK_STYLE_ATTR_FORMAT_SOURCE
:
1437 if ( SvXMLUnitConverter::convertEnum( nAttrEnum
, sValue
, aFormatSourceMap
) )
1438 bFromSystem
= (sal_Bool
) nAttrEnum
;
1440 case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW
:
1441 if ( SvXMLUnitConverter::convertBool( bAttrBool
, sValue
) )
1442 bTruncate
= bAttrBool
;
1444 case XML_TOK_STYLE_ATTR_VOLATILE
:
1445 // volatile formats can be removed after importing
1446 // if not used in other styles
1447 if ( SvXMLUnitConverter::convertBool( bAttrBool
, sValue
) )
1448 bRemoveAfterUse
= bAttrBool
;
1450 case XML_TOK_STYLE_ATTR_TRANSL_FORMAT
:
1451 aNatNumAttr
.Format
= sValue
;
1453 case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE
:
1454 aNatNumAttr
.Locale
.Language
= sValue
;
1456 case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY
:
1457 aNatNumAttr
.Locale
.Country
= sValue
;
1459 case XML_TOK_STYLE_ATTR_TRANSL_STYLE
:
1460 aNatNumAttr
.Style
= sValue
;
1465 if ( sLanguage
.getLength() || sCountry
.getLength() )
1467 nFormatLang
= MsLangId::convertIsoNamesToLanguage( sLanguage
, sCountry
);
1468 if ( nFormatLang
== LANGUAGE_DONTKNOW
)
1469 nFormatLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1472 if ( aNatNumAttr
.Format
.getLength() )
1474 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1477 sal_Int32 nNatNum
= pFormatter
->GetNatNum()->convertFromXmlAttributes( aNatNumAttr
);
1478 aFormatCode
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "[NatNum" ) );
1479 aFormatCode
.append( nNatNum
, 10 );
1481 LanguageType eLang
= MsLangId::convertLocaleToLanguage( aNatNumAttr
.Locale
);
1482 if ( eLang
== LANGUAGE_DONTKNOW
)
1483 eLang
= LANGUAGE_SYSTEM
; //! error handling for invalid locales?
1484 if ( eLang
!= nFormatLang
&& eLang
!= LANGUAGE_SYSTEM
)
1486 aFormatCode
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "][$-" ) );
1487 // language code in upper hex:
1488 aFormatCode
.append( String::CreateFromInt32( sal_Int32( eLang
), 16 ).ToUpperAscii() );
1490 aFormatCode
.append( sal_Unicode(']') );
1495 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport
& rImport
,
1496 USHORT nPrfx
, const rtl::OUString
& rLName
,
1497 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
1498 const sal_Int32 nTempKey
,
1499 SvXMLStylesContext
& rStyles
) :
1500 SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
, XML_STYLE_FAMILY_DATA_STYLE
),
1502 pStyles( &rStyles
),
1506 nFormatLang( LANGUAGE_SYSTEM
),
1507 bAutoOrder( FALSE
),
1508 bFromSystem( FALSE
),
1512 bHasExtraText( FALSE
),
1513 bHasLongDoW( FALSE
),
1515 bHasDateTime( FALSE
),
1516 bRemoveAfterUse( sal_False
),
1517 eDateDOW( XML_DEA_NONE
),
1518 eDateDay( XML_DEA_NONE
),
1519 eDateMonth( XML_DEA_NONE
),
1520 eDateYear( XML_DEA_NONE
),
1521 eDateHours( XML_DEA_NONE
),
1522 eDateMins( XML_DEA_NONE
),
1523 eDateSecs( XML_DEA_NONE
),
1524 bDateNoDefault( sal_False
)
1526 SetAttribute(XML_NAMESPACE_STYLE
, GetXMLToken(XML_NAME
), rLName
);
1529 SvXMLNumFormatContext::~SvXMLNumFormatContext()
1533 SvXMLImportContext
* SvXMLNumFormatContext::CreateChildContext(
1534 USHORT nPrfx
, const rtl::OUString
& rLName
,
1535 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
)
1537 SvXMLImportContext
* pContext
= NULL
;
1539 const SvXMLTokenMap
& rTokenMap
= pData
->GetStyleElemTokenMap();
1540 sal_uInt16 nToken
= rTokenMap
.Get( nPrfx
, rLName
);
1543 case XML_TOK_STYLE_TEXT
:
1544 case XML_TOK_STYLE_NUMBER
:
1545 case XML_TOK_STYLE_SCIENTIFIC_NUMBER
:
1546 case XML_TOK_STYLE_FRACTION
:
1547 case XML_TOK_STYLE_CURRENCY_SYMBOL
:
1548 case XML_TOK_STYLE_DAY
:
1549 case XML_TOK_STYLE_MONTH
:
1550 case XML_TOK_STYLE_YEAR
:
1551 case XML_TOK_STYLE_ERA
:
1552 case XML_TOK_STYLE_DAY_OF_WEEK
:
1553 case XML_TOK_STYLE_WEEK_OF_YEAR
:
1554 case XML_TOK_STYLE_QUARTER
:
1555 case XML_TOK_STYLE_HOURS
:
1556 case XML_TOK_STYLE_AM_PM
:
1557 case XML_TOK_STYLE_MINUTES
:
1558 case XML_TOK_STYLE_SECONDS
:
1559 case XML_TOK_STYLE_BOOLEAN
:
1560 case XML_TOK_STYLE_TEXT_CONTENT
:
1561 pContext
= new SvXMLNumFmtElementContext( GetImport(), nPrfx
, rLName
,
1562 *this, nToken
, xAttrList
);
1565 case XML_TOK_STYLE_PROPERTIES
:
1566 pContext
= new SvXMLNumFmtPropContext( GetImport(), nPrfx
, rLName
,
1569 case XML_TOK_STYLE_MAP
:
1571 // SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
1572 // so there's no need for an extra flag
1573 pContext
= new SvXMLNumFmtMapContext( GetImport(), nPrfx
, rLName
,
1580 pContext
= new SvXMLImportContext( GetImport(), nPrfx
, rLName
);
1584 sal_Int32
SvXMLNumFormatContext::GetKey()
1588 if (bRemoveAfterUse
)
1590 // format is used -> don't remove
1591 bRemoveAfterUse
= sal_False
;
1593 pData
->SetUsed(nKey
);
1595 // Add to import's list of keys now - CreateAndInsert didn't add
1596 // the style if bRemoveAfterUse was set.
1597 GetImport().AddNumberStyle( nKey
, GetName() );
1603 // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
1604 bRemoveAfterUse
= sal_False
;
1605 CreateAndInsert(sal_True
);
1610 sal_Int32
SvXMLNumFormatContext::PrivateGetKey()
1612 // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
1618 CreateAndInsert(sal_True
);
1623 sal_Int32
SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference
< com::sun::star::util::XNumberFormatsSupplier
>& xFormatsSupplier
)
1627 SvNumberFormatter
* pFormatter
= NULL
;
1628 SvNumberFormatsSupplierObj
* pObj
=
1629 SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier
);
1631 pFormatter
= pObj
->GetNumberFormatter();
1634 return CreateAndInsert( pFormatter
);
1642 void SvXMLNumFormatContext::CreateAndInsert(sal_Bool
/*bOverwrite*/)
1645 CreateAndInsert(pData
->GetNumberFormatter());
1648 sal_Int32
SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter
* pFormatter
)
1652 DBG_ERROR("no number formatter");
1656 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1658 for (sal_uInt32 i
= 0; i
< aMyConditions
.size(); i
++)
1660 SvXMLNumFormatContext
* pStyle
= (SvXMLNumFormatContext
*)pStyles
->FindStyleChildContext(
1661 XML_STYLE_FAMILY_DATA_STYLE
, aMyConditions
[i
].sMapName
, sal_False
);
1664 if ((pStyle
->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag
1669 if ( !aFormatCode
.getLength() )
1671 // insert empty format as empty string (with quotes)
1672 // #93901# this check has to be done before inserting the conditions
1673 aFormatCode
.appendAscii("\"\""); // ""
1676 aFormatCode
.insert( 0, aConditions
.makeStringAndClear() );
1677 OUString sFormat
= aFormatCode
.makeStringAndClear();
1679 // test special cases
1681 if ( bAutoDec
) // automatic decimal places
1683 // #99391# adjust only if the format contains no text elements, no conditions
1684 // and no color definition (detected by the '[' at the start)
1686 if ( nType
== XML_TOK_STYLES_NUMBER_STYLE
&& !bHasExtraText
&&
1687 aMyConditions
.size() == 0 && sFormat
.toChar() != (sal_Unicode
)'[' )
1688 nIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1690 if ( bAutoInt
) // automatic integer digits
1692 //! only if two decimal places was set?
1694 if ( nType
== XML_TOK_STYLES_NUMBER_STYLE
&& !bHasExtraText
&&
1695 aMyConditions
.size() == 0 && sFormat
.toChar() != (sal_Unicode
)'[' )
1696 nIndex
= pFormatter
->GetFormatIndex( NF_NUMBER_SYSTEM
, nFormatLang
);
1699 // boolean is always the builtin boolean format
1700 // (no other boolean formats are implemented)
1701 if ( nType
== XML_TOK_STYLES_BOOLEAN_STYLE
)
1702 nIndex
= pFormatter
->GetFormatIndex( NF_BOOLEAN
, nFormatLang
);
1704 // check for default date formats
1705 if ( nType
== XML_TOK_STYLES_DATE_STYLE
&& bAutoOrder
&& !bDateNoDefault
)
1707 NfIndexTableOffset eFormat
= (NfIndexTableOffset
) SvXMLNumFmtDefaults::GetDefaultDateFormat(
1708 eDateDOW
, eDateDay
, eDateMonth
, eDateYear
,
1709 eDateHours
, eDateMins
, eDateSecs
, bFromSystem
);
1710 if ( eFormat
< NF_INDEX_TABLE_ENTRIES
)
1712 // #109651# if a date format has the automatic-order attribute and
1713 // contains exactly the elements of one of the default date formats,
1714 // use that default format, with the element order and separators
1715 // from the current locale settings
1717 nIndex
= pFormatter
->GetFormatIndex( eFormat
, nFormatLang
);
1721 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
&& sFormat
.getLength() )
1723 // insert by format string
1725 String
aFormatStr( sFormat
);
1726 nIndex
= pFormatter
->GetEntryKey( aFormatStr
, nFormatLang
);
1727 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1729 xub_StrLen nErrPos
= 0;
1731 sal_Bool bOk
= pFormatter
->PutEntry( aFormatStr
, nErrPos
, l_nType
, nIndex
, nFormatLang
);
1732 if ( !bOk
&& nErrPos
== 0 && aFormatStr
!= String(sFormat
) )
1734 // if the string was modified by PutEntry, look for an existing format
1735 // with the modified string
1736 nIndex
= pFormatter
->GetEntryKey( aFormatStr
, nFormatLang
);
1737 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1741 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1746 //! I18N doesn't provide SYSTEM or extended date information yet
1747 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&& !bFromSystem
)
1749 // instead of automatic date format, use fixed formats if bFromSystem is not set
1750 //! prevent use of automatic formats in other cases, force user-defined format?
1752 sal_uInt32 nNewIndex
= nIndex
;
1754 NfIndexTableOffset eOffset
= pFormatter
->GetIndexTableOffset( nIndex
);
1755 if ( eOffset
== NF_DATE_SYSTEM_SHORT
)
1757 const International
& rInt
= pData
->GetInternational( nFormatLang
);
1758 if ( rInt
.IsDateDayLeadingZero() && rInt
.IsDateMonthLeadingZero() )
1760 if ( rInt
.IsDateCentury() )
1761 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, nFormatLang
);
1763 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYS_DDMMYY
, nFormatLang
);
1766 else if ( eOffset
== NF_DATE_SYSTEM_LONG
)
1768 const International
& rInt
= pData
->GetInternational( nFormatLang
);
1769 if ( !rInt
.IsLongDateDayLeadingZero() )
1771 sal_Bool bCentury
= rInt
.IsLongDateCentury();
1772 MonthFormat eMonth
= rInt
.GetLongDateMonthFormat();
1773 if ( eMonth
== MONTH_LONG
&& bCentury
)
1775 if ( rInt
.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG
)
1776 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYS_NNNNDMMMMYYYY
, nFormatLang
);
1778 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYS_NNDMMMMYYYY
, nFormatLang
);
1780 else if ( eMonth
== MONTH_SHORT
&& !bCentury
)
1781 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYS_NNDMMMYY
, nFormatLang
);
1785 if ( nNewIndex
!= nIndex
)
1787 // verify the fixed format really matches the format string
1788 // (not the case with some formats from locale data)
1790 const SvNumberformat
* pFixedFormat
= pFormatter
->GetEntry( nNewIndex
);
1791 if ( pFixedFormat
&& pFixedFormat
->GetFormatstring() == String(sFormat
) )
1797 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&& !bAutoOrder
)
1799 // use fixed-order formats instead of SYS... if bAutoOrder is false
1800 // (only if the format strings are equal for the locale)
1802 NfIndexTableOffset eOffset
= pFormatter
->GetIndexTableOffset( nIndex
);
1803 if ( eOffset
== NF_DATE_SYS_DMMMYYYY
)
1805 sal_uInt32 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_DIN_DMMMYYYY
, nFormatLang
);
1806 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nIndex
);
1807 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewIndex
);
1808 if ( pOldEntry
&& pNewEntry
&& pOldEntry
->GetFormatstring() == pNewEntry
->GetFormatstring() )
1811 else if ( eOffset
== NF_DATE_SYS_DMMMMYYYY
)
1813 sal_uInt32 nNewIndex
= pFormatter
->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY
, nFormatLang
);
1814 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nIndex
);
1815 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewIndex
);
1816 if ( pOldEntry
&& pNewEntry
&& pOldEntry
->GetFormatstring() == pNewEntry
->GetFormatstring() )
1821 if ((nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) && sFormatTitle
.getLength())
1823 SvNumberformat
* pFormat
= const_cast<SvNumberformat
*>(pFormatter
->GetEntry( nIndex
));
1826 String
sTitle (sFormatTitle
);
1827 pFormat
->SetComment(sTitle
);
1831 if ( nIndex
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1833 DBG_ERROR("invalid number format");
1834 nIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1837 pData
->AddKey( nIndex
, GetName(), bRemoveAfterUse
);
1840 // Add to import's list of keys (shared between styles and content import)
1841 // only if not volatile - formats are removed from NumberFormatter at the
1842 // end of each import (in SvXMLNumFmtHelper dtor).
1843 // If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there.
1845 if (!bRemoveAfterUse
)
1846 GetImport().AddNumberStyle( nKey
, GetName() );
1849 ByteString
aByte( String(sFormatName
), gsl_getSystemTextEncoding() );
1850 aByte
.Append( " | " );
1851 aByte
.Append(ByteString( String(sFormat
), gsl_getSystemTextEncoding() ));
1852 aByte
.Append( " | " );
1853 aByte
.Append(ByteString::CreateFromInt32( nIndex
));
1855 // DBG_ERROR(aByte.GetBuffer());
1862 void SvXMLNumFormatContext::Finish( sal_Bool bOverwrite
)
1864 SvXMLStyleContext::Finish( bOverwrite
);
1868 const LocaleDataWrapper
& SvXMLNumFormatContext::GetLocaleData() const
1870 return pData
->GetLocaleData( nFormatLang
);
1873 void SvXMLNumFormatContext::AddToCode( const rtl::OUString
& rString
)
1875 aFormatCode
.append( rString
);
1876 bHasExtraText
= sal_True
;
1879 void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo
& rInfo
)
1881 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
1885 // store special conditions
1886 bAutoDec
= ( rInfo
.nDecimals
< 0 );
1887 bAutoInt
= ( rInfo
.nInteger
< 0 );
1889 sal_uInt16 nPrec
= 0;
1890 sal_uInt16 nLeading
= 0;
1891 if ( rInfo
.nDecimals
>= 0 ) // < 0 : Default
1892 nPrec
= (sal_uInt16
) rInfo
.nDecimals
;
1893 if ( rInfo
.nInteger
>= 0 ) // < 0 : Default
1894 nLeading
= (sal_uInt16
) rInfo
.nInteger
;
1898 if ( nType
== XML_TOK_STYLES_CURRENCY_STYLE
)
1900 // for currency formats, "automatic decimals" is used for the automatic
1901 // currency format with (fixed) decimals from the locale settings
1903 const LocaleDataWrapper
& rLoc
= pData
->GetLocaleData( nFormatLang
);
1904 nPrec
= rLoc
.getCurrDigits();
1908 // for other types, "automatic decimals" means dynamic determination of
1909 // decimals, as achieved with the "general" keyword
1911 aFormatCode
.append( pFormatter
->GetStandardName( nFormatLang
) );
1920 sal_uInt16 nGenPrec
= nPrec
;
1921 if ( rInfo
.bDecReplace
|| rInfo
.bVarDecimals
)
1922 nGenPrec
= 0; // generate format without decimals...
1924 sal_Bool bGrouping
= rInfo
.bGrouping
;
1925 USHORT nEmbeddedCount
= rInfo
.aEmbeddedElements
.Count();
1926 if ( nEmbeddedCount
)
1927 bGrouping
= sal_False
; // grouping and embedded characters can't be used together
1930 sal_uInt32 nStdIndex
= pFormatter
->GetStandardIndex( nFormatLang
);
1931 pFormatter
->GenerateFormat( aNumStr
, nStdIndex
, nFormatLang
,
1932 bGrouping
, sal_False
, nGenPrec
, nLeading
);
1934 if ( rInfo
.nExpDigits
>= 0 && nLeading
== 0 && !bGrouping
&& nEmbeddedCount
== 0 )
1936 // #i43959# For scientific numbers, "#" in the integer part forces a digit,
1937 // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
1939 aNumStr
.EraseLeadingChars( (sal_Unicode
)'#' );
1942 if ( nEmbeddedCount
)
1944 // insert embedded strings into number string
1945 // only the integer part is supported
1946 // nZeroPos is the string position where format position 0 is inserted
1948 xub_StrLen nZeroPos
= aNumStr
.Search( pData
->GetLocaleData( nFormatLang
).getNumDecimalSep() );
1949 if ( nZeroPos
== STRING_NOTFOUND
)
1950 nZeroPos
= aNumStr
.Len();
1952 // aEmbeddedElements is sorted - last entry has the largest position (leftmost)
1953 const SvXMLEmbeddedElement
* pLastObj
= rInfo
.aEmbeddedElements
[nEmbeddedCount
- 1];
1954 sal_Int32 nLastFormatPos
= pLastObj
->nFormatPos
;
1955 if ( nLastFormatPos
>= nZeroPos
)
1957 // add '#' characters so all embedded texts are really embedded in digits
1958 // (there always has to be a digit before the leftmost embedded text)
1960 xub_StrLen nAddCount
= (xub_StrLen
)nLastFormatPos
+ 1 - nZeroPos
;
1962 aDigitStr
.Fill( nAddCount
, (sal_Unicode
)'#' );
1963 aNumStr
.Insert( aDigitStr
, 0 );
1964 nZeroPos
= nZeroPos
+ nAddCount
;
1967 // aEmbeddedElements is sorted with ascending positions - loop is from right to left
1968 for (USHORT nElement
= 0; nElement
< nEmbeddedCount
; nElement
++)
1970 const SvXMLEmbeddedElement
* pObj
= rInfo
.aEmbeddedElements
[nElement
];
1971 sal_Int32 nFormatPos
= pObj
->nFormatPos
;
1972 sal_Int32 nInsertPos
= nZeroPos
- nFormatPos
;
1973 if ( nFormatPos
>= 0 && nInsertPos
>= 0 )
1975 rtl::OUStringBuffer
aContent( pObj
->aText
);
1976 // #107805# always quote embedded strings - even space would otherwise
1977 // be recognized as thousands separator in French.
1978 aContent
.insert( 0, (sal_Unicode
) '"' );
1979 aContent
.append( (sal_Unicode
) '"' );
1981 aNumStr
.Insert( String( aContent
.makeStringAndClear() ), (xub_StrLen
)nInsertPos
);
1986 aFormatCode
.append( aNumStr
);
1988 if ( ( rInfo
.bDecReplace
|| rInfo
.bVarDecimals
) && nPrec
) // add decimal replacement (dashes)
1990 // add dashes for explicit decimal replacement, # for variable decimals
1991 sal_Unicode cAdd
= rInfo
.bDecReplace
? '-' : '#';
1993 aFormatCode
.append( pData
->GetLocaleData( nFormatLang
).getNumDecimalSep() );
1994 for ( sal_uInt16 i
=0; i
<nPrec
; i
++)
1995 aFormatCode
.append( cAdd
);
1998 // add extra thousands separators for display factor
2000 if ( rInfo
.fDisplayFactor
!= 1.0 && rInfo
.fDisplayFactor
> 0.0 )
2002 // test for 1.0 is just for optimization - nSepCount would be 0
2004 // one separator for each factor of 1000
2005 sal_Int32 nSepCount
= (sal_Int32
) ::rtl::math::round( log10(rInfo
.fDisplayFactor
) / 3.0 );
2006 if ( nSepCount
> 0 )
2008 OUString aSep
= pData
->GetLocaleData( nFormatLang
).getNumThousandSep();
2009 for ( sal_Int32 i
=0; i
<nSepCount
; i
++ )
2010 aFormatCode
.append( aSep
);
2015 void SvXMLNumFormatContext::AddCurrency( const rtl::OUString
& rContent
, LanguageType nLang
)
2017 sal_Bool bAutomatic
= sal_False
;
2018 OUString aSymbol
= rContent
;
2019 if ( aSymbol
.getLength() == 0 )
2021 // get currency symbol for language
2023 //aSymbol = pData->GetLocaleData( nFormatLang ).getCurrSymbol();
2025 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2028 pFormatter
->ChangeIntl( nFormatLang
);
2029 String sCurString
, sDummy
;
2030 pFormatter
->GetCompatibilityCurrency( sCurString
, sDummy
);
2031 aSymbol
= sCurString
;
2033 bAutomatic
= sal_True
;
2036 else if ( nLang
== LANGUAGE_SYSTEM
&& aSymbol
.compareToAscii("CCC") == 0 )
2038 // "CCC" is used for automatic long symbol
2039 bAutomatic
= sal_True
;
2044 // remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
2045 // otherwise the currency symbol isn't recognized (#94048#)
2047 sal_Int32 nLength
= aFormatCode
.getLength();
2048 if ( nLength
> 1 && aFormatCode
.charAt( nLength
-1 ) == '"' )
2050 // find start of quoted string
2051 // When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
2052 // they must be handled here, too.
2054 sal_Int32 nFirst
= nLength
- 2;
2055 while ( nFirst
>= 0 && aFormatCode
.charAt( nFirst
) != '"' )
2059 // remove both quotes from aFormatCode
2060 rtl::OUString aOld
= aFormatCode
.makeStringAndClear();
2062 aFormatCode
.append( aOld
.copy( 0, nFirst
) );
2063 if ( nLength
> nFirst
+ 2 )
2064 aFormatCode
.append( aOld
.copy( nFirst
+ 1, nLength
- nFirst
- 2 ) );
2070 aFormatCode
.appendAscii( "[$" ); // intro for "new" currency symbols
2072 aFormatCode
.append( aSymbol
);
2076 if ( nLang
!= LANGUAGE_SYSTEM
)
2078 // '-' sign and language code in hex:
2079 aFormatCode
.append( (sal_Unicode
) '-' );
2080 aFormatCode
.append( String::CreateFromInt32( sal_Int32( nLang
), 16 ).ToUpperAscii() );
2083 aFormatCode
.append( (sal_Unicode
) ']' ); // end of "new" currency symbol
2087 void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex
)
2089 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2093 if ( nIndex
== NF_KEY_G
|| nIndex
== NF_KEY_GG
|| nIndex
== NF_KEY_GGG
)
2096 if ( nIndex
== NF_KEY_NNNN
)
2098 nIndex
= NF_KEY_NNN
;
2099 bHasLongDoW
= sal_True
; // to remove string constant with separator
2102 String sKeyword
= pFormatter
->GetKeyword( nFormatLang
, nIndex
);
2104 if ( nIndex
== NF_KEY_H
|| nIndex
== NF_KEY_HH
||
2105 nIndex
== NF_KEY_MI
|| nIndex
== NF_KEY_MMI
||
2106 nIndex
== NF_KEY_S
|| nIndex
== NF_KEY_SS
)
2108 if ( !bTruncate
&& !bHasDateTime
)
2110 // with truncate-on-overflow = false, add "[]" to first time part
2112 sKeyword
.Insert( (sal_Unicode
) '[', 0 );
2113 sKeyword
.Append( (sal_Unicode
) ']' );
2115 bHasDateTime
= sal_True
;
2118 aFormatCode
.append( sKeyword
);
2120 // collect the date elements that the format contains, to recognize default date formats
2123 case NF_KEY_NN
: eDateDOW
= XML_DEA_SHORT
; break;
2125 case NF_KEY_NNNN
: eDateDOW
= XML_DEA_LONG
; break;
2126 case NF_KEY_D
: eDateDay
= XML_DEA_SHORT
; break;
2127 case NF_KEY_DD
: eDateDay
= XML_DEA_LONG
; break;
2128 case NF_KEY_M
: eDateMonth
= XML_DEA_SHORT
; break;
2129 case NF_KEY_MM
: eDateMonth
= XML_DEA_LONG
; break;
2130 case NF_KEY_MMM
: eDateMonth
= XML_DEA_TEXTSHORT
; break;
2131 case NF_KEY_MMMM
: eDateMonth
= XML_DEA_TEXTLONG
; break;
2132 case NF_KEY_YY
: eDateYear
= XML_DEA_SHORT
; break;
2133 case NF_KEY_YYYY
: eDateYear
= XML_DEA_LONG
; break;
2134 case NF_KEY_H
: eDateHours
= XML_DEA_SHORT
; break;
2135 case NF_KEY_HH
: eDateHours
= XML_DEA_LONG
; break;
2136 case NF_KEY_MI
: eDateMins
= XML_DEA_SHORT
; break;
2137 case NF_KEY_MMI
: eDateMins
= XML_DEA_LONG
; break;
2138 case NF_KEY_S
: eDateSecs
= XML_DEA_SHORT
; break;
2139 case NF_KEY_SS
: eDateSecs
= XML_DEA_LONG
; break;
2141 case NF_KEY_AMPM
: break; // AM/PM may or may not be in date/time formats -> ignore by itself
2143 bDateNoDefault
= sal_True
; // any other element -> no default format
2147 sal_Bool
lcl_IsAtEnd( rtl::OUStringBuffer
& rBuffer
, const String
& rToken
)
2149 sal_Int32 nBufLen
= rBuffer
.getLength();
2150 xub_StrLen nTokLen
= rToken
.Len();
2152 if ( nTokLen
> nBufLen
)
2155 sal_Int32 nStartPos
= nTokLen
- nBufLen
;
2156 for ( xub_StrLen nTokPos
= 0; nTokPos
< nTokLen
; nTokPos
++ )
2157 if ( rToken
.GetChar( nTokPos
) != rBuffer
.charAt( nStartPos
+ nTokPos
) )
2163 sal_Bool
SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld
, sal_uInt16 nNew
)
2165 // replaces one keyword with another if it is found at the end of the code
2167 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2171 String sOldStr
= pFormatter
->GetKeyword( nFormatLang
, nOld
);
2172 if ( lcl_IsAtEnd( aFormatCode
, sOldStr
) )
2174 // remove old keyword
2175 aFormatCode
.setLength( aFormatCode
.getLength() - sOldStr
.Len() );
2178 String sNewStr
= pFormatter
->GetKeyword( nFormatLang
, nNew
);
2179 aFormatCode
.append( sNewStr
);
2181 return sal_True
; // changed
2183 return sal_False
; // not found
2186 void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex
)
2188 rtl::OUString rApplyName
= aMyConditions
[nIndex
].sMapName
;
2189 rtl::OUString rCondition
= aMyConditions
[nIndex
].sCondition
;
2190 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2191 sal_uInt32 l_nKey
= pData
->GetKeyForName( rApplyName
);
2192 OUString sValue
= OUString::createFromAscii( "value()" ); //! define constant
2193 sal_Int32 nValLen
= sValue
.getLength();
2195 if ( pFormatter
&& l_nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&&
2196 rCondition
.copy( 0, nValLen
) == sValue
)
2198 //! test for valid conditions
2199 //! test for default conditions
2201 OUString sRealCond
= rCondition
.copy( nValLen
, rCondition
.getLength() - nValLen
);
2202 sal_Bool bDefaultCond
= sal_False
;
2204 //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
2205 //! allow blanks in conditions
2206 sal_Bool bFirstCond
= ( aConditions
.getLength() == 0 );
2207 if ( bFirstCond
&& aMyConditions
.size() == 1 && sRealCond
.compareToAscii( ">=0" ) == 0 )
2208 bDefaultCond
= sal_True
;
2210 if ( nType
== XML_TOK_STYLES_TEXT_STYLE
&& nIndex
== 2 )
2212 // The third condition in a number format with a text part can only be
2213 // "all other numbers", the condition string must be empty.
2214 bDefaultCond
= sal_True
;
2219 sal_Int32 nPos
= sRealCond
.indexOf( '.' );
2221 { // #i8026# #103991# localize decimal separator
2222 const String
& rDecSep
= GetLocaleData().getNumDecimalSep();
2223 if ( rDecSep
.Len() > 1 || rDecSep
.GetChar(0) != '.' )
2224 sRealCond
= sRealCond
.replaceAt( nPos
, 1, rDecSep
);
2226 aConditions
.append( (sal_Unicode
) '[' );
2227 aConditions
.append( sRealCond
);
2228 aConditions
.append( (sal_Unicode
) ']' );
2231 const SvNumberformat
* pFormat
= pFormatter
->GetEntry(l_nKey
);
2233 aConditions
.append( OUString( pFormat
->GetFormatstring() ) );
2235 aConditions
.append( (sal_Unicode
) ';' );
2239 void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex
, const rtl::OUString
& rFormat
, const LocaleDataWrapper
& rData
)
2241 rtl::OUString rCondition
= aMyConditions
[nIndex
].sCondition
;
2242 OUString sValue
= OUString::createFromAscii( "value()" ); //! define constant
2243 sal_Int32 nValLen
= sValue
.getLength();
2245 if ( rCondition
.copy( 0, nValLen
) == sValue
)
2247 //! test for valid conditions
2248 //! test for default conditions
2250 OUString sRealCond
= rCondition
.copy( nValLen
, rCondition
.getLength() - nValLen
);
2251 sal_Bool bDefaultCond
= sal_False
;
2253 //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
2254 //! allow blanks in conditions
2255 sal_Bool bFirstCond
= ( aConditions
.getLength() == 0 );
2256 if ( bFirstCond
&& aMyConditions
.size() == 1 && sRealCond
.compareToAscii( ">=0" ) == 0 )
2257 bDefaultCond
= sal_True
;
2259 if ( nType
== XML_TOK_STYLES_TEXT_STYLE
&& nIndex
== 2 )
2261 // The third condition in a number format with a text part can only be
2262 // "all other numbers", the condition string must be empty.
2263 bDefaultCond
= sal_True
;
2268 sal_Int32 nPos
= sRealCond
.indexOf( '.' );
2270 { // #i8026# #103991# localize decimal separator
2271 const String
& rDecSep
= rData
.getNumDecimalSep();
2272 if ( rDecSep
.Len() > 1 || rDecSep
.GetChar(0) != '.' )
2273 sRealCond
= sRealCond
.replaceAt( nPos
, 1, rDecSep
);
2275 aConditions
.append( (sal_Unicode
) '[' );
2276 aConditions
.append( sRealCond
);
2277 aConditions
.append( (sal_Unicode
) ']' );
2280 aConditions
.append( rFormat
);
2282 aConditions
.append( (sal_Unicode
) ';' );
2286 void SvXMLNumFormatContext::AddCondition( const rtl::OUString
& rCondition
, const rtl::OUString
& rApplyName
)
2288 MyCondition aCondition
;
2289 aCondition
.sCondition
= rCondition
;
2290 aCondition
.sMapName
= rApplyName
;
2291 aMyConditions
.push_back(aCondition
);
2294 void SvXMLNumFormatContext::AddColor( const Color
& rColor
)
2296 SvNumberFormatter
* pFormatter
= pData
->GetNumberFormatter();
2300 OUStringBuffer aColName
;
2301 for ( sal_uInt16 i
=0; i
<XML_NUMF_COLORCOUNT
; i
++ )
2302 if ( rColor
== aNumFmtStdColors
[i
] )
2304 aColName
= OUString( pFormatter
->GetKeyword( nFormatLang
, sal::static_int_cast
< USHORT
>(NF_KEY_FIRSTCOLOR
+ i
) ) );
2308 if ( aColName
.getLength() )
2310 aColName
.insert( 0, (sal_Unicode
) '[' );
2311 aColName
.append( (sal_Unicode
) ']' );
2312 aFormatCode
.insert( 0, aColName
.makeStringAndClear() );
2316 void SvXMLNumFormatContext::UpdateCalendar( const rtl::OUString
& rNewCalendar
)
2318 if ( rNewCalendar
!= sCalendar
)
2320 sCalendar
= rNewCalendar
;
2321 if ( sCalendar
.getLength() )
2323 aFormatCode
.appendAscii( "[~" ); // intro for calendar code
2324 aFormatCode
.append( sCalendar
);
2325 aFormatCode
.append( (sal_Unicode
) ']' ); // end of "new" currency symbolcalendar code
2330 sal_Bool
SvXMLNumFormatContext::IsSystemLanguage()
2332 return nFormatLang
== LANGUAGE_SYSTEM
;
2335 //-------------------------------------------------------------------------
2338 // SvXMLNumFmtHelper
2342 //SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2343 // const uno::Reference<util::XNumberFormatsSupplier>& rSupp )
2344 SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2345 const uno::Reference
<util::XNumberFormatsSupplier
>& rSupp
,
2346 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
)
2347 : mxServiceFactory(xServiceFactory
)
2349 DBG_ASSERT( mxServiceFactory
.is(), "got no service manager" );
2351 SvNumberFormatter
* pFormatter
= NULL
;
2352 SvNumberFormatsSupplierObj
* pObj
=
2353 SvNumberFormatsSupplierObj::getImplementation( rSupp
);
2355 pFormatter
= pObj
->GetNumberFormatter();
2358 // pData = new SvXMLNumImpData( pFormatter );
2359 pData
= new SvXMLNumImpData( pFormatter
, mxServiceFactory
);
2363 // SvXMLNumFmtHelper::SvXMLNumFmtHelper( SvNumberFormatter* pNumberFormatter )
2364 SvXMLNumFmtHelper::SvXMLNumFmtHelper(
2365 SvNumberFormatter
* pNumberFormatter
,
2366 const uno::Reference
<lang::XMultiServiceFactory
>& xServiceFactory
)
2367 : mxServiceFactory(xServiceFactory
)
2369 DBG_ASSERT( mxServiceFactory
.is(), "got no service manager" );
2372 // pData = new SvXMLNumImpData( pNumberFormatter );
2373 pData
= new SvXMLNumImpData( pNumberFormatter
, mxServiceFactory
);
2376 SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
2378 // remove temporary (volatile) formats from NumberFormatter
2379 pData
->RemoveVolatileFormats();
2384 SvXMLStyleContext
* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport
& rImport
,
2385 USHORT nPrefix
, const OUString
& rLocalName
,
2386 const uno::Reference
<xml::sax::XAttributeList
>& xAttrList
,
2387 SvXMLStylesContext
& rStyles
)
2389 SvXMLStyleContext
* pContext
= NULL
;
2391 const SvXMLTokenMap
& rTokenMap
= pData
->GetStylesElemTokenMap();
2392 sal_uInt16 nToken
= rTokenMap
.Get( nPrefix
, rLocalName
);
2395 case XML_TOK_STYLES_NUMBER_STYLE
:
2396 case XML_TOK_STYLES_CURRENCY_STYLE
:
2397 case XML_TOK_STYLES_PERCENTAGE_STYLE
:
2398 case XML_TOK_STYLES_DATE_STYLE
:
2399 case XML_TOK_STYLES_TIME_STYLE
:
2400 case XML_TOK_STYLES_BOOLEAN_STYLE
:
2401 case XML_TOK_STYLES_TEXT_STYLE
:
2402 pContext
= new SvXMLNumFormatContext( rImport
, nPrefix
, rLocalName
,
2403 pData
, nToken
, xAttrList
, rStyles
);
2407 // return NULL if not a data style, caller must handle other elements
2411 const SvXMLTokenMap
& SvXMLNumFmtHelper::GetStylesElemTokenMap()
2413 return pData
->GetStylesElemTokenMap();
2416 /*sal_uInt32 SvXMLNumFmtHelper::GetKeyForName( const rtl::OUString& rName )
2418 return pData->GetKeyForName( rName );