/* -*- 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 .
*/
// 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;
charconst 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.
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;
// 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;
// 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 );
}
} 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;
}
// 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);
}
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; default: break;
} 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;
// 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;
} elseif( 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 elseif( 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;
} elseif( 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 ... elseif( auto obj = dynamic_cast<SbUnoObject*>( xObj.get() ) )
{
aRetType = obj->getUnoAny().getValueType();
} // SbUnoAnyObject? elseif( auto 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() )
{ if( auto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) return obj->getValue(); if( auto pClassModuleObj = dynamic_cast<SbClassModuleObject*>( xObj.get() ) )
{
Any aRetAny;
SbModule& rClassModule = pClassModuleObj->getClassModule(); if (rClassModule.createCOMWrapperForIface(aRetAny, pClassModuleObj)) return aRetAny;
} if( dynamic_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(); elseif( d >= SbxMININT && d <= SbxMAXINT )
aType = ::cppu::UnoType<sal_Int16>::get(); elseif( 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(); elseif( 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 ? default: break;
}
}
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() );
try
{ // transfer to the sequence
xArray->set( aRetVal, i, aElementVal );
} catch( const 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 staticbool implGetTypeByName( const OUString& rName, Type& rRetType )
{ bool bSuccess = false;
// 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;
}
// 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 );
// 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" );
// Return true for XInvocation based objects as interface type names don't count then
Reference< XInvocation > xInvocation( aToInspectObj, UNO_QUERY ); if( xInvocation.is() )
{ returntrue;
} 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;
// 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];
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.