Kaydet (Commit) 6ca5d288 authored tarafından Miklos Vajna's avatar Miklos Vajna

sw user field type: fix locale of string -> float conversion

The key part is the SwUserFieldType::GetValue() hunk, the field type has
to always use the same locale, which means if we get an SwCalc reference
that works with the document or field locale that has to be switched
temporarily.

Change-Id: I26ff18e74f477729a66b066c4baf6d215a7685bc
Reviewed-on: https://gerrit.libreoffice.org/58492Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Jenkins
üst 82828c6c
......@@ -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; }
......
......@@ -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;
......
<?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>
......@@ -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();
......
......@@ -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() )
......
......@@ -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:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment