| /************************************************************** |
| * |
| * 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" |
| |
| #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 "xmloff/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 |
| sal_Bool operator ==( const SvXMLEmbeddedElement& r ) const { return nFormatPos == r.nFormatPos; } |
| sal_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, sal_uInt16 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( sal_uInt16 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, sal_uInt16 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( sal_uInt16 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, sal_uInt16 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( sal_uInt16 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, sal_uInt16 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( sal_uInt16 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 ) |
| { |
| sal_uInt16 nCount = aNameEntries.Count(); |
| for (sal_uInt16 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 |
| |
| sal_uInt16 nCount = aNameEntries.Count(); |
| for (sal_uInt16 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 ) |
| { |
| sal_uInt16 nCount = aNameEntries.Count(); |
| for (sal_uInt16 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; |
| |
| sal_uInt16 nCount = aNameEntries.Count(); |
| for (sal_uInt16 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, |
| sal_uInt16 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( |
| sal_uInt16 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, |
| sal_uInt16 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( |
| sal_uInt16 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, |
| sal_uInt16 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( |
| sal_uInt16 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, |
| sal_uInt16 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( sal_False ), |
| bTextual( sal_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( |
| sal_uInt16 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; |
| sal_uInt16 nElementCount = aNumInfo.aEmbeddedElements.Count(); |
| for (sal_uInt16 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&, sal_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&, sal_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&, sal_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&, sal_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, sal_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&, sal_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, |
| sal_uInt16 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( sal_False ), |
| bFromSystem( sal_False ), |
| bTruncate( sal_True ), |
| bAutoDec( sal_False ), |
| bAutoInt( sal_False ), |
| bHasExtraText( sal_False ), |
| bHasLongDoW( sal_False ), |
| bHasEra( sal_False ), |
| bHasDateTime( sal_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, |
| sal_uInt16 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( sal_False ), |
| bFromSystem( sal_False ), |
| bTruncate( sal_True ), |
| bAutoDec( sal_False ), |
| bAutoInt( sal_False ), |
| bHasExtraText( sal_False ), |
| bHasLongDoW( sal_False ), |
| bHasEra( sal_False ), |
| bHasDateTime( sal_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( |
| sal_uInt16 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; |
| sal_uInt16 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 (sal_uInt16 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< sal_uInt16 >(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, |
| sal_uInt16 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 ); |
| }*/ |
| |
| |