Update ooo320-m1
[ooovba.git] / xmloff / source / style / xmlnumfi.cxx
blobc61e7a87ca2c4fdabc168fb2f531dee32f3514b0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlnumfi.cxx,v $
10 * $Revision: 1.48 $
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>
46 // #110680#
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
69 rtl::OUString aName;
70 sal_uInt32 nKey;
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
82 sal_Int32 nFormatPos;
83 rtl::OUString aText;
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 //-------------------------------------------------------------------------
98 class SvXMLNumImpData
100 SvNumberFormatter* pFormatter;
101 SvXMLTokenMap* pStylesElemTokenMap;
102 SvXMLTokenMap* pStyleElemTokenMap;
103 SvXMLTokenMap* pStyleAttrTokenMap;
104 SvXMLTokenMap* pStyleElemAttrTokenMap;
105 LocaleDataWrapper* pLocaleData;
106 SvXMLNumFmtEntryArr aNameEntries;
108 // #110680#
109 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceFactory;
111 public:
112 // #110680#
113 // SvXMLNumImpData( SvNumberFormatter* pFmt );
114 SvXMLNumImpData(
115 SvNumberFormatter* pFmt,
116 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory );
117 ~SvXMLNumImpData();
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
134 sal_Int32 nDecimals;
135 sal_Int32 nInteger;
136 sal_Int32 nExpDigits;
137 sal_Int32 nNumerDigits;
138 sal_Int32 nDenomDigits;
139 sal_Bool bGrouping;
140 sal_Bool bDecReplace;
141 sal_Bool bVarDecimals;
142 double fDisplayFactor;
143 SvXMLEmbeddedElementArr aEmbeddedElements;
145 SvXMLNumberInfo()
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;
156 sal_uInt16 nType;
157 rtl::OUStringBuffer aContent;
158 SvXMLNumberInfo aNumInfo;
159 LanguageType nElementLang;
160 sal_Bool bLong;
161 sal_Bool bTextual;
162 rtl::OUString sCalendar;
164 public:
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;
189 public:
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;
210 rtl::OUString sName;
212 public:
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;
232 Color aColor;
233 sal_Bool bColSet;
235 public:
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
256 XML_TOK_STYLE_TEXT,
257 XML_TOK_STYLE_NUMBER,
258 XML_TOK_STYLE_SCIENTIFIC_NUMBER,
259 XML_TOK_STYLE_FRACTION,
260 XML_TOK_STYLE_CURRENCY_SYMBOL,
261 XML_TOK_STYLE_DAY,
262 XML_TOK_STYLE_MONTH,
263 XML_TOK_STYLE_YEAR,
264 XML_TOK_STYLE_ERA,
265 XML_TOK_STYLE_DAY_OF_WEEK,
266 XML_TOK_STYLE_WEEK_OF_YEAR,
267 XML_TOK_STYLE_QUARTER,
268 XML_TOK_STYLE_HOURS,
269 XML_TOK_STYLE_AM_PM,
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,
275 XML_TOK_STYLE_MAP
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 //-------------------------------------------------------------------------
314 // standard colors
317 #define XML_NUMF_COLORCOUNT 10
319 static ColorData aNumFmtStdColors[XML_NUMF_COLORCOUNT] =
321 COL_BLACK,
322 COL_LIGHTBLUE,
323 COL_LIGHTGREEN,
324 COL_LIGHTCYAN,
325 COL_LIGHTRED,
326 COL_LIGHTMAGENTA,
327 COL_BROWN,
328 COL_GRAY,
329 COL_YELLOW,
330 COL_WHITE
334 // token maps
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;
365 sal_Bool bSystem;
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 //-------------------------------------------------------------------------
396 // SvXMLNumImpData
399 // #110680#
400 // SvXMLNumImpData::SvXMLNumImpData( SvNumberFormatter* pFmt ) :
401 SvXMLNumImpData::SvXMLNumImpData(
402 SvNumberFormatter* pFmt,
403 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory )
404 : pFormatter(pFmt),
405 pStylesElemTokenMap(NULL),
406 pStyleElemTokenMap(NULL),
407 pStyleAttrTokenMap(NULL),
408 pStyleElemAttrTokenMap(NULL),
409 pLocaleData(NULL),
411 // #110680#
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;
423 delete pLocaleData;
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
452 break;
456 else
458 // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
459 SetUsed( nKey );
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
478 // them is used
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
489 if ( !pFormatter )
490 return;
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[] =
511 // style elements
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 },
519 XML_TOKEN_MAP_END
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 },
554 XML_TOKEN_MAP_END
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 },
581 XML_TOKEN_MAP_END
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 },
609 XML_TOKEN_MAP_END
612 pStyleElemAttrTokenMap = new SvXMLTokenMap( aStyleElemAttrMap );
614 return *pStyleElemAttrTokenMap;
617 const LocaleDataWrapper& SvXMLNumImpData::GetLocaleData( LanguageType nLang )
619 if ( !pLocaleData )
620 // #110680#
621 //pLocaleData = new LocaleDataWrapper(
622 // (pFormatter ? pFormatter->GetServiceManager() :
623 // ::comphelper::getProcessServiceFactory()),
624 // MsLangId::convertLanguageToLocale( nLang ) );
625 pLocaleData = new LocaleDataWrapper(
626 (pFormatter ? pFormatter->GetServiceManager() :
627 mxServiceFactory),
628 MsLangId::convertLanguageToLocale( nLang ) );
629 else
630 pLocaleData->setLocale( MsLangId::convertLanguageToLocale( nLang ) );
631 return *pLocaleData;
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 );
652 OUString aLocalName;
653 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
654 if ( nPrefix == XML_NAMESPACE_STYLE )
656 if ( IsXMLToken( aLocalName, XML_CONDITION) )
657 sCondition = sValue;
658 else if ( IsXMLToken( aLocalName, XML_APPLY_STYLE_NAME) )
659 sName = sValue;
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 ),
697 bColSet( sal_False )
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 );
704 OUString aLocalName;
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()
729 if (bColSet)
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 ),
745 nTextPosition( 0 )
747 sal_Int32 nAttrVal;
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 );
754 OUString aLocalName;
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;
794 sal_Unicode cTS;
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
805 // in date formats.
807 return sal_False; // force quotes
810 // see ImpSvNumberformatScan::Next_Symbol
811 if ( cChar == ' ' ||
812 cChar == '-' ||
813 cChar == '/' ||
814 cChar == '.' ||
815 cChar == ',' ||
816 cChar == ':' ||
817 cChar == '\'' )
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 == '%' )
822 return sal_True;
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 == ')' ) )
829 return sal_True;
831 return sal_False;
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 ) ) ||
841 ( nLength == 2 &&
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)
847 bQuote = sal_False;
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) '%' );
856 if ( nPos >= 0 )
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
864 else
866 // quote text behind percent character
867 rContent.insert( nPos + 1, (sal_Unicode) '"' );
868 rContent.append( (sal_Unicode) '"' );
871 if ( nPos > 0 )
873 if ( nPos == 1 && lcl_ValidChar( rContent.charAt(0), rParent ) )
875 // single character that doesn't need quoting
877 else
879 // quote text before percent character
880 rContent.insert( nPos, (sal_Unicode) '"' );
881 rContent.insert( 0, (sal_Unicode) '"' );
884 bQuote = sal_False;
886 // else: normal quoting (below)
889 if ( bQuote )
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 );
894 if ( bEscape )
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( "\"\\\"" ) );
900 sal_Int32 nPos = 0;
901 while ( nPos < rContent.getLength() )
903 if ( rContent.charAt( nPos ) == (sal_Unicode) '"' )
905 rContent.insert( nPos, aInsert );
906 nPos += aInsert.getLength();
908 ++nPos;
912 // quote string literals
913 rContent.insert( 0, (sal_Unicode) '"' );
914 rContent.append( (sal_Unicode) '"' );
916 // remove redundant double quotes at start or end
917 if ( bEscape )
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();
928 if ( nLen > 2 &&
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 ),
949 nType( nNewType ),
950 nElementLang( LANGUAGE_SYSTEM ),
951 bLong( FALSE ),
952 bTextual( FALSE )
954 OUString sLanguage, sCountry;
955 sal_Int32 nAttrVal;
956 sal_Bool bAttrBool;
957 sal_uInt16 nAttrEnum;
958 double fAttrDouble;
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 );
965 OUString aLocalName;
966 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
968 const SvXMLTokenMap& rTokenMap = rParent.GetData()->GetStyleElemAttrTokenMap();
969 sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
971 switch (nToken)
973 case XML_TOK_ELEM_ATTR_DECIMAL_PLACES:
974 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
975 aNumInfo.nDecimals = nAttrVal;
976 break;
977 case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS:
978 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
979 aNumInfo.nInteger = nAttrVal;
980 break;
981 case XML_TOK_ELEM_ATTR_GROUPING:
982 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
983 aNumInfo.bGrouping = bAttrBool;
984 break;
985 case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR:
986 if ( SvXMLUnitConverter::convertDouble( fAttrDouble, sValue ) )
987 aNumInfo.fDisplayFactor = fAttrDouble;
988 break;
989 case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT:
990 if ( sValue.getLength() > 0 )
991 aNumInfo.bDecReplace = sal_True; // only a default string is supported
992 else
993 aNumInfo.bVarDecimals = sal_True; // empty replacement string: variable decimals
994 break;
995 case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS:
996 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
997 aNumInfo.nExpDigits = nAttrVal;
998 break;
999 case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS:
1000 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
1001 aNumInfo.nNumerDigits = nAttrVal;
1002 break;
1003 case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS:
1004 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
1005 aNumInfo.nDenomDigits = nAttrVal;
1006 break;
1007 case XML_TOK_ELEM_ATTR_LANGUAGE:
1008 sLanguage = sValue;
1009 break;
1010 case XML_TOK_ELEM_ATTR_COUNTRY:
1011 sCountry = sValue;
1012 break;
1013 case XML_TOK_ELEM_ATTR_STYLE:
1014 if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aStyleValueMap ) )
1015 bLong = (sal_Bool) nAttrEnum;
1016 break;
1017 case XML_TOK_ELEM_ATTR_TEXTUAL:
1018 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
1019 bTextual = bAttrBool;
1020 break;
1021 case XML_TOK_ELEM_ATTR_CALENDAR:
1022 sCalendar = sValue;
1023 break;
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 );
1050 else
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
1068 delete pObj;
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;
1076 break;
1083 void SvXMLNumFmtElementContext::EndElement()
1085 sal_Bool bEffLong = bLong;
1086 switch (nType)
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() );
1109 break;
1111 case XML_TOK_STYLE_NUMBER:
1112 rParent.AddNumber( aNumInfo );
1113 break;
1115 case XML_TOK_STYLE_CURRENCY_SYMBOL:
1116 rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
1117 break;
1119 case XML_TOK_STYLE_TEXT_CONTENT:
1120 rParent.AddToCode( OUString::valueOf((sal_Unicode)'@') );
1121 break;
1122 case XML_TOK_STYLE_BOOLEAN:
1123 // ignored - only default boolean format is supported
1124 break;
1126 case XML_TOK_STYLE_DAY:
1127 rParent.UpdateCalendar( sCalendar );
1128 #if 0
1129 //! I18N doesn't provide SYSTEM or extended date information yet
1130 if ( rParent.IsFromSystem() )
1131 bEffLong = SvXMLNumFmtDefaults::IsSystemLongDay( rParent.GetInternational(), bLong );
1132 #endif
1133 rParent.AddNfKeyword(
1134 sal::static_int_cast< sal_uInt16 >(
1135 bEffLong ? NF_KEY_DD : NF_KEY_D ) );
1136 break;
1137 case XML_TOK_STYLE_MONTH:
1138 rParent.UpdateCalendar( sCalendar );
1139 #if 0
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 );
1146 #endif
1147 rParent.AddNfKeyword(
1148 sal::static_int_cast< sal_uInt16 >(
1149 bTextual
1150 ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
1151 : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
1152 break;
1153 case XML_TOK_STYLE_YEAR:
1154 rParent.UpdateCalendar( sCalendar );
1155 #if 0
1156 //! I18N doesn't provide SYSTEM or extended date information yet
1157 if ( rParent.IsFromSystem() )
1158 bEffLong = SvXMLNumFmtDefaults::IsSystemLongYear( rParent.GetInternational(), bLong );
1159 #endif
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 ) );
1165 else
1166 rParent.AddNfKeyword(
1167 sal::static_int_cast< sal_uInt16 >(
1168 bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
1169 break;
1170 case XML_TOK_STYLE_ERA:
1171 rParent.UpdateCalendar( sCalendar );
1172 #if 0
1173 //! I18N doesn't provide SYSTEM or extended date information yet
1174 if ( rParent.IsFromSystem() )
1175 bEffLong = SvXMLNumFmtDefaults::IsSystemLongEra( rParent.GetInternational(), bLong );
1176 #endif
1177 rParent.AddNfKeyword(
1178 sal::static_int_cast< sal_uInt16 >(
1179 bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
1180 // HasEra flag is set
1181 break;
1182 case XML_TOK_STYLE_DAY_OF_WEEK:
1183 rParent.UpdateCalendar( sCalendar );
1184 #if 0
1185 //! I18N doesn't provide SYSTEM or extended date information yet
1186 if ( rParent.IsFromSystem() )
1187 bEffLong = SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( rParent.GetInternational(), bLong );
1188 #endif
1189 rParent.AddNfKeyword(
1190 sal::static_int_cast< sal_uInt16 >(
1191 bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
1192 break;
1193 case XML_TOK_STYLE_WEEK_OF_YEAR:
1194 rParent.UpdateCalendar( sCalendar );
1195 rParent.AddNfKeyword( NF_KEY_WW );
1196 break;
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 ) );
1202 break;
1203 case XML_TOK_STYLE_HOURS:
1204 rParent.AddNfKeyword(
1205 sal::static_int_cast< sal_uInt16 >(
1206 bEffLong ? NF_KEY_HH : NF_KEY_H ) );
1207 break;
1208 case XML_TOK_STYLE_AM_PM:
1209 //! short/long?
1210 rParent.AddNfKeyword( NF_KEY_AMPM );
1211 break;
1212 case XML_TOK_STYLE_MINUTES:
1213 rParent.AddNfKeyword(
1214 sal::static_int_cast< sal_uInt16 >(
1215 bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
1216 break;
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') );
1232 break;
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
1246 sal_Int32 i;
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)'?') );
1253 break;
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') );
1263 break;
1265 default:
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
1275 #if 0
1276 return bLong ? rIntn.IsLongDateDayLeadingZero() : rIntn.IsDateDayLeadingZero();
1277 #else
1278 return !bLong;
1279 #endif
1282 sal_Bool SvXMLNumFmtDefaults::IsSystemLongMonth( const SvtSysLocale&, BOOL bLong )
1284 // TODO: merge system information and defaults into i18n locale data
1285 #if 0
1286 if (bLong)
1288 MonthFormat eMonth = rIntn.GetLongDateMonthFormat();
1289 return ( eMonth == MONTH_ZERO || eMonth == MONTH_LONG );
1291 else
1292 return rIntn.IsDateMonthLeadingZero();
1293 #else
1294 return !bLong;
1295 #endif
1298 sal_Bool SvXMLNumFmtDefaults::IsSystemTextualMonth( const SvtSysLocale&, BOOL bLong )
1300 // TODO: merge system information and defaults into i18n locale data
1301 #if 0
1302 if (bLong)
1304 MonthFormat eMonth = rIntn.GetLongDateMonthFormat();
1305 return ( eMonth == MONTH_SHORT || eMonth == MONTH_LONG );
1307 else
1308 return sal_False;
1309 #else
1310 return bLong;
1311 #endif
1314 sal_Bool SvXMLNumFmtDefaults::IsSystemLongYear( const SvtSysLocale&, BOOL bLong )
1316 // TODO: merge system information and defaults into i18n locale data
1317 #if 0
1318 return bLong ? rIntn.IsLongDateCentury() : rIntn.IsDateCentury();
1319 #else
1320 return bLong;
1321 #endif
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
1333 #if 0
1334 return ( bLong && rIntn.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG );
1335 #else
1336 return bLong && true;
1337 #endif
1340 sal_uInt16 SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW,
1341 SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth,
1342 SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours,
1343 SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs,
1344 sal_Bool bSystem )
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 ),
1378 pData( pNewData ),
1379 pStyles( &rStyles ),
1380 aMyConditions(),
1381 nType( nNewType ),
1382 nKey(-1),
1383 nFormatLang( LANGUAGE_SYSTEM ),
1384 bAutoOrder( FALSE ),
1385 bFromSystem( FALSE ),
1386 bTruncate( TRUE ),
1387 bAutoDec( FALSE ),
1388 bAutoInt( FALSE ),
1389 bHasExtraText( FALSE ),
1390 bHasLongDoW( FALSE ),
1391 bHasEra( 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;
1405 sal_Bool bAttrBool;
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 );
1418 switch (nToken)
1420 case XML_TOK_STYLE_ATTR_NAME:
1421 // aName = sValue;
1422 break;
1423 case XML_TOK_STYLE_ATTR_LANGUAGE:
1424 sLanguage = sValue;
1425 break;
1426 case XML_TOK_STYLE_ATTR_COUNTRY:
1427 sCountry = sValue;
1428 break;
1429 case XML_TOK_STYLE_ATTR_TITLE:
1430 sFormatTitle = sValue;
1431 break;
1432 case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER:
1433 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
1434 bAutoOrder = bAttrBool;
1435 break;
1436 case XML_TOK_STYLE_ATTR_FORMAT_SOURCE:
1437 if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aFormatSourceMap ) )
1438 bFromSystem = (sal_Bool) nAttrEnum;
1439 break;
1440 case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW:
1441 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
1442 bTruncate = bAttrBool;
1443 break;
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;
1449 break;
1450 case XML_TOK_STYLE_ATTR_TRANSL_FORMAT:
1451 aNatNumAttr.Format = sValue;
1452 break;
1453 case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE:
1454 aNatNumAttr.Locale.Language = sValue;
1455 break;
1456 case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY:
1457 aNatNumAttr.Locale.Country = sValue;
1458 break;
1459 case XML_TOK_STYLE_ATTR_TRANSL_STYLE:
1460 aNatNumAttr.Style = sValue;
1461 break;
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();
1475 if ( pFormatter )
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 ),
1501 pData( NULL ),
1502 pStyles( &rStyles ),
1503 aMyConditions(),
1504 nType( 0 ),
1505 nKey(nTempKey),
1506 nFormatLang( LANGUAGE_SYSTEM ),
1507 bAutoOrder( FALSE ),
1508 bFromSystem( FALSE ),
1509 bTruncate( TRUE ),
1510 bAutoDec( FALSE ),
1511 bAutoInt( FALSE ),
1512 bHasExtraText( FALSE ),
1513 bHasLongDoW( FALSE ),
1514 bHasEra( 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 );
1541 switch (nToken)
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 );
1563 break;
1565 case XML_TOK_STYLE_PROPERTIES:
1566 pContext = new SvXMLNumFmtPropContext( GetImport(), nPrfx, rLName,
1567 *this, xAttrList );
1568 break;
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,
1574 *this, xAttrList );
1576 break;
1579 if( !pContext )
1580 pContext = new SvXMLImportContext( GetImport(), nPrfx, rLName );
1581 return pContext;
1584 sal_Int32 SvXMLNumFormatContext::GetKey()
1586 if (nKey > -1)
1588 if (bRemoveAfterUse)
1590 // format is used -> don't remove
1591 bRemoveAfterUse = sal_False;
1592 if (pData)
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() );
1599 return nKey;
1601 else
1603 // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
1604 bRemoveAfterUse = sal_False;
1605 CreateAndInsert(sal_True);
1606 return nKey;
1610 sal_Int32 SvXMLNumFormatContext::PrivateGetKey()
1612 // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
1614 if (nKey > -1)
1615 return nKey;
1616 else
1618 CreateAndInsert(sal_True);
1619 return nKey;
1623 sal_Int32 SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier >& xFormatsSupplier )
1625 if (nKey <= -1)
1627 SvNumberFormatter* pFormatter = NULL;
1628 SvNumberFormatsSupplierObj* pObj =
1629 SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier );
1630 if (pObj)
1631 pFormatter = pObj->GetNumberFormatter();
1633 if ( pFormatter )
1634 return CreateAndInsert( pFormatter );
1635 else
1636 return -1;
1638 else
1639 return nKey;
1642 void SvXMLNumFormatContext::CreateAndInsert(sal_Bool /*bOverwrite*/)
1644 if (!(nKey > -1))
1645 CreateAndInsert(pData->GetNumberFormatter());
1648 sal_Int32 SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
1650 if (!pFormatter)
1652 DBG_ERROR("no number formatter");
1653 return -1;
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);
1662 if (pStyle)
1664 if ((pStyle->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag
1665 AddCondition(i);
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;
1730 short l_nType = 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 )
1738 bOk = sal_True;
1740 if (!bOk)
1741 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
1745 #if 0
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 );
1762 else
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 );
1777 else
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) )
1792 nIndex = nNewIndex;
1795 #endif
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() )
1809 nIndex = nNewIndex;
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() )
1817 nIndex = nNewIndex;
1821 if ((nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND) && sFormatTitle.getLength())
1823 SvNumberformat* pFormat = const_cast<SvNumberformat*>(pFormatter->GetEntry( nIndex ));
1824 if (pFormat)
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 );
1838 nKey = nIndex;
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() );
1848 #if 0
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());
1856 int xxx=42;
1857 #endif
1859 return nKey;
1862 void SvXMLNumFormatContext::Finish( sal_Bool bOverwrite )
1864 SvXMLStyleContext::Finish( bOverwrite );
1865 // AddCondition();
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();
1882 if (!pFormatter)
1883 return;
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;
1896 if ( bAutoDec )
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();
1906 else
1908 // for other types, "automatic decimals" means dynamic determination of
1909 // decimals, as achieved with the "general" keyword
1911 aFormatCode.append( pFormatter->GetStandardName( nFormatLang ) );
1912 return;
1915 if ( bAutoInt )
1917 //!...
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
1929 String aNumStr;
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;
1961 String aDigitStr;
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();
2026 if ( pFormatter )
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;
2042 if ( bAutomatic )
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 ) != '"' )
2056 --nFirst;
2057 if ( nFirst >= 0 )
2059 // remove both quotes from aFormatCode
2060 rtl::OUString aOld = aFormatCode.makeStringAndClear();
2061 if ( nFirst > 0 )
2062 aFormatCode.append( aOld.copy( 0, nFirst ) );
2063 if ( nLength > nFirst + 2 )
2064 aFormatCode.append( aOld.copy( nFirst + 1, nLength - nFirst - 2 ) );
2069 if (!bAutomatic)
2070 aFormatCode.appendAscii( "[$" ); // intro for "new" currency symbols
2072 aFormatCode.append( aSymbol );
2074 if (!bAutomatic)
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();
2090 if (!pFormatter)
2091 return;
2093 if ( nIndex == NF_KEY_G || nIndex == NF_KEY_GG || nIndex == NF_KEY_GGG )
2094 bHasEra = sal_True;
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
2121 switch ( nIndex )
2123 case NF_KEY_NN: eDateDOW = XML_DEA_SHORT; break;
2124 case NF_KEY_NNN:
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;
2140 case NF_KEY_AP:
2141 case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself
2142 default:
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 )
2153 return sal_False;
2155 sal_Int32 nStartPos = nTokLen - nBufLen;
2156 for ( xub_StrLen nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
2157 if ( rToken.GetChar( nTokPos ) != rBuffer.charAt( nStartPos + nTokPos ) )
2158 return sal_False;
2160 return sal_True;
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();
2168 if (!pFormatter)
2169 return sal_False;
2171 String sOldStr = pFormatter->GetKeyword( nFormatLang, nOld );
2172 if ( lcl_IsAtEnd( aFormatCode, sOldStr ) )
2174 // remove old keyword
2175 aFormatCode.setLength( aFormatCode.getLength() - sOldStr.Len() );
2177 // add new keyword
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;
2217 if (!bDefaultCond)
2219 sal_Int32 nPos = sRealCond.indexOf( '.' );
2220 if ( nPos >= 0 )
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);
2232 if ( pFormat )
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;
2266 if (!bDefaultCond)
2268 sal_Int32 nPos = sRealCond.indexOf( '.' );
2269 if ( nPos >= 0 )
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();
2297 if (!pFormatter)
2298 return;
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) ) );
2305 break;
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
2341 // #110680#
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 );
2354 if (pObj)
2355 pFormatter = pObj->GetNumberFormatter();
2357 // #110680#
2358 // pData = new SvXMLNumImpData( pFormatter );
2359 pData = new SvXMLNumImpData( pFormatter, mxServiceFactory );
2362 // #110680#
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" );
2371 // #110680#
2372 // pData = new SvXMLNumImpData( pNumberFormatter );
2373 pData = new SvXMLNumImpData( pNumberFormatter, mxServiceFactory );
2376 SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
2378 // remove temporary (volatile) formats from NumberFormatter
2379 pData->RemoveVolatileFormats();
2381 delete pData;
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 );
2393 switch (nToken)
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 );
2404 break;
2407 // return NULL if not a data style, caller must handle other elements
2408 return pContext;
2411 const SvXMLTokenMap& SvXMLNumFmtHelper::GetStylesElemTokenMap()
2413 return pData->GetStylesElemTokenMap();
2416 /*sal_uInt32 SvXMLNumFmtHelper::GetKeyForName( const rtl::OUString& rName )
2418 return pData->GetKeyForName( rName );