sc/qa/extras/macros-test.cxx              |   27 +++++++++++++++++++
 sc/qa/extras/testdocuments/tdf159412.fods |   41 ++++++++++++++++++++++++++++++
 scripting/source/basprov/basscript.cxx    |   19 ++++++++++---
 3 files changed, 83 insertions(+), 4 deletions(-)

New commits:
commit 4541614e5f88604b4b1e17b0223d11c2e330d451
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Jan 28 23:53:22 2024 +0600
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Jan 29 03:34:21 2024 +0100

    tdf#159412: make sure to keep the value while changing the type
    
    SbxValue::SetType clears the original value. We need to use the Get/Put
    cycle, asking for a specific type in Get, and then making sure that the
    variable is not fixed on Put.
    
    Change-Id: I0a6c106d511e8491c89a5a2153f47a708f83ee1e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162664
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx
index 4494f3f65bee..92878cf2bea5 100644
--- a/sc/qa/extras/macros-test.cxx
+++ b/sc/qa/extras/macros-test.cxx
@@ -897,6 +897,33 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf116127)
     CPPUNIT_ASSERT_EQUAL(Any(true), aRet);
 }
 
+CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf159412)
+{
+    // Run a macro, that itself calls two other functions using invoke,
+    // passing a small integer value to agruments of types Long and Double
+    createScDoc("tdf159412.fods");
+
+    css::uno::Any aRet;
+    css::uno::Sequence<sal_Int16> aOutParamIndex;
+    css::uno::Sequence<css::uno::Any> aOutParam;
+    css::uno::Sequence<css::uno::Any> aParams;
+
+    SfxObjectShell::CallXScript(
+        mxComponent,
+        
"vnd.sun.Star.script:Standard.Module1.TestInvoke?language=Basic&location=document",
+        aParams, aRet, aOutParamIndex, aOutParam);
+
+    OUString aReturnValue;
+    aRet >>= aReturnValue;
+
+    // Without the fix in place, this test would have failed with
+    // - Expected: 1 Long/2 Double
+    // - Actual  : 0 Long/0 Double
+    // i.e., the passed 1 and 2 values were lost.
+
+    CPPUNIT_ASSERT_EQUAL(u"1 Long/2 Double"_ustr, aReturnValue);
+}
+
 ScMacrosTest::ScMacrosTest()
       : ScModelTestBase("/sc/qa/extras/testdocuments")
 {
diff --git a/sc/qa/extras/testdocuments/tdf159412.fods 
b/sc/qa/extras/testdocuments/tdf159412.fods
new file mode 100644
index 000000000000..ec537dd06167
--- /dev/null
+++ b/sc/qa/extras/testdocuments/tdf159412.fods
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
office:version="1.3" 
office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:scripts>
+  <office:script script:language="ooo:Basic">
+   <ooo:libraries>
+    <ooo:library-embedded ooo:name="Standard">
+     <ooo:module ooo:name="Module1">
+      <ooo:source-code>REM  *****  BASIC  *****
+
+Function TestInvoke
+  script = 
ThisComponent.scriptProvider.getScript(&quot;vnd.sun.star.script:Standard.Module1.S_Ref_Long?language=Basic&amp;location=document&quot;)
+  ret = script.invoke(Array(1), Array(), Array())
+
+  script = 
ThisComponent.scriptProvider.getScript(&quot;vnd.sun.star.script:Standard.Module1.S_Ref_Dbl?language=Basic&amp;location=document&quot;)
+  ret = ret &amp; &quot;/&quot; &amp; script.invoke(Array(2), Array(), Array())
+
+  TestInvoke = ret
+End Function
+
+Function S_Ref_Long(n As Long)
+  S_Ref_Long = CStr(n) &amp; &quot; &quot; &amp; TypeName(n)
+End Function
+
+Function S_Ref_Dbl(n As Double)
+  S_Ref_Dbl = CStr(n) &amp; &quot; &quot; &amp; TypeName(n)
+End Function
+
+
+      </ooo:source-code>
+     </ooo:module>
+    </ooo:library-embedded>
+   </ooo:libraries>
+  </office:script>
+ </office:scripts>
+ <office:body>
+  <office:spreadsheet>
+   <table:table table:name="Sheet1"/>
+  </office:spreadsheet>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/scripting/source/basprov/basscript.cxx 
b/scripting/source/basprov/basscript.cxx
index de50f62e11de..148d1877d875 100644
--- a/scripting/source/basprov/basscript.cxx
+++ b/scripting/source/basprov/basscript.cxx
@@ -41,6 +41,17 @@ using namespace ::com::sun::star::document;
 using namespace ::com::sun::star::beans;
 
 
+static void ChangeTypeKeepingValue(SbxVariable& var, SbxDataType to)
+{
+    SbxValues val(to);
+    var.Get(val);
+    bool bSetFlag = var.IsSet(SbxFlagBits::Fixed);
+    var.ResetFlag(SbxFlagBits::Fixed);
+    var.Put(val);
+    if (bSetFlag)
+        var.SetFlag(SbxFlagBits::Fixed);
+}
+
 namespace basprov
 {
 
@@ -218,14 +229,14 @@ constexpr OUString BASSCRIPT_PROPERTY_CALLER = 
u"Caller"_ustr;
                             {
                                 sal_Int32 val = xSbxVar->GetLong();
                                 if (val >= -16777216 && val <= 16777215)
-                                    xSbxVar->SetType(t);
+                                    ChangeTypeKeepingValue(*xSbxVar, t);
                             }
                             else if (t == SbxDOUBLE && (a == SbxINTEGER || a 
== SbxLONG))
-                                xSbxVar->SetType(t);
+                                ChangeTypeKeepingValue(*xSbxVar, t);
                             else if (t == SbxLONG && a == SbxINTEGER)
-                                xSbxVar->SetType(t);
+                                ChangeTypeKeepingValue(*xSbxVar, t);
                             else if (t == SbxULONG && a == SbxUSHORT)
-                                xSbxVar->SetType(t);
+                                ChangeTypeKeepingValue(*xSbxVar, t);
                             // Enable passing by ref
                             if (t != SbxVARIANT)
                                 xSbxVar->SetFlag(SbxFlagBits::Fixed);

Reply via email to