basic/qa/basic_coverage/test_isnumeric_method.bas |   35 ++++++++++++++++------
 basic/qa/vba_tests/isnumeric.vb                   |    8 +++++
 basic/source/runtime/runtime.cxx                  |    2 -
 basic/source/sbx/sbxbool.cxx                      |    2 -
 basic/source/sbx/sbxconv.hxx                      |    6 +--
 basic/source/sbx/sbxexec.cxx                      |    2 -
 basic/source/sbx/sbxscan.cxx                      |   25 +++++++++++----
 basic/source/sbx/sbxvalue.cxx                     |    7 ++--
 include/basic/sbxvar.hxx                          |    2 -
 9 files changed, 64 insertions(+), 25 deletions(-)

New commits:
commit f8ac9d3311a623fdca64583b08780ea8ebed157c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Jan 6 15:16:40 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Jan 8 06:02:43 2025 +0100

    tdf#164599: Allow space between sign and number in VBASupport mode
    
    Change-Id: Ib9e8c8770f8c2d1b348ff032502467915829c4f3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179865
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/basic/qa/basic_coverage/test_isnumeric_method.bas 
b/basic/qa/basic_coverage/test_isnumeric_method.bas
index 21e4a91a8b45..eb476e8a6b35 100644
--- a/basic/qa/basic_coverage/test_isnumeric_method.bas
+++ b/basic/qa/basic_coverage/test_isnumeric_method.bas
@@ -28,7 +28,7 @@ Sub verify_IsNumeric
     TestUtil.Assert(Not IsNumeric(" "), "Not IsNumeric("" "")")
     TestUtil.Assert(Not IsNumeric(" + "), "Not IsNumeric("" + "")")
     TestUtil.Assert(Not IsNumeric(" - "), "Not IsNumeric("" - "")")
-    ' Note: the two following tests should behave different in VBA 
(TODO/FIXME);
+    ' Note: the two following tests behave different in VBA;
     ' should it be unified maybe in non-VBA, too (a breaking change)?
     TestUtil.Assert(Not IsNumeric(" + 0 "), "Not IsNumeric("" + 0 "")")
     TestUtil.Assert(Not IsNumeric(" - 0 "), "Not IsNumeric("" - 0 "")")
diff --git a/basic/qa/vba_tests/isnumeric.vb b/basic/qa/vba_tests/isnumeric.vb
index ead7e83e1494..721a2fb7f4b6 100644
--- a/basic/qa/vba_tests/isnumeric.vb
+++ b/basic/qa/vba_tests/isnumeric.vb
@@ -26,6 +26,14 @@ rem    TestUtil.Assert(IsNumeric(True), "IsNumeric(True)")
     TestUtil.Assert(IsNumeric("123"),   "IsNumeric(""123"")")
     TestUtil.Assert(IsNumeric("+123"),  "IsNumeric(""+123"")")
 
+    TestUtil.Assert(Not IsNumeric(""), "Not IsNumeric("""")")
+    TestUtil.Assert(Not IsNumeric(" "), "Not IsNumeric("" "")")
+    TestUtil.Assert(Not IsNumeric(" + "), "Not IsNumeric("" + "")")
+    TestUtil.Assert(Not IsNumeric(" - "), "Not IsNumeric("" - "")")
+
+    TestUtil.Assert(IsNumeric(" + 0 "), "IsNumeric("" + 0 "")")
+    TestUtil.Assert(IsNumeric(" - 0 "), "IsNumeric("" - 0 "")")
+
     Exit Sub
 errorHandler:
     TestUtil.ReportErrorHandler("verify_testIsNumeric", Err, Error$, Erl)
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index 84e2e78dc99e..f843d6b44e13 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -102,6 +102,13 @@ ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, 
SbxDataType& rType,
         p++;
         bMinus = true;
     }
+#if HAVE_FEATURE_SCRIPTING
+    if (SbiRuntime::isVBAEnabled())
+    {
+        while (p != rWSrc.end() && (*p == ' ' || *p == '       '))
+            p++;
+    }
+#endif
     const auto pNumberStart = p;
     if (p != rWSrc.end()
         && (rtl::isAsciiDigit(*p)
commit 20db60030eaa9a2bc099894d89a63808e12c7635
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Jan 6 14:49:40 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Jan 8 06:02:37 2025 +0100

    Use sal_Int32 for string length
    
    Change-Id: Ie069c20b7d91631cb3b5d39e1a52f09cc13e8a22
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179864
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index 2fcbfb7372cb..3a715a9278db 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -2521,7 +2521,7 @@ void SbiRuntime::StepINPUT()
         // then with a string value
         if( !pVar->IsFixed() || pVar->IsNumeric() )
         {
-            sal_uInt16 nLen = 0;
+            sal_Int32 nLen = 0;
             if( !pVar->Scan( s, &nLen ) )
             {
                 err = SbxBase::GetError();
diff --git a/basic/source/sbx/sbxbool.cxx b/basic/source/sbx/sbxbool.cxx
index fd9002b4eff3..c6d9c2fbd166 100644
--- a/basic/source/sbx/sbxbool.cxx
+++ b/basic/source/sbx/sbxbool.cxx
@@ -79,7 +79,7 @@ enum SbxBOOL ImpGetBool( const SbxValues* p )
                     bool bError = true;
                     double n;
                     SbxDataType t;
-                    sal_uInt16 nLen = 0;
+                    sal_Int32 nLen = 0;
                     if( ImpScan( *p->pOUString, n, t, &nLen ) == ERRCODE_NONE )
                     {
                         if( nLen == p->pOUString->getLength() )
diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx
index 11725dec5b29..edb0e8cd973c 100644
--- a/basic/source/sbx/sbxconv.hxx
+++ b/basic/source/sbx/sbxconv.hxx
@@ -63,11 +63,11 @@ inline auto ImpDoubleToSalInt64(double d)
 // SBXSCAN.CXX
 extern void ImpCvtNum( double nNum, short nPrec, OUString& rRes, bool 
bCoreString=false );
 extern ErrCode ImpScan
-    ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_uInt16* 
pLen,
+    ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_Int32* 
pLen,
       bool* pHasNumber, bool bOnlyIntntl );
 // A version that uses defaults / compatibility settings for bOnlyIntntl
 extern ErrCode ImpScan
-    ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_uInt16* 
pLen );
+    ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_Int32* 
pLen );
 
 void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep, 
sal_Unicode& rcDecimalSepAlt );
 
diff --git a/basic/source/sbx/sbxexec.cxx b/basic/source/sbx/sbxexec.cxx
index 8c88099efbee..9d9b339ef715 100644
--- a/basic/source/sbx/sbxexec.cxx
+++ b/basic/source/sbx/sbxexec.cxx
@@ -129,7 +129,7 @@ static SbxVariableRef Operand
                    || *p == '&' ) )
     {
         // A number could be scanned in directly!
-        sal_uInt16 nLen;
+        sal_Int32 nLen;
         if (!refVar->Scan(p, &nLen))
         {
             refVar.clear();
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index 008b5aeb0a4e..84e2e78dc99e 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -71,7 +71,7 @@ static bool ImpStrChr( std::u16string_view str, sal_Unicode c 
) { return str.fin
 // conversion error if data type is fixed and it doesn't fit
 
 ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, SbxDataType& rType,
-                  sal_uInt16* pLen, bool* pHasNumber, bool bOnlyIntntl )
+                 sal_Int32* pLen, bool* pHasNumber, bool bOnlyIntntl )
 {
     sal_Unicode cDecSep, cGrpSep, cDecSepAlt;
     if( bOnlyIntntl )
@@ -237,7 +237,7 @@ ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, 
SbxDataType& rType,
     while (p != rWSrc.end() && (*p == ' ' || *p == '   '))
         p++;
     if( pLen )
-        *pLen = static_cast<sal_uInt16>( p - pStart );
+        *pLen = p - pStart;
     if (pHasNumber)
         *pHasNumber = pNumberEnd > pNumberStart;
     if( bMinus )
@@ -246,7 +246,7 @@ ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, 
SbxDataType& rType,
     return ERRCODE_NONE;
 }
 
-ErrCode ImpScan(std::u16string_view rSrc, double& nVal, SbxDataType& rType, 
sal_uInt16* pLen)
+ErrCode ImpScan(std::u16string_view rSrc, double& nVal, SbxDataType& rType, 
sal_Int32* pLen)
 {
     using namespace officecfg::Office::Scripting;
     static const bool bEnv = std::getenv("LIBREOFFICE6FLOATINGPOINTMODE") != 
nullptr;
@@ -258,7 +258,7 @@ ErrCode ImpScan(std::u16string_view rSrc, double& nVal, 
SbxDataType& rType, sal_
 // port for CDbl in the Basic
 ErrCode SbxValue::ScanNumIntnl( const OUString& rSrc, double& nVal, bool 
bSingle )
 {
-    sal_uInt16 nLen = 0;
+    sal_Int32 nLen = 0;
     ErrCode nRetError = ImpScan( rSrc, nVal, o3tl::temporary(SbxDataType()), 
&nLen, nullptr,
         /*bOnlyIntntl*/true );
     // read completely?
@@ -324,7 +324,7 @@ static void printfmtstr(std::u16string_view rStr, OUString& 
rRes, std::u16string
 }
 
 
-bool SbxValue::Scan(std::u16string_view rSrc, sal_uInt16* pLen)
+bool SbxValue::Scan(std::u16string_view rSrc, sal_Int32* pLen)
 {
     ErrCode eRes = ERRCODE_NONE;
     if( !CanWrite() )
diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx
index 6b70fe31131a..146c4f50faf1 100644
--- a/basic/source/sbx/sbxvalue.cxx
+++ b/basic/source/sbx/sbxvalue.cxx
@@ -692,7 +692,7 @@ bool SbxValue::ImpIsNumeric( bool bOnlyIntntl ) const
             OUString s( *aData.pOUString );
             double n;
             SbxDataType t2;
-            sal_uInt16 nLen = 0;
+            sal_Int32 nLen = 0;
             bool bHasNumber = false;
             if( ImpScan( s, n, t2, &nLen, &bHasNumber, bOnlyIntntl ) == 
ERRCODE_NONE )
                 return nLen == s.getLength() && bHasNumber;
diff --git a/include/basic/sbxvar.hxx b/include/basic/sbxvar.hxx
index 29976d1fe7f6..daa961be1a19 100644
--- a/include/basic/sbxvar.hxx
+++ b/include/basic/sbxvar.hxx
@@ -189,7 +189,7 @@ public:
     SAL_DLLPRIVATE bool Convert( SbxDataType );
     bool Compute( SbxOperator, const SbxValue& );
     bool Compare( SbxOperator, const SbxValue& ) const;
-    SAL_DLLPRIVATE bool Scan( std::u16string_view, sal_uInt16* );
+    SAL_DLLPRIVATE bool Scan( std::u16string_view, sal_Int32* );
     SAL_DLLPRIVATE void Format( OUString&, const OUString* = nullptr ) const;
 
     // The following operators are defined for easier handling.
commit bb86627216f5532b6d776fafafd9e796060b57b8
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Jan 6 14:45:44 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Jan 8 06:02:30 2025 +0100

    tdf#154284: check if ImpScan found a number at all
    
    Change-Id: Iddc87bd0d04f9b0212b03d63f3177b17bb07d278
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179863
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/basic/qa/basic_coverage/test_isnumeric_method.bas 
b/basic/qa/basic_coverage/test_isnumeric_method.bas
index 1b454aa8d5ec..21e4a91a8b45 100644
--- a/basic/qa/basic_coverage/test_isnumeric_method.bas
+++ b/basic/qa/basic_coverage/test_isnumeric_method.bas
@@ -8,13 +8,32 @@
 
 Option Explicit
 
-Function doUnitTest as String
+Function doUnitTest() As String
+    TestUtil.TestInit
+    verify_IsNumeric
+    doUnitTest = TestUtil.GetResult()
+End Function
+
+Sub verify_IsNumeric
+    On Error GoTo errorHandler
+
     dim aVariant as Variant
     aVariant = 3
-    ' ISNUMERIC
-    If ( IsNumeric( aVariant ) = False ) Then
-        doUnitTest = "FAIL"
-    Else
-        doUnitTest = "OK"
-    End If
-End Function
+    TestUtil.Assert(IsNumeric(aVariant), "IsNumeric(aVariant)")
+
+    TestUtil.Assert(IsNumeric(" 0 "), "IsNumeric("" 0 "")")
+    TestUtil.Assert(IsNumeric(" +0 "), "IsNumeric("" +0 "")")
+    TestUtil.Assert(IsNumeric(" -0 "), "IsNumeric("" -0 "")")
+    TestUtil.Assert(Not IsNumeric(""), "Not IsNumeric("""")")
+    TestUtil.Assert(Not IsNumeric(" "), "Not IsNumeric("" "")")
+    TestUtil.Assert(Not IsNumeric(" + "), "Not IsNumeric("" + "")")
+    TestUtil.Assert(Not IsNumeric(" - "), "Not IsNumeric("" - "")")
+    ' Note: the two following tests should behave different in VBA 
(TODO/FIXME);
+    ' should it be unified maybe in non-VBA, too (a breaking change)?
+    TestUtil.Assert(Not IsNumeric(" + 0 "), "Not IsNumeric("" + 0 "")")
+    TestUtil.Assert(Not IsNumeric(" - 0 "), "Not IsNumeric("" - 0 "")")
+
+    Exit Sub
+errorHandler:
+    TestUtil.ReportErrorHandler("verify_IsNumeric", Err, Error$, Erl)
+End Sub
diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx
index 82652e5dbff6..11725dec5b29 100644
--- a/basic/source/sbx/sbxconv.hxx
+++ b/basic/source/sbx/sbxconv.hxx
@@ -64,7 +64,7 @@ inline auto ImpDoubleToSalInt64(double d)
 extern void ImpCvtNum( double nNum, short nPrec, OUString& rRes, bool 
bCoreString=false );
 extern ErrCode ImpScan
     ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_uInt16* 
pLen,
-      bool bOnlyIntntl );
+      bool* pHasNumber, bool bOnlyIntntl );
 // A version that uses defaults / compatibility settings for bOnlyIntntl
 extern ErrCode ImpScan
     ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_uInt16* 
pLen );
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index 1084d6cf2810..008b5aeb0a4e 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -71,7 +71,7 @@ static bool ImpStrChr( std::u16string_view str, sal_Unicode c 
) { return str.fin
 // conversion error if data type is fixed and it doesn't fit
 
 ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, SbxDataType& rType,
-                  sal_uInt16* pLen, bool bOnlyIntntl )
+                  sal_uInt16* pLen, bool* pHasNumber, bool bOnlyIntntl )
 {
     sal_Unicode cDecSep, cGrpSep, cDecSepAlt;
     if( bOnlyIntntl )
@@ -102,6 +102,7 @@ ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, 
SbxDataType& rType,
         p++;
         bMinus = true;
     }
+    const auto pNumberStart = p;
     if (p != rWSrc.end()
         && (rtl::isAsciiDigit(*p)
             || ((*p == cDecSep || (cGrpSep && *p == cGrpSep) || (cDecSepAlt && 
*p == cDecSepAlt))
@@ -231,11 +232,14 @@ ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, 
SbxDataType& rType,
         return ERRCODE_BASIC_CONVERSION;
     }
 #endif
+    const auto pNumberEnd = p;
     // tdf#146672 - skip whitespaces and tabs at the end of the scanned string
     while (p != rWSrc.end() && (*p == ' ' || *p == '   '))
         p++;
     if( pLen )
         *pLen = static_cast<sal_uInt16>( p - pStart );
+    if (pHasNumber)
+        *pHasNumber = pNumberEnd > pNumberStart;
     if( bMinus )
         nVal = -nVal;
     rType = eScanType;
@@ -248,14 +252,14 @@ ErrCode ImpScan(std::u16string_view rSrc, double& nVal, 
SbxDataType& rType, sal_
     static const bool bEnv = std::getenv("LIBREOFFICE6FLOATINGPOINTMODE") != 
nullptr;
     bool bMode = bEnv || 
Basic::Compatibility::UseLibreOffice6FloatingPointConversion::get();
 
-    return ImpScan(rSrc, nVal, rType, pLen, !bMode);
+    return ImpScan(rSrc, nVal, rType, pLen, nullptr, !bMode);
 }
 
 // port for CDbl in the Basic
 ErrCode SbxValue::ScanNumIntnl( const OUString& rSrc, double& nVal, bool 
bSingle )
 {
     sal_uInt16 nLen = 0;
-    ErrCode nRetError = ImpScan( rSrc, nVal, o3tl::temporary(SbxDataType()), 
&nLen,
+    ErrCode nRetError = ImpScan( rSrc, nVal, o3tl::temporary(SbxDataType()), 
&nLen, nullptr,
         /*bOnlyIntntl*/true );
     // read completely?
     if( nRetError == ERRCODE_NONE && nLen != rSrc.getLength() )
diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx
index da1efcf688ce..6b70fe31131a 100644
--- a/basic/source/sbx/sbxvalue.cxx
+++ b/basic/source/sbx/sbxvalue.cxx
@@ -693,8 +693,9 @@ bool SbxValue::ImpIsNumeric( bool bOnlyIntntl ) const
             double n;
             SbxDataType t2;
             sal_uInt16 nLen = 0;
-            if( ImpScan( s, n, t2, &nLen, bOnlyIntntl ) == ERRCODE_NONE )
-                return nLen == s.getLength();
+            bool bHasNumber = false;
+            if( ImpScan( s, n, t2, &nLen, &bHasNumber, bOnlyIntntl ) == 
ERRCODE_NONE )
+                return nLen == s.getLength() && bHasNumber;
         }
         return false;
     }

Reply via email to