Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/basic/source/classes/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 165 kB image not shown  

Quelle  sbunoobj.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <sal/config.h>

#include <osl/diagnose.h>
#include <o3tl/any.hxx>
#include <o3tl/safeint.hxx>
#include <utility>
#include <vcl/svapp.hxx>
#include <comphelper/errcode.hxx>
#include <svl/hint.hxx>

#include <cppuhelper/implbase.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <comphelper/interfacecontainer4.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/processfactory.hxx>
#include <cppuhelper/weakref.hxx>

#include <rtl/math.hxx>
#include <rtl/ustrbuf.hxx>

#include <com/sun/star/script/ArrayWrapper.hpp>
#include <com/sun/star/script/CannotConvertException.hpp>
#include <com/sun/star/script/NativeObjectWrapper.hpp>
#include <com/sun/star/sheet/XSheetCellCursor.hpp>

#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/uno/DeploymentException.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/beans/PropertyConcept.hpp>
#include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/theIntrospection.hpp>
#include <com/sun/star/script/BasicErrorException.hpp>
#include <com/sun/star/script/InvocationAdapterFactory.hpp>
#include <com/sun/star/script/XAllListener.hpp>
#include <com/sun/star/script/Converter.hpp>
#include <com/sun/star/script/XDefaultProperty.hpp>
#include <com/sun/star/script/XDirectInvocation.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/reflection/XIdlArray.hpp>
#include <com/sun/star/reflection/XIdlReflection.hpp>
#include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
#include <com/sun/star/reflection/XSingletonTypeDescription.hpp>
#include <com/sun/star/reflection/theCoreReflection.hpp>
#include <com/sun/star/bridge/oleautomation/NamedArgument.hpp>
#include <com/sun/star/bridge/oleautomation/Date.hpp>
#include <com/sun/star/bridge/oleautomation/Decimal.hpp>
#include <com/sun/star/bridge/oleautomation/Currency.hpp>
#include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
#include <com/sun/star/script/XAutomationInvocation.hpp>

#include <rtlproto.hxx>

#include <basic/sbstar.hxx>
#include <basic/sbuno.hxx>
#include <basic/sberrors.hxx>
#include <sbunoobj.hxx>
#include <sbintern.hxx>
#include <runtime.hxx>

#include <algorithm>
#include <math.h>
#include <memory>
#include <string_view>
#include <unordered_map>
#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
#include <com/sun/star/reflection/XConstantsTypeDescription.hpp>

using com::sun::star::uno::Reference;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::reflection;
using namespace com::sun::star::beans;
using namespace com::sun::star::script;
using namespace com::sun::star::container;
using namespace com::sun::star::bridge;
using namespace cppu;


// Identifiers for creating the strings for dbg_Properties
constexpr OUString ID_DBG_SUPPORTEDINTERFACES = u"Dbg_SupportedInterfaces"_ustr;
constexpr OUString ID_DBG_PROPERTIES = u"Dbg_Properties"_ustr;
constexpr OUString ID_DBG_METHODS = u"Dbg_Methods"_ustr;

char const aSeqLevelStr[] = "[]";

// Gets the default property for a uno object. Note: There is some
// redirection built in. The property name specifies the name
// of the default property.

bool SbUnoObject::getDefaultPropName( SbUnoObject const * pUnoObj, OUString& sDfltProp )
{
    bool bResult = false;
    Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY );
    if ( xDefaultProp.is() )
    {
        sDfltProp = xDefaultProp->getDefaultPropertyName();
        if ( !sDfltProp.isEmpty() )
            bResult = true;
    }
    return bResult;
}

SbxVariable* getDefaultProp( SbxVariable* pRef )
{
    SbxVariable* pDefaultProp = nullptr;
    if ( pRef->GetType() == SbxOBJECT )
    {
        SbxObject* pObj = dynamic_cast<SbxObject*>(pRef);
        if (!pObj)
        {
            SbxBase* pObjVarObj = pRef->GetObject();
            pObj = dynamic_cast<SbxObject*>( pObjVarObj );
        }
        if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj))
        {
            pDefaultProp = pUnoObj->GetDfltProperty();
        }
    }
    return pDefaultProp;
}

void SetSbUnoObjectDfltPropName( SbxObject* pObj )
{
    SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj );
    if ( pUnoObj )
    {
        OUString sDfltPropName;

        if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
        {
            pUnoObj->SetDfltProperty( sDfltPropName );
        }
    }
}

// save CoreReflection statically
static Reference< XIdlReflection > getCoreReflection_Impl()
{
    return css::reflection::theCoreReflection::get(
        comphelper::getProcessComponentContext());
}

// save CoreReflection statically
static Reference< XHierarchicalNameAccess > const & getCoreReflection_HierarchicalNameAccess_Impl()
{
    static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess;

    if( !xCoreReflection_HierarchicalNameAccess.is() )
    {
        Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
        if( xCoreReflection.is() )
        {
            xCoreReflection_HierarchicalNameAccess =
                Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY );
        }
    }
    return xCoreReflection_HierarchicalNameAccess;
}

// Hold TypeProvider statically
static Reference< XHierarchicalNameAccess > const & getTypeProvider_Impl()
{
    static Reference< XHierarchicalNameAccess > xAccess;

    // Do we have already CoreReflection; if not obtain it
    if( !xAccess.is() )
    {
        const Reference< XComponentContext >& xContext(
            comphelper::getProcessComponentContext() );
        if( xContext.is() )
        {
            xContext->getValueByName(
                u"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr )
                    >>= xAccess;
            OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" );
        }
        if( !xAccess.is() )
        {
            throw DeploymentException(
                    u"/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible"_ustr );
        }
    }
    return xAccess;
}

// Hold TypeConverter statically
static Reference< XTypeConverter > const & getTypeConverter_Impl()
{
    static Reference< XTypeConverter > xTypeConverter;

    // Do we have already CoreReflection; if not obtain it
    if( !xTypeConverter.is() )
    {
        const Reference< XComponentContext >& xContext(
            comphelper::getProcessComponentContext() );
        if( xContext.is() )
        {
            xTypeConverter = Converter::create(xContext);
        }
        if( !xTypeConverter.is() )
        {
            throw DeploymentException(
                u"com.sun.star.script.Converter service not accessible"_ustr );
        }
    }
    return xTypeConverter;
}


// #111851 factory function to create an OLE object
SbUnoObject* createOLEObject_Impl( const OUString& aType )
{
    static const Reference<XMultiServiceFactory> xOLEFactory = [] {
        Reference<XMultiServiceFactory> xFactory;
        const Reference< XComponentContext >& xContext( comphelper::getProcessComponentContext() );
        if( xContext.is() )
        {
            Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager();
            xFactory.set(
                xSMgr->createInstanceWithContext( u"com.sun.star.bridge.OleObjectFactory"_ustr, xContext ),
                UNO_QUERY );
        }
        return xFactory;
    }();

    SbUnoObject* pUnoObj = nullptr;
    if( xOLEFactory.is() )
    {
        // some type names available in VBA can not be directly used in COM
        OUString aOLEType = aType;
        if ( aOLEType == "SAXXMLReader30" )
        {
            aOLEType = "Msxml2.SAXXMLReader.3.0";
        }
        Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType );
        if( xOLEObject.is() )
        {
            pUnoObj = new SbUnoObject( aType, Any(xOLEObject) );
            OUString sDfltPropName;

            if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
                pUnoObj->SetDfltProperty( sDfltPropName );
        }
    }
    return pUnoObj;
}


namespace
{
    void lcl_indent( OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel )
    {
        while ( _nLevel-- > 0 )
        {
            _inout_rBuffer.append( " " );
        }
    }
}

static void implAppendExceptionMsg( OUStringBuffer& _inout_rBuffer, const Exception& _e, std::u16string_view _rExceptionType, sal_Int32 _nLevel )
{
    _inout_rBuffer.append( "\n" );
    lcl_indent( _inout_rBuffer, _nLevel );
    _inout_rBuffer.append( "Type: " );

    if ( _rExceptionType.empty() )
        _inout_rBuffer.append( "Unknown" );
    else
        _inout_rBuffer.append( _rExceptionType );

    _inout_rBuffer.append( "\n" );
    lcl_indent( _inout_rBuffer, _nLevel );
    _inout_rBuffer.append( "Message: " );
    _inout_rBuffer.append( _e.Message );

}

// construct an error message for the exception
static OUString implGetExceptionMsg( const Exception& e, std::u16string_view aExceptionType_ )
{
    OUStringBuffer aMessageBuf;
    implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 );
    return aMessageBuf.makeStringAndClear();
}

static OUString implGetExceptionMsg( const Any& _rCaughtException )
{
    auto e = o3tl::tryAccess<Exception>(_rCaughtException);
    OSL_PRECOND( e, "implGetExceptionMsg: illegal argument!" );
    if ( !e )
    {
        return OUString();
    }
    return implGetExceptionMsg( *e, _rCaughtException.getValueTypeName() );
}

static Any convertAny( const Any& rVal, const Type& aDestType )
{
    Any aConvertedVal;
    const Reference< XTypeConverter >& xConverter = getTypeConverter_Impl();
    try
    {
        aConvertedVal = xConverter->convertTo( rVal, aDestType );
    }
    catchconst IllegalArgumentException& )
    {
        StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
            implGetExceptionMsg( ::cppu::getCaughtException() ) );
        return aConvertedVal;
    }
    catchconst CannotConvertException& e2 )
    {
        StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
                          implGetExceptionMsg( e2, u"com.sun.star.lang.IllegalArgumentException" ) );
        return aConvertedVal;
    }
    return aConvertedVal;
}


// #105565 Special Object to wrap a strongly typed Uno Any


// TODO: source out later
static Reference<XIdlClass> TypeToIdlClass( const Type& rType )
{
    return getCoreReflection_Impl()->forName(rType.getTypeName());
}

// Exception type unknown
templateclass EXCEPTION >
static OUString implGetExceptionMsg( const EXCEPTION& e )
{
    return implGetExceptionMsg( e, cppu::UnoType<decltype(e)>::get().getTypeName() );
}

static void implHandleBasicErrorException( BasicErrorException const & e )
{
    ErrCode nError = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(e.ErrorCode) );
    StarBASIC::Error( nError, e.ErrorMessageArgument );
}

static void implHandleWrappedTargetException( const Any& _rWrappedTargetException )
{
    Any aExamine( _rWrappedTargetException );

    // completely strip the first InvocationTargetException, its error message isn't of any
    // interest to the user, it just says something like "invoking the UNO method went wrong.".
    InvocationTargetException aInvocationError;
    if ( aExamine >>= aInvocationError )
        aExamine = aInvocationError.TargetException;

    BasicErrorException aBasicError;

    ErrCode nError( ERRCODE_BASIC_EXCEPTION );
    OUStringBuffer aMessageBuf;

    // strip any other WrappedTargetException instances, but this time preserve the error messages.
    WrappedTargetException aWrapped;
    sal_Int32 nLevel = 0;
    while ( aExamine >>= aWrapped )
    {
        // special handling for BasicErrorException errors
        if ( aWrapped.TargetException >>= aBasicError )
        {
            nError = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(aBasicError.ErrorCode) );
            aMessageBuf.append( aBasicError.ErrorMessageArgument );
            aExamine.clear();
            break;
        }

        // append this round's message
        implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel );
        if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION )
            // there is a next chain element
            aMessageBuf.append( "\nTargetException:" );

        // next round
        aExamine = aWrapped.TargetException;
        ++nLevel;
    }

    if ( auto e = o3tl::tryAccess<Exception>(aExamine) )
    {
        // the last element in the chain is still an exception, but no WrappedTargetException
        implAppendExceptionMsg( aMessageBuf, *e, aExamine.getValueTypeName(), nLevel );
    }

    StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() );
}

static void implHandleAnyException( const Any& _rCaughtException )
{
    BasicErrorException aBasicError;
    WrappedTargetException aWrappedError;

    if ( _rCaughtException >>= aBasicError )
    {
        implHandleBasicErrorException( aBasicError );
    }
    else if ( _rCaughtException >>= aWrappedError )
    {
        implHandleWrappedTargetException( _rCaughtException );
    }
    else
    {
        StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) );
    }
}

namespace {

// NativeObjectWrapper handling
struct ObjectItem
{
    SbxObjectRef    m_xNativeObj;

    explicit ObjectItem( SbxObject* pNativeObj )
        : m_xNativeObj( pNativeObj )
    {}
};

}

typedef std::vector< ObjectItem > NativeObjectWrapperVector;

namespace {

NativeObjectWrapperVector gaNativeObjectWrapperVector;

}

void clearNativeObjectWrapperVector()
{
    gaNativeObjectWrapperVector.clear();
}

static sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj )
{
    sal_uInt32 nIndex = gaNativeObjectWrapperVector.size();
    gaNativeObjectWrapperVector.emplace_back( pNativeObj );
    return nIndex;
}

static SbxObject* lcl_getNativeObject( sal_uInt32 nIndex )
{
    SbxObjectRef xRetObj;
    if( nIndex < gaNativeObjectWrapperVector.size() )
    {
        ObjectItem& rItem = gaNativeObjectWrapperVector[ nIndex ];
        xRetObj = rItem.m_xNativeObj;
    }
    return xRetObj.get();
}

// convert from Uno to Sbx
static SbxDataType unoToSbxType( TypeClass eType )
{
    SbxDataType eRetType = SbxVOID;

    switch( eType )
    {
        case TypeClass_INTERFACE:
        case TypeClass_TYPE:
        case TypeClass_STRUCT:
        case TypeClass_EXCEPTION:       eRetType = SbxOBJECT;   break;

        case TypeClass_ENUM:            eRetType = SbxLONG;     break;
        case TypeClass_SEQUENCE:
            eRetType = SbxDataType( SbxOBJECT | SbxARRAY );
            break;


        case TypeClass_ANY:             eRetType = SbxVARIANT;  break;
        case TypeClass_BOOLEAN:         eRetType = SbxBOOL;     break;
        case TypeClass_CHAR:            eRetType = SbxCHAR;     break;
        case TypeClass_STRING:          eRetType = SbxSTRING;   break;
        case TypeClass_FLOAT:           eRetType = SbxSINGLE;   break;
        case TypeClass_DOUBLE:          eRetType = SbxDOUBLE;   break;
        case TypeClass_BYTE:            eRetType = SbxINTEGER;  break;
        case TypeClass_SHORT:           eRetType = SbxINTEGER;  break;
        case TypeClass_LONG:            eRetType = SbxLONG;     break;
        case TypeClass_HYPER:           eRetType = SbxSALINT64; break;
        case TypeClass_UNSIGNED_SHORT:  eRetType = SbxUSHORT;   break;
        case TypeClass_UNSIGNED_LONG:   eRetType = SbxULONG;    break;
        case TypeClass_UNSIGNED_HYPER:  eRetType = SbxSALUINT64;break;
        defaultbreak;
    }
    return eRetType;
}

static SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass )
{
    SbxDataType eRetType = SbxVOID;
    if( xIdlClass.is() )
    {
        TypeClass eType = xIdlClass->getTypeClass();
        eRetType = unoToSbxType( eType );
    }
    return eRetType;
}

static void implSequenceToMultiDimArray( SbxDimArray*& pArray, Sequence< sal_Int32 >&&nbsp;indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32 dimension, bool bIsZeroIndex, Type const * pType )
{
    const Type& aType = aValue.getValueType();
    TypeClass eTypeClass = aType.getTypeClass();

    sal_Int32 dimCopy = dimension;

    if ( eTypeClass == TypeClass_SEQUENCE )
    {
        Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
        Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
        typelib_TypeDescription * pTD = nullptr;
        aType.getDescription( &pTD );
        Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType );
        ::typelib_typedescription_release( pTD );

        sal_Int32 nLen = xIdlArray->getLen( aValue );
        for ( sal_Int32 index = 0; index < nLen; ++index )
        {
            auto pindices = indices.getArray();
            Any aElementAny = xIdlArray->get( aValue, static_cast<sal_uInt32>(index) );
            // This detects the dimension were currently processing
            if ( dimCopy == dimension )
            {
                ++dimCopy;
                if ( sizes.getLength() < dimCopy )
                {
                    sizes.realloc( sizes.getLength() + 1 );
                    sizes.getArray()[ sizes.getLength() - 1 ] = nLen;
                    indices.realloc( indices.getLength() + 1 );
                    pindices = indices.getArray();
                }
            }

            if ( bIsZeroIndex )
                pindices[ dimCopy - 1 ] = index;
            else
                pindices[ dimCopy - 1] = index + 1;

            implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType );
        }

    }
    else
    {
        if ( !indices.hasElements() )
        {
            // Should never ever get here ( indices.getLength()
            // should equal number of dimensions in the array )
            // And that should at least be 1 !
            // #QUESTION is there a better error?
            StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECT );
            return;
        }

        SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() );
        if ( !pArray )
        {
            pArray = new SbxDimArray( eSbxElementType );
            sal_Int32 nIndexLen = indices.getLength();

            // Dimension the array
            for ( sal_Int32 index = 0; index < nIndexLen; ++index )
            {
                if ( bIsZeroIndex )
                    pArray->unoAddDim(0, sizes[index] - 1);
                else
                    pArray->unoAddDim(1, sizes[index]);

            }
        }

        if ( pArray )
        {
            auto xVar = tools::make_ref<SbxVariable>( eSbxElementType );
            unoToSbxValue( xVar.get(), aValue );

            sal_Int32* pIndices = indices.getArray();
            pArray->Put(xVar.get(), pIndices);

        }
    }
}

void unoToSbxValue( SbxVariable* pVar, const Any& aValue )
{
    const Type& aType = aValue.getValueType();
    TypeClass eTypeClass = aType.getTypeClass();
    switch( eTypeClass )
    {
        case TypeClass_TYPE:
        {
            // Map Type to IdlClass
            Type aType_;
            aValue >>= aType_;
            Reference<XIdlClass> xClass = TypeToIdlClass( aType_ );
            Any aClassAny;
            aClassAny <<= xClass;

            // instantiate SbUnoObject
            SbUnoObject* pSbUnoObject = new SbUnoObject( OUString(), aClassAny );
            SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject);

            // If the object is invalid deliver null
            if( !pSbUnoObject->getUnoAny().hasValue() )
            {
                pVar->PutObject( nullptr );
            }
            else
            {
                pVar->PutObject( xWrapper.get() );
            }
        }
        break;
        // Interfaces and Structs must be wrapped in a SbUnoObject
        case TypeClass_INTERFACE:
        case TypeClass_STRUCT:
        case TypeClass_EXCEPTION:
        {
            if( eTypeClass == TypeClass_STRUCT )
            {
                ArrayWrapper aWrap;
                NativeObjectWrapper aNativeObjectWrapper;
                if ( aValue >>= aWrap )
                {
                    SbxDimArray* pArray = nullptr;
                    Sequence< sal_Int32 > indices;
                    Sequence< sal_Int32 > sizes;
                    implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, /*dimension*/0, aWrap.IsZeroIndex, nullptr );
                    if ( pArray )
                    {
                        SbxDimArrayRef xArray = pArray;
                        SbxFlagBits nFlags = pVar->GetFlags();
                        pVar->ResetFlag( SbxFlagBits::Fixed );
                        pVar->PutObject( xArray.get() );
                        pVar->SetFlags( nFlags );
                    }
                    else
                        pVar->PutEmpty();
                    break;
                }
                else if ( aValue >>= aNativeObjectWrapper )
                {
                    sal_uInt32 nIndex = 0;
                    if( aNativeObjectWrapper.ObjectId >>= nIndex )
                    {
                        SbxObject* pObj = lcl_getNativeObject( nIndex );
                        pVar->PutObject( pObj );
                    }
                    else
                        pVar->PutEmpty();
                    break;
                }
                else
                {
                    SbiInstance* pInst = GetSbData()->pInst;
                    if( pInst && pInst->IsCompatibility() )
                    {
                        oleautomation::Date aDate;
                        if( aValue >>= aDate )
                        {
                            pVar->PutDate( aDate.Value );
                            break;
                        }
                        else
                        {
                            oleautomation::Decimal aDecimal;
                            if( aValue >>= aDecimal )
                            {
                                pVar->PutDecimal( aDecimal );
                                break;
                            }
                            else
                            {
                                oleautomation::Currency aCurrency;
                                if( aValue >>= aCurrency )
                                {
                                    pVar->PutCurrency( aCurrency.Value );
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            // instantiate a SbUnoObject
            SbUnoObject* pSbUnoObject = new SbUnoObject( OUString(), aValue );
            //If this is called externally e.g. from the scripting
            //framework then there is no 'active' runtime the default property will not be set up
            //only a vba object will have XDefaultProp set anyway so... this
            //test seems a bit of overkill
            //if ( SbiRuntime::isVBAEnabled() )
            {
                OUString sDfltPropName;

                if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) )
                {
                    pSbUnoObject->SetDfltProperty( sDfltPropName );
                }
            }
            SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject);

            // If the object is invalid deliver null
            if( !pSbUnoObject->getUnoAny().hasValue() )
            {
                pVar->PutObject( nullptr );
            }
            else
            {
                pVar->PutObject( xWrapper.get() );
            }
        }
        break;


        case TypeClass_ENUM:
        {
            sal_Int32 nEnum = 0;
            enum2int( nEnum, aValue );
            pVar->PutLong( nEnum );
        }
            break;

        case TypeClass_SEQUENCE:
        {
            Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
            Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
            sal_Int32 i, nLen = xIdlArray->getLen( aValue );

            typelib_TypeDescription * pTD = nullptr;
            aType.getDescription( &pTD );
            assert( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE );
            Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType );
            ::typelib_typedescription_release( pTD );

            // build an Array in Basic
            SbxDimArrayRef xArray;
            SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() );
            xArray = new SbxDimArray( eSbxElementType );
            if( nLen > 0 )
            {
                xArray->unoAddDim(0, nLen - 1);

                // register the elements as variables
                for( i = 0 ; i < nLen ; i++ )
                {
                    // convert elements
                    Any aElementAny = xIdlArray->get( aValue, static_cast<sal_uInt32>(i) );
                    auto xVar = tools::make_ref<SbxVariable>( eSbxElementType );
                    unoToSbxValue( xVar.get(), aElementAny );

                    // put into the Array
                    xArray->Put(xVar.get(), &i);
                }
            }
            else
            {
                xArray->unoAddDim(0, -1);
            }

            // return the Array
            SbxFlagBits nFlags = pVar->GetFlags();
            pVar->ResetFlag( SbxFlagBits::Fixed );
            pVar->PutObject( xArray.get() );
            pVar->SetFlags( nFlags );

        }
        break;


        case TypeClass_BOOLEAN:         pVar->PutBool( *o3tl::forceAccess<bool>(aValue) ); break;
        case TypeClass_CHAR:
        {
            pVar->PutChar( *o3tl::forceAccess<sal_Unicode>(aValue) );
            break;
        }
        case TypeClass_STRING:          { OUString val; aValue >>= val; pVar->PutString( val ); }  break;
        case TypeClass_FLOAT:           { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break;
        case TypeClass_DOUBLE:          { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break;
        case TypeClass_BYTE:            { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
        case TypeClass_SHORT:           { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
        case TypeClass_LONG:            { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break;
        case TypeClass_HYPER:           { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break;
        case TypeClass_UNSIGNED_SHORT:  { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break;
        case TypeClass_UNSIGNED_LONG:   { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break;
        case TypeClass_UNSIGNED_HYPER:  { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break;
        default:                        pVar->PutEmpty();                       break;
    }
}

// Deliver the reflection for Sbx types
static Type getUnoTypeForSbxBaseType( SbxDataType eType )
{
    Type aRetType = cppu::UnoType<void>::get();
    switch( eType )
    {
        case SbxNULL:       aRetType = cppu::UnoType<XInterface>::get(); break;
        case SbxINTEGER:    aRetType = cppu::UnoType<sal_Int16>::get(); break;
        case SbxLONG:       aRetType = cppu::UnoType<sal_Int32>::get(); break;
        case SbxSINGLE:     aRetType = cppu::UnoType<float>::get(); break;
        case SbxDOUBLE:     aRetType = cppu::UnoType<double>::get(); break;
        case SbxCURRENCY:   aRetType = cppu::UnoType<oleautomation::Currency>::get(); break;
        case SbxDECIMAL:    aRetType = cppu::UnoType<oleautomation::Decimal>::get(); break;
        case SbxDATE:       {
                            SbiInstance* pInst = GetSbData()->pInst;
                            if( pInst && pInst->IsCompatibility() )
                                aRetType = cppu::UnoType<oleautomation::Date>::get();
                            else
                                aRetType = cppu::UnoType<double>::get();
                            }
                            break;
        case SbxSTRING:     aRetType = cppu::UnoType<OUString>::get(); break;
        case SbxBOOL:       aRetType = cppu::UnoType<sal_Bool>::get(); break;
        case SbxVARIANT:    aRetType = cppu::UnoType<Any>::get(); break;
        case SbxCHAR:       aRetType = cppu::UnoType<cppu::UnoCharType>::get(); break;
        case SbxBYTE:       aRetType = cppu::UnoType<sal_Int8>::get(); break;
        case SbxUSHORT:     aRetType = cppu::UnoType<cppu::UnoUnsignedShortType>::get(); break;
        case SbxULONG:      aRetType = ::cppu::UnoType<sal_uInt32>::get(); break;
        // map machine-dependent ones to long for consistency
        case SbxINT:        aRetType = ::cppu::UnoType<sal_Int32>::get(); break;
        case SbxUINT:       aRetType = ::cppu::UnoType<sal_uInt32>::get(); break;
        defaultbreak;
    }
    return aRetType;
}

// Converting of Sbx to Uno without a know target class for TypeClass_ANY
static Type getUnoTypeForSbxValue( const SbxValue* pVal )
{
    Type aRetType = cppu::UnoType<void>::get();
    if( !pVal )
        return aRetType;

    // convert SbxType to Uno
    SbxDataType eBaseType = pVal->SbxValue::GetType();
    if( eBaseType == SbxOBJECT )
    {
        SbxBaseRef xObj = pVal->GetObject();
        if( !xObj.is() )
        {
            aRetType = cppu::UnoType<XInterface>::get();
            return aRetType;
        }

        ifauto pArray = dynamic_cast<SbxDimArray*>( xObj.get() ) )
        {
            sal_Int32 nDims = pArray->GetDims();
            Type aElementType = getUnoTypeForSbxBaseType( static_cast<SbxDataType>(pArray->GetType() & 0xfff) );
            TypeClass eElementTypeClass = aElementType.getTypeClass();

            // Normal case: One dimensional array
            sal_Int32 nLower, nUpper;
            if (nDims == 1 && pArray->GetDim(1, nLower, nUpper))
            {
                if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
                {
                    // If all elements of the arrays are from the same type, take
                    // this one - otherwise the whole will be considered as Any-Sequence
                    bool bNeedsInit = true;

                    for (sal_Int32 aIdx[1] = { nLower }; aIdx[0] <= nUpper; ++aIdx[0])
                    {
                        SbxVariableRef xVar = pArray->Get(aIdx);
                        Type aType = getUnoTypeForSbxValue( xVar.get() );
                        if( bNeedsInit )
                        {
                            if( aType.getTypeClass() == TypeClass_VOID )
                            {
                                // if only first element is void: different types  -> []any
                                // if all elements are void: []void is not allowed -> []any
                                aElementType = cppu::UnoType<Any>::get();
                                break;
                            }
                            aElementType = std::move(aType);
                            bNeedsInit = false;
                        }
                        else if( aElementType != aType )
                        {
                            // different types -> AnySequence
                            aElementType = cppu::UnoType<Any>::get();
                            break;
                        }
                    }
                }

                OUString aSeqTypeName = aSeqLevelStr + aElementType.getTypeName();
                aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName );
            }
            // #i33795 Map also multi dimensional arrays to corresponding sequences
            else if( nDims > 1 )
            {
                if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
                {
                    // For this check the array's dim structure does not matter
                    sal_uInt32 nFlatArraySize = pArray->Count();

                    bool bNeedsInit = true;
                    for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ )
                    {
                        SbxVariableRef xVar = pArray->SbxArray::Get(i);
                        Type aType = getUnoTypeForSbxValue( xVar.get() );
                        if( bNeedsInit )
                        {
                            if( aType.getTypeClass() == TypeClass_VOID )
                            {
                                // if only first element is void: different types  -> []any
                                // if all elements are void: []void is not allowed -> []any
                                aElementType = cppu::UnoType<Any>::get();
                                break;
                            }
                            aElementType = std::move(aType);
                            bNeedsInit = false;
                        }
                        else if( aElementType != aType )
                        {
                            // different types -> AnySequence
                            aElementType = cppu::UnoType<Any>::get();
                            break;
                        }
                    }
                }

                OUStringBuffer aSeqTypeName;
                for(sal_Int32 iDim = 0 ; iDim < nDims ; iDim++ )
                {
                    aSeqTypeName.append(aSeqLevelStr);
                }
                aSeqTypeName.append(aElementType.getTypeName());
                aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
            }
        }
        // No array, but ...
        else ifauto obj = dynamic_cast<SbUnoObject*>( xObj.get() ) )
        {
            aRetType = obj->getUnoAny().getValueType();
        }
        // SbUnoAnyObject?
        else ifauto any = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) )
        {
            aRetType = any->getValue().getValueType();
        }
        // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
    }
    // No object, convert basic type
    else
    {
        if (eBaseType == SbxBYTE && pVal->GetByte() > 127)
        {
            // Basic Byte type is unsigned; cppu::UnoType<sal_uInt8> corresponds to UNO boolean,
            // so values 128-255 are only representable starting with UNO short types
            eBaseType = SbxUSHORT;
        }
        aRetType = getUnoTypeForSbxBaseType( eBaseType );
    }
    return aRetType;
}

// converting of Sbx to Uno without known target class for TypeClass_ANY
static Any sbxToUnoValueImpl( const SbxValue* pVar, bool bBlockConversionToSmallestType false )
{
    SbxDataType eBaseType = pVar->SbxValue::GetType();
    if( eBaseType == SbxOBJECT )
    {
        SbxBaseRef xObj = pVar->GetObject();
        if( xObj.is() )
        {
            ifauto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) )
                return obj->getValue();
            ifauto pClassModuleObj = dynamic_cast<SbClassModuleObject*>( xObj.get() ) )
            {
                Any aRetAny;
                SbModule& rClassModule = pClassModuleObj->getClassModule();
                if (rClassModule.createCOMWrapperForIface(aRetAny, pClassModuleObj))
                    return aRetAny;
            }
            ifdynamic_cast<const SbUnoObject*>( xObj.get() ) == nullptr )
            {
                // Create NativeObjectWrapper to identify object in case of callbacks
                SbxObject* pObj = dynamic_cast<SbxObject*>( pVar->GetObject() );
                if( pObj != nullptr )
                {
                    NativeObjectWrapper aNativeObjectWrapper;
                    sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj );
                    aNativeObjectWrapper.ObjectId <<= nIndex;
                    Any aRetAny;
                    aRetAny <<= aNativeObjectWrapper;
                    return aRetAny;
                }
            }
        }
    }

    Type aType = getUnoTypeForSbxValue( pVar );
    TypeClass eType = aType.getTypeClass();

    if( !bBlockConversionToSmallestType )
    {
        // #79615 Choose "smallest" representation for int values
        // because up cast is allowed, downcast not
        switch( eType )
        {
            case TypeClass_FLOAT:
            case TypeClass_DOUBLE:
            {
                double d = pVar->GetDouble();
                if( rtl::math::approxEqual(d, floor( d )) )
                {
                    if( d >= -128 && d <= 127 )
                        aType = ::cppu::UnoType<sal_Int8>::get();
                    else if( d >= SbxMININT && d <= SbxMAXINT )
                        aType = ::cppu::UnoType<sal_Int16>::get();
                    else if( d >= -SbxMAXLNG && d <= SbxMAXLNG )
                        aType = ::cppu::UnoType<sal_Int32>::get();
                }
                break;
            }
            case TypeClass_SHORT:
            {
                sal_Int16 n = pVar->GetInteger();
                if( n >= -128 && n <= 127 )
                    aType = ::cppu::UnoType<sal_Int8>::get();
                break;
            }
            case TypeClass_LONG:
            {
                sal_Int32 n = pVar->GetLong();
                if( n >= -128 && n <= 127 )
                    aType = ::cppu::UnoType<sal_Int8>::get();
                else if( n >= SbxMININT && n <= SbxMAXINT )
                    aType = ::cppu::UnoType<sal_Int16>::get();
                break;
            }
            case TypeClass_UNSIGNED_LONG:
            {
                sal_uInt32 n = pVar->GetLong();
                if( n <= SbxMAXUINT )
                    aType = cppu::UnoType<cppu::UnoUnsignedShortType>::get();
                break;
            }
            // TODO: need to add hyper types ?
            defaultbreak;
        }
    }

    return sbxToUnoValue( pVar, aType );
}


// Helper function for StepREDIMP
static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray,
    const Type& aElemType, sal_Int32 nMaxDimIndex, sal_Int32 nActualDim,
    sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
{
    sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1;
    OUStringBuffer aSeqTypeName;
    sal_Int32 i;
    for( i = 0 ; i < nSeqLevel ; i++ )
    {
        aSeqTypeName.append(aSeqLevelStr);
    }
    aSeqTypeName.append(aElemType.getTypeName());
    Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );

    // Create Sequence instance
    Any aRetVal;
    Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType );
    xIdlTargetClass->createObject( aRetVal );

    // Alloc sequence according to array bounds
    sal_Int32 nUpper = pUpperBounds[nActualDim];
    sal_Int32 nLower = pLowerBounds[nActualDim];
    sal_Int32 nSeqSize = nUpper - nLower + 1;
    Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
    xArray->realloc( aRetVal, nSeqSize );

    sal_Int32& ri = pActualIndices[nActualDim];

    for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ )
    {
        Any aElementVal;

        if( nActualDim < nMaxDimIndex )
        {
            aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType,
                nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds );
        }
        else
        {
            SbxVariable* pSource = pArray->Get(pActualIndices);
            aElementVal = sbxToUnoValue( pSource, aElemType );
        }

        try
        {
            // transfer to the sequence
            xArray->set( aRetVal, i, aElementVal );
        }
        catchconst IllegalArgumentException& )
        {
            StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
                implGetExceptionMsg( ::cppu::getCaughtException() ) );
        }
        catch (const IndexOutOfBoundsException&)
        {
            StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE );
        }
    }
    return aRetVal;
}

// Map old interface
Any sbxToUnoValue( const SbxValue* pVar )
{
    return sbxToUnoValueImpl( pVar );
}

// function to find a global identifier in
// the UnoScope and to wrap it for Sbx
static bool implGetTypeByName( const OUString& rName, Type& rRetType )
{
    bool bSuccess = false;

    const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl();
    if( xTypeAccess->hasByHierarchicalName( rName ) )
    {
        Any aRet = xTypeAccess->getByHierarchicalName( rName );
        Reference< XTypeDescription > xTypeDesc;
        aRet >>= xTypeDesc;

        if( xTypeDesc.is() )
        {
            rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() );
            bSuccess = true;
        }
    }
    return bSuccess;
}


// converting of Sbx to Uno with known target class
Any sbxToUnoValue( const SbxValue* pVar, const Type& rType, Property const * pUnoProperty )
{
    Any aRetVal;

    // #94560 No conversion of empty/void for MAYBE_VOID properties
    if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID )
    {
        if( pVar->IsEmpty() )
            return aRetVal;
    }

    SbxDataType eBaseType = pVar->SbxValue::GetType();
    if( eBaseType == SbxOBJECT )
    {
        SbxBaseRef xObj = pVar->GetObject();
        if ( auto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) )
        {
            return obj->getValue();
        }
    }

    TypeClass eType = rType.getTypeClass();

    // tdf#162431 - check for missing parameters
    if (eType != TypeClass_ANY && eType != TypeClass_VOID && pVar->GetType() == SbxERROR)
    {
        SbxVariable* paSbxVariable = dynamic_cast<SbxVariable*>(const_cast<SbxValue*>(pVar));
        if (paSbxVariable && SbiRuntime::IsMissing(paSbxVariable, 1))
            StarBASIC::Error(ERRCODE_BASIC_NOT_OPTIONAL);
    }

    switch( eType )
    {
        case TypeClass_INTERFACE:
        case TypeClass_STRUCT:
        case TypeClass_EXCEPTION:
        {
            Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );

            // null reference?
            if( pVar->IsNull() && eType == TypeClass_INTERFACE )
            {
                Reference< XInterface > xRef;
                OUString aClassName = xIdlTargetClass->getName();
                Type aClassType( xIdlTargetClass->getTypeClass(), aClassName );
                aRetVal.setValue( &xRef, aClassType );
            }
            else
            {
                // #112368 Special conversion for Decimal, Currency and Date
                if( eType == TypeClass_STRUCT )
                {
                    SbiInstance* pInst = GetSbData()->pInst;
                    if( pInst && pInst->IsCompatibility() )
                    {
                        if( rType == cppu::UnoType<oleautomation::Decimal>::get())
                        {
                            oleautomation::Decimal aDecimal;
                            pVar->fillAutomationDecimal( aDecimal );
                            aRetVal <<= aDecimal;
                            break;
                        }
                        else if( rType == cppu::UnoType<oleautomation::Currency>::get())
                        {
                            // assumes per previous code that ole Currency is Int64
                            aRetVal <<= pVar->GetInt64();
                            break;
                        }
                        else if( rType == cppu::UnoType<oleautomation::Date>::get())
                        {
                            oleautomation::Date aDate;
                            aDate.Value = pVar->GetDate();
                            aRetVal <<= aDate;
                            break;
                        }
                    }
                }

                SbxBaseRef pObj = pVar->GetObject();
                ifauto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) )
                {
                    aRetVal = obj->getUnoAny();
                }
                else ifauto structRef = dynamic_cast<SbUnoStructRefObject*>( pObj.get() ) )
                {
                    aRetVal = structRef->getUnoAny();
                }
                else
                {
                    // null object -> null XInterface
                    Reference<XInterface> xInt;
                    aRetVal <<= xInt;
                }
            }
        }
        break;

        case TypeClass_TYPE:
        {
            if( eBaseType == SbxOBJECT )
            {
                // XIdlClass?
                Reference< XIdlClass > xIdlClass;

                SbxBaseRef pObj = pVar->GetObject();
                ifauto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) )
                {
                    Any aUnoAny = obj->getUnoAny();
                    aUnoAny >>= xIdlClass;
                }

                if( xIdlClass.is() )
                {
                    OUString aClassName = xIdlClass->getName();
                    Type aType( xIdlClass->getTypeClass(), aClassName );
                    aRetVal <<= aType;
                }
            }
            else if( eBaseType == SbxSTRING )
            {
                OUString aTypeName = pVar->GetOUString();
                Type aType;
                bool bSuccess = implGetTypeByName( aTypeName, aType );
                if( bSuccess )
                {
                    aRetVal <<= aType;
                }
            }
        }
        break;


        case TypeClass_ENUM:
        {
            aRetVal = int2enum( pVar->GetLong(), rType );
        }
        break;

        case TypeClass_SEQUENCE:
        {
            SbxBaseRef xObj = pVar->GetObject();
            ifauto pArray = dynamic_cast<SbxDimArray*>( xObj.get() ) )
            {
                sal_Int32 nDims = pArray->GetDims();

                // Normal case: One dimensional array
                sal_Int32 nLower, nUpper;
                if (nDims == 1 && pArray->GetDim(1, nLower, nUpper))
                {
                    sal_Int32 nSeqSize = nUpper - nLower + 1;

                    // create the instance of the required sequence
                    Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
                    xIdlTargetClass->createObject( aRetVal );
                    Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
                    xArray->realloc( aRetVal, nSeqSize );

                    // Element-Type
                    OUString aClassName = xIdlTargetClass->getName();
                    typelib_TypeDescription * pSeqTD = nullptr;
                    typelib_typedescription_getByName( &pSeqTD, aClassName.pData );
                    assert( pSeqTD );
                    Type aElemType( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType );

                    // convert all array member and register them
                    sal_Int32 aIdx[1];
                    aIdx[0] = nLower;
                    for (sal_Int32 i = 0 ; i < nSeqSize; ++i, ++aIdx[0])
                    {
                        SbxVariableRef xVar = pArray->Get(aIdx);

                        // Convert the value of Sbx to Uno
                        Any aAnyValue = sbxToUnoValue( xVar.get(), aElemType );

                        try
                        {
                            // insert in the sequence
                            xArray->set( aRetVal, i, aAnyValue );
                        }
                        catchconst IllegalArgumentException& )
                        {
                            StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
                                implGetExceptionMsg( ::cppu::getCaughtException() ) );
                        }
                        catch (const IndexOutOfBoundsException&)
                        {
                            StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE );
                        }
                    }
                }
                // #i33795 Map also multi dimensional arrays to corresponding sequences
                else if( nDims > 1 )
                {
                    // Element-Type
                    typelib_TypeDescription * pSeqTD = nullptr;
                    Type aCurType( rType );
                    sal_Int32 nSeqLevel = 0;
                    Type aElemType;
                    do
                    {
                        OUString aTypeName = aCurType.getTypeName();
                        typelib_typedescription_getByName( &pSeqTD, aTypeName.pData );
                        assert( pSeqTD );
                        if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE )
                        {
                            aCurType = Type( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType );
                            nSeqLevel++;
                        }
                        else
                        {
                            aElemType = aCurType;
                            break;
                        }
                    }
                    whiletrue );

                    if( nSeqLevel == nDims )
                    {
                        std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDims]);
                        std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDims]);
                        std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDims]);
                        for(sal_Int32 i = 1 ; i <= nDims ; i++ )
                        {
                            sal_Int32 lBound, uBound;
                            pArray->GetDim(i, lBound, uBound);

                            sal_Int32 j = i - 1;
                            pActualIndices[j] = pLowerBounds[j] = lBound;
                            pUpperBounds[j] = uBound;
                        }

                        aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType,
                            nDims - 1, 0, pActualIndices.get(), pLowerBounds.get(), pUpperBounds.get() );
                    }
                }
            }
        }
        break;


        // for Any use the class independent converting routine
        case TypeClass_ANY:
        {
            aRetVal = sbxToUnoValueImpl( pVar );
        }
        break;

        case TypeClass_BOOLEAN:
        {
            aRetVal <<= pVar->GetBool();
            break;
        }
        case TypeClass_CHAR:
        {
            aRetVal <<= pVar->GetChar();
            break;
        }
        case TypeClass_STRING:          aRetVal <<= pVar->GetOUString(); break;
        case TypeClass_FLOAT:           aRetVal <<= pVar->GetSingle(); break;
        case TypeClass_DOUBLE:          aRetVal <<= pVar->GetDouble(); break;

        case TypeClass_BYTE:
        {
            sal_Int16 nVal = pVar->GetInteger();
            bool bOverflow = false;
            if( nVal < -128 )
            {
                bOverflow = true;
                nVal = -128;
            }
            else if( nVal > 255 ) // 128..255 map to -128..-1
            {
                bOverflow = true;
                nVal = 127;
            }
            if( bOverflow )
                   StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );

            sal_Int8 nByteVal = static_cast<sal_Int8>(nVal);
            aRetVal <<= nByteVal;
            break;
        }
        case TypeClass_SHORT:           aRetVal <<= pVar->GetInteger();  break;
        case TypeClass_LONG:            aRetVal <<= pVar->GetLong();     break;
        case TypeClass_HYPER:           aRetVal <<= pVar->GetInt64();    break;
        case TypeClass_UNSIGNED_SHORT:  aRetVal <<= pVar->GetUShort();  break;
        case TypeClass_UNSIGNED_LONG:   aRetVal <<= pVar->GetULong();   break;
        case TypeClass_UNSIGNED_HYPER:  aRetVal <<= pVar->GetUInt64();  break;
        defaultbreak;
    }

    return aRetVal;
}

static void processAutomationParams( SbxArray* pParams, Sequence< Any >& args, sal_uInt32 nParamCount )
{
    AutomationNamedArgsSbxArray* pArgNamesArray = dynamic_cast<AutomationNamedArgsSbxArray*>( pParams );

    args.realloc( nParamCount );
    Any* pAnyArgs = args.getArray();
    bool bBlockConversionToSmallestType = GetSbData()->pInst->IsCompatibility();
    sal_uInt32 i = 0;
    if( pArgNamesArray )
    {
        Sequence< OUString >& rNameSeq = pArgNamesArray->getNames();
        OUString* pNames = rNameSeq.getArray();
        Any aValAny;
        for( i = 0 ; i < nParamCount ; i++ )
        {
            sal_uInt32 iSbx = i + 1;

            aValAny = sbxToUnoValueImpl(pParams->Get(iSbx),
            bBlockConversionToSmallestType );

            OUString aParamName = pNames[iSbx];
            if( !aParamName.isEmpty() )
            {
                oleautomation::NamedArgument aNamedArgument;
                aNamedArgument.Name = aParamName;
                aNamedArgument.Value = aValAny;
                pAnyArgs[i] <<= aNamedArgument;
            }
            else
            {
                pAnyArgs[i] = aValAny;
            }
        }
    }
    else
    {
        for( i = 0 ; i < nParamCount ; i++ )
        {
            pAnyArgs[i] = sbxToUnoValueImpl(pParams->Get(i + 1),
            bBlockConversionToSmallestType );
        }
    }

}

namespace {

enum class INVOKETYPE
{
   GetProp = 0,
   Func
};

}

static Any invokeAutomationMethod( const OUString& Name, Sequence< Any > const & args, SbxArray* pParams, sal_uInt32 nParamCount, Reference< XInvocation > const & rxInvocation, INVOKETYPE invokeType )
{
    Sequence< sal_Int16 > OutParamIndex;
    Sequence< Any > OutParam;

    Any aRetAny;
    switch( invokeType )
    {
        case INVOKETYPE::Func:
            aRetAny = rxInvocation->invoke( Name, args, OutParamIndex, OutParam );
            break;
        case INVOKETYPE::GetProp:
            {
                Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY );
                aRetAny = xAutoInv->invokeGetProperty( Name, args, OutParamIndex, OutParam );
                break;
            }
        default:
            assert(false); break;

    }
    const sal_Int16* pIndices = OutParamIndex.getConstArray();
    sal_uInt32 nLen = OutParamIndex.getLength();
    if( nLen )
    {
        const Any* pNewValues = OutParam.getConstArray();
        for( sal_uInt32 j = 0 ; j < nLen ; j++ )
        {
            sal_Int16 iTarget = pIndices[ j ];
            if( o3tl::make_unsigned(iTarget) >= nParamCount )
                break;
            unoToSbxValue(pParams->Get(j + 1), pNewValues[j]);
        }
    }
    return aRetAny;
}

// Debugging help method to readout the implemented interfaces of an object
static OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel )
{
    Type aIfaceType = cppu::UnoType<XInterface>::get();
    static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType );

    OUStringBuffer aRetStr;
    for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ )
        aRetStr.append( " " );
    aRetStr.append( xClass->getName() );
    OUString aClassName = xClass->getName();
    Type aClassType( xClass->getTypeClass(), aClassName );

    // checking if the interface is really supported
    if( !x->queryInterface( aClassType ).hasValue() )
    {
        aRetStr.append( " (ERROR: Not really supported!)\n" );
    }
    // Are there super interfaces?
    else
    {
        aRetStr.append( "\n" );

        // get the super interfaces
        Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses();
        const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray();
        sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength();
        for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ )
        {
            const Reference< XIdlClass >& rxIfaceClass = pClasses[j];
            if( !rxIfaceClass->equals( xIfaceClass ) )
                aRetStr.append( Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ) );
        }
    }
    return aRetStr.makeStringAndClear();
}

static OUString getDbgObjectNameImpl(SbUnoObject& rUnoObj)
{
    OUString aName = rUnoObj.GetClassName();
    if( aName.isEmpty() )
    {
        Any aToInspectObj = rUnoObj.getUnoAny();
        Reference< XInterface > xObj(aToInspectObj, css::uno::UNO_QUERY);
        if( xObj.is() )
        {
            Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY );
            if( xServiceInfo.is() )
                aName = xServiceInfo->getImplementationName();
        }
    }
    return aName;
}

static OUString getDbgObjectName(SbUnoObject& rUnoObj)
{
    OUString aName = getDbgObjectNameImpl(rUnoObj);
    if( aName.isEmpty() )
        aName += "Unknown";

    OUStringBuffer aRet;
    if( aName.getLength() > 20 )
    {
        aRet.append( "\n" );
    }
    aRet.append( "\"" + aName + "\":" );
    return aRet.makeStringAndClear();
}

OUString getBasicObjectTypeName( SbxObject* pObj )
{
    if (pObj)
    {
        if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj))
        {
            return getDbgObjectNameImpl(*pUnoObj);
        }
        else if (SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>(pObj))
        {
            return pUnoStructObj->GetClassName();
        }
    }
    return OUString();
}

namespace {

bool matchesBasicTypeName(
    css::uno::Reference<css::reflection::XIdlClass> const & unoType, OUString const & ;basicTypeName)
{
    if (unoType->getName().endsWithIgnoreAsciiCase(basicTypeName)) {
        return true;
    }
    auto const sups = unoType->getSuperclasses();
    return std::any_of(
        sups.begin(), sups.end(),
        [&basicTypeName](auto const & t) { return matchesBasicTypeName(t, basicTypeName); });
}

}

bool checkUnoObjectType(SbUnoObject& rUnoObj, const OUString& rClass)
{
    Any aToInspectObj = rUnoObj.getUnoAny();

    // Return true for XInvocation based objects as interface type names don't count then
    Reference< XInvocation > xInvocation( aToInspectObj, UNO_QUERY );
    if( xInvocation.is() )
    {
        return true;
    }
    bool bResult = false;
    Reference< XTypeProvider > xTypeProvider( aToInspectObj, UNO_QUERY );
    if( xTypeProvider.is() )
    {
        /*  Although interfaces in the ooo.vba namespace obey the IDL rules and
            have a leading 'X', in Basic we want to be able to do something
            like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
            add a leading 'X' to the class name and a leading dot to the entire
            type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
            which matches the interface names 'ooo.vba.excel.XWorkbooks' or
            'ooo.vba.msforms.XLabel'.
         */

        OUString aClassName;
        if ( SbiRuntime::isVBAEnabled() )
        {
            aClassName = ".";
            sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' );
            if( nClassNameDot >= 0 )
            {
                aClassName += OUString::Concat(rClass.subView( 0, nClassNameDot + 1 )) + "X" + rClass.subView( nClassNameDot + 1 );
            }
            else
            {
                aClassName += "X" + rClass;
            }
        }
        else // assume extended type declaration support for basic ( can't get here
             // otherwise.
            aClassName = rClass;

        Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
        const Type* pTypeArray = aTypeSeq.getConstArray();
        sal_uInt32 nIfaceCount = aTypeSeq.getLength();
        for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
        {
            const Type& rType = pTypeArray[j];

            Reference<XIdlClass> xClass = TypeToIdlClass( rType );
            if( !xClass.is() )
            {
                OSL_FAIL("failed to get XIdlClass for type");
                break;
            }
            OUString aInterfaceName = xClass->getName();
            if ( aInterfaceName == "com.sun.star.bridge.oleautomation.XAutomationObject" )
            {
                // there is a hack in the extensions/source/ole/oleobj.cxx
                // to return the typename of the automation object, let's
                // check if it matches
                Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY );
                if ( xInv.is() )
                {
                    OUString sTypeName;
                    xInv->getValue( u"$GetTypeName"_ustr ) >>= sTypeName;
                    if ( sTypeName.isEmpty() || sTypeName == "IDispatch" )
                    {
                        // can't check type, leave it pass
                        bResult = true;
                    }
                    else
                    {
                        bResult = sTypeName == rClass;
                    }
                }
                break// finished checking automation object
            }

            if ( matchesBasicTypeName(xClass, aClassName) )
            {
                bResult = true;
                break;
            }
        }
    }
    return bResult;
}

// Debugging help method to readout the implemented interfaces of an object
static OUString Impl_GetSupportedInterfaces(SbUnoObject& rUnoObj)
{
    Any aToInspectObj = rUnoObj.getUnoAny();

    // allow only TypeClass interface
    OUStringBuffer aRet;
    auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj);
    if( !x )
    {
        aRet.append( ID_DBG_SUPPORTEDINTERFACES
            + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
    }
    else
    {
        Reference< XTypeProvider > xTypeProvider( *x, UNO_QUERY );

        aRet.append( "Supported interfaces by object "
            + getDbgObjectName(rUnoObj)
            + "\n" );
        if( xTypeProvider.is() )
        {
            // get the interfaces of the implementation
            Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
            const Type* pTypeArray = aTypeSeq.getConstArray();
            sal_uInt32 nIfaceCount = aTypeSeq.getLength();
            for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
            {
                const Type& rType = pTypeArray[j];

                Reference<XIdlClass> xClass = TypeToIdlClass( rType );
                if( xClass.is() )
                {
                    aRet.append( Impl_GetInterfaceInfo( *x, xClass, 1 ) );
                }
                else
                {
                    typelib_TypeDescription * pTD = nullptr;
                    rType.getDescription( &pTD );

                    aRet.append( OUString::Concat("*** ERROR: No IdlClass for type \"")
                        + OUString::unacquired(&pTD->pTypeName)
                        + "\"\n*** Please check type library\n" );
                }
            }
        }
    }
    return aRet.makeStringAndClear();
}


// Debugging help method SbxDataType -> String
static OUString Dbg_SbxDataType2String( SbxDataType eType )
{
    OUStringBuffer aRet;
    switch( +eType )
    {
        case SbxEMPTY:      aRet.append("SbxEMPTY"); break;
        case SbxNULL:       aRet.append("SbxNULL"); break;
        case SbxINTEGER:    aRet.append("SbxINTEGER"); break;
        case SbxLONG:       aRet.append("SbxLONG"); break;
        case SbxSINGLE:     aRet.append("SbxSINGLE"); break;
        case SbxDOUBLE:     aRet.append("SbxDOUBLE"); break;
        case SbxCURRENCY:   aRet.append("SbxCURRENCY"); break;
        case SbxDECIMAL:    aRet.append("SbxDECIMAL"); break;
        case SbxDATE:       aRet.append("SbxDATE"); break;
        case SbxSTRING:     aRet.append("SbxSTRING"); break;
        case SbxOBJECT:     aRet.append("SbxOBJECT"); break;
        case SbxERROR:      aRet.append("SbxERROR"); break;
        case SbxBOOL:       aRet.append("SbxBOOL"); break;
        case SbxVARIANT:    aRet.append("SbxVARIANT"); break;
--> --------------------

--> maximum size reached

--> --------------------

95%


¤ Dauer der Verarbeitung: 0.19 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.