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