diff options
-rw-r--r-- | sw/inc/calc.hxx | 1 | ||||
-rw-r--r-- | sw/inc/usrfld.hxx | 14 | ||||
-rw-r--r-- | sw/qa/extras/layout/data/user-field-type-language.fodt | 21 | ||||
-rw-r--r-- | sw/qa/extras/layout/layout.cxx | 24 | ||||
-rw-r--r-- | sw/source/core/bastyp/calc.cxx | 5 | ||||
-rw-r--r-- | sw/source/core/fields/usrfld.cxx | 31 |
6 files changed, 92 insertions, 4 deletions
diff --git a/sw/inc/calc.hxx b/sw/inc/calc.hxx index 3396c506ab18..94d2643a547f 100644 --- a/sw/inc/calc.hxx +++ b/sw/inc/calc.hxx @@ -231,6 +231,7 @@ public: bool Push(const SwUserFieldType* pUserFieldType); void Pop(); + CharClass* GetCharClass(); void SetCalcError( SwCalcError eErr ) { m_eError = eErr; } bool IsCalcError() const { return SwCalcError::NONE != m_eError; } diff --git a/sw/inc/usrfld.hxx b/sw/inc/usrfld.hxx index e98258c624c3..ee565278fe6d 100644 --- a/sw/inc/usrfld.hxx +++ b/sw/inc/usrfld.hxx @@ -26,12 +26,20 @@ class SfxPoolItem; class SwCalc; class SwDoc; +/** + * The shared part of a user field. + * + * Tracks the value, but conversion between the float and string representation + * always happens with the system locale. + */ class SW_DLLPUBLIC SwUserFieldType : public SwValueFieldType { bool bValidValue : 1; bool bDeleted : 1; + /// Float value type. double nValue; OUString aName; + /// String value type. OUString aContent; sal_uInt16 nType; @@ -84,6 +92,12 @@ inline void SwUserFieldType::SetType(sal_uInt16 nSub) EnableFormat(!(nSub & nsSwGetSetExpType::GSE_STRING)); } +/** + * The non-shared part of a user field. + * + * Tracks the number format and the language, conversion between the float and + * string representation is independent from the system locale. + */ class SW_DLLPUBLIC SwUserField : public SwValueField { sal_uInt16 nSubType; diff --git a/sw/qa/extras/layout/data/user-field-type-language.fodt b/sw/qa/extras/layout/data/user-field-type-language.fodt new file mode 100644 index 000000000000..f741add7ddd7 --- /dev/null +++ b/sw/qa/extras/layout/data/user-field-type-language.fodt @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:default-style style:family="paragraph"> + <style:text-properties fo:language="en" fo:country="GB"/> + </style:default-style> + </office:styles> + <office:automatic-styles> + <number:number-style style:name="N10004" number:language="en" number:country="GB"> + <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> + </number:number-style> + </office:automatic-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <text:user-field-decls> + <text:user-field-decl office:value-type="float" office:value="1234.56" text:name="user-field-decl-name-example"/> + </text:user-field-decls> + <text:p>Before <text:user-field-get style:data-style-name="N10004" text:name="user-field-decl-name-example">1,234.56</text:user-field-get> after.</text:p> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 96dfcc0a2757..2325fd84e5a2 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -10,6 +10,8 @@ #include <swmodeltestbase.hxx> #include <test/mtfxmldump.hxx> #include <com/sun/star/linguistic2/LinguServiceManager.hpp> +#include <comphelper/scopeguard.hxx> +#include <unotools/syslocaleoptions.hxx> static char const DATA_DIRECTORY[] = "/sw/qa/extras/layout/data/"; @@ -28,6 +30,7 @@ public: void testTdf118672(); void testTdf117923(); void testTdf109077(); + void testUserFieldTypeLanguage(); CPPUNIT_TEST_SUITE(SwLayoutWriter); CPPUNIT_TEST(testTdf116830); @@ -41,6 +44,7 @@ public: CPPUNIT_TEST(testTdf118672); CPPUNIT_TEST(testTdf117923); CPPUNIT_TEST(testTdf109077); + CPPUNIT_TEST(testUserFieldTypeLanguage); CPPUNIT_TEST_SUITE_END(); private: @@ -250,6 +254,26 @@ void SwLayoutWriter::testTdf109077() CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(15), nTextBoxTop - nShapeTop); } +void SwLayoutWriter::testUserFieldTypeLanguage() +{ + // Set the system locale to German, the document will be English. + SvtSysLocaleOptions aOptions; + aOptions.SetLocaleConfigString("de-DE"); + aOptions.Commit(); + comphelper::ScopeGuard g([&aOptions] { + aOptions.SetLocaleConfigString(OUString()); + aOptions.Commit(); + }); + + SwDoc* pDoc = createDoc("user-field-type-language.fodt"); + SwViewShell* pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell(); + pViewShell->UpdateFields(); + xmlDocPtr pXmlDoc = parseLayoutDump(); + // This was "123,456.00", via a buggy 1234.56 -> 1234,56 -> 123456 -> + // 123,456.00 transform chain. + assertXPath(pXmlDoc, "/root/page/body/txt/Special[@nType='POR_FLD']", "rText", "1,234.56"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwLayoutWriter); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/bastyp/calc.cxx b/sw/source/core/bastyp/calc.cxx index d9c3f682ed5b..ed59425aa964 100644 --- a/sw/source/core/bastyp/calc.cxx +++ b/sw/source/core/bastyp/calc.cxx @@ -609,6 +609,11 @@ void SwCalc::Pop() m_aRekurStack.pop_back(); } +CharClass* SwCalc::GetCharClass() +{ + return m_pCharClass; +} + SwCalcOper SwCalc::GetToken() { if( m_nCommandPos >= m_sCommand.getLength() ) diff --git a/sw/source/core/fields/usrfld.cxx b/sw/source/core/fields/usrfld.cxx index d81ba1c84ae8..5537fc36ea92 100644 --- a/sw/source/core/fields/usrfld.cxx +++ b/sw/source/core/fields/usrfld.cxx @@ -41,6 +41,18 @@ using namespace ::com::sun::star; +namespace +{ +/** + * Returns the language used for float <-> string conversions in + * SwUserFieldType. + */ +LanguageType GetFieldTypeLanguage() +{ + return LANGUAGE_SYSTEM; +} +} + // Userfields SwUserField::SwUserField(SwUserFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFormat) @@ -232,7 +244,21 @@ double SwUserFieldType::GetValue( SwCalc& rCalc ) rCalc.SetCalcError( SwCalcError::Syntax ); return 0; } + + // See if we need to temporarily switch rCalc's language: in case it + // differs from the field type locale. + CharClass* pCharClass = rCalc.GetCharClass(); + LanguageTag aCalcLanguage = pCharClass->getLanguageTag(); + LanguageTag aFieldTypeLanguage(GetFieldTypeLanguage()); + bool bSwitchLanguage = aCalcLanguage != aFieldTypeLanguage; + if (bSwitchLanguage) + pCharClass->setLanguageTag(aFieldTypeLanguage); + nValue = rCalc.Calculate( aContent ).GetDouble(); + + if (bSwitchLanguage) + pCharClass->setLanguageTag(aCalcLanguage); + rCalc.Pop(); if( !rCalc.IsCalcError() ) @@ -313,10 +339,7 @@ void SwUserFieldType::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) rAny >>= fVal; nValue = fVal; - // The following line is in fact wrong, since the language is unknown (is part of the - // field) and, thus, aContent should also belong to the field. Each field can have a - // different language, but the same content with just different formatting. - aContent = DoubleToString(nValue, static_cast<sal_uInt16>(LANGUAGE_SYSTEM)); + aContent = DoubleToString(nValue, static_cast<sal_uInt16>(GetFieldTypeLanguage())); } break; case FIELD_PROP_PAR2: |