From 4935422b410757bb4920b98a2d81da3c11b8e3d7 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Tue, 9 Jul 2013 15:48:10 +0200 Subject: read/write ODF *:script* and *:rfc-language-tag* This prepares to be able to read/write the attributes, it does not enable proper handling of unknown language tags yet. An unknown tag usually falls back to SYSTEM locale. Change-Id: I4a78e8fd37deae188c69570157bc4589a712bc7a --- include/xmloff/languagetagodf.hxx | 35 +++ include/xmloff/xmlexp.hxx | 33 +++ include/xmloff/xmltoken.hxx | 2 + include/xmloff/xmltypes.hxx | 3 + sc/source/filter/xml/XMLExportDatabaseRanges.cxx | 5 +- sc/source/filter/xml/xmlimprt.cxx | 2 + sc/source/filter/xml/xmlimprt.hxx | 2 + sc/source/filter/xml/xmlsorti.cxx | 23 +- sc/source/filter/xml/xmlsorti.hxx | 4 +- .../XMLIndexBibliographyConfigurationContext.hxx | 3 +- xmloff/source/core/xmlexp.cxx | 105 +++++++++ xmloff/source/core/xmltoken.cxx | 2 + xmloff/source/style/chrlohdl.cxx | 260 +++++++++++++++++++-- xmloff/source/style/chrlohdl.hxx | 22 ++ xmloff/source/style/prhdlfac.cxx | 6 + xmloff/source/style/xmlnumfe.cxx | 17 +- xmloff/source/style/xmlnumfi.cxx | 64 +++-- .../text/XMLIndexAlphabeticalSourceContext.cxx | 14 +- .../text/XMLIndexAlphabeticalSourceContext.hxx | 3 +- .../XMLIndexBibliographyConfigurationContext.cxx | 21 +- xmloff/source/text/XMLIndexSourceBaseContext.cxx | 2 + xmloff/source/text/XMLIndexSourceBaseContext.hxx | 2 + xmloff/source/text/XMLSectionExport.cxx | 10 +- xmloff/source/text/txtprmap.cxx | 12 + 24 files changed, 573 insertions(+), 79 deletions(-) create mode 100644 include/xmloff/languagetagodf.hxx diff --git a/include/xmloff/languagetagodf.hxx b/include/xmloff/languagetagodf.hxx new file mode 100644 index 000000000000..9eef8e84af8b --- /dev/null +++ b/include/xmloff/languagetagodf.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +/** Helper to gather the single language tag relevant attributes during reading + ODF and form a resulting LanguageTag when done. + + For example fo:language, fo:script, fo:country, style:rfc-language-tag + */ +struct LanguageTagODF +{ + OUString maRfcLanguageTag; + OUString maLanguage; + OUString maScript; + OUString maCountry; + + bool isEmpty() const { return maRfcLanguageTag.isEmpty() && + maLanguage.isEmpty() && maScript.isEmpty() && maCountry.isEmpty(); } + + /** Best call this only once per instance, it recreates a LanguageTag + instance on every call. + */ + LanguageTag getLanguageTag() const { return LanguageTag( maRfcLanguageTag, maLanguage, maScript, maCountry); } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/xmloff/xmlexp.hxx b/include/xmloff/xmlexp.hxx index 148f73692158..8a58cfd166b6 100644 --- a/include/xmloff/xmlexp.hxx +++ b/include/xmloff/xmlexp.hxx @@ -70,6 +70,7 @@ class XMLEventExport; class XMLSettingsExportHelper; class XMLImageMapExport; class XMLErrors; +class LanguageTag; // Shapes in Writer cannot be named via context menu (#i51726#) #include @@ -77,6 +78,7 @@ class XMLErrors; namespace com { namespace sun { namespace star { namespace frame { class XModel; } namespace container { class XIndexContainer; } + namespace lang { struct Locale; } } } } namespace comphelper { class UnoInterfaceToUniqueIdentifierMapper; } @@ -349,6 +351,37 @@ public: const OUString& rValue ); void AddAttribute( const OUString& rQName, enum ::xmloff::token::XMLTokenEnum eValue ); + + /** Add language tag attributes, deciding which are necessary. + + @param nPrefix + Namespace prefix for *:language, *:script and *:country + + @param nPrefixRfc + Namespace prefix for *:rfc-language-tag + + @param bWriteEmpty + Whether to write empty *:language and *:country attribute + values in case of an empty locale (denoting system). + + @param eClass + default, XML_LANGUAGE: XML_SCRIPT, XML_COUNTRY, XML_RFC_LANGUAGE_TAG + XML_LANGUAGE_ASIAN: XML_SCRIPT_ASIAN, XML_COUNTRY_ASIAN, XML_RFC_LANGUAGE_TAG_ASIAN + also switches nPrefix XML_NAMESPACE_FO to XML_NAMESPACE_STYLE + XML_LANGUAGE_COMPLEX: XML_SCRIPT_COMPLEX, XML_COUNTRY_COMPLEX, XML_RFC_LANGUAGE_TAG_COMPLEX + also switches nPrefix XML_NAMESPACE_FO to XML_NAMESPACE_STYLE + */ + void AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc, + const ::com::sun::star::lang::Locale& rLocale, bool bWriteEmpty, + enum ::xmloff::token::XMLTokenEnum eClass = ::xmloff::token::XML_LANGUAGE ); + + /** Same as AddLanguageTagAttributes() but with LanguageTag parameter + instead of Locale. + */ + void AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc, + const LanguageTag& rLanguageTag, bool bWriteEmpty, + enum ::xmloff::token::XMLTokenEnum eClass = ::xmloff::token::XML_LANGUAGE ); + // add several attributes to the common attribute list void AddAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList ); diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx index a47dedd9fc25..69282ce707d1 100644 --- a/include/xmloff/xmltoken.hxx +++ b/include/xmloff/xmltoken.hxx @@ -1547,6 +1547,8 @@ namespace xmloff { namespace token { XML_SCIENTIFIC_NUMBER, XML_SCORE_SPACES, XML_SCRIPT, + XML_SCRIPT_ASIAN, + XML_SCRIPT_COMPLEX, XML_SCROLL, XML_SDEV, XML_SEARCH_CRITERIA_MUST_APPLY_TO_WHOLE_CELL, diff --git a/include/xmloff/xmltypes.hxx b/include/xmloff/xmltypes.hxx index c20394fd934e..1953af47ee7d 100644 --- a/include/xmloff/xmltypes.hxx +++ b/include/xmloff/xmltypes.hxx @@ -274,6 +274,9 @@ #define XML_TYPE_BOOL_FALSE (XML_TEXT_TYPES_START + 114) #define XML_TYPE_FILLSTYLE (XML_TEXT_TYPES_START + 115) +#define XML_TYPE_CHAR_SCRIPT (XML_TEXT_TYPES_START + 116) +#define XML_TYPE_CHAR_RFC_LANGUAGE_TAG (XML_TEXT_TYPES_START + 117) + #define XML_SCH_TYPES_START (0x4 << XML_TYPE_APP_SHIFT) #define XML_PM_TYPES_START (0x5 << XML_TYPE_APP_SHIFT) // page master #define XML_DB_TYPES_START (0x6 << XML_TYPE_APP_SHIFT) diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx index 29b8ea6b1810..4fa8b2ad491d 100644 --- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx @@ -325,10 +325,7 @@ private: if (aParam.bCaseSens) mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE); - if (!aParam.aCollatorLocale.Language.isEmpty()) - mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_LANGUAGE, aParam.aCollatorLocale.Language); - if (!aParam.aCollatorLocale.Country.isEmpty()) - mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_COUNTRY, aParam.aCollatorLocale.Country); + mrExport.AddLanguageTagAttributes( XML_NAMESPACE_TABLE, XML_NAMESPACE_TABLE, aParam.aCollatorLocale, false); if (!aParam.aCollatorAlgorithm.isEmpty()) mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ALGORITHM, aParam.aCollatorAlgorithm); diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index de77a8270776..ba46743b744e 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -1408,7 +1408,9 @@ const SvXMLTokenMap& ScXMLImport::GetSortAttrTokenMap() { XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_TOK_SORT_ATTR_BIND_STYLES_TO_CONTENT }, { XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, XML_TOK_SORT_ATTR_TARGET_RANGE_ADDRESS }, { XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TOK_SORT_ATTR_CASE_SENSITIVE }, + { XML_NAMESPACE_TABLE, XML_RFC_LANGUAGE_TAG, XML_TOK_SORT_ATTR_RFC_LANGUAGE_TAG }, { XML_NAMESPACE_TABLE, XML_LANGUAGE, XML_TOK_SORT_ATTR_LANGUAGE }, + { XML_NAMESPACE_TABLE, XML_SCRIPT, XML_TOK_SORT_ATTR_SCRIPT }, { XML_NAMESPACE_TABLE, XML_COUNTRY, XML_TOK_SORT_ATTR_COUNTRY }, { XML_NAMESPACE_TABLE, XML_ALGORITHM, XML_TOK_SORT_ATTR_ALGORITHM }, XML_TOKEN_MAP_END diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index aa85f7e978d5..6203b61658c6 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -509,7 +509,9 @@ enum ScXMLSortAttrTokens XML_TOK_SORT_ATTR_BIND_STYLES_TO_CONTENT, XML_TOK_SORT_ATTR_TARGET_RANGE_ADDRESS, XML_TOK_SORT_ATTR_CASE_SENSITIVE, + XML_TOK_SORT_ATTR_RFC_LANGUAGE_TAG, XML_TOK_SORT_ATTR_LANGUAGE, + XML_TOK_SORT_ATTR_SCRIPT, XML_TOK_SORT_ATTR_COUNTRY, XML_TOK_SORT_ATTR_ALGORITHM }; diff --git a/sc/source/filter/xml/xmlsorti.cxx b/sc/source/filter/xml/xmlsorti.cxx index e87ba2387137..175966f1e759 100644 --- a/sc/source/filter/xml/xmlsorti.cxx +++ b/sc/source/filter/xml/xmlsorti.cxx @@ -45,8 +45,6 @@ ScXMLSortContext::ScXMLSortContext( ScXMLImport& rImport, ScXMLDatabaseRangeContext* pTempDatabaseRangeContext) : SvXMLImportContext( rImport, nPrfx, rLName ), pDatabaseRangeContext(pTempDatabaseRangeContext), - sCountry(), - sLanguage(), sAlgorithm(), nUserListIndex(0), bCopyOutputData(false), @@ -87,11 +85,17 @@ ScXMLSortContext::ScXMLSortContext( ScXMLImport& rImport, bIsCaseSensitive = IsXMLToken(sValue, XML_TRUE); } break; + case XML_TOK_SORT_ATTR_RFC_LANGUAGE_TAG : + maLanguageTagODF.maRfcLanguageTag = sValue; + break; case XML_TOK_SORT_ATTR_LANGUAGE : - sLanguage = sValue; + maLanguageTagODF.maLanguage = sValue; + break; + case XML_TOK_SORT_ATTR_SCRIPT : + maLanguageTagODF.maScript = sValue; break; case XML_TOK_SORT_ATTR_COUNTRY : - sCountry = sValue; + maLanguageTagODF.maCountry = sValue; break; case XML_TOK_SORT_ATTR_ALGORITHM : sAlgorithm = sValue; @@ -130,11 +134,9 @@ SvXMLImportContext *ScXMLSortContext::CreateChildContext( sal_uInt16 nPrefix, void ScXMLSortContext::EndElement() { - sal_Int32 nLangLength(sLanguage.getLength()); - sal_Int32 nCountryLength(sCountry.getLength()); sal_Int32 nAlgoLength(sAlgorithm.getLength()); sal_uInt8 i (0); - if (nLangLength || nCountryLength) + if (!maLanguageTagODF.isEmpty()) ++i; if (nAlgoLength) ++i; @@ -153,13 +155,10 @@ void ScXMLSortContext::EndElement() aSortDescriptor[5].Value <<= nUserListIndex; aSortDescriptor[6].Name = OUString(SC_UNONAME_SORTFLD); aSortDescriptor[6].Value <<= aSortFields; - if (nLangLength || nCountryLength) + if (!maLanguageTagODF.isEmpty()) { - lang::Locale aLocale; - aLocale.Language = sLanguage; - aLocale.Country = sCountry; aSortDescriptor[7].Name = OUString(SC_UNONAME_COLLLOC); - aSortDescriptor[7].Value <<= aLocale; + aSortDescriptor[7].Value <<= maLanguageTagODF.getLanguageTag().getLocale( false); } if (nAlgoLength) { diff --git a/sc/source/filter/xml/xmlsorti.hxx b/sc/source/filter/xml/xmlsorti.hxx index 419796893aed..de952a48d692 100644 --- a/sc/source/filter/xml/xmlsorti.hxx +++ b/sc/source/filter/xml/xmlsorti.hxx @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -34,8 +35,7 @@ class ScXMLSortContext : public SvXMLImportContext com::sun::star::uno::Sequence aSortFields; com::sun::star::table::CellAddress aOutputPosition; - OUString sCountry; - OUString sLanguage; + LanguageTagODF maLanguageTagODF; OUString sAlgorithm; sal_Int16 nUserListIndex; bool bCopyOutputData; diff --git a/xmloff/inc/XMLIndexBibliographyConfigurationContext.hxx b/xmloff/inc/XMLIndexBibliographyConfigurationContext.hxx index 2c6e67110dc7..cc0234e21ed0 100644 --- a/xmloff/inc/XMLIndexBibliographyConfigurationContext.hxx +++ b/xmloff/inc/XMLIndexBibliographyConfigurationContext.hxx @@ -21,6 +21,7 @@ #define _XMLOFF_XMLINDEXBIBLIOGRAPHYCONFIGURATIONCONTEXT_HXX_ #include +#include #include #include #include @@ -56,7 +57,7 @@ class XMLIndexBibliographyConfigurationContext : public SvXMLStyleContext OUString sSuffix; OUString sPrefix; OUString sAlgorithm; - ::com::sun::star::lang::Locale aLocale; + LanguageTagODF maLanguageTagODF; sal_Bool bNumberedEntries; sal_Bool bSortByPosition; diff --git a/xmloff/source/core/xmlexp.cxx b/xmloff/source/core/xmlexp.cxx index 7892901e3d23..357999b51016 100644 --- a/xmloff/source/core/xmlexp.cxx +++ b/xmloff/source/core/xmlexp.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -1021,6 +1022,110 @@ void SvXMLExport::AddAttribute( const OUString& rQName, GetXMLToken(eValue) ); } +void SvXMLExport::AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc, + const ::com::sun::star::lang::Locale& rLocale, bool bWriteEmpty, + enum ::xmloff::token::XMLTokenEnum eClass ) +{ + if (rLocale.Variant.isEmpty()) + { + // Per convention The BCP 47 string is always stored in Variant, if + // that is empty we have a plain language-country combination, no need + // to convert to LanguageTag first. Also catches the case of empty + // locale denoting system locale. + xmloff::token::XMLTokenEnum eLanguage, eCountry; + switch (eClass) + { + default: + case XML_LANGUAGE: + eLanguage = XML_LANGUAGE; + eCountry = XML_COUNTRY; + break; + case XML_LANGUAGE_ASIAN: + eLanguage = XML_LANGUAGE_ASIAN; + eCountry = XML_COUNTRY_ASIAN; + if (nPrefix == XML_NAMESPACE_FO) + nPrefix = XML_NAMESPACE_STYLE; + break; + case XML_LANGUAGE_COMPLEX: + eLanguage = XML_LANGUAGE_COMPLEX; + eCountry = XML_COUNTRY_COMPLEX; + if (nPrefix == XML_NAMESPACE_FO) + nPrefix = XML_NAMESPACE_STYLE; + break; + } + if (bWriteEmpty || !rLocale.Language.isEmpty()) + AddAttribute( nPrefix, eLanguage, rLocale.Language); + if (bWriteEmpty || !rLocale.Country.isEmpty()) + AddAttribute( nPrefix, eCountry, rLocale.Country); + } + else + { + LanguageTag aLanguageTag( rLocale); + AddLanguageTagAttributes( nPrefix, nPrefixRfc, aLanguageTag, bWriteEmpty, eClass); + } +} + +void SvXMLExport::AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc, + const LanguageTag& rLanguageTag, bool bWriteEmpty, xmloff::token::XMLTokenEnum eClass ) +{ + xmloff::token::XMLTokenEnum eLanguage, eScript, eCountry, eRfcLanguageTag; + switch (eClass) + { + default: + case XML_LANGUAGE: + eLanguage = XML_LANGUAGE; + eScript = XML_SCRIPT; + eCountry = XML_COUNTRY; + eRfcLanguageTag = XML_RFC_LANGUAGE_TAG; + break; + case XML_LANGUAGE_ASIAN: + eLanguage = XML_LANGUAGE_ASIAN; + eScript = XML_SCRIPT_ASIAN; + eCountry = XML_COUNTRY_ASIAN; + eRfcLanguageTag = XML_RFC_LANGUAGE_TAG_ASIAN; + if (nPrefix == XML_NAMESPACE_FO) + nPrefix = XML_NAMESPACE_STYLE; + break; + case XML_LANGUAGE_COMPLEX: + eLanguage = XML_LANGUAGE_COMPLEX; + eScript = XML_SCRIPT_COMPLEX; + eCountry = XML_COUNTRY_COMPLEX; + eRfcLanguageTag = XML_RFC_LANGUAGE_TAG_COMPLEX; + if (nPrefix == XML_NAMESPACE_FO) + nPrefix = XML_NAMESPACE_STYLE; + break; + } + if (rLanguageTag.isIsoODF()) + { + if (bWriteEmpty || !rLanguageTag.isSystemLocale()) + { + AddAttribute( nPrefix, eLanguage, rLanguageTag.getLanguage()); + if (rLanguageTag.hasScript()) + AddAttribute( nPrefix, eScript, rLanguageTag.getScript()); + if (bWriteEmpty || !rLanguageTag.getCountry().isEmpty()) + AddAttribute( nPrefix, eCountry, rLanguageTag.getCountry()); + } + } + else + { + AddAttribute( nPrefixRfc, eRfcLanguageTag, rLanguageTag.getBcp47()); + // Also in case of non-pure-ISO tag store best matching fo: attributes + // for consumers not handling *:rfc-language-tag, ensuring that only + // valid ISO codes are stored. Here the bWriteEmpty parameter has no + // meaning. + OUString aLanguage, aCountry; + rLanguageTag.getIsoLanguageCountry( aLanguage, aCountry); + if (!aLanguage.isEmpty()) + { + AddAttribute( nPrefix, eLanguage, aLanguage); + if (rLanguageTag.hasScript()) + AddAttribute( nPrefix, eScript, rLanguageTag.getScript()); + if (!aCountry.isEmpty()) + AddAttribute( nPrefix, eCountry, aCountry); + } + } +} + void SvXMLExport::AddAttributeList( const uno::Reference< xml::sax::XAttributeList >& xAttrList ) { if( xAttrList.is()) diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index 07934bb96e7b..2c97507c2d9e 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -1553,6 +1553,8 @@ namespace xmloff { namespace token { TOKEN( "scientific-number", XML_SCIENTIFIC_NUMBER ), TOKEN( "score-spaces", XML_SCORE_SPACES ), TOKEN( "script", XML_SCRIPT ), + TOKEN( "script-asian", XML_SCRIPT_ASIAN ), + TOKEN( "script-complex", XML_SCRIPT_COMPLEX ), TOKEN( "scroll", XML_SCROLL ), TOKEN( "sdev", XML_SDEV ), TOKEN( "search-criteria-must-apply-to-whole-cell", XML_SEARCH_CRITERIA_MUST_APPLY_TO_WHOLE_CELL ), diff --git a/xmloff/source/style/chrlohdl.cxx b/xmloff/source/style/chrlohdl.cxx index 9a702723f8a7..9fd0cfe6625b 100644 --- a/xmloff/source/style/chrlohdl.cxx +++ b/xmloff/source/style/chrlohdl.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,10 +29,19 @@ using namespace ::com::sun::star; using namespace ::xmloff::token; -/////////////////////////////////////////////////////////////////////////////// -// -// class XMLEscapementPropHdl -// + +/* TODO-BCP47: this fiddling with Locale is quite ugly and fragile, especially + * for the fo:script temporarily stored in Variant, it would be better to use + * LanguageTagODF but we have that nasty UNO API requirement here. + * => make LanguageTagODF (unpublished) API? */ + + +// For runtime performance, instead of converting back and forth between +// com::sun::star::Locale and LanguageTag to decide if script or tag are +// needed, this code takes advantage of knowledge about the internal +// representation of BCP 47 language tags in a Locale if present as done in a +// LanguageTag. + XMLCharLanguageHdl::~XMLCharLanguageHdl() { @@ -44,7 +54,25 @@ bool XMLCharLanguageHdl::equals( const ::com::sun::star::uno::Any& r1, const ::c lang::Locale aLocale1, aLocale2; if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) ) - bRet = ( aLocale1.Language == aLocale2.Language ); + { + bool bEmptyOrScriptVariant1 = (aLocale1.Variant.isEmpty() || aLocale1.Variant[0] == '-'); + bool bEmptyOrScriptVariant2 = (aLocale2.Variant.isEmpty() || aLocale2.Variant[0] == '-'); + if (bEmptyOrScriptVariant1 && bEmptyOrScriptVariant2) + bRet = ( aLocale1.Language == aLocale2.Language ); + else + { + OUString aLanguage1, aLanguage2; + if (bEmptyOrScriptVariant1) + aLanguage1 = aLocale1.Language; + else + aLanguage1 = LanguageTag( aLocale1).getLanguage(); + if (bEmptyOrScriptVariant2) + aLanguage2 = aLocale2.Language; + else + aLanguage2 = LanguageTag( aLocale2).getLanguage(); + bRet = ( aLanguage1 == aLanguage2 ); + } + } return bRet; } @@ -52,11 +80,25 @@ bool XMLCharLanguageHdl::equals( const ::com::sun::star::uno::Any& r1, const ::c sal_Bool XMLCharLanguageHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const { lang::Locale aLocale; - rValue >>= aLocale; if( !IsXMLToken(rStrImpValue, XML_NONE) ) - aLocale.Language = rStrImpValue; + { + if (aLocale.Variant.isEmpty()) + aLocale.Language = rStrImpValue; + else + { + if (!aLocale.Language.isEmpty() || aLocale.Variant[0] != '-') + SAL_WARN( "xmloff.style", "XMLCharLanguageHdl::importXML - attempt to import language twice"); + else + { + aLocale.Variant = rStrImpValue + aLocale.Variant; + if (!aLocale.Country.isEmpty()) + aLocale.Variant += "-" + aLocale.Country; + aLocale.Language = I18NLANGTAG_QLT; + } + } + } rValue <<= aLocale; return sal_True; @@ -68,7 +110,127 @@ sal_Bool XMLCharLanguageHdl::exportXML( OUString& rStrExpValue, const uno::Any& if(!(rValue >>= aLocale)) return sal_False; - rStrExpValue = aLocale.Language; + if (aLocale.Variant.isEmpty()) + rStrExpValue = aLocale.Language; + else + { + LanguageTag aLanguageTag( aLocale); + OUString aCountry; + aLanguageTag.getIsoLanguageCountry( rStrExpValue, aCountry); + } + + if( rStrExpValue.isEmpty() ) + rStrExpValue = GetXMLToken( XML_NONE ); + + return sal_True; +} + +// =========================================================================== + +XMLCharScriptHdl::~XMLCharScriptHdl() +{ + // nothing to do +} + +bool XMLCharScriptHdl::equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const +{ + sal_Bool bRet = sal_False; + lang::Locale aLocale1, aLocale2; + + if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) ) + { + bool bEmptyVariant1 = aLocale1.Variant.isEmpty(); + bool bEmptyVariant2 = aLocale2.Variant.isEmpty(); + if (bEmptyVariant1 && bEmptyVariant2) + bRet = sal_True; + else if ((bEmptyVariant1 && !bEmptyVariant2) || (!bEmptyVariant1 && bEmptyVariant2)) + ; // stays false + else + { + OUString aScript1, aScript2; + if (aLocale1.Variant[0] == '-') + aScript1 = aLocale1.Variant.copy(1); + else + aScript1 = LanguageTag( aLocale1).getScript(); + if (aLocale2.Variant[0] == '-') + aScript2 = aLocale2.Variant.copy(1); + else + aScript2 = LanguageTag( aLocale2).getScript(); + bRet = ( aScript1 == aScript2 ); + } + } + + return bRet; +} + +sal_Bool XMLCharScriptHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const +{ + lang::Locale aLocale; + rValue >>= aLocale; + + if( !IsXMLToken( rStrImpValue, XML_NONE ) ) + { + // Import the script only if we don't have a full BCP 47 language tag + // in Variant yet. + if (aLocale.Variant.isEmpty()) + { + if (aLocale.Language.isEmpty()) + { + SAL_INFO( "xmloff.style", "XMLCharScriptHdl::importXML - script but no language yet"); + // Temporarily store in Variant and hope the best (we will get + // a language later, yes?) + aLocale.Variant = "-" + rStrImpValue; + } + else + { + aLocale.Variant = aLocale.Language + "-" + rStrImpValue; + if (!aLocale.Country.isEmpty()) + aLocale.Variant += "-" + aLocale.Country; + aLocale.Language = I18NLANGTAG_QLT; + } + } + else if (aLocale.Variant[0] == '-') + { + SAL_WARN( "xmloff.style", "XMLCharScriptHdl::importXML - attempt to insert script twice: " + << rStrImpValue << " -> " << aLocale.Variant); + } + else + { + // Assume that if there already is a script or anything else BCP 47 + // it was read by XMLCharRfcLanguageTagHdl() and takes precedence. + // On the other hand, an *:rfc-language-tag without script and a + // *:script ?!? +#if OSL_DEBUG_LEVEL > 0 || defined(DBG_UTIL) + LanguageTag aLanguageTag( aLocale); + if (!aLanguageTag.hasScript()) + { + SAL_WARN( "xmloff.style", "XMLCharScriptHdl::importXML - attempt to insert script over bcp47: " + << rStrImpValue << " -> " << aLanguageTag.getBcp47()); + } +#endif + } + } + + rValue <<= aLocale; + return sal_True; +} + +sal_Bool XMLCharScriptHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const +{ + lang::Locale aLocale; + if(!(rValue >>= aLocale)) + return sal_False; + + // Do not write script='none' for default script. + + if (aLocale.Variant.isEmpty()) + return sal_False; + + LanguageTag aLanguageTag( aLocale); + if (!aLanguageTag.hasScript()) + return sal_False; + + rStrExpValue = aLanguageTag.getScript(); if( rStrExpValue.isEmpty() ) rStrExpValue = GetXMLToken( XML_NONE ); @@ -76,10 +238,7 @@ sal_Bool XMLCharLanguageHdl::exportXML( OUString& rStrExpValue, const uno::Any& return sal_True; } -/////////////////////////////////////////////////////////////////////////////// -// -// class XMLEscapementHeightPropHdl -// +// =========================================================================== XMLCharCountryHdl::~XMLCharCountryHdl() { @@ -100,11 +259,27 @@ bool XMLCharCountryHdl::equals( const ::com::sun::star::uno::Any& r1, const ::co sal_Bool XMLCharCountryHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const { lang::Locale aLocale; - rValue >>= aLocale; if( !IsXMLToken( rStrImpValue, XML_NONE ) ) - aLocale.Country = rStrImpValue; + { + if (aLocale.Country.isEmpty()) + { + aLocale.Country = rStrImpValue; + if (aLocale.Variant.getLength() >= 7 && aLocale.Language == I18NLANGTAG_QLT) + { + // already assembled language tag, at least ll-Ssss and not + // ll-CC or lll-CC + sal_Int32 i = aLocale.Variant.indexOf('-'); // separator to script + if (2 <= i && i < aLocale.Variant.getLength()) + { + i = aLocale.Variant.indexOf( '-', i+1); + if (i < 0) // no other separator + aLocale.Variant += "-" + rStrImpValue; // append country + } + } + } + } rValue <<= aLocale; return sal_True; @@ -116,7 +291,14 @@ sal_Bool XMLCharCountryHdl::exportXML( OUString& rStrExpValue, const uno::Any& r if(!(rValue >>= aLocale)) return sal_False; - rStrExpValue = aLocale.Country; + if (aLocale.Variant.isEmpty()) + rStrExpValue = aLocale.Country; + else + { + LanguageTag aLanguageTag( aLocale); + OUString aLanguage; + aLanguageTag.getIsoLanguageCountry( aLanguage, rStrExpValue); + } if( rStrExpValue.isEmpty() ) rStrExpValue = GetXMLToken( XML_NONE ); @@ -124,4 +306,52 @@ sal_Bool XMLCharCountryHdl::exportXML( OUString& rStrExpValue, const uno::Any& r return sal_True; } +// =========================================================================== + +XMLCharRfcLanguageTagHdl::~XMLCharRfcLanguageTagHdl() +{ + // nothing to do +} + +bool XMLCharRfcLanguageTagHdl::equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const +{ + sal_Bool bRet = sal_False; + lang::Locale aLocale1, aLocale2; + + if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) ) + bRet = ( aLocale1.Variant == aLocale2.Variant ); + + return bRet; +} + +sal_Bool XMLCharRfcLanguageTagHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const +{ + lang::Locale aLocale; + rValue >>= aLocale; + + if( !IsXMLToken( rStrImpValue, XML_NONE ) ) + { + aLocale.Variant = rStrImpValue; + aLocale.Language = I18NLANGTAG_QLT; + } + + rValue <<= aLocale; + return sal_True; +} + +sal_Bool XMLCharRfcLanguageTagHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const +{ + lang::Locale aLocale; + if(!(rValue >>= aLocale)) + return sal_False; + + // Do not write rfc-language-tag='none' if BCP 47 is not needed. + if (aLocale.Variant.isEmpty()) + return sal_False; + + rStrExpValue = aLocale.Variant; + + return sal_True; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/style/chrlohdl.hxx b/xmloff/source/style/chrlohdl.hxx index 241b96279d5e..258876989b42 100644 --- a/xmloff/source/style/chrlohdl.hxx +++ b/xmloff/source/style/chrlohdl.hxx @@ -36,6 +36,17 @@ public: virtual sal_Bool exportXML( OUString& rStrExpValue, const ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const; }; +class XMLCharScriptHdl : public XMLPropertyHandler +{ +public: + virtual ~XMLCharScriptHdl(); + + virtual bool equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const; + + virtual sal_Bool importXML( const OUString& rStrImpValue, ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const; + virtual sal_Bool exportXML( OUString& rStrExpValue, const ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const; +}; + class XMLCharCountryHdl : public XMLPropertyHandler { public: @@ -47,6 +58,17 @@ public: virtual sal_Bool exportXML( OUString& rStrExpValue, const ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const; }; +class XMLCharRfcLanguageTagHdl : public XMLPropertyHandler +{ +public: + virtual ~XMLCharRfcLanguageTagHdl(); + + virtual bool equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const; + + virtual sal_Bool importXML( const OUString& rStrImpValue, ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const; + virtual sal_Bool exportXML( OUString& rStrExpValue, const ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const; +}; + #endif // _XMLOFF_PROPERTYHANDLER_CHARLOCALETYPES_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/style/prhdlfac.cxx b/xmloff/source/style/prhdlfac.cxx index c6bb25f049a4..305a5daf1fa7 100644 --- a/xmloff/source/style/prhdlfac.cxx +++ b/xmloff/source/style/prhdlfac.cxx @@ -368,9 +368,15 @@ const XMLPropertyHandler* XMLPropertyHandlerFactory::CreatePropertyHandler( sal_ case XML_TYPE_CHAR_HEIGHT_DIFF: pPropHdl = new XMLCharHeightDiffHdl; break; + case XML_TYPE_CHAR_RFC_LANGUAGE_TAG: + pPropHdl = new XMLCharRfcLanguageTagHdl; + break; case XML_TYPE_CHAR_LANGUAGE: pPropHdl = new XMLCharLanguageHdl; break; + case XML_TYPE_CHAR_SCRIPT: + pPropHdl = new XMLCharScriptHdl; + break; case XML_TYPE_CHAR_COUNTRY: pPropHdl = new XMLCharCountryHdl; break; diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx index a71042f9b603..a23e94b42e4d 100644 --- a/xmloff/source/style/xmlnumfe.cxx +++ b/xmloff/source/style/xmlnumfe.cxx @@ -340,19 +340,8 @@ void SvXMLNumFmtExport::AddLanguageAttr_Impl( sal_Int32 nLang ) { if ( nLang != LANGUAGE_SYSTEM ) { - /* FIXME-BCP47: handle language tags! - * ODF now provides fo:script, and rfc-language-tag attribute in case a - * locale can't be expressed using these three ISO codes. - * Of course these need to be read in xmlnumfi.cxx then.. - * In general all places using XML_LANGUAGE and XML_COUNTRY need to be - * adapted once we really support bcp47. */ - OUString aLangStr, aCountryStr; - LanguageTag( (LanguageType)nLang ).getIsoLanguageCountry( aLangStr, aCountryStr ); - - if (!aLangStr.isEmpty()) - rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_LANGUAGE, aLangStr ); - if (!aCountryStr.isEmpty()) - rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_COUNTRY, aCountryStr ); + rExport.AddLanguageTagAttributes( XML_NAMESPACE_NUMBER, XML_NAMESPACE_NUMBER, + LanguageTag( (LanguageType)nLang), false); } } @@ -1118,6 +1107,8 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt rFormat.GetNatNumXml( aAttr, nPart ); if ( !aAttr.Format.isEmpty() ) { + /* FIXME-BCP47: ODF defines no transliteration-script or + * transliteration-rfc-language-tag */ rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT, aAttr.Format ); rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE, diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx index 9747063aca3c..5d7a98cab75e 100644 --- a/xmloff/source/style/xmlnumfi.cxx +++ b/xmloff/source/style/xmlnumfi.cxx @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -263,7 +264,9 @@ enum SvXMLStyleTokens enum SvXMLStyleAttrTokens { XML_TOK_STYLE_ATTR_NAME, + XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_LANGUAGE, + XML_TOK_STYLE_ATTR_SCRIPT, XML_TOK_STYLE_ATTR_COUNTRY, XML_TOK_STYLE_ATTR_TITLE, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER, @@ -271,7 +274,9 @@ enum SvXMLStyleAttrTokens XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW, XML_TOK_STYLE_ATTR_VOLATILE, XML_TOK_STYLE_ATTR_TRANSL_FORMAT, + XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE, + XML_TOK_STYLE_ATTR_TRANSL_SCRIPT, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY, XML_TOK_STYLE_ATTR_TRANSL_STYLE }; @@ -287,7 +292,9 @@ enum SvXMLStyleElemAttrTokens 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_RFC_LANGUAGE_TAG, XML_TOK_ELEM_ATTR_LANGUAGE, + XML_TOK_ELEM_ATTR_SCRIPT, XML_TOK_ELEM_ATTR_COUNTRY, XML_TOK_ELEM_ATTR_STYLE, XML_TOK_ELEM_ATTR_TEXTUAL, @@ -545,7 +552,9 @@ const SvXMLTokenMap& SvXMLNumImpData::GetStyleAttrTokenMap() { // attributes for a style { XML_NAMESPACE_STYLE, XML_NAME, XML_TOK_STYLE_ATTR_NAME }, + { XML_NAMESPACE_NUMBER, XML_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG, }, { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_STYLE_ATTR_LANGUAGE }, + { XML_NAMESPACE_NUMBER, XML_SCRIPT, XML_TOK_STYLE_ATTR_SCRIPT }, { 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 }, @@ -553,7 +562,9 @@ const SvXMLTokenMap& SvXMLNumImpData::GetStyleAttrTokenMap() { 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 }, + // not defined in ODF { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG }, { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE }, + // not defined in ODF { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_SCRIPT, XML_TOK_STYLE_ATTR_TRANSL_SCRIPT }, { 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 @@ -580,7 +591,9 @@ const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemAttrTokenMap() { 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_RFC_LANGUAGE_TAG, XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG }, { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_ELEM_ATTR_LANGUAGE }, + { XML_NAMESPACE_NUMBER, XML_SCRIPT, XML_TOK_ELEM_ATTR_SCRIPT }, { 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 }, @@ -925,7 +938,7 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport, bLong( sal_False ), bTextual( sal_False ) { - OUString sLanguage, sCountry; + LanguageTagODF aLanguageTagODF; sal_Int32 nAttrVal; bool bAttrBool(false); sal_uInt16 nAttrEnum; @@ -982,11 +995,17 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport, if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 )) aNumInfo.nFracDenominator = nAttrVal; break; + case XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG: + aLanguageTagODF.maRfcLanguageTag = sValue; + break; case XML_TOK_ELEM_ATTR_LANGUAGE: - sLanguage = sValue; + aLanguageTagODF.maLanguage = sValue; + break; + case XML_TOK_ELEM_ATTR_SCRIPT: + aLanguageTagODF.maScript = sValue; break; case XML_TOK_ELEM_ATTR_COUNTRY: - sCountry = sValue; + aLanguageTagODF.maCountry = sValue; break; case XML_TOK_ELEM_ATTR_STYLE: if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aStyleValueMap ) ) @@ -1002,11 +1021,11 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport, } } - if ( !sLanguage.isEmpty() || !sCountry.isEmpty() ) + if ( !aLanguageTagODF.isEmpty() ) { - nElementLang = LanguageTag( sLanguage, sCountry ).getLanguageType( false); + nElementLang = aLanguageTagODF.getLanguageTag().getLanguageType( false); if ( nElementLang == LANGUAGE_DONTKNOW ) - nElementLang = LANGUAGE_SYSTEM; //! error handling for invalid locales? + nElementLang = LANGUAGE_SYSTEM; //! error handling for unknown locales? } } @@ -1305,7 +1324,8 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, eDateSecs( XML_DEA_NONE ), bDateNoDefault( sal_False ) { - OUString sLanguage, sCountry; + LanguageTagODF aLanguageTagODF; + OUString sNatNumAttrScript, sNatNumAttrRfcLanguageTag; ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr; bool bAttrBool(false); sal_uInt16 nAttrEnum; @@ -1324,11 +1344,17 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, { case XML_TOK_STYLE_ATTR_NAME: break; + case XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG: + aLanguageTagODF.maRfcLanguageTag = sValue; + break; case XML_TOK_STYLE_ATTR_LANGUAGE: - sLanguage = sValue; + aLanguageTagODF.maLanguage = sValue; + break; + case XML_TOK_STYLE_ATTR_SCRIPT: + aLanguageTagODF.maScript = sValue; break; case XML_TOK_STYLE_ATTR_COUNTRY: - sCountry = sValue; + aLanguageTagODF.maCountry = sValue; break; case XML_TOK_STYLE_ATTR_TITLE: sFormatTitle = sValue; @@ -1354,9 +1380,15 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, case XML_TOK_STYLE_ATTR_TRANSL_FORMAT: aNatNumAttr.Format = sValue; break; + case XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG: + sNatNumAttrRfcLanguageTag = sValue; + break; case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE: aNatNumAttr.Locale.Language = sValue; break; + case XML_TOK_STYLE_ATTR_TRANSL_SCRIPT: + sNatNumAttrScript = sValue; + break; case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY: aNatNumAttr.Locale.Country = sValue; break; @@ -1366,11 +1398,11 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, } } - if ( !sLanguage.isEmpty() || !sCountry.isEmpty() ) + if (!aLanguageTagODF.isEmpty()) { - nFormatLang = LanguageTag( sLanguage, sCountry ).getLanguageType( false); + nFormatLang = aLanguageTagODF.getLanguageTag().getLanguageType( false); if ( nFormatLang == LANGUAGE_DONTKNOW ) - nFormatLang = LANGUAGE_SYSTEM; //! error handling for invalid locales? + nFormatLang = LANGUAGE_SYSTEM; //! error handling for unknown locales? } if ( !aNatNumAttr.Format.isEmpty() ) @@ -1378,13 +1410,17 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); if ( pFormatter ) { + LanguageTag aLanguageTag( sNatNumAttrRfcLanguageTag, aNatNumAttr.Locale.Language, + sNatNumAttrScript, aNatNumAttr.Locale.Country); + aNatNumAttr.Locale = aLanguageTag.getLocale( false); + sal_Int32 nNatNum = pFormatter->GetNatNum()->convertFromXmlAttributes( aNatNumAttr ); aFormatCode.append( "[NatNum" ); aFormatCode.append( nNatNum, 10 ); - LanguageType eLang = LanguageTag( aNatNumAttr.Locale ).getLanguageType( false); + LanguageType eLang = aLanguageTag.getLanguageType( false); if ( eLang == LANGUAGE_DONTKNOW ) - eLang = LANGUAGE_SYSTEM; //! error handling for invalid locales? + eLang = LANGUAGE_SYSTEM; //! error handling for unknown locales? if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM ) { aFormatCode.append( "][$-" ); diff --git a/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx index 28acc591322d..b6d71d28fc37 100644 --- a/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx +++ b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx @@ -172,11 +172,17 @@ void XMLIndexAlphabeticalSourceContext::ProcessAttribute( case XML_TOK_INDEXSOURCE_SORT_ALGORITHM: sAlgorithm = rValue; break; + case XML_TOK_INDEXSOURCE_RFC_LANGUAGE_TAG: + maLanguageTagODF.maRfcLanguageTag = rValue; + break; case XML_TOK_INDEXSOURCE_LANGUAGE: - aLocale.Language = rValue; + maLanguageTagODF.maLanguage = rValue; + break; + case XML_TOK_INDEXSOURCE_SCRIPT: + maLanguageTagODF.maScript = rValue; break; case XML_TOK_INDEXSOURCE_COUNTRY: - aLocale.Country = rValue; + maLanguageTagODF.maCountry = rValue; break; default: @@ -228,9 +234,9 @@ void XMLIndexAlphabeticalSourceContext::EndElement() rIndexPropertySet->setPropertyValue(sSortAlgorithm, aAny); } - if ( !aLocale.Language.isEmpty() && !aLocale.Country.isEmpty() ) + if ( !maLanguageTagODF.isEmpty() ) { - aAny <<= aLocale; + aAny <<= maLanguageTagODF.getLanguageTag().getLocale( false); rIndexPropertySet->setPropertyValue(sLocale, aAny); } diff --git a/xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx index cfc1573acfc2..44a1a60fa82c 100644 --- a/xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx +++ b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx @@ -21,6 +21,7 @@ #define _XMLOFF_XMLINDEXALPHABETICALSOURCECONTEXT_HXX_ #include "XMLIndexSourceBaseContext.hxx" +#include #include #include @@ -48,7 +49,7 @@ class XMLIndexAlphabeticalSourceContext : public XMLIndexSourceBaseContext const OUString sSortAlgorithm; const OUString sLocale; - ::com::sun::star::lang::Locale aLocale; + LanguageTagODF maLanguageTagODF; OUString sAlgorithm; OUString sMainEntryStyleName; diff --git a/xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx b/xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx index e838485154c1..1fb9cdf3bb03 100644 --- a/xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx +++ b/xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx @@ -66,7 +66,7 @@ XMLIndexBibliographyConfigurationContext::XMLIndexBibliographyConfigurationConte sSuffix(), sPrefix(), sAlgorithm(), - aLocale(), + maLanguageTagODF(), bNumberedEntries(sal_False), bSortByPosition(sal_True) { @@ -133,11 +133,22 @@ void XMLIndexBibliographyConfigurationContext::ProcessAttribute( { if( IsXMLToken(sLocalName, XML_LANGUAGE) ) { - aLocale.Language = sValue; + maLanguageTagODF.maLanguage = sValue; + } + else if( IsXMLToken(sLocalName, XML_SCRIPT) ) + { + maLanguageTagODF.maScript = sValue; } else if( IsXMLToken(sLocalName, XML_COUNTRY) ) { - aLocale.Country = sValue; + maLanguageTagODF.maCountry = sValue; + } + } + else if( XML_NAMESPACE_STYLE == nPrefix ) + { + if( IsXMLToken(sLocalName, XML_RFC_LANGUAGE_TAG) ) + { + maLanguageTagODF.maRfcLanguageTag = sValue; } } } @@ -255,9 +266,9 @@ void XMLIndexBibliographyConfigurationContext::CreateAndInsert(sal_Bool) aAny.setValue(&bSortByPosition, ::getBooleanCppuType()); xPropSet->setPropertyValue(sIsSortByPosition, aAny); - if( !aLocale.Language.isEmpty() && !aLocale.Country.isEmpty() ) + if( !maLanguageTagODF.isEmpty() ) { - aAny <<= aLocale; + aAny <<= maLanguageTagODF.getLanguageTag().getLocale( false); xPropSet->setPropertyValue(sLocale, aAny); } diff --git a/xmloff/source/text/XMLIndexSourceBaseContext.cxx b/xmloff/source/text/XMLIndexSourceBaseContext.cxx index eb44e58fea08..8f93b702342f 100644 --- a/xmloff/source/text/XMLIndexSourceBaseContext.cxx +++ b/xmloff/source/text/XMLIndexSourceBaseContext.cxx @@ -132,7 +132,9 @@ static SvXMLTokenMapEntry aIndexSourceTokenMap[] = XML_TOK_INDEXSOURCE_USE_INDEX_SOURCE_STYLES }, { XML_NAMESPACE_TEXT, XML_SORT_ALGORITHM, XML_TOK_INDEXSOURCE_SORT_ALGORITHM }, + { XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG, XML_TOK_INDEXSOURCE_RFC_LANGUAGE_TAG }, { XML_NAMESPACE_FO, XML_LANGUAGE, XML_TOK_INDEXSOURCE_LANGUAGE }, + { XML_NAMESPACE_FO, XML_SCRIPT, XML_TOK_INDEXSOURCE_SCRIPT }, { XML_NAMESPACE_FO, XML_COUNTRY, XML_TOK_INDEXSOURCE_COUNTRY }, { XML_NAMESPACE_TEXT, XML_INDEX_NAME, XML_TOK_INDEXSOURCE_USER_INDEX_NAME }, { XML_NAMESPACE_TEXT, diff --git a/xmloff/source/text/XMLIndexSourceBaseContext.hxx b/xmloff/source/text/XMLIndexSourceBaseContext.hxx index 31ffd2662e43..539338cdf9e3 100644 --- a/xmloff/source/text/XMLIndexSourceBaseContext.hxx +++ b/xmloff/source/text/XMLIndexSourceBaseContext.hxx @@ -61,7 +61,9 @@ enum IndexSourceParamEnum XML_TOK_INDEXSOURCE_COMMA_SEPARATED, XML_TOK_INDEXSOURCE_USE_INDEX_SOURCE_STYLES, XML_TOK_INDEXSOURCE_SORT_ALGORITHM, + XML_TOK_INDEXSOURCE_RFC_LANGUAGE_TAG, XML_TOK_INDEXSOURCE_LANGUAGE, + XML_TOK_INDEXSOURCE_SCRIPT, XML_TOK_INDEXSOURCE_COUNTRY, XML_TOK_INDEXSOURCE_USER_INDEX_NAME, XML_TOK_INDEXSOURCE_USE_OUTLINE_LEVEL diff --git a/xmloff/source/text/XMLSectionExport.cxx b/xmloff/source/text/XMLSectionExport.cxx index 38330c77d5a2..f5f763dfe752 100644 --- a/xmloff/source/text/XMLSectionExport.cxx +++ b/xmloff/source/text/XMLSectionExport.cxx @@ -710,10 +710,7 @@ void XMLSectionExport::ExportAlphabeticalIndexStart( aAny = rPropertySet->getPropertyValue(sLocale); Locale aLocale; aAny >>= aLocale; - GetExport().AddAttribute(XML_NAMESPACE_FO, XML_LANGUAGE, - aLocale.Language); - GetExport().AddAttribute(XML_NAMESPACE_FO, XML_COUNTRY, - aLocale.Country); + GetExport().AddLanguageTagAttributes( XML_NAMESPACE_FO, XML_NAMESPACE_STYLE, aLocale, true); ExportBaseIndexSource(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet); } @@ -1696,10 +1693,7 @@ void XMLSectionExport::ExportBibliographyConfiguration(SvXMLExport& rExport) aAny = xPropSet->getPropertyValue(sLocale); Locale aLocale; aAny >>= aLocale; - rExport.AddAttribute(XML_NAMESPACE_FO, XML_LANGUAGE, - aLocale.Language); - rExport.AddAttribute(XML_NAMESPACE_FO, XML_COUNTRY, - aLocale.Country); + rExport.AddLanguageTagAttributes( XML_NAMESPACE_FO, XML_NAMESPACE_STYLE, aLocale, true); // configuration element SvXMLElementExport aElement(rExport, XML_NAMESPACE_TEXT, diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx index def83355d0aa..079f01bdadc1 100644 --- a/xmloff/source/text/txtprmap.cxx +++ b/xmloff/source/text/txtprmap.cxx @@ -119,7 +119,9 @@ XMLPropertyMapEntry aXMLParaPropMap[] = // RES_CHRATR_KERNING MT_E( "CharKerning", FO, LETTER_SPACING, XML_TYPE_TEXT_KERNING, 0 ), // RES_CHRATR_LANGUAGE + MT_ED( "CharLocale", STYLE, RFC_LANGUAGE_TAG, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocale", FO, LANGUAGE, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ), + MT_ED( "CharLocale", FO, SCRIPT, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocale", FO, COUNTRY, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ), // RES_CHRATR_POSTURE MT_E( "CharPosture", FO, FONT_STYLE, XML_TYPE_TEXT_POSTURE, 0 ), @@ -167,7 +169,9 @@ XMLPropertyMapEntry aXMLParaPropMap[] = MT_ED( "CharPropHeightAsian",STYLE, FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CJK ), MT_ED( "CharDiffHeightAsian",STYLE,FONT_SIZE_REL_ASIAN, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CJK ), // RES_CHRATR_CJK_LANGUAGE + MT_ED( "CharLocaleAsian", STYLE, RFC_LANGUAGE_TAG_ASIAN, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleAsian", STYLE, LANGUAGE_ASIAN, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ), + MT_ED( "CharLocaleAsian", STYLE, SCRIPT_ASIAN, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleAsian", STYLE, COUNTRY_ASIAN, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ), // RES_CHRATR_CJK_POSTURE MT_E( "CharPostureAsian", STYLE, FONT_STYLE_ASIAN, XML_TYPE_TEXT_POSTURE, 0 ), @@ -185,7 +189,9 @@ XMLPropertyMapEntry aXMLParaPropMap[] = MT_ED( "CharPropHeightComplex",STYLE, FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CTL ), MT_ED( "CharDiffHeightComplex",STYLE,FONT_SIZE_REL_COMPLEX, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CTL ), // RES_CHRATR_CTL_LANGUAGE + MT_ED( "CharLocaleComplex", STYLE, RFC_LANGUAGE_TAG_COMPLEX, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleComplex", STYLE, LANGUAGE_COMPLEX, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ), + MT_ED( "CharLocaleComplex", STYLE, SCRIPT_COMPLEX, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleComplex", STYLE, COUNTRY_COMPLEX, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ), // RES_CHRATR_CTL_POSTURE MT_E( "CharPostureComplex", STYLE, FONT_STYLE_COMPLEX, XML_TYPE_TEXT_POSTURE, 0 ), @@ -416,7 +422,9 @@ XMLPropertyMapEntry aXMLTextPropMap[] = // RES_CHRATR_KERNING MT_E( "CharKerning", FO, LETTER_SPACING, XML_TYPE_TEXT_KERNING, 0 ), // RES_CHRATR_LANGUAGE + MT_ED( "CharLocale", STYLE, RFC_LANGUAGE_TAG, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocale", FO, LANGUAGE, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ), + MT_ED( "CharLocale", FO, SCRIPT, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocale", FO, COUNTRY, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ), // RES_CHRATR_POSTURE MT_E( "CharPosture", FO, FONT_STYLE, XML_TYPE_TEXT_POSTURE, 0 ), @@ -465,7 +473,9 @@ XMLPropertyMapEntry aXMLTextPropMap[] = MT_ED( "CharPropHeightAsian",STYLE, FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CJK ), MT_ED( "CharDiffHeightAsian",STYLE,FONT_SIZE_REL_ASIAN, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CJK ), // RES_CHRATR_CJK_LANGUAGE + MT_ED( "CharLocaleAsian", STYLE, RFC_LANGUAGE_TAG_ASIAN, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleAsian", STYLE, LANGUAGE_ASIAN, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ), + MT_ED( "CharLocaleAsian", STYLE, SCRIPT_ASIAN, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleAsian", STYLE, COUNTRY_ASIAN, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ), // RES_CHRATR_CJK_POSTURE MT_E( "CharPostureAsian", STYLE, FONT_STYLE_ASIAN, XML_TYPE_TEXT_POSTURE, 0 ), @@ -483,7 +493,9 @@ XMLPropertyMapEntry aXMLTextPropMap[] = MT_ED( "CharPropHeightComplex",STYLE, FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CTL ), MT_ED( "CharDiffHeightComplex",STYLE,FONT_SIZE_REL_COMPLEX, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CTL ), // RES_CHRATR_CTL_LANGUAGE + MT_ED( "CharLocaleComplex", STYLE, RFC_LANGUAGE_TAG_COMPLEX, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleComplex", STYLE, LANGUAGE_COMPLEX, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ), + MT_ED( "CharLocaleComplex", STYLE, SCRIPT_COMPLEX, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( "CharLocaleComplex", STYLE, COUNTRY_COMPLEX, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ), // RES_CHRATR_CTL_POSTURE MT_E( "CharPostureComplex", STYLE, FONT_STYLE_COMPLEX, XML_TYPE_TEXT_POSTURE, 0 ), -- cgit