summaryrefslogtreecommitdiff
path: root/xmloff/source/style/xmlnumfi.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmloff/source/style/xmlnumfi.cxx')
-rw-r--r--xmloff/source/style/xmlnumfi.cxx2418
1 files changed, 2418 insertions, 0 deletions
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
new file mode 100644
index 000000000000..a192baa2216b
--- /dev/null
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -0,0 +1,2418 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_xmloff.hxx"
+
+#include <unotools/syslocale.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <svl/zforlist.hxx>
+
+#include <svl/zformat.hxx>
+#include <svl/numuno.hxx>
+#include <rtl/math.hxx>
+#include <i18npool/mslangid.hxx>
+#include <tools/debug.hxx>
+#include <rtl/ustrbuf.hxx>
+
+// #110680#
+//#include <comphelper/processfactory.hxx>
+
+#include <xmloff/xmlnumfi.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include "xmlnmspe.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+//-------------------------------------------------------------------------
+
+struct SvXMLNumFmtEntry
+{
+ rtl::OUString aName;
+ sal_uInt32 nKey;
+ sal_Bool bRemoveAfterUse;
+
+ SvXMLNumFmtEntry( const rtl::OUString& rN, sal_uInt32 nK, sal_Bool bR ) :
+ aName(rN), nKey(nK), bRemoveAfterUse(bR) {}
+};
+
+typedef SvXMLNumFmtEntry* SvXMLNumFmtEntryPtr;
+SV_DECL_PTRARR_DEL( SvXMLNumFmtEntryArr, SvXMLNumFmtEntryPtr, 4, 4 )
+
+struct SvXMLEmbeddedElement
+{
+ sal_Int32 nFormatPos;
+ rtl::OUString aText;
+
+ SvXMLEmbeddedElement( sal_Int32 nFP, const rtl::OUString& rT ) :
+ nFormatPos(nFP), aText(rT) {}
+
+ // comparison operators for PTRARR sorting - sorted by position
+ BOOL operator ==( const SvXMLEmbeddedElement& r ) const { return nFormatPos == r.nFormatPos; }
+ BOOL operator < ( const SvXMLEmbeddedElement& r ) const { return nFormatPos < r.nFormatPos; }
+};
+
+typedef SvXMLEmbeddedElement* SvXMLEmbeddedElementPtr;
+SV_DECL_PTRARR_SORT_DEL( SvXMLEmbeddedElementArr, SvXMLEmbeddedElementPtr, 0, 4 )
+
+//-------------------------------------------------------------------------
+
+class SvXMLNumImpData
+{
+ SvNumberFormatter* pFormatter;
+ SvXMLTokenMap* pStylesElemTokenMap;
+ SvXMLTokenMap* pStyleElemTokenMap;
+ SvXMLTokenMap* pStyleAttrTokenMap;
+ SvXMLTokenMap* pStyleElemAttrTokenMap;
+ LocaleDataWrapper* pLocaleData;
+ SvXMLNumFmtEntryArr aNameEntries;
+
+ // #110680#
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceFactory;
+
+public:
+ // #110680#
+ // SvXMLNumImpData( SvNumberFormatter* pFmt );
+ SvXMLNumImpData(
+ SvNumberFormatter* pFmt,
+ const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory );
+ ~SvXMLNumImpData();
+
+ SvNumberFormatter* GetNumberFormatter() const { return pFormatter; }
+ const SvXMLTokenMap& GetStylesElemTokenMap();
+ const SvXMLTokenMap& GetStyleElemTokenMap();
+ const SvXMLTokenMap& GetStyleAttrTokenMap();
+ const SvXMLTokenMap& GetStyleElemAttrTokenMap();
+ const LocaleDataWrapper& GetLocaleData( LanguageType nLang );
+ sal_uInt32 GetKeyForName( const rtl::OUString& rName );
+ void AddKey( sal_uInt32 nKey, const rtl::OUString& rName, sal_Bool bRemoveAfterUse );
+ void SetUsed( sal_uInt32 nKey );
+ void RemoveVolatileFormats();
+};
+
+
+struct SvXMLNumberInfo
+{
+ sal_Int32 nDecimals;
+ sal_Int32 nInteger;
+ sal_Int32 nExpDigits;
+ sal_Int32 nNumerDigits;
+ sal_Int32 nDenomDigits;
+ sal_Bool bGrouping;
+ sal_Bool bDecReplace;
+ sal_Bool bVarDecimals;
+ double fDisplayFactor;
+ SvXMLEmbeddedElementArr aEmbeddedElements;
+
+ SvXMLNumberInfo()
+ {
+ nDecimals = nInteger = nExpDigits = nNumerDigits = nDenomDigits = -1;
+ bGrouping = bDecReplace = bVarDecimals = sal_False;
+ fDisplayFactor = 1.0;
+ }
+};
+
+class SvXMLNumFmtElementContext : public SvXMLImportContext
+{
+ SvXMLNumFormatContext& rParent;
+ sal_uInt16 nType;
+ rtl::OUStringBuffer aContent;
+ SvXMLNumberInfo aNumInfo;
+ LanguageType nElementLang;
+ sal_Bool bLong;
+ sal_Bool bTextual;
+ rtl::OUString sCalendar;
+
+public:
+ SvXMLNumFmtElementContext( SvXMLImport& rImport, USHORT nPrfx,
+ const rtl::OUString& rLName,
+ SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual ~SvXMLNumFmtElementContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual void Characters( const rtl::OUString& rChars );
+ virtual void EndElement();
+
+ void AddEmbeddedElement( sal_Int32 nFormatPos, const rtl::OUString& rContent );
+};
+
+
+class SvXMLNumFmtEmbeddedTextContext : public SvXMLImportContext
+{
+ SvXMLNumFmtElementContext& rParent;
+ rtl::OUStringBuffer aContent;
+ sal_Int32 nTextPosition;
+
+public:
+ SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, USHORT nPrfx,
+ const rtl::OUString& rLName,
+ SvXMLNumFmtElementContext& rParentContext,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual ~SvXMLNumFmtEmbeddedTextContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual void Characters( const rtl::OUString& rChars );
+ virtual void EndElement();
+};
+
+
+class SvXMLNumFmtMapContext : public SvXMLImportContext
+{
+ SvXMLNumFormatContext& rParent;
+ rtl::OUString sCondition;
+ rtl::OUString sName;
+
+public:
+ SvXMLNumFmtMapContext( SvXMLImport& rImport, USHORT nPrfx,
+ const rtl::OUString& rLName,
+ SvXMLNumFormatContext& rParentContext,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual ~SvXMLNumFmtMapContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual void Characters( const rtl::OUString& rChars );
+ virtual void EndElement();
+};
+
+
+class SvXMLNumFmtPropContext : public SvXMLImportContext
+{
+ SvXMLNumFormatContext& rParent;
+ Color aColor;
+ sal_Bool bColSet;
+
+public:
+ SvXMLNumFmtPropContext( SvXMLImport& rImport, USHORT nPrfx,
+ const rtl::OUString& rLName,
+ SvXMLNumFormatContext& rParentContext,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual ~SvXMLNumFmtPropContext();
+
+ virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+ virtual void Characters( const rtl::OUString& rChars );
+ virtual void EndElement();
+};
+
+
+//-------------------------------------------------------------------------
+
+enum SvXMLStyleTokens
+{
+ XML_TOK_STYLE_TEXT,
+ XML_TOK_STYLE_NUMBER,
+ XML_TOK_STYLE_SCIENTIFIC_NUMBER,
+ XML_TOK_STYLE_FRACTION,
+ XML_TOK_STYLE_CURRENCY_SYMBOL,
+ XML_TOK_STYLE_DAY,
+ XML_TOK_STYLE_MONTH,
+ XML_TOK_STYLE_YEAR,
+ XML_TOK_STYLE_ERA,
+ XML_TOK_STYLE_DAY_OF_WEEK,
+ XML_TOK_STYLE_WEEK_OF_YEAR,
+ XML_TOK_STYLE_QUARTER,
+ XML_TOK_STYLE_HOURS,
+ XML_TOK_STYLE_AM_PM,
+ XML_TOK_STYLE_MINUTES,
+ XML_TOK_STYLE_SECONDS,
+ XML_TOK_STYLE_BOOLEAN,
+ XML_TOK_STYLE_TEXT_CONTENT,
+ XML_TOK_STYLE_PROPERTIES,
+ XML_TOK_STYLE_MAP
+};
+
+enum SvXMLStyleAttrTokens
+{
+ XML_TOK_STYLE_ATTR_NAME,
+ XML_TOK_STYLE_ATTR_LANGUAGE,
+ XML_TOK_STYLE_ATTR_COUNTRY,
+ XML_TOK_STYLE_ATTR_TITLE,
+ XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER,
+ XML_TOK_STYLE_ATTR_FORMAT_SOURCE,
+ XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW,
+ XML_TOK_STYLE_ATTR_VOLATILE,
+ XML_TOK_STYLE_ATTR_TRANSL_FORMAT,
+ XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE,
+ XML_TOK_STYLE_ATTR_TRANSL_COUNTRY,
+ XML_TOK_STYLE_ATTR_TRANSL_STYLE
+};
+
+enum SvXMLStyleElemAttrTokens
+{
+ XML_TOK_ELEM_ATTR_DECIMAL_PLACES,
+ XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS,
+ XML_TOK_ELEM_ATTR_GROUPING,
+ XML_TOK_ELEM_ATTR_DISPLAY_FACTOR,
+ XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT,
+ XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS,
+ XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS,
+ XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS,
+ XML_TOK_ELEM_ATTR_LANGUAGE,
+ XML_TOK_ELEM_ATTR_COUNTRY,
+ XML_TOK_ELEM_ATTR_STYLE,
+ XML_TOK_ELEM_ATTR_TEXTUAL,
+ XML_TOK_ELEM_ATTR_CALENDAR
+};
+
+//-------------------------------------------------------------------------
+
+//
+// standard colors
+//
+
+#define XML_NUMF_COLORCOUNT 10
+
+static ColorData aNumFmtStdColors[XML_NUMF_COLORCOUNT] =
+{
+ COL_BLACK,
+ COL_LIGHTBLUE,
+ COL_LIGHTGREEN,
+ COL_LIGHTCYAN,
+ COL_LIGHTRED,
+ COL_LIGHTMAGENTA,
+ COL_BROWN,
+ COL_GRAY,
+ COL_YELLOW,
+ COL_WHITE
+};
+
+//
+// token maps
+//
+
+// maps for SvXMLUnitConverter::convertEnum
+
+static __FAR_DATA SvXMLEnumMapEntry aStyleValueMap[] =
+{
+ { XML_SHORT, sal_False },
+ { XML_LONG, sal_True },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+static __FAR_DATA SvXMLEnumMapEntry aFormatSourceMap[] =
+{
+ { XML_FIXED, sal_False },
+ { XML_LANGUAGE, sal_True },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+//-------------------------------------------------------------------------
+
+struct SvXMLDefaultDateFormat
+{
+ NfIndexTableOffset eFormat;
+ SvXMLDateElementAttributes eDOW;
+ SvXMLDateElementAttributes eDay;
+ SvXMLDateElementAttributes eMonth;
+ SvXMLDateElementAttributes eYear;
+ SvXMLDateElementAttributes eHours;
+ SvXMLDateElementAttributes eMins;
+ SvXMLDateElementAttributes eSecs;
+ sal_Bool bSystem;
+};
+
+static __FAR_DATA SvXMLDefaultDateFormat aDefaultDateFormats[] =
+{
+ // format day-of-week day month year hours minutes seconds format-source
+
+ { NF_DATE_SYSTEM_SHORT, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_True },
+ { NF_DATE_SYSTEM_LONG, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_True },
+ { NF_DATE_SYS_MMYY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_DDMMM, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_TEXTSHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_DDMMYYYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_DDMMYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_DMMMYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_DMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_DMMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_NNDMMMYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_NNDMMMMYYYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATE_SYS_NNNNDMMMMYYYY, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False },
+ { NF_DATETIME_SYSTEM_SHORT_HHMM, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, sal_True },
+ { NF_DATETIME_SYS_DDMMYYYY_HHMMSS, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, sal_False }
+};
+
+//-------------------------------------------------------------------------
+
+SV_IMPL_PTRARR( SvXMLNumFmtEntryArr, SvXMLNumFmtEntryPtr );
+SV_IMPL_OP_PTRARR_SORT( SvXMLEmbeddedElementArr, SvXMLEmbeddedElementPtr );
+
+//-------------------------------------------------------------------------
+
+//
+// SvXMLNumImpData
+//
+
+// #110680#
+// SvXMLNumImpData::SvXMLNumImpData( SvNumberFormatter* pFmt ) :
+SvXMLNumImpData::SvXMLNumImpData(
+ SvNumberFormatter* pFmt,
+ const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory )
+: pFormatter(pFmt),
+ pStylesElemTokenMap(NULL),
+ pStyleElemTokenMap(NULL),
+ pStyleAttrTokenMap(NULL),
+ pStyleElemAttrTokenMap(NULL),
+ pLocaleData(NULL),
+
+ // #110680#
+ mxServiceFactory(xServiceFactory)
+{
+ DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
+}
+
+SvXMLNumImpData::~SvXMLNumImpData()
+{
+ delete pStylesElemTokenMap;
+ delete pStyleElemTokenMap;
+ delete pStyleAttrTokenMap;
+ delete pStyleElemAttrTokenMap;
+ delete pLocaleData;
+}
+
+sal_uInt32 SvXMLNumImpData::GetKeyForName( const rtl::OUString& rName )
+{
+ USHORT nCount = aNameEntries.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const SvXMLNumFmtEntry* pObj = aNameEntries[i];
+ if ( pObj->aName == rName )
+ return pObj->nKey; // found
+ }
+ return NUMBERFORMAT_ENTRY_NOT_FOUND;
+}
+
+void SvXMLNumImpData::AddKey( sal_uInt32 nKey, const rtl::OUString& rName, sal_Bool bRemoveAfterUse )
+{
+ if ( bRemoveAfterUse )
+ {
+ // if there is already an entry for this key without the bRemoveAfterUse flag,
+ // clear the flag for this entry, too
+
+ USHORT nCount = aNameEntries.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvXMLNumFmtEntry* pObj = aNameEntries[i];
+ if ( pObj->nKey == nKey && !pObj->bRemoveAfterUse )
+ {
+ bRemoveAfterUse = sal_False; // clear flag for new entry
+ break;
+ }
+ }
+ }
+ else
+ {
+ // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
+ SetUsed( nKey );
+ }
+
+ SvXMLNumFmtEntry* pObj = new SvXMLNumFmtEntry( rName, nKey, bRemoveAfterUse );
+ aNameEntries.Insert( pObj, aNameEntries.Count() );
+}
+
+void SvXMLNumImpData::SetUsed( sal_uInt32 nKey )
+{
+ USHORT nCount = aNameEntries.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvXMLNumFmtEntry* pObj = aNameEntries[i];
+ if ( pObj->nKey == nKey )
+ {
+ pObj->bRemoveAfterUse = sal_False; // used -> don't remove
+
+ // continue searching - there may be several entries for the same key
+ // (with different names), the format must not be deleted if any one of
+ // them is used
+ }
+ }
+}
+
+void SvXMLNumImpData::RemoveVolatileFormats()
+{
+ // remove temporary (volatile) formats from NumberFormatter
+ // called at the end of each import (styles and content), so volatile formats
+ // from styles can't be used in content
+
+ if ( !pFormatter )
+ return;
+
+ USHORT nCount = aNameEntries.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const SvXMLNumFmtEntry* pObj = aNameEntries[i];
+ if ( pObj->bRemoveAfterUse )
+ {
+ const SvNumberformat* pFormat = pFormatter->GetEntry(pObj->nKey);
+ if (pFormat && (pFormat->GetType() & NUMBERFORMAT_DEFINED))
+ pFormatter->DeleteEntry( pObj->nKey );
+ }
+ }
+}
+
+const SvXMLTokenMap& SvXMLNumImpData::GetStylesElemTokenMap()
+{
+ if( !pStylesElemTokenMap )
+ {
+ static __FAR_DATA SvXMLTokenMapEntry aStylesElemMap[] =
+ {
+ // style elements
+ { XML_NAMESPACE_NUMBER, XML_NUMBER_STYLE, XML_TOK_STYLES_NUMBER_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_CURRENCY_STYLE, XML_TOK_STYLES_CURRENCY_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_PERCENTAGE_STYLE, XML_TOK_STYLES_PERCENTAGE_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_DATE_STYLE, XML_TOK_STYLES_DATE_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_TIME_STYLE, XML_TOK_STYLES_TIME_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_BOOLEAN_STYLE, XML_TOK_STYLES_BOOLEAN_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_TEXT_STYLE, XML_TOK_STYLES_TEXT_STYLE },
+ XML_TOKEN_MAP_END
+ };
+
+ pStylesElemTokenMap = new SvXMLTokenMap( aStylesElemMap );
+ }
+ return *pStylesElemTokenMap;
+}
+
+const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemTokenMap()
+{
+ if( !pStyleElemTokenMap )
+ {
+ static __FAR_DATA SvXMLTokenMapEntry aStyleElemMap[] =
+ {
+ // elements in a style
+ { XML_NAMESPACE_NUMBER, XML_TEXT, XML_TOK_STYLE_TEXT },
+ { XML_NAMESPACE_NUMBER, XML_NUMBER, XML_TOK_STYLE_NUMBER },
+ { XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER, XML_TOK_STYLE_SCIENTIFIC_NUMBER },
+ { XML_NAMESPACE_NUMBER, XML_FRACTION, XML_TOK_STYLE_FRACTION },
+ { XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL, XML_TOK_STYLE_CURRENCY_SYMBOL },
+ { XML_NAMESPACE_NUMBER, XML_DAY, XML_TOK_STYLE_DAY },
+ { XML_NAMESPACE_NUMBER, XML_MONTH, XML_TOK_STYLE_MONTH },
+ { XML_NAMESPACE_NUMBER, XML_YEAR, XML_TOK_STYLE_YEAR },
+ { XML_NAMESPACE_NUMBER, XML_ERA, XML_TOK_STYLE_ERA },
+ { XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK, XML_TOK_STYLE_DAY_OF_WEEK },
+ { XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR, XML_TOK_STYLE_WEEK_OF_YEAR },
+ { XML_NAMESPACE_NUMBER, XML_QUARTER, XML_TOK_STYLE_QUARTER },
+ { XML_NAMESPACE_NUMBER, XML_HOURS, XML_TOK_STYLE_HOURS },
+ { XML_NAMESPACE_NUMBER, XML_AM_PM, XML_TOK_STYLE_AM_PM },
+ { XML_NAMESPACE_NUMBER, XML_MINUTES, XML_TOK_STYLE_MINUTES },
+ { XML_NAMESPACE_NUMBER, XML_SECONDS, XML_TOK_STYLE_SECONDS },
+ { XML_NAMESPACE_NUMBER, XML_BOOLEAN, XML_TOK_STYLE_BOOLEAN },
+ { XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT, XML_TOK_STYLE_TEXT_CONTENT },
+ { XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES, XML_TOK_STYLE_PROPERTIES },
+ { XML_NAMESPACE_STYLE, XML_MAP, XML_TOK_STYLE_MAP },
+ XML_TOKEN_MAP_END
+ };
+
+ pStyleElemTokenMap = new SvXMLTokenMap( aStyleElemMap );
+ }
+ return *pStyleElemTokenMap;
+}
+
+const SvXMLTokenMap& SvXMLNumImpData::GetStyleAttrTokenMap()
+{
+ if( !pStyleAttrTokenMap )
+ {
+ static __FAR_DATA SvXMLTokenMapEntry aStyleAttrMap[] =
+ {
+ // attributes for a style
+ { XML_NAMESPACE_STYLE, XML_NAME, XML_TOK_STYLE_ATTR_NAME },
+ { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_STYLE_ATTR_LANGUAGE },
+ { XML_NAMESPACE_NUMBER, XML_COUNTRY, XML_TOK_STYLE_ATTR_COUNTRY },
+ { XML_NAMESPACE_NUMBER, XML_TITLE, XML_TOK_STYLE_ATTR_TITLE },
+ { XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER },
+ { XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE, XML_TOK_STYLE_ATTR_FORMAT_SOURCE },
+ { XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW, XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW },
+ { XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TOK_STYLE_ATTR_VOLATILE },
+ { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT, XML_TOK_STYLE_ATTR_TRANSL_FORMAT },
+ { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE },
+ { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY },
+ { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE, XML_TOK_STYLE_ATTR_TRANSL_STYLE },
+ XML_TOKEN_MAP_END
+ };
+
+ pStyleAttrTokenMap = new SvXMLTokenMap( aStyleAttrMap );
+ }
+ return *pStyleAttrTokenMap;
+}
+
+const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemAttrTokenMap()
+{
+ if( !pStyleElemAttrTokenMap )
+ {
+ static __FAR_DATA SvXMLTokenMapEntry aStyleElemAttrMap[] =
+ {
+ // attributes for an element within a style
+ { XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES, XML_TOK_ELEM_ATTR_DECIMAL_PLACES },
+ { XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS, XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS },
+ { XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TOK_ELEM_ATTR_GROUPING },
+ { XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, XML_TOK_ELEM_ATTR_DISPLAY_FACTOR },
+ { XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT, XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT },
+ { XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS, XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS },
+ { XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS, XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS },
+ { XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS, XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS },
+ { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_ELEM_ATTR_LANGUAGE },
+ { XML_NAMESPACE_NUMBER, XML_COUNTRY, XML_TOK_ELEM_ATTR_COUNTRY },
+ { XML_NAMESPACE_NUMBER, XML_STYLE, XML_TOK_ELEM_ATTR_STYLE },
+ { XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TOK_ELEM_ATTR_TEXTUAL },
+ { XML_NAMESPACE_NUMBER, XML_CALENDAR, XML_TOK_ELEM_ATTR_CALENDAR },
+ XML_TOKEN_MAP_END
+ };
+
+ pStyleElemAttrTokenMap = new SvXMLTokenMap( aStyleElemAttrMap );
+ }
+ return *pStyleElemAttrTokenMap;
+}
+
+const LocaleDataWrapper& SvXMLNumImpData::GetLocaleData( LanguageType nLang )
+{
+ if ( !pLocaleData )
+ // #110680#
+ //pLocaleData = new LocaleDataWrapper(
+ // (pFormatter ? pFormatter->GetServiceManager() :
+ // ::comphelper::getProcessServiceFactory()),
+ // MsLangId::convertLanguageToLocale( nLang ) );
+ pLocaleData = new LocaleDataWrapper(
+ (pFormatter ? pFormatter->GetServiceManager() :
+ mxServiceFactory),
+ MsLangId::convertLanguageToLocale( nLang ) );
+ else
+ pLocaleData->setLocale( MsLangId::convertLanguageToLocale( nLang ) );
+ return *pLocaleData;
+}
+
+//-------------------------------------------------------------------------
+
+//
+// SvXMLNumFmtMapContext
+//
+
+SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport& rImport,
+ USHORT nPrfx, const rtl::OUString& rLName,
+ SvXMLNumFormatContext& rParentContext,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport, nPrfx, rLName ),
+ rParent( rParentContext )
+{
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for( sal_Int16 i=0; i < nAttrCount; i++ )
+ {
+ OUString sAttrName = xAttrList->getNameByIndex( i );
+ OUString sValue = xAttrList->getValueByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+ if ( nPrefix == XML_NAMESPACE_STYLE )
+ {
+ if ( IsXMLToken( aLocalName, XML_CONDITION) )
+ sCondition = sValue;
+ else if ( IsXMLToken( aLocalName, XML_APPLY_STYLE_NAME) )
+ sName = sValue;
+ }
+ }
+}
+
+SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext()
+{
+}
+
+SvXMLImportContext* SvXMLNumFmtMapContext::CreateChildContext(
+ USHORT nPrfx, const rtl::OUString& rLName,
+ const uno::Reference<xml::sax::XAttributeList>& )
+{
+ // no elements supported - use default context
+ return new SvXMLImportContext( GetImport(), nPrfx, rLName );
+}
+
+void SvXMLNumFmtMapContext::Characters( const rtl::OUString& )
+{
+}
+
+void SvXMLNumFmtMapContext::EndElement()
+{
+ rParent.AddCondition( sCondition, sName );
+}
+
+//-------------------------------------------------------------------------
+
+//
+// SvXMLNumFmtPropContext
+//
+
+SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport& rImport,
+ USHORT nPrfx, const rtl::OUString& rLName,
+ SvXMLNumFormatContext& rParentContext,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport, nPrfx, rLName ),
+ rParent( rParentContext ),
+ bColSet( sal_False )
+{
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for( sal_Int16 i=0; i < nAttrCount; i++ )
+ {
+ OUString sAttrName = xAttrList->getNameByIndex( i );
+ OUString sValue = xAttrList->getValueByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+ if ( nPrefix == XML_NAMESPACE_FO && IsXMLToken( aLocalName, XML_COLOR ) )
+ bColSet = SvXMLUnitConverter::convertColor( aColor, sValue );
+ }
+}
+
+SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext()
+{
+}
+
+SvXMLImportContext* SvXMLNumFmtPropContext::CreateChildContext(
+ USHORT nPrfx, const rtl::OUString& rLName,
+ const uno::Reference<xml::sax::XAttributeList>& )
+{
+ // no elements supported - use default context
+ return new SvXMLImportContext( GetImport(), nPrfx, rLName );
+}
+
+void SvXMLNumFmtPropContext::Characters( const rtl::OUString& )
+{
+}
+
+void SvXMLNumFmtPropContext::EndElement()
+{
+ if (bColSet)
+ rParent.AddColor( aColor );
+}
+
+//-------------------------------------------------------------------------
+
+//
+// SvXMLNumFmtEmbeddedTextContext
+//
+
+SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport,
+ USHORT nPrfx, const rtl::OUString& rLName,
+ SvXMLNumFmtElementContext& rParentContext,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport, nPrfx, rLName ),
+ rParent( rParentContext ),
+ nTextPosition( 0 )
+{
+ sal_Int32 nAttrVal;
+
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for( sal_Int16 i=0; i < nAttrCount; i++ )
+ {
+ OUString sAttrName = xAttrList->getNameByIndex( i );
+ OUString sValue = xAttrList->getValueByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+ if ( nPrefix == XML_NAMESPACE_NUMBER && IsXMLToken( aLocalName, XML_POSITION ) )
+ {
+ if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
+ nTextPosition = nAttrVal;
+ }
+ }
+}
+
+SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext()
+{
+}
+
+SvXMLImportContext* SvXMLNumFmtEmbeddedTextContext::CreateChildContext(
+ USHORT nPrfx, const rtl::OUString& rLName,
+ const uno::Reference<xml::sax::XAttributeList>& )
+{
+ // no elements supported - use default context
+ return new SvXMLImportContext( GetImport(), nPrfx, rLName );
+}
+
+void SvXMLNumFmtEmbeddedTextContext::Characters( const rtl::OUString& rChars )
+{
+ aContent.append( rChars );
+}
+
+void SvXMLNumFmtEmbeddedTextContext::EndElement()
+{
+ rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() );
+}
+
+//-------------------------------------------------------------------------
+
+sal_Bool lcl_ValidChar( sal_Unicode cChar, const SvXMLNumFormatContext& rParent )
+{
+ sal_uInt16 nFormatType = rParent.GetType();
+
+ // Treat space equal to non-breaking space separator.
+ const sal_Unicode cNBSP = 0x00A0;
+ sal_Unicode cTS;
+ if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE ||
+ nFormatType == XML_TOK_STYLES_CURRENCY_STYLE ||
+ nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) &&
+ (cChar == (cTS = rParent.GetLocaleData().getNumThousandSep().GetChar(0)) ||
+ (cChar == ' ' && cTS == cNBSP)) )
+ {
+ // #i22394# Extra occurrences of thousands separator must be quoted, so they
+ // aren't mis-interpreted as display-factor.
+ // This must be limited to the format types that can contain a number element,
+ // because the same character can be a date separator that should not be quoted
+ // in date formats.
+
+ return sal_False; // force quotes
+ }
+
+ // see ImpSvNumberformatScan::Next_Symbol
+ if ( cChar == ' ' ||
+ cChar == '-' ||
+ cChar == '/' ||
+ cChar == '.' ||
+ cChar == ',' ||
+ cChar == ':' ||
+ cChar == '\'' )
+ return sal_True; // for all format types
+
+ // percent sign must be used without quotes for percentage styles only
+ if ( nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE && cChar == '%' )
+ return sal_True;
+
+ // don't put quotes around single parentheses (often used for negative numbers)
+ if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE ||
+ nFormatType == XML_TOK_STYLES_CURRENCY_STYLE ||
+ nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) &&
+ ( cChar == '(' || cChar == ')' ) )
+ return sal_True;
+
+ return sal_False;
+}
+
+void lcl_EnquoteIfNecessary( rtl::OUStringBuffer& rContent, const SvXMLNumFormatContext& rParent )
+{
+ sal_Bool bQuote = sal_True;
+ sal_Int32 nLength = rContent.getLength();
+
+ if ( ( nLength == 1 &&
+ lcl_ValidChar( rContent.charAt(0), rParent ) ) ||
+ ( nLength == 2 &&
+ lcl_ValidChar( rContent.charAt(0), rParent ) &&
+ rContent.charAt(1) == ' ' ) )
+ {
+ // don't quote single separator characters like space or percent,
+ // or separator characters followed by space (used in date formats)
+ bQuote = sal_False;
+ }
+ else if ( rParent.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE && nLength > 1 )
+ {
+ // the percent character in percentage styles must be left out of quoting
+ // (one occurence is enough even if there are several percent characters in the string)
+
+ rtl::OUString aString( rContent.getStr() );
+ sal_Int32 nPos = aString.indexOf( (sal_Unicode) '%' );
+ if ( nPos >= 0 )
+ {
+ if ( nPos + 1 < nLength )
+ {
+ if ( nPos + 2 == nLength && lcl_ValidChar( rContent.charAt(nPos + 1), rParent ) )
+ {
+ // single character that doesn't need quoting
+ }
+ else
+ {
+ // quote text behind percent character
+ rContent.insert( nPos + 1, (sal_Unicode) '"' );
+ rContent.append( (sal_Unicode) '"' );
+ }
+ }
+ if ( nPos > 0 )
+ {
+ if ( nPos == 1 && lcl_ValidChar( rContent.charAt(0), rParent ) )
+ {
+ // single character that doesn't need quoting
+ }
+ else
+ {
+ // quote text before percent character
+ rContent.insert( nPos, (sal_Unicode) '"' );
+ rContent.insert( 0, (sal_Unicode) '"' );
+ }
+ }
+ bQuote = sal_False;
+ }
+ // else: normal quoting (below)
+ }
+
+ if ( bQuote )
+ {
+ // #i55469# quotes in the string itself have to be escaped
+ rtl::OUString aString( rContent.getStr() );
+ bool bEscape = ( aString.indexOf( (sal_Unicode) '"' ) >= 0 );
+ if ( bEscape )
+ {
+ // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
+ // and a quote to resume quoting.
+ rtl::OUString aInsert( rtl::OUString::createFromAscii( "\"\\\"" ) );
+
+ sal_Int32 nPos = 0;
+ while ( nPos < rContent.getLength() )
+ {
+ if ( rContent.charAt( nPos ) == (sal_Unicode) '"' )
+ {
+ rContent.insert( nPos, aInsert );
+ nPos += aInsert.getLength();
+ }
+ ++nPos;
+ }
+ }
+
+ // quote string literals
+ rContent.insert( 0, (sal_Unicode) '"' );
+ rContent.append( (sal_Unicode) '"' );
+
+ // remove redundant double quotes at start or end
+ if ( bEscape )
+ {
+ if ( rContent.getLength() > 2 &&
+ rContent.charAt(0) == (sal_Unicode) '"' &&
+ rContent.charAt(1) == (sal_Unicode) '"' )
+ {
+ String aTrimmed( rContent.makeStringAndClear().copy(2) );
+ rContent = rtl::OUStringBuffer( aTrimmed );
+ }
+
+ sal_Int32 nLen = rContent.getLength();
+ if ( nLen > 2 &&
+ rContent.charAt(nLen-1) == (sal_Unicode) '"' &&
+ rContent.charAt(nLen-2) == (sal_Unicode) '"' )
+ {
+ String aTrimmed( rContent.makeStringAndClear().copy( 0, nLen - 2 ) );
+ rContent = rtl::OUStringBuffer( aTrimmed );
+ }
+ }
+ }
+}
+
+//
+// SvXMLNumFmtElementContext
+//
+
+SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
+ USHORT nPrfx, const rtl::OUString& rLName,
+ SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport, nPrfx, rLName ),
+ rParent( rParentContext ),
+ nType( nNewType ),
+ nElementLang( LANGUAGE_SYSTEM ),
+ bLong( FALSE ),
+ bTextual( FALSE )
+{
+ OUString sLanguage, sCountry;
+ sal_Int32 nAttrVal;
+ sal_Bool bAttrBool;
+ sal_uInt16 nAttrEnum;
+ double fAttrDouble;
+
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for( sal_Int16 i=0; i < nAttrCount; i++ )
+ {
+ OUString sAttrName = xAttrList->getNameByIndex( i );
+ OUString sValue = xAttrList->getValueByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+
+ const SvXMLTokenMap& rTokenMap = rParent.GetData()->GetStyleElemAttrTokenMap();
+ sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
+
+ switch (nToken)
+ {
+ case XML_TOK_ELEM_ATTR_DECIMAL_PLACES:
+ if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
+ aNumInfo.nDecimals = nAttrVal;
+ break;
+ case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS:
+ if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
+ aNumInfo.nInteger = nAttrVal;
+ break;
+ case XML_TOK_ELEM_ATTR_GROUPING:
+ if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
+ aNumInfo.bGrouping = bAttrBool;
+ break;
+ case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR:
+ if ( SvXMLUnitConverter::convertDouble( fAttrDouble, sValue ) )
+ aNumInfo.fDisplayFactor = fAttrDouble;
+ break;
+ case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT:
+ if ( sValue.getLength() > 0 )
+ aNumInfo.bDecReplace = sal_True; // only a default string is supported
+ else
+ aNumInfo.bVarDecimals = sal_True; // empty replacement string: variable decimals
+ break;
+ case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS:
+ if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
+ aNumInfo.nExpDigits = nAttrVal;
+ break;
+ case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS:
+ if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
+ aNumInfo.nNumerDigits = nAttrVal;
+ break;
+ case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS:
+ if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) )
+ aNumInfo.nDenomDigits = nAttrVal;
+ break;
+ case XML_TOK_ELEM_ATTR_LANGUAGE:
+ sLanguage = sValue;
+ break;
+ case XML_TOK_ELEM_ATTR_COUNTRY:
+ sCountry = sValue;
+ break;
+ case XML_TOK_ELEM_ATTR_STYLE:
+ if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aStyleValueMap ) )
+ bLong = (sal_Bool) nAttrEnum;
+ break;
+ case XML_TOK_ELEM_ATTR_TEXTUAL:
+ if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
+ bTextual = bAttrBool;
+ break;
+ case XML_TOK_ELEM_ATTR_CALENDAR:
+ sCalendar = sValue;
+ break;
+ }
+ }
+
+ if ( sLanguage.getLength() || sCountry.getLength() )
+ {
+ nElementLang = MsLangId::convertIsoNamesToLanguage( sLanguage, sCountry );
+ if ( nElementLang == LANGUAGE_DONTKNOW )
+ nElementLang = LANGUAGE_SYSTEM; //! error handling for invalid locales?
+ }
+}
+
+SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext()
+{
+}
+
+SvXMLImportContext* SvXMLNumFmtElementContext::CreateChildContext(
+ USHORT nPrfx, const rtl::OUString& rLName,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList )
+{
+ // only number:number supports number:embedded-text child element
+
+ if ( nType == XML_TOK_STYLE_NUMBER &&
+ nPrfx == XML_NAMESPACE_NUMBER && IsXMLToken( rLName, XML_EMBEDDED_TEXT ) )
+ {
+ return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx, rLName, *this, xAttrList );
+ }
+ else
+ return new SvXMLImportContext( GetImport(), nPrfx, rLName );
+}
+
+void SvXMLNumFmtElementContext::Characters( const rtl::OUString& rChars )
+{
+ aContent.append( rChars );
+}
+
+void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos, const rtl::OUString& rContent )
+{
+ if ( rContent.getLength() )
+ {
+ SvXMLEmbeddedElement* pObj = new SvXMLEmbeddedElement( nFormatPos, rContent );
+ if ( !aNumInfo.aEmbeddedElements.Insert( pObj ) )
+ {
+ // there's already an element at this position - append text to existing element
+
+ delete pObj;
+ USHORT nElementCount = aNumInfo.aEmbeddedElements.Count();
+ for (USHORT i=0; i<nElementCount; i++)
+ {
+ pObj = aNumInfo.aEmbeddedElements[i];
+ if ( pObj->nFormatPos == nFormatPos )
+ {
+ pObj->aText += rContent;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void SvXMLNumFmtElementContext::EndElement()
+{
+ sal_Bool bEffLong = bLong;
+ switch (nType)
+ {
+ case XML_TOK_STYLE_TEXT:
+ if ( rParent.HasLongDoW() &&
+ rParent.GetLocaleData().getLongDateDayOfWeekSep() ==
+ String( aContent.getStr() ) )
+ {
+ // skip separator constant after long day of week
+ // (NF_KEY_NNNN contains the separator)
+
+ if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) )
+ {
+ //!aContent.setLength(0); //! doesn't work, #76293#
+ aContent = OUStringBuffer();
+ }
+
+ rParent.SetHasLongDoW( sal_False ); // only once
+ }
+ if ( aContent.getLength() )
+ {
+ lcl_EnquoteIfNecessary( aContent, rParent );
+ rParent.AddToCode( aContent.makeStringAndClear() );
+ }
+ break;
+
+ case XML_TOK_STYLE_NUMBER:
+ rParent.AddNumber( aNumInfo );
+ break;
+
+ case XML_TOK_STYLE_CURRENCY_SYMBOL:
+ rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
+ break;
+
+ case XML_TOK_STYLE_TEXT_CONTENT:
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)'@') );
+ break;
+ case XML_TOK_STYLE_BOOLEAN:
+ // ignored - only default boolean format is supported
+ break;
+
+ case XML_TOK_STYLE_DAY:
+ rParent.UpdateCalendar( sCalendar );
+#if 0
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( rParent.IsFromSystem() )
+ bEffLong = SvXMLNumFmtDefaults::IsSystemLongDay( rParent.GetInternational(), bLong );
+#endif
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_DD : NF_KEY_D ) );
+ break;
+ case XML_TOK_STYLE_MONTH:
+ rParent.UpdateCalendar( sCalendar );
+#if 0
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( rParent.IsFromSystem() )
+ {
+ bEffLong = SvXMLNumFmtDefaults::IsSystemLongMonth( rParent.GetInternational(), bLong );
+ bTextual = SvXMLNumFmtDefaults::IsSystemTextualMonth( rParent.GetInternational(), bLong );
+ }
+#endif
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bTextual
+ ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
+ : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
+ break;
+ case XML_TOK_STYLE_YEAR:
+ rParent.UpdateCalendar( sCalendar );
+#if 0
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( rParent.IsFromSystem() )
+ bEffLong = SvXMLNumFmtDefaults::IsSystemLongYear( rParent.GetInternational(), bLong );
+#endif
+ // Y after G (era) is replaced by E
+ if ( rParent.HasEra() )
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_EEC : NF_KEY_EC ) );
+ else
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
+ break;
+ case XML_TOK_STYLE_ERA:
+ rParent.UpdateCalendar( sCalendar );
+#if 0
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( rParent.IsFromSystem() )
+ bEffLong = SvXMLNumFmtDefaults::IsSystemLongEra( rParent.GetInternational(), bLong );
+#endif
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
+ // HasEra flag is set
+ break;
+ case XML_TOK_STYLE_DAY_OF_WEEK:
+ rParent.UpdateCalendar( sCalendar );
+#if 0
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( rParent.IsFromSystem() )
+ bEffLong = SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( rParent.GetInternational(), bLong );
+#endif
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
+ break;
+ case XML_TOK_STYLE_WEEK_OF_YEAR:
+ rParent.UpdateCalendar( sCalendar );
+ rParent.AddNfKeyword( NF_KEY_WW );
+ break;
+ case XML_TOK_STYLE_QUARTER:
+ rParent.UpdateCalendar( sCalendar );
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_QQ : NF_KEY_Q ) );
+ break;
+ case XML_TOK_STYLE_HOURS:
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_HH : NF_KEY_H ) );
+ break;
+ case XML_TOK_STYLE_AM_PM:
+ //! short/long?
+ rParent.AddNfKeyword( NF_KEY_AMPM );
+ break;
+ case XML_TOK_STYLE_MINUTES:
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
+ break;
+ case XML_TOK_STYLE_SECONDS:
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_SS : NF_KEY_S ) );
+ if ( aNumInfo.nDecimals > 0 )
+ {
+ // manually add the decimal places
+ const String& rSep = rParent.GetLocaleData().getNumDecimalSep();
+ for ( xub_StrLen j=0; j<rSep.Len(); j++ )
+ {
+ rParent.AddToCode( OUString::valueOf( rSep.GetChar(j) ) );
+ }
+ for (sal_Int32 i=0; i<aNumInfo.nDecimals; i++)
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)'0') );
+ }
+ break;
+
+ case XML_TOK_STYLE_FRACTION:
+ {
+ if ( aNumInfo.nInteger >= 0 )
+ {
+ // add integer part only if min-integer-digits attribute is there
+ aNumInfo.nDecimals = 0;
+ rParent.AddNumber( aNumInfo ); // number without decimals
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)' ') );
+ }
+
+ //! build string and add at once
+
+ sal_Int32 i;
+ for (i=0; i<aNumInfo.nNumerDigits; i++)
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)'?') );
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)'/') );
+ for (i=0; i<aNumInfo.nDenomDigits; i++)
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)'?') );
+ }
+ break;
+
+ case XML_TOK_STYLE_SCIENTIFIC_NUMBER:
+ {
+ rParent.AddNumber( aNumInfo ); // simple number
+
+ rParent.AddToCode( OUString::createFromAscii( "E+" ) );
+ for (sal_Int32 i=0; i<aNumInfo.nExpDigits; i++)
+ rParent.AddToCode( OUString::valueOf((sal_Unicode)'0') );
+ }
+ break;
+
+ default:
+ DBG_ERROR("invalid element ID");
+ }
+}
+
+//-------------------------------------------------------------------------
+
+sal_Bool SvXMLNumFmtDefaults::IsSystemLongDay( const SvtSysLocale&, BOOL bLong )
+{
+ // TODO: merge system information and defaults into i18n locale data
+#if 0
+ return bLong ? rIntn.IsLongDateDayLeadingZero() : rIntn.IsDateDayLeadingZero();
+#else
+ return !bLong;
+#endif
+}
+
+sal_Bool SvXMLNumFmtDefaults::IsSystemLongMonth( const SvtSysLocale&, BOOL bLong )
+{
+ // TODO: merge system information and defaults into i18n locale data
+#if 0
+ if (bLong)
+ {
+ MonthFormat eMonth = rIntn.GetLongDateMonthFormat();
+ return ( eMonth == MONTH_ZERO || eMonth == MONTH_LONG );
+ }
+ else
+ return rIntn.IsDateMonthLeadingZero();
+#else
+ return !bLong;
+#endif
+}
+
+sal_Bool SvXMLNumFmtDefaults::IsSystemTextualMonth( const SvtSysLocale&, BOOL bLong )
+{
+ // TODO: merge system information and defaults into i18n locale data
+#if 0
+ if (bLong)
+ {
+ MonthFormat eMonth = rIntn.GetLongDateMonthFormat();
+ return ( eMonth == MONTH_SHORT || eMonth == MONTH_LONG );
+ }
+ else
+ return sal_False;
+#else
+ return bLong;
+#endif
+}
+
+sal_Bool SvXMLNumFmtDefaults::IsSystemLongYear( const SvtSysLocale&, BOOL bLong )
+{
+ // TODO: merge system information and defaults into i18n locale data
+#if 0
+ return bLong ? rIntn.IsLongDateCentury() : rIntn.IsDateCentury();
+#else
+ return bLong;
+#endif
+}
+
+sal_Bool SvXMLNumFmtDefaults::IsSystemLongEra( const SvtSysLocale& rSysLoc, BOOL bLong )
+{
+ // TODO: merge system information and defaults into i18n locale data
+ return IsSystemLongYear( rSysLoc, bLong ); // no separate setting
+}
+
+sal_Bool SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( const SvtSysLocale&, BOOL bLong )
+{
+ // TODO: merge system information and defaults into i18n locale data
+#if 0
+ return ( bLong && rIntn.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG );
+#else
+ return bLong && true;
+#endif
+}
+
+sal_uInt16 SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW,
+ SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth,
+ SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours,
+ SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs,
+ sal_Bool bSystem )
+{
+ const sal_uInt16 nCount = sizeof(aDefaultDateFormats) / sizeof(SvXMLDefaultDateFormat);
+ for (sal_uInt16 nPos=0; nPos<nCount; nPos++)
+ {
+ const SvXMLDefaultDateFormat& rEntry = aDefaultDateFormats[nPos];
+ if ( bSystem == rEntry.bSystem &&
+ ( eDOW == rEntry.eDOW || ( rEntry.eDOW == XML_DEA_ANY && eDOW != XML_DEA_NONE ) ) &&
+ ( eDay == rEntry.eDay || ( rEntry.eDay == XML_DEA_ANY && eDay != XML_DEA_NONE ) ) &&
+ ( eMonth == rEntry.eMonth || ( rEntry.eMonth == XML_DEA_ANY && eMonth != XML_DEA_NONE ) ) &&
+ ( eYear == rEntry.eYear || ( rEntry.eYear == XML_DEA_ANY && eYear != XML_DEA_NONE ) ) &&
+ ( eHours == rEntry.eHours || ( rEntry.eHours == XML_DEA_ANY && eHours != XML_DEA_NONE ) ) &&
+ ( eMins == rEntry.eMins || ( rEntry.eMins == XML_DEA_ANY && eMins != XML_DEA_NONE ) ) &&
+ ( eSecs == rEntry.eSecs || ( rEntry.eSecs == XML_DEA_ANY && eSecs != XML_DEA_NONE ) ) )
+ {
+ return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat);
+ }
+ }
+
+ return NF_INDEX_TABLE_ENTRIES; // invalid
+}
+
+//-------------------------------------------------------------------------
+
+//
+// SvXMLNumFormatContext
+//
+
+SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
+ USHORT nPrfx, const rtl::OUString& rLName,
+ SvXMLNumImpData* pNewData, sal_uInt16 nNewType,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList,
+ SvXMLStylesContext& rStyles ) :
+ SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList ),
+ pData( pNewData ),
+ pStyles( &rStyles ),
+ aMyConditions(),
+ nType( nNewType ),
+ nKey(-1),
+ nFormatLang( LANGUAGE_SYSTEM ),
+ bAutoOrder( FALSE ),
+ bFromSystem( FALSE ),
+ bTruncate( TRUE ),
+ bAutoDec( FALSE ),
+ bAutoInt( FALSE ),
+ bHasExtraText( FALSE ),
+ bHasLongDoW( FALSE ),
+ bHasEra( FALSE ),
+ bHasDateTime( FALSE ),
+ bRemoveAfterUse( sal_False ),
+ eDateDOW( XML_DEA_NONE ),
+ eDateDay( XML_DEA_NONE ),
+ eDateMonth( XML_DEA_NONE ),
+ eDateYear( XML_DEA_NONE ),
+ eDateHours( XML_DEA_NONE ),
+ eDateMins( XML_DEA_NONE ),
+ eDateSecs( XML_DEA_NONE ),
+ bDateNoDefault( sal_False )
+{
+ OUString sLanguage, sCountry;
+ ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr;
+ sal_Bool bAttrBool;
+ sal_uInt16 nAttrEnum;
+
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for( sal_Int16 i=0; i < nAttrCount; i++ )
+ {
+ OUString sAttrName = xAttrList->getNameByIndex( i );
+ OUString sValue = xAttrList->getValueByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+
+ const SvXMLTokenMap& rTokenMap = pData->GetStyleAttrTokenMap();
+ sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
+ switch (nToken)
+ {
+ case XML_TOK_STYLE_ATTR_NAME:
+// aName = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_LANGUAGE:
+ sLanguage = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_COUNTRY:
+ sCountry = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_TITLE:
+ sFormatTitle = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER:
+ if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
+ bAutoOrder = bAttrBool;
+ break;
+ case XML_TOK_STYLE_ATTR_FORMAT_SOURCE:
+ if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aFormatSourceMap ) )
+ bFromSystem = (sal_Bool) nAttrEnum;
+ break;
+ case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW:
+ if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
+ bTruncate = bAttrBool;
+ break;
+ case XML_TOK_STYLE_ATTR_VOLATILE:
+ // volatile formats can be removed after importing
+ // if not used in other styles
+ if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) )
+ bRemoveAfterUse = bAttrBool;
+ break;
+ case XML_TOK_STYLE_ATTR_TRANSL_FORMAT:
+ aNatNumAttr.Format = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE:
+ aNatNumAttr.Locale.Language = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY:
+ aNatNumAttr.Locale.Country = sValue;
+ break;
+ case XML_TOK_STYLE_ATTR_TRANSL_STYLE:
+ aNatNumAttr.Style = sValue;
+ break;
+ }
+ }
+
+ if ( sLanguage.getLength() || sCountry.getLength() )
+ {
+ nFormatLang = MsLangId::convertIsoNamesToLanguage( sLanguage, sCountry );
+ if ( nFormatLang == LANGUAGE_DONTKNOW )
+ nFormatLang = LANGUAGE_SYSTEM; //! error handling for invalid locales?
+ }
+
+ if ( aNatNumAttr.Format.getLength() )
+ {
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ if ( pFormatter )
+ {
+ sal_Int32 nNatNum = pFormatter->GetNatNum()->convertFromXmlAttributes( aNatNumAttr );
+ aFormatCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "[NatNum" ) );
+ aFormatCode.append( nNatNum, 10 );
+
+ LanguageType eLang = MsLangId::convertLocaleToLanguage( aNatNumAttr.Locale );
+ if ( eLang == LANGUAGE_DONTKNOW )
+ eLang = LANGUAGE_SYSTEM; //! error handling for invalid locales?
+ if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM )
+ {
+ aFormatCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "][$-" ) );
+ // language code in upper hex:
+ aFormatCode.append( String::CreateFromInt32( sal_Int32( eLang ), 16 ).ToUpperAscii() );
+ }
+ aFormatCode.append( sal_Unicode(']') );
+ }
+ }
+}
+
+SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
+ USHORT nPrfx, const rtl::OUString& rLName,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList,
+ const sal_Int32 nTempKey,
+ SvXMLStylesContext& rStyles ) :
+ SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, XML_STYLE_FAMILY_DATA_STYLE ),
+ pData( NULL ),
+ pStyles( &rStyles ),
+ aMyConditions(),
+ nType( 0 ),
+ nKey(nTempKey),
+ nFormatLang( LANGUAGE_SYSTEM ),
+ bAutoOrder( FALSE ),
+ bFromSystem( FALSE ),
+ bTruncate( TRUE ),
+ bAutoDec( FALSE ),
+ bAutoInt( FALSE ),
+ bHasExtraText( FALSE ),
+ bHasLongDoW( FALSE ),
+ bHasEra( FALSE ),
+ bHasDateTime( FALSE ),
+ bRemoveAfterUse( sal_False ),
+ eDateDOW( XML_DEA_NONE ),
+ eDateDay( XML_DEA_NONE ),
+ eDateMonth( XML_DEA_NONE ),
+ eDateYear( XML_DEA_NONE ),
+ eDateHours( XML_DEA_NONE ),
+ eDateMins( XML_DEA_NONE ),
+ eDateSecs( XML_DEA_NONE ),
+ bDateNoDefault( sal_False )
+{
+ SetAttribute(XML_NAMESPACE_STYLE, GetXMLToken(XML_NAME), rLName);
+}
+
+SvXMLNumFormatContext::~SvXMLNumFormatContext()
+{
+}
+
+SvXMLImportContext* SvXMLNumFormatContext::CreateChildContext(
+ USHORT nPrfx, const rtl::OUString& rLName,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList )
+{
+ SvXMLImportContext* pContext = NULL;
+
+ const SvXMLTokenMap& rTokenMap = pData->GetStyleElemTokenMap();
+ sal_uInt16 nToken = rTokenMap.Get( nPrfx, rLName );
+ switch (nToken)
+ {
+ case XML_TOK_STYLE_TEXT:
+ case XML_TOK_STYLE_NUMBER:
+ case XML_TOK_STYLE_SCIENTIFIC_NUMBER:
+ case XML_TOK_STYLE_FRACTION:
+ case XML_TOK_STYLE_CURRENCY_SYMBOL:
+ case XML_TOK_STYLE_DAY:
+ case XML_TOK_STYLE_MONTH:
+ case XML_TOK_STYLE_YEAR:
+ case XML_TOK_STYLE_ERA:
+ case XML_TOK_STYLE_DAY_OF_WEEK:
+ case XML_TOK_STYLE_WEEK_OF_YEAR:
+ case XML_TOK_STYLE_QUARTER:
+ case XML_TOK_STYLE_HOURS:
+ case XML_TOK_STYLE_AM_PM:
+ case XML_TOK_STYLE_MINUTES:
+ case XML_TOK_STYLE_SECONDS:
+ case XML_TOK_STYLE_BOOLEAN:
+ case XML_TOK_STYLE_TEXT_CONTENT:
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nPrfx, rLName,
+ *this, nToken, xAttrList );
+ break;
+
+ case XML_TOK_STYLE_PROPERTIES:
+ pContext = new SvXMLNumFmtPropContext( GetImport(), nPrfx, rLName,
+ *this, xAttrList );
+ break;
+ case XML_TOK_STYLE_MAP:
+ {
+ // SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
+ // so there's no need for an extra flag
+ pContext = new SvXMLNumFmtMapContext( GetImport(), nPrfx, rLName,
+ *this, xAttrList );
+ }
+ break;
+ }
+
+ if( !pContext )
+ pContext = new SvXMLImportContext( GetImport(), nPrfx, rLName );
+ return pContext;
+}
+
+sal_Int32 SvXMLNumFormatContext::GetKey()
+{
+ if (nKey > -1)
+ {
+ if (bRemoveAfterUse)
+ {
+ // format is used -> don't remove
+ bRemoveAfterUse = sal_False;
+ if (pData)
+ pData->SetUsed(nKey);
+
+ // Add to import's list of keys now - CreateAndInsert didn't add
+ // the style if bRemoveAfterUse was set.
+ GetImport().AddNumberStyle( nKey, GetName() );
+ }
+ return nKey;
+ }
+ else
+ {
+ // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
+ bRemoveAfterUse = sal_False;
+ CreateAndInsert(sal_True);
+ return nKey;
+ }
+}
+
+sal_Int32 SvXMLNumFormatContext::PrivateGetKey()
+{
+ // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
+
+ if (nKey > -1)
+ return nKey;
+ else
+ {
+ CreateAndInsert(sal_True);
+ return nKey;
+ }
+}
+
+sal_Int32 SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier >& xFormatsSupplier )
+{
+ if (nKey <= -1)
+ {
+ SvNumberFormatter* pFormatter = NULL;
+ SvNumberFormatsSupplierObj* pObj =
+ SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier );
+ if (pObj)
+ pFormatter = pObj->GetNumberFormatter();
+
+ if ( pFormatter )
+ return CreateAndInsert( pFormatter );
+ else
+ return -1;
+ }
+ else
+ return nKey;
+}
+
+void SvXMLNumFormatContext::CreateAndInsert(sal_Bool /*bOverwrite*/)
+{
+ if (!(nKey > -1))
+ CreateAndInsert(pData->GetNumberFormatter());
+}
+
+sal_Int32 SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
+{
+ if (!pFormatter)
+ {
+ DBG_ERROR("no number formatter");
+ return -1;
+ }
+
+ sal_uInt32 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
+
+ for (sal_uInt32 i = 0; i < aMyConditions.size(); i++)
+ {
+ SvXMLNumFormatContext* pStyle = (SvXMLNumFormatContext *)pStyles->FindStyleChildContext(
+ XML_STYLE_FAMILY_DATA_STYLE, aMyConditions[i].sMapName, sal_False);
+ if (pStyle)
+ {
+ if ((pStyle->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag
+ AddCondition(i);
+ }
+ }
+
+ if ( !aFormatCode.getLength() )
+ {
+ // insert empty format as empty string (with quotes)
+ // #93901# this check has to be done before inserting the conditions
+ aFormatCode.appendAscii("\"\""); // ""
+ }
+
+ aFormatCode.insert( 0, aConditions.makeStringAndClear() );
+ OUString sFormat = aFormatCode.makeStringAndClear();
+
+ // test special cases
+
+ if ( bAutoDec ) // automatic decimal places
+ {
+ // #99391# adjust only if the format contains no text elements, no conditions
+ // and no color definition (detected by the '[' at the start)
+
+ if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText &&
+ aMyConditions.size() == 0 && sFormat.toChar() != (sal_Unicode)'[' )
+ nIndex = pFormatter->GetStandardIndex( nFormatLang );
+ }
+ if ( bAutoInt ) // automatic integer digits
+ {
+ //! only if two decimal places was set?
+
+ if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText &&
+ aMyConditions.size() == 0 && sFormat.toChar() != (sal_Unicode)'[' )
+ nIndex = pFormatter->GetFormatIndex( NF_NUMBER_SYSTEM, nFormatLang );
+ }
+
+ // boolean is always the builtin boolean format
+ // (no other boolean formats are implemented)
+ if ( nType == XML_TOK_STYLES_BOOLEAN_STYLE )
+ nIndex = pFormatter->GetFormatIndex( NF_BOOLEAN, nFormatLang );
+
+ // check for default date formats
+ if ( nType == XML_TOK_STYLES_DATE_STYLE && bAutoOrder && !bDateNoDefault )
+ {
+ NfIndexTableOffset eFormat = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat(
+ eDateDOW, eDateDay, eDateMonth, eDateYear,
+ eDateHours, eDateMins, eDateSecs, bFromSystem );
+ if ( eFormat < NF_INDEX_TABLE_ENTRIES )
+ {
+ // #109651# if a date format has the automatic-order attribute and
+ // contains exactly the elements of one of the default date formats,
+ // use that default format, with the element order and separators
+ // from the current locale settings
+
+ nIndex = pFormatter->GetFormatIndex( eFormat, nFormatLang );
+ }
+ }
+
+ if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND && sFormat.getLength() )
+ {
+ // insert by format string
+
+ String aFormatStr( sFormat );
+ nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang );
+ if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
+ {
+ xub_StrLen nErrPos = 0;
+ short l_nType = 0;
+ sal_Bool bOk = pFormatter->PutEntry( aFormatStr, nErrPos, l_nType, nIndex, nFormatLang );
+ if ( !bOk && nErrPos == 0 && aFormatStr != String(sFormat) )
+ {
+ // if the string was modified by PutEntry, look for an existing format
+ // with the modified string
+ nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang );
+ if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND )
+ bOk = sal_True;
+ }
+ if (!bOk)
+ nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
+ }
+ }
+
+#if 0
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !bFromSystem )
+ {
+ // instead of automatic date format, use fixed formats if bFromSystem is not set
+ //! prevent use of automatic formats in other cases, force user-defined format?
+
+ sal_uInt32 nNewIndex = nIndex;
+
+ NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex );
+ if ( eOffset == NF_DATE_SYSTEM_SHORT )
+ {
+ const International& rInt = pData->GetInternational( nFormatLang );
+ if ( rInt.IsDateDayLeadingZero() && rInt.IsDateMonthLeadingZero() )
+ {
+ if ( rInt.IsDateCentury() )
+ nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, nFormatLang );
+ else
+ nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYY, nFormatLang );
+ }
+ }
+ else if ( eOffset == NF_DATE_SYSTEM_LONG )
+ {
+ const International& rInt = pData->GetInternational( nFormatLang );
+ if ( !rInt.IsLongDateDayLeadingZero() )
+ {
+ sal_Bool bCentury = rInt.IsLongDateCentury();
+ MonthFormat eMonth = rInt.GetLongDateMonthFormat();
+ if ( eMonth == MONTH_LONG && bCentury )
+ {
+ if ( rInt.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG )
+ nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_NNNNDMMMMYYYY, nFormatLang );
+ else
+ nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_NNDMMMMYYYY, nFormatLang );
+ }
+ else if ( eMonth == MONTH_SHORT && !bCentury )
+ nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_NNDMMMYY, nFormatLang );
+ }
+ }
+
+ if ( nNewIndex != nIndex )
+ {
+ // verify the fixed format really matches the format string
+ // (not the case with some formats from locale data)
+
+ const SvNumberformat* pFixedFormat = pFormatter->GetEntry( nNewIndex );
+ if ( pFixedFormat && pFixedFormat->GetFormatstring() == String(sFormat) )
+ nIndex = nNewIndex;
+ }
+ }
+#endif
+
+ if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !bAutoOrder )
+ {
+ // use fixed-order formats instead of SYS... if bAutoOrder is false
+ // (only if the format strings are equal for the locale)
+
+ NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex );
+ if ( eOffset == NF_DATE_SYS_DMMMYYYY )
+ {
+ sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMYYYY, nFormatLang );
+ const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
+ const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
+ if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
+ nIndex = nNewIndex;
+ }
+ else if ( eOffset == NF_DATE_SYS_DMMMMYYYY )
+ {
+ sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY, nFormatLang );
+ const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
+ const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
+ if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
+ nIndex = nNewIndex;
+ }
+ }
+
+ if ((nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND) && sFormatTitle.getLength())
+ {
+ SvNumberformat* pFormat = const_cast<SvNumberformat*>(pFormatter->GetEntry( nIndex ));
+ if (pFormat)
+ {
+ String sTitle (sFormatTitle);
+ pFormat->SetComment(sTitle);
+ }
+ }
+
+ if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
+ {
+ DBG_ERROR("invalid number format");
+ nIndex = pFormatter->GetStandardIndex( nFormatLang );
+ }
+
+ pData->AddKey( nIndex, GetName(), bRemoveAfterUse );
+ nKey = nIndex;
+
+ // Add to import's list of keys (shared between styles and content import)
+ // only if not volatile - formats are removed from NumberFormatter at the
+ // end of each import (in SvXMLNumFmtHelper dtor).
+ // If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there.
+
+ if (!bRemoveAfterUse)
+ GetImport().AddNumberStyle( nKey, GetName() );
+
+#if 0
+ ByteString aByte( String(sFormatName), gsl_getSystemTextEncoding() );
+ aByte.Append( " | " );
+ aByte.Append(ByteString( String(sFormat), gsl_getSystemTextEncoding() ));
+ aByte.Append( " | " );
+ aByte.Append(ByteString::CreateFromInt32( nIndex ));
+
+// DBG_ERROR(aByte.GetBuffer());
+ int xxx=42;
+#endif
+
+ return nKey;
+}
+
+void SvXMLNumFormatContext::Finish( sal_Bool bOverwrite )
+{
+ SvXMLStyleContext::Finish( bOverwrite );
+// AddCondition();
+}
+
+const LocaleDataWrapper& SvXMLNumFormatContext::GetLocaleData() const
+{
+ return pData->GetLocaleData( nFormatLang );
+}
+
+void SvXMLNumFormatContext::AddToCode( const rtl::OUString& rString )
+{
+ aFormatCode.append( rString );
+ bHasExtraText = sal_True;
+}
+
+void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
+{
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ if (!pFormatter)
+ return;
+
+ // store special conditions
+ bAutoDec = ( rInfo.nDecimals < 0 );
+ bAutoInt = ( rInfo.nInteger < 0 );
+
+ sal_uInt16 nPrec = 0;
+ sal_uInt16 nLeading = 0;
+ if ( rInfo.nDecimals >= 0 ) // < 0 : Default
+ nPrec = (sal_uInt16) rInfo.nDecimals;
+ if ( rInfo.nInteger >= 0 ) // < 0 : Default
+ nLeading = (sal_uInt16) rInfo.nInteger;
+
+ if ( bAutoDec )
+ {
+ if ( nType == XML_TOK_STYLES_CURRENCY_STYLE )
+ {
+ // for currency formats, "automatic decimals" is used for the automatic
+ // currency format with (fixed) decimals from the locale settings
+
+ const LocaleDataWrapper& rLoc = pData->GetLocaleData( nFormatLang );
+ nPrec = rLoc.getCurrDigits();
+ }
+ else
+ {
+ // for other types, "automatic decimals" means dynamic determination of
+ // decimals, as achieved with the "general" keyword
+
+ aFormatCode.append( pFormatter->GetStandardName( nFormatLang ) );
+ return;
+ }
+ }
+ if ( bAutoInt )
+ {
+ //!...
+ }
+
+ sal_uInt16 nGenPrec = nPrec;
+ if ( rInfo.bDecReplace || rInfo.bVarDecimals )
+ nGenPrec = 0; // generate format without decimals...
+
+ sal_Bool bGrouping = rInfo.bGrouping;
+ USHORT nEmbeddedCount = rInfo.aEmbeddedElements.Count();
+ if ( nEmbeddedCount )
+ bGrouping = sal_False; // grouping and embedded characters can't be used together
+
+ String aNumStr;
+ sal_uInt32 nStdIndex = pFormatter->GetStandardIndex( nFormatLang );
+ pFormatter->GenerateFormat( aNumStr, nStdIndex, nFormatLang,
+ bGrouping, sal_False, nGenPrec, nLeading );
+
+ if ( rInfo.nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 )
+ {
+ // #i43959# For scientific numbers, "#" in the integer part forces a digit,
+ // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
+
+ aNumStr.EraseLeadingChars( (sal_Unicode)'#' );
+ }
+
+ if ( nEmbeddedCount )
+ {
+ // insert embedded strings into number string
+ // only the integer part is supported
+ // nZeroPos is the string position where format position 0 is inserted
+
+ xub_StrLen nZeroPos = aNumStr.Search( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() );
+ if ( nZeroPos == STRING_NOTFOUND )
+ nZeroPos = aNumStr.Len();
+
+ // aEmbeddedElements is sorted - last entry has the largest position (leftmost)
+ const SvXMLEmbeddedElement* pLastObj = rInfo.aEmbeddedElements[nEmbeddedCount - 1];
+ sal_Int32 nLastFormatPos = pLastObj->nFormatPos;
+ if ( nLastFormatPos >= nZeroPos )
+ {
+ // add '#' characters so all embedded texts are really embedded in digits
+ // (there always has to be a digit before the leftmost embedded text)
+
+ xub_StrLen nAddCount = (xub_StrLen)nLastFormatPos + 1 - nZeroPos;
+ String aDigitStr;
+ aDigitStr.Fill( nAddCount, (sal_Unicode)'#' );
+ aNumStr.Insert( aDigitStr, 0 );
+ nZeroPos = nZeroPos + nAddCount;
+ }
+
+ // aEmbeddedElements is sorted with ascending positions - loop is from right to left
+ for (USHORT nElement = 0; nElement < nEmbeddedCount; nElement++)
+ {
+ const SvXMLEmbeddedElement* pObj = rInfo.aEmbeddedElements[nElement];
+ sal_Int32 nFormatPos = pObj->nFormatPos;
+ sal_Int32 nInsertPos = nZeroPos - nFormatPos;
+ if ( nFormatPos >= 0 && nInsertPos >= 0 )
+ {
+ rtl::OUStringBuffer aContent( pObj->aText );
+ // #107805# always quote embedded strings - even space would otherwise
+ // be recognized as thousands separator in French.
+ aContent.insert( 0, (sal_Unicode) '"' );
+ aContent.append( (sal_Unicode) '"' );
+
+ aNumStr.Insert( String( aContent.makeStringAndClear() ), (xub_StrLen)nInsertPos );
+ }
+ }
+ }
+
+ aFormatCode.append( aNumStr );
+
+ if ( ( rInfo.bDecReplace || rInfo.bVarDecimals ) && nPrec ) // add decimal replacement (dashes)
+ {
+ // add dashes for explicit decimal replacement, # for variable decimals
+ sal_Unicode cAdd = rInfo.bDecReplace ? '-' : '#';
+
+ aFormatCode.append( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() );
+ for ( sal_uInt16 i=0; i<nPrec; i++)
+ aFormatCode.append( cAdd );
+ }
+
+ // add extra thousands separators for display factor
+
+ if ( rInfo.fDisplayFactor != 1.0 && rInfo.fDisplayFactor > 0.0 )
+ {
+ // test for 1.0 is just for optimization - nSepCount would be 0
+
+ // one separator for each factor of 1000
+ sal_Int32 nSepCount = (sal_Int32) ::rtl::math::round( log10(rInfo.fDisplayFactor) / 3.0 );
+ if ( nSepCount > 0 )
+ {
+ OUString aSep = pData->GetLocaleData( nFormatLang ).getNumThousandSep();
+ for ( sal_Int32 i=0; i<nSepCount; i++ )
+ aFormatCode.append( aSep );
+ }
+ }
+}
+
+void SvXMLNumFormatContext::AddCurrency( const rtl::OUString& rContent, LanguageType nLang )
+{
+ sal_Bool bAutomatic = sal_False;
+ OUString aSymbol = rContent;
+ if ( aSymbol.getLength() == 0 )
+ {
+ // get currency symbol for language
+
+ //aSymbol = pData->GetLocaleData( nFormatLang ).getCurrSymbol();
+
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ if ( pFormatter )
+ {
+ pFormatter->ChangeIntl( nFormatLang );
+ String sCurString, sDummy;
+ pFormatter->GetCompatibilityCurrency( sCurString, sDummy );
+ aSymbol = sCurString;
+
+ bAutomatic = sal_True;
+ }
+ }
+ else if ( nLang == LANGUAGE_SYSTEM && aSymbol.compareToAscii("CCC") == 0 )
+ {
+ // "CCC" is used for automatic long symbol
+ bAutomatic = sal_True;
+ }
+
+ if ( bAutomatic )
+ {
+ // remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
+ // otherwise the currency symbol isn't recognized (#94048#)
+
+ sal_Int32 nLength = aFormatCode.getLength();
+ if ( nLength > 1 && aFormatCode.charAt( nLength-1 ) == '"' )
+ {
+ // find start of quoted string
+ // When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
+ // they must be handled here, too.
+
+ sal_Int32 nFirst = nLength - 2;
+ while ( nFirst >= 0 && aFormatCode.charAt( nFirst ) != '"' )
+ --nFirst;
+ if ( nFirst >= 0 )
+ {
+ // remove both quotes from aFormatCode
+ rtl::OUString aOld = aFormatCode.makeStringAndClear();
+ if ( nFirst > 0 )
+ aFormatCode.append( aOld.copy( 0, nFirst ) );
+ if ( nLength > nFirst + 2 )
+ aFormatCode.append( aOld.copy( nFirst + 1, nLength - nFirst - 2 ) );
+ }
+ }
+ }
+
+ if (!bAutomatic)
+ aFormatCode.appendAscii( "[$" ); // intro for "new" currency symbols
+
+ aFormatCode.append( aSymbol );
+
+ if (!bAutomatic)
+ {
+ if ( nLang != LANGUAGE_SYSTEM )
+ {
+ // '-' sign and language code in hex:
+ aFormatCode.append( (sal_Unicode) '-' );
+ aFormatCode.append( String::CreateFromInt32( sal_Int32( nLang ), 16 ).ToUpperAscii() );
+ }
+
+ aFormatCode.append( (sal_Unicode) ']' ); // end of "new" currency symbol
+ }
+}
+
+void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex )
+{
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ if (!pFormatter)
+ return;
+
+ if ( nIndex == NF_KEY_G || nIndex == NF_KEY_GG || nIndex == NF_KEY_GGG )
+ bHasEra = sal_True;
+
+ if ( nIndex == NF_KEY_NNNN )
+ {
+ nIndex = NF_KEY_NNN;
+ bHasLongDoW = sal_True; // to remove string constant with separator
+ }
+
+ String sKeyword = pFormatter->GetKeyword( nFormatLang, nIndex );
+
+ if ( nIndex == NF_KEY_H || nIndex == NF_KEY_HH ||
+ nIndex == NF_KEY_MI || nIndex == NF_KEY_MMI ||
+ nIndex == NF_KEY_S || nIndex == NF_KEY_SS )
+ {
+ if ( !bTruncate && !bHasDateTime )
+ {
+ // with truncate-on-overflow = false, add "[]" to first time part
+
+ sKeyword.Insert( (sal_Unicode) '[', 0 );
+ sKeyword.Append( (sal_Unicode) ']' );
+ }
+ bHasDateTime = sal_True;
+ }
+
+ aFormatCode.append( sKeyword );
+
+ // collect the date elements that the format contains, to recognize default date formats
+ switch ( nIndex )
+ {
+ 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
+ }
+}
+
+sal_Bool lcl_IsAtEnd( rtl::OUStringBuffer& rBuffer, const String& rToken )
+{
+ sal_Int32 nBufLen = rBuffer.getLength();
+ xub_StrLen nTokLen = rToken.Len();
+
+ if ( nTokLen > nBufLen )
+ return sal_False;
+
+ sal_Int32 nStartPos = nBufLen - nTokLen;
+ for ( xub_StrLen nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
+ if ( rToken.GetChar( nTokPos ) != rBuffer.charAt( nStartPos + nTokPos ) )
+ return sal_False;
+
+ return sal_True;
+}
+
+sal_Bool SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld, sal_uInt16 nNew )
+{
+ // replaces one keyword with another if it is found at the end of the code
+
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ if (!pFormatter)
+ return sal_False;
+
+ String sOldStr = pFormatter->GetKeyword( nFormatLang, nOld );
+ if ( lcl_IsAtEnd( aFormatCode, sOldStr ) )
+ {
+ // remove old keyword
+ aFormatCode.setLength( aFormatCode.getLength() - sOldStr.Len() );
+
+ // add new keyword
+ String sNewStr = pFormatter->GetKeyword( nFormatLang, nNew );
+ aFormatCode.append( sNewStr );
+
+ return sal_True; // changed
+ }
+ return sal_False; // not found
+}
+
+void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex )
+{
+ rtl::OUString rApplyName = aMyConditions[nIndex].sMapName;
+ rtl::OUString rCondition = aMyConditions[nIndex].sCondition;
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ sal_uInt32 l_nKey = pData->GetKeyForName( rApplyName );
+ OUString sValue = OUString::createFromAscii( "value()" ); //! define constant
+ sal_Int32 nValLen = sValue.getLength();
+
+ if ( pFormatter && l_nKey != NUMBERFORMAT_ENTRY_NOT_FOUND &&
+ rCondition.copy( 0, nValLen ) == sValue )
+ {
+ //! test for valid conditions
+ //! test for default conditions
+
+ OUString sRealCond = rCondition.copy( nValLen, rCondition.getLength() - nValLen );
+ sal_Bool bDefaultCond = sal_False;
+
+ //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
+ //! allow blanks in conditions
+ sal_Bool bFirstCond = ( aConditions.getLength() == 0 );
+ if ( bFirstCond && aMyConditions.size() == 1 && sRealCond.compareToAscii( ">=0" ) == 0 )
+ bDefaultCond = sal_True;
+
+ if ( nType == XML_TOK_STYLES_TEXT_STYLE && nIndex == 2 )
+ {
+ // The third condition in a number format with a text part can only be
+ // "all other numbers", the condition string must be empty.
+ bDefaultCond = sal_True;
+ }
+
+ if (!bDefaultCond)
+ {
+ sal_Int32 nPos = sRealCond.indexOf( '.' );
+ if ( nPos >= 0 )
+ { // #i8026# #103991# localize decimal separator
+ const String& rDecSep = GetLocaleData().getNumDecimalSep();
+ if ( rDecSep.Len() > 1 || rDecSep.GetChar(0) != '.' )
+ sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep );
+ }
+ aConditions.append( (sal_Unicode) '[' );
+ aConditions.append( sRealCond );
+ aConditions.append( (sal_Unicode) ']' );
+ }
+
+ const SvNumberformat* pFormat = pFormatter->GetEntry(l_nKey);
+ if ( pFormat )
+ aConditions.append( OUString( pFormat->GetFormatstring() ) );
+
+ aConditions.append( (sal_Unicode) ';' );
+ }
+}
+
+void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex, const rtl::OUString& rFormat, const LocaleDataWrapper& rData )
+{
+ rtl::OUString rCondition = aMyConditions[nIndex].sCondition;
+ OUString sValue = OUString::createFromAscii( "value()" ); //! define constant
+ sal_Int32 nValLen = sValue.getLength();
+
+ if ( rCondition.copy( 0, nValLen ) == sValue )
+ {
+ //! test for valid conditions
+ //! test for default conditions
+
+ OUString sRealCond = rCondition.copy( nValLen, rCondition.getLength() - nValLen );
+ sal_Bool bDefaultCond = sal_False;
+
+ //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
+ //! allow blanks in conditions
+ sal_Bool bFirstCond = ( aConditions.getLength() == 0 );
+ if ( bFirstCond && aMyConditions.size() == 1 && sRealCond.compareToAscii( ">=0" ) == 0 )
+ bDefaultCond = sal_True;
+
+ if ( nType == XML_TOK_STYLES_TEXT_STYLE && nIndex == 2 )
+ {
+ // The third condition in a number format with a text part can only be
+ // "all other numbers", the condition string must be empty.
+ bDefaultCond = sal_True;
+ }
+
+ if (!bDefaultCond)
+ {
+ sal_Int32 nPos = sRealCond.indexOf( '.' );
+ if ( nPos >= 0 )
+ { // #i8026# #103991# localize decimal separator
+ const String& rDecSep = rData.getNumDecimalSep();
+ if ( rDecSep.Len() > 1 || rDecSep.GetChar(0) != '.' )
+ sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep );
+ }
+ aConditions.append( (sal_Unicode) '[' );
+ aConditions.append( sRealCond );
+ aConditions.append( (sal_Unicode) ']' );
+ }
+
+ aConditions.append( rFormat );
+
+ aConditions.append( (sal_Unicode) ';' );
+ }
+}
+
+void SvXMLNumFormatContext::AddCondition( const rtl::OUString& rCondition, const rtl::OUString& rApplyName )
+{
+ MyCondition aCondition;
+ aCondition.sCondition = rCondition;
+ aCondition.sMapName = rApplyName;
+ aMyConditions.push_back(aCondition);
+}
+
+void SvXMLNumFormatContext::AddColor( const Color& rColor )
+{
+ SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
+ if (!pFormatter)
+ return;
+
+ OUStringBuffer aColName;
+ for ( sal_uInt16 i=0; i<XML_NUMF_COLORCOUNT; i++ )
+ if ( rColor == aNumFmtStdColors[i] )
+ {
+ aColName = OUString( pFormatter->GetKeyword( nFormatLang, sal::static_int_cast< USHORT >(NF_KEY_FIRSTCOLOR + i) ) );
+ break;
+ }
+
+ if ( aColName.getLength() )
+ {
+ aColName.insert( 0, (sal_Unicode) '[' );
+ aColName.append( (sal_Unicode) ']' );
+ aFormatCode.insert( 0, aColName.makeStringAndClear() );
+ }
+}
+
+void SvXMLNumFormatContext::UpdateCalendar( const rtl::OUString& rNewCalendar )
+{
+ if ( rNewCalendar != sCalendar )
+ {
+ sCalendar = rNewCalendar;
+ if ( sCalendar.getLength() )
+ {
+ aFormatCode.appendAscii( "[~" ); // intro for calendar code
+ aFormatCode.append( sCalendar );
+ aFormatCode.append( (sal_Unicode) ']' ); // end of "new" currency symbolcalendar code
+ }
+ }
+}
+
+sal_Bool SvXMLNumFormatContext::IsSystemLanguage()
+{
+ return nFormatLang == LANGUAGE_SYSTEM;
+}
+
+//-------------------------------------------------------------------------
+
+//
+// SvXMLNumFmtHelper
+//
+
+// #110680#
+//SvXMLNumFmtHelper::SvXMLNumFmtHelper(
+// const uno::Reference<util::XNumberFormatsSupplier>& rSupp )
+SvXMLNumFmtHelper::SvXMLNumFmtHelper(
+ const uno::Reference<util::XNumberFormatsSupplier>& rSupp,
+ const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory )
+: mxServiceFactory(xServiceFactory)
+{
+ DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
+
+ SvNumberFormatter* pFormatter = NULL;
+ SvNumberFormatsSupplierObj* pObj =
+ SvNumberFormatsSupplierObj::getImplementation( rSupp );
+ if (pObj)
+ pFormatter = pObj->GetNumberFormatter();
+
+ // #110680#
+ // pData = new SvXMLNumImpData( pFormatter );
+ pData = new SvXMLNumImpData( pFormatter, mxServiceFactory );
+}
+
+// #110680#
+// SvXMLNumFmtHelper::SvXMLNumFmtHelper( SvNumberFormatter* pNumberFormatter )
+SvXMLNumFmtHelper::SvXMLNumFmtHelper(
+ SvNumberFormatter* pNumberFormatter,
+ const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory )
+: mxServiceFactory(xServiceFactory)
+{
+ DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
+
+ // #110680#
+ // pData = new SvXMLNumImpData( pNumberFormatter );
+ pData = new SvXMLNumImpData( pNumberFormatter, mxServiceFactory );
+}
+
+SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
+{
+ // remove temporary (volatile) formats from NumberFormatter
+ pData->RemoveVolatileFormats();
+
+ delete pData;
+}
+
+SvXMLStyleContext* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport& rImport,
+ USHORT nPrefix, const OUString& rLocalName,
+ const uno::Reference<xml::sax::XAttributeList>& xAttrList,
+ SvXMLStylesContext& rStyles )
+{
+ SvXMLStyleContext* pContext = NULL;
+
+ const SvXMLTokenMap& rTokenMap = pData->GetStylesElemTokenMap();
+ sal_uInt16 nToken = rTokenMap.Get( nPrefix, rLocalName );
+ switch (nToken)
+ {
+ case XML_TOK_STYLES_NUMBER_STYLE:
+ case XML_TOK_STYLES_CURRENCY_STYLE:
+ case XML_TOK_STYLES_PERCENTAGE_STYLE:
+ case XML_TOK_STYLES_DATE_STYLE:
+ case XML_TOK_STYLES_TIME_STYLE:
+ case XML_TOK_STYLES_BOOLEAN_STYLE:
+ case XML_TOK_STYLES_TEXT_STYLE:
+ pContext = new SvXMLNumFormatContext( rImport, nPrefix, rLocalName,
+ pData, nToken, xAttrList, rStyles );
+ break;
+ }
+
+ // return NULL if not a data style, caller must handle other elements
+ return pContext;
+}
+
+const SvXMLTokenMap& SvXMLNumFmtHelper::GetStylesElemTokenMap()
+{
+ return pData->GetStylesElemTokenMap();
+}
+
+/*sal_uInt32 SvXMLNumFmtHelper::GetKeyForName( const rtl::OUString& rName )
+{
+ return pData->GetKeyForName( rName );
+}*/
+
+