|  | /************************************************************** | 
|  | * | 
|  | * 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 coditions 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; | 
|  | } |