wizards/source/scriptforge/SF_PythonHelper.xba   |   41 +++++++++++++++--------
 wizards/source/scriptforge/python/scriptforge.py |   10 +++--
 wizards/source/scriptforge/script.xlb            |   26 +++++++-------
 3 files changed, 47 insertions(+), 30 deletions(-)

New commits:
commit 8bc9ddf83236789328cc0fb4154a0bbf80d66078
Author:     Jean-Pierre Ledure <j...@ledure.be>
AuthorDate: Sun Sep 14 18:05:14 2025 +0200
Commit:     Jean-Pierre Ledure <j...@ledure.be>
CommitDate: Mon Sep 15 07:35:37 2025 +0200

    ScriptForge Extend Python-Basic gateway for objects
    
    A Python ScriptForge object may be passed to
    Basic functions, so far only when it is
    positioned as the first argument in the
    method signature.
    
    Like in:
       dialogB.Center(dialogA)
    
    The actual commit extends the protocol
    between Python and Basic to allow passing
    Python objects from another position
    in the method signature.
    
    However this possibility is limited to
    maximum 1 such argument.
    (Note that removing this limitation,
    if ever needed, would not require
    a big change.)
    
    No impact on user existing scripts.
    No documentation update.
    
    Change-Id: I191b7bb7c32b158b7274815577349ddfa1406b93
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190931
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <j...@ledure.be>

diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba 
b/wizards/source/scriptforge/SF_PythonHelper.xba
index 085d5ff639af..06048c3b598a 100644
--- a/wizards/source/scriptforge/SF_PythonHelper.xba
+++ b/wizards/source/scriptforge/SF_PythonHelper.xba
@@ -603,6 +603,9 @@ Public Function _PythonDispatcher(ByRef BasicObject As 
Variant _
 &apos;&apos;&apos;     Args:
 &apos;&apos;&apos;             BasicObject: a module or a class instance - May 
also be the reserved string: &quot;SF_Services&quot;
 &apos;&apos;&apos;             CallType: one of the constants applicable to a 
CallByName statement + optional protocol flags
+&apos;&apos;&apos;                     When CallType is an array (applicable 
when CallType includes cstObject)
+&apos;&apos;&apos;                             CallType[0] = CallType scalar
+&apos;&apos;&apos;                             CallType[1] = argument index on 
which to apply the scalar value
 &apos;&apos;&apos;             Script: the name of the method or property
 &apos;&apos;&apos;             Args: the arguments to pass to the method. 
Input arguments can contain symbolic constants for Null, Missing, etc.
 &apos;&apos;&apos;     Returns:
@@ -621,6 +624,8 @@ Public Function _PythonDispatcher(ByRef BasicObject As 
Variant _
 
 Dim vReturn As Variant                         &apos;  The value returned by 
the invoked property or method
 Dim vReturnArray As Variant                    &apos;  Return value
+Dim iCallType As Integer                       &apos;  Alias of CallType
+Dim iArgIndex As Integer                       &apos;  Index companion when 
CallType is an array
 Dim vBasicObject As Variant                    &apos;  Alias of BasicObject to 
avoid &quot;Object reference not set&quot; error
 Dim iNbArgs As Integer                         &apos;  Number of valid input 
arguments
 Dim vArg As Variant                                    &apos;  Alias for a 
single argument
@@ -653,7 +658,8 @@ Const cstDateRet = 128              &apos;  Return value 
can be a date
 Const cstUno = 256                     &apos;  Return value can be a UNO object
 Const cstArgArray = 512                &apos;  Any argument can be a 2D array
 Const cstRetArray = 1024       &apos;  Return value can be an array
-Const cstObject = 2048         &apos;  1st argument is a Basic object when 
numeric
+Const cstObject = 2048         &apos;  n-th argument is a Basic object when 
numeric
+                                                       &apos;  n (default = 0) 
can be passed as companion in an array
 Const cstHardCode = 4096       &apos;  Method must not be executed with 
CallByName()
 &apos; Returned object nature
 Const objMODULE = 1, objCLASS = 2, objDICT = 3, objUNO = 4
@@ -665,6 +671,15 @@ Check:
        &apos;  Ignore Null basic objects (Null = Null or Nothing)
        If IsNull(BasicObject) Or IsEmpty(BasicObject) Then GoTo Catch
 
+       &apos;  Intercept CallType when the targeted argument should be 
identified
+       If IsArray(CallType) Then
+               iCallType = CallType(0)
+               iArgIndex = CallType(1)
+       Else
+               iCallType = CallType
+               iArgIndex = 0
+       End If
+
        &apos;  Reinterpret arguments one by one into vArgs
        &apos;  - convert UNO dates/times
        &apos;  - identify conventional NoArgs/Empty/Null/Missing constants
@@ -680,7 +695,7 @@ Check:
                                If vArg = cstNoArgs Then Exit For
                        End If
                        &apos;  Is 1st argument a reference to a Basic object ?
-                       If i = 0 And (( CallType And cstObject ) = cstObject) 
And SF_Utils._VarTypeExt(vArg) = V_NUMERIC Then
+                       If i = iArgIndex And (( iCallType And cstObject ) = 
cstObject) And SF_Utils._VarTypeExt(vArg) = V_NUMERIC Then
                                If vArg &lt; 0 Or Not 
IsArray(_SF_.PythonStorage) Then GoTo Catch
                                If vArg &gt; UBound(_SF_.PythonStorage) Then 
GoTo Catch
                                vArg = _SF_.PythonStorage(vArg)
@@ -695,8 +710,8 @@ Check:
                                        Exit For        &apos;  Next arguments 
must be missing also
                                End If
                        ElseIf  VarType(vArg) = V_OBJECT Then
-                               If ( CallType And cstDateArg ) = cstDateArg 
Then vArg = CDateFromUnoDateTime(vArg)
-                       ElseIf ( CallType And cstDictArg ) = cstDictArg Then
+                               If ( iCallType And cstDateArg ) = cstDateArg 
Then vArg = CDateFromUnoDateTime(vArg)
+                       ElseIf ( iCallType And cstDictArg ) = cstDictArg Then
                                If IsArray(vArg) Then
                                        If UBound(vArg) &gt;= 0 Then
                                                If sess.UnoObjectType(vArg(0)) 
= &quot;com.sun.star.beans.PropertyValue&quot; Then
@@ -776,7 +791,7 @@ Try:
                        sLibrary = Split(sServiceName, &quot;.&quot;)(0)
 
                        &apos;  Methods in standard modules are called by 
ExecuteBasicScript() when arrays are returned
-                       If Not bBasicClass And (CallType And vbMethod) = 
vbMethod And (CallType And cstRetArray) = cstRetArray Then
+                       If Not bBasicClass And (iCallType And vbMethod) = 
vbMethod And (iCallType And cstRetArray) = cstRetArray Then
                                sScript = sLibrary &amp; &quot;.&quot; &amp; 
sObjectType &amp; &quot;.&quot; &amp; Script
                                &apos;  Force validation in targeted function, 
not in ExecuteBasicScript()
                                _SF_.StackLevel = -1
@@ -794,14 +809,14 @@ Try:
                                _SF_.StackLevel = 0
 
                        &apos;  Properties in any service are got and set with 
obj.GetProperty/SetProperty(...)
-                       ElseIf (CallType And vbGet) = vbGet Then        &apos;  
In some cases (Calc ...) GetProperty may have an argument
+                       ElseIf (iCallType And vbGet) = vbGet Then       &apos;  
In some cases (Calc ...) GetProperty may have an argument
                                If UBound(vArgs) &lt; 0 Then vReturn = 
vBasicObject.GetProperty(Script) Else vReturn = 
vBasicObject.GetProperty(Script, vArgs(0))
-                       ElseIf (CallType And vbLet) = vbLet Then
+                       ElseIf (iCallType And vbLet) = vbLet Then
                                vReturn = vBasicObject.SetProperty(Script, 
vArgs(0))
 
                        &apos;  Methods in class modules using a 2D array or 
returning arrays are hardcoded as exceptions. Bug #138155
-                       ElseIf ((CallType And vbMethod) + (CallType And 
cstArgArray)) = vbMethod + cstArgArray Or _
-                                  ((CallType And vbMethod) + (CallType And 
cstRetArray)) = vbMethod + cstRetArray Then
+                       ElseIf ((iCallType And vbMethod) + (iCallType And 
cstArgArray)) = vbMethod + cstArgArray Or _
+                                  ((iCallType And vbMethod) + (iCallType And 
cstRetArray)) = vbMethod + cstRetArray Then
                                If Script = &quot;Methods&quot; Then
                                        vReturn = vBasicObject.Methods()
                                ElseIf Script = &quot;Properties&quot; Then
@@ -875,7 +890,7 @@ Try:
                                End If
 
                        &apos;  Specific methods in class modules may better 
not be executed with CallByName() because they do not return immediately
-                       ElseIf bBasicClass And ((CallType And vbMethod) + 
(CallType And cstHardCode)) = vbMethod + cstHardCode Then
+                       ElseIf bBasicClass And ((iCallType And vbMethod) + 
(iCallType And cstHardCode)) = vbMethod + cstHardCode Then
                                Select Case sServiceName
                                        Case &quot;SFDialogs.Dialog&quot;
                                                Select Case Script
@@ -884,7 +899,7 @@ Try:
                                End Select
 
                        &apos;  Methods in all modules are invoked with 
CallByName
-                       ElseIf ((CallType And vbMethod) = vbMethod) Then
+                       ElseIf ((iCallType And vbMethod) = vbMethod) Then
                                Select Case UBound(vArgs)
                                        &apos;  Dirty alternatives to process 
usual and ParamArray cases
                                        &apos;  But, up to ... how many ?
@@ -934,7 +949,7 @@ Try:
                        End If
 
                        &apos;  Post processing
-                       If (CallType And cstPost) = cstPost Then
+                       If (iCallType And cstPost) = cstPost Then
                                If Script = &quot;Dispose&quot; Then
                                        &apos;  Special case: Dispose() must 
update the cache for class objects created in Python scripts
                                        Set _SF_.PythonStorage(BasicObject) = 
Nothing
@@ -971,7 +986,7 @@ Try:
        ElseIf VarType(vReturn) = V_OBJECT And Not IsNull(vReturn) Then
                &apos;  Uno or not Uno ?
                bUno = False
-               If (CallType And cstUno) = cstUno Then          &apos;  UNO 
considered only when pre-announced in CallType
+               If (iCallType And cstUno) = cstUno Then         &apos;  UNO 
considered only when pre-announced in CallType
                        Set oObjDesc = SF_Utils._VarTypeObj(vReturn)
                        bUno = ( oObjDesc.iVarType = V_UNOOBJECT )
                End If
diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index 3e21db3f114b..2ba18e377a60 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -348,9 +348,10 @@ class ScriptForge(object, metaclass = _Singleton):
                     argslist[i] = argdict.ConvertToPropertyValues()
             return tuple(argslist)
 
-        #
+        # Intercept flags is a tuple
+        flag = (flags[0] if isinstance(flags, tuple) else flags)
         # Intercept dictionary arguments
-        if flags & SFServices.flgDictArg == SFServices.flgDictArg:  # Bits 
comparison
+        if flag & SFServices.flgDictArg == SFServices.flgDictArg:  # Bits 
comparison
             args = ConvertDictArgs()
         #
         # Run the basic script
@@ -395,7 +396,7 @@ class ScriptForge(object, metaclass = _Singleton):
             # Intercept empty array
             if isinstance(returnvalue, uno.ByteSequence):
                 return ()
-            if flags & SFServices.flgDateRet == SFServices.flgDateRet:  # Bits 
comparison
+            if flag & SFServices.flgDateRet == SFServices.flgDateRet:  # Bits 
comparison
                 # Intercept all UNO dates in the 1D or 2D array
                 if isinstance(returnvalue[0], tuple):   # tuple of tuples
                     arr = []
@@ -555,7 +556,8 @@ class SFServices(object):
     flgArrayArg = 512  # 1st argument can be a 2D array
     flgArrayRet = 1024  # Invoked service method can return a 2D array 
(standard modules) or any array (class modules)
     flgUno = 256  # Invoked service method/property can return a UNO object
-    flgObject = 2048  # 1st argument may be a Basic object
+    flgObject = 2048  # N-th argument may be a Basic object
+                      # N (default = 0) can be passed as companion in a tuple
     flgHardCode = 4096  # Force hardcoded call to method, avoid CallByName()
     # Basic class type
     moduleClass, moduleStandard = 2, 1
diff --git a/wizards/source/scriptforge/script.xlb 
b/wizards/source/scriptforge/script.xlb
index 7c5f29231c27..bead89b8a66e 100644
--- a/wizards/source/scriptforge/script.xlb
+++ b/wizards/source/scriptforge/script.xlb
@@ -1,6 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 
1.0//EN" "library.dtd">
 <library:library xmlns:library="http://openoffice.org/2000/library"; 
library:name="ScriptForge" library:readonly="false" 
library:passwordprotected="false">
+ <library:element library:name="SF_Timer"/>
+ <library:element library:name="SF_FileSystem"/>
+ <library:element library:name="__License"/>
+ <library:element library:name="SF_Root"/>
+ <library:element library:name="SF_Region"/>
+ <library:element library:name="SF_L10N"/>
+ <library:element library:name="SF_SharedMemory"/>
+ <library:element library:name="_CodingConventions"/>
+ <library:element library:name="SF_Session"/>
+ <library:element library:name="SF_Dictionary"/>
+ <library:element library:name="SF_Exception"/>
+ <library:element library:name="SF_UI"/>
+ <library:element library:name="SF_Services"/>
  <library:element library:name="SF_PythonHelper"/>
  <library:element library:name="SF_Platform"/>
  <library:element library:name="SF_Array"/>
@@ -8,17 +21,4 @@
  <library:element library:name="SF_Utils"/>
  <library:element library:name="SF_String"/>
  <library:element library:name="_ModuleModel"/>
- <library:element library:name="SF_SharedMemory"/>
- <library:element library:name="SF_L10N"/>
- <library:element library:name="SF_Region"/>
- <library:element library:name="__License"/>
- <library:element library:name="SF_Root"/>
- <library:element library:name="SF_Timer"/>
- <library:element library:name="SF_FileSystem"/>
- <library:element library:name="SF_Services"/>
- <library:element library:name="SF_UI"/>
- <library:element library:name="SF_Exception"/>
- <library:element library:name="SF_Dictionary"/>
- <library:element library:name="SF_Session"/>
- <library:element library:name="_CodingConventions"/>
 </library:library>
\ No newline at end of file

Reply via email to