Make the tdf#97983 changes to BASIC optional
If you want to keep the string to floating point conversion semantics
in BASIC as they were in LibreOffice 6, you can either set the
LIBREOFFICE6FLOATINGPOINTMODE environment variable to some non-empty
value, or set the org.openoffice.Office.Scripting/Basic/Compatibility/
UseLibreOffice6FloatingPointConversion flag in the Expert
Configuration. (Or use a registry modification file with that effect.)
Adapt the relevant unit test accordingly. Thanks to Mike Kaganski for
showing how to access the setting in the LibreOffice registry from
Basic.
Change-Id: I13d6d5d834e1bb81ef8df489db2b1da79f01dfc5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125756
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/basic/qa/basic_coverage/test_types_conversion.bas b/basic/qa/basic_coverage/test_types_conversion.bas
index 1b923ad..2d93114 100644
--- a/basic/qa/basic_coverage/test_types_conversion.bas
+++ b/basic/qa/basic_coverage/test_types_conversion.bas
@@ -11,6 +11,21 @@ Dim nTotalCount As Integer
Dim nPassCount As Integer
Dim nFailCount As Integer
' See LibreOffice6FloatingPointMode in basic/source/runtime/methods1.cxx
Function LibreOffice6FloatingPointMode() As Boolean
Dim bMode As Boolean
bMode = Environ("LIBREOFFICE6FLOATINGPOINTMODE") <> ""
If (Not bMode) Then
Dim oConfigProvider As Object, aNodePath(0) As New com.sun.star.beans.PropertyValue, oRegistryKey As Object
oConfigProvider = createUnoService("com.sun.star.configuration.ConfigurationProvider")
aNodePath(0).Name = "nodepath"
aNodePath(0).Value = "org.openoffice.Office.Scripting/Basic/Compatibility"
oRegistryKey = oConfigProvider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", aNodePath)
bMode = oRegistryKey.getPropertyValue("UseLibreOffice6FloatingPointConversion")
End If
LibreOffice6FloatingPointMode = bMode
End Function
' For the following tests the en-US (English - United States) locale is required
Function doUnitTest() As String
nTotalCount = 0
@@ -39,10 +54,17 @@ Function doUnitTest() As String
nVal = " -123.456 "
AssertTest(nVal = -123.456)
' Wrong decimal separator (interpreted as group separator)
StartTest()
nVal = " -123,456 "
AssertTest(nVal = -123456)
If LibreOffice6FloatingPointMode() Then
' Wrong decimal separator (and not even interpreted as group separator)
StartTest()
nVal = " -123,45 "
AssertTest(nVal = -123)
Else
' Wrong decimal separator (interpreted as group separator)
StartTest()
nVal = " -123,456 "
AssertTest(nVal = -123456)
End If
If ((nFailCount > 0) Or (nPassCount <> nTotalCount)) Then
doUnitTest = "FAIL"
diff --git a/basic/source/inc/rtlproto.hxx b/basic/source/inc/rtlproto.hxx
index b20fa9a..06f0bd8 100644
--- a/basic/source/inc/rtlproto.hxx
+++ b/basic/source/inc/rtlproto.hxx
@@ -354,6 +354,7 @@ extern void SbRtl_CDec(StarBASIC * pBasic, SbxArray & rPar, bool bWrite);
extern void SbRtl_Partition(StarBASIC * pBasic, SbxArray & rPar, bool bWrite);
extern bool LibreOffice6FloatingPointMode();
extern double Now_Impl();
extern void Wait_Impl( bool bDurationBased, SbxArray& rPar );
diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx
index 117e84d..8e78776 100644
--- a/basic/source/runtime/methods1.cxx
+++ b/basic/source/runtime/methods1.cxx
@@ -61,6 +61,9 @@
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/i18n/LocaleCalendar2.hpp>
#include <com/sun/star/sheet/XFunctionAccess.hpp>
#include <officecfg/Office/Scripting.hxx>
#include <memory>
using namespace comphelper;
@@ -2970,6 +2973,13 @@ void SbRtl_CompatibilityMode(StarBASIC *, SbxArray & rPar, bool)
rPar.Get(0)->PutBool(bEnabled);
}
bool LibreOffice6FloatingPointMode()
{
static bool bMode = std::getenv("LIBREOFFICE6FLOATINGPOINTMODE") != nullptr;
return bMode || officecfg::Office::Scripting::Basic::Compatibility::UseLibreOffice6FloatingPointConversion::get();
}
void SbRtl_Input(StarBASIC *, SbxArray & rPar, bool)
{
// 2 parameters needed
diff --git a/basic/source/sbx/sbxbool.cxx b/basic/source/sbx/sbxbool.cxx
index 723939f..0b5f211 100644
--- a/basic/source/sbx/sbxbool.cxx
+++ b/basic/source/sbx/sbxbool.cxx
@@ -21,6 +21,7 @@
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include "sbxres.hxx"
#include <rtlproto.hxx>
enum SbxBOOL ImpGetBool( const SbxValues* p )
{
@@ -80,7 +81,7 @@ enum SbxBOOL ImpGetBool( const SbxValues* p )
double n;
SbxDataType t;
sal_uInt16 nLen = 0;
if( ImpScan( *p->pOUString, n, t, &nLen, true ) == ERRCODE_NONE )
if( ImpScan( *p->pOUString, n, t, &nLen, !LibreOffice6FloatingPointMode() ) == ERRCODE_NONE )
{
if( nLen == p->pOUString->getLength() )
{
diff --git a/basic/source/sbx/sbxbyte.cxx b/basic/source/sbx/sbxbyte.cxx
index 4974213..1892167 100644
--- a/basic/source/sbx/sbxbyte.cxx
+++ b/basic/source/sbx/sbxbyte.cxx
@@ -24,6 +24,7 @@
//#include <basic/sbx.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <rtl/math.hxx>
@@ -165,7 +166,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else if( d > SbxMAXBYTE )
{
diff --git a/basic/source/sbx/sbxchar.cxx b/basic/source/sbx/sbxchar.cxx
index d25ccc0..36bd8d6 100644
--- a/basic/source/sbx/sbxchar.cxx
+++ b/basic/source/sbx/sbxchar.cxx
@@ -20,6 +20,7 @@
#include <vcl/errcode.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <rtl/math.hxx>
@@ -147,7 +148,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else if( d > SbxMAXCHAR )
{
diff --git a/basic/source/sbx/sbxdbl.cxx b/basic/source/sbx/sbxdbl.cxx
index 9718c1d..84b5403 100644
--- a/basic/source/sbx/sbxdbl.cxx
+++ b/basic/source/sbx/sbxdbl.cxx
@@ -22,6 +22,7 @@
#include <o3tl/float_int_conversion.hxx>
#include <vcl/errcode.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <runtime.hxx>
double ImpGetDouble( const SbxValues* p )
@@ -81,7 +82,7 @@ double ImpGetDouble( const SbxValues* p )
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
{
nRes = 0;
#if HAVE_FEATURE_SCRIPTING
diff --git a/basic/source/sbx/sbxint.cxx b/basic/source/sbx/sbxint.cxx
index 85febcd..f702c6b 100644
--- a/basic/source/sbx/sbxint.cxx
+++ b/basic/source/sbx/sbxint.cxx
@@ -24,6 +24,7 @@
#include <vcl/errcode.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <rtl/math.hxx>
@@ -140,7 +141,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else
nRes = ImpDoubleToInteger(d);
@@ -383,7 +384,7 @@ start:
// Check if really 0 or invalid conversion
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else
nRes = ImpDoubleToSalInt64(d);
@@ -639,7 +640,7 @@ start:
// Check if really 0 or invalid conversion
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else
nRes = ImpDoubleToSalUInt64(d);
diff --git a/basic/source/sbx/sbxlng.cxx b/basic/source/sbx/sbxlng.cxx
index 915cf86..1bc4e4e 100644
--- a/basic/source/sbx/sbxlng.cxx
+++ b/basic/source/sbx/sbxlng.cxx
@@ -23,6 +23,7 @@
#include <vcl/errcode.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <rtl/math.hxx>
@@ -103,7 +104,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else
nRes = ImpDoubleToLong(d);
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index e6037d0..d8c1582 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -26,6 +26,7 @@
#include <vcl/errcode.hxx>
#include <unotools/resmgr.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <unotools/syslocale.hxx>
#include <unotools/charclass.hxx>
@@ -400,7 +401,7 @@ bool SbxValue::Scan( const OUString& rSrc, sal_uInt16* pLen )
{
double n;
SbxDataType t;
eRes = ImpScan( rSrc, n, t, pLen, true );
eRes = ImpScan( rSrc, n, t, pLen, !LibreOffice6FloatingPointMode() );
if( eRes == ERRCODE_NONE )
{
if( !IsFixed() )
diff --git a/basic/source/sbx/sbxsng.cxx b/basic/source/sbx/sbxsng.cxx
index f97c681..bdcc4b1 100644
--- a/basic/source/sbx/sbxsng.cxx
+++ b/basic/source/sbx/sbxsng.cxx
@@ -23,6 +23,7 @@
#include <vcl/errcode.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
float ImpGetSingle( const SbxValues* p )
{
@@ -109,7 +110,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else if( d > SbxMAXSNG )
{
diff --git a/basic/source/sbx/sbxuint.cxx b/basic/source/sbx/sbxuint.cxx
index d8eeec4..6299612 100644
--- a/basic/source/sbx/sbxuint.cxx
+++ b/basic/source/sbx/sbxuint.cxx
@@ -23,6 +23,7 @@
#include <vcl/errcode.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
sal_uInt16 ImpGetUShort( const SbxValues* p )
{
@@ -136,7 +137,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else
nRes = ImpDoubleToUShort(d);
diff --git a/basic/source/sbx/sbxulng.cxx b/basic/source/sbx/sbxulng.cxx
index fa872b8..a0db33f 100644
--- a/basic/source/sbx/sbxulng.cxx
+++ b/basic/source/sbx/sbxulng.cxx
@@ -23,6 +23,7 @@
#include <vcl/errcode.hxx>
#include <basic/sberrors.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
sal_uInt32 ImpGetULong( const SbxValues* p )
{
@@ -103,7 +104,7 @@ start:
{
double d;
SbxDataType t;
if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( *p->pOUString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
nRes = 0;
else
nRes = ImpDoubleToULong(d);
diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx
index 7530f88..fe7245a 100644
--- a/basic/source/sbx/sbxvalue.cxx
+++ b/basic/source/sbx/sbxvalue.cxx
@@ -30,6 +30,7 @@
#include <basic/sbx.hxx>
#include <sbunoobj.hxx>
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <runtime.hxx>
@@ -1324,7 +1325,7 @@ bool SbxValue::LoadData( SvStream& r, sal_uInt16 )
RTL_TEXTENCODING_ASCII_US);
double d;
SbxDataType t;
if( ImpScan( aVal, d, t, nullptr, true ) != ERRCODE_NONE || t == SbxDOUBLE )
if( ImpScan( aVal, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE || t == SbxDOUBLE )
{
aData.nSingle = 0.0F;
return false;
@@ -1339,7 +1340,7 @@ bool SbxValue::LoadData( SvStream& r, sal_uInt16 )
OUString aVal = read_uInt16_lenPrefixed_uInt8s_ToOUString(r,
RTL_TEXTENCODING_ASCII_US);
SbxDataType t;
if( ImpScan( aVal, aData.nDouble, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( aVal, aData.nDouble, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
{
aData.nDouble = 0.0;
return false;
diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx
index b8be36e..8c5d657 100644
--- a/basic/source/sbx/sbxvar.cxx
+++ b/basic/source/sbx/sbxvar.cxx
@@ -26,6 +26,7 @@
#include <runtime.hxx>
#include "sbxres.hxx"
#include "sbxconv.hxx"
#include <rtlproto.hxx>
#include <sbunoobj.hxx>
#include <rtl/character.hxx>
#include <rtl/ustrbuf.hxx>
@@ -437,7 +438,7 @@ bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
rStrm, RTL_TEXTENCODING_ASCII_US);
double d;
SbxDataType t;
if( ImpScan( aTmpString, d, t, nullptr, true ) != ERRCODE_NONE || t == SbxDOUBLE )
if( ImpScan( aTmpString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE || t == SbxDOUBLE )
{
aTmp.nSingle = 0;
return false;
@@ -452,7 +453,7 @@ bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
RTL_TEXTENCODING_ASCII_US);
SbxDataType t;
if( ImpScan( aTmpString, aTmp.nDouble, t, nullptr, true ) != ERRCODE_NONE )
if( ImpScan( aTmpString, aTmp.nDouble, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
{
aTmp.nDouble = 0;
return false;
diff --git a/officecfg/registry/schema/org/openoffice/Office/Scripting.xcs b/officecfg/registry/schema/org/openoffice/Office/Scripting.xcs
index fa9aacd..ca8374f 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Scripting.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Scripting.xcs
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- fill-column: 100 -*- -->
<!--
* This file is part of the LibreOffice project.
*
@@ -39,5 +39,29 @@
<desc>Lists the registered Scripting Framework runtimes.</desc>
</info>
</set>
<group oor:name="Basic">
<info>
<desc>Contains settings for the Basic interpreter.</desc>
</info>
<group oor:name="Compatibility">
<info>
<desc>Contains settings for the compatibility with previous version of this software or
with other software products.
</desc>
</info>
<prop oor:name="UseLibreOffice6FloatingPointConversion" oor:type="xs:boolean" oor:nillable="false">
<info>
<!-- Yes, this description refers to a bug report and is technobabble. That is
intentional. This property is to be changed only by people who know what they are
doing.
-->
<desc>Whether conversion from strings to floating-point numbers in Basic should behave
as in LibreOffice 6, before the fix to tdf#97983.
</desc>
</info>
<value>false</value>
</prop>
</group>
</group>
</component>
</oor:component-schema>