/* -*- 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];
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; case SbxDATAOBJECT: aRet.append("SbxDATAOBJECT"); break; case SbxCHAR: aRet.append("SbxCHAR"); break; case SbxBYTE: aRet.append("SbxBYTE"); break; case SbxUSHORT: aRet.append("SbxUSHORT"); break; case SbxULONG: aRet.append("SbxULONG"); break; case SbxSALINT64: aRet.append("SbxINT64"); break; case SbxSALUINT64: aRet.append("SbxUINT64"); break; case SbxINT: aRet.append("SbxINT"); break; case SbxUINT: aRet.append("SbxUINT"); break; case SbxVOID: aRet.append("SbxVOID"); break; case SbxHRESULT: aRet.append("SbxHRESULT"); break; case SbxPOINTER: aRet.append("SbxPOINTER"); break; case SbxDIMARRAY: aRet.append("SbxDIMARRAY"); break; case SbxCARRAY: aRet.append("SbxCARRAY"); break; case SbxUSERDEF: aRet.append("SbxUSERDEF"); break; case SbxLPSTR: aRet.append("SbxLPSTR"); break; case SbxLPWSTR: aRet.append("SbxLPWSTR"); break; case SbxCoreSTRING: aRet.append("SbxCoreSTRING"); break; case SbxOBJECT | SbxARRAY: aRet.append("SbxARRAY"); break; default: aRet.append("Unknown Sbx-Type!");break;
} return aRet.makeStringAndClear();
}
// Debugging help method to display the properties of a SbUnoObjects static OUString Impl_DumpProperties(SbUnoObject& rUnoObj)
{
OUStringBuffer aRet("Properties of object " + getDbgObjectName(rUnoObj));
// Debugging help method to display the methods of an SbUnoObjects static OUString Impl_DumpMethods(SbUnoObject& rUnoObj)
{
OUStringBuffer aRet("Methods of object " + getDbgObjectName(rUnoObj));
// XIntrospectionAccess, so that the types of the parameter could be outputted
Reference< XIntrospectionAccess > xAccess = rUnoObj.getIntrospectionAccess(); if( !xAccess.is() )
{ const Reference< XInvocation >& xInvok = rUnoObj.getInvocation(); if( xInvok.is() )
xAccess = xInvok->getIntrospection();
} if( !xAccess.is() )
{
aRet.append( "\nUnknown, no introspection available\n" ); return aRet.makeStringAndClear();
}
Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods
( MethodConcept::ALL - MethodConcept::DANGEROUS ); const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray();
SbxVariable* pVar = pHint->GetVar();
SbxArray* pParams = pVar->GetParameters();
SbUnoProperty* pProp = dynamic_cast<SbUnoProperty*>( pVar );
SbUnoMethod* pMeth = dynamic_cast<SbUnoMethod*>( pVar ); if( pProp )
{ bool bInvocation = pProp->isInvocationBased(); if( pHint->GetId() == SfxHintId::BasicDataWanted )
{ // Test-Properties
sal_Int32 nId = pProp->nId; if( nId < 0 )
{ // Id == -1: Display implemented interfaces according the ClassProvider if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
{
OUString aRetStr = Impl_GetSupportedInterfaces(*this);
pVar->PutString( aRetStr );
} // Id == -2: output properties elseif( nId == -2 ) // Property ID_DBG_PROPERTIES
{ // now all properties must be created
implCreateAll();
OUString aRetStr = Impl_DumpProperties(*this);
pVar->PutString( aRetStr );
} // Id == -3: output the methods elseif( nId == -3 ) // Property ID_DBG_METHODS
{ // now all properties must be created
implCreateAll();
OUString aRetStr = Impl_DumpMethods(*this);
pVar->PutString( aRetStr );
} return;
}
if( !bInvocation && mxUnoAccess.is() )
{ try
{ if ( maStructInfo )
{
StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() ); if ( aMember.isEmpty() )
{
StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND );
} else
{ if ( pProp->isUnoStruct() )
{
SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), std::move(aMember) );
SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject);
pVar->PutObject( xWrapper.get() );
} else
{
Any aRetAny = aMember.getValue(); // take over the value from Uno to Sbx
unoToSbxValue( pVar, aRetAny );
} return;
}
} // get the value
Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY );
Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() ); // The use of getPropertyValue (instead of using the index) is // suboptimal, but the refactoring to XInvocation is already pending // Otherwise it is possible to use FastPropertySet
// take over the value from Uno to Sbx
unoToSbxValue( pVar, aRetAny );
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
} elseif( bInvocation && mxInvocation.is() )
{ try
{
sal_uInt32 nParamCount = pParams ? (pParams->Count() - 1) : 0; bool bCanBeConsideredAMethod = mxInvocation->hasMethod( pProp->GetName() );
Any aRetAny; if ( bCanBeConsideredAMethod && nParamCount )
{ // Automation properties have methods, so... we need to invoke this through // XInvocation
Sequence<Any> args;
processAutomationParams( pParams, args, nParamCount );
aRetAny = invokeAutomationMethod( pProp->GetName(), args, pParams, nParamCount, mxInvocation, INVOKETYPE::GetProp );
} else
aRetAny = mxInvocation->getValue( pProp->GetName() ); // take over the value from Uno to Sbx
unoToSbxValue( pVar, aRetAny );
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
}
} elseif( pHint->GetId() == SfxHintId::BasicDataChanged )
{ if( !bInvocation && mxUnoAccess.is() )
{ if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY )
{
StarBASIC::Error( ERRCODE_BASIC_PROP_READONLY ); return;
} if ( maStructInfo )
{
StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() ); if ( aMember.isEmpty() )
{
StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND );
} else
{
Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
aMember.setValue( aAnyValue );
} return;
} // take over the value from Uno to Sbx
Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); try
{ // set the value
Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY );
xPropSet->setPropertyValue( pProp->GetName(), aAnyValue ); // The use of getPropertyValue (instead of using the index) is // suboptimal, but the refactoring to XInvocation is already pending // Otherwise it is possible to use FastPropertySet
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
} elseif( bInvocation && mxInvocation.is() )
{ // take over the value from Uno to Sbx
Any aAnyValue = sbxToUnoValueImpl( pVar ); try
{ // set the value
mxInvocation->setValue( pProp->GetName(), aAnyValue );
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
}
}
} elseif( pMeth )
{ bool bInvocation = pMeth->isInvocationBased(); if( pHint->GetId() == SfxHintId::BasicDataWanted )
{ // number of Parameter -1 because of Param0 == this
sal_uInt32 nParamCount = pParams ? (pParams->Count() - 1) : 0;
Sequence<Any> args; bool bOutParams = false;
// remove parameter here, because this was not done anymore in unoToSbxValue() // for arrays if( pParams )
pVar->SetParameters( nullptr );
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
GetSbData()->bBlockCompilerError = false; // #106433 Unblock compiler errors
}
} else
SbxObject::Notify( rBC, rHint );
}
SbUnoObject::SbUnoObject( const OUString& aName_, const Any& aUnoObj_ )
: SbxObject( aName_ )
, bNeedIntrospection( true )
, bNativeCOMObject( false )
{ // beat out again the default properties of Sbx
Remove( u"Name"_ustr, SbxClassType::DontCare );
Remove( u"Parent"_ustr, SbxClassType::DontCare );
// check the type of the objects
TypeClass eType = aUnoObj_.getValueTypeClass();
Reference< XInterface > x; if( eType == TypeClass_INTERFACE )
{ // get the interface from the Any
aUnoObj_ >>= x; if( !x.is() ) return;
}
// Did the object have an invocation itself?
mxInvocation.set( x, UNO_QUERY );
if( mxInvocation.is() )
{
// get the ExactName
mxExactNameInvocation.set( mxInvocation, UNO_QUERY );
// The remainder refers only to the introspection
Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY ); if( !xTypeProvider.is() )
{
bNeedIntrospection = false; return;
}
// Ignore introspection based members for COM objects to avoid // hiding of equally named COM symbols, e.g. XInvocation::getValue
Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY ); if( xAutomationObject.is() )
bNativeCOMObject = true;
}
maTmpUnoObj = aUnoObj_;
//*** Define the name *** bool bFatalError = true;
// Is it an interface or a struct? bool bSetClassName = false;
OUString aClassName_; if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION )
{ // Struct is Ok
bFatalError = false;
// insert the real name of the class if( aName_.isEmpty() )
{
aClassName_ = aUnoObj_.getValueTypeName();
bSetClassName = true;
}
StructRefInfo aThisStruct( maTmpUnoObj, maTmpUnoObj.getValueType(), 0 );
maStructInfo = std::make_shared<SbUnoStructRefObject>( GetName(), aThisStruct );
} elseif( eType == TypeClass_INTERFACE )
{ // Interface works always through the type in the Any
bFatalError = false;
} if( bSetClassName )
SetClassName( aClassName_ );
// pass the introspection try
{
mxUnoAccess = xIntrospection->inspect( maTmpUnoObj );
} catch( const RuntimeException& e )
{
StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
}
if( !mxUnoAccess.is() )
{ // #51475 mark to indicate an invalid object (no mxMaterialHolder) return;
}
// get MaterialHolder from access
mxMaterialHolder.set( mxUnoAccess, UNO_QUERY );
// get ExactName from access
mxExactName.set( mxUnoAccess, UNO_QUERY );
}
// Start of a list of all SbUnoMethod-Instances static SbUnoMethod* s_pFirst = nullptr;
void clearUnoMethodsForBasic( StarBASIC const * pBasic )
{
SbUnoMethod* pMeth = s_pFirst; while( pMeth )
{
SbxObject* pObject = pMeth->GetParent(); if ( pObject )
{
StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() ); if ( pModBasic == pBasic )
{ // for now the solution is to remove the method from the list and to clear it, // but in case the element should be correctly transferred to another StarBASIC, // we should either set module parent to NULL without clearing it, or even // set the new StarBASIC as the parent of the module // pObject->SetParent( NULL );
// start from the beginning after object clearing, the cycle will end since the method is removed each time
pMeth = s_pFirst;
} else
pMeth = pMeth->pNext;
} else
pMeth = pMeth->pNext;
}
}
bool isVeryLargeUnoProperty(SbxVariable const * pVar)
{ auto pUnoVar = dynamic_cast<const SbUnoProperty*>(pVar); if (!pUnoVar) returnfalse; // The ScCellRangeObj methods will attempt to generate massive strings, // which will use up massive amounts of RAM and also lock of the program // for some time. const OUString & aUnoName = pUnoVar->getUnoName(); if (aUnoName == "DataArray" || aUnoName == "FormulaArray")
{ auto pParent = dynamic_cast<const SbUnoObject*>(pUnoVar->GetParent()); if (!pParent) returnfalse;
css::uno::Any aAny = const_cast<SbUnoObject*>(pParent)->getUnoAny();
css::uno::Reference<css::sheet::XSheetCellCursor> xCursor = aAny.query<css::sheet::XSheetCellCursor>(); if (xCursor) returntrue;
} returnfalse;
}
// New 1999-03-04: Create properties on demand. Therefore search now via // IntrospectionAccess if a property or a method of the required name exist if( !pRes )
{
OUString aUName( rName ); if( mxUnoAccess.is() && !bNativeCOMObject )
{ if( mxExactName.is() )
{
OUString aUExactName = mxExactName->getExactName( aUName ); if( !aUExactName.isEmpty() )
{
aUName = aUExactName;
}
} if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) )
{ const Property aProp = mxUnoAccess->
getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS );
// If the property could be void the type had to be set to Variant
SbxDataType eSbxType; if( aProp.Attributes & PropertyAttribute::MAYBEVOID )
eSbxType = SbxVARIANT; else
eSbxType = unoToSbxType( aProp.Type.getTypeClass() );
// ATTENTION: Because of XNameAccess, the variable generated here // may not be included as a fixed property in the object and therefore // won't be stored anywhere. // If this leads to problems, it has to be created // synthetically or a class SbUnoNameAccessProperty, // which checks the existence on access and which // is disposed if the name is not found anymore.
pRes = new SbxVariable( SbxVARIANT );
unoToSbxValue( pRes, aAny );
}
} catch( const NoSuchElementException& e )
{
StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
} catch( const Exception& )
{ // Establish so that the exception error will not be overwritten if( !pRes )
pRes = new SbxVariable( SbxVARIANT );
}
} catch( const RuntimeException& e )
{ // Establish so that the exception error will not be overwritten if( !pRes )
pRes = new SbxVariable( SbxVARIANT );
StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
}
}
}
// At the very end checking if the Dbg_-Properties are meant
sal_uInt32 i; for( i = 0 ; i < nPropCount ; i++ )
{ const Property& rProp = pProps_[ i ];
// If the property could be void the type had to be set to Variant
SbxDataType eSbxType; if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
eSbxType = SbxVARIANT; else
eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
// Create SbUnoMethod and superimpose it auto xMethRef = tools::make_ref<SbUnoMethod>
( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
QuickInsert( xMethRef.get() );
}
}
// output the value
Any SbUnoObject::getUnoAny()
{
Any aRetAny; if( bNeedIntrospection ) doIntrospection(); if ( maStructInfo )
aRetAny = maTmpUnoObj; elseif( mxMaterialHolder.is() )
aRetAny = mxMaterialHolder->getMaterial(); elseif( mxInvocation.is() )
aRetAny <<= mxInvocation; return aRetAny;
}
double SbUnoObject::GetDate() const
{ // Handle structure info here. Without this, oleautomation data may be unable to convert // to the wanted data type in the base method. if (maStructInfo)
{ if (css::bridge::oleautomation::Date date; maTmpUnoObj >>= date) return date.Value;
}
return SbxObject::GetDate();
}
// help method to create a Uno-Struct per CoreReflection static SbUnoObjectRef Impl_CreateUnoStruct( const OUString& aClassName )
{ // get CoreReflection
Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); if( !xCoreReflection.is() ) return nullptr;
// Is it really a struct?
TypeClass eType = xClass->getTypeClass(); if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) ) return nullptr;
// create an instance
Any aNewAny;
xClass->createObject( aNewAny ); // make a SbUnoObject out of it
SbUnoObjectRef pUnoObj = new SbUnoObject( aClassName, aNewAny ); return pUnoObj;
}
// Factory-Class to create Uno-Structs per DIM AS NEW
SbxBaseRef SbUnoFactory::Create( sal_uInt16, sal_uInt32 )
{ // Via SbxId nothing works in Uno return nullptr;
}
void RTL_Impl_CreateUnoStruct( SbxArray& rPar )
{ // We need 1 parameter minimum if (rPar.Count() < 2)
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); return;
}
// get the name of the class of the struct
OUString aClassName = rPar.Get(1)->GetOUString();
// try to create Struct with the same name
SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName ); if( !xUnoObj.is() )
{ return;
} // return the object
SbxVariableRef refVar = rPar.Get(0);
refVar->PutObject( xUnoObj.get() );
}
void RTL_Impl_CreateUnoService( SbxArray& rPar )
{ // We need 1 Parameter minimum if (rPar.Count() < 2)
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); return;
}
// get the name of the class of the struct
OUString aServiceName = rPar.Get(1)->GetOUString();
// search for the service and instantiate it
Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
Reference< XInterface > xInterface; try
{
xInterface = xFactory->createInstance( aServiceName );
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
SbxVariableRef refVar = rPar.Get(0); if( xInterface.is() )
{ // Create a SbUnoObject out of it and return it
SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, Any(xInterface) ); if( xUnoObj->getUnoAny().hasValue() )
{ // return the object
refVar->PutObject( xUnoObj.get() );
} else
{
refVar->PutObject( nullptr );
}
} else
{
refVar->PutObject( nullptr );
}
}
void RTL_Impl_CreateUnoServiceWithArguments( SbxArray& rPar )
{ // We need 2 parameter minimum if (rPar.Count() < 3)
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); return;
}
// get the name of the class of the struct
OUString aServiceName = rPar.Get(1)->GetOUString();
Any aArgAsAny = sbxToUnoValue(rPar.Get(2),
cppu::UnoType<Sequence<Any>>::get() );
Sequence< Any > aArgs;
aArgAsAny >>= aArgs;
// search for the service and instantiate it
Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
Reference< XInterface > xInterface; try
{
xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs );
} catch( const Exception& )
{
implHandleAnyException( ::cppu::getCaughtException() );
}
SbxVariableRef refVar = rPar.Get(0); if( xInterface.is() )
{ // Create a SbUnoObject out of it and return it
SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, Any(xInterface) ); if( xUnoObj->getUnoAny().hasValue() )
{ // return the object
refVar->PutObject( xUnoObj.get() );
} else
{
refVar->PutObject( nullptr );
}
} else
{
refVar->PutObject( nullptr );
}
}
// get the global service manager
Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
// Create a SbUnoObject out of it and return it
SbUnoObjectRef xUnoObj = new SbUnoObject( u"ProcessServiceManager"_ustr, Any(xFactory) );
refVar->PutObject( xUnoObj.get() );
}
// variable for the return value
SbxVariableRef refVar = rPar.Get(0);
refVar->PutBool( false );
// get the Uno-Object
SbxBaseRef pObj = rPar.Get(1)->GetObject(); auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ); if( obj == nullptr )
{ return;
}
Any aAny = obj->getUnoAny(); auto x = o3tl::tryAccess<Reference<XInterface>>(aAny); if( !x )
{ return;
}
// get CoreReflection
Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); if( !xCoreReflection.is() )
{ return;
} for( sal_uInt32 i = 2 ; i < nParCount ; i++ )
{ // get the name of the interface of the struct
OUString aIfaceName = rPar.Get(i)->GetOUString();
// search for the class
Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName ); if( !xClass.is() )
{ return;
} // check if the interface will be supported
OUString aClassName = xClass->getName();
Type aClassType( xClass->getTypeClass(), aClassName ); if( !(*x)->queryInterface( aClassType ).hasValue() )
{ return;
}
}
// Everything works; then return TRUE
refVar->PutBool( true );
}
void RTL_Impl_IsUnoStruct( SbxArray& rPar )
{ // We need 1 parameter minimum if (rPar.Count() < 2)
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); return;
}
// variable for the return value
SbxVariableRef refVar = rPar.Get(0);
refVar->PutBool( false );
// helper wrapper function to interact with TypeProvider and // XTypeDescriptionEnumerationAccess. // if it fails for whatever reason // returned Reference<> be null e.g. .is() will be false
auto it = aConstHash.find( rName.toAsciiLowerCase() );
if ( it != aConstHash.end() )
{
pConst = new SbxVariable( SbxVARIANT );
pConst->SetName( rName );
unoToSbxValue( pConst, it->second );
}
return pConst;
}
// Function to search for a global identifier in the // UnoScope and to wrap it for Sbx
SbUnoClass* findUnoClass( const OUString& rName )
{ // #105550 Check if module exists
SbUnoClass* pUnoClass = nullptr;
// If nothing were located the submodule isn't known yet if( !pRes )
{ // If it is already a class, ask for the field if( m_xClass.is() )
{ // Is it a field(?)
Reference< XIdlField > xField = m_xClass->getField( rName ); if( xField.is() )
{ try
{
Any aAny = xField->get( {} ); //TODO: does this make sense?
// Insert variable, so that it could be found later
QuickInsert( pRes );
// Take us out as listener at once, // the values are all constant if( pRes->IsBroadcaster() )
EndListening( pRes->GetBroadcaster(), true );
}
} return pRes;
}
// Default: Ignore not needed parameters bool bParameterError = false;
// Is the last parameter a rest parameter? bool bRestParameterMode = false; if( nUnoParamCount > 0 )
{
Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ]; if( xLastParam.is() )
{ if( xLastParam->isRestParameter() )
bRestParameterMode = true;
}
}
// Too many parameters with context as first parameter?
sal_uInt32 nSbxParameterOffset = 1;
sal_uInt32 nParameterOffsetByContext = 0;
Reference < XComponentContext > xFirstParamContext; if( nParamCount > nUnoParamCount )
{ // Check if first parameter is a context and use it // then in createInstanceWithArgumentsAndContext
Any aArg0 = sbxToUnoValue(pParams->Get(nSbxParameterOffset)); if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() )
nParameterOffsetByContext = 1;
}
Reference < XComponentContext > xContextToUse; if( nParamCount > 0 )
{ // Check if first parameter is a context and use it then
Reference < XComponentContext > xFirstParamContext;
Any aArg1 = sbxToUnoValue(pParams->Get(1)); if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() )
xContextToUse = std::move(xFirstParamContext);
}
// Implementation of an EventAttacher-drawn AllListener, which // solely transmits several events to a general AllListener class BasicAllListener_Impl : public WeakImplHelper< XAllListener >
{ void firing_impl(const AllEventObject& Event, Any* pRet);
Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
Sequence< sal_Int16 >&, Sequence< Any >&)
{
Any aRet;
// create Uno-Service // 1. Parameter == Prefix-Name of the macro // 2. Parameter == fully qualified name of the listener void SbRtl_CreateUnoListener(StarBASIC * pBasic, SbxArray & rPar, bool)
{ // We need 2 parameters if (rPar.Count() != 3)
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); return;
}
// get the name of the class of the struct
OUString aPrefixName = rPar.Get(1)->GetOUString();
OUString aListenerClassName = rPar.Get(2)->GetOUString();
// get the CoreReflection
Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); if( !xCoreReflection.is() ) return;
// get the AllListenerAdapterService const Reference< XComponentContext >& xContext( comphelper::getProcessComponentContext() );
// search the class
Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName ); if( !xClass.is() ) return;
// From 1999-11-30: get the InvocationAdapterFactory
Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory =
InvocationAdapterFactory::create( xContext );
// Represents the DefaultContext property of the ProcessServiceManager // in the Basic runtime system. void RTL_Impl_GetDefaultContext( SbxArray& rPar )
{
SbxVariableRef refVar = rPar.Get(0);
Any aContextAny( comphelper::getProcessComponentContext() );
// Creates a Basic wrapper object for a strongly typed Uno value // 1. parameter: Uno type as full qualified type name, e.g. "byte[]" void RTL_Impl_CreateUnoValue( SbxArray& rPar )
{ // 2 parameters needed if (rPar.Count() != 3)
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); return;
}
// get the name of the class of the struct
OUString aTypeName = rPar.Get(1)->GetOUString();
SbxVariable* pVal = rPar.Get(2);
ComponentRefVector& rv = pItem->m_vComImplementsObjects; for (autoconst& elem : rv)
{
Reference< XComponent > xComponent( elem ); if (xComponent.is())
xComponent->dispose();
}
delete pItem;
GaDisposeItemVector.erase( it );
}
// Handle module implements mechanism for OLE types bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject )
{ // For now: Take first interface that allows to instantiate COM wrapper // TODO: Check if support for multiple interfaces is needed
// Due to an incorrect behavior IE returns an object instead of a string // in some scenarios. Calling toString at the object may correct this. // Helper function used in sbxvalue.cxx bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal )
{ bool bSuccess = false;
if( auto pUnoObj = dynamic_cast<SbUnoObject*>( pObj) )
{ // Only for native COM objects if( pUnoObj->isNativeCOMObject() )
{
SbxVariableRef pMeth = pObj->Find( u"toString"_ustr, SbxClassType::Method ); if ( pMeth.is() )
{
SbxValues aRes;
pMeth->Get( aRes );
pVal->Put( aRes );
bSuccess = true;
}
}
} return bSuccess;
}
SbxVariable* pVar = pHint->GetVar();
SbUnoProperty* pProp = dynamic_cast<SbUnoProperty*>( pVar ); if( pProp )
{
StructFieldInfo::iterator it = maFields.find( pProp->GetName() ); // handle get/set of members of struct if( pHint->GetId() == SfxHintId::BasicDataWanted )
{ // Test-Properties
sal_Int32 nId = pProp->nId; if( nId < 0 )
{ // Id == -1: Display implemented interfaces according the ClassProvider if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
{
OUString aRet = OUString::Concat( ID_DBG_SUPPORTEDINTERFACES )
+ " not available.\n(TypeClass is not TypeClass_INTERFACE)\n";
pVar->PutString( aRet );
} // Id == -2: output properties elseif( nId == -2 ) // Property ID_DBG_PROPERTIES
{ // by now all properties must be established
implCreateAll();
OUString aRetStr = Impl_DumpProperties();
pVar->PutString( aRetStr );
} // Id == -3: output the methods elseif( nId == -3 ) // Property ID_DBG_METHODS
{ // by now all properties must be established
implCreateAll();
OUString aRet = "Methods of object "
+ getDbgObjectName()
+ "\nNo methods found\n";
pVar->PutString( aRet );
} return;
}
if ( it != maFields.end() )
{
Any aRetAny = it->second->getValue();
unoToSbxValue( pVar, aRetAny );
} else
StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND );
} elseif( pHint->GetId() == SfxHintId::BasicDataChanged )
{ if ( it != maFields.end() )
{ // take over the value from Uno to Sbx
Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
it->second->setValue( aAnyValue );
} else
StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND );
}
} else
SbxObject::Notify( rBC, rHint );
}
StructRefInfo SbUnoStructRefObject::getStructMember( const OUString& rMemberName )
{ if (!mbMemberCacheInit)
{
initMemberCache();
}
StructFieldInfo::iterator it = maFields.find( rMemberName );
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 und die Messung sind noch experimentell.