/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#define _SVSTDARR_ULONGS
#define _ZFORLIST_DECLARE_TABLE

#include <svl/svstdarr.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
#include <svl/numuno.hxx>
#include <i18npool/mslangid.hxx>
#include <tools/debug.hxx>
#include <rtl/math.hxx>
#include <unotools/calendarwrapper.hxx>
#include <unotools/charclass.hxx>
#include <com/sun/star/lang/Locale.hpp>
#include <rtl/ustrbuf.hxx>

// #110680#
//#include <comphelper/processfactory.hxx>

#include <com/sun/star/i18n/NativeNumberXmlAttributes.hpp>

#include <xmloff/xmlnumfe.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmluconv.hxx>
#include <xmloff/attrlist.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/families.hxx>
#include <xmloff/xmlnumfi.hxx>		// SvXMLNumFmtDefaults

#define _SVSTDARR_USHORTS
#include <svl/svstdarr.hxx>
#include <svl/nfsymbol.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlexp.hxx>

#include <set>

using ::rtl::OUString;
using ::rtl::OUStringBuffer;

using namespace ::com::sun::star;
using namespace ::xmloff::token;
using namespace ::svt;

//-------------------------------------------------------------------------

//	4th condition for text formats doesn't work
//#define XMLNUM_MAX_PARTS	4
#define XMLNUM_MAX_PARTS	3

//-------------------------------------------------------------------------

struct LessuInt32
{
	sal_Bool operator() (const sal_uInt32 rValue1, const sal_uInt32 rValue2) const
	{
		return rValue1 < rValue2;
	}
};

typedef std::set< sal_uInt32, LessuInt32 >	SvXMLuInt32Set;

class SvXMLNumUsedList_Impl
{
	SvXMLuInt32Set				aUsed;
	SvXMLuInt32Set				aWasUsed;
	SvXMLuInt32Set::iterator	aCurrentUsedPos;
	sal_uInt32					nUsedCount;
	sal_uInt32					nWasUsedCount;

public:
			SvXMLNumUsedList_Impl();
			~SvXMLNumUsedList_Impl();

	void		SetUsed( sal_uInt32 nKey );
	sal_Bool	IsUsed( sal_uInt32 nKey ) const;
	sal_Bool	IsWasUsed( sal_uInt32 nKey ) const;
	void		Export();

	sal_Bool	GetFirstUsed(sal_uInt32& nKey);
	sal_Bool	GetNextUsed(sal_uInt32& nKey);

	void GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed);
	void SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed);
};

//-------------------------------------------------------------------------

struct SvXMLEmbeddedTextEntry
{
	sal_uInt16		nSourcePos;		// position in NumberFormat (to skip later)
	sal_Int32		nFormatPos;		// resulting position in embedded-text element
	rtl::OUString	aText;

	SvXMLEmbeddedTextEntry( sal_uInt16 nSP, sal_Int32 nFP, const rtl::OUString& rT ) :
		nSourcePos(nSP), nFormatPos(nFP), aText(rT) {}
};

typedef SvXMLEmbeddedTextEntry* SvXMLEmbeddedTextEntryPtr;
SV_DECL_PTRARR_DEL( SvXMLEmbeddedTextEntryArr, SvXMLEmbeddedTextEntryPtr, 4, 4 )

//-------------------------------------------------------------------------

SV_IMPL_PTRARR( SvXMLEmbeddedTextEntryArr, SvXMLEmbeddedTextEntryPtr );

//-------------------------------------------------------------------------

//
//!	SvXMLNumUsedList_Impl should be optimized!
//

SvXMLNumUsedList_Impl::SvXMLNumUsedList_Impl() :
	nUsedCount(0),
	nWasUsedCount(0)
{
}

SvXMLNumUsedList_Impl::~SvXMLNumUsedList_Impl()
{
}

void SvXMLNumUsedList_Impl::SetUsed( sal_uInt32 nKey )
{
	if ( !IsWasUsed(nKey) )
	{
		std::pair<SvXMLuInt32Set::iterator, bool> aPair = aUsed.insert( nKey );
		if (aPair.second)
			nUsedCount++;
	}
}

sal_Bool SvXMLNumUsedList_Impl::IsUsed( sal_uInt32 nKey ) const
{
	SvXMLuInt32Set::const_iterator aItr = aUsed.find(nKey);
	return (aItr != aUsed.end());
}

sal_Bool SvXMLNumUsedList_Impl::IsWasUsed( sal_uInt32 nKey ) const
{
	SvXMLuInt32Set::const_iterator aItr = aWasUsed.find(nKey);
	return (aItr != aWasUsed.end());
}

void SvXMLNumUsedList_Impl::Export()
{
	SvXMLuInt32Set::iterator aItr = aUsed.begin();
	while (aItr != aUsed.end())
	{
		std::pair<SvXMLuInt32Set::iterator, bool> aPair = aWasUsed.insert( *aItr );
		if (aPair.second)
			nWasUsedCount++;
		aItr++;
	}
	aUsed.clear();
	nUsedCount = 0;
}

sal_Bool SvXMLNumUsedList_Impl::GetFirstUsed(sal_uInt32& nKey)
{
	sal_Bool bRet(sal_False);
	aCurrentUsedPos = aUsed.begin();
	if(nUsedCount)
	{
		DBG_ASSERT(aCurrentUsedPos != aUsed.end(), "something went wrong");
		nKey = *aCurrentUsedPos;
		bRet = sal_True;
	}
	return bRet;
}

sal_Bool SvXMLNumUsedList_Impl::GetNextUsed(sal_uInt32& nKey)
{
	sal_Bool bRet(sal_False);
	if (aCurrentUsedPos != aUsed.end())
	{
		aCurrentUsedPos++;
		if (aCurrentUsedPos != aUsed.end())
		{
			nKey = *aCurrentUsedPos;
			bRet = sal_True;
		}
	}
	return bRet;
}

void SvXMLNumUsedList_Impl::GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed)
{
	rWasUsed.realloc(nWasUsedCount);
	sal_Int32* pWasUsed = rWasUsed.getArray();
	if (pWasUsed)
	{
		SvXMLuInt32Set::iterator aItr = aWasUsed.begin();
		while (aItr != aWasUsed.end())
		{
			*pWasUsed = *aItr;
			aItr++;
			pWasUsed++;
		}
	}
}

void SvXMLNumUsedList_Impl::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed)
{
	DBG_ASSERT(nWasUsedCount == 0, "WasUsed should be empty");
	sal_Int32 nCount(rWasUsed.getLength());
	const sal_Int32* pWasUsed = rWasUsed.getConstArray();
	for (sal_uInt16 i = 0; i < nCount; i++, pWasUsed++)
	{
		std::pair<SvXMLuInt32Set::iterator, bool> aPair = aWasUsed.insert( *pWasUsed );
		if (aPair.second)
			nWasUsedCount++;
	}
}

//-------------------------------------------------------------------------

SvXMLNumFmtExport::SvXMLNumFmtExport(
            SvXMLExport& rExp,
			const uno::Reference< util::XNumberFormatsSupplier >& rSupp ) :
	rExport( rExp ),
	sPrefix( OUString::createFromAscii( "N" ) ),
	pFormatter( NULL ),
	pCharClass( NULL ),
	pLocaleData( NULL )
{
	//	supplier must be SvNumberFormatsSupplierObj
	SvNumberFormatsSupplierObj* pObj =
					SvNumberFormatsSupplierObj::getImplementation( rSupp );
	if (pObj)
		pFormatter = pObj->GetNumberFormatter();

	if ( pFormatter )
	{
		pCharClass = new CharClass( pFormatter->GetServiceManager(),
			pFormatter->GetLocale() );
		pLocaleData = new LocaleDataWrapper( pFormatter->GetServiceManager(),
			pFormatter->GetLocale() );
	}
	else
	{
		lang::Locale aLocale( MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage() ) );

		// #110680#
		// pCharClass = new CharClass( ::comphelper::getProcessServiceFactory(), aLocale );
		// pLocaleData = new LocaleDataWrapper( ::comphelper::getProcessServiceFactory(), aLocale );
		pCharClass = new CharClass( rExport.getServiceFactory(), aLocale );
		pLocaleData = new LocaleDataWrapper( rExport.getServiceFactory(), aLocale );
	}

	pUsedList = new SvXMLNumUsedList_Impl;
}

SvXMLNumFmtExport::SvXMLNumFmtExport(
                       SvXMLExport& rExp,
					   const ::com::sun::star::uno::Reference<
						::com::sun::star::util::XNumberFormatsSupplier >& rSupp,
					   const rtl::OUString& rPrefix ) :
	rExport( rExp ),
	sPrefix( rPrefix ),
	pFormatter( NULL ),
	pCharClass( NULL ),
	pLocaleData( NULL )
{
	//	supplier must be SvNumberFormatsSupplierObj
	SvNumberFormatsSupplierObj* pObj =
					SvNumberFormatsSupplierObj::getImplementation( rSupp );
	if (pObj)
		pFormatter = pObj->GetNumberFormatter();

	if ( pFormatter )
	{
		pCharClass = new CharClass( pFormatter->GetServiceManager(),
			pFormatter->GetLocale() );
		pLocaleData = new LocaleDataWrapper( pFormatter->GetServiceManager(),
			pFormatter->GetLocale() );
	}
	else
	{
		lang::Locale aLocale( MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage() ) );

		// #110680#
		// pCharClass = new CharClass( ::comphelper::getProcessServiceFactory(), aLocale );
		// pLocaleData = new LocaleDataWrapper( ::comphelper::getProcessServiceFactory(), aLocale );
		pCharClass = new CharClass( rExport.getServiceFactory(), aLocale );
		pLocaleData = new LocaleDataWrapper( rExport.getServiceFactory(), aLocale );
	}

	pUsedList = new SvXMLNumUsedList_Impl;
}

SvXMLNumFmtExport::~SvXMLNumFmtExport()
{
	delete pUsedList;
	delete pLocaleData;
	delete pCharClass;
}

//-------------------------------------------------------------------------

//
//	helper methods
//

OUString lcl_CreateStyleName( sal_Int32 nKey, sal_Int32 nPart, sal_Bool bDefPart, const rtl::OUString& rPrefix )
{
	OUStringBuffer aFmtName( 10L );
	aFmtName.append( rPrefix );
	aFmtName.append( nKey );
	if (!bDefPart)
	{
		aFmtName.append( (sal_Unicode)'P' );
		aFmtName.append( nPart );
	}
	return aFmtName.makeStringAndClear();
}

void SvXMLNumFmtExport::AddCalendarAttr_Impl( const OUString& rCalendar )
{
	if ( rCalendar.getLength() )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_CALENDAR, rCalendar );
	}
}

void SvXMLNumFmtExport::AddTextualAttr_Impl( sal_Bool bText )
{
	if ( bText )			// non-textual
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TRUE );
	}
}

void SvXMLNumFmtExport::AddStyleAttr_Impl( sal_Bool bLong )
{
	if ( bLong )			// short is default
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_STYLE, XML_LONG );
	}
}

void SvXMLNumFmtExport::AddLanguageAttr_Impl( sal_Int32 nLang )
{
	if ( nLang != LANGUAGE_SYSTEM )
	{
		OUString aLangStr, aCountryStr;
        MsLangId::convertLanguageToIsoNames( (LanguageType)nLang, aLangStr, aCountryStr );

		if (aLangStr.getLength())
			rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_LANGUAGE, aLangStr );
		if (aCountryStr.getLength())
			rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_COUNTRY, aCountryStr );
	}
}

//-------------------------------------------------------------------------

//
//	methods to write individual elements within a format
//

void SvXMLNumFmtExport::AddToTextElement_Impl( const OUString& rString )
{
	//	append to sTextContent, write element in FinishTextElement_Impl
	//	to avoid several text elements following each other

	sTextContent.append( rString );
}

void SvXMLNumFmtExport::FinishTextElement_Impl()
{
	if ( sTextContent.getLength() )
	{
        SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT,
                                  sal_True, sal_False );
		rExport.Characters( sTextContent.makeStringAndClear() );
	}
}

void SvXMLNumFmtExport::WriteColorElement_Impl( const Color& rColor )
{
	FinishTextElement_Impl();

	OUStringBuffer aColStr( 7 );
	SvXMLUnitConverter::convertColor( aColStr, rColor );
	rExport.AddAttribute( XML_NAMESPACE_FO, XML_COLOR,
                          aColStr.makeStringAndClear() );

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteCurrencyElement_Impl( const OUString& rString,
													const OUString& rExt )
{
	FinishTextElement_Impl();

	if ( rExt.getLength() )
	{
		sal_Int32 nLang = rExt.toInt32(16);		// hex
		if ( nLang < 0 )						// extension string may contain "-" separator
			nLang = -nLang;
		AddLanguageAttr_Impl( nLang );			// adds to pAttrList
	}

    SvXMLElementExport aElem( rExport,
                              XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL,
                              sal_True, sal_False );
	rExport.Characters( rString );
}

void SvXMLNumFmtExport::WriteBooleanElement_Impl()
{
	FinishTextElement_Impl();

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_BOOLEAN,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteTextContentElement_Impl()
{
	FinishTextElement_Impl();

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT,
                              sal_True, sal_False );
}

//	date elements

void SvXMLNumFmtExport::WriteDayElement_Impl( const OUString& rCalendar, sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_DAY,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteMonthElement_Impl( const OUString& rCalendar, sal_Bool bLong, sal_Bool bText )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
	AddStyleAttr_Impl( bLong );		// adds to pAttrList
	AddTextualAttr_Impl( bText );	// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_MONTH,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteYearElement_Impl( const OUString& rCalendar, sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_YEAR,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteEraElement_Impl( const OUString& rCalendar, sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_ERA,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteDayOfWeekElement_Impl( const OUString& rCalendar, sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteWeekElement_Impl( const OUString& rCalendar )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteQuarterElement_Impl( const OUString& rCalendar, sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_QUARTER,
                              sal_True, sal_False );
}

//	time elements

void SvXMLNumFmtExport::WriteHoursElement_Impl( sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_HOURS,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteMinutesElement_Impl( sal_Bool bLong )
{
	FinishTextElement_Impl();

	AddStyleAttr_Impl( bLong );		// adds to pAttrList

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_MINUTES,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteSecondsElement_Impl( sal_Bool bLong, sal_uInt16 nDecimals )
{
	FinishTextElement_Impl();

	AddStyleAttr_Impl( bLong );		// adds to pAttrList
	if ( nDecimals > 0 )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
                              OUString::valueOf( (sal_Int32) nDecimals ) );
	}

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_SECONDS,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteAMPMElement_Impl()
{
	FinishTextElement_Impl();

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_AM_PM,
                              sal_True, sal_False );
}

//	numbers

void SvXMLNumFmtExport::WriteNumberElement_Impl(
							sal_Int32 nDecimals, sal_Int32 nInteger,
							const OUString& rDashStr, sal_Bool bVarDecimals,
							sal_Bool bGrouping, sal_Int32 nTrailingThousands,
							const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
{
	FinishTextElement_Impl();

	//	decimals
	if ( nDecimals >= 0 )	// negative = automatic
	{
        rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
                              OUString::valueOf( nDecimals ) );
	}

	//	integer digits
	if ( nInteger >= 0 )	// negative = automatic
	{
        rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
                              OUString::valueOf( nInteger ) );
	}

	//	decimal replacement (dashes) or variable decimals (#)
	if ( rDashStr.getLength() || bVarDecimals )
	{
		//	variable decimals means an empty replacement string
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT,
                              rDashStr );
	}

	//	(automatic) grouping separator
	if ( bGrouping )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
	}

	//	display-factor if there are trailing thousands separators
	if ( nTrailingThousands )
	{
		//	each separator character removes three digits
		double fFactor = ::rtl::math::pow10Exp( 1.0, 3 * nTrailingThousands );

		OUStringBuffer aFactStr;
		SvXMLUnitConverter::convertDouble( aFactStr, fFactor );
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, aFactStr.makeStringAndClear() );
	}

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_NUMBER,
                              sal_True, sal_True );

	//	number:embedded-text as child elements

	sal_uInt16 nEntryCount = rEmbeddedEntries.Count();
	for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
	{
		SvXMLEmbeddedTextEntry* pObj = rEmbeddedEntries[nEntry];

		//	position attribute
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_POSITION,
								OUString::valueOf( pObj->nFormatPos ) );
	    SvXMLElementExport aChildElem( rExport, XML_NAMESPACE_NUMBER, XML_EMBEDDED_TEXT,
			                              sal_True, sal_False );

		//	text as element content
        rtl::OUString aContent( pObj->aText );
        while ( nEntry+1 < nEntryCount && rEmbeddedEntries[nEntry+1]->nFormatPos == pObj->nFormatPos )
        {
            // The array can contain several elements for the same position in the number
            // (for example, literal text and space from underscores). They must be merged
            // into a single embedded-text element.
            aContent += rEmbeddedEntries[nEntry+1]->aText;
            ++nEntry;
        }
        rExport.Characters( aContent );
	}
}

void SvXMLNumFmtExport::WriteScientificElement_Impl(
							sal_Int32 nDecimals, sal_Int32 nInteger,
							sal_Bool bGrouping, sal_Int32 nExp )
{
	FinishTextElement_Impl();

	//	decimals
	if ( nDecimals >= 0 )	// negative = automatic
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
                              OUString::valueOf( nDecimals ) );
	}

	//	integer digits
	if ( nInteger >= 0 )	// negative = automatic
	{
        rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
                              OUString::valueOf( nInteger ) );
	}

	//	(automatic) grouping separator
	if ( bGrouping )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
	}

	//	exponent digits
	if ( nExp >= 0 )
	{
        rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS,
                              OUString::valueOf( nExp ) );
	}

    SvXMLElementExport aElem( rExport,
                              XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER,
                              sal_True, sal_False );
}

void SvXMLNumFmtExport::WriteFractionElement_Impl(
							sal_Int32 nInteger, sal_Bool bGrouping,
							sal_Int32 nNumerator, sal_Int32 nDenominator )
{
	FinishTextElement_Impl();

	//	integer digits
	if ( nInteger >= 0 )		// negative = default (no integer part)
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
                              OUString::valueOf( nInteger ) );
	}

	//	(automatic) grouping separator
	if ( bGrouping )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
	}

	//	numerator digits
	if ( nNumerator >= 0 )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,
                                 OUString::valueOf( nNumerator ) );
	}

	//	denominator digits
	if ( nDenominator >= 0 )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS,
                              OUString::valueOf( nDenominator ) );
	}

    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_FRACTION,
                              sal_True, sal_False );
}

//	mapping (condition)

void SvXMLNumFmtExport::WriteMapElement_Impl( sal_Int32 nOp, double fLimit,
												sal_Int32 nKey, sal_Int32 nPart )
{
	FinishTextElement_Impl();

	if ( nOp != NUMBERFORMAT_OP_NO )
	{
		// style namespace

		OUStringBuffer aCondStr( 20L );
		aCondStr.appendAscii( "value()" );			//! define constant
		switch ( nOp )
		{
			case NUMBERFORMAT_OP_EQ: aCondStr.append( (sal_Unicode) '=' );	break;
			case NUMBERFORMAT_OP_NE: aCondStr.appendAscii( "<>" );			break;
			case NUMBERFORMAT_OP_LT: aCondStr.append( (sal_Unicode) '<' );	break;
			case NUMBERFORMAT_OP_LE: aCondStr.appendAscii( "<=" );			break;
			case NUMBERFORMAT_OP_GT: aCondStr.append( (sal_Unicode) '>' );	break;
			case NUMBERFORMAT_OP_GE: aCondStr.appendAscii( ">=" );			break;
			default:
				DBG_ERROR("unknown operator");
		}
        ::rtl::math::doubleToUStringBuffer( aCondStr, fLimit,
                rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
                '.', true );

		rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_CONDITION,
                              aCondStr.makeStringAndClear() );

		rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_APPLY_STYLE_NAME,
                              rExport.EncodeStyleName( lcl_CreateStyleName( nKey, nPart, sal_False,
                                                   sPrefix ) ) );

        SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_MAP,
                                  sal_True, sal_False );
	}
}

//-------------------------------------------------------------------------
//	for old (automatic) currency formats: parse currency symbol from text

xub_StrLen lcl_FindSymbol( const String& sUpperStr, const String& sCurString )
{
	//	search for currency symbol
	//	Quoting as in ImpSvNumberformatScan::Symbol_Division

	xub_StrLen nCPos = 0;
	while (nCPos != STRING_NOTFOUND)
	{
		nCPos = sUpperStr.Search( sCurString, nCPos );
		if (nCPos != STRING_NOTFOUND)
		{
			// in Quotes?
			xub_StrLen nQ = SvNumberformat::GetQuoteEnd( sUpperStr, nCPos );
			if ( nQ == STRING_NOTFOUND )
			{
				//	dm can be escaped as "dm or \d
				sal_Unicode c;
				if ( nCPos == 0 ||
					((c = sUpperStr.GetChar(xub_StrLen(nCPos-1))) != '"'
							&& c != '\\') )
				{
					return nCPos;					// found
				}
				else
					nCPos++;						// continue
			}
			else
				nCPos = nQ + 1;						// continue after quote end
		}
	}
	return STRING_NOTFOUND;							// not found
}

sal_Bool SvXMLNumFmtExport::WriteTextWithCurrency_Impl( const OUString& rString,
							const ::com::sun::star::lang::Locale& rLocale )
{
	//	returns sal_True if currency element was written

	sal_Bool bRet = sal_False;

//	pLocaleData->setLocale( rLocale );
//	String sCurString = pLocaleData->getCurrSymbol();

	LanguageType nLang = MsLangId::convertLocaleToLanguage( rLocale );
	pFormatter->ChangeIntl( nLang );
	String sCurString, sDummy;
	pFormatter->GetCompatibilityCurrency( sCurString, sDummy );

	pCharClass->setLocale( rLocale );
	String sUpperStr = pCharClass->upper(rString);
	xub_StrLen nPos = lcl_FindSymbol( sUpperStr, sCurString );
	if ( nPos != STRING_NOTFOUND )
	{
		sal_Int32 nLength = rString.getLength();
		sal_Int32 nCurLen = sCurString.Len();
		sal_Int32 nCont = nPos + nCurLen;

		//	text before currency symbol
		if ( nPos > 0 )
			AddToTextElement_Impl( rString.copy( 0, nPos ) );

		//	currency symbol (empty string -> default)
		OUString sEmpty;
		WriteCurrencyElement_Impl( sEmpty, sEmpty );
		bRet = sal_True;

		//	text after currency symbol
		if ( nCont < nLength )
			AddToTextElement_Impl( rString.copy( nCont, nLength-nCont ) );
	}
	else
		AddToTextElement_Impl( rString );		// simple text

	return bRet;		// sal_True: currency element written
}

//-------------------------------------------------------------------------

OUString lcl_GetDefaultCalendar( SvNumberFormatter* pFormatter, LanguageType nLang )
{
	//	get name of first non-gregorian calendar for the language

	OUString aCalendar;
	CalendarWrapper* pCalendar = pFormatter->GetCalendar();
	if (pCalendar)
	{
		lang::Locale aLocale( MsLangId::convertLanguageToLocale( nLang ) );

		uno::Sequence<OUString> aCals = pCalendar->getAllCalendars( aLocale );
		sal_Int32 nCnt = aCals.getLength();
		sal_Bool bFound = sal_False;
		for ( sal_Int32 j=0; j < nCnt && !bFound; j++ )
		{
			if ( !aCals[j].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("gregorian") ) )
			{
				aCalendar = aCals[j];
				bFound = sal_True;
			}
		}
	}
	return aCalendar;
}

//-------------------------------------------------------------------------

sal_Bool lcl_IsInEmbedded( const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries, sal_uInt16 nPos )
{
	sal_uInt16 nCount = rEmbeddedEntries.Count();
	for (sal_uInt16 i=0; i<nCount; i++)
		if ( rEmbeddedEntries[i]->nSourcePos == nPos )
			return sal_True;

	return sal_False;		// not found
}

sal_Bool lcl_IsDefaultDateFormat( const SvNumberformat& rFormat, sal_Bool bSystemDate, NfIndexTableOffset eBuiltIn )
{
	//	make an extra loop to collect date elements, to check if it is a default format
	//	before adding the automatic-order attribute

	SvXMLDateElementAttributes eDateDOW = XML_DEA_NONE;
	SvXMLDateElementAttributes eDateDay = XML_DEA_NONE;
	SvXMLDateElementAttributes eDateMonth = XML_DEA_NONE;
	SvXMLDateElementAttributes eDateYear = XML_DEA_NONE;
	SvXMLDateElementAttributes eDateHours = XML_DEA_NONE;
	SvXMLDateElementAttributes eDateMins = XML_DEA_NONE;
	SvXMLDateElementAttributes eDateSecs = XML_DEA_NONE;
	sal_Bool bDateNoDefault = sal_False;

	sal_uInt16 nPos = 0;
	sal_Bool bEnd = sal_False;
	short nLastType = 0;
	while (!bEnd)
	{
		short nElemType = rFormat.GetNumForType( 0, nPos, sal_False );
		switch ( nElemType )
		{
			case 0:
				if ( nLastType == NF_SYMBOLTYPE_STRING )
					bDateNoDefault = sal_True;	// text at the end -> no default date format
				bEnd = sal_True;				// end of format reached
				break;
			case NF_SYMBOLTYPE_STRING:
			case NF_SYMBOLTYPE_DATESEP:
			case NF_SYMBOLTYPE_TIMESEP:
			case NF_SYMBOLTYPE_TIME100SECSEP:
				// text is ignored, except at the end
				break;
			// same mapping as in SvXMLNumFormatContext::AddNfKeyword:
			case NF_KEY_NN:		eDateDOW = XML_DEA_SHORT;		break;
			case NF_KEY_NNN:
			case NF_KEY_NNNN:	eDateDOW = XML_DEA_LONG;		break;
			case NF_KEY_D:		eDateDay = XML_DEA_SHORT;		break;
			case NF_KEY_DD:		eDateDay = XML_DEA_LONG;		break;
			case NF_KEY_M:		eDateMonth = XML_DEA_SHORT;		break;
			case NF_KEY_MM:		eDateMonth = XML_DEA_LONG;		break;
			case NF_KEY_MMM:	eDateMonth = XML_DEA_TEXTSHORT;	break;
			case NF_KEY_MMMM:	eDateMonth = XML_DEA_TEXTLONG;	break;
			case NF_KEY_YY:		eDateYear = XML_DEA_SHORT;		break;
			case NF_KEY_YYYY:	eDateYear = XML_DEA_LONG;		break;
			case NF_KEY_H:		eDateHours = XML_DEA_SHORT;		break;
			case NF_KEY_HH:		eDateHours = XML_DEA_LONG;		break;
			case NF_KEY_MI:		eDateMins = XML_DEA_SHORT;		break;
			case NF_KEY_MMI:	eDateMins = XML_DEA_LONG;		break;
			case NF_KEY_S:		eDateSecs = XML_DEA_SHORT;		break;
			case NF_KEY_SS:		eDateSecs = XML_DEA_LONG;		break;
			case NF_KEY_AP:
			case NF_KEY_AMPM:	break;			// AM/PM may or may not be in date/time formats -> ignore by itself
			default:
				bDateNoDefault = sal_True;		// any other element -> no default format
		}
		nLastType = nElemType;
		++nPos;
	}

	if ( bDateNoDefault )
		return sal_False;						// additional elements
	else
	{
		NfIndexTableOffset eFound = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat(
				eDateDOW, eDateDay, eDateMonth, eDateYear, eDateHours, eDateMins, eDateSecs, bSystemDate );

		return ( eFound == eBuiltIn );
	}
}

//
//	export one part (condition)
//

void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey,
											sal_uInt16 nPart, sal_Bool bDefPart )
{
	//!	for the default part, pass the conditions from the other parts!

	//
	//	element name
	//

	NfIndexTableOffset eBuiltIn = pFormatter->GetIndexTableOffset( nKey );

	short nFmtType = 0;
	sal_Bool bThousand = sal_False;
	sal_uInt16 nPrecision = 0;
	sal_uInt16 nLeading = 0;
	rFormat.GetNumForInfo( nPart, nFmtType, bThousand, nPrecision, nLeading);
	nFmtType &= ~NUMBERFORMAT_DEFINED;

	//	special treatment of builtin formats that aren't detected by normal parsing
	//	(the same formats that get the type set in SvNumberFormatter::ImpGenerateFormats)
	if ( eBuiltIn == NF_NUMBER_STANDARD )
		nFmtType = NUMBERFORMAT_NUMBER;
	else if ( eBuiltIn == NF_BOOLEAN )
		nFmtType = NUMBERFORMAT_LOGICAL;
	else if ( eBuiltIn == NF_TEXT )
		nFmtType = NUMBERFORMAT_TEXT;

    // #101606# An empty subformat is a valid number-style resulting in an
    // empty display string for the condition of the subformat.
    if ( nFmtType == NUMBERFORMAT_UNDEFINED && rFormat.GetNumForType( nPart,
                0, sal_False ) == 0 )
        nFmtType = 0;

	XMLTokenEnum eType = XML_TOKEN_INVALID;
	switch ( nFmtType )
	{
		// type is 0 if a format contains no recognized elements
		// (like text only) - this is handled as a number-style.
		case 0:
		case NUMBERFORMAT_NUMBER:
		case NUMBERFORMAT_SCIENTIFIC:
		case NUMBERFORMAT_FRACTION:
			eType = XML_NUMBER_STYLE;
			break;
		case NUMBERFORMAT_PERCENT:
			eType = XML_PERCENTAGE_STYLE;
			break;
		case NUMBERFORMAT_CURRENCY:
			eType = XML_CURRENCY_STYLE;
			break;
		case NUMBERFORMAT_DATE:
		case NUMBERFORMAT_DATETIME:
			eType = XML_DATE_STYLE;
			break;
		case NUMBERFORMAT_TIME:
			eType = XML_TIME_STYLE;
			break;
		case NUMBERFORMAT_TEXT:
			eType = XML_TEXT_STYLE;
			break;
		case NUMBERFORMAT_LOGICAL:
			eType = XML_BOOLEAN_STYLE;
			break;
	}
    DBG_ASSERT( eType != XML_TOKEN_INVALID, "unknown format type" );

	OUString sAttrValue;
	sal_Bool bUserDef = ( ( rFormat.GetType() & NUMBERFORMAT_DEFINED ) != 0 );

	//
	//	common attributes for format
	//

	//	format name (generated from key) - style namespace
	rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
                        lcl_CreateStyleName( nKey, nPart, bDefPart, sPrefix ) );

	//	"volatile" attribute for styles used only in maps
	if ( !bDefPart )
		rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TRUE );

	//	language / country
	LanguageType nLang = rFormat.GetLanguage();
	AddLanguageAttr_Impl( nLang );					// adds to pAttrList

	//	title (comment)
	//	titles for builtin formats are not written
	sAttrValue = rFormat.GetComment();
	if ( sAttrValue.getLength() && bUserDef && bDefPart )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TITLE, sAttrValue );
	}

	//	automatic ordering for currency and date formats
	//	only used for some built-in formats
	sal_Bool bAutoOrder = ( eBuiltIn == NF_CURRENCY_1000INT     || eBuiltIn == NF_CURRENCY_1000DEC2 ||
						eBuiltIn == NF_CURRENCY_1000INT_RED || eBuiltIn == NF_CURRENCY_1000DEC2_RED ||
						eBuiltIn == NF_CURRENCY_1000DEC2_DASHED ||
						eBuiltIn == NF_DATE_SYSTEM_SHORT	|| eBuiltIn == NF_DATE_SYSTEM_LONG ||
						eBuiltIn == NF_DATE_SYS_MMYY		|| eBuiltIn == NF_DATE_SYS_DDMMM ||
						eBuiltIn == NF_DATE_SYS_DDMMYYYY	|| eBuiltIn == NF_DATE_SYS_DDMMYY ||
						eBuiltIn == NF_DATE_SYS_DMMMYY		|| eBuiltIn == NF_DATE_SYS_DMMMYYYY ||
						eBuiltIn == NF_DATE_SYS_DMMMMYYYY	|| eBuiltIn == NF_DATE_SYS_NNDMMMYY ||
						eBuiltIn == NF_DATE_SYS_NNDMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNNNDMMMMYYYY ||
						eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM || eBuiltIn == NF_DATETIME_SYS_DDMMYYYY_HHMMSS );

	//	format source (for date and time formats)
	//	only used for some built-in formats
	sal_Bool bSystemDate = ( eBuiltIn == NF_DATE_SYSTEM_SHORT ||
						 eBuiltIn == NF_DATE_SYSTEM_LONG  ||
						 eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM );
	sal_Bool bLongSysDate = ( eBuiltIn == NF_DATE_SYSTEM_LONG );

	// check if the format definition matches the key
	if ( bAutoOrder && ( nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) &&
			!lcl_IsDefaultDateFormat( rFormat, bSystemDate, eBuiltIn ) )
	{
		bAutoOrder = bSystemDate = bLongSysDate = sal_False;		// don't write automatic-order attribute then
	}

	if ( bAutoOrder &&
		( nFmtType == NUMBERFORMAT_CURRENCY || nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) )
	{
		//	#85109# format type must be checked to avoid dtd errors if
		//	locale data contains other format types at the built-in positions

		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER,
                              XML_TRUE );
	}

	if ( bSystemDate && bAutoOrder &&
		( nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) )
	{
		//	#85109# format type must be checked to avoid dtd errors if
		//	locale data contains other format types at the built-in positions

		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE,
                              XML_LANGUAGE );
	}

	//	overflow for time formats as in [hh]:mm
	//	controlled by bThousand from number format info
	//	default for truncate-on-overflow is true
	if ( nFmtType == NUMBERFORMAT_TIME && bThousand )
	{
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW,
                              XML_FALSE );
	}

    //
    // Native number transliteration
    //
    ::com::sun::star::i18n::NativeNumberXmlAttributes aAttr;
    rFormat.GetNatNumXml( aAttr, nPart );
    if ( aAttr.Format.getLength() )
    {
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT,
                              aAttr.Format );
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE,
                              aAttr.Locale.Language );
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY,
                              aAttr.Locale.Country );
		rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE,
                              aAttr.Style );
    }

    //
    // The element
    //
    SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, eType,
                              sal_True, sal_True );

	//
	//	color (properties element)
	//

	const Color* pCol = rFormat.GetColor( nPart );
	if (pCol)
		WriteColorElement_Impl(*pCol);


	//	detect if there is "real" content, excluding color and maps
	//!	move to implementation of Write... methods?
	sal_Bool bAnyContent = sal_False;

	//
	//	format elements
	//

	SvXMLEmbeddedTextEntryArr aEmbeddedEntries(0);
	if ( eBuiltIn == NF_NUMBER_STANDARD )
	{
		//	default number format contains just one number element
		WriteNumberElement_Impl( -1, 1, OUString(), sal_False, sal_False, 0, aEmbeddedEntries );
		bAnyContent = sal_True;
	}
	else if ( eBuiltIn == NF_BOOLEAN )
	{
		//	boolean format contains just one boolean element
		WriteBooleanElement_Impl();
		bAnyContent = sal_True;
	}
	else
	{
		//	first loop to collect attributes

		sal_Bool bDecDashes  = sal_False;
		sal_Bool bVarDecimals = sal_False;
		sal_Bool bExpFound   = sal_False;
		sal_Bool bCurrFound  = sal_False;
		sal_Bool bInInteger  = sal_True;
		sal_Int32 nExpDigits = 0;
		sal_Int32 nIntegerSymbols = 0;			// for embedded-text, including "#"
		sal_Int32 nTrailingThousands = 0;		// thousands-separators after all digits
		OUString sCurrExt;
		OUString aCalendar;
		sal_uInt16 nPos = 0;
		sal_Bool bEnd = sal_False;
		while (!bEnd)
		{
			short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False );
			const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False );

			switch ( nElemType )
			{
				case 0:
					bEnd = sal_True;				// end of format reached
					break;
				case NF_SYMBOLTYPE_DIGIT:
					if ( bExpFound && pElemStr )
						nExpDigits += pElemStr->Len();
					else if ( !bDecDashes && pElemStr && pElemStr->GetChar(0) == '-' )
						bDecDashes = sal_True;
					else if ( !bVarDecimals && !bInInteger && pElemStr && pElemStr->GetChar(0) == '#' )
					{
						//	If the decimal digits string starts with a '#', variable
						//	decimals is assumed (for 0.###, but not 0.0##).
						bVarDecimals = sal_True;
					}
					if ( bInInteger && pElemStr )
						nIntegerSymbols += pElemStr->Len();
					nTrailingThousands = 0;
					break;
				case NF_SYMBOLTYPE_DECSEP:
					bInInteger = sal_False;
					break;
				case NF_SYMBOLTYPE_THSEP:
					if (pElemStr)
						nTrailingThousands += pElemStr->Len();		// is reset to 0 if digits follow
					break;
				case NF_SYMBOLTYPE_EXP:
					bExpFound = sal_True;			// following digits are exponent digits
					bInInteger = sal_False;
					break;
				case NF_SYMBOLTYPE_CURRENCY:
					bCurrFound = sal_True;
					break;
				case NF_SYMBOLTYPE_CURREXT:
					if (pElemStr)
						sCurrExt = *pElemStr;
					break;

				// E, EE, R, RR: select non-gregorian calendar
				// AAA, AAAA: calendar is switched at the position of the element
				case NF_KEY_EC:
				case NF_KEY_EEC:
				case NF_KEY_R:
				case NF_KEY_RR:
					if (!aCalendar.getLength())
						aCalendar = lcl_GetDefaultCalendar( pFormatter, nLang );
					break;
			}
			++nPos;
		}

		//	collect strings for embedded-text (must be known before number element is written)

		sal_Bool bAllowEmbedded = ( nFmtType == 0 || nFmtType == NUMBERFORMAT_NUMBER ||
										nFmtType == NUMBERFORMAT_CURRENCY ||
										nFmtType == NUMBERFORMAT_PERCENT );
		if ( bAllowEmbedded )
		{
			sal_Int32 nDigitsPassed = 0;
			nPos = 0;
			bEnd = sal_False;
			while (!bEnd)
			{
				short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False );
				const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False );

				switch ( nElemType )
				{
					case 0:
						bEnd = sal_True;				// end of format reached
						break;
					case NF_SYMBOLTYPE_DIGIT:
						if ( pElemStr )
							nDigitsPassed += pElemStr->Len();
						break;
					case NF_SYMBOLTYPE_STRING:
                    case NF_SYMBOLTYPE_BLANK:
                    case NF_SYMBOLTYPE_PERCENT:
						if ( nDigitsPassed > 0 && nDigitsPassed < nIntegerSymbols && pElemStr )
						{
                            //	text (literal or underscore) within the integer part of a number:number element

                            String aEmbeddedStr;
                            if ( nElemType == NF_SYMBOLTYPE_STRING || nElemType == NF_SYMBOLTYPE_PERCENT )
                                aEmbeddedStr = *pElemStr;
                            else
                                SvNumberformat::InsertBlanks( aEmbeddedStr, 0, pElemStr->GetChar(1) );

							sal_Int32 nEmbedPos = nIntegerSymbols - nDigitsPassed;

							SvXMLEmbeddedTextEntry* pObj = new SvXMLEmbeddedTextEntry( nPos, nEmbedPos, aEmbeddedStr );
							aEmbeddedEntries.Insert( pObj, aEmbeddedEntries.Count() );
						}
						break;
				}
				++nPos;
			}
		}

		//	final loop to write elements

		sal_Bool bNumWritten = sal_False;
		sal_Bool bCurrencyWritten = sal_False;
		short nPrevType = 0;
		nPos = 0;
		bEnd = sal_False;
		while (!bEnd)
		{
			short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False );
			const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False );

			switch ( nElemType )
			{
				case 0:
					bEnd = sal_True;				// end of format reached
					break;
				case NF_SYMBOLTYPE_STRING:
                case NF_SYMBOLTYPE_DATESEP:
                case NF_SYMBOLTYPE_TIMESEP:
                case NF_SYMBOLTYPE_TIME100SECSEP:
                case NF_SYMBOLTYPE_PERCENT:
					if (pElemStr)
					{
						if ( ( nPrevType == NF_KEY_S || nPrevType == NF_KEY_SS ) &&
							 ( nElemType == NF_SYMBOLTYPE_TIME100SECSEP ) &&
							 nPrecision > 0 )
						{
							//	decimal separator after seconds is implied by
							//	"decimal-places" attribute and must not be written
							//	as text element
							//!	difference between '.' and ',' is lost here
						}
						else if ( lcl_IsInEmbedded( aEmbeddedEntries, nPos ) )
						{
							//	text is written as embedded-text child of the number,
							//	don't create a text element
						}
						else if ( nFmtType == NUMBERFORMAT_CURRENCY && !bCurrFound && !bCurrencyWritten )
						{
							//	automatic currency symbol is implemented as part of
							//	normal text -> search for the symbol
							bCurrencyWritten = WriteTextWithCurrency_Impl( *pElemStr,
								MsLangId::convertLanguageToLocale( nLang ) );
							bAnyContent = sal_True;
						}
						else
							AddToTextElement_Impl( *pElemStr );
					}
					break;
				case NF_SYMBOLTYPE_BLANK:
					if ( pElemStr && !lcl_IsInEmbedded( aEmbeddedEntries, nPos ) )
					{
						//	turn "_x" into the number of spaces used for x in InsertBlanks in the NumberFormat
                        //  (#i20396# the spaces may also be in embedded-text elements)

						String aBlanks;
						SvNumberformat::InsertBlanks( aBlanks, 0, pElemStr->GetChar(1) );
						AddToTextElement_Impl( aBlanks );
					}
					break;
                case NF_KEY_GENERAL :
                        WriteNumberElement_Impl( -1, 1, OUString(), sal_False, sal_False, 0, aEmbeddedEntries );
                    break;
				case NF_KEY_CCC:
					if (pElemStr)
					{
						if ( bCurrencyWritten )
							AddToTextElement_Impl( *pElemStr );		// never more than one currency element
						else
						{
							//!	must be different from short automatic format
							//!	but should still be empty (meaning automatic)
							//	pElemStr is "CCC"

							WriteCurrencyElement_Impl( *pElemStr, OUString() );
							bAnyContent = sal_True;
							bCurrencyWritten = sal_True;
						}
					}
					break;
				case NF_SYMBOLTYPE_CURRENCY:
					if (pElemStr)
					{
						if ( bCurrencyWritten )
							AddToTextElement_Impl( *pElemStr );		// never more than one currency element
						else
						{
							WriteCurrencyElement_Impl( *pElemStr, sCurrExt );
							bAnyContent = sal_True;
							bCurrencyWritten = sal_True;
						}
					}
					break;
				case NF_SYMBOLTYPE_DIGIT:
					if (!bNumWritten)			// write number part
					{
						switch ( nFmtType )
						{
							// for type 0 (not recognized as a special type),
							// write a "normal" number
							case 0:
							case NUMBERFORMAT_NUMBER:
							case NUMBERFORMAT_CURRENCY:
							case NUMBERFORMAT_PERCENT:
								{
									//	decimals
									//	only some built-in formats have automatic decimals
									sal_Int32 nDecimals = nPrecision;	// from GetFormatSpecialInfo
									if ( eBuiltIn == NF_NUMBER_STANDARD ||
										 eBuiltIn == NF_CURRENCY_1000DEC2 ||
										 eBuiltIn == NF_CURRENCY_1000DEC2_RED ||
										 eBuiltIn == NF_CURRENCY_1000DEC2_CCC ||
										 eBuiltIn == NF_CURRENCY_1000DEC2_DASHED )
										nDecimals = -1;

									//	integer digits
									//	only one built-in format has automatic integer digits
									sal_Int32 nInteger = nLeading;
									if ( eBuiltIn == NF_NUMBER_SYSTEM )
										nInteger = -1;

									//	string for decimal replacement
									//	has to be taken from nPrecision
									//	(positive number even for automatic decimals)
									String sDashStr;
									if ( bDecDashes && nPrecision > 0 )
										sDashStr.Fill( nPrecision, '-' );

									WriteNumberElement_Impl( nDecimals, nInteger, sDashStr, bVarDecimals,
														bThousand, nTrailingThousands, aEmbeddedEntries );
									bAnyContent = sal_True;
								}
								break;
							case NUMBERFORMAT_SCIENTIFIC:
                                // #i43959# for scientific numbers, count all integer symbols ("0" and "#")
                                // as integer digits: use nIntegerSymbols instead of nLeading
                                // (use of '#' to select multiples in exponent might be added later)
                                WriteScientificElement_Impl( nPrecision, nIntegerSymbols, bThousand, nExpDigits );
								bAnyContent = sal_True;
								break;
							case NUMBERFORMAT_FRACTION:
                                {
                                    sal_Int32 nInteger = nLeading;
                                    if ( pElemStr && pElemStr->GetChar(0) == '?' )
                                    {
                                        //  If the first digit character is a question mark,
                                        //  the fraction doesn't have an integer part, and no
                                        //  min-integer-digits attribute must be written.
                                        nInteger = -1;
                                    }
                                    WriteFractionElement_Impl( nInteger, bThousand, nPrecision, nPrecision );
                                    bAnyContent = sal_True;
                                }
								break;
						}

						bNumWritten = sal_True;
					}
					break;
                case NF_SYMBOLTYPE_DECSEP:
                    if ( pElemStr && nPrecision == 0 )
                    {
                        //  A decimal separator after the number, without following decimal digits,
                        //  isn't modelled as part of the number element, so it's written as text
                        //  (the distinction between a quoted and non-quoted, locale-dependent
                        //  character is lost here).

                        AddToTextElement_Impl( *pElemStr );
                    }
                    break;
				case NF_SYMBOLTYPE_DEL:
					if ( pElemStr && *pElemStr == XubString('@') )
					{
						WriteTextContentElement_Impl();
						bAnyContent = sal_True;
					}
					break;

				case NF_SYMBOLTYPE_CALENDAR:
					if ( pElemStr )
						aCalendar = *pElemStr;
					break;

				// date elements:

				case NF_KEY_D:
				case NF_KEY_DD:
					{
						sal_Bool bLong = ( nElemType == NF_KEY_DD );
						WriteDayElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
						bAnyContent = sal_True;
					}
					break;
				case NF_KEY_DDD:
				case NF_KEY_DDDD:
				case NF_KEY_NN:
				case NF_KEY_NNN:
				case NF_KEY_NNNN:
				case NF_KEY_AAA:
				case NF_KEY_AAAA:
					{
						OUString aCalAttr = aCalendar;
						if ( nElemType == NF_KEY_AAA || nElemType == NF_KEY_AAAA )
						{
							//	calendar attribute for AAA and AAAA is switched only for this element
							if (!aCalAttr.getLength())
								aCalAttr = lcl_GetDefaultCalendar( pFormatter, nLang );
						}

						sal_Bool bLong = ( nElemType == NF_KEY_NNN || nElemType == NF_KEY_NNNN ||
										   nElemType == NF_KEY_DDDD || nElemType == NF_KEY_AAAA );
						WriteDayOfWeekElement_Impl( aCalAttr, ( bSystemDate ? bLongSysDate : bLong ) );
						bAnyContent = sal_True;
						if ( nElemType == NF_KEY_NNNN )
						{
							//	write additional text element for separator
							pLocaleData->setLocale( MsLangId::convertLanguageToLocale( nLang ) );
							AddToTextElement_Impl( pLocaleData->getLongDateDayOfWeekSep() );
						}
					}
					break;
				case NF_KEY_M:
				case NF_KEY_MM:
				case NF_KEY_MMM:
				case NF_KEY_MMMM:
				case NF_KEY_MMMMM:		//! first letter of month name, no attribute available
					{
						sal_Bool bLong = ( nElemType == NF_KEY_MM  || nElemType == NF_KEY_MMMM );
						sal_Bool bText = ( nElemType == NF_KEY_MMM || nElemType == NF_KEY_MMMM ||
											nElemType == NF_KEY_MMMMM );
						WriteMonthElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ), bText );
						bAnyContent = sal_True;
					}
					break;
				case NF_KEY_YY:
				case NF_KEY_YYYY:
				case NF_KEY_EC:
				case NF_KEY_EEC:
				case NF_KEY_R:		//! R acts as EE, no attribute available
					{
						//! distinguish EE and R
						//	calendar attribute for E and EE and R is set in first loop
						sal_Bool bLong = ( nElemType == NF_KEY_YYYY || nElemType == NF_KEY_EEC ||
											nElemType == NF_KEY_R );
						WriteYearElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
						bAnyContent = sal_True;
					}
					break;
				case NF_KEY_G:
				case NF_KEY_GG:
				case NF_KEY_GGG:
				case NF_KEY_RR:		//! RR acts as GGGEE, no attribute available
					{
						//!	distinguish GG and GGG and RR
						sal_Bool bLong = ( nElemType == NF_KEY_GGG || nElemType == NF_KEY_RR );
						WriteEraElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
						bAnyContent = sal_True;
						if ( nElemType == NF_KEY_RR )
						{
							//	calendar attribute for RR is set in first loop
							WriteYearElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : sal_True ) );
						}
					}
					break;
				case NF_KEY_Q:
				case NF_KEY_QQ:
					{
						sal_Bool bLong = ( nElemType == NF_KEY_QQ );
						WriteQuarterElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
						bAnyContent = sal_True;
					}
					break;
				case NF_KEY_WW:
					WriteWeekElement_Impl( aCalendar );
					bAnyContent = sal_True;
					break;

				// time elements (bSystemDate is not used):

				case NF_KEY_H:
				case NF_KEY_HH:
					WriteHoursElement_Impl( nElemType == NF_KEY_HH );
					bAnyContent = sal_True;
					break;
				case NF_KEY_MI:
				case NF_KEY_MMI:
					WriteMinutesElement_Impl( nElemType == NF_KEY_MMI );
					bAnyContent = sal_True;
					break;
				case NF_KEY_S:
				case NF_KEY_SS:
					WriteSecondsElement_Impl( ( nElemType == NF_KEY_SS ), nPrecision );
					bAnyContent = sal_True;
					break;
				case NF_KEY_AMPM:
				case NF_KEY_AP:
					WriteAMPMElement_Impl();		// short/long?
					bAnyContent = sal_True;
					break;
			}
			nPrevType = nElemType;
			++nPos;
		}
	}

	if ( sTextContent.getLength() )
		bAnyContent = sal_True;		// element written in FinishTextElement_Impl

	FinishTextElement_Impl();		// final text element - before maps

	if ( !bAnyContent )
	{
		//	for an empty format, write an empty text element
        SvXMLElementExport aTElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT,
                                   sal_True, sal_False );
	}

	//
	//	mapping (conditions) must be last elements
	//

	if (bDefPart)
	{
		SvNumberformatLimitOps eOp1, eOp2;
		double fLimit1, fLimit2;
		rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 );

		WriteMapElement_Impl( eOp1, fLimit1, nKey, 0 );
		WriteMapElement_Impl( eOp2, fLimit2, nKey, 1 );

		if ( rFormat.HasTextFormat() )
		{
			//	4th part is for text -> make an "all other numbers" condition for the 3rd part
			//	by reversing the 2nd condition

			SvNumberformatLimitOps eOp3 = NUMBERFORMAT_OP_NO;
			double fLimit3 = fLimit2;
			switch ( eOp2 )
			{
				case NUMBERFORMAT_OP_EQ: eOp3 = NUMBERFORMAT_OP_NE; break;
				case NUMBERFORMAT_OP_NE: eOp3 = NUMBERFORMAT_OP_EQ; break;
				case NUMBERFORMAT_OP_LT: eOp3 = NUMBERFORMAT_OP_GE; break;
				case NUMBERFORMAT_OP_LE: eOp3 = NUMBERFORMAT_OP_GT; break;
				case NUMBERFORMAT_OP_GT: eOp3 = NUMBERFORMAT_OP_LE; break;
				case NUMBERFORMAT_OP_GE: eOp3 = NUMBERFORMAT_OP_LT; break;
				default:
					break;
			}

			if ( fLimit1 == fLimit2 &&
					( ( eOp1 == NUMBERFORMAT_OP_LT && eOp2 == NUMBERFORMAT_OP_GT ) ||
					  ( eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT ) ) )
			{
				//	For <x and >x, add =x as last condition
				//	(just for readability, <=x would be valid, too)

				eOp3 = NUMBERFORMAT_OP_EQ;
			}

			WriteMapElement_Impl( eOp3, fLimit3, nKey, 2 );
		}
	}
}

//-------------------------------------------------------------------------

//
//	export one format
//

void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey )
{
	sal_uInt16 nUsedParts = 0;
	sal_uInt16 nPart;
	for (nPart=0; nPart<XMLNUM_MAX_PARTS; nPart++)
		if (rFormat.GetNumForType( nPart, 0, sal_False ) != 0)
			nUsedParts = nPart+1;

	SvNumberformatLimitOps eOp1, eOp2;
	double fLimit1, fLimit2;
	rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 );

	//	if conditions are set, even empty formats must be written

	if ( eOp1 != NUMBERFORMAT_OP_NO && nUsedParts < 2 )
		nUsedParts = 2;
	if ( eOp2 != NUMBERFORMAT_OP_NO && nUsedParts < 3 )
		nUsedParts = 3;
	if ( rFormat.HasTextFormat() && nUsedParts < 4 )
		nUsedParts = 4;

	for (nPart=0; nPart<nUsedParts; nPart++)
	{
		sal_Bool bDefault = ( nPart+1 == nUsedParts );			// last = default
		ExportPart_Impl( rFormat, nKey, nPart, bDefault );
	}
}

//-------------------------------------------------------------------------

//
//	export method called by application
//

void SvXMLNumFmtExport::Export( sal_Bool bIsAutoStyle )
{
	if ( !pFormatter )
		return;							// no formatter -> no entries

	sal_uInt32 nKey;
	const SvNumberformat* pFormat = NULL;
	sal_Bool bNext(pUsedList->GetFirstUsed(nKey));
	while(bNext)
	{
		pFormat = pFormatter->GetEntry(nKey);
		if(pFormat)
			ExportFormat_Impl( *pFormat, nKey );
		bNext = pUsedList->GetNextUsed(nKey);
	}
	if (!bIsAutoStyle)
	{
		SvUShorts aLanguages;
		pFormatter->GetUsedLanguages( aLanguages );
		sal_uInt16 nLangCount = aLanguages.Count();
		for (sal_uInt16 nLangPos=0; nLangPos<nLangCount; nLangPos++)
		{
			LanguageType nLang = aLanguages[nLangPos];

			sal_uInt32 nDefaultIndex = 0;
			SvNumberFormatTable& rTable = pFormatter->GetEntryTable(
											NUMBERFORMAT_DEFINED, nDefaultIndex, nLang );
			pFormat = rTable.First();
			while (pFormat)
			{
				nKey = rTable.GetCurKey();
				if (!pUsedList->IsUsed(nKey))
				{
					DBG_ASSERT((pFormat->GetType() & NUMBERFORMAT_DEFINED) != 0, "a not user defined numberformat found");
					//	user-defined and used formats are exported
					ExportFormat_Impl( *pFormat, nKey );
					// if it is a user-defined Format it will be added else nothing will happen
					pUsedList->SetUsed(nKey);
				}

				pFormat = rTable.Next();
			}
		}
	}
	pUsedList->Export();
}

OUString SvXMLNumFmtExport::GetStyleName( sal_uInt32 nKey )
{
	if(pUsedList->IsUsed(nKey) || pUsedList->IsWasUsed(nKey))
		return lcl_CreateStyleName( nKey, 0, sal_True, sPrefix );
	else
	{
		DBG_ERROR("There is no written Data-Style");
		return rtl::OUString();
	}
}

void SvXMLNumFmtExport::SetUsed( sal_uInt32 nKey )
{
    DBG_ASSERT( pFormatter != NULL, "missing formatter" );
    if( !pFormatter )
        return;

	if (pFormatter->GetEntry(nKey))
		pUsedList->SetUsed( nKey );
	else {
		DBG_ERROR("no existing Numberformat found with this key");
    }
}

void SvXMLNumFmtExport::GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed)
{
	if (pUsedList)
		pUsedList->GetWasUsed(rWasUsed);
}

void SvXMLNumFmtExport::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed)
{
	if (pUsedList)
		pUsedList->SetWasUsed(rWasUsed);
}



const SvNumberformat* lcl_GetFormat( SvNumberFormatter* pFormatter,
                           sal_uInt32 nKey )
{
    return ( pFormatter != NULL ) ? pFormatter->GetEntry( nKey ) : NULL;
}

sal_uInt32 SvXMLNumFmtExport::ForceSystemLanguage( sal_uInt32 nKey )
{
    sal_uInt32 nRet = nKey;

    const SvNumberformat* pFormat = lcl_GetFormat( pFormatter, nKey );
    if( pFormat != NULL )
    {
        DBG_ASSERT( pFormatter != NULL, "format without formatter?" );

        xub_StrLen nErrorPos;
        short nType = pFormat->GetType();

        sal_uInt32 nNewKey = pFormatter->GetFormatForLanguageIfBuiltIn(
                       nKey, LANGUAGE_SYSTEM );

        if( nNewKey != nKey )
        {
            nRet = nNewKey;
        }
        else
        {
            String aFormatString( pFormat->GetFormatstring() );
            pFormatter->PutandConvertEntry(
                            aFormatString,
                            nErrorPos, nType, nNewKey,
                            pFormat->GetLanguage(), LANGUAGE_SYSTEM );

            // success? Then use new key.
            if( nErrorPos == 0 )
                nRet = nNewKey;
        }
    }

    return nRet;
}
