diff options
Diffstat (limited to 'basic/source/classes')
-rw-r--r-- | basic/source/classes/disas.cxx | 687 | ||||
-rw-r--r-- | basic/source/classes/errobject.cxx | 225 | ||||
-rw-r--r-- | basic/source/classes/eventatt.cxx | 599 | ||||
-rw-r--r-- | basic/source/classes/image.cxx | 544 | ||||
-rw-r--r-- | basic/source/classes/makefile.mk | 76 | ||||
-rw-r--r-- | basic/source/classes/propacc.cxx | 430 | ||||
-rw-r--r-- | basic/source/classes/sb.cxx | 2135 | ||||
-rw-r--r-- | basic/source/classes/sb.src | 681 | ||||
-rw-r--r-- | basic/source/classes/sbintern.cxx | 82 | ||||
-rwxr-xr-x | basic/source/classes/sbunoobj.cxx | 4855 | ||||
-rwxr-xr-x | basic/source/classes/sbxmod.cxx | 2626 |
11 files changed, 12940 insertions, 0 deletions
diff --git a/basic/source/classes/disas.cxx b/basic/source/classes/disas.cxx new file mode 100644 index 000000000000..37d777cb8da8 --- /dev/null +++ b/basic/source/classes/disas.cxx @@ -0,0 +1,687 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdio.h> +#include <string.h> +#include <tools/stream.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include "iosys.hxx" +#include "disas.hxx" +#include "sbtrace.hxx" + + +static const char* pOp1[] = { + "NOP", + + // Operators + // the following operators have the same order as in + // enum SbxVarOp + "EXP", "MUL", "DIV", "MOD", "PLUS", "MINUS", "NEG", + "EQ", "NE", "LT", "GT", "LE", "GE", + "IDIV", "AND", "OR", "XOR", "EQV", "IMP", "NOT", + "CAT", + // End enum SbxVarOp + "LIKE", "IS", + // Load/Store + "ARGC", // Create new Argv + "ARGV", // TOS ==> current Argv + "INPUT", // Input ==> TOS + "LINPUT", // Line Input ==> TOS + "GET", // get TOS + "SET", // Save Object TOS ==> TOS-1 + "PUT", // TOS ==> TOS-1 + "CONST", // TOS ==> TOS-1, then ReadOnly + "DIM", // DIM + "REDIM", // REDIM + "REDIMP", // REDIM PRESERVE + "ERASE", // delete TOS + // Branch + "STOP", // End of program + "INITFOR", // FOR-Variable init + "NEXT", // FOR-Variable increment + "CASE", // Begin CASE + "ENDCASE", // End CASE + "STDERR", // Default error handling + "NOERROR", // No error handling + "LEAVE", // leave UP + // I/O + "CHANNEL", // TOS = Channelnumber + "PRINT", // print TOS + "PRINTF", // print TOS in field + "WRITE", // write TOS + "RENAME", // Rename Tos+1 to Tos + "PROMPT", // TOS = Prompt for Input + "RESTART", // Define restart point + "STDIO", // Switch to I/O channel 0 + // Misc + "EMPTY", // Empty statement to stack + "ERROR", // TOS = error code + "LSET", // Save object TOS ==> TOS-1 + "RSET", // Save object TOS ==> TOS-1 (TODO: Same as above?) + "REDIMP_ERASE", + "INITFOREACH", + "VBASET", + "ERASE_CLEAR", + "ARRAYACCESS", + "BYVAL" +}; + +static const char* pOp2[] = { + "NUMBER", // Load a numeric constant (+ID) + "STRING", // Load a string constant (+ID) + "CONSTANT", // Immediate Load (+value) + "ARGN", // Save named args in argv (+StringID) + "PAD", // Pad String to defined length (+length) + // Branches + "JUMP", // Jump to target (+Target) + "JUMP.T", // evaluate TOS, conditional jump (+Target) + "JUMP.F", // evaluate TOS, conditional jump (+Target) + "ONJUMP", // evaluate TOS, jump into JUMP-table (+MaxVal) + "GOSUB", // UP-Call (+Target) + "RETURN", // UP-Return (+0 or Target) + "TESTFOR", // Test FOR-Variable, increment (+Endlabel) + "CASETO", // Tos+1 <= Case <= Tos, 2xremove (+Target) + "ERRHDL", // Error-Handler (+Offset) + "RESUME", // Resume after errors (+0 or 1 or Label) + // I/O + "CLOSE", // (+channel/0) + "PRCHAR", // (+char) + // Objects + "SETCLASS", // Test Set + Classname (+StringId) + "TESTCLASS", // Check TOS class (+StringId) + "LIB", // Set Libname for Declare-Procs (+StringId) + // New since Beta 3 (TODO: Which Beta3?) + "BASED", // TOS is incremted about BASE, push BASE before + "ARGTYP", // Convert last parameter in argv (+Type) + "VBASETCLASS", +}; + +static const char* pOp3[] = { + // All opcodes with two operands + "RTL", // Load from RTL (+StringID+Typ) + "FIND", // Load (+StringID+Typ) + "ELEM", // Load element (+StringID+Typ) + "PARAM", // Parameter (+Offset+Typ) + + // Branching + "CALL", // Call DECLARE method (+StringID+Typ) + "CALL.C", // Call Cdecl-DECLARE method (+StringID+Typ) + "CASEIS", // Case-Test (+Test-Opcode+False-Target) + "STMNT", // Start of a statement (+Line+Col) + + // I/O + "OPEN", // (+SvStreamFlags+Flags) + + // Objects and variables + "LOCAL", // Local variables (+StringID+Typ) + "PUBLIC", // Modul global var (+StringID+Typ) + "GLOBAL", // Global var (+StringID+Typ) + "CREATE", // Create object (+StringId+StringId) + "STATIC", // Create static object (+StringId+StringId) + "TCREATE", // Create User defined Object (+StringId+StringId) + "DCREATE", // Create User defined Object-Array kreieren (+StringId+StringId) + "GLOBAL_P", // Define persistent global var (existing after basic restart) + // P=PERSIST (+StringID+Typ) + "FIND_G", // Searches for global var with special handling due to _GLOBAL_P + "DCREATE_REDIMP", // Change dimensions of a user defined Object-Array (+StringId+StringId) + "FIND_CM", // Search inside a class module (CM) to enable global search in time + "PUBLIC_P", // Module global Variable (persisted between calls)(+StringID+Typ) + "FIND_STATIC", // local static var lookup (+StringID+Typ) +}; + +static const char** pOps[3] = { pOp1, pOp2, pOp3 }; + +typedef void( SbiDisas::*Func )( String& ); // Processing routines + +static const Func pOperand2[] = { + &SbiDisas::StrOp, // Load a numeric constant (+ID) + &SbiDisas::StrOp, // Load a string constant (+ID) + &SbiDisas::ImmOp, // Immediate Load (+Wert) + &SbiDisas::StrOp, // Save a named argument (+ID) + &SbiDisas::ImmOp, // Strip String to fixed size (+length) + + // Branches + &SbiDisas::LblOp, // Jump (+Target) + &SbiDisas::LblOp, // eval TOS, conditional jump (+Target) + &SbiDisas::LblOp, // eval TOS, conditional jump (+Target) + &SbiDisas::OnOp, // eval TOS, jump in JUMP table (+MaxVal) + &SbiDisas::LblOp, // UP call (+Target) + &SbiDisas::ReturnOp, // UP Return (+0 or Target) + &SbiDisas::LblOp, // test FOR-Variable, increment (+Endlabel) + &SbiDisas::LblOp, // Tos+1 <= Case <= Tos), 2xremove (+Target) + &SbiDisas::LblOp, // Error handler (+Offset) + &SbiDisas::ResumeOp, // Resume after errors (+0 or 1 or Label) + + // I/O + &SbiDisas::CloseOp, // (+channel/0) + &SbiDisas::CharOp, // (+char) + + // Objects + &SbiDisas::StrOp, // Test classname (+StringId) + &SbiDisas::StrOp, // TESTCLASS, Check TOS class (+StringId) + &SbiDisas::StrOp, // Set libname for declare procs (+StringId) + &SbiDisas::ImmOp, // TOS is incremented about BASE erhoeht, BASE pushed before + &SbiDisas::TypeOp, // Convert last parameter to/in(?) argv (+Typ) + &SbiDisas::StrOp, // VBASETCLASS (+StringId) +}; + +static const Func pOperand3[] = { + // All opcodes with two operands + &SbiDisas::VarOp, // Load from RTL (+StringID+Typ) + &SbiDisas::VarOp, // Load (+StringID+Typ) + &SbiDisas::VarOp, // Load Element (+StringID+Typ) + &SbiDisas::OffOp, // Parameter (+Offset+Typ) + + // Branch + &SbiDisas::VarOp, // Call DECLARE-Method (+StringID+Typ) + &SbiDisas::VarOp, // Call CDecl-DECLARE-Methode (+StringID+Typ) + &SbiDisas::CaseOp, // Case-Test (+Test-Opcode+False-Target) + &SbiDisas::StmntOp, // Statement (+Row+Column) + + // I/O + &SbiDisas::StrmOp, // (+SvStreamFlags+Flags) + + // Objects + &SbiDisas::VarDefOp, // Define local var (+StringID+Typ) + &SbiDisas::VarDefOp, // Define Module global var (+StringID+Typ) + &SbiDisas::VarDefOp, // Define global var (+StringID+Typ) + &SbiDisas::Str2Op, // Create object (+StringId+StringId) + &SbiDisas::VarDefOp, // Define static object (+StringID+Typ) + &SbiDisas::Str2Op, // Create User defined Object (+StringId+StringId) + &SbiDisas::Str2Op, // Create User defined Object-Array (+StringId+StringId) + &SbiDisas::VarDefOp, // Define persistent global var P=PERSIST (+StringID+Typ) + &SbiDisas::VarOp, // Searches for global var with special handling due to _GLOBAL_P + &SbiDisas::Str2Op, // Redimensionate User defined Object-Array (+StringId+StringId) + &SbiDisas::VarOp, // FIND_CM + &SbiDisas::VarDefOp, // PUBLIC_P + &SbiDisas::VarOp, // FIND_STATIC +}; + +// TODO: Why as method? Isn't a simple define sufficient? +static const char* _crlf() +{ +#if defined (UNX) || defined( PM2 ) + return "\n"; +#else + return "\r\n"; +#endif +} + +// This method exists because we want to load the file as own segment +sal_Bool SbModule::Disassemble( String& rText ) +{ + rText.Erase(); + if( pImage ) + { + SbiDisas aDisas( this, pImage ); + aDisas.Disas( rText ); + } + return sal_Bool( rText.Len() != 0 ); +} + +SbiDisas::SbiDisas( SbModule* p, const SbiImage* q ) : rImg( *q ), pMod( p ) +{ + memset( cLabels, 0, 8192 ); + nLine = 0; + nOff = 0; + nPC = 0; + nOp1 = nOp2 = nParts = 0; + eOp = _NOP; + // Set Label-Bits + nOff = 0; + while( Fetch() ) + { + switch( eOp ) + { + case _RESUME: if( nOp1 <= 1 ) break; + case _RETURN: if( !nOp1 ) break; + case _JUMP: + case _JUMPT: + case _JUMPF: + case _GOSUB: + case _TESTFOR: + case _CASEIS: + case _CASETO: + case _ERRHDL: + cLabels[ (nOp1 & 0xffff) >> 3 ] |= ( 1 << ( nOp1 & 7 ) ); + break; + default: break; + } + } + nOff = 0; + // Add the publics + for( sal_uInt16 i = 0; i < pMod->GetMethods()->Count(); i++ ) + { + SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i )); + if( pMeth ) + { + sal_uInt16 nPos = (sal_uInt16) (pMeth->GetId()); + cLabels[ nPos >> 3 ] |= ( 1 << ( nPos & 7 ) ); + } + } +} + +// Read current opcode +sal_Bool SbiDisas::Fetch() +{ + nPC = nOff; + if( nOff >= rImg.GetCodeSize() ) + return sal_False; + const unsigned char* p = (const unsigned char*)( rImg.GetCode() + nOff ); + eOp = (SbiOpcode) ( *p++ & 0xFF ); + if( eOp <= SbOP0_END ) + { + nOp1 = nOp2 = 0; + nParts = 1; + nOff++; + return sal_True; + } + else if( eOp <= SbOP1_END ) + { + nOff += 5; + if( nOff > rImg.GetCodeSize() ) + return sal_False; + nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; + nParts = 2; + return sal_True; + } + else if( eOp <= SbOP2_END ) + { + nOff += 9; + if( nOff > rImg.GetCodeSize() ) + return sal_False; + nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; + nOp2 = *p++; nOp2 |= *p++ << 8; nOp2 |= *p++ << 16; nOp2 |= *p++ << 24; + nParts = 3; + return sal_True; + } + else + return sal_False; +} + +void SbiDisas::Disas( SvStream& r ) +{ + String aText; + nOff = 0; + while( DisasLine( aText ) ) + { + ByteString aByteText( aText, gsl_getSystemTextEncoding() ); + r.WriteLine( aByteText ); + } +} + +void SbiDisas::Disas( String& r ) +{ + r.Erase(); + String aText; + nOff = 0; + while( DisasLine( aText ) ) + { + r += aText; + r.AppendAscii( _crlf() ); + } + aText.ConvertLineEnd(); +} + +sal_Bool SbiDisas::DisasLine( String& rText ) +{ + char cBuf[ 100 ]; + const char* pMask[] = { + "%08" SAL_PRIXUINT32 " ", + "%08" SAL_PRIXUINT32 " %02X ", + "%08" SAL_PRIXUINT32 " %02X %08X ", + "%08" SAL_PRIXUINT32 " %02X %08X %08X " }; + rText.Erase(); + if( !Fetch() ) + return sal_False; + +#ifdef DBG_TRACE_BASIC + String aTraceStr_STMNT; +#endif + + // New line? + if( eOp == _STMNT && nOp1 != nLine ) + { + // Find line + String aSource = rImg.aOUSource; + nLine = nOp1; + sal_uInt16 n = 0; + sal_uInt16 l = (sal_uInt16)nLine; + while( --l ) { + n = aSource.SearchAscii( "\n", n ); + if( n == STRING_NOTFOUND ) break; + else n++; + } + // Show position + if( n != STRING_NOTFOUND ) + { + sal_uInt16 n2 = aSource.SearchAscii( "\n", n ); + if( n2 == STRING_NOTFOUND ) n2 = aSource.Len() - n; + String s( aSource.Copy( n, n2 - n + 1 ) ); + sal_Bool bDone; + do { + bDone = sal_True; + n = s.Search( '\r' ); + if( n != STRING_NOTFOUND ) bDone = sal_False, s.Erase( n, 1 ); + n = s.Search( '\n' ); + if( n != STRING_NOTFOUND ) bDone = sal_False, s.Erase( n, 1 ); + } while( !bDone ); +// snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC ); +// rText += cBuf; + rText.AppendAscii( "; " ); + rText += s; + rText.AppendAscii( _crlf() ); + +#ifdef DBG_TRACE_BASIC + aTraceStr_STMNT = s; +#endif + } + } + + // Label? + const char* p = ""; + if( cLabels[ nPC >> 3 ] & ( 1 << ( nPC & 7 ) ) ) + { + // Public? + ByteString aByteMethName; + for( sal_uInt16 i = 0; i < pMod->GetMethods()->Count(); i++ ) + { + SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i )); + if( pMeth ) + { + aByteMethName = ByteString( pMeth->GetName(), gsl_getSystemTextEncoding() ); + if( pMeth->GetId() == nPC ) + { + p = aByteMethName.GetBuffer(); + break; + } + if( pMeth->GetId() >= nPC ) + break; + } + } + snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC ); + rText.AppendAscii( cBuf ); + if( p && *p ) + { + rText.AppendAscii( p ); + } + else + { + // fix warning (now error) for "Lbl%04lX" format + snprintf( cBuf, sizeof(cBuf), "Lbl%08" SAL_PRIXUINT32, nPC ); + rText.AppendAscii( cBuf ); + } + rText += ':'; + rText.AppendAscii( _crlf() ); + } + snprintf( cBuf, sizeof(cBuf), pMask[ nParts ], nPC, (sal_uInt16) eOp, nOp1, nOp2 ); + + String aPCodeStr; + aPCodeStr.AppendAscii( cBuf ); + int n = eOp; + if( eOp >= SbOP2_START ) + n -= SbOP2_START; + else if( eOp >= SbOP1_START ) + n -= SbOP1_START; + aPCodeStr += '\t'; + aPCodeStr.AppendAscii( pOps[ nParts-1 ][ n ] ); + aPCodeStr += '\t'; + switch( nParts ) + { + case 2: (this->*( pOperand2[ n ] ) )( aPCodeStr ); break; + case 3: (this->*( pOperand3[ n ] ) )( aPCodeStr ); break; + } + + rText += aPCodeStr; + +#ifdef DBG_TRACE_BASIC + dbg_RegisterTraceTextForPC( pMod, nPC, aTraceStr_STMNT, aPCodeStr ); +#endif + + return sal_True; +} + +// Read from StringPool +void SbiDisas::StrOp( String& rText ) +{ + String aStr = rImg.GetString( (sal_uInt16)nOp1 ); + ByteString aByteString( aStr, RTL_TEXTENCODING_ASCII_US ); + const char* p = aByteString.GetBuffer(); + if( p ) + { + rText += '"'; + rText.AppendAscii( p ); + rText += '"'; + } + else + { + rText.AppendAscii( "?String? " ); + rText += (sal_uInt16)nOp1; + } +} + +void SbiDisas::Str2Op( String& rText ) +{ + StrOp( rText ); + rText += ','; + String s; + nOp1 = nOp2; + StrOp( s ); + rText += s; +} + +// Immediate Operand +void SbiDisas::ImmOp( String& rText ) +{ + rText += String::CreateFromInt32(nOp1); +} + +// OnGoto Operand +void SbiDisas::OnOp( String& rText ) +{ + rText += String::CreateFromInt32(nOp1 & 0x7FFF); + if( nOp1 & 0x800 ) + rText.AppendAscii( "\t; Gosub" ); +} + +// Label +void SbiDisas::LblOp( String& rText ) +{ + char cBuf[ 10 ]; + snprintf( cBuf, sizeof(cBuf), "Lbl%04" SAL_PRIXUINT32, nOp1 ); + rText.AppendAscii( cBuf ); +} + +// 0 or Label +void SbiDisas::ReturnOp( String& rText ) +{ + if( nOp1 ) + LblOp( rText ); +} + +// 0, 1 or Label +void SbiDisas::ResumeOp( String& rText ) +{ + switch( nOp1 ) + { + case 1: rText.AppendAscii( "NEXT" ); break; + case 2: LblOp( rText ); + } +} + +// print Prompt +// sal_False/TRUE +void SbiDisas::PromptOp( String& rText ) +{ + if( nOp1 ) + rText.AppendAscii( "\"? \"" ); +} + +// 0 or 1 +void SbiDisas::CloseOp( String& rText ) +{ + rText.AppendAscii( nOp1 ? "Channel" : "All" ); +} + +// Print character +void SbiDisas::CharOp( String& rText ) +{ + const char* p = NULL; + switch( nOp1 ) + { + case 7: p = "'\\a'"; break; + case 9: p = "'\\t'"; break; + case 10: p = "'\\n'"; break; + case 12: p = "'\\f'"; break; + case 13: p = "'\\r'"; break; + } + if( p ) rText.AppendAscii( p ); + else if( nOp1 >= ' ' ) + rText += '\'', + rText += (char) nOp1, + rText += '\''; + else + rText.AppendAscii( "char " ), + rText += (sal_uInt16)nOp1; +} + +// Print var: String-ID and type +void SbiDisas::VarOp( String& rText ) +{ + rText += rImg.GetString( (sal_uInt16)(nOp1 & 0x7FFF) ); + rText.AppendAscii( "\t; " ); + // The type + sal_uInt32 n = nOp1; + nOp1 = nOp2; + TypeOp( rText ); + if( n & 0x8000 ) + rText.AppendAscii( ", Args" ); +} + +// Define variable: String-ID and type +void SbiDisas::VarDefOp( String& rText ) +{ + rText += rImg.GetString( (sal_uInt16)(nOp1 & 0x7FFF) ); + rText.AppendAscii( "\t; " ); + // The Typ + nOp1 = nOp2; + TypeOp( rText ); +} + +// Print variable: Offset and Typ +void SbiDisas::OffOp( String& rText ) +{ + rText += String::CreateFromInt32( nOp1 & 0x7FFF ); + rText.AppendAscii( "\t; " ); + // The type + sal_uInt32 n = nOp1; + nOp1 = nOp2; + TypeOp( rText ); + if( n & 0x8000 ) + rText.AppendAscii( ", Args" ); +} + +// Data type +#ifdef HP9000 // TODO: remove this! +static char* SbiDisas_TypeOp_pTypes[13] = { + "Empty","Null","Integer","Long","Single","Double", + "Currency","Date","String","Object","Error","Boolean", + "Variant" }; +#define pTypes SbiDisas_TypeOp_pTypes +#endif +void SbiDisas::TypeOp( String& rText ) +{ + // AB 19.1.96: Typ kann Flag für BYVAL enthalten (StepARGTYP) + if( nOp1 & 0x8000 ) + { + nOp1 &= 0x7FFF; // Flag wegfiltern + rText.AppendAscii( "BYVAL " ); + } + if( nOp1 < 13 ) + { +#ifndef HP9000 + static char pTypes[][13] = { + "Empty","Null","Integer","Long","Single","Double", + "Currency","Date","String","Object","Error","Boolean", + "Variant" }; +#endif + rText.AppendAscii( pTypes[ nOp1 ] ); + } + else + { + rText.AppendAscii( "type " ); + rText += (sal_uInt16)nOp1; + } +} +#ifdef HP9000 +#undef pTypes +#endif + +// sal_True-Label, condition Opcode +void SbiDisas::CaseOp( String& rText ) +{ + LblOp( rText ); + rText += ','; + rText.AppendAscii( pOp1[ nOp2 - SbxEQ + _EQ ] ); +} + +// Row, column +void SbiDisas::StmntOp( String& rText ) +{ + rText += String::CreateFromInt32( nOp1 ); + rText += ','; + sal_uInt32 nCol = nOp2 & 0xFF; + sal_uInt32 nFor = nOp2 / 0x100; + rText += String::CreateFromInt32( nCol ); + rText.AppendAscii( " (For-Level: " ); + rText += String::CreateFromInt32( nFor ); + rText += ')'; +} + +// open mode, flags +void SbiDisas::StrmOp( String& rText ) +{ + char cBuf[ 10 ]; + snprintf( cBuf, sizeof(cBuf), "%04" SAL_PRIXUINT32, nOp1 ); + rText.AppendAscii( cBuf ); + if( nOp2 & SBSTRM_INPUT ) + rText.AppendAscii( ", Input" ); + if( nOp2 & SBSTRM_OUTPUT ) + rText.AppendAscii( ", Output" ); + if( nOp2 & SBSTRM_APPEND ) + rText.AppendAscii( ", Append" ); + if( nOp2 & SBSTRM_RANDOM ) + rText.AppendAscii( ", Random" ); + if( nOp2 & SBSTRM_BINARY ) + rText.AppendAscii( ", Binary" ); +} + + diff --git a/basic/source/classes/errobject.cxx b/basic/source/classes/errobject.cxx new file mode 100644 index 000000000000..0ec0454e2bb5 --- /dev/null +++ b/basic/source/classes/errobject.cxx @@ -0,0 +1,225 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include "errobject.hxx" + +#include <cppuhelper/implbase2.hxx> +#include <com/sun/star/script/XDefaultProperty.hpp> +#include "sbintern.hxx" +#include "runtime.hxx" + +using namespace ::com::sun::star; +using namespace ::ooo; + +typedef ::cppu::WeakImplHelper2< vba::XErrObject, script::XDefaultProperty > ErrObjectImpl_BASE; + +class ErrObject : public ErrObjectImpl_BASE +{ + rtl::OUString m_sHelpFile; + rtl::OUString m_sSource; + rtl::OUString m_sDescription; + sal_Int32 m_nNumber; + sal_Int32 m_nHelpContext; + +public: + ErrObject(); + ~ErrObject(); + // Attributes + virtual ::sal_Int32 SAL_CALL getNumber() throw (uno::RuntimeException); + virtual void SAL_CALL setNumber( ::sal_Int32 _number ) throw (uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getHelpContext() throw (uno::RuntimeException); + virtual void SAL_CALL setHelpContext( ::sal_Int32 _helpcontext ) throw (uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getHelpFile() throw (uno::RuntimeException); + virtual void SAL_CALL setHelpFile( const ::rtl::OUString& _helpfile ) throw (uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDescription() throw (uno::RuntimeException); + virtual void SAL_CALL setDescription( const ::rtl::OUString& _description ) throw (uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSource() throw (uno::RuntimeException); + virtual void SAL_CALL setSource( const ::rtl::OUString& _source ) throw (uno::RuntimeException); + + // Methods + virtual void SAL_CALL Clear( ) throw (uno::RuntimeException); + virtual void SAL_CALL Raise( const uno::Any& Number, const uno::Any& Source, const uno::Any& Description, const uno::Any& HelpFile, const uno::Any& HelpContext ) throw (uno::RuntimeException); + // XDefaultProperty + virtual ::rtl::OUString SAL_CALL getDefaultPropertyName( ) throw (uno::RuntimeException); + + // Helper method + void setData( const uno::Any& Number, const uno::Any& Source, const uno::Any& Description, + const uno::Any& HelpFile, const uno::Any& HelpContext ) throw (uno::RuntimeException); +}; + + +ErrObject::~ErrObject() +{ +} + +ErrObject::ErrObject() : m_nNumber(0), m_nHelpContext(0) +{ +} + +sal_Int32 SAL_CALL +ErrObject::getNumber() throw (uno::RuntimeException) +{ + return m_nNumber; +} + +void SAL_CALL +ErrObject::setNumber( ::sal_Int32 _number ) throw (uno::RuntimeException) +{ + pINST->setErrorVB( _number, String() ); + ::rtl::OUString _description = pINST->GetErrorMsg(); + setData( uno::makeAny( _number ), uno::Any(), uno::makeAny( _description ), uno::Any(), uno::Any() ); +} + +::sal_Int32 SAL_CALL +ErrObject::getHelpContext() throw (uno::RuntimeException) +{ + return m_nHelpContext; +} +void SAL_CALL +ErrObject::setHelpContext( ::sal_Int32 _helpcontext ) throw (uno::RuntimeException) +{ + m_nHelpContext = _helpcontext; +} + +::rtl::OUString SAL_CALL +ErrObject::getHelpFile() throw (uno::RuntimeException) +{ + return m_sHelpFile; +} + +void SAL_CALL +ErrObject::setHelpFile( const ::rtl::OUString& _helpfile ) throw (uno::RuntimeException) +{ + m_sHelpFile = _helpfile; +} + +::rtl::OUString SAL_CALL +ErrObject::getDescription() throw (uno::RuntimeException) +{ + return m_sDescription; +} + +void SAL_CALL +ErrObject::setDescription( const ::rtl::OUString& _description ) throw (uno::RuntimeException) +{ + m_sDescription = _description; +} + +::rtl::OUString SAL_CALL +ErrObject::getSource() throw (uno::RuntimeException) +{ + return m_sSource; +} + +void SAL_CALL +ErrObject::setSource( const ::rtl::OUString& _source ) throw (uno::RuntimeException) +{ + m_sSource = _source; +} + +// Methods +void SAL_CALL +ErrObject::Clear( ) throw (uno::RuntimeException) +{ + m_sHelpFile = rtl::OUString(); + m_sSource = m_sHelpFile; + m_sDescription = m_sSource; + m_nNumber = 0; + m_nHelpContext = 0; +} + +void SAL_CALL +ErrObject::Raise( const uno::Any& Number, const uno::Any& Source, const uno::Any& Description, const uno::Any& HelpFile, const uno::Any& HelpContext ) throw (uno::RuntimeException) +{ + setData( Number, Source, Description, HelpFile, HelpContext ); + if ( m_nNumber ) + pINST->ErrorVB( m_nNumber, m_sDescription ); +} + +// XDefaultProperty +::rtl::OUString SAL_CALL +ErrObject::getDefaultPropertyName( ) throw (uno::RuntimeException) +{ + static rtl::OUString sDfltPropName( RTL_CONSTASCII_USTRINGPARAM("Number") ); + return sDfltPropName; +} + +void ErrObject::setData( const uno::Any& Number, const uno::Any& Source, const uno::Any& Description, const uno::Any& HelpFile, const uno::Any& HelpContext ) + throw (uno::RuntimeException) +{ + if ( !Number.hasValue() ) + throw uno::RuntimeException( rtl::OUString::createFromAscii("Missing Required Paramater"), uno::Reference< uno::XInterface >() ); + Number >>= m_nNumber; + Description >>= m_sDescription; + Source >>= m_sSource; + HelpFile >>= m_sHelpFile; + HelpContext >>= m_nHelpContext; +} + +// SbxErrObject +SbxErrObject::SbxErrObject( const String& rName, const Any& rUnoObj ) + : SbUnoObject( rName, rUnoObj ) + , m_pErrObject( NULL ) +{ + OSL_TRACE("SbxErrObject::SbxErrObject ctor"); + rUnoObj >>= m_xErr; + if ( m_xErr.is() ) + { + SetDfltProperty( uno::Reference< script::XDefaultProperty >( m_xErr, uno::UNO_QUERY_THROW )->getDefaultPropertyName() ) ; + m_pErrObject = static_cast< ErrObject* >( m_xErr.get() ); + } +} + +SbxErrObject::~SbxErrObject() +{ + OSL_TRACE("SbxErrObject::~SbxErrObject dtor"); +} + +uno::Reference< vba::XErrObject > +SbxErrObject::getUnoErrObject() +{ + SbxVariable* pVar = getErrObject(); + SbxErrObject* pGlobErr = static_cast< SbxErrObject* >( pVar ); + return pGlobErr->m_xErr; +} + +SbxVariableRef +SbxErrObject::getErrObject() +{ + static SbxVariableRef pGlobErr = new SbxErrObject( String( RTL_CONSTASCII_USTRINGPARAM("Err")), uno::makeAny( uno::Reference< vba::XErrObject >( new ErrObject() ) ) ); + return pGlobErr; +} + +void SbxErrObject::setNumberAndDescription( ::sal_Int32 _number, const ::rtl::OUString& _description ) + throw (uno::RuntimeException) +{ + if( m_pErrObject != NULL ) + m_pErrObject->setData( uno::makeAny( _number ), uno::Any(), uno::makeAny( _description ), uno::Any(), uno::Any() ); +} + diff --git a/basic/source/classes/eventatt.cxx b/basic/source/classes/eventatt.cxx new file mode 100644 index 000000000000..8d9f30e4982f --- /dev/null +++ b/basic/source/classes/eventatt.cxx @@ -0,0 +1,599 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +//#include <stl_queue.h> +#include <osl/mutex.hxx> +#include <comphelper/processfactory.hxx> + + +#include <com/sun/star/script/XEventAttacher.hpp> +#include <com/sun/star/script/XAllListener.hpp> +#include <com/sun/star/script/XScriptEventsSupplier.hpp> +#include <com/sun/star/script/XScriptEventsAttacher.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/resource/XStringResourceSupplier.hpp> +#include <com/sun/star/resource/XStringResourceManager.hpp> +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/awt/XDialog.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/script/provider/XScriptProviderFactory.hpp> + +#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp> +#include <com/sun/star/script/provider/XScriptProvider.hpp> +#include <com/sun/star/awt/XDialogProvider.hpp> + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <basic/basicmanagerrepository.hxx> +#include <basic/basmgr.hxx> +//================================================================================================== + +#include <xmlscript/xmldlg_imexp.hxx> +#include <sbunoobj.hxx> +#include <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbuno.hxx> +#include <runtime.hxx> +#include <sbintern.hxx> + + +#include <cppuhelper/implbase1.hxx> +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::resource; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::reflection; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::cppu; +using namespace ::osl; + + +void SFURL_firing_impl( const ScriptEvent& aScriptEvent, Any* pRet, const Reference< frame::XModel >& xModel ) +{ + OSL_TRACE("SFURL_firing_impl() processing script url %s", + ::rtl::OUStringToOString( aScriptEvent.ScriptCode, + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + try + { + Reference< provider::XScriptProvider > xScriptProvider; + if ( xModel.is() ) + { + Reference< provider::XScriptProviderSupplier > xSupplier( xModel, UNO_QUERY ); + OSL_ENSURE( xSupplier.is(), "SFURL_firing_impl: failed to get script provider supplier" ); + if ( xSupplier.is() ) + xScriptProvider.set( xSupplier->getScriptProvider() ); + } + else + { + Reference< XComponentContext > xContext; + Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + OSL_VERIFY( xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "DefaultContext" ) ) >>= xContext ); + if ( xContext.is() ) + { + Reference< provider::XScriptProviderFactory > xFactory( + xContext->getValueByName( + ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory" ) ), + UNO_QUERY ); + OSL_ENSURE( xFactory.is(), "SFURL_firing_impl: failed to get master script provider factory" ); + if ( xFactory.is() ) + { + Any aCtx; + aCtx <<= ::rtl::OUString::createFromAscii( "user" ); + xScriptProvider.set( xFactory->createScriptProvider( aCtx ), UNO_QUERY ); + } + } + } + + if ( !xScriptProvider.is() ) + { + OSL_TRACE("SFURL_firing_impl() Failed to create msp"); + return; + } + Sequence< Any > inArgs( 0 ); + Sequence< Any > outArgs( 0 ); + Sequence< sal_Int16 > outIndex; + + // get Arguments for script + inArgs = aScriptEvent.Arguments; + + Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode ); + + if ( !xScript.is() ) + { + OSL_TRACE("SFURL_firing_impl() Failed to obtain XScript"); + return; + } + + Any result = xScript->invoke( inArgs, outIndex, outArgs ); + if ( pRet ) + { + *pRet = result; + } + } + catch ( RuntimeException& re ) + { + OSL_TRACE("SFURL_firing_impl() Caught RuntimeException reason %s.", + ::rtl::OUStringToOString( re.Message, + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + catch ( Exception& e ) + { + OSL_TRACE("SFURL_firing_impl() Caught Exception reason %s.", + ::rtl::OUStringToOString( e.Message, + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + +} + + +class BasicScriptListener_Impl : public WeakImplHelper1< XScriptListener > +{ + StarBASICRef maBasicRef; + Reference< frame::XModel > m_xModel; + + virtual void firing_impl(const ScriptEvent& aScriptEvent, Any* pRet); + +public: + BasicScriptListener_Impl( StarBASIC* pBasic, const Reference< frame::XModel >& xModel ) + : maBasicRef( pBasic ), m_xModel( xModel ) {} + + // Methods of XAllListener + virtual void SAL_CALL firing(const ScriptEvent& aScriptEvent) + throw( RuntimeException ); + virtual Any SAL_CALL approveFiring(const ScriptEvent& aScriptEvent) + throw( InvocationTargetException, RuntimeException ); + + // Methods of XEventListener + virtual void SAL_CALL disposing(const EventObject& Source) + throw( RuntimeException ); +}; + +// Methods XAllListener +void BasicScriptListener_Impl::firing( const ScriptEvent& aScriptEvent ) throw ( RuntimeException ) +{ + firing_impl( aScriptEvent, NULL ); +} + +Any BasicScriptListener_Impl::approveFiring( const ScriptEvent& aScriptEvent ) + throw ( InvocationTargetException, RuntimeException ) +{ + Any aRetAny; + firing_impl( aScriptEvent, &aRetAny ); + return aRetAny; +} + +// Methods XEventListener +void BasicScriptListener_Impl::disposing(const EventObject& ) throw ( RuntimeException ) +{ + // TODO: ??? + //vos::OGuard guard( Application::GetSolarMutex() ); + //xSbxObj.Clear(); +} + + +void BasicScriptListener_Impl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet ) +{ + //Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + //{ + if( aScriptEvent.ScriptType.compareToAscii( "StarBasic" ) == 0 ) + { + // Full qualified name? + String aMacro( aScriptEvent.ScriptCode ); + String aLibName; + String aLocation; + if( aMacro.GetTokenCount( '.' ) == 3 ) + { + sal_uInt16 nLast = 0; + ::rtl::OUString aFullLibName = aMacro.GetToken( 0, '.', nLast ); + + sal_Int32 nIndex = aFullLibName.indexOf( (sal_Unicode)':' ); + if (nIndex >= 0) + { + aLocation = aFullLibName.copy( 0, nIndex ); + aLibName = aFullLibName.copy( nIndex + 1 ); + } + + String aModul = aMacro.GetToken( 0, '.', nLast ); + aMacro.Erase( 0, nLast ); + } + + SbxObject* p = maBasicRef; + SbxObject* pParent = p->GetParent(); + SbxObject* pParentParent = pParent ? pParent->GetParent() : NULL; + + StarBASICRef xAppStandardBasic; + StarBASICRef xDocStandardBasic; + if( pParentParent ) + { + // Own basic must be document library + xAppStandardBasic = (StarBASIC*)pParentParent; + xDocStandardBasic = (StarBASIC*)pParent; + } + else if( pParent ) + { + String aName = p->GetName(); + if( aName.EqualsAscii("Standard") ) + { + // Own basic is doc standard lib + xDocStandardBasic = (StarBASIC*)p; + } + xAppStandardBasic = (StarBASIC*)pParent; + } + else + { + xAppStandardBasic = (StarBASIC*)p; + } + + sal_Bool bSearchLib = true; + StarBASICRef xLibSearchBasic; + if( aLocation.EqualsAscii("application") ) + xLibSearchBasic = xAppStandardBasic; + else if( aLocation.EqualsAscii("document") ) + xLibSearchBasic = xDocStandardBasic; + else + bSearchLib = false; + + SbxVariable* pMethVar = NULL; + // Be still tolerant and make default search if no search basic exists + if( bSearchLib && xLibSearchBasic.Is() ) + { + StarBASICRef xLibBasic; + sal_Int16 nCount = xLibSearchBasic->GetObjects()->Count(); + for( sal_Int16 nObj = -1; nObj < nCount ; nObj++ ) + { + StarBASIC* pBasic; + if( nObj == -1 ) + { + pBasic = (StarBASIC*)xLibSearchBasic; + } + else + { + SbxVariable* pVar = xLibSearchBasic->GetObjects()->Get( nObj ); + pBasic = PTR_CAST(StarBASIC,pVar); + } + if( pBasic ) + { + String aName = pBasic->GetName(); + if( aName == aLibName ) + { + // Search only in the lib, not automatically in application basic + sal_uInt16 nFlags = pBasic->GetFlags(); + pBasic->ResetFlag( SBX_GBLSEARCH ); + pMethVar = pBasic->Find( aMacro, SbxCLASS_DONTCARE ); + pBasic->SetFlags( nFlags ); + break; + } + } + } + } + + // Default: Be tolerant and search everywhere + if( (!pMethVar || !pMethVar->ISA(SbMethod)) && maBasicRef.Is() ) + pMethVar = maBasicRef->FindQualified( aMacro, SbxCLASS_DONTCARE ); + + SbMethod* pMeth = PTR_CAST(SbMethod,pMethVar); + if( !pMeth ) + return; + + // Setup parameters + SbxArrayRef xArray; + String aTmp; + sal_Int32 nCnt = aScriptEvent.Arguments.getLength(); + if( nCnt ) + { + xArray = new SbxArray; + const Any *pArgs = aScriptEvent.Arguments.getConstArray(); + for( sal_Int32 i = 0; i < nCnt; i++ ) + { + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, pArgs[i] ); + xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) ); + } + } + + // Call method + SbxVariableRef xValue = pRet ? new SbxVariable : 0; + if( xArray.Is() ) + pMeth->SetParameters( xArray ); + pMeth->Call( xValue ); + if( pRet ) + *pRet = sbxToUnoValue( xValue ); + pMeth->SetParameters( NULL ); + } + else // scripting framework script + { + //callBasic via scripting framework + SFURL_firing_impl( aScriptEvent, pRet, m_xModel ); + + } +} + +Any implFindDialogLibForDialog( const Any& rDlgAny, SbxObject* pBasic ) +{ + Any aRetDlgLibAny; + + SbxVariable* pDlgLibContVar = pBasic->Find + ( String::CreateFromAscii("DialogLibraries"), SbxCLASS_OBJECT ); + if( pDlgLibContVar && pDlgLibContVar->ISA(SbUnoObject) ) + { + SbUnoObject* pDlgLibContUnoObj = (SbUnoObject*)(SbxBase*)pDlgLibContVar; + Any aDlgLibContAny = pDlgLibContUnoObj->getUnoAny(); + + Reference< XLibraryContainer > xDlgLibContNameAccess( aDlgLibContAny, UNO_QUERY ); + OSL_ENSURE( xDlgLibContNameAccess.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" ); + if( xDlgLibContNameAccess.is() ) + { + Sequence< ::rtl::OUString > aLibNames = xDlgLibContNameAccess->getElementNames(); + const ::rtl::OUString* pLibNames = aLibNames.getConstArray(); + sal_Int32 nLibNameCount = aLibNames.getLength(); + + for( sal_Int32 iLib = 0 ; iLib < nLibNameCount ; iLib++ ) + { + if ( !xDlgLibContNameAccess->isLibraryLoaded( pLibNames[ iLib ] ) ) + // if the library isn't loaded, then the dialog cannot originate from this lib + continue; + + Any aDlgLibAny = xDlgLibContNameAccess->getByName( pLibNames[ iLib ] ); + + Reference< XNameAccess > xDlgLibNameAccess( aDlgLibAny, UNO_QUERY ); + OSL_ENSURE( xDlgLibNameAccess.is(), "implFindDialogLibForDialog: invalid dialog lib!" ); + if( xDlgLibNameAccess.is() ) + { + Sequence< ::rtl::OUString > aDlgNames = xDlgLibNameAccess->getElementNames(); + const ::rtl::OUString* pDlgNames = aDlgNames.getConstArray(); + sal_Int32 nDlgNameCount = aDlgNames.getLength(); + + for( sal_Int32 iDlg = 0 ; iDlg < nDlgNameCount ; iDlg++ ) + { + Any aDlgAny = xDlgLibNameAccess->getByName( pDlgNames[ iDlg ] ); + if( aDlgAny == rDlgAny ) + { + aRetDlgLibAny = aDlgLibAny; + break; + } + } + } + } + } + } + + return aRetDlgLibAny; +} + +Any implFindDialogLibForDialogBasic( const Any& aAnyISP, SbxObject* pBasic, StarBASIC*& pFoundBasic ) +{ + Any aDlgLibAny; + // Find dialog library for dialog, direct access is not possible here + StarBASIC* pStartedBasic = (StarBASIC*)pBasic; + SbxObject* pParentBasic = pStartedBasic ? pStartedBasic->GetParent() : NULL; + SbxObject* pParentParentBasic = pParentBasic ? pParentBasic->GetParent() : NULL; + + SbxObject* pSearchBasic1 = NULL; + SbxObject* pSearchBasic2 = NULL; + if( pParentParentBasic ) + { + pSearchBasic1 = pParentBasic; + pSearchBasic2 = pParentParentBasic; + } + else + { + pSearchBasic1 = pStartedBasic; + pSearchBasic2 = pParentBasic; + } + if( pSearchBasic1 ) + { + aDlgLibAny = implFindDialogLibForDialog( aAnyISP, pSearchBasic1 ); + + if ( aDlgLibAny.hasValue() ) + pFoundBasic = (StarBASIC*)pSearchBasic1; + + else if( pSearchBasic2 ) + { + aDlgLibAny = implFindDialogLibForDialog( aAnyISP, pSearchBasic2 ); + if ( aDlgLibAny.hasValue() ) + pFoundBasic = (StarBASIC*)pSearchBasic2; + } + } + return aDlgLibAny; +} + +static ::rtl::OUString aDecorationPropName = + ::rtl::OUString::createFromAscii( "Decoration" ); +static ::rtl::OUString aTitlePropName = + ::rtl::OUString::createFromAscii( "Title" ); + +void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + static ::rtl::OUString aResourceResolverPropName = ::rtl::OUString::createFromAscii( "ResourceResolver" ); + + (void)pBasic; + (void)bWrite; + + Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() ); + if( !xMSF.is() ) + return; + + // We need at least 1 parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Get dialog + SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject(); + if( !(pObj && pObj->ISA(SbUnoObject)) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj; + Any aAnyISP = pUnoObj->getUnoAny(); + TypeClass eType = aAnyISP.getValueType().getTypeClass(); + + if( eType != TypeClass_INTERFACE ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Create new uno dialog + Reference< XNameContainer > xDialogModel( xMSF->createInstance + ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ) ), + UNO_QUERY ); + if( !xDialogModel.is() ) + return; + + Reference< XInputStreamProvider > xISP; + aAnyISP >>= xISP; + if( !xISP.is() ) + return; + + Reference< XComponentContext > xContext; + Reference< XPropertySet > xProps( xMSF, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + OSL_VERIFY( xProps->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext ); + + // Import the DialogModel + Reference< XInputStream > xInput( xISP->createInputStream() ); + + // i83963 Force decoration + uno::Reference< beans::XPropertySet > xDlgModPropSet( xDialogModel, uno::UNO_QUERY ); + if( xDlgModPropSet.is() ) + { + bool bDecoration = true; + try + { + Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName ); + aDecorationAny >>= bDecoration; + if( !bDecoration ) + { + xDlgModPropSet->setPropertyValue( aDecorationPropName, makeAny( true ) ); + xDlgModPropSet->setPropertyValue( aTitlePropName, makeAny( ::rtl::OUString() ) ); + } + } + catch( UnknownPropertyException& ) + {} + } + + Any aDlgLibAny; + bool bDocDialog = false; + StarBASIC* pFoundBasic = NULL; + OSL_TRACE("About to try get a hold of ThisComponent"); + Reference< frame::XModel > xModel = StarBASIC::GetModelFromBasic( pINST->GetBasic() ) ; + aDlgLibAny = implFindDialogLibForDialogBasic( aAnyISP, pINST->GetBasic(), pFoundBasic ); + // If we found the dialog then it belongs to the Search basic + if ( !pFoundBasic ) + { + Reference< frame::XDesktop > xDesktop( xMSF->createInstance + ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ), + UNO_QUERY ); + Reference< container::XEnumeration > xModels; + if ( xDesktop.is() ) + { + Reference< container::XEnumerationAccess > xComponents( xDesktop->getComponents(), UNO_QUERY ); + if ( xComponents.is() ) + xModels.set( xComponents->createEnumeration(), UNO_QUERY ); + if ( xModels.is() ) + { + while ( xModels->hasMoreElements() ) + { + Reference< frame::XModel > xNextModel( xModels->nextElement(), UNO_QUERY ); + if ( xNextModel.is() ) + { + BasicManager* pMgr = basic::BasicManagerRepository::getDocumentBasicManager( xNextModel ); + if ( pMgr ) + aDlgLibAny = implFindDialogLibForDialogBasic( aAnyISP, pMgr->GetLib(0), pFoundBasic ); + if ( aDlgLibAny.hasValue() ) + { + bDocDialog = true; + xModel = xNextModel; + break; + } + } + } + } + } + } + if ( pFoundBasic ) + bDocDialog = pFoundBasic->IsDocBasic(); + Reference< XScriptListener > xScriptListener = new BasicScriptListener_Impl( pINST->GetBasic(), xModel ); + + Sequence< Any > aArgs( 4 ); + if( bDocDialog ) + aArgs[ 0 ] <<= xModel; + else + aArgs[ 0 ] <<= uno::Reference< uno::XInterface >(); + aArgs[ 1 ] <<= xInput; + aArgs[ 2 ] = aDlgLibAny; + aArgs[ 3 ] <<= xScriptListener; + // Create a "living" Dialog + Reference< XControl > xCntrl; + try + { + Reference< XDialogProvider > xDlgProv( xMSF->createInstanceWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.DialogProvider" ) ), aArgs ), UNO_QUERY ); + xCntrl.set( xDlgProv->createDialog( rtl::OUString() ), UNO_QUERY_THROW ); + // Add dialog model to dispose vector + Reference< XComponent > xDlgComponent( xCntrl->getModel(), UNO_QUERY ); + pINST->getComponentVector().push_back( xDlgComponent ); + // need ThisCompoent from calling script + } + // preserve existing bad behaviour, it's possible... but probably + // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes + // create dialog fails. So, in this case let's not throw, just leave basic + // detect the unset object. + catch( uno::Exception& ) + { + } + + // Return dialog + Any aRetVal; + aRetVal <<= xCntrl; + SbxVariableRef refVar = rPar.Get(0); + unoToSbxValue( (SbxVariable*)refVar, aRetVal ); +} + + +//=================================================================== + diff --git a/basic/source/classes/image.cxx b/basic/source/classes/image.cxx new file mode 100644 index 000000000000..fc6228d1aee9 --- /dev/null +++ b/basic/source/classes/image.cxx @@ -0,0 +1,544 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <tools/tenccvt.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include <string.h> // memset() etc +#include "image.hxx" +#include <codegen.hxx> +SbiImage::SbiImage() +{ + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + pLegacyPCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nCodeSize = 0; + nLegacyCodeSize = + nDimBase = 0; + bInit = + bError = sal_False; + bFirstInit = sal_True; + eCharSet = gsl_getSystemTextEncoding(); +} + +SbiImage::~SbiImage() +{ + Clear(); +} + +void SbiImage::Clear() +{ + delete[] pStringOff; + delete[] pStrings; + delete[] pCode; + ReleaseLegacyBuffer(); + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nLegacyCodeSize = 0; + nCodeSize = 0; + eCharSet = gsl_getSystemTextEncoding(); + nDimBase = 0; + bError = sal_False; +} + +/************************************************************************** +* +* Service-Routines for Load/Store +* +**************************************************************************/ + +sal_Bool SbiGood( SvStream& r ) +{ + return sal_Bool( !r.IsEof() && r.GetError() == SVSTREAM_OK ); +} + +// Open Record +sal_uIntPtr SbiOpenRecord( SvStream& r, sal_uInt16 nSignature, sal_uInt16 nElem ) +{ + sal_uIntPtr nPos = r.Tell(); + r << nSignature << (sal_Int32) 0 << nElem; + return nPos; +} + +// Close Record +void SbiCloseRecord( SvStream& r, sal_uIntPtr nOff ) +{ + sal_uIntPtr nPos = r.Tell(); + r.Seek( nOff + 2 ); + r << (sal_Int32) ( nPos - nOff - 8 ); + r.Seek( nPos ); +} + +/************************************************************************** +* +* Load/Store +* +**************************************************************************/ + +// If the version number does not find, binary parts are omitted, but not +// source, comments and name +sal_Bool SbiImage::Load( SvStream& r ) +{ + sal_uInt32 nVersion = 0; // Versionsnumber + return Load( r, nVersion ); +} +sal_Bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion ) +{ + + sal_uInt16 nSign, nCount; + sal_uInt32 nLen, nOff; + + Clear(); + // Read Master-Record + r >> nSign >> nLen >> nCount; + sal_uIntPtr nLast = r.Tell() + nLen; + sal_uInt32 nCharSet; // System charset + sal_uInt32 lDimBase; + sal_uInt16 nReserved1; + sal_uInt32 nReserved2; + sal_uInt32 nReserved3; + sal_Bool bBadVer = sal_False; + if( nSign == B_MODULE ) + { + r >> nVersion >> nCharSet >> lDimBase + >> nFlags >> nReserved1 >> nReserved2 >> nReserved3; + eCharSet = (CharSet) nCharSet; + eCharSet = GetSOLoadTextEncoding( eCharSet ); + bBadVer = sal_Bool( nVersion > B_CURVERSION ); + nDimBase = (sal_uInt16) lDimBase; + } + + bool bLegacy = ( nVersion < B_EXT_IMG_VERSION ); + + sal_uIntPtr nNext; + while( ( nNext = r.Tell() ) < nLast ) + { + short i; + + r >> nSign >> nLen >> nCount; + nNext += nLen + 8; + if( r.GetError() == SVSTREAM_OK ) + switch( nSign ) + { + case B_NAME: + r.ReadByteString( aName, eCharSet ); + //r >> aName; + break; + case B_COMMENT: + r.ReadByteString( aComment, eCharSet ); + //r >> aComment; + break; + case B_SOURCE: + { + String aTmp; + r.ReadByteString( aTmp, eCharSet ); + aOUSource = aTmp; + //r >> aSource; + break; + } +#ifdef EXTENDED_BINARY_MODULES + case B_EXTSOURCE: + { + for( sal_uInt16 j = 0 ; j < nCount ; j++ ) + { + String aTmp; + r.ReadByteString( aTmp, eCharSet ); + aOUSource += aTmp; + } + break; + } +#endif + case B_PCODE: + if( bBadVer ) break; + pCode = new char[ nLen ]; + nCodeSize = nLen; + r.Read( pCode, nCodeSize ); + if ( bLegacy ) + { + ReleaseLegacyBuffer(); // release any previously held buffer + nLegacyCodeSize = (sal_uInt16) nCodeSize; + pLegacyPCode = pCode; + + PCodeBuffConvertor< sal_uInt16, sal_uInt32 > aLegacyToNew( (sal_uInt8*)pLegacyPCode, nLegacyCodeSize ); + aLegacyToNew.convert(); + pCode = (char*)aLegacyToNew.GetBuffer(); + nCodeSize = aLegacyToNew.GetSize(); + // we don't release the legacy buffer + // right now, thats because the module + // needs it to fix up the method + // nStart members. When that is done + // the module can release the buffer + // or it can wait until this routine + // is called again or when this class // destructs all of which will trigger + // release of the buffer. + } + break; + case B_PUBLICS: + case B_POOLDIR: + case B_SYMPOOL: + case B_LINERANGES: + break; + case B_STRINGPOOL: + if( bBadVer ) break; + MakeStrings( nCount ); + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + { + r >> nOff; + pStringOff[ i ] = (sal_uInt16) nOff; + } + r >> nLen; + if( SbiGood( r ) ) + { + delete [] pStrings; + pStrings = new sal_Unicode[ nLen ]; + nStringSize = (sal_uInt16) nLen; + + char* pByteStrings = new char[ nLen ]; + r.Read( pByteStrings, nStringSize ); + for( short j = 0; j < nStrings; j++ ) + { + sal_uInt16 nOff2 = (sal_uInt16) pStringOff[ j ]; + String aStr( pByteStrings + nOff2, eCharSet ); + memcpy( pStrings + nOff2, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( sal_Unicode ) ); + } + delete[] pByteStrings; + } break; + case B_MODEND: + goto done; + default: + break; + } + else + break; + r.Seek( nNext ); + } +done: + r.Seek( nLast ); + //if( eCharSet != ::GetSystemCharSet() ) + //ConvertStrings(); + if( !SbiGood( r ) ) + bError = sal_True; + return sal_Bool( !bError ); +} + +sal_Bool SbiImage::Save( SvStream& r, sal_uInt32 nVer ) +{ + bool bLegacy = ( nVer < B_EXT_IMG_VERSION ); + + // detect if old code exceeds legacy limits + // if so, then disallow save + if ( bLegacy && ExceedsLegacyLimits() ) + { + SbiImage aEmptyImg; + aEmptyImg.aName = aName; + aEmptyImg.Save( r, B_LEGACYVERSION ); + return sal_True; + } + // First of all the header + sal_uIntPtr nStart = SbiOpenRecord( r, B_MODULE, 1 ); + sal_uIntPtr nPos; + + eCharSet = GetSOStoreTextEncoding( eCharSet ); + if ( bLegacy ) + r << (sal_Int32) B_LEGACYVERSION; + else + r << (sal_Int32) B_CURVERSION; + r << (sal_Int32) eCharSet + << (sal_Int32) nDimBase + << (sal_Int16) nFlags + << (sal_Int16) 0 + << (sal_Int32) 0 + << (sal_Int32) 0; + + // Name? + if( aName.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_NAME, 1 ); + r.WriteByteString( aName, eCharSet ); + //r << aName; + SbiCloseRecord( r, nPos ); + } + // Comment? + if( aComment.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_COMMENT, 1 ); + r.WriteByteString( aComment, eCharSet ); + //r << aComment; + SbiCloseRecord( r, nPos ); + } + // Source? + if( aOUSource.getLength() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_SOURCE, 1 ); + String aTmp; + sal_Int32 nLen = aOUSource.getLength(); + const sal_Int32 nMaxUnitSize = STRING_MAXLEN - 1; + if( nLen > STRING_MAXLEN ) + aTmp = aOUSource.copy( 0, nMaxUnitSize ); + else + aTmp = aOUSource; + r.WriteByteString( aTmp, eCharSet ); + //r << aSource; + SbiCloseRecord( r, nPos ); + +#ifdef EXTENDED_BINARY_MODULES + if( nLen > STRING_MAXLEN ) + { + sal_Int32 nRemainingLen = nLen - nMaxUnitSize; + sal_uInt16 nUnitCount = sal_uInt16( (nRemainingLen + nMaxUnitSize - 1) / nMaxUnitSize ); + nPos = SbiOpenRecord( r, B_EXTSOURCE, nUnitCount ); + for( sal_uInt16 i = 0 ; i < nUnitCount ; i++ ) + { + sal_Int32 nCopyLen = + (nRemainingLen > nMaxUnitSize) ? nMaxUnitSize : nRemainingLen; + String aTmp2 = aOUSource.copy( (i+1) * nMaxUnitSize, nCopyLen ); + nRemainingLen -= nCopyLen; + r.WriteByteString( aTmp2, eCharSet ); + } + SbiCloseRecord( r, nPos ); + } +#endif + } + // Binary data? + if( pCode && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_PCODE, 1 ); + if ( bLegacy ) + { + ReleaseLegacyBuffer(); // release any previously held buffer + PCodeBuffConvertor< sal_uInt32, sal_uInt16 > aNewToLegacy( (sal_uInt8*)pCode, nCodeSize ); + aNewToLegacy.convert(); + pLegacyPCode = (char*)aNewToLegacy.GetBuffer(); + nLegacyCodeSize = aNewToLegacy.GetSize(); + r.Write( pLegacyPCode, nLegacyCodeSize ); + } + else + r.Write( pCode, nCodeSize ); + SbiCloseRecord( r, nPos ); + } + // String-Pool? + if( nStrings ) + { + nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings ); + // For every String: + // sal_uInt32 Offset of the Strings in the Stringblock + short i; + + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + r << (sal_uInt32) pStringOff[ i ]; + + // Then the String-Block + char* pByteStrings = new char[ nStringSize ]; + for( i = 0; i < nStrings; i++ ) + { + sal_uInt16 nOff = (sal_uInt16) pStringOff[ i ]; + ByteString aStr( pStrings + nOff, eCharSet ); + memcpy( pByteStrings + nOff, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( char ) ); + } + r << (sal_uInt32) nStringSize; + r.Write( pByteStrings, nStringSize ); + + delete[] pByteStrings; + SbiCloseRecord( r, nPos ); + } + // Set overall length + SbiCloseRecord( r, nStart ); + if( !SbiGood( r ) ) + bError = sal_True; + return sal_Bool( !bError ); +} + +/************************************************************************** +* +* Routines called by the compiler +* +**************************************************************************/ + +void SbiImage::MakeStrings( short nSize ) +{ + nStrings = 0; + nStringIdx = 0; + nStringOff = 0; + nStringSize = 1024; + pStrings = new sal_Unicode[ nStringSize ]; + pStringOff = new sal_uInt32[ nSize ]; + if( pStrings && pStringOff ) + { + nStrings = nSize; + memset( pStringOff, 0, nSize * sizeof( sal_uInt32 ) ); + memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) ); + } + else + bError = sal_True; +} + +// Hinzufuegen eines Strings an den StringPool. Der String-Puffer +// waechst dynamisch in 1K-Schritten +// Add a string to StringPool. The String buffer is dynamically +// growing in 1K-Steps +void SbiImage::AddString( const String& r ) +{ + if( nStringIdx >= nStrings ) + bError = sal_True; + if( !bError ) + { + xub_StrLen len = r.Len() + 1; + sal_uInt32 needed = nStringOff + len; + if( needed > 0xFFFFFF00L ) + bError = sal_True; // out of mem! + else if( needed > nStringSize ) + { + sal_uInt32 nNewLen = needed + 1024; + nNewLen &= 0xFFFFFC00; // trim to 1K border + if( nNewLen > 0xFFFFFF00L ) + nNewLen = 0xFFFFFF00L; + sal_Unicode* p = NULL; + if( (p = new sal_Unicode[ nNewLen ]) != NULL ) + { + memcpy( p, pStrings, nStringSize * sizeof( sal_Unicode ) ); + delete[] pStrings; + pStrings = p; + nStringSize = sal::static_int_cast< sal_uInt16 >(nNewLen); + } + else + bError = sal_True; + } + if( !bError ) + { + pStringOff[ nStringIdx++ ] = nStringOff; + //ByteString aByteStr( r, eCharSet ); + memcpy( pStrings + nStringOff, r.GetBuffer(), len * sizeof( sal_Unicode ) ); + nStringOff = nStringOff + len; + // Last String? The update the size of the buffer + if( nStringIdx >= nStrings ) + nStringSize = nStringOff; + } + } +} + +// Add code block +// The block was fetched by the compiler from class SbBuffer and +// is already created with new. Additionally it contains all Integers +// in Big Endian format, so can be directly read/written. +void SbiImage::AddCode( char* p, sal_uInt32 s ) +{ + pCode = p; + nCodeSize = s; +} + +// Add user type +void SbiImage::AddType(SbxObject* pObject) +{ + if( !rTypes.Is() ) + rTypes = new SbxArray; + SbxObject *pCopyObject = new SbxObject(*pObject); + rTypes->Insert (pCopyObject,rTypes->Count()); +} + +void SbiImage::AddEnum(SbxObject* pObject) // Register enum type +{ + if( !rEnums.Is() ) + rEnums = new SbxArray; + rEnums->Insert( pObject, rEnums->Count() ); +} + + +/************************************************************************** +* +* Accessing the image +* +**************************************************************************/ + +// Note: IDs start with 1 +String SbiImage::GetString( short nId ) const +{ + if( nId && nId <= nStrings ) + { + sal_uInt32 nOff = pStringOff[ nId - 1 ]; + sal_Unicode* pStr = pStrings + nOff; + + // #i42467: Special treatment for vbNullChar + if( *pStr == 0 ) + { + sal_uInt32 nNextOff = (nId < nStrings) ? pStringOff[ nId ] : nStringOff; + sal_uInt32 nLen = nNextOff - nOff - 1; + if( nLen == 1 ) + { + // Force length 1 and make char 0 afterwards + String aNullCharStr( String::CreateFromAscii( " " ) ); + aNullCharStr.SetChar( 0, 0 ); + return aNullCharStr; + } + } + else + { + String aStr( pStr ); + return aStr; + } + } + return String(); +} + +const SbxObject* SbiImage::FindType (String aTypeName) const +{ + return rTypes.Is() ? (SbxObject*)rTypes->Find(aTypeName,SbxCLASS_OBJECT) : NULL; +} + +sal_uInt16 SbiImage::CalcLegacyOffset( sal_Int32 nOffset ) +{ + return SbiCodeGen::calcLegacyOffSet( (sal_uInt8*)pCode, nOffset ) ; +} + +sal_uInt32 SbiImage::CalcNewOffset( sal_Int16 nOffset ) +{ + return SbiCodeGen::calcNewOffSet( (sal_uInt8*)pLegacyPCode, nOffset ) ; +} + +void SbiImage::ReleaseLegacyBuffer() +{ + delete[] pLegacyPCode; + pLegacyPCode = NULL; + nLegacyCodeSize = 0; +} + +sal_Bool SbiImage::ExceedsLegacyLimits() +{ + if ( ( nStringSize > 0xFF00L ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00L ) ) + return sal_True; + return sal_False; +} diff --git a/basic/source/classes/makefile.mk b/basic/source/classes/makefile.mk new file mode 100644 index 000000000000..e00ed4674cc1 --- /dev/null +++ b/basic/source/classes/makefile.mk @@ -0,0 +1,76 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=classes +LIBTARGET=NO + +# --- Settings ----------------------------------------------------------- + +ENABLE_EXCEPTIONS=TRUE + +.INCLUDE : settings.mk + +ALLTAR .SEQUENTIAL : \ + $(MISC)$/$(TARGET).don \ + $(MISC)$/$(TARGET).slo + +$(MISC)$/$(TARGET).don : $(SOLARBINDIR)$/oovbaapi.rdb + +$(CPPUMAKER) -O$(OUT)$/inc -BUCR $(SOLARBINDIR)$/oovbaapi.rdb -X$(SOLARBINDIR)$/types.rdb && echo > $@ + echo $@ + +$(MISC)$/$(TARGET).slo : $(SLOTARGET) + echo $@ + +# --- Allgemein ----------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/sb.obj \ + $(SLO)$/sbxmod.obj \ + $(SLO)$/image.obj \ + $(SLO)$/sbintern.obj \ + $(SLO)$/sbunoobj.obj \ + $(SLO)$/propacc.obj \ + $(SLO)$/disas.obj \ + $(SLO)$/errobject.obj \ + $(SLO)$/eventatt.obj + +OBJFILES= \ + $(OBJ)$/sbintern.obj + +SRS1NAME=$(TARGET) +SRC1FILES= sb.src + +LIB1TARGET= $(SLB)$/$(TARGET).lib +LIB1OBJFILES = $(SLOFILES) + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/basic/source/classes/propacc.cxx b/basic/source/classes/propacc.cxx new file mode 100644 index 000000000000..9168ef915770 --- /dev/null +++ b/basic/source/classes/propacc.cxx @@ -0,0 +1,430 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "propacc.hxx" + +#include <tools/urlobj.hxx> +#include <tools/errcode.hxx> +#include <svl/svarray.hxx> +#include <basic/sbstar.hxx> +#include <sbunoobj.hxx> + +using com::sun::star::uno::Reference; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace cppu; + + +//======================================================================== + +// Declaration conversion from Sbx to UNO with known target type +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty = NULL ); + +//======================================================================== + +#ifdef WNT +#define CDECL _cdecl +#endif +#if defined(UNX) || defined(OS2) +#define CDECL +#endif + +int CDECL SbCompare_PropertyValues_Impl( const void *arg1, const void *arg2 ) +{ + return ((PropertyValue*)arg1)->Name.compareTo( ((PropertyValue*)arg2)->Name ); +} + +extern "C" int CDECL SbCompare_UString_PropertyValue_Impl( const void *arg1, const void *arg2 ) +{ + const ::rtl::OUString *pArg1 = (::rtl::OUString*) arg1; + const PropertyValue **pArg2 = (const PropertyValue**) arg2; + return pArg1->compareTo( (*pArg2)->Name ); +} + +int CDECL SbCompare_Properties_Impl( const void *arg1, const void *arg2 ) +{ + return ((Property*)arg1)->Name.compareTo( ((Property*)arg2)->Name ); +} + +extern "C" int CDECL SbCompare_UString_Property_Impl( const void *arg1, const void *arg2 ) +{ + const ::rtl::OUString *pArg1 = (::rtl::OUString*) arg1; + const Property *pArg2 = (Property*) arg2; + return pArg1->compareTo( pArg2->Name ); +} + +//---------------------------------------------------------------------------- + +SbPropertyValues::SbPropertyValues() +{ +} + +//---------------------------------------------------------------------------- + +SbPropertyValues::~SbPropertyValues() +{ + _xInfo = Reference< XPropertySetInfo >(); + + for ( sal_uInt16 n = 0; n < _aPropVals.Count(); ++n ) + delete _aPropVals.GetObject( n ); +} + +//---------------------------------------------------------------------------- + +Reference< XPropertySetInfo > SbPropertyValues::getPropertySetInfo(void) throw( RuntimeException ) +{ + // create on demand? + if ( !_xInfo.is() ) + { + SbPropertySetInfo *pInfo = new SbPropertySetInfo( _aPropVals ); + ((SbPropertyValues*)this)->_xInfo = (XPropertySetInfo*)pInfo; + } + return _xInfo; +} + +//------------------------------------------------------------------------- + +sal_Int32 SbPropertyValues::GetIndex_Impl( const ::rtl::OUString &rPropName ) const +{ + PropertyValue **ppPV; + ppPV = (PropertyValue **) + bsearch( &rPropName, _aPropVals.GetData(), _aPropVals.Count(), + sizeof( PropertyValue* ), + SbCompare_UString_PropertyValue_Impl ); + return ppPV ? ( (ppPV-_aPropVals.GetData()) / sizeof(ppPV) ) : USHRT_MAX; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::setPropertyValue( + const ::rtl::OUString& aPropertyName, + const Any& aValue) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + sal_Int32 nIndex = GetIndex_Impl( aPropertyName ); + PropertyValue *pPropVal = _aPropVals.GetObject( + sal::static_int_cast< sal_uInt16 >(nIndex)); + pPropVal->Value = aValue; +} + +//---------------------------------------------------------------------------- + +Any SbPropertyValues::getPropertyValue( + const ::rtl::OUString& aPropertyName) + throw(::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + sal_Int32 nIndex = GetIndex_Impl( aPropertyName ); + if ( nIndex != USHRT_MAX ) + return _aPropVals.GetObject( + sal::static_int_cast< sal_uInt16 >(nIndex))->Value; + return Any(); +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::addPropertyChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XPropertyChangeListener >& ) + throw () +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::removePropertyChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XPropertyChangeListener >& ) + throw () +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::addVetoableChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XVetoableChangeListener >& ) + throw() +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::removeVetoableChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XVetoableChangeListener >& ) + throw() +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +Sequence< PropertyValue > SbPropertyValues::getPropertyValues(void) throw (::com::sun::star::uno::RuntimeException) +{ + Sequence<PropertyValue> aRet( _aPropVals.Count()); + for ( sal_uInt16 n = 0; n < _aPropVals.Count(); ++n ) + aRet.getArray()[n] = *_aPropVals.GetObject(n); + return aRet; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::setPropertyValues(const Sequence< PropertyValue >& rPropertyValues ) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + if ( _aPropVals.Count() ) + throw PropertyExistException(); + + const PropertyValue *pPropVals = rPropertyValues.getConstArray(); + for ( sal_Int16 n = 0; n < rPropertyValues.getLength(); ++n ) + { + PropertyValue *pPropVal = new PropertyValue(pPropVals[n]); + _aPropVals.Insert( pPropVal, n ); + } +} + +//============================================================================ +//PropertySetInfoImpl + +PropertySetInfoImpl::PropertySetInfoImpl() +{ +} + +sal_Int32 PropertySetInfoImpl::GetIndex_Impl( const ::rtl::OUString &rPropName ) const +{ + Property *pP; + pP = (Property*) + bsearch( &rPropName, _aProps.getConstArray(), _aProps.getLength(), + sizeof( Property ), + SbCompare_UString_Property_Impl ); + return pP ? sal::static_int_cast<sal_Int32>( (pP-_aProps.getConstArray()) / sizeof(pP) ) : -1; +} + +Sequence< Property > PropertySetInfoImpl::getProperties(void) throw() +{ + return _aProps; +} + +Property PropertySetInfoImpl::getPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ) +{ + sal_Int32 nIndex = GetIndex_Impl( Name ); + if( USHRT_MAX != nIndex ) + return _aProps.getConstArray()[ nIndex ]; + return Property(); +} + +sal_Bool PropertySetInfoImpl::hasPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ) +{ + sal_Int32 nIndex = GetIndex_Impl( Name ); + return USHRT_MAX != nIndex; +} + + +//============================================================================ + +SbPropertySetInfo::SbPropertySetInfo() +{ +} + +//---------------------------------------------------------------------------- + +SbPropertySetInfo::SbPropertySetInfo( const SbPropertyValueArr_Impl &rPropVals ) +{ + aImpl._aProps.realloc( rPropVals.Count() ); + for ( sal_uInt16 n = 0; n < rPropVals.Count(); ++n ) + { + Property &rProp = aImpl._aProps.getArray()[n]; + const PropertyValue &rPropVal = *rPropVals.GetObject(n); + rProp.Name = rPropVal.Name; + rProp.Handle = rPropVal.Handle; + rProp.Type = getCppuVoidType(); + rProp.Attributes = 0; + } +} + +//---------------------------------------------------------------------------- + +SbPropertySetInfo::~SbPropertySetInfo() +{ +} + +//------------------------------------------------------------------------- + +Sequence< Property > SbPropertySetInfo::getProperties(void) throw( RuntimeException ) +{ + return aImpl.getProperties(); +} + +Property SbPropertySetInfo::getPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.getPropertyByName( Name ); +} + +sal_Bool SbPropertySetInfo::hasPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.hasPropertyByName( Name ); +} + + +//---------------------------------------------------------------------------- + +SbPropertyContainer::SbPropertyContainer() +{ +} + +//---------------------------------------------------------------------------- + +SbPropertyContainer::~SbPropertyContainer() +{ +} + +//---------------------------------------------------------------------------- +void SbPropertyContainer::addProperty(const ::rtl::OUString& Name, + sal_Int16 Attributes, + const Any& DefaultValue) + throw( PropertyExistException, IllegalTypeException, + IllegalArgumentException, RuntimeException ) +{ + (void)Name; + (void)Attributes; + (void)DefaultValue; +} + +//---------------------------------------------------------------------------- +void SbPropertyContainer::removeProperty(const ::rtl::OUString& Name) + throw( UnknownPropertyException, RuntimeException ) +{ + (void)Name; +} + +//---------------------------------------------------------------------------- +// XPropertySetInfo +Sequence< Property > SbPropertyContainer::getProperties(void) throw () +{ + return aImpl.getProperties(); +} + +Property SbPropertyContainer::getPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.getPropertyByName( Name ); +} + +sal_Bool SbPropertyContainer::hasPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.hasPropertyByName( Name ); +} + +//---------------------------------------------------------------------------- + +Sequence< PropertyValue > SbPropertyContainer::getPropertyValues(void) +{ + return Sequence<PropertyValue>(); +} + +//---------------------------------------------------------------------------- + +void SbPropertyContainer::setPropertyValues(const Sequence< PropertyValue >& PropertyValues_) +{ + (void)PropertyValues_; +} + +//---------------------------------------------------------------------------- + +void RTL_Impl_CreatePropertySet( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // We need at least one parameter + // TODO: In this case < 2 is not correct ;-) + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Get class names of struct + String aServiceName( RTL_CONSTASCII_USTRINGPARAM("stardiv.uno.beans.PropertySet") ); + +#if 0 + // Service suchen und instanzieren + Reference< XMultiServiceFactory > xServiceManager = getProcessServiceFactory(); + Reference< XInterface > xInterface; + if( xProv.is() ) + xInterface = xProv->newInstance(); +#else + Reference< XInterface > xInterface = (OWeakObject*) new SbPropertyValues(); +#endif + + SbxVariableRef refVar = rPar.Get(0); + if( xInterface.is() ) + { + // Set PropertyValues + Any aArgAsAny = sbxToUnoValue( rPar.Get(1), + getCppuType( (Sequence<PropertyValue>*)0 ) ); + Sequence<PropertyValue> *pArg = + (Sequence<PropertyValue>*) aArgAsAny.getValue(); + Reference< XPropertyAccess > xPropAcc = Reference< XPropertyAccess >::query( xInterface ); + xPropAcc->setPropertyValues( *pArg ); + + // Build a SbUnoObject and return it + Any aAny; + aAny <<= xInterface; + SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny ); + if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID ) + { + // Return object + refVar->PutObject( (SbUnoObject*)xUnoObj ); + return; + } + } + + // Object could not be created + refVar->PutObject( NULL ); +} + diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx new file mode 100644 index 000000000000..e2f53dd8ed8e --- /dev/null +++ b/basic/source/classes/sb.cxx @@ -0,0 +1,2135 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdio.h> + +#include "sb.hxx" +#include <tools/rcid.h> +#include <tools/config.hxx> +#include <tools/stream.hxx> +#ifndef __RSC //autogen +#include <tools/errinf.hxx> +#endif +#include <basic/sbx.hxx> +#include <tools/list.hxx> +#include <tools/shl.hxx> +#include <tools/rc.hxx> +#include <vcl/svapp.hxx> +#include "sbunoobj.hxx" +#include "sbjsmeth.hxx" +#include "sbjsmod.hxx" +#include "sbintern.hxx" +#include "disas.hxx" +#include "runtime.hxx" +#include <basic/sbuno.hxx> +#include <basic/sbobjmod.hxx> +#include "stdobj.hxx" +#include "filefmt.hxx" +#include "sb.hrc" +#include <basrid.hxx> +#include <vos/mutex.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include "errobject.hxx" +#include <hash_map> + +#include <com/sun/star/script/ModuleType.hpp> +#include <com/sun/star/script/ModuleInfo.hpp> +using namespace ::com::sun::star::script; + +// #pragma SW_SEGMENT_CLASS( SBASIC, SBASIC_CODE ) + +SV_IMPL_VARARR(SbTextPortions,SbTextPortion) + +TYPEINIT1(StarBASIC,SbxObject) + +#define RTLNAME "@SBRTL" +// i#i68894# +using namespace ::com::sun::star; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::lang::XMultiServiceFactory; + +const static String aThisComponent( RTL_CONSTASCII_USTRINGPARAM("ThisComponent") ); +const static String aVBAHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) ); + +SbxObject* StarBASIC::getVBAGlobals( ) +{ + if ( !pVBAGlobals ) + { + Any aThisDoc; + if ( GetUNOConstant("ThisComponent", aThisDoc) ) + { + Reference< XMultiServiceFactory > xDocFac( aThisDoc, UNO_QUERY ); + if ( xDocFac.is() ) + { + try + { + xDocFac->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) ); + } + catch( Exception& ) + { + // Ignore + } + } + } + pVBAGlobals = (SbUnoObject*)Find( aVBAHook , SbxCLASS_DONTCARE ); + } + return pVBAGlobals; +} + +// i#i68894# +SbxVariable* StarBASIC::VBAFind( const String& rName, SbxClassType t ) +{ + if( rName == aThisComponent ) + return NULL; + // rename to init globals + if ( getVBAGlobals( ) ) + return pVBAGlobals->Find( rName, t ); + return NULL; + +} +// Create array for conversion SFX <-> VB error code +struct SFX_VB_ErrorItem +{ + sal_uInt16 nErrorVB; + SbError nErrorSFX; +}; + +const SFX_VB_ErrorItem __FAR_DATA SFX_VB_ErrorTab[] = +{ + { 1, SbERR_BASIC_EXCEPTION }, // #87844 Map exception to error code 1 + { 2, SbERR_SYNTAX }, + { 3, SbERR_NO_GOSUB }, + { 4, SbERR_REDO_FROM_START }, + { 5, SbERR_BAD_ARGUMENT }, + { 6, SbERR_MATH_OVERFLOW }, + { 7, SbERR_NO_MEMORY }, + { 8, SbERR_ALREADY_DIM }, + { 9, SbERR_OUT_OF_RANGE }, + { 10, SbERR_DUPLICATE_DEF }, + { 11, SbERR_ZERODIV }, + { 12, SbERR_VAR_UNDEFINED }, + { 13, SbERR_CONVERSION }, + { 14, SbERR_BAD_PARAMETER }, + { 18, SbERR_USER_ABORT }, + { 20, SbERR_BAD_RESUME }, + { 28, SbERR_STACK_OVERFLOW }, + { 35, SbERR_PROC_UNDEFINED }, + { 48, SbERR_BAD_DLL_LOAD }, + { 49, SbERR_BAD_DLL_CALL }, + { 51, SbERR_INTERNAL_ERROR }, + { 52, SbERR_BAD_CHANNEL }, + { 53, SbERR_FILE_NOT_FOUND }, + { 54, SbERR_BAD_FILE_MODE }, + { 55, SbERR_FILE_ALREADY_OPEN }, + { 57, SbERR_IO_ERROR }, + { 58, SbERR_FILE_EXISTS }, + { 59, SbERR_BAD_RECORD_LENGTH }, + { 61, SbERR_DISK_FULL }, + { 62, SbERR_READ_PAST_EOF }, + { 63, SbERR_BAD_RECORD_NUMBER }, + { 67, SbERR_TOO_MANY_FILES }, + { 68, SbERR_NO_DEVICE }, + { 70, SbERR_ACCESS_DENIED }, + { 71, SbERR_NOT_READY }, + { 73, SbERR_NOT_IMPLEMENTED }, + { 74, SbERR_DIFFERENT_DRIVE }, + { 75, SbERR_ACCESS_ERROR }, + { 76, SbERR_PATH_NOT_FOUND }, + { 91, SbERR_NO_OBJECT }, + { 93, SbERR_BAD_PATTERN }, + { 94, SBERR_IS_NULL }, + { 250, SbERR_DDE_ERROR }, + { 280, SbERR_DDE_WAITINGACK }, + { 281, SbERR_DDE_OUTOFCHANNELS }, + { 282, SbERR_DDE_NO_RESPONSE }, + { 283, SbERR_DDE_MULT_RESPONSES }, + { 284, SbERR_DDE_CHANNEL_LOCKED }, + { 285, SbERR_DDE_NOTPROCESSED }, + { 286, SbERR_DDE_TIMEOUT }, + { 287, SbERR_DDE_USER_INTERRUPT }, + { 288, SbERR_DDE_BUSY }, + { 289, SbERR_DDE_NO_DATA }, + { 290, SbERR_DDE_WRONG_DATA_FORMAT }, + { 291, SbERR_DDE_PARTNER_QUIT }, + { 292, SbERR_DDE_CONV_CLOSED }, + { 293, SbERR_DDE_NO_CHANNEL }, + { 294, SbERR_DDE_INVALID_LINK }, + { 295, SbERR_DDE_QUEUE_OVERFLOW }, + { 296, SbERR_DDE_LINK_ALREADY_EST }, + { 297, SbERR_DDE_LINK_INV_TOPIC }, + { 298, SbERR_DDE_DLL_NOT_FOUND }, + { 323, SbERR_CANNOT_LOAD }, + { 341, SbERR_BAD_INDEX }, + { 366, SbERR_NO_ACTIVE_OBJECT }, + { 380, SbERR_BAD_PROP_VALUE }, + { 382, SbERR_PROP_READONLY }, + { 394, SbERR_PROP_WRITEONLY }, + { 420, SbERR_INVALID_OBJECT }, + { 423, SbERR_NO_METHOD }, + { 424, SbERR_NEEDS_OBJECT }, + { 425, SbERR_INVALID_USAGE_OBJECT }, + { 430, SbERR_NO_OLE }, + { 438, SbERR_BAD_METHOD }, + { 440, SbERR_OLE_ERROR }, + { 445, SbERR_BAD_ACTION }, + { 446, SbERR_NO_NAMED_ARGS }, + { 447, SbERR_BAD_LOCALE }, + { 448, SbERR_NAMED_NOT_FOUND }, + { 449, SbERR_NOT_OPTIONAL }, + { 450, SbERR_WRONG_ARGS }, + { 451, SbERR_NOT_A_COLL }, + { 452, SbERR_BAD_ORDINAL }, + { 453, SbERR_DLLPROC_NOT_FOUND }, + { 460, SbERR_BAD_CLIPBD_FORMAT }, + { 951, SbERR_UNEXPECTED }, + { 952, SbERR_EXPECTED }, + { 953, SbERR_SYMBOL_EXPECTED }, + { 954, SbERR_VAR_EXPECTED }, + { 955, SbERR_LABEL_EXPECTED }, + { 956, SbERR_LVALUE_EXPECTED }, + { 957, SbERR_VAR_DEFINED }, + { 958, SbERR_PROC_DEFINED }, + { 959, SbERR_LABEL_DEFINED }, + { 960, SbERR_UNDEF_VAR }, + { 961, SbERR_UNDEF_ARRAY }, + { 962, SbERR_UNDEF_PROC }, + { 963, SbERR_UNDEF_LABEL }, + { 964, SbERR_UNDEF_TYPE }, + { 965, SbERR_BAD_EXIT }, + { 966, SbERR_BAD_BLOCK }, + { 967, SbERR_BAD_BRACKETS }, + { 968, SbERR_BAD_DECLARATION }, + { 969, SbERR_BAD_PARAMETERS }, + { 970, SbERR_BAD_CHAR_IN_NUMBER }, + { 971, SbERR_MUST_HAVE_DIMS }, + { 972, SbERR_NO_IF }, + { 973, SbERR_NOT_IN_SUBR }, + { 974, SbERR_NOT_IN_MAIN }, + { 975, SbERR_WRONG_DIMS }, + { 976, SbERR_BAD_OPTION }, + { 977, SbERR_CONSTANT_REDECLARED }, + { 978, SbERR_PROG_TOO_LARGE }, + { 979, SbERR_NO_STRINGS_ARRAYS }, + { 1000, SbERR_PROPERTY_NOT_FOUND }, + { 1001, SbERR_METHOD_NOT_FOUND }, + { 1002, SbERR_ARG_MISSING }, + { 1003, SbERR_BAD_NUMBER_OF_ARGS }, + { 1004, SbERR_METHOD_FAILED }, + { 1005, SbERR_SETPROP_FAILED }, + { 1006, SbERR_GETPROP_FAILED }, + { 1007, SbERR_BASIC_COMPAT }, + { 0xFFFF, 0xFFFFFFFFL } // End mark +}; + +// The StarBASIC factory is a hack. When a SbModule is created, its pointer +// is saved and given to the following SbProperties/SbMethods. This restores +// the Modul-relationshop. But it works only when a modul is loaded. +// Can cause troubles with separately loaded properties! + +SbxBase* SbiFactory::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator ) +{ + if( nCreator == SBXCR_SBX ) + { + String aEmpty; + switch( nSbxId ) + { + case SBXID_BASIC: + return new StarBASIC( NULL ); + case SBXID_BASICMOD: + return new SbModule( aEmpty ); + case SBXID_BASICPROP: + return new SbProperty( aEmpty, SbxVARIANT, NULL ); + case SBXID_BASICMETHOD: + return new SbMethod( aEmpty, SbxVARIANT, NULL ); + case SBXID_JSCRIPTMOD: + return new SbJScriptModule( aEmpty ); + case SBXID_JSCRIPTMETH: + return new SbJScriptMethod( aEmpty, SbxVARIANT, NULL ); + } + } + return NULL; +} + +SbxObject* SbiFactory::CreateObject( const String& rClass ) +{ + if( rClass.EqualsIgnoreCaseAscii( "StarBASIC" ) ) + return new StarBASIC( NULL ); + else + if( rClass.EqualsIgnoreCaseAscii( "StarBASICModule" ) ) + { + String aEmpty; + return new SbModule( aEmpty ); + } + else + if( rClass.EqualsIgnoreCaseAscii( "Collection" ) ) + { + String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") ); + return new BasicCollection( aCollectionName ); + } + else + return NULL; +} + + +// Factory class to create OLE objects +class SbOLEFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +SbxBase* SbOLEFactory::Create( sal_uInt16, sal_uInt32 ) +{ + // Not supported + return NULL; +} + +SbUnoObject* createOLEObject_Impl( const String& aType ); // sbunoobj.cxx + +SbxObject* SbOLEFactory::CreateObject( const String& rClassName ) +{ + SbxObject* pRet = createOLEObject_Impl( rClassName ); + return pRet; +} + + +//======================================================================== +// SbFormFactory, show user forms by: dim as new <user form name> + +class SbFormFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 ) +{ + // Not supported + return NULL; +} + +SbxObject* SbFormFactory::CreateObject( const String& rClassName ) +{ + if( SbModule* pMod = pMOD ) + { + if( SbxVariable* pVar = pMod->Find( rClassName, SbxCLASS_OBJECT ) ) + { + if( SbUserFormModule* pFormModule = PTR_CAST( SbUserFormModule, pVar->GetObject() ) ) + { + bool bInitState = pFormModule->getInitState(); + if( bInitState ) + { + // Not the first instantiate, reset + bool bTriggerTerminateEvent = false; + pFormModule->ResetApiObj( bTriggerTerminateEvent ); + pFormModule->setInitState( false ); + } + else + { + pFormModule->Load(); + } + return pFormModule->CreateInstance(); + } + } + } + return 0; +} + + +//======================================================================== +// SbTypeFactory + +SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj ) +{ + SbxObject* pRet = new SbxObject( rTypeObj ); + pRet->PutObject( pRet ); + + // Copy the properties, not only the reference to them + SbxArray* pProps = pRet->GetProperties(); + sal_uInt32 nCount = pProps->Count32(); + for( sal_uInt32 i = 0 ; i < nCount ; i++ ) + { + SbxVariable* pVar = pProps->Get32( i ); + SbxProperty* pProp = PTR_CAST( SbxProperty, pVar ); + if( pProp ) + { + SbxProperty* pNewProp = new SbxProperty( *pProp ); + SbxDataType eVarType = pVar->GetType(); + if( eVarType & SbxARRAY ) + { + SbxBase* pParObj = pVar->GetObject(); + SbxDimArray* pSource = PTR_CAST(SbxDimArray,pParObj); + SbxDimArray* pDest = new SbxDimArray( pVar->GetType() ); + sal_Int32 lb = 0; + sal_Int32 ub = 0; + + pDest->setHasFixedSize( pSource->hasFixedSize() ); + if ( pSource->GetDims() && pSource->hasFixedSize() ) + { + for ( sal_Int32 j = 1 ; j <= pSource->GetDims(); ++j ) + { + pSource->GetDim32( (sal_Int32)j, lb, ub ); + pDest->AddDim32( lb, ub ); + } + } + else + pDest->unoAddDim( 0, -1 ); // variant array + + sal_uInt16 nSavFlags = pVar->GetFlags(); + pNewProp->ResetFlag( SBX_FIXED ); + // need to reset the FIXED flag + // when calling PutObject ( because the type will not match Object ) + pNewProp->PutObject( pDest ); + pNewProp->SetFlags( nSavFlags ); + } + if( eVarType == SbxOBJECT ) + { + SbxBase* pObjBase = pVar->GetObject(); + SbxObject* pSrcObj = PTR_CAST(SbxObject,pObjBase); + SbxObject* pDestObj = NULL; + if( pSrcObj != NULL ) + pDestObj = cloneTypeObjectImpl( *pSrcObj ); + pNewProp->PutObject( pDestObj ); + } + pProps->PutDirect( pNewProp, i ); + } + } + return pRet; +} + +// Factory class to create user defined objects (type command) +class SbTypeFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 ) +{ + // Not supported + return NULL; +} + +SbxObject* SbTypeFactory::CreateObject( const String& rClassName ) +{ + SbxObject* pRet = NULL; + SbModule* pMod = pMOD; + if( pMod ) + { + const SbxObject* pObj = pMod->FindType( rClassName ); + if( pObj ) + pRet = cloneTypeObjectImpl( *pObj ); + } + return pRet; +} + +SbxObject* createUserTypeImpl( const String& rClassName ) +{ + SbxObject* pRetObj = pTYPEFAC->CreateObject( rClassName ); + return pRetObj; +} + +TYPEINIT1(SbClassModuleObject,SbModule) + +SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule ) + : SbModule( pClassModule->GetName() ) + , mpClassModule( pClassModule ) + , mbInitializeEventDone( false ) +{ + aOUSource = pClassModule->aOUSource; + aComment = pClassModule->aComment; + pImage = pClassModule->pImage; + pBreaks = pClassModule->pBreaks; + + SetClassName( pClassModule->GetName() ); + + // Allow search only internally + ResetFlag( SBX_GBLSEARCH ); + + // Copy the methods from original class module + SbxArray* pClassMethods = pClassModule->GetMethods(); + sal_uInt32 nMethodCount = pClassMethods->Count32(); + sal_uInt32 i; + for( i = 0 ; i < nMethodCount ; i++ ) + { + SbxVariable* pVar = pClassMethods->Get32( i ); + + // Exclude SbIfaceMapperMethod to copy them in a second step + SbIfaceMapperMethod* pIfaceMethod = PTR_CAST( SbIfaceMapperMethod, pVar ); + if( !pIfaceMethod ) + { + SbMethod* pMethod = PTR_CAST(SbMethod, pVar ); + if( pMethod ) + { + sal_uInt16 nFlags_ = pMethod->GetFlags(); + pMethod->SetFlag( SBX_NO_BROADCAST ); + SbMethod* pNewMethod = new SbMethod( *pMethod ); + pNewMethod->ResetFlag( SBX_NO_BROADCAST ); + pMethod->SetFlags( nFlags_ ); + pNewMethod->pMod = this; + pNewMethod->SetParent( this ); + pMethods->PutDirect( pNewMethod, i ); + StartListening( pNewMethod->GetBroadcaster(), sal_True ); + } + } + } + + // Copy SbIfaceMapperMethod in a second step to ensure that + // the corresponding base methods have already been copied + for( i = 0 ; i < nMethodCount ; i++ ) + { + SbxVariable* pVar = pClassMethods->Get32( i ); + + SbIfaceMapperMethod* pIfaceMethod = PTR_CAST( SbIfaceMapperMethod, pVar ); + if( pIfaceMethod ) + { + SbMethod* pImplMethod = pIfaceMethod->getImplMethod(); + if( !pImplMethod ) + { + DBG_ERROR( "No ImplMethod" ); + continue; + } + + // Search for own copy of ImplMethod + String aImplMethodName = pImplMethod->GetName(); + SbxVariable* p = pMethods->Find( aImplMethodName, SbxCLASS_METHOD ); + SbMethod* pImplMethodCopy = p ? PTR_CAST(SbMethod,p) : NULL; + if( !pImplMethodCopy ) + { + DBG_ERROR( "Found no ImplMethod copy" ); + continue; + } + SbIfaceMapperMethod* pNewIfaceMethod = + new SbIfaceMapperMethod( pIfaceMethod->GetName(), pImplMethodCopy ); + pMethods->PutDirect( pNewIfaceMethod, i ); + } + } + + // Copy the properties from original class module + SbxArray* pClassProps = pClassModule->GetProperties(); + sal_uInt32 nPropertyCount = pClassProps->Count32(); + for( i = 0 ; i < nPropertyCount ; i++ ) + { + SbxVariable* pVar = pClassProps->Get32( i ); + SbProcedureProperty* pProcedureProp = PTR_CAST( SbProcedureProperty, pVar ); + if( pProcedureProp ) + { + sal_uInt16 nFlags_ = pProcedureProp->GetFlags(); + pProcedureProp->SetFlag( SBX_NO_BROADCAST ); + SbProcedureProperty* pNewProp = new SbProcedureProperty + ( pProcedureProp->GetName(), pProcedureProp->GetType() ); + // ( pProcedureProp->GetName(), pProcedureProp->GetType(), this ); + pNewProp->SetFlags( nFlags_ ); // Copy flags + pNewProp->ResetFlag( SBX_NO_BROADCAST ); // except the Broadcast if it was set + pProcedureProp->SetFlags( nFlags_ ); + pProps->PutDirect( pNewProp, i ); + StartListening( pNewProp->GetBroadcaster(), sal_True ); + } + else + { + SbxProperty* pProp = PTR_CAST( SbxProperty, pVar ); + if( pProp ) + { + sal_uInt16 nFlags_ = pProp->GetFlags(); + pProp->SetFlag( SBX_NO_BROADCAST ); + SbxProperty* pNewProp = new SbxProperty( *pProp ); + + // Special handling for modules instances and collections, they need + // to be instantiated, otherwise all refer to the same base object + SbxDataType eVarType = pProp->GetType(); + if( eVarType == SbxOBJECT ) + { + SbxBase* pObjBase = pProp->GetObject(); + SbxObject* pObj = PTR_CAST(SbxObject,pObjBase); + if( pObj != NULL ) + { + String aObjClass = pObj->GetClassName(); + + SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pObjBase); + if( pClassModuleObj != NULL ) + { + SbModule* pLclClassModule = pClassModuleObj->getClassModule(); + SbClassModuleObject* pNewObj = new SbClassModuleObject( pLclClassModule ); + pNewObj->SetName( pProp->GetName() ); + pNewObj->SetParent( pLclClassModule->pParent ); + pNewProp->PutObject( pNewObj ); + } + else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) ) + { + String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") ); + BasicCollection* pNewCollection = new BasicCollection( aCollectionName ); + pNewCollection->SetName( pProp->GetName() ); + pNewCollection->SetParent( pClassModule->pParent ); + pNewProp->PutObject( pNewCollection ); + } + } + } + + pNewProp->ResetFlag( SBX_NO_BROADCAST ); + pNewProp->SetParent( this ); + pProps->PutDirect( pNewProp, i ); + pProp->SetFlags( nFlags_ ); + } + } + } + SetModuleType( ModuleType::CLASS ); + mbVBACompat = pClassModule->mbVBACompat; +} + +SbClassModuleObject::~SbClassModuleObject() +{ + if( StarBASIC::IsRunning() ) + triggerTerminateEvent(); + + // Must be deleted by base class dtor because this data + // is not owned by the SbClassModuleObject object + pImage = NULL; + pBreaks = NULL; +} + +void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + handleProcedureProperties( rBC, rHint ); +} + +SbxVariable* SbClassModuleObject::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pRes = SbxObject::Find( rName, t ); + if( pRes ) + { + triggerInitializeEvent(); + + SbIfaceMapperMethod* pIfaceMapperMethod = PTR_CAST(SbIfaceMapperMethod,pRes); + if( pIfaceMapperMethod ) + { + pRes = pIfaceMapperMethod->getImplMethod(); + pRes->SetFlag( SBX_EXTFOUND ); + } + } + return pRes; +} + +void SbClassModuleObject::triggerInitializeEvent( void ) +{ + static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Initialize") ); + + if( mbInitializeEventDone ) + return; + + mbInitializeEventDone = true; + + // Search method + SbxVariable* pMeth = SbxObject::Find( aInitMethodName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + pMeth->Get( aVals ); + } +} + +void SbClassModuleObject::triggerTerminateEvent( void ) +{ + static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Terminate") ); + + if( !mbInitializeEventDone || GetSbData()->bRunInit ) + return; + + // Search method + SbxVariable* pMeth = SbxObject::Find( aTermMethodName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + pMeth->Get( aVals ); + } +} + + +SbClassData::SbClassData( void ) +{ + mxIfaces = new SbxArray(); +} + +void SbClassData::clear( void ) +{ + mxIfaces->Clear(); + maRequiredTypes.clear(); +} + +SbClassFactory::SbClassFactory( void ) +{ + String aDummyName; + xClassModules = new SbxObject( aDummyName ); +} + +SbClassFactory::~SbClassFactory() +{} + +void SbClassFactory::AddClassModule( SbModule* pClassModule ) +{ + SbxObject* pParent = pClassModule->GetParent(); + xClassModules->Insert( pClassModule ); + pClassModule->SetParent( pParent ); +} + +void SbClassFactory::RemoveClassModule( SbModule* pClassModule ) +{ + xClassModules->Remove( pClassModule ); +} + +SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 ) +{ + // Not supported + return NULL; +} + +SbxObject* SbClassFactory::CreateObject( const String& rClassName ) +{ + SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE ); + SbxObject* pRet = NULL; + if( pVar ) + { + SbModule* pMod = (SbModule*)pVar; + pRet = new SbClassModuleObject( pMod ); + } + return pRet; +} + +SbModule* SbClassFactory::FindClass( const String& rClassName ) +{ + SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE ); + SbModule* pMod = pVar ? (SbModule*)pVar : NULL; + return pMod; +} + +typedef std::vector< StarBASIC* > DocBasicVector; +static DocBasicVector GaDocBasics; + +StarBASIC::StarBASIC( StarBASIC* p, sal_Bool bIsDocBasic ) + : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ), bDocBasic( bIsDocBasic ) +{ + SetParent( p ); + pLibInfo = NULL; + bNoRtl = bBreak = sal_False; + bVBAEnabled = sal_False; + pModules = new SbxArray; + + if( !GetSbData()->nInst++ ) + { + pSBFAC = new SbiFactory; + AddFactory( pSBFAC ); + pTYPEFAC = new SbTypeFactory; + AddFactory( pTYPEFAC ); + pCLASSFAC = new SbClassFactory; + AddFactory( pCLASSFAC ); + pOLEFAC = new SbOLEFactory; + AddFactory( pOLEFAC ); + pFORMFAC = new SbFormFactory; + AddFactory( pFORMFAC ); + pUNOFAC = new SbUnoFactory; + AddFactory( pUNOFAC ); + } + pRtl = new SbiStdObject( String( RTL_CONSTASCII_USTRINGPARAM(RTLNAME) ), this ); + // Search via StarBasic is always global + SetFlag( SBX_GBLSEARCH ); + pVBAGlobals = NULL; + bQuit = sal_False; + + if( bDocBasic ) + GaDocBasics.push_back( this ); +} + +// #51727 Override SetModified so that the modified state +// is not given to the parent +void StarBASIC::SetModified( sal_Bool b ) +{ + SbxBase::SetModified( b ); +} + +StarBASIC::~StarBASIC() +{ + if( !--GetSbData()->nInst ) + { + RemoveFactory( pSBFAC ); + delete pSBFAC; pSBFAC = NULL; + RemoveFactory( pUNOFAC ); + delete pUNOFAC; pUNOFAC = NULL; + RemoveFactory( pTYPEFAC ); + delete pTYPEFAC; pTYPEFAC = NULL; + RemoveFactory( pCLASSFAC ); + delete pCLASSFAC; pCLASSFAC = NULL; + RemoveFactory( pOLEFAC ); + delete pOLEFAC; pOLEFAC = NULL; + RemoveFactory( pFORMFAC ); + delete pFORMFAC; pFORMFAC = NULL; + +#ifdef DBG_UTIL + // There is no need to clean SbiData at program end, + // but we dislike MLK's at Purify + // TODO: Where else??? + SbiGlobals** pp = (SbiGlobals**) ::GetAppData( SHL_SBC ); + SbiGlobals* p = *pp; + if( p ) + { + delete p; + *pp = 0; + } +#endif + } + else if( bDocBasic ) + { + SbxError eOld = SbxBase::GetError(); + + DocBasicVector::iterator it; + for( it = GaDocBasics.begin() ; it != GaDocBasics.end() ; ++it ) + { + if( *it == this ) + { + GaDocBasics.erase( it ); + break; + } + } + for( it = GaDocBasics.begin() ; it != GaDocBasics.end() ; ++it ) + { + StarBASIC* pBasic = *it; + pBasic->implClearDependingVarsOnDelete( this ); + } + + SbxBase::ResetError(); + if( eOld != SbxERR_OK ) + SbxBase::SetError( eOld ); + } + + // #100326 Set Parent NULL in registered listeners + if( xUnoListeners.Is() ) + { + sal_uInt16 uCount = xUnoListeners->Count(); + for( sal_uInt16 i = 0 ; i < uCount ; i++ ) + { + SbxVariable* pListenerObj = xUnoListeners->Get( i ); + pListenerObj->SetParent( NULL ); + } + xUnoListeners = NULL; + } + + clearUnoMethodsForBasic( this ); + disposeComVariablesForBasic( this ); +} + +// Override new() operator, so that everyone can create a new instance +void* StarBASIC::operator new( size_t n ) +{ + if( n < sizeof( StarBASIC ) ) + { +// DBG_ASSERT( sal_False, "Warnung: inkompatibler BASIC-Stand!" ); + n = sizeof( StarBASIC ); + } + return ::operator new( n ); +} + +void StarBASIC::operator delete( void* p ) +{ + ::operator delete( p ); +} + +void StarBASIC::implClearDependingVarsOnDelete( StarBASIC* pDeletedBasic ) +{ + if( this != pDeletedBasic ) + { + for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*)pModules->Get( i ); + p->ClearVarsDependingOnDeletedBasic( pDeletedBasic ); + } + } + + for( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic && pBasic != pDeletedBasic ) + pBasic->implClearDependingVarsOnDelete( pDeletedBasic ); + } +} + + +/************************************************************************** +* +* Creation/Managment of modules +* +**************************************************************************/ + +SbModule* StarBASIC::MakeModule( const String& rName, const String& rSrc ) +{ + return MakeModule32( rName, rSrc ); +} + +SbModule* StarBASIC::MakeModule32( const String& rName, const ::rtl::OUString& rSrc ) +{ + ModuleInfo mInfo; + mInfo.ModuleType = ModuleType::NORMAL; + return MakeModule32( rName, mInfo, rSrc ); +} +SbModule* StarBASIC::MakeModule32( const String& rName, const ModuleInfo& mInfo, const rtl::OUString& rSrc ) +{ + + OSL_TRACE("create module %s type mInfo %d", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(), mInfo.ModuleType ); + SbModule* p = NULL; + switch ( mInfo.ModuleType ) + { + case ModuleType::DOCUMENT: + // In theory we should be able to create Object modules + // in ordinary basic ( in vba mode thought these are create + // by the application/basic and not by the user ) + p = new SbObjModule( rName, mInfo, isVBAEnabled() ); + break; + case ModuleType::CLASS: + p = new SbModule( rName, isVBAEnabled() ); + p->SetModuleType( ModuleType::CLASS ); + break; + case ModuleType::FORM: + p = new SbUserFormModule( rName, mInfo, isVBAEnabled() ); + break; + default: + p = new SbModule( rName, isVBAEnabled() ); + + } + p->SetSource32( rSrc ); + p->SetParent( this ); + pModules->Insert( p, pModules->Count() ); + SetModified( sal_True ); + return p; +} + +void StarBASIC::Insert( SbxVariable* pVar ) +{ + if( pVar->IsA( TYPE(SbModule) ) ) + { + pModules->Insert( pVar, pModules->Count() ); + pVar->SetParent( this ); + StartListening( pVar->GetBroadcaster(), sal_True ); + } + else + { + sal_Bool bWasModified = IsModified(); + SbxObject::Insert( pVar ); + if( !bWasModified && pVar->IsSet( SBX_DONTSTORE ) ) + SetModified( sal_False ); + } +} + +void StarBASIC::Remove( SbxVariable* pVar ) +{ + if( pVar->IsA( TYPE(SbModule) ) ) + { + // #87540 Can be last reference! + SbxVariableRef xVar = pVar; + pModules->Remove( pVar ); + pVar->SetParent( 0 ); + EndListening( pVar->GetBroadcaster() ); + } + else + SbxObject::Remove( pVar ); +} + +sal_Bool StarBASIC::Compile( SbModule* pMod ) +{ + return pMod ? pMod->Compile() : sal_False; +} + +sal_Bool StarBASIC::Disassemble( SbModule* pMod, String& rText ) +{ + rText.Erase(); + if( pMod ) + pMod->Disassemble( rText ); + return sal_Bool( rText.Len() != 0 ); +} + +void StarBASIC::Clear() +{ + while( pModules->Count() ) + pModules->Remove( pModules->Count() - 1 ); +} + +SbModule* StarBASIC::FindModule( const String& rName ) +{ + for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) + return p; + } + return NULL; +} + + +struct ClassModuleRunInitItem +{ + SbModule* m_pModule; + bool m_bProcessing; + bool m_bRunInitDone; + //ModuleVector m_vModulesDependingOnThisModule; + + ClassModuleRunInitItem( void ) + : m_pModule( NULL ) + , m_bProcessing( false ) + , m_bRunInitDone( false ) + {} + ClassModuleRunInitItem( SbModule* pModule ) + : m_pModule( pModule ) + , m_bProcessing( false ) + , m_bRunInitDone( false ) + {} +}; + +// Derive from has_map type instead of typedef +// to allow forward declaration in sbmod.hxx +class ModuleInitDependencyMap : public + std::hash_map< ::rtl::OUString, ClassModuleRunInitItem, + ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > +{}; + +void SbModule::implProcessModuleRunInit( ModuleInitDependencyMap& rMap, ClassModuleRunInitItem& rItem ) +{ + rItem.m_bProcessing = true; + + //bool bAnyDependencies = true; + SbModule* pModule = rItem.m_pModule; + if( pModule->pClassData != NULL ) + { + StringVector& rReqTypes = pModule->pClassData->maRequiredTypes; + if( rReqTypes.size() > 0 ) + { + for( StringVector::iterator it = rReqTypes.begin() ; it != rReqTypes.end() ; ++it ) + { + String& rStr = *it; + + // Is required type a class module? + ModuleInitDependencyMap::iterator itFind = rMap.find( rStr ); + if( itFind != rMap.end() ) + { + ClassModuleRunInitItem& rParentItem = itFind->second; + if( rParentItem.m_bProcessing ) + { + // TODO: raise error? + DBG_ERROR( "Cyclic module dependency detected" ); + continue; + } + + if( !rParentItem.m_bRunInitDone ) + implProcessModuleRunInit( rMap, rParentItem ); + } + } + } + } + + pModule->RunInit(); + rItem.m_bRunInitDone = true; + rItem.m_bProcessing = false; +} + +// Run Init-Code of all modules (including inserted libraries) +void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) +{ + ::vos::OGuard guard( Application::GetSolarMutex() ); + + // Init own modules + for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( !pModule->IsCompiled() ) + pModule->Compile(); + } + // compile modules first then RunInit ( otherwise there is + // can be order dependency, e.g. classmodule A has a member + // of of type classmodule B and classmodule B hasn't been compiled yet ) + + // Consider required types to init in right order. Class modules + // that are required by other modules have to be initialized first. + ModuleInitDependencyMap aMIDMap; + for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + String aModuleName = pModule->GetName(); + if( pModule->isProxyModule() ) + aMIDMap[aModuleName] = ClassModuleRunInitItem( pModule ); + } + + ModuleInitDependencyMap::iterator it; + for( it = aMIDMap.begin() ; it != aMIDMap.end(); ++it ) + { + ClassModuleRunInitItem& rItem = it->second; + SbModule::implProcessModuleRunInit( aMIDMap, rItem ); + } + + // Call RunInit on standard modules + for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( !pModule->isProxyModule() ) + pModule->RunInit(); + } + + // Check all objects if they are BASIC, + // if yes initialize + for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic && pBasic != pBasicNotToInit ) + pBasic->InitAllModules(); + } +} + +// #88329 Put modules back to not initialised state to +// force reinitialisation at next start +void StarBASIC::DeInitAllModules( void ) +{ + // Deinit own modules + for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( pModule->pImage && !pModule->isProxyModule() && !pModule->ISA(SbObjModule) ) + pModule->pImage->bInit = false; + } + + for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic ) + pBasic->DeInitAllModules(); + } +} + +// #43011 For TestTool, to delete global vars +void StarBASIC::ClearGlobalVars( void ) +{ + SbxArrayRef xProps( GetProperties() ); + sal_uInt16 nPropCount = xProps->Count(); + for ( sal_uInt16 nProp = 0 ; nProp < nPropCount ; ++nProp ) + { + SbxBase* pVar = xProps->Get( nProp ); + pVar->Clear(); + } + SetModified( sal_True ); +} + +// This implementation at first searches within the runtime library, +// then it looks for an element within one module. This moudle can be +// a public var or an entrypoint. If it is not found and we look for a +// method and a module with the given name is found the search continues +// for entrypoint "Main". +// If this fails again a conventional search over objects is performend. +SbxVariable* StarBASIC::Find( const String& rName, SbxClassType t ) +{ + static String aMainStr( RTL_CONSTASCII_USTRINGPARAM("Main") ); + + SbxVariable* pRes = NULL; + SbModule* pNamed = NULL; + // "Extended" search in Runtime Lib + // but only if SbiRuntime has not set the flag + if( !bNoRtl ) + { + if( t == SbxCLASS_DONTCARE || t == SbxCLASS_OBJECT ) + { + if( rName.EqualsIgnoreCaseAscii( RTLNAME ) ) + pRes = pRtl; + } + if( !pRes ) + pRes = ((SbiStdObject*) (SbxObject*) pRtl)->Find( rName, t ); + if( pRes ) + pRes->SetFlag( SBX_EXTFOUND ); + } + // Search module + if( !pRes ) + for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( p->IsVisible() ) + { + // Remember modul fpr Main() call + // or is the name equal?!? + if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) + { + if( t == SbxCLASS_OBJECT || t == SbxCLASS_DONTCARE ) + { + pRes = p; break; + } + pNamed = p; + } + // Only variables qualified by the Module Name e.g. Sheet1.foo + // should work for Documant && Class type Modules + sal_Int32 nType = p->GetModuleType(); + if ( nType == ModuleType::DOCUMENT || nType == ModuleType::FORM ) + continue; + + // otherwise check if the element is available + // unset GBLSEARCH-Flag (due to Rekursion) + sal_uInt16 nGblFlag = p->GetFlags() & SBX_GBLSEARCH; + p->ResetFlag( SBX_GBLSEARCH ); + pRes = p->Find( rName, t ); + p->SetFlag( nGblFlag ); + if( pRes ) + break; + } + } + if( !pRes && pNamed && ( t == SbxCLASS_METHOD || t == SbxCLASS_DONTCARE ) && + !pNamed->GetName().EqualsIgnoreCaseAscii( aMainStr ) ) + pRes = pNamed->Find( aMainStr, SbxCLASS_METHOD ); + if( !pRes ) + pRes = SbxObject::Find( rName, t ); + return pRes; +} + +sal_Bool StarBASIC::Call( const String& rName, SbxArray* pParam ) +{ + sal_Bool bRes = SbxObject::Call( rName, pParam ); + if( !bRes ) + { + SbxError eErr = SbxBase::GetError(); + SbxBase::ResetError(); + if( eErr != SbxERR_OK ) + RTError( (SbError)eErr, 0, 0, 0 ); + } + return bRes; +} + +// Find method via name (e.g. query via BASIC IDE) +SbxBase* StarBASIC::FindSBXInCurrentScope( const String& rName ) +{ + if( !pINST ) + return NULL; + if( !pINST->pRun ) + return NULL; + return pINST->pRun->FindElementExtern( rName ); +} + +// Preserve old interface +SbxVariable* StarBASIC::FindVarInCurrentScopy +( const String& rName, sal_uInt16& rStatus ) +{ + rStatus = 1; // Presumption: nothing found + SbxVariable* pVar = NULL; + SbxBase* pSbx = FindSBXInCurrentScope( rName ); + if( pSbx ) + { + if( !pSbx->ISA(SbxMethod) && !pSbx->ISA(SbxObject) ) + pVar = PTR_CAST(SbxVariable,pSbx); + } + if( pVar ) + rStatus = 0; // We found something + return pVar; +} + +void StarBASIC::QuitAndExitApplication() +{ + Stop(); + bQuit = sal_True; +} + +void StarBASIC::Stop() +{ + SbiInstance* p = pINST; + while( p ) + { + p->Stop(); + p = p->pNext; + } +} + +sal_Bool StarBASIC::IsRunning() +{ + return sal_Bool( pINST != NULL ); +} + +/************************************************************************** +* +* Object factories and others +* +**************************************************************************/ + +// Activation of an object. There is no need to access active objects +// with name via BASIC. If NULL is given, everything is activated. +void StarBASIC::ActivateObject( const String* pName, sal_Bool bActivate ) +{ + if( pName ) + { + SbxObject* p = (SbxObject*) SbxObject::Find( *pName, SbxCLASS_OBJECT ); + if( p ) + { + if( bActivate ) + p->SetFlag( SBX_EXTSEARCH ); + else + p->ResetFlag( SBX_EXTSEARCH ); + } + } + else + { + for( sal_uInt16 i = 0; i < GetObjects()->Count(); i++ ) + { + SbxObject* p = (SbxObject*) GetObjects()->Get( i ); + if( bActivate ) + p->SetFlag( SBX_EXTSEARCH ); + else + p->ResetFlag( SBX_EXTSEARCH ); + } + } +} + +/************************************************************************** +* +* Debugging and error handling +* +**************************************************************************/ + +SbMethod* StarBASIC::GetActiveMethod( sal_uInt16 nLevel ) +{ + if( pINST ) + return pINST->GetCaller( nLevel ); + else + return NULL; +} + +SbModule* StarBASIC::GetActiveModule() +{ + if( pINST && !IsCompilerError() ) + return pINST->GetActiveModule(); + else + return pCMOD; +} + +sal_uInt16 StarBASIC::BreakPoint( sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) +{ + SetErrorData( 0, l, c1, c2 ); + bBreak = sal_True; + if( GetSbData()->aBreakHdl.IsSet() ) + return (sal_uInt16) GetSbData()->aBreakHdl.Call( this ); + else + return BreakHdl(); +} + +sal_uInt16 StarBASIC::StepPoint( sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) +{ + SetErrorData( 0, l, c1, c2 ); + bBreak = sal_False; + if( GetSbData()->aBreakHdl.IsSet() ) + return (sal_uInt16) GetSbData()->aBreakHdl.Call( this ); + else + return BreakHdl(); +} + +sal_uInt16 __EXPORT StarBASIC::BreakHdl() +{ + return (sal_uInt16) ( aBreakHdl.IsSet() + ? aBreakHdl.Call( this ) : SbDEBUG_CONTINUE ); +} + +// Calls for error handler and break handler +sal_uInt16 StarBASIC::GetLine() { return GetSbData()->nLine; } +sal_uInt16 StarBASIC::GetCol1() { return GetSbData()->nCol1; } +sal_uInt16 StarBASIC::GetCol2() { return GetSbData()->nCol2; } + +// Specific to error handler +SbError StarBASIC::GetErrorCode() { return GetSbData()->nCode; } +const String& StarBASIC::GetErrorText() { return GetSbData()->aErrMsg; } +sal_Bool StarBASIC::IsCompilerError() { return GetSbData()->bCompiler; } +void StarBASIC::SetGlobalLanguageMode( SbLanguageMode eLanguageMode ) +{ + GetSbData()->eLanguageMode = eLanguageMode; +} +SbLanguageMode StarBASIC::GetGlobalLanguageMode() +{ + return GetSbData()->eLanguageMode; +} +// Local settings +SbLanguageMode StarBASIC::GetLanguageMode() +{ + // Use global settings? + if( eLanguageMode == SB_LANG_GLOBAL ) + return GetSbData()->eLanguageMode; + else + return eLanguageMode; +} + +// AB: 29.3.96 +// Das Mapping zwischen alten und neuen Fehlercodes erfolgt, indem die Tabelle +// SFX_VB_ErrorTab[] durchsucht wird. Dies ist zwar nicht besonders performant, +// verbraucht aber viel weniger Speicher als entsprechende switch-Bloecke. +// Die Umrechnung von Fehlercodes muss nicht schnell sein, daher auch keine +// binaere Suche bei VB-Error -> SFX-Error. + +// Neue Fehler-Codes auf alte, Sbx-Kompatible zurueckmappen +sal_uInt16 StarBASIC::GetVBErrorCode( SbError nError ) +{ + sal_uInt16 nRet = 0; + + if( SbiRuntime::isVBAEnabled() ) + { + switch( nError ) + { + case SbERR_BASIC_ARRAY_FIX: + return 10; + case SbERR_BASIC_STRING_OVERFLOW: + return 14; + case SbERR_BASIC_EXPR_TOO_COMPLEX: + return 16; + case SbERR_BASIC_OPER_NOT_PERFORM: + return 17; + case SbERR_BASIC_TOO_MANY_DLL: + return 47; + case SbERR_BASIC_LOOP_NOT_INIT: + return 92; + default: + nRet = 0; + } + } + + // Suchschleife + const SFX_VB_ErrorItem* pErrItem; + sal_uInt16 nIndex = 0; + do + { + pErrItem = SFX_VB_ErrorTab + nIndex; + if( pErrItem->nErrorSFX == nError ) + { + nRet = pErrItem->nErrorVB; + break; + } + nIndex++; + } + while( pErrItem->nErrorVB != 0xFFFF ); // bis End-Marke + return nRet; +} + +SbError StarBASIC::GetSfxFromVBError( sal_uInt16 nError ) +{ + SbError nRet = 0L; + + if( SbiRuntime::isVBAEnabled() ) + { + switch( nError ) + { + case 1: + case 2: + case 4: + case 8: + case 12: + case 73: + return 0L; + case 10: + return SbERR_BASIC_ARRAY_FIX; + case 14: + return SbERR_BASIC_STRING_OVERFLOW; + case 16: + return SbERR_BASIC_EXPR_TOO_COMPLEX; + case 17: + return SbERR_BASIC_OPER_NOT_PERFORM; + case 47: + return SbERR_BASIC_TOO_MANY_DLL; + case 92: + return SbERR_BASIC_LOOP_NOT_INIT; + default: + nRet = 0L; + } + } + const SFX_VB_ErrorItem* pErrItem; + sal_uInt16 nIndex = 0; + do + { + pErrItem = SFX_VB_ErrorTab + nIndex; + if( pErrItem->nErrorVB == nError ) + { + nRet = pErrItem->nErrorSFX; + break; + } + else if( pErrItem->nErrorVB > nError ) + break; // kann nicht mehr gefunden werden + + nIndex++; + } + while( pErrItem->nErrorVB != 0xFFFF ); // bis End-Marke + return nRet; +} + +// Error- / Break-Daten setzen +void StarBASIC::SetErrorData +( SbError nCode, sal_uInt16 nLine, sal_uInt16 nCol1, sal_uInt16 nCol2 ) +{ + SbiGlobals& aGlobals = *GetSbData(); + aGlobals.nCode = nCode; + aGlobals.nLine = nLine; + aGlobals.nCol1 = nCol1; + aGlobals.nCol2 = nCol2; +} + +//---------------------------------------------------------------- +// Hilfsklasse zum Zugriff auf String SubResourcen einer Resource. +// Quelle: sfx2\source\doc\docfile.cxx (TLX) +struct BasicStringList_Impl : private Resource +{ + ResId aResId; + + BasicStringList_Impl( ResId& rErrIdP, sal_uInt16 nId) + : Resource( rErrIdP ),aResId(nId, *rErrIdP.GetResMgr() ){} + ~BasicStringList_Impl() { FreeResource(); } + + String GetString(){ return String( aResId ); } + sal_Bool IsErrorTextAvailable( void ) + { return IsAvailableRes(aResId.SetRT(RSC_STRING)); } +}; +//---------------------------------------------------------------- + +// #60175 Flag, das bei Basic-Fehlern das Anziehen der SFX-Resourcen verhindert +static sal_Bool bStaticSuppressSfxResource = sal_False; + +void StarBASIC::StaticSuppressSfxResource( sal_Bool bSuppress ) +{ + bStaticSuppressSfxResource = bSuppress; +} + +// Hack for #83750, use bStaticSuppressSfxResource as setup flag +sal_Bool runsInSetup( void ) +{ + return bStaticSuppressSfxResource; +} + + +void StarBASIC::MakeErrorText( SbError nId, const String& aMsg ) +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + if( bStaticSuppressSfxResource ) + { + GetSbData()->aErrMsg = String( RTL_CONSTASCII_USTRINGPARAM("No resource: Error message not available") ); + return; + } + + sal_uInt16 nOldID = GetVBErrorCode( nId ); + + // Hilfsklasse instanzieren + BasResId aId( RID_BASIC_START ); + BasicStringList_Impl aMyStringList( aId, sal_uInt16(nId & ERRCODE_RES_MASK) ); + + if( aMyStringList.IsErrorTextAvailable() ) + { + // Merge Message mit Zusatztext + String aMsg1 = aMyStringList.GetString(); + // Argument-Platzhalter durch %s ersetzen + String aSrgStr( RTL_CONSTASCII_USTRINGPARAM("$(ARG1)") ); + sal_uInt16 nResult = aMsg1.Search( aSrgStr ); + + if( nResult != STRING_NOTFOUND ) + { + aMsg1.Erase( nResult, aSrgStr.Len() ); + aMsg1.Insert( aMsg, nResult ); + } + GetSbData()->aErrMsg = aMsg1; + } + else if( nOldID != 0 ) + { + String aStdMsg( RTL_CONSTASCII_USTRINGPARAM("Fehler ") ); + aStdMsg += String::CreateFromInt32( nOldID); + aStdMsg += String( RTL_CONSTASCII_USTRINGPARAM(": Kein Fehlertext verfuegbar!") ); + GetSbData()->aErrMsg = aStdMsg; + } + else + GetSbData()->aErrMsg = String::EmptyString(); + +} + +sal_Bool StarBASIC::CError + ( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + // Compiler-Fehler waehrend der Laufzeit -> Programm anhalten + if( IsRunning() ) + { + // #109018 Check if running Basic is affected + StarBASIC* pStartedBasic = pINST->GetBasic(); + if( pStartedBasic != this ) + return sal_False; + + Stop(); + } + + // Flag setzen, damit GlobalRunInit den Fehler mitbekommt + GetSbData()->bGlobalInitErr = sal_True; + + // Fehlertext basteln + MakeErrorText( code, rMsg ); + + // Umsetzung des Codes fuer String-Transport in SFX-Error + if( rMsg.Len() ) + code = (sal_uIntPtr)*new StringErrorInfo( code, String(rMsg) ); + + SetErrorData( code, l, c1, c2 ); + GetSbData()->bCompiler = sal_True; + sal_Bool bRet; + if( GetSbData()->aErrHdl.IsSet() ) + bRet = (sal_Bool) GetSbData()->aErrHdl.Call( this ); + else + bRet = ErrorHdl(); + GetSbData()->bCompiler = sal_False; // nur sal_True fuer Error-Handler + return bRet; +} + +sal_Bool StarBASIC::RTError + ( SbError code, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) +{ + return RTError( code, String(), l, c1, c2 ); +} + +sal_Bool StarBASIC::RTError( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + SbError c = code; + if( (c & ERRCODE_CLASS_MASK) == ERRCODE_CLASS_COMPILER ) + c = 0; + MakeErrorText( c, rMsg ); + + // Umsetzung des Codes fuer String-Transport in SFX-Error + if( rMsg.Len() ) + { + // very confusing, even though MakeErrorText sets up the error text + // seems that this is not used ( if rMsg already has content ) + // In the case of VBA MakeErrorText also formats the error to be alittle more + // like vba ( adds an error number etc ) + if ( SbiRuntime::isVBAEnabled() && ( code == SbERR_BASIC_COMPAT ) ) + { + String aTmp = '\''; + aTmp += String::CreateFromInt32( SbxErrObject::getUnoErrObject()->getNumber() ); + aTmp += String( RTL_CONSTASCII_USTRINGPARAM("\'\n") ); + aTmp += GetSbData()->aErrMsg.Len() ? GetSbData()->aErrMsg : rMsg; + code = (sal_uIntPtr)*new StringErrorInfo( code, aTmp ); + } + else + code = (sal_uIntPtr)*new StringErrorInfo( code, String(rMsg) ); + } + + SetErrorData( code, l, c1, c2 ); + if( GetSbData()->aErrHdl.IsSet() ) + return (sal_Bool) GetSbData()->aErrHdl.Call( this ); + else + return ErrorHdl(); +} + +void StarBASIC::Error( SbError n ) +{ + Error( n, String() ); +} + +void StarBASIC::Error( SbError n, const String& rMsg ) +{ + if( pINST ) + pINST->Error( n, rMsg ); +} + +void StarBASIC::FatalError( SbError n ) +{ + if( pINST ) + pINST->FatalError( n ); +} + +void StarBASIC::FatalError( SbError _errCode, const String& _details ) +{ + if( pINST ) + pINST->FatalError( _errCode, _details ); +} + +SbError StarBASIC::GetErrBasic() +{ + if( pINST ) + return pINST->GetErr(); + else + return 0; +} + +// #66536 Zusatz-Message fuer RTL-Funktion Error zugreifbar machen +String StarBASIC::GetErrorMsg() +{ + if( pINST ) + return pINST->GetErrorMsg(); + else + return String(); +} + +sal_uInt16 StarBASIC::GetErl() +{ + if( pINST ) + return pINST->GetErl(); + else + return 0; +} + +sal_Bool __EXPORT StarBASIC::ErrorHdl() +{ + return (sal_Bool) ( aErrorHdl.IsSet() + ? aErrorHdl.Call( this ) : sal_False ); +} + +Link StarBASIC::GetGlobalErrorHdl() +{ + return GetSbData()->aErrHdl; +} + +void StarBASIC::SetGlobalErrorHdl( const Link& rLink ) +{ + GetSbData()->aErrHdl = rLink; +} + + +Link StarBASIC::GetGlobalBreakHdl() +{ + return GetSbData()->aBreakHdl; +} + +void StarBASIC::SetGlobalBreakHdl( const Link& rLink ) +{ + GetSbData()->aBreakHdl = rLink; +} + +SbxArrayRef StarBASIC::getUnoListeners( void ) +{ + if( !xUnoListeners.Is() ) + xUnoListeners = new SbxArray(); + return xUnoListeners; +} + + +/************************************************************************** +* +* Laden und Speichern +* +**************************************************************************/ + +sal_Bool StarBASIC::LoadData( SvStream& r, sal_uInt16 nVer ) +{ + if( !SbxObject::LoadData( r, nVer ) ) + return sal_False; + + // #95459 Delete dialogs, otherwise endless recursion + // in SbxVarable::GetType() if dialogs are accessed + sal_uInt16 nObjCount = pObjs->Count(); + SbxVariable** ppDeleteTab = new SbxVariable*[ nObjCount ]; + sal_uInt16 nObj; + + for( nObj = 0 ; nObj < nObjCount ; nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST( StarBASIC, pVar ); + ppDeleteTab[nObj] = pBasic ? NULL : pVar; + } + for( nObj = 0 ; nObj < nObjCount ; nObj++ ) + { + SbxVariable* pVar = ppDeleteTab[nObj]; + if( pVar ) + pObjs->Remove( pVar ); + } + delete[] ppDeleteTab; + + sal_uInt16 nMod; + pModules->Clear(); + r >> nMod; + for( sal_uInt16 i = 0; i < nMod; i++ ) + { + SbModule* pMod = (SbModule*) SbxBase::Load( r ); + if( !pMod ) + return sal_False; + else if( pMod->ISA(SbJScriptModule) ) + { + // Ref zuweisen, damit pMod deleted wird + SbModuleRef xRef = pMod; + } + else + { + pMod->SetParent( this ); + pModules->Put( pMod, i ); + } + } + // HACK fuer SFX-Mist! + SbxVariable* p = Find( String( RTL_CONSTASCII_USTRINGPARAM("FALSE") ), SbxCLASS_PROPERTY ); + if( p ) + Remove( p ); + p = Find( String( RTL_CONSTASCII_USTRINGPARAM("TRUE") ), SbxCLASS_PROPERTY ); + if( p ) + Remove( p ); + // Ende des Hacks! + // Suche ueber StarBASIC ist immer global + DBG_ASSERT( IsSet( SBX_GBLSEARCH ), "Basic ohne GBLSEARCH geladen" ); + SetFlag( SBX_GBLSEARCH ); + return sal_True; +} + +sal_Bool StarBASIC::StoreData( SvStream& r ) const +{ + if( !SbxObject::StoreData( r ) ) + return sal_False; + r << (sal_uInt16) pModules->Count(); + for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( !p->Store( r ) ) + return sal_False; + } + return sal_True; +} + +sal_Bool StarBASIC::LoadOldModules( SvStream& ) +{ + return sal_False; +} + +bool StarBASIC::GetUNOConstant( const sal_Char* _pAsciiName, ::com::sun::star::uno::Any& aOut ) +{ + bool bRes = false; + ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); + SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( Find( sVarName, SbxCLASS_DONTCARE ) ); + if ( pGlobs ) + { + aOut = pGlobs->getUnoAny(); + bRes = true; + } + return bRes; +} + +Reference< frame::XModel > StarBASIC::GetModelFromBasic( SbxObject* pBasic ) +{ + OSL_PRECOND( pBasic != NULL, "getModelFromBasic: illegal call!" ); + if ( !pBasic ) + return NULL; + + // look for the ThisComponent variable, first in the parent (which + // might be the document's Basic), then in the parent's parent (which might be + // the application Basic) + const ::rtl::OUString sThisComponent( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ); + SbxVariable* pThisComponent = NULL; + + SbxObject* pLookup = pBasic->GetParent(); + while ( pLookup && !pThisComponent ) + { + pThisComponent = pLookup->Find( sThisComponent, SbxCLASS_OBJECT ); + pLookup = pLookup->GetParent(); + } + if ( !pThisComponent ) + { + OSL_TRACE("Failed to get ThisComponent"); + // the application Basic, at the latest, should have this variable + return NULL; + } + + Any aThisComponentAny( sbxToUnoValue( pThisComponent ) ); + Reference< frame::XModel > xModel( aThisComponentAny, UNO_QUERY ); + if ( !xModel.is() ) + { + // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller. + Reference< frame::XController > xController( aThisComponentAny, UNO_QUERY ); + if ( xController.is() ) + xModel = xController->getModel(); + } + + if ( !xModel.is() ) + return NULL; + +#if OSL_DEBUG_LEVEL > 0 + OSL_TRACE("Have model ThisComponent points to url %s", + ::rtl::OUStringToOString( xModel->getURL(), + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); +#endif + + return xModel; +} + + +//======================================================================== +// #118116 Implementation Collection object + +TYPEINIT1(BasicCollection,SbxObject) + +static const char pCountStr[] = "Count"; +static const char pAddStr[] = "Add"; +static const char pItemStr[] = "Item"; +static const char pRemoveStr[] = "Remove"; +static sal_uInt16 nCountHash = 0, nAddHash, nItemHash, nRemoveHash; + +SbxInfoRef BasicCollection::xAddInfo = NULL; +SbxInfoRef BasicCollection::xItemInfo = NULL; + +BasicCollection::BasicCollection( const XubString& rClass ) + : SbxObject( rClass ) +{ + if( !nCountHash ) + { + nCountHash = MakeHashCode( String::CreateFromAscii( pCountStr ) ); + nAddHash = MakeHashCode( String::CreateFromAscii( pAddStr ) ); + nItemHash = MakeHashCode( String::CreateFromAscii( pItemStr ) ); + nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemoveStr ) ); + } + Initialize(); + +} + +BasicCollection::~BasicCollection() +{} + +void BasicCollection::Clear() +{ + SbxObject::Clear(); + Initialize(); +} + +void BasicCollection::Initialize() +{ + xItemArray = new SbxArray(); + SetType( SbxOBJECT ); + SetFlag( SBX_FIXED ); + ResetFlag( SBX_WRITE ); + SbxVariable* p; + p = Make( String::CreateFromAscii( pCountStr ), SbxCLASS_PROPERTY, SbxINTEGER ); + p->ResetFlag( SBX_WRITE ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pAddStr ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pItemStr ), SbxCLASS_METHOD, SbxVARIANT ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pRemoveStr ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + if ( !xAddInfo.Is() ) + { + xAddInfo = new SbxInfo; + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Item") ), SbxVARIANT, SBX_READ ); + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Key") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Before") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("After") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); + } + if ( !xItemInfo.Is() ) + { + xItemInfo = new SbxInfo; + xItemInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Index") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL); + } +} + +SbxVariable* BasicCollection::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pFind = SbxObject::Find( rName, t ); + return pFind; +} + +void BasicCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1, + const SfxHint& rHint, const TypeId& rId2 ) +{ + const SbxHint* p = PTR_CAST(SbxHint,&rHint); + if( p ) + { + sal_uIntPtr nId = p->GetId(); + sal_Bool bRead = sal_Bool( nId == SBX_HINT_DATAWANTED ); + sal_Bool bWrite = sal_Bool( nId == SBX_HINT_DATACHANGED ); + sal_Bool bRequestInfo = sal_Bool( nId == SBX_HINT_INFOWANTED ); + SbxVariable* pVar = p->GetVar(); + SbxArray* pArg = pVar->GetParameters(); + XubString aVarName( pVar->GetName() ); + if( bRead || bWrite ) + { + if( pVar->GetHashCode() == nCountHash + && aVarName.EqualsIgnoreCaseAscii( pCountStr ) ) + pVar->PutLong( xItemArray->Count32() ); + else if( pVar->GetHashCode() == nAddHash + && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) + CollAdd( pArg ); + else if( pVar->GetHashCode() == nItemHash + && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) + CollItem( pArg ); + else if( pVar->GetHashCode() == nRemoveHash + && aVarName.EqualsIgnoreCaseAscii( pRemoveStr ) ) + CollRemove( pArg ); + else + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); + return; + } + else if ( bRequestInfo ) + { + if( pVar->GetHashCode() == nAddHash + && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) + pVar->SetInfo( xAddInfo ); + else if( pVar->GetHashCode() == nItemHash + && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) + pVar->SetInfo( xItemInfo ); + } + } + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); +} + +sal_Int32 BasicCollection::implGetIndex( SbxVariable* pIndexVar ) +{ + sal_Int32 nIndex = -1; + if( pIndexVar->GetType() == SbxSTRING ) + nIndex = implGetIndexForName( pIndexVar->GetString() ); + else + nIndex = pIndexVar->GetLong() - 1; + return nIndex; +} + +sal_Int32 BasicCollection::implGetIndexForName( const String& rName ) +{ + sal_Int32 nIndex = -1; + sal_Int32 nCount = xItemArray->Count32(); + sal_Int32 nNameHash = MakeHashCode( rName ); + for( sal_Int32 i = 0 ; i < nCount ; i++ ) + { + SbxVariable* pVar = xItemArray->Get32( i ); + if( pVar->GetHashCode() == nNameHash && + pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) + { + nIndex = i; + break; + } + } + return nIndex; +} + +void BasicCollection::CollAdd( SbxArray* pPar_ ) +{ + sal_uInt16 nCount = pPar_->Count(); + if( nCount < 2 || nCount > 5 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + + SbxVariable* pItem = pPar_->Get(1); + if( pItem ) + { + int nNextIndex; + if( nCount < 4 ) + { + nNextIndex = xItemArray->Count(); + } + else + { + SbxVariable* pBefore = pPar_->Get(3); + if( nCount == 5 ) + { + if( !( pBefore->IsErr() || ( pBefore->GetType() == SbxEMPTY ) ) ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + SbxVariable* pAfter = pPar_->Get(4); + sal_Int32 nAfterIndex = implGetIndex( pAfter ); + if( nAfterIndex == -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + nNextIndex = nAfterIndex + 1; + } + else // if( nCount == 4 ) + { + sal_Int32 nBeforeIndex = implGetIndex( pBefore ); + if( nBeforeIndex == -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + nNextIndex = nBeforeIndex; + } + } + + SbxVariableRef pNewItem = new SbxVariable( *pItem ); + if( nCount >= 3 ) + { + SbxVariable* pKey = pPar_->Get(2); + if( !( pKey->IsErr() || ( pKey->GetType() == SbxEMPTY ) ) ) + { + if( pKey->GetType() != SbxSTRING ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + String aKey = pKey->GetString(); + if( implGetIndexForName( aKey ) != -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + pNewItem->SetName( aKey ); + } + } + pNewItem->SetFlag( SBX_READWRITE ); + xItemArray->Insert32( pNewItem, nNextIndex ); + } + else + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } +} + +void BasicCollection::CollItem( SbxArray* pPar_ ) +{ + if( pPar_->Count() != 2 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + SbxVariable* pRes = NULL; + SbxVariable* p = pPar_->Get( 1 ); + sal_Int32 nIndex = implGetIndex( p ); + if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() ) + pRes = xItemArray->Get32( nIndex ); + if( !pRes ) + SetError( SbERR_BAD_ARGUMENT ); + else + *(pPar_->Get(0)) = *pRes; +} + +void BasicCollection::CollRemove( SbxArray* pPar_ ) +{ + if( pPar_ == NULL || pPar_->Count() != 2 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + + SbxVariable* p = pPar_->Get( 1 ); + sal_Int32 nIndex = implGetIndex( p ); + if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() ) + xItemArray->Remove32( nIndex ); + else + SetError( SbERR_BAD_ARGUMENT ); +} + diff --git a/basic/source/classes/sb.src b/basic/source/classes/sb.src new file mode 100644 index 000000000000..73cc1c3a0b2c --- /dev/null +++ b/basic/source/classes/sb.src @@ -0,0 +1,681 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#define __RSC +#ifndef _ERRCODE_HXX //autogen +#include <tools/errcode.hxx> +#endif +#include "sb.hrc" +#include <basic/sberrors.hxx> + +Resource RID_BASIC_START +{ + String SbERR_SYNTAX & ERRCODE_RES_MASK + { + Text [ en-US ] = "Syntax error." ; + }; + String SbERR_NO_GOSUB & ERRCODE_RES_MASK + { + Text [ en-US ] = "Return without Gosub." ; + }; + String SbERR_REDO_FROM_START & ERRCODE_RES_MASK + { + Text [ en-US ] = "Incorrect entry; please retry." ; + }; + String SbERR_BAD_ARGUMENT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiger Prozeduraufruf : Ungltiger Prozeduraufruf */ + Text [ en-US ] = "Invalid procedure call." ; + }; + String SbERR_MATH_OVERFLOW & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? šberlauf : Überlauf */ + Text [ en-US ] = "Overflow." ; + }; + String SbERR_NO_MEMORY & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Nicht gen³gend Speicher : Nicht gengend Speicher */ + Text [ en-US ] = "Not enough memory." ; + }; + String SbERR_ALREADY_DIM & ERRCODE_RES_MASK + { + Text [ en-US ] = "Array already dimensioned." ; + }; + String SbERR_OUT_OF_RANGE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Index au˜erhalb des definierten Bereichs : Index auÿerhalb des definierten Bereichs */ + Text [ en-US ] = "Index out of defined range." ; + }; + String SbERR_DUPLICATE_DEF & ERRCODE_RES_MASK + { + Text [ en-US ] = "Duplicate definition." ; + }; + String SbERR_ZERODIV & ERRCODE_RES_MASK + { + Text [ en-US ] = "Division by zero." ; + }; + String SbERR_VAR_UNDEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable not defined." ; + }; + String SbERR_CONVERSION & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Datentypen unvertrõglich : Datentypen unvertr§glich */ + Text [ en-US ] = "Data type mismatch." ; + }; + String SbERR_BAD_PARAMETER & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiger Parameter : Ungltiger Parameter */ + Text [ en-US ] = "Invalid parameter." ; + }; + String SbERR_USER_ABORT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Process interrupted by user." ; + }; + String SbERR_BAD_RESUME & ERRCODE_RES_MASK + { + Text [ en-US ] = "Resume without error." ; + }; + String SbERR_STACK_OVERFLOW & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Nicht gen³gend Stapelspeicher : Nicht gengend Stapelspeicher */ + Text [ en-US ] = "Not enough stack memory." ; + }; + String SbERR_PROC_UNDEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Sub-procedure or function procedure not defined." ; + }; + String SbERR_BAD_DLL_LOAD & ERRCODE_RES_MASK + { + Text [ en-US ] = "Error loading DLL file." ; + }; + String SbERR_BAD_DLL_CALL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Wrong DLL call convention." ; + }; + String SbERR_INTERNAL_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "Internal error $(ARG1)." ; + }; + String SbERR_BAD_CHANNEL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Invalid file name or file number." ; + }; + String SbERR_FILE_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "File not found." ; + }; + String SbERR_BAD_FILE_MODE & ERRCODE_RES_MASK + { + Text [ en-US ] = "Incorrect file mode." ; + }; + String SbERR_FILE_ALREADY_OPEN & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Datei bereits ge÷ffnet : Datei bereits ge”ffnet */ + Text [ en-US ] = "File already open." ; + }; + String SbERR_IO_ERROR & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Gerõte-E/A-Fehler : Ger§te-E/A-Fehler */ + Text [ en-US ] = "Device I/O error." ; + }; + String SbERR_FILE_EXISTS & ERRCODE_RES_MASK + { + Text [ en-US ] = "File already exists." ; + }; + String SbERR_BAD_RECORD_LENGTH & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Falsche Datensatzlõnge : Falsche Datensatzl§nge */ + Text [ en-US ] = "Incorrect record length." ; + }; + String SbERR_DISK_FULL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Disk or hard drive full." ; + }; + String SbERR_READ_PAST_EOF & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Lesen ³ber das Ende der Datei hinaus : Lesen ber das Ende der Datei hinaus */ + Text [ en-US ] = "Reading exceeds EOF." ; + }; + String SbERR_BAD_RECORD_NUMBER & ERRCODE_RES_MASK + { + Text [ en-US ] = "Incorrect record number." ; + }; + String SbERR_TOO_MANY_FILES & ERRCODE_RES_MASK + { + Text [ en-US ] = "Too many files." ; + }; + String SbERR_NO_DEVICE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Gerõt nicht verf³gbar : Ger§t nicht verfgbar */ + Text [ en-US ] = "Device not available." ; + }; + String SbERR_ACCESS_DENIED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Access denied." ; + }; + String SbERR_NOT_READY & ERRCODE_RES_MASK + { + Text [ en-US ] = "Disk not ready." ; + }; + String SbERR_NOT_IMPLEMENTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Not implemented." ; + }; + String SbERR_DIFFERENT_DRIVE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Umbenennen auf verschiedenen Laufwerken nicht m÷glich : Umbenennen auf verschiedenen Laufwerken nicht m”glich */ + Text [ en-US ] = "Renaming on different drives impossible." ; + }; + String SbERR_ACCESS_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "Path/File access error." ; + }; + String SbERR_PATH_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Path not found." ; + }; + String SbERR_NO_OBJECT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object variable not set." ; + }; + String SbERR_BAD_PATTERN & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Zeichenfolgenmuster unzulõssig : Zeichenfolgenmuster unzul§ssig */ + Text [ en-US ] = "Invalid string pattern." ; + }; + String SBERR_IS_NULL & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Verwendung von Null unzulõssig : Verwendung von Null unzul§ssig */ + Text [ en-US ] = "Use of zero not permitted." ; + }; + String SbERR_DDE_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE Error." ; + }; + String SbERR_DDE_WAITINGACK & ERRCODE_RES_MASK + { + Text [ en-US ] = "Awaiting response to DDE connection." ; + }; + String SbERR_DDE_OUTOFCHANNELS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Keine freien DDE-Kanõle : Keine freien DDE-Kan§le */ + Text [ en-US ] = "No DDE channels available." ; + }; + String SbERR_DDE_NO_RESPONSE & ERRCODE_RES_MASK + { + Text [ en-US ] = "No application responded to DDE connect initiation." ; + }; + String SbERR_DDE_MULT_RESPONSES & ERRCODE_RES_MASK + { + Text [ en-US ] = "Too many applications responded to DDE connect initiation." ; + }; + String SbERR_DDE_CHANNEL_LOCKED & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE channel locked." ; + }; + String SbERR_DDE_NOTPROCESSED & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Fremdapplikation kann DDE-Operation nicht ausf³hren : Fremdapplikation kann DDE-Operation nicht ausfhren */ + Text [ en-US ] = "External application cannot execute DDE operation." ; + }; + String SbERR_DDE_TIMEOUT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Zeit³berschreitung wõhrend des Wartens auf DDE-Antwort : Zeitberschreitung w§hrend des Wartens auf DDE-Antwort */ + Text [ en-US ] = "Timeout while waiting for DDE response." ; + }; + String SbERR_DDE_USER_INTERRUPT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Benutzer dr³ckte ESCAPE wõhrend der DDE-Operation : Benutzer drckte ESCAPE w§hrend der DDE-Operation */ + Text [ en-US ] = "User pressed ESCAPE during DDE operation." ; + }; + String SbERR_DDE_BUSY & ERRCODE_RES_MASK + { + Text [ en-US ] = "External application busy." ; + }; + String SbERR_DDE_NO_DATA & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE operation without data." ; + }; + String SbERR_DDE_WRONG_DATA_FORMAT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Data are in wrong format." ; + }; + String SbERR_DDE_PARTNER_QUIT & ERRCODE_RES_MASK + { + Text [ en-US ] = "External application has been terminated." ; + }; + String SbERR_DDE_CONV_CLOSED & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? DDE-Verbindung ist unterbrochen oder geõndert worden : DDE-Verbindung ist unterbrochen oder ge§ndert worden */ + Text [ en-US ] = "DDE connection interrupted or modified." ; + }; + String SbERR_DDE_NO_CHANNEL & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE method invoked with no channel open." ; + }; + String SbERR_DDE_INVALID_LINK & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiges DDE-Linkformat : Ungltiges DDE-Linkformat */ + Text [ en-US ] = "Invalid DDE link format." ; + }; + String SbERR_DDE_QUEUE_OVERFLOW & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE message has been lost." ; + }; + String SbERR_DDE_LINK_ALREADY_EST & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Paste Link bereits durchgef³hrt : Paste Link bereits durchgefhrt */ + Text [ en-US ] = "Paste link already performed." ; + }; + String SbERR_DDE_LINK_INV_TOPIC & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? LinkMode kann wegen ung³ltigen Link-Topics nicht gesetzt werden : LinkMode kann wegen ungltigen Link-Topics nicht gesetzt werden */ + Text [ en-US ] = "Link mode cannot be set due to invalid link topic." ; + }; + String SbERR_DDE_DLL_NOT_FOUND & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? F³r DDE wird DDEML.DLL ben÷tigt : Fr DDE wird DDEML.DLL ben”tigt */ + Text [ en-US ] = "DDE requires the DDEML.DLL file." ; + }; + String SbERR_CANNOT_LOAD & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Das Modul kann nicht geladen werden, ung³ltiges Format : Das Modul kann nicht geladen werden, ungltiges Format */ + Text [ en-US ] = "Module cannot be loaded; invalid format." ; + }; + String SbERR_BAD_INDEX & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiger Objektindex : Ungltiger Objektindex */ + Text [ en-US ] = "Invalid object index." ; + }; + String SbERR_NO_ACTIVE_OBJECT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Objekt ist nicht verf³gbar : Objekt ist nicht verfgbar */ + Text [ en-US ] = "Object is not available." ; + }; + String SbERR_BAD_PROP_VALUE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Falscher Wert f³r Eigenschaft : Falscher Wert fr Eigenschaft */ + Text [ en-US ] = "Incorrect property value." ; + }; + String SbERR_PROP_READONLY & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Eigenschaft ist schreibgesch³tzt : Eigenschaft ist schreibgeschtzt */ + Text [ en-US ] = "This property is read-only." ; + }; + String SbERR_PROP_WRITEONLY & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Eigenschaft ist lesegesch³tzt : Eigenschaft ist lesegeschtzt */ + Text [ en-US ] = "This property is write only." ; + }; + String SbERR_INVALID_OBJECT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltige Objektreferenz : Ungltige Objektreferenz */ + Text [ en-US ] = "Invalid object reference." ; + }; + String SbERR_NO_METHOD & ERRCODE_RES_MASK + { + Text [ en-US ] = "Property or method not found: $(ARG1)." ; + }; + String SbERR_NEEDS_OBJECT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object required." ; + }; + String SbERR_INVALID_USAGE_OBJECT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Invalid use of an object." ; + }; + String SbERR_NO_OLE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? OLE-Automatisierung wird von diesem Objekt nicht unterst³tzt : OLE-Automatisierung wird von diesem Objekt nicht untersttzt */ + Text [ en-US ] = "OLE Automation is not supported by this object." ; + }; + String SbERR_BAD_METHOD & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Objekt unterst³tzt diese Eigenschaft oder Methode nicht : Objekt untersttzt diese Eigenschaft oder Methode nicht */ + Text [ en-US ] = "This property or method is not supported by the object." ; + }; + String SbERR_OLE_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "OLE Automation Error." ; + }; + String SbERR_BAD_ACTION & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Diese Aktion wird vom angegebenen Objekt nicht unterst³tzt : Diese Aktion wird vom angegebenen Objekt nicht untersttzt */ + Text [ en-US ] = "This action is not supported by given object." ; + }; + String SbERR_NO_NAMED_ARGS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Benannte Argumente werden vom angegebenen Objekt nicht unterst³tzt : Benannte Argumente werden vom angegebenen Objekt nicht untersttzt */ + Text [ en-US ] = "Named arguments are not supported by given object." ; + }; + String SbERR_BAD_LOCALE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Das aktuelle Gebietsschema wird vom angegebenen Objekt nicht unterst³tzt : Das aktuelle Gebietsschema wird vom angegebenen Objekt nicht untersttzt */ + Text [ en-US ] = "The current locale setting is not supported by the given object." ; + }; + String SbERR_NAMED_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Named argument not found." ; + }; + String SbERR_NOT_OPTIONAL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Argument is not optional." ; + }; + String SbERR_WRONG_ARGS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Invalid number of arguments." ; + }; + String SbERR_NOT_A_COLL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object is not a list." ; + }; + String SbERR_BAD_ORDINAL & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ordnungszahl ung³ltig : Ordnungszahl ungltig */ + Text [ en-US ] = "Invalid ordinal number." ; + }; + String SbERR_DLLPROC_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Specified DLL function not found." ; + }; + String SbERR_BAD_CLIPBD_FORMAT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiges Clipboard-Format : Ungltiges Clipboard-Format */ + Text [ en-US ] = "Invalid clipboard format." ; + }; + String SbERR_PROPERTY_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object does not have this property." ; + }; + String SbERR_METHOD_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object does not have this method." ; + }; + String SbERR_ARG_MISSING & ERRCODE_RES_MASK + { + Text [ en-US ] = "Required argument lacking." ; + }; + String SbERR_BAD_NUMBER_OF_ARGS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltige Anzahl von Argumenten : Ungltige Anzahl von Argumenten */ + Text [ en-US ] = "Invalid number of arguments." ; + }; + String SbERR_METHOD_FAILED & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Fehler in Ausf³hrung einer Methode : Fehler in Ausfhrung einer Methode */ + Text [ en-US ] = "Error executing a method." ; + }; + String SbERR_SETPROP_FAILED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unable to set property." ; + }; + String SbERR_GETPROP_FAILED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unable to determine property." ; + }; + // Compiler errors. These are not runtime errors. + String SbERR_UNEXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unexpected symbol: $(ARG1)." ; + }; + String SbERR_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Expected: $(ARG1)." ; + }; + String SbERR_SYMBOL_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Symbol expected." ; + }; + String SbERR_VAR_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable expected." ; + }; + String SbERR_LABEL_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Label expected." ; + }; + String SbERR_LVALUE_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Value cannot be applied." ; + }; + String SbERR_VAR_DEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable $(ARG1) already defined." ; + }; + String SbERR_PROC_DEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Sub procedure or function procedure $(ARG1) already defined." ; + }; + String SbERR_LABEL_DEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Label $(ARG1) already defined." ; + }; + String SbERR_UNDEF_VAR & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable $(ARG1) not found." ; + }; + String SbERR_UNDEF_ARRAY & ERRCODE_RES_MASK + { + Text [ en-US ] = "Array or procedure $(ARG1) not found." ; + }; + String SbERR_UNDEF_PROC & ERRCODE_RES_MASK + { + Text [ en-US ] = "Procedure $(ARG1) not found." ; + }; + String SbERR_UNDEF_LABEL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Label $(ARG1) undefined." ; + }; + String SbERR_UNDEF_TYPE & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unknown data type $(ARG1)." ; + }; + String SbERR_BAD_EXIT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Exit $(ARG1) expected." ; + }; + String SbERR_BAD_BLOCK & ERRCODE_RES_MASK + { + Text [ en-US ] = "Statement block still open: $(ARG1) missing." ; + }; + String SbERR_BAD_BRACKETS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Parentheses do not match." ; + }; + String SbERR_BAD_DECLARATION & ERRCODE_RES_MASK + { + Text [ en-US ] = "Symbol $(ARG1) already defined differently." ; + }; + String SbERR_BAD_PARAMETERS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Parameters do not correspond to procedure." ; + }; + String SbERR_BAD_CHAR_IN_NUMBER & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiges Zeichen in Zahl : Ungltiges Zeichen in Zahl */ + Text [ en-US ] = "Invalid character in number." ; + }; + String SbERR_MUST_HAVE_DIMS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Array mu˜ dimensioniert werden : Array muÿ dimensioniert werden */ + Text [ en-US ] = "Array must be dimensioned." ; + }; + String SbERR_NO_IF & ERRCODE_RES_MASK + { + Text [ en-US ] = "Else/Endif without If." ; + }; + String SbERR_NOT_IN_SUBR & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? $(ARG1) innerhalb einer Prozedur unzulõssig : $(ARG1) innerhalb einer Prozedur unzul§ssig */ + Text [ en-US ] = "$(ARG1) not allowed within a procedure." ; + }; + String SbERR_NOT_IN_MAIN & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? $(ARG1) au˜erhalb einer Prozedur unzulõssig : $(ARG1) auÿerhalb einer Prozedur unzul§ssig */ + Text [ en-US ] = "$(ARG1) not allowed outside a procedure." ; + }; + String SbERR_WRONG_DIMS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Dimension specifications do not match." ; + }; + String SbERR_BAD_OPTION & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unknown option: $(ARG1)." ; + }; + String SbERR_CONSTANT_REDECLARED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Constant $(ARG1) redefined." ; + }; + String SbERR_PROG_TOO_LARGE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Programm ist zu gro˜ : Programm ist zu groÿ */ + Text [ en-US ] = "Program too large." ; + }; + String SbERR_NO_STRINGS_ARRAYS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Strings oder Arrays unzulõssig : Strings oder Arrays unzul§ssig */ + Text [ en-US ] = "Strings or arrays not permitted." ; + }; + String ERRCODE_BASIC_EXCEPTION & ERRCODE_RES_MASK + { + Text [ en-US ] = "An exception occurred $(ARG1)." ; + }; + String ERRCODE_BASIC_ARRAY_FIX & ERRCODE_RES_MASK + { + Text [ en-US ] = "This array is fixed or temporarily locked." ; + }; + String ERRCODE_BASIC_STRING_OVERFLOW & ERRCODE_RES_MASK + { + Text [ en-US ] = "Out of string space." ; + }; + String ERRCODE_BASIC_EXPR_TOO_COMPLEX & ERRCODE_RES_MASK + { + Text [ en-US ] = "Expression Too Complex." ; + }; + String ERRCODE_BASIC_OPER_NOT_PERFORM & ERRCODE_RES_MASK + { + Text [ en-US ] = "Can't perform requested operation." ; + }; + String ERRCODE_BASIC_TOO_MANY_DLL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Too many DLL application clients." ; + }; + String ERRCODE_BASIC_LOOP_NOT_INIT & ERRCODE_RES_MASK + { + Text [ en-US ] = "For loop not initialized." ; + }; + String ERRCODE_BASIC_COMPAT & ERRCODE_RES_MASK + { + Text [ en-US ] = "$(ARG1)" ; + }; +}; + // Hinweis: IDS_SBERR_TERMINATED = IDS_SBERR_START+2000. +String IDS_SBERR_TERMINATED +{ + Text [ en-US ] = "The macro running has been interrupted" ; +}; +String IDS_SBERR_STOREREF +{ + Text [ en-US ] = "Reference will not be saved: "; +}; +String ERRCODE_BASMGR_LIBLOAD & ERRCODE_RES_MASK +{ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1)'' */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1)'' */ + Text [ en-US ] = "Error loading library '$(ARG1)'." ; +}; +String ERRCODE_BASMGR_LIBSAVE & ERRCODE_RES_MASK +{ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1)'' */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1)'' */ + Text [ en-US ] = "Error saving library: '$(ARG1)'." ; +}; +String ERRCODE_BASMGR_MGROPEN & ERRCODE_RES_MASK +{ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + Text [ en-US ] = "The BASIC from the file '$(ARG1)' could not be initialized." ; +}; +String ERRCODE_BASMGR_MGRSAVE & ERRCODE_RES_MASK +{ + Text [ en-US ] = "Error saving BASIC: '$(ARG1)'." ; +}; +String ERRCODE_BASMGR_REMOVELIB & ERRCODE_RES_MASK +{ + Text [ en-US ] = "Error removing library." ; +}; +String ERRCODE_BASMGR_UNLOADLIB & ERRCODE_RES_MASK +{ + Text [ en-US ] = "The library could not be removed from memory." ; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/basic/source/classes/sbintern.cxx b/basic/source/classes/sbintern.cxx new file mode 100644 index 000000000000..2b1f32e474d5 --- /dev/null +++ b/basic/source/classes/sbintern.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/shl.hxx> + +#include "sbintern.hxx" +#include "sbunoobj.hxx" +#include "token.hxx" // Tokenizer +#include "symtbl.hxx" // Symbolverwaltung +#include "parser.hxx" // Parser +#include "codegen.hxx" // Code-Generator +#include <basic/basmgr.hxx> + +SV_IMPL_PTRARR(SbErrorStack, SbErrorStackEntry*) + +SbiGlobals* GetSbData() +{ + SbiGlobals** pp = (SbiGlobals**) ::GetAppData( SHL_SBC ); + SbiGlobals* p = *pp; + if( !p ) + p = *pp = new SbiGlobals; + return p; +} + +SbiGlobals::SbiGlobals() +{ + pInst = NULL; + pMod = NULL; + pSbFac= NULL; + pUnoFac = NULL; + pTypeFac = NULL; + pOLEFac = NULL; + pCompMod = NULL; // JSM + nInst = 0; + nCode = 0; + nLine = 0; + nCol1 = nCol2 = 0; + bCompiler = sal_False; + bGlobalInitErr = sal_False; + bRunInit = sal_False; + eLanguageMode = SB_LANG_BASIC; + pErrStack = NULL; + pTransliterationWrapper = NULL; + bBlockCompilerError = sal_False; + pAppBasMgr = NULL; + pMSOMacroRuntimLib = NULL; +} + +SbiGlobals::~SbiGlobals() +{ + delete pErrStack; + delete pSbFac; + delete pUnoFac; + delete pTransliterationWrapper; +} + diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx new file mode 100755 index 000000000000..13ae406cb305 --- /dev/null +++ b/basic/source/classes/sbunoobj.cxx @@ -0,0 +1,4855 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +//#include <stl_queue.h> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _TOOLERR_HXX //autogen +#include <tools/errcode.hxx> +#endif +#include <svl/hint.hxx> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/processfactory.hxx> + +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> + +#include <com/sun/star/script/ArrayWrapper.hpp> +#include <com/sun/star/script/NativeObjectWrapper.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/script/BasicErrorException.hpp> +#include <com/sun/star/script/XAllListener.hpp> +#include <com/sun/star/script/XInvocationAdapterFactory.hpp> +#include <com/sun/star/script/XTypeConverter.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/XIdlClassProvider.hpp> +#include <com/sun/star/reflection/XServiceConstructorDescription.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> + + +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; + + +#include<basic/sbstar.hxx> +#include<basic/sbuno.hxx> +#include<basic/sberrors.hxx> +#include<sbunoobj.hxx> +#include"sbjsmod.hxx" +#include<basic/basmgr.hxx> +#include<sbintern.hxx> +#include<runtime.hxx> + +#include<math.h> +#include <hash_map> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include <com/sun/star/reflection/XConstantsTypeDescription.hpp> + +TYPEINIT1(SbUnoMethod,SbxMethod) +TYPEINIT1(SbUnoProperty,SbxProperty) +TYPEINIT1(SbUnoObject,SbxObject) +TYPEINIT1(SbUnoClass,SbxObject) +TYPEINIT1(SbUnoService,SbxObject) +TYPEINIT1(SbUnoServiceCtor,SbxMethod) +TYPEINIT1(SbUnoSingleton,SbxObject) + +typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper; + +// Flag, um immer ueber Invocation zu gehen +//#define INVOCATION_ONLY + + +// Identifier fuer die dbg_-Properies als Strings anlegen +static char const ID_DBG_SUPPORTEDINTERFACES[] = "Dbg_SupportedInterfaces"; +static char const ID_DBG_PROPERTIES[] = "Dbg_Properties"; +static char const ID_DBG_METHODS[] = "Dbg_Methods"; + +static ::rtl::OUString aSeqLevelStr( RTL_CONSTASCII_USTRINGPARAM("[]") ); +static ::rtl::OUString defaultNameSpace( RTL_CONSTASCII_USTRINGPARAM("ooo.vba") ); + +// Gets the default property for an uno object. Note: There is some +// redirection built in. The property name specifies the name +// of the default property. + +bool SbUnoObject::getDefaultPropName( SbUnoObject* pUnoObj, String& sDfltProp ) +{ + bool result = false; + Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY ); + if ( xDefaultProp.is() ) + { + sDfltProp = xDefaultProp->getDefaultPropertyName(); + if ( sDfltProp.Len() ) + result = true; + } + return result; +} + +SbxVariable* getDefaultProp( SbxVariable* pRef ) +{ + SbxVariable* pDefaultProp = NULL; + if ( pRef->GetType() == SbxOBJECT ) + { + SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pRef); + if ( !pObj ) + { + SbxBase* pObjVarObj = pRef->GetObject(); + pObj = PTR_CAST(SbxObject,pObjVarObj); + } + if ( pObj && pObj->ISA(SbUnoObject) ) + { + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj); + pDefaultProp = pUnoObj->GetDfltProperty(); + } + } + return pDefaultProp; +} + +Reference< XComponentContext > getComponentContext_Impl( void ) +{ + static Reference< XComponentContext > xContext; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xContext.is() ) + { + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + xProps->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; + OSL_ASSERT( xContext.is() ); + } + } + return xContext; +} + +// CoreReflection statisch speichern +Reference< XIdlReflection > getCoreReflection_Impl( void ) +{ + static Reference< XIdlReflection > xCoreReflection; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xCoreReflection.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) ) + >>= xCoreReflection; + OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessable!?" ); + } + if( !xCoreReflection.is() ) + { + throw DeploymentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessable") ), + Reference< XInterface >() ); + } + } + return xCoreReflection; +} + +// CoreReflection statisch speichern +Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl( void ) +{ + 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 +Reference< XHierarchicalNameAccess > getTypeProvider_Impl( void ) +{ + static Reference< XHierarchicalNameAccess > xAccess; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xAccess.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) ) + >>= xAccess; + OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessable!?" ); + } + if( !xAccess.is() ) + { + throw DeploymentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM + ("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessable") ), + Reference< XInterface >() ); + } + } + return xAccess; +} + +// Hold TypeConverter statically +Reference< XTypeConverter > getTypeConverter_Impl( void ) +{ + static Reference< XTypeConverter > xTypeConverter; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xTypeConverter.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); + xTypeConverter = Reference<XTypeConverter>( + xSMgr->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter")), + xContext ), UNO_QUERY ); + } + if( !xTypeConverter.is() ) + { + throw DeploymentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM + ("com.sun.star.script.Converter service not accessable") ), + Reference< XInterface >() ); + } + } + return xTypeConverter; +} + + +// #111851 factory function to create an OLE object +SbUnoObject* createOLEObject_Impl( const String& aType ) +{ + static Reference< XMultiServiceFactory > xOLEFactory; + static bool bNeedsInit = true; + + if( bNeedsInit ) + { + bNeedsInit = false; + + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); + xOLEFactory = Reference<XMultiServiceFactory>( + xSMgr->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.OleObjectFactory")), + xContext ), UNO_QUERY ); + } + } + + SbUnoObject* pUnoObj = NULL; + if( xOLEFactory.is() ) + { + // some type names available in VBA can not be directly used in COM + ::rtl::OUString aOLEType = aType; + if ( aOLEType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SAXXMLReader30" ) ) ) ) + aOLEType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Msxml2.SAXXMLReader.3.0" ) ); + + Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType ); + if( xOLEObject.is() ) + { + Any aAny; + aAny <<= xOLEObject; + pUnoObj = new SbUnoObject( aType, aAny ); + } + } + return pUnoObj; +} + + +namespace +{ + void lcl_indent( ::rtl::OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel ) + { + while ( _nLevel-- > 0 ) + _inout_rBuffer.appendAscii( " " ); + } +} + +void implAppendExceptionMsg( ::rtl::OUStringBuffer& _inout_rBuffer, const Exception& _e, const ::rtl::OUString& _rExceptionType, sal_Int32 _nLevel ) +{ + _inout_rBuffer.appendAscii( "\n" ); + lcl_indent( _inout_rBuffer, _nLevel ); + _inout_rBuffer.appendAscii( "Type: " ); + + if ( _rExceptionType.getLength() == 0 ) + _inout_rBuffer.appendAscii( "Unknown" ); + else + _inout_rBuffer.append( _rExceptionType ); + + _inout_rBuffer.appendAscii( "\n" ); + lcl_indent( _inout_rBuffer, _nLevel ); + _inout_rBuffer.appendAscii( "Message: " ); + _inout_rBuffer.append( _e.Message ); + +} + +// Fehlermeldungs-Message bei Exception zusammenbauen +::rtl::OUString implGetExceptionMsg( const Exception& e, const ::rtl::OUString& aExceptionType_ ) +{ + ::rtl::OUStringBuffer aMessageBuf; + implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 ); + return aMessageBuf.makeStringAndClear(); +} + +String implGetExceptionMsg( const Any& _rCaughtException ) +{ + OSL_PRECOND( _rCaughtException.getValueTypeClass() == TypeClass_EXCEPTION, "implGetExceptionMsg: illegal argument!" ); + if ( _rCaughtException.getValueTypeClass() != TypeClass_EXCEPTION ) + return String(); + + return implGetExceptionMsg( *static_cast< const Exception* >( _rCaughtException.getValue() ), _rCaughtException.getValueTypeName() ); +} + +Any convertAny( const Any& rVal, const Type& aDestType ) +{ + Any aConvertedVal; + Reference< XTypeConverter > xConverter = getTypeConverter_Impl(); + try + { + aConvertedVal = xConverter->convertTo( rVal, aDestType ); + } + catch( const IllegalArgumentException& ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + return aConvertedVal; + } + catch( CannotConvertException& e2 ) + { + String aCannotConvertExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) ); + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e2, aCannotConvertExceptionName ) ); + return aConvertedVal; + } + return aConvertedVal; +} + + +// #105565 Special Object to wrap a strongly typed Uno Any +TYPEINIT1(SbUnoAnyObject,SbxObject) + + +// TODO: Spaeter auslagern +Reference<XIdlClass> TypeToIdlClass( const Type& rType ) +{ + // void als Default-Klasse eintragen + Reference<XIdlClass> xRetClass; + typelib_TypeDescription * pTD = 0; + rType.getDescription( &pTD ); + + if( pTD ) + { + ::rtl::OUString sOWName( pTD->pTypeName ); + Reference< XIdlReflection > xRefl = getCoreReflection_Impl(); + xRetClass = xRefl->forName( sOWName ); + } + return xRetClass; +} + +// Exception type unknown +template< class EXCEPTION > +String implGetExceptionMsg( const EXCEPTION& e ) +{ + return implGetExceptionMsg( e, ::getCppuType( &e ).getTypeName() ); +} + +// Error-Message fuer WrappedTargetExceptions +String implGetWrappedMsg( const WrappedTargetException& e ) +{ + String aMsg; + Any aWrappedAny = e.TargetException; + Type aExceptionType = aWrappedAny.getValueType(); + + // Really an Exception? + if( aExceptionType.getTypeClass() == TypeClass_EXCEPTION ) + { + Exception& e_ = *( (Exception*)aWrappedAny.getValue() ); + aMsg = implGetExceptionMsg( e_, String( aExceptionType.getTypeName() ) ); + } + // Otherwise use WrappedTargetException itself + else + { + aMsg = implGetExceptionMsg( e ); + } + + return aMsg; +} + +void implHandleBasicErrorException( BasicErrorException& e ) +{ + SbError nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)e.ErrorCode ); + StarBASIC::Error( nError, e.ErrorMessageArgument ); +} + +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; + + SbError nError( ERRCODE_BASIC_EXCEPTION ); + ::rtl::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( (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.appendAscii( "\nTargetException:" ); + + // next round + aExamine = aWrapped.TargetException; + ++nLevel; + } + + if ( aExamine.getValueTypeClass() == TypeClass_EXCEPTION ) + { + // the last element in the chain is still an exception, but no WrappedTargetException + implAppendExceptionMsg( aMessageBuf, *static_cast< const Exception* >( aExamine.getValue() ), 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 ) ); + } +} + + +// NativeObjectWrapper handling +struct ObjectItem +{ + SbxObjectRef m_xNativeObj; + + ObjectItem( void ) + {} + ObjectItem( SbxObject* pNativeObj ) + : m_xNativeObj( pNativeObj ) + {} +}; +static std::vector< ObjectItem > GaNativeObjectWrapperVector; + +void clearNativeObjectWrapperVector( void ) +{ + GaNativeObjectWrapperVector.clear(); +} + +sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj ) +{ + sal_uInt32 nIndex = GaNativeObjectWrapperVector.size(); + GaNativeObjectWrapperVector.push_back( ObjectItem( pNativeObj ) ); + return nIndex; +} + +SbxObject* lcl_getNativeObject( sal_uInt32 nIndex ) +{ + SbxObjectRef xRetObj; + if( nIndex < GaNativeObjectWrapperVector.size() ) + { + ObjectItem& rItem = GaNativeObjectWrapperVector[ nIndex ]; + xRetObj = rItem.m_xNativeObj; + } + return xRetObj; +} + + +// Von Uno nach Sbx wandeln +SbxDataType unoToSbxType( TypeClass eType ) +{ + SbxDataType eRetType = SbxVOID; + + switch( eType ) + { + case TypeClass_INTERFACE: + case TypeClass_TYPE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ARRAY: break; + */ + case TypeClass_ENUM: eRetType = SbxLONG; break; + case TypeClass_SEQUENCE: + eRetType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: 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_OCTET: break; + case TypeClass_BYTE: eRetType = SbxINTEGER; break; + //case TypeClass_INT: eRetType = SbxINT; break; + case TypeClass_SHORT: eRetType = SbxINTEGER; break; + case TypeClass_LONG: eRetType = SbxLONG; break; + case TypeClass_HYPER: eRetType = SbxSALINT64; break; + //case TypeClass_UNSIGNED_OCTET: break; + case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break; + case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break; + case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break; + //case TypeClass_UNSIGNED_INT: eRetType = SbxUINT; break; + //case TypeClass_UNSIGNED_BYTE: eRetType = SbxUSHORT; break; + default: break; + } + return eRetType; +} + +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 >& indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32& dimension, sal_Bool bIsZeroIndex, Type* pType = NULL ) +{ + Type aType = aValue.getValueType(); + TypeClass eTypeClass = aType.getTypeClass(); + + sal_Int32 indicesIndex = indices.getLength() -1; + sal_Int32 dimCopy = dimension; + + if ( eTypeClass == TypeClass_SEQUENCE ) + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); + Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); + typelib_TypeDescription * pTD = 0; + aType.getDescription( &pTD ); + Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType ); + ::typelib_typedescription_release( pTD ); + + sal_Int32 nLen = xIdlArray->getLen( aValue ); + for ( sal_Int32 index = 0; index < nLen; ++index ) + { + Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)index ); + // This detects the dimension were currently processing + if ( dimCopy == dimension ) + { + ++dimCopy; + if ( sizes.getLength() < dimCopy ) + { + sizes.realloc( sizes.getLength() + 1 ); + sizes[ sizes.getLength() - 1 ] = nLen; + indices.realloc( indices.getLength() + 1 ); + indicesIndex = indices.getLength() - 1; + } + } + + if ( bIsZeroIndex ) + indices[ dimCopy - 1 ] = index; + else + indices[ dimCopy - 1] = index + 1; + + implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType ); + } + + } + else + { + if ( indices.getLength() < 1 ) + { + // 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( SbERR_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->unoAddDim32( 0, sizes[ index ] - 1); + else + pArray->unoAddDim32( 1, sizes[ index ] ); + + } + } + + if ( pArray ) + { + SbxVariableRef xVar = new SbxVariable( eSbxElementType ); + unoToSbxValue( (SbxVariable*)xVar, aValue ); + + sal_Int32* pIndices = indices.getArray(); + pArray->Put32( (SbxVariable*)xVar, pIndices ); + + } + } +} + +void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) +{ + 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; + + // SbUnoObject instanzieren + String aName; + SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny ); + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + + // #51475 Wenn das Objekt ungueltig ist null liefern + if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID ) + { + pVar->PutObject( NULL ); + } + else + { + pVar->PutObject( xWrapper ); + } + } + break; + // Interfaces und Structs muessen in ein SbUnoObject gewrappt werden + case TypeClass_INTERFACE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + { + if( eTypeClass == TypeClass_STRUCT ) + { + ArrayWrapper aWrap; + NativeObjectWrapper aNativeObjectWrapper; + if ( (aValue >>= aWrap) ) + { + SbxDimArray* pArray = NULL; + Sequence< sal_Int32 > indices; + Sequence< sal_Int32 > sizes; + sal_Int32 dimension = 0; + implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, dimension, aWrap.IsZeroIndex ); + if ( pArray ) + { + SbxDimArrayRef xArray = pArray; + sal_uInt16 nFlags = pVar->GetFlags(); + pVar->ResetFlag( SBX_FIXED ); + pVar->PutObject( (SbxDimArray*)xArray ); + 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 = 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) ) + { + sal_Int64 nValue64 = aCurrency.Value; + SbxINT64 aInt64; + aInt64.nHigh = + sal::static_int_cast< sal_Int32 >( + nValue64 >> 32); + aInt64.nLow = (sal_uInt32)( nValue64 & 0xffffffff ); + pVar->PutCurrency( aInt64 ); + break; + } + } + } + } + } + } + // SbUnoObject instanzieren + String aName; + SbUnoObject* pSbUnoObject = new SbUnoObject( aName, 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() ) + { + String sDfltPropName; + + if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) ) + pSbUnoObject->SetDfltProperty( sDfltPropName ); + } + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + + // #51475 Wenn das Objekt ungueltig ist null liefern + if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID ) + { + pVar->PutObject( NULL ); + } + else + { + pVar->PutObject( xWrapper ); + } + } + break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_ARRAY: 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 = 0; + aType.getDescription( &pTD ); + OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE ); + Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType ); + ::typelib_typedescription_release( pTD ); + + // In Basic Array anlegen + SbxDimArrayRef xArray; + SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() ); + xArray = new SbxDimArray( eSbxElementType ); + if( nLen > 0 ) + { + xArray->unoAddDim32( 0, nLen - 1 ); + + // Elemente als Variablen eintragen + for( i = 0 ; i < nLen ; i++ ) + { + // Elemente wandeln + Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)i ); + SbxVariableRef xVar = new SbxVariable( eSbxElementType ); + unoToSbxValue( (SbxVariable*)xVar, aElementAny ); + + // Ins Array braten + xArray->Put32( (SbxVariable*)xVar, &i ); + } + } + else + { + xArray->unoAddDim( 0, -1 ); + } + + // Array zurueckliefern + sal_uInt16 nFlags = pVar->GetFlags(); + pVar->ResetFlag( SBX_FIXED ); + pVar->PutObject( (SbxDimArray*)xArray ); + pVar->SetFlags( nFlags ); + + // #54548, Die Parameter duerfen hier nicht weggehauen werden + //pVar->SetParameters( NULL ); + } + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: break; + + case TypeClass_ANY: + { + // Any rausholen und konvertieren + //Any* pAny = (Any*)aValue.get(); + //if( pAny ) + //unoToSbxValue( pVar, *pAny ); + } + break; + */ + + case TypeClass_BOOLEAN: pVar->PutBool( *(sal_Bool*)aValue.getValue() ); break; + case TypeClass_CHAR: + { + pVar->PutChar( *(sal_Unicode*)aValue.getValue() ); + break; + } + case TypeClass_STRING: { ::rtl::OUString val; aValue >>= val; pVar->PutString( String( 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_OCTET: break; + case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; + //case TypeClass_INT: 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_OCTET: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; + //case TypeClass_UNSIGNED_INT: break; + //case TypeClass_UNSIGNED_BYTE: break; + default: pVar->PutEmpty(); break; + } +} + +// Reflection fuer Sbx-Typen liefern +Type getUnoTypeForSbxBaseType( SbxDataType eType ) +{ + Type aRetType = getCppuVoidType(); + switch( eType ) + { + //case SbxEMPTY: eRet = TypeClass_VOID; break; + case SbxNULL: aRetType = ::getCppuType( (const Reference< XInterface > *)0 ); break; + case SbxINTEGER: aRetType = ::getCppuType( (sal_Int16*)0 ); break; + case SbxLONG: aRetType = ::getCppuType( (sal_Int32*)0 ); break; + case SbxSINGLE: aRetType = ::getCppuType( (float*)0 ); break; + case SbxDOUBLE: aRetType = ::getCppuType( (double*)0 ); break; + case SbxCURRENCY: aRetType = ::getCppuType( (oleautomation::Currency*)0 ); break; + case SbxDECIMAL: aRetType = ::getCppuType( (oleautomation::Decimal*)0 ); break; + case SbxDATE: { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + aRetType = ::getCppuType( (double*)0 ); + else + aRetType = ::getCppuType( (oleautomation::Date*)0 ); + } + break; + // case SbxDATE: aRetType = ::getCppuType( (double*)0 ); break; + case SbxSTRING: aRetType = ::getCppuType( (::rtl::OUString*)0 ); break; + //case SbxOBJECT: break; + //case SbxERROR: break; + case SbxBOOL: aRetType = ::getCppuType( (sal_Bool*)0 ); break; + case SbxVARIANT: aRetType = ::getCppuType( (Any*)0 ); break; + //case SbxDATAOBJECT: break; + case SbxCHAR: aRetType = ::getCppuType( (sal_Unicode*)0 ); break; + case SbxBYTE: aRetType = ::getCppuType( (sal_Int8*)0 ); break; + case SbxUSHORT: aRetType = ::getCppuType( (sal_uInt16*)0 ); break; + case SbxULONG: aRetType = ::getCppuType( (sal_uInt32*)0 ); break; + //case SbxLONG64: break; + //case SbxULONG64: break; + // Maschinenabhaengige zur Sicherheit auf Hyper abbilden + case SbxINT: aRetType = ::getCppuType( (sal_Int32*)0 ); break; + case SbxUINT: aRetType = ::getCppuType( (sal_uInt32*)0 ); break; + //case SbxVOID: break; + //case SbxHRESULT: break; + //case SbxPOINTER: break; + //case SbxDIMARRAY: break; + //case SbxCARRAY: break; + //case SbxUSERDEF: break; + //case SbxLPSTR: break; + //case SbxLPWSTR: break; + //case SbxCoreSTRING: break; + default: break; + } + return aRetType; +} + +// Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY +Type getUnoTypeForSbxValue( SbxValue* pVal ) +{ + Type aRetType = getCppuVoidType(); + if( !pVal ) + return aRetType; + + // SbxType nach Uno wandeln + SbxDataType eBaseType = pVal->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVal->GetObject(); + if( !xObj ) + { + // #109936 No error any more + // StarBASIC::Error( SbERR_INVALID_OBJECT ); + aRetType = getCppuType( static_cast<Reference<XInterface> *>(0) ); + return aRetType; + } + + if( xObj->ISA(SbxDimArray) ) + { + SbxBase* pObj = (SbxBase*)xObj; + SbxDimArray* pArray = (SbxDimArray*)pObj; + + short nDims = pArray->GetDims(); + Type aElementType = getUnoTypeForSbxBaseType( (SbxDataType)(pArray->GetType() & 0xfff) ); + TypeClass eElementTypeClass = aElementType.getTypeClass(); + + // Normal case: One dimensional array + sal_Int32 nLower, nUpper; + if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) + { + if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) + { + // Wenn alle Elemente des Arrays vom gleichen Typ sind, wird + // der genommen, sonst wird das ganze als Any-Sequence betrachtet + sal_Bool bNeedsInit = sal_True; + + sal_Int32 nSize = nUpper - nLower + 1; + sal_Int32 nIdx = nLower; + for( sal_Int32 i = 0 ; i < nSize ; i++,nIdx++ ) + { + SbxVariableRef xVar = pArray->Get32( &nIdx ); + Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar ); + if( bNeedsInit ) + { + if( aType.getTypeClass() == TypeClass_VOID ) + { + // #88522 + // if only first element is void: different types -> []any + // if all elements are void: []void is not allowed -> []any + aElementType = getCppuType( (Any*)0 ); + break; + } + aElementType = aType; + bNeedsInit = sal_False; + } + else if( aElementType != aType ) + { + // Verschiedene Typen -> AnySequence + aElementType = getCppuType( (Any*)0 ); + break; + } + } + } + + ::rtl::OUString aSeqTypeName( aSeqLevelStr ); + aSeqTypeName += 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->Count32(); + + sal_Bool bNeedsInit = sal_True; + for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ ) + { + SbxVariableRef xVar = pArray->SbxArray::Get32( i ); + Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar ); + 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 = getCppuType( (Any*)0 ); + break; + } + aElementType = aType; + bNeedsInit = sal_False; + } + else if( aElementType != aType ) + { + // Verschiedene Typen -> AnySequence + aElementType = getCppuType( (Any*)0 ); + break; + } + } + } + + ::rtl::OUString aSeqTypeName; + for( short iDim = 0 ; iDim < nDims ; iDim++ ) + aSeqTypeName += aSeqLevelStr; + aSeqTypeName += aElementType.getTypeName(); + aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); + } + } + // Kein Array, sondern... + else if( xObj->ISA(SbUnoObject) ) + { + aRetType = ((SbUnoObject*)(SbxBase*)xObj)->getUnoAny().getValueType(); + } + // SbUnoAnyObject? + else if( xObj->ISA(SbUnoAnyObject) ) + { + aRetType = ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue().getValueType(); + } + // Sonst ist es ein Nicht-Uno-Basic-Objekt -> default==void liefern + } + // Kein Objekt, Basistyp konvertieren + else + { + aRetType = getUnoTypeForSbxBaseType( eBaseType ); + } + return aRetType; +} + +// Deklaration Konvertierung von Sbx nach Uno mit bekannter Zielklasse +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty = NULL ); + +// Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY +Any sbxToUnoValueImpl( SbxVariable* pVar, bool bBlockConversionToSmallestType = false ) +{ + SbxDataType eBaseType = pVar->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj.Is() ) + { + if( xObj->ISA(SbUnoAnyObject) ) + return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue(); + if( xObj->ISA(SbClassModuleObject) ) + { + Any aRetAny; + SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)xObj; + SbModule* pClassModule = pClassModuleObj->getClassModule(); + if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) ) + return aRetAny; + } + if( !xObj->ISA(SbUnoObject) ) + { + // Create NativeObjectWrapper to identify object in case of callbacks + SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject()); + if( pObj != NULL ) + { + 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" represention for int values + // because up cast is allowed, downcast not + switch( eType ) + { + case TypeClass_FLOAT: + case TypeClass_DOUBLE: + { + double d = pVar->GetDouble(); + if( d == floor( d ) ) + { + if( d >= -128 && d <= 127 ) + aType = ::getCppuType( (sal_Int8*)0 ); + else if( d >= SbxMININT && d <= SbxMAXINT ) + aType = ::getCppuType( (sal_Int16*)0 ); + else if( d >= -SbxMAXLNG && d <= SbxMAXLNG ) + aType = ::getCppuType( (sal_Int32*)0 ); + } + break; + } + case TypeClass_SHORT: + { + sal_Int16 n = pVar->GetInteger(); + if( n >= -128 && n <= 127 ) + aType = ::getCppuType( (sal_Int8*)0 ); + break; + } + case TypeClass_LONG: + { + sal_Int32 n = pVar->GetLong(); + if( n >= -128 && n <= 127 ) + aType = ::getCppuType( (sal_Int8*)0 ); + else if( n >= SbxMININT && n <= SbxMAXINT ) + aType = ::getCppuType( (sal_Int16*)0 ); + break; + } + case TypeClass_UNSIGNED_SHORT: + { + sal_uInt16 n = pVar->GetUShort(); + if( n <= 255 ) + aType = ::getCppuType( (sal_uInt8*)0 ); + break; + } + case TypeClass_UNSIGNED_LONG: + { + sal_uInt32 n = pVar->GetLong(); + if( n <= 255 ) + aType = ::getCppuType( (sal_uInt8*)0 ); + else if( n <= SbxMAXUINT ) + aType = ::getCppuType( (sal_uInt16*)0 ); + break; + } + default: break; + } + } + + return sbxToUnoValue( pVar, aType ); +} + + + +// Helper function for StepREDIMP +static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray, + const Type& aElemType, short nMaxDimIndex, short nActualDim, + sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) +{ + sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1; + ::rtl::OUString aSeqTypeName; + sal_Int32 i; + for( i = 0 ; i < nSeqLevel ; i++ ) + aSeqTypeName += aSeqLevelStr; + + aSeqTypeName += aElemType.getTypeName(); + Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName ); + + // 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->Get32( pActualIndices ); + aElementVal = sbxToUnoValue( pSource, aElemType ); + } + + try + { + // In die Sequence uebernehmen + xArray->set( aRetVal, i, aElementVal ); + } + catch( const IllegalArgumentException& ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + } + catch (IndexOutOfBoundsException&) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + } + return aRetVal; +} + +// Map old interface +Any sbxToUnoValue( SbxVariable* pVar ) +{ + return sbxToUnoValueImpl( pVar ); +} + + +// Funktion, um einen globalen Bezeichner im +// UnoScope zu suchen und fuer Sbx zu wrappen +static bool implGetTypeByName( const String& rName, Type& rRetType ) +{ + bool bSuccess = false; + + 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; +} + + +// Konvertierung von Sbx nach Uno mit bekannter Zielklasse +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* 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 = (SbxBase*)pVar->GetObject(); + if( xObj.Is() && xObj->ISA(SbUnoAnyObject) ) + { + return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue(); + } + } + + TypeClass eType = rType.getTypeClass(); + switch( eType ) + { + case TypeClass_INTERFACE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); + + // Null-Referenz? + if( pVar->IsNull() && eType == TypeClass_INTERFACE ) + { + Reference< XInterface > xRef; + ::rtl::OUString aClassName = xIdlTargetClass->getName(); + Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() ); + aRetVal.setValue( &xRef, aClassType ); + } + else + { + // #112368 Special conversion for Decimal, Currency and Date + if( eType == TypeClass_STRUCT ) + { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + if( rType == ::getCppuType( (oleautomation::Decimal*)0 ) ) + { + oleautomation::Decimal aDecimal; + pVar->fillAutomationDecimal( aDecimal ); + aRetVal <<= aDecimal; + break; + } + else if( rType == ::getCppuType( (oleautomation::Currency*)0 ) ) + { + SbxINT64 aInt64 = pVar->GetCurrency(); + oleautomation::Currency aCurrency; + sal_Int64& rnValue64 = aCurrency.Value; + rnValue64 = aInt64.nHigh; + rnValue64 <<= 32; + rnValue64 |= aInt64.nLow; + aRetVal <<= aCurrency; + break; + } + else if( rType == ::getCppuType( (oleautomation::Date*)0 ) ) + { + oleautomation::Date aDate; + aDate.Value = pVar->GetDate(); + aRetVal <<= aDate; + break; + } + } + } + + SbxBaseRef pObj = (SbxBase*)pVar->GetObject(); + if( pObj && pObj->ISA(SbUnoObject) ) + { + aRetVal = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + } + else + { + // #109936 NULL object -> NULL XInterface + Reference<XInterface> xInt; + aRetVal <<= xInt; + } + } + } + break; + + case TypeClass_TYPE: + { + if( eBaseType == SbxOBJECT ) + { + // XIdlClass? + Reference< XIdlClass > xIdlClass; + + SbxBaseRef pObj = (SbxBase*)pVar->GetObject(); + if( pObj && pObj->ISA(SbUnoObject) ) + { + Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + aUnoAny >>= xIdlClass; + } + + if( xIdlClass.is() ) + { + ::rtl::OUString aClassName = xIdlClass->getName(); + Type aType( xIdlClass->getTypeClass(), aClassName.getStr() ); + aRetVal <<= aType; + } + } + else if( eBaseType == SbxSTRING ) + { + // String representing type? + String aTypeName = pVar->GetString(); + Type aType; + bool bSuccess = implGetTypeByName( aTypeName, aType ); + if( bSuccess ) + aRetVal <<= aType; + } + } + break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_ARRAY: break; + */ + + // Array -> Sequence + case TypeClass_ENUM: + { + aRetVal = int2enum( pVar->GetLong(), rType ); + } + break; + + case TypeClass_SEQUENCE: + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj && xObj->ISA(SbxDimArray) ) + { + SbxBase* pObj = (SbxBase*)xObj; + SbxDimArray* pArray = (SbxDimArray*)pObj; + + short nDims = pArray->GetDims(); + + // Normal case: One dimensional array + sal_Int32 nLower, nUpper; + if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) + { + sal_Int32 nSeqSize = nUpper - nLower + 1; + + // Instanz der geforderten Sequence erzeugen + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); + xIdlTargetClass->createObject( aRetVal ); + Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); + xArray->realloc( aRetVal, nSeqSize ); + + // Element-Type + ::rtl::OUString aClassName = xIdlTargetClass->getName(); + typelib_TypeDescription * pSeqTD = 0; + typelib_typedescription_getByName( &pSeqTD, aClassName.pData ); + OSL_ASSERT( pSeqTD ); + Type aElemType( ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + // Reference< XIdlClass > xElementClass = TypeToIdlClass( aElemType ); + + // Alle Array-Member umwandeln und eintragen + sal_Int32 nIdx = nLower; + for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ ) + { + SbxVariableRef xVar = pArray->Get32( &nIdx ); + + // Wert von Sbx nach Uno wandeln + Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType ); + + try + { + // In die Sequence uebernehmen + xArray->set( aRetVal, i, aAnyValue ); + } + catch( const IllegalArgumentException& ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + } + catch (IndexOutOfBoundsException&) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + } + } + // #i33795 Map also multi dimensional arrays to corresponding sequences + else if( nDims > 1 ) + { + // Element-Type + typelib_TypeDescription * pSeqTD = 0; + Type aCurType( rType ); + sal_Int32 nSeqLevel = 0; + Type aElemType; + do + { + ::rtl::OUString aTypeName = aCurType.getTypeName(); + typelib_typedescription_getByName( &pSeqTD, aTypeName.pData ); + OSL_ASSERT( pSeqTD ); + if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE ) + { + aCurType = Type( ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + nSeqLevel++; + } + else + { + aElemType = aCurType; + break; + } + } + while( true ); + + if( nSeqLevel == nDims ) + { + sal_Int32* pLowerBounds = new sal_Int32[nDims]; + sal_Int32* pUpperBounds = new sal_Int32[nDims]; + sal_Int32* pActualIndices = new sal_Int32[nDims]; + for( short i = 1 ; i <= nDims ; i++ ) + { + sal_Int32 lBound, uBound; + pArray->GetDim32( i, lBound, uBound ); + + short j = i - 1; + pActualIndices[j] = pLowerBounds[j] = lBound; + pUpperBounds[j] = uBound; + } + + aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType, + nDims - 1, 0, pActualIndices, pLowerBounds, pUpperBounds ); + + delete[] pUpperBounds; + delete[] pLowerBounds; + delete[] pActualIndices; + } + } + } + } + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: break; + */ + + // Bei Any die Klassen-unabhaengige Konvertierungs-Routine nutzen + case TypeClass_ANY: + { + aRetVal = sbxToUnoValueImpl( pVar ); + } + break; + + case TypeClass_BOOLEAN: + { + sal_Bool b = pVar->GetBool(); + aRetVal.setValue( &b, getBooleanCppuType() ); + break; + } + case TypeClass_CHAR: + { + sal_Unicode c = pVar->GetChar(); + aRetVal.setValue( &c , getCharCppuType() ); + break; + } + case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break; + case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break; + case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break; + //case TypeClass_OCTET: break; + + case TypeClass_BYTE: + { + sal_Int16 nVal = pVar->GetInteger(); + sal_Bool bOverflow = sal_False; + if( nVal < -128 ) + { + bOverflow = sal_True; + nVal = -128; + } + else if( nVal > 127 ) + { + bOverflow = sal_True; + nVal = 127; + } + if( bOverflow ) + StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW ); + + sal_Int8 nByteVal = (sal_Int8)nVal; + aRetVal <<= nByteVal; + break; + } + //case TypeClass_INT: break; + case TypeClass_SHORT: aRetVal <<= (sal_Int16)( pVar->GetInteger() ); break; + case TypeClass_LONG: aRetVal <<= (sal_Int32)( pVar->GetLong() ); break; + case TypeClass_HYPER: aRetVal <<= (sal_Int64)( pVar->GetInt64() ); break; + //case TypeClass_UNSIGNED_OCTET:break; + case TypeClass_UNSIGNED_SHORT: aRetVal <<= (sal_uInt16)( pVar->GetUShort() ); break; + case TypeClass_UNSIGNED_LONG: aRetVal <<= (sal_uInt32)( pVar->GetULong() ); break; + case TypeClass_UNSIGNED_HYPER: aRetVal <<= (sal_uInt64)( pVar->GetUInt64() ); break; + //case TypeClass_UNSIGNED_INT: break; + //case TypeClass_UNSIGNED_BYTE: break; + default: break; + } + + return aRetVal; +} + +// Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces +String Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel ) +{ + Type aIfaceType = ::getCppuType( (const Reference< XInterface > *)0 ); + static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType ); + + String aRetStr; + for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ ) + aRetStr.AppendAscii( " " ); + aRetStr += String( xClass->getName() ); + ::rtl::OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + + // Pruefen, ob das Interface wirklich unterstuetzt wird + if( !x->queryInterface( aClassType ).hasValue() ) + { + aRetStr.AppendAscii( " (ERROR: Not really supported!)\n" ); + } + // Gibt es Super-Interfaces + else + { + aRetStr.AppendAscii( "\n" ); + + // Super-Interfaces holen + 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 += Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ); + } + } + return aRetStr; +} + +String getDbgObjectNameImpl( SbUnoObject* pUnoObj ) +{ + String aName; + if( pUnoObj ) + { + aName = pUnoObj->GetClassName(); + if( !aName.Len() ) + { + Any aToInspectObj = pUnoObj->getUnoAny(); + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + Reference< XInterface > xObj; + if( eType == TypeClass_INTERFACE ) + xObj = *(Reference< XInterface >*)aToInspectObj.getValue(); + if( xObj.is() ) + { + Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY ); + if( xServiceInfo.is() ) + aName = xServiceInfo->getImplementationName(); + } + } + } + return aName; +} + +String getDbgObjectName( SbUnoObject* pUnoObj ) +{ + String aName = getDbgObjectNameImpl( pUnoObj ); + if( !aName.Len() ) + aName.AppendAscii( "Unknown" ); + + String aRet; + if( aName.Len() > 20 ) + aRet.AppendAscii( "\n" ); + aRet.AppendAscii( "\"" ); + aRet += aName; + aRet.AppendAscii( "\":" ); + return aRet; +} + +String getBasicObjectTypeName( SbxObject* pObj ) +{ + String aName; + if( pObj ) + { + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + if( pUnoObj ) + aName = getDbgObjectNameImpl( pUnoObj ); + } + return aName; +} + +bool checkUnoObjectType( SbUnoObject* pUnoObj, + const String& aClass ) +{ + Any aToInspectObj = pUnoObj->getUnoAny(); + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + if( eType != TypeClass_INTERFACE ) + return false; + const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue(); + + // Return true for XInvocation based objects as interface type names don't count then + Reference< XInvocation > xInvocation( x, UNO_QUERY ); + if( xInvocation.is() ) + return true; + + bool result = false; + Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY ); + if( xTypeProvider.is() ) + { + 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() ) + { + DBG_ERROR("failed to get XIdlClass for type"); + break; + } + ::rtl::OUString sClassName = xClass->getName(); + if ( sClassName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("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, lets check if it + // matches + Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY ); + if ( xInv.is() ) + { + rtl::OUString sTypeName; + xInv->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("$GetTypeName") ) ) >>= sTypeName; + if ( sTypeName.getLength() == 0 || sTypeName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") ) ) ) + // can't check type, leave it pass + result = true; + else + result = sTypeName.equals( aClass ); + } + break; // finished checking automation object + } + OSL_TRACE("Checking if object implements %s", + OUStringToOString( defaultNameSpace + aClass, + RTL_TEXTENCODING_UTF8 ).getStr() ); + // although interfaces in the ooo.vba.vba namespace + // obey the idl rules and have a leading X, in basic we + // want to be able to do something like + // 'dim wrkbooks as WorkBooks' + // so test assumes the 'X' has been dropped + sal_Int32 indexLastDot = sClassName.lastIndexOf('.'); + if ( indexLastDot > -1 && sClassName.copy( indexLastDot + 1).equalsIgnoreAsciiCase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("X") ) + aClass ) ) + { + result = true; + break; + } + } + } + return result; +} + +// Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces +String Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj ) +{ + Any aToInspectObj = pUnoObj->getUnoAny(); + + // #54898: Nur TypeClass Interface zulasssen + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + String aRet; + if( eType != TypeClass_INTERFACE ) + { + aRet.AppendAscii( RTL_CONSTASCII_STRINGPARAM(ID_DBG_SUPPORTEDINTERFACES) ); + aRet.AppendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" ); + } + else + { + // Interface aus dem Any besorgen + const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue(); + + // XIdlClassProvider-Interface ansprechen + Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY ); + Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY ); + + aRet.AssignAscii( "Supported interfaces by object " ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + aRet.AppendAscii( "\n" ); + if( xTypeProvider.is() ) + { + // Interfaces der Implementation holen + 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 += Impl_GetInterfaceInfo( x, xClass, 1 ); + } + else + { + typelib_TypeDescription * pTD = 0; + rType.getDescription( &pTD ); + String TypeName( ::rtl::OUString( pTD->pTypeName ) ); + + aRet.AppendAscii( "*** ERROR: No IdlClass for type \"" ); + aRet += TypeName; + aRet.AppendAscii( "\"\n*** Please check type library\n" ); + } + } + } + else if( xClassProvider.is() ) + { + + DBG_ERROR( "XClassProvider not supported in UNO3" ); + } + } + return aRet; +} + + + +// Dbg-Hilfsmethode SbxDataType -> String +String Dbg_SbxDataType2String( SbxDataType eType ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Unknown Sbx-Type!") ); + switch( +eType ) + { + case SbxEMPTY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxEMPTY") ); break; + case SbxNULL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxNULL") ); break; + case SbxINTEGER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINTEGER") ); break; + case SbxLONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG") ); break; + case SbxSINGLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSINGLE") ); break; + case SbxDOUBLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDOUBLE") ); break; + case SbxCURRENCY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCURRENCY") ); break; + case SbxDECIMAL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDECIMAL") ); break; + case SbxDATE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATE") ); break; + case SbxSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSTRING") ); break; + case SbxOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxOBJECT") ); break; + case SbxERROR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxERROR") ); break; + case SbxBOOL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBOOL") ); break; + case SbxVARIANT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVARIANT") ); break; + case SbxDATAOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATAOBJECT") ); break; + case SbxCHAR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCHAR") ); break; + case SbxBYTE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBYTE") ); break; + case SbxUSHORT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSHORT") ); break; + case SbxULONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG") ); break; + case SbxLONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG64") ); break; + case SbxULONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG64") ); break; + case SbxSALINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT64") ); break; + case SbxSALUINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT64") ); break; + case SbxINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT") ); break; + case SbxUINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT") ); break; + case SbxVOID: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVOID") ); break; + case SbxHRESULT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxHRESULT") ); break; + case SbxPOINTER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxPOINTER") ); break; + case SbxDIMARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDIMARRAY") ); break; + case SbxCARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCARRAY") ); break; + case SbxUSERDEF: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSERDEF") ); break; + case SbxLPSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPSTR") ); break; + case SbxLPWSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPWSTR") ); break; + case SbxCoreSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCoreSTRING" ) ); break; + case SbxOBJECT | SbxARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxARRAY") ); break; + default: break; + } + return aRet; +} + +// Dbg-Hilfsmethode zum Anzeigen der Properties eines SbUnoObjects +String Impl_DumpProperties( SbUnoObject* pUnoObj ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Properties of object ") ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + + // Uno-Infos auswerten, um Arrays zu erkennen + Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess(); + if( !xAccess.is() ) + { + Reference< XInvocation > xInvok = pUnoObj->getInvocation(); + if( xInvok.is() ) + xAccess = xInvok->getIntrospection(); + } + if( !xAccess.is() ) + { + aRet.AppendAscii( "\nUnknown, no introspection available\n" ); + return aRet; + } + + Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + sal_uInt32 nUnoPropCount = props.getLength(); + const Property* pUnoProps = props.getConstArray(); + + SbxArray* pProps = pUnoObj->GetProperties(); + sal_uInt16 nPropCount = pProps->Count(); + sal_uInt16 nPropsPerLine = 1 + nPropCount / 30; + for( sal_uInt16 i = 0; i < nPropCount; i++ ) + { + SbxVariable* pVar = pProps->Get( i ); + if( pVar ) + { + String aPropStr; + if( (i % nPropsPerLine) == 0 ) + aPropStr.AppendAscii( "\n" ); + + // Typ und Namen ausgeben + // Ist es in Uno eine Sequence? + SbxDataType eType = pVar->GetFullType(); + + sal_Bool bMaybeVoid = sal_False; + if( i < nUnoPropCount ) + { + const Property& rProp = pUnoProps[ i ]; + + // #63133: Bei MAYBEVOID Typ aus Uno neu konvertieren, + // damit nicht immer nur SbxEMPTY ausgegben wird. + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + { + eType = unoToSbxType( rProp.Type.getTypeClass() ); + bMaybeVoid = sal_True; + } + if( eType == SbxOBJECT ) + { + Type aType = rProp.Type; + if( aType.getTypeClass() == TypeClass_SEQUENCE ) + eType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + } + } + aPropStr += Dbg_SbxDataType2String( eType ); + if( bMaybeVoid ) + aPropStr.AppendAscii( "/void" ); + aPropStr.AppendAscii( " " ); + aPropStr += pVar->GetName(); + + if( i == nPropCount - 1 ) + aPropStr.AppendAscii( "\n" ); + else + aPropStr.AppendAscii( "; " ); + + aRet += aPropStr; + } + } + return aRet; +} + +// Dbg-Hilfsmethode zum Anzeigen der Methoden eines SbUnoObjects +String Impl_DumpMethods( SbUnoObject* pUnoObj ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Methods of object ") ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + + // XIntrospectionAccess, um die Typen der Parameter auch ausgeben zu koennen + Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess(); + if( !xAccess.is() ) + { + Reference< XInvocation > xInvok = pUnoObj->getInvocation(); + if( xInvok.is() ) + xAccess = xInvok->getIntrospection(); + } + if( !xAccess.is() ) + { + aRet.AppendAscii( "\nUnknown, no introspection available\n" ); + return aRet; + } + Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods + ( MethodConcept::ALL - MethodConcept::DANGEROUS ); + const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray(); + + SbxArray* pMethods = pUnoObj->GetMethods(); + sal_uInt16 nMethodCount = pMethods->Count(); + if( !nMethodCount ) + { + aRet.AppendAscii( "\nNo methods found\n" ); + return aRet; + } + sal_uInt16 nPropsPerLine = 1 + nMethodCount / 30; + for( sal_uInt16 i = 0; i < nMethodCount; i++ ) + { + SbxVariable* pVar = pMethods->Get( i ); + if( pVar ) + { + String aPropStr; + if( (i % nPropsPerLine) == 0 ) + aPropStr.AppendAscii( "\n" ); + + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = pUnoMethods[i]; + + // Ist es in Uno eine Sequence? + SbxDataType eType = pVar->GetFullType(); + if( eType == SbxOBJECT ) + { + Reference< XIdlClass > xClass = rxMethod->getReturnType(); + if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE ) + eType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + } + // Name und Typ ausgeben + aPropStr += Dbg_SbxDataType2String( eType ); + aPropStr.AppendAscii( " " ); + aPropStr += pVar->GetName(); + aPropStr.AppendAscii( " ( " ); + + // get-Methode darf keinen Parameter haben + Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes(); + sal_uInt32 nParamCount = aParamsSeq.getLength(); + const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray(); + + if( nParamCount > 0 ) + { + for( sal_uInt16 j = 0; j < nParamCount; j++ ) + { + String aTypeStr = Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ); + aPropStr += aTypeStr; + + if( j < nParamCount - 1 ) + aPropStr.AppendAscii( ", " ); + } + } + else + aPropStr.AppendAscii( "void" ); + + aPropStr.AppendAscii( " ) " ); + + if( i == nMethodCount - 1 ) + aPropStr.AppendAscii( "\n" ); + else + aPropStr.AppendAscii( "; " ); + + aRet += aPropStr; + } + } + return aRet; +} + +TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray) + +// Implementation SbUnoObject +void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + if( bNeedIntrospection ) + doIntrospection(); + + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pParams = pVar->GetParameters(); + SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar); + SbUnoMethod* pMeth = PTR_CAST(SbUnoMethod,pVar); + if( pProp ) + { + bool bInvocation = pProp->isInvocationBased(); + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Test-Properties + sal_Int32 nId = pProp->nId; + if( nId < 0 ) + { + // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen + if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" + { + String aRetStr = Impl_GetSupportedInterfaces( this ); + pVar->PutString( aRetStr ); + } + // Id == -2: Properties ausgeben + else if( nId == -2 ) // Property ID_DBG_PROPERTIES + { + // Jetzt muessen alle Properties angelegt werden + implCreateAll(); + String aRetStr = Impl_DumpProperties( this ); + pVar->PutString( aRetStr ); + } + // Id == -3: Methoden ausgeben + else if( nId == -3 ) // Property ID_DBG_METHODS + { + // Jetzt muessen alle Properties angelegt werden + implCreateAll(); + String aRetStr = Impl_DumpMethods( this ); + pVar->PutString( aRetStr ); + } + return; + } + + if( !bInvocation && mxUnoAccess.is() ) + { + try + { + // Wert holen + Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() ); + // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist + // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an + // Ansonsten kann auch FastPropertySet genutzt werden + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + else if( bInvocation && mxInvocation.is() ) + { + try + { + // Wert holen + Any aRetAny = mxInvocation->getValue( pProp->GetName() ); + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + if( !bInvocation && mxUnoAccess.is() ) + { + if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY ) + { + StarBASIC::Error( SbERR_PROP_READONLY ); + return; + } + + // Wert von Uno nach Sbx uebernehmen + Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); + try + { + // Wert setzen + Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + xPropSet->setPropertyValue( pProp->GetName(), aAnyValue ); + // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist + // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an + // Ansonsten kann auch FastPropertySet genutzt werden + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + else if( bInvocation && mxInvocation.is() ) + { + // Wert von Uno nach Sbx uebernehmen + Any aAnyValue = sbxToUnoValueImpl( pVar ); + try + { + // Wert setzen + mxInvocation->setValue( pProp->GetName(), aAnyValue ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + } + else if( pMeth ) + { + bool bInvocation = pMeth->isInvocationBased(); + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Anzahl Parameter -1 wegen Param0 == this + sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0; + Sequence<Any> args; + sal_Bool bOutParams = sal_False; + sal_uInt32 i; + + if( !bInvocation && mxUnoAccess.is() ) + { + // Infos holen + const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); + const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); + sal_uInt32 nUnoParamCount = rInfoSeq.getLength(); + sal_uInt32 nAllocParamCount = nParamCount; + + // Ueberschuessige Parameter ignorieren, Alternative: Error schmeissen + if( nParamCount > nUnoParamCount ) + { + nParamCount = nUnoParamCount; + nAllocParamCount = nParamCount; + } + else if( nParamCount < nUnoParamCount ) + { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + // Check types + bool bError = false; + for( i = nParamCount ; i < nUnoParamCount ; i++ ) + { + const ParamInfo& rInfo = pParamInfos[i]; + const Reference< XIdlClass >& rxClass = rInfo.aType; + if( rxClass->getTypeClass() != TypeClass_ANY ) + { + bError = true; + StarBASIC::Error( SbERR_NOT_OPTIONAL ); + } + } + if( !bError ) + nAllocParamCount = nUnoParamCount; + } + } + + if( nAllocParamCount > 0 ) + { + args.realloc( nAllocParamCount ); + Any* pAnyArgs = args.getArray(); + for( i = 0 ; i < nParamCount ; i++ ) + { + const ParamInfo& rInfo = pParamInfos[i]; + const Reference< XIdlClass >& rxClass = rInfo.aType; + //const XIdlClassRef& rxClass = pUnoParams[i]; + + com::sun::star::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() ); + + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + pAnyArgs[i] = sbxToUnoValue( pParams->Get( (sal_uInt16)(i+1) ), aType ); + + // Wenn es nicht schon feststeht pruefen, ob Out-Parameter vorliegen + if( !bOutParams ) + { + ParamMode aParamMode = rInfo.aMode; + if( aParamMode != ParamMode_IN ) + bOutParams = sal_True; + } + } + } + } + else if( bInvocation && pParams && mxInvocation.is() ) + { + bool bOLEAutomation = true; + // TODO: bOLEAutomation = xOLEAutomation.is() + + AutomationNamedArgsSbxArray* pArgNamesArray = NULL; + if( bOLEAutomation ) + pArgNamesArray = PTR_CAST(AutomationNamedArgsSbxArray,pParams); + + args.realloc( nParamCount ); + Any* pAnyArgs = args.getArray(); + bool bBlockConversionToSmallestType = pINST->IsCompatibility(); + if( pArgNamesArray ) + { + Sequence< ::rtl::OUString >& rNameSeq = pArgNamesArray->getNames(); + ::rtl::OUString* pNames = rNameSeq.getArray(); + + Any aValAny; + for( i = 0 ; i < nParamCount ; i++ ) + { + sal_uInt16 iSbx = (sal_uInt16)(i+1); + + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ), + bBlockConversionToSmallestType ); + + ::rtl::OUString aParamName = pNames[iSbx]; + if( aParamName.getLength() ) + { + oleautomation::NamedArgument aNamedArgument; + aNamedArgument.Name = aParamName; + aNamedArgument.Value = aValAny; + pAnyArgs[i] <<= aNamedArgument; + } + else + { + pAnyArgs[i] = aValAny; + } + } + } + else + { + for( i = 0 ; i < nParamCount ; i++ ) + { + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (sal_uInt16)(i+1) ), + bBlockConversionToSmallestType ); + } + } + } + + // Methode callen + GetSbData()->bBlockCompilerError = sal_True; // #106433 Block compiler errors for API calls + try + { + if( !bInvocation && mxUnoAccess.is() ) + { + Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args ); + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + + // Muessen wir Out-Parameter zurueckkopieren? + if( bOutParams ) + { + const Any* pAnyArgs = args.getConstArray(); + + // Infos holen + const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); + const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); + + sal_uInt32 j; + for( j = 0 ; j < nParamCount ; j++ ) + { + const ParamInfo& rInfo = pParamInfos[j]; + ParamMode aParamMode = rInfo.aMode; + if( aParamMode != ParamMode_IN ) + unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] ); + } + } + } + else if( bInvocation && mxInvocation.is() ) + { + Reference< XDirectInvocation > xDirectInvoke; + if ( pMeth->needsDirectInvocation() ) + xDirectInvoke.set( mxInvocation, UNO_QUERY ); + + Any aRetAny; + if ( xDirectInvoke.is() ) + aRetAny = xDirectInvoke->directInvoke( pMeth->GetName(), args ); + else + { + Sequence< sal_Int16 > OutParamIndex; + Sequence< Any > OutParam; + aRetAny = mxInvocation->invoke( pMeth->GetName(), args, OutParamIndex, OutParam ); + + 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( iTarget >= (sal_Int16)nParamCount ) + break; + unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pNewValues[ j ] ); + } + } + } + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + } + + // #55460, Parameter hier weghauen, da das in unoToSbxValue() + // bei Arrays wegen #54548 nicht mehr gemacht wird + if( pParams ) + pVar->SetParameters( NULL ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + GetSbData()->bBlockCompilerError = sal_False; // #106433 Unblock compiler errors + } + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + + +#ifdef INVOCATION_ONLY +// Aus USR +Reference< XInvocation > createDynamicInvocationFor( const Any& aAny ); +#endif + +SbUnoObject::SbUnoObject( const String& aName_, const Any& aUnoObj_ ) + : SbxObject( aName_ ) + , bNeedIntrospection( sal_True ) + , bNativeCOMObject( sal_False ) +{ + static Reference< XIntrospection > xIntrospection; + + // Default-Properties von Sbx wieder rauspruegeln + Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE ); + Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE ); + + // Typ des Objekts pruefen + TypeClass eType = aUnoObj_.getValueType().getTypeClass(); + Reference< XInterface > x; + if( eType == TypeClass_INTERFACE ) + { + // Interface aus dem Any besorgen + x = *(Reference< XInterface >*)aUnoObj_.getValue(); + if( !x.is() ) + return; + } + + Reference< XTypeProvider > xTypeProvider; +#ifdef INVOCATION_ONLY + // Invocation besorgen + mxInvocation = createDynamicInvocationFor( aUnoObj_ ); +#else + // Hat das Object selbst eine Invocation? + mxInvocation = Reference< XInvocation >( x, UNO_QUERY ); + + xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY ); +#endif + + if( mxInvocation.is() ) + { + // #94670: This is WRONG because then the MaterialHolder doesn't refer + // to the object implementing XInvocation but to the object passed to + // the invocation service!!! + // mxMaterialHolder = Reference< XMaterialHolder >::query( mxInvocation ); + + // ExactName holen + mxExactNameInvocation = Reference< XExactName >::query( mxInvocation ); + + // Rest bezieht sich nur auf Introspection + if( !xTypeProvider.is() ) + { + bNeedIntrospection = sal_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 = sal_True; + } + + maTmpUnoObj = aUnoObj_; + + + //*** Namen bestimmen *** + sal_Bool bFatalError = sal_True; + + // Ist es ein Interface oder eine struct? + sal_Bool bSetClassName = sal_False; + String aClassName_; + if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION ) + { + // Struct ist Ok + bFatalError = sal_False; + + // #67173 Echten Klassen-Namen eintragen + if( aName_.Len() == 0 ) + { + aClassName_ = String( aUnoObj_.getValueType().getTypeName() ); + bSetClassName = sal_True; + } + } + else if( eType == TypeClass_INTERFACE ) + { + // #70197 Interface geht immer durch Typ im Any + bFatalError = sal_False; + + // Nach XIdlClassProvider-Interface fragen + Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY ); + if( xClassProvider.is() ) + { + // #67173 Echten Klassen-Namen eintragen + if( aName_.Len() == 0 ) + { + Sequence< Reference< XIdlClass > > szClasses = xClassProvider->getIdlClasses(); + sal_uInt32 nLen = szClasses.getLength(); + if( nLen ) + { + const Reference< XIdlClass > xImplClass = szClasses.getConstArray()[ 0 ]; + if( xImplClass.is() ) + { + aClassName_ = String( xImplClass->getName() ); + bSetClassName = sal_True; + } + } + } + } + } + if( bSetClassName ) + SetClassName( aClassName_ ); + + // Weder Interface noch Struct -> FatalError + if( bFatalError ) + { + StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION ); + return; + } + + // #67781 Introspection erst on demand durchfuehren +} + +SbUnoObject::~SbUnoObject() +{ +} + + +// #76470 Introspection on Demand durchfuehren +void SbUnoObject::doIntrospection( void ) +{ + static Reference< XIntrospection > xIntrospection; + + if( !bNeedIntrospection ) + return; + bNeedIntrospection = sal_False; + + if( !xIntrospection.is() ) + { + // Introspection-Service holen + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + if ( xFactory.is() ) + { + Reference< XInterface > xI = xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection") ); + if (xI.is()) + xIntrospection = Reference< XIntrospection >::query( xI ); + //xI->queryInterface( ::getCppuType( (const Reference< XIntrospection > *)0 ), xIntrospection ); + } + } + if( !xIntrospection.is() ) + { + StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION ); + return; + } + + // Introspection durchfuehren + try + { + mxUnoAccess = xIntrospection->inspect( maTmpUnoObj ); + } + catch( RuntimeException& e ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + + if( !mxUnoAccess.is() ) + { + // #51475 Ungueltiges Objekt kennzeichnen (kein mxMaterialHolder) + return; + } + + // MaterialHolder vom Access holen + mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess ); + + // ExactName vom Access holen + mxExactName = Reference< XExactName >::query( mxUnoAccess ); +} + + + + +// #67781 Start einer Liste aller SbUnoMethod-Instanzen +static SbUnoMethod* pFirst = NULL; + +void clearUnoMethodsForBasic( StarBASIC* pBasic ) +{ + SbUnoMethod* pMeth = pFirst; + while( pMeth ) + { + SbxObject* pObject = dynamic_cast< SbxObject* >( 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 transfered 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 ); + + if( pMeth == pFirst ) + pFirst = pMeth->pNext; + else if( pMeth->pPrev ) + pMeth->pPrev->pNext = pMeth->pNext; + if( pMeth->pNext ) + pMeth->pNext->pPrev = pMeth->pPrev; + + pMeth->pPrev = NULL; + pMeth->pNext = NULL; + + pMeth->SbxValue::Clear(); + pObject->SbxValue::Clear(); + + // start from the beginning after object clearing, the cycle will end since the method is removed each time + pMeth = pFirst; + } + else + pMeth = pMeth->pNext; + } + else + pMeth = pMeth->pNext; + } +} + +void clearUnoMethods( void ) +{ + SbUnoMethod* pMeth = pFirst; + while( pMeth ) + { + pMeth->SbxValue::Clear(); + pMeth = pMeth->pNext; + } +} + + +SbUnoMethod::SbUnoMethod +( + const String& aName_, + SbxDataType eSbxType, + Reference< XIdlMethod > xUnoMethod_, + bool bInvocation, + bool bDirect +) + : SbxMethod( aName_, eSbxType ) + , mbInvocation( bInvocation ) + , mbDirectInvocation( bDirect ) +{ + m_xUnoMethod = xUnoMethod_; + pParamInfoSeq = NULL; + + // #67781 Methode in Liste eintragen + pNext = pFirst; + pPrev = NULL; + pFirst = this; + if( pNext ) + pNext->pPrev = this; +} + +SbUnoMethod::~SbUnoMethod() +{ + delete pParamInfoSeq; + + if( this == pFirst ) + pFirst = pNext; + else if( pPrev ) + pPrev->pNext = pNext; + if( pNext ) + pNext->pPrev = pPrev; +} + +SbxInfo* SbUnoMethod::GetInfo() +{ + if( !pInfo && m_xUnoMethod.is() ) + { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + pInfo = new SbxInfo(); + + const Sequence<ParamInfo>& rInfoSeq = getParamInfos(); + const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); + sal_uInt32 nParamCount = rInfoSeq.getLength(); + + for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) + { + const ParamInfo& rInfo = pParamInfos[i]; + ::rtl::OUString aParamName = rInfo.aName; + + // const Reference< XIdlClass >& rxClass = rInfo.aType; + SbxDataType t = SbxVARIANT; + sal_uInt16 nFlags_ = SBX_READ; + pInfo->AddParam( aParamName, t, nFlags_ ); + } + } + } + return pInfo; +} + +const Sequence<ParamInfo>& SbUnoMethod::getParamInfos( void ) +{ + if( !pParamInfoSeq && m_xUnoMethod.is() ) + { + Sequence<ParamInfo> aTmp = m_xUnoMethod->getParameterInfos() ; + pParamInfoSeq = new Sequence<ParamInfo>( aTmp ); + } + return *pParamInfoSeq; +} + +SbUnoProperty::SbUnoProperty +( + const String& aName_, + SbxDataType eSbxType, + const Property& aUnoProp_, + sal_Int32 nId_, + bool bInvocation +) + : SbxProperty( aName_, eSbxType ) + , aUnoProp( aUnoProp_ ) + , nId( nId_ ) + , mbInvocation( bInvocation ) +{ + // #54548, bei bedarf Dummy-Array einsetzen, damit SbiRuntime::CheckArray() geht + static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT ); + if( eSbxType & SbxARRAY ) + PutObject( xDummyArray ); +} + +SbUnoProperty::~SbUnoProperty() +{} + + +SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t ) +{ + static Reference< XIdlMethod > xDummyMethod; + static Property aDummyProp; + + SbxVariable* pRes = SbxObject::Find( rName, t ); + + if( bNeedIntrospection ) + doIntrospection(); + + // Neu 4.3.1999: Properties on Demand anlegen, daher jetzt perIntrospectionAccess + // suchen, ob doch eine Property oder Methode des geforderten Namens existiert + if( !pRes ) + { + ::rtl::OUString aUName( rName ); + if( mxUnoAccess.is() && !bNativeCOMObject ) + { + if( mxExactName.is() ) + { + ::rtl::OUString aUExactName = mxExactName->getExactName( aUName ); + if( aUExactName.getLength() ) + aUName = aUExactName; + } + if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) ) + { + const Property& rProp = mxUnoAccess-> + getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + + // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden + SbxDataType eSbxType; + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + eSbxType = SbxVARIANT; + else + eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); + + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, 0, false ); + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + else if( mxUnoAccess->hasMethod( aUName, + MethodConcept::ALL - MethodConcept::DANGEROUS ) ) + { + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = mxUnoAccess-> + getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS ); + + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(), + unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + + // Wenn immer noch nichts gefunden wurde, muss geprueft werden, ob NameAccess vorliegt + if( !pRes ) + { + try + { + Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + ::rtl::OUString aUName2( rName ); + + if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) ) + { + Any aAny = xNameAccess->getByName( aUName2 ); + + // ACHTUNG: Die hier erzeugte Variable darf wegen bei XNameAccess + // nicht als feste Property in das Object aufgenommen werden und + // wird daher nirgendwo gehalten. + // Wenn das Probleme gibt, muss das kuenstlich gemacht werden oder + // es muss eine Klasse SbUnoNameAccessProperty geschaffen werden, + // bei der die Existenz staendig neu ueberprueft und die ggf. weg- + // geworfen wird, wenn der Name nicht mehr gefunden wird. + pRes = new SbxVariable( SbxVARIANT ); + unoToSbxValue( pRes, aAny ); + } + } + catch( NoSuchElementException& e ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + catch( const Exception& ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + if( !pRes && mxInvocation.is() ) + { + if( mxExactNameInvocation.is() ) + { + ::rtl::OUString aUExactName = mxExactNameInvocation->getExactName( aUName ); + if( aUExactName.getLength() ) + aUName = aUExactName; + } + + try + { + if( mxInvocation->hasProperty( aUName ) ) + { + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, aDummyProp, 0, true ); + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + else if( mxInvocation->hasMethod( aUName ) ) + { + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + else + { + Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY ); + if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) ) + { + SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + + } + } + catch( RuntimeException& e ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + } + } + + // Ganz am Schluss noch pruefen, ob die Dbg_-Properties gemeint sind + + if( !pRes ) + { + if( rName.EqualsIgnoreCaseAscii( ID_DBG_SUPPORTEDINTERFACES ) || + rName.EqualsIgnoreCaseAscii( ID_DBG_PROPERTIES ) || + rName.EqualsIgnoreCaseAscii( ID_DBG_METHODS ) ) + { + // Anlegen + implCreateDbgProperties(); + + // Jetzt muessen sie regulaer gefunden werden + pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE ); + } + } + return pRes; +} + + +// Hilfs-Methode zum Anlegen der dbg_-Properties +void SbUnoObject::implCreateDbgProperties( void ) +{ + Property aProp; + + // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen + SbxVariableRef xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_SUPPORTEDINTERFACES)), SbxSTRING, aProp, -1, false ); + QuickInsert( (SbxVariable*)xVarRef ); + + // Id == -2: Properties ausgeben + xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_PROPERTIES)), SbxSTRING, aProp, -2, false ); + QuickInsert( (SbxVariable*)xVarRef ); + + // Id == -3: Methoden ausgeben + xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_METHODS)), SbxSTRING, aProp, -3, false ); + QuickInsert( (SbxVariable*)xVarRef ); +} + +void SbUnoObject::implCreateAll( void ) +{ + // Bestehende Methoden und Properties alle wieder wegwerfen + pMethods = new SbxArray; + pProps = new SbxArray; + + if( bNeedIntrospection ) doIntrospection(); + + // Instrospection besorgen + Reference< XIntrospectionAccess > xAccess = mxUnoAccess; + if( !xAccess.is() || bNativeCOMObject ) + { + if( mxInvocation.is() ) + xAccess = mxInvocation->getIntrospection(); + else if( bNativeCOMObject ) + return; + } + if( !xAccess.is() ) + return; + + // Properties anlegen + Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + sal_uInt32 nPropCount = props.getLength(); + const Property* pProps_ = props.getConstArray(); + + sal_uInt32 i; + for( i = 0 ; i < nPropCount ; i++ ) + { + const Property& rProp = pProps_[ i ]; + + // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden + SbxDataType eSbxType; + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + eSbxType = SbxVARIANT; + else + eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); + + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, i, false ); + QuickInsert( (SbxVariable*)xVarRef ); + } + + // Dbg_-Properties anlegen + implCreateDbgProperties(); + + // Methoden anlegen + Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods + ( MethodConcept::ALL - MethodConcept::DANGEROUS ); + sal_uInt32 nMethCount = aMethodSeq.getLength(); + const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray(); + for( i = 0 ; i < nMethCount ; i++ ) + { + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = pMethods_[i]; + + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod + ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); + QuickInsert( (SbxVariable*)xMethRef ); + } +} + + +// Wert rausgeben +Any SbUnoObject::getUnoAny( void ) +{ + Any aRetAny; + if( bNeedIntrospection ) doIntrospection(); + if( mxMaterialHolder.is() ) + aRetAny = mxMaterialHolder->getMaterial(); + else if( mxInvocation.is() ) + aRetAny <<= mxInvocation; + return aRetAny; +} + +// Hilfsmethode zum Anlegen einer Uno-Struct per CoreReflection +SbUnoObject* Impl_CreateUnoStruct( const String& aClassName ) +{ + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( !xCoreReflection.is() ) + return NULL; + + // Klasse suchen + Reference< XIdlClass > xClass; + Reference< XHierarchicalNameAccess > xHarryName = + getCoreReflection_HierarchicalNameAccess_Impl(); + if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) ) + xClass = xCoreReflection->forName( aClassName ); + if( !xClass.is() ) + return NULL; + + // Ist es ueberhaupt ein struct? + TypeClass eType = xClass->getTypeClass(); + if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) ) + return NULL; + + // Instanz erzeugen + Any aNewAny; + xClass->createObject( aNewAny ); + + // SbUnoObject daraus basteln + SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny ); + return pUnoObj; +} + + +// Factory-Klasse fuer das Anlegen von Uno-Structs per DIM AS NEW +SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 ) +{ + // Ueber SbxId laeuft in Uno nix + return NULL; +} + +SbxObject* SbUnoFactory::CreateObject( const String& rClassName ) +{ + return Impl_CreateUnoStruct( rClassName ); +} + + +// Provisorische Schnittstelle fuer UNO-Anbindung +// Liefert ein SbxObject, das ein Uno-Interface wrappt +SbxObjectRef GetSbUnoObject( const String& aName, const Any& aUnoObj_ ) +{ + return new SbUnoObject( aName, aUnoObj_ ); +} + +// Force creation of all properties for debugging +void createAllObjectProperties( SbxObject* pObj ) +{ + if( !pObj ) + return; + + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + if( pUnoObj ) + pUnoObj->createAllProperties(); + else + pObj->GetAll( SbxCLASS_DONTCARE ); +} + + +void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 1 Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aClassName = rPar.Get(1)->GetString(); + + // Versuchen, gleichnamige Struct zu erzeugen + SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName ); + if( !xUnoObj ) + return; + + // Objekt zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( (SbUnoObject*)xUnoObj ); +} + +void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 1 Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aServiceName = rPar.Get(1)->GetString(); + + // Service suchen und instanzieren + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + Reference< XInterface > xInterface; + if ( xFactory.is() ) + { + try + { + xInterface = xFactory->createInstance( aServiceName ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + + SbxVariableRef refVar = rPar.Get(0); + if( xInterface.is() ) + { + Any aAny; + aAny <<= xInterface; + + // SbUnoObject daraus basteln und zurueckliefern + SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny ); + if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID ) + { + // Objekt zurueckliefern + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } + } + else + { + refVar->PutObject( NULL ); + } +} + +void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 2 Parameter + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aServiceName = rPar.Get(1)->GetString(); + Any aArgAsAny = sbxToUnoValue( rPar.Get(2), + getCppuType( (Sequence<Any>*)0 ) ); + Sequence< Any > aArgs; + aArgAsAny >>= aArgs; + + // Service suchen und instanzieren + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + Reference< XInterface > xInterface; + if ( xFactory.is() ) + { + try + { + xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + + SbxVariableRef refVar = rPar.Get(0); + if( xInterface.is() ) + { + Any aAny; + aAny <<= xInterface; + + // SbUnoObject daraus basteln und zurueckliefern + SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny ); + if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID ) + { + // Objekt zurueckliefern + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } + } + else + { + refVar->PutObject( NULL ); + } +} + +void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + SbxVariableRef refVar = rPar.Get(0); + + // Globalen Service-Manager holen + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + if( xFactory.is() ) + { + Any aAny; + aAny <<= xFactory; + + // SbUnoObject daraus basteln und zurueckliefern + SbUnoObjectRef xUnoObj = new SbUnoObject( String( RTL_CONSTASCII_USTRINGPARAM("ProcessServiceManager") ), aAny ); + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } +} + +void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 2 Parameter + sal_uInt16 nParCount = rPar.Count(); + if( nParCount < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Variable fuer Rueckgabewert + SbxVariableRef refVar = rPar.Get(0); + refVar->PutBool( sal_False ); + + // Uno-Objekt holen + SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject(); + if( !(pObj && pObj->ISA(SbUnoObject)) ) + return; + Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + TypeClass eType = aAny.getValueType().getTypeClass(); + if( eType != TypeClass_INTERFACE ) + return; + + // Interface aus dem Any besorgen + Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue(); + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( !xCoreReflection.is() ) + return; + + for( sal_uInt16 i = 2 ; i < nParCount ; i++ ) + { + // Interface-Name der struct holen + String aIfaceName = rPar.Get( i )->GetString(); + + // Klasse suchen + Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName ); + if( !xClass.is() ) + return; + + // Pruefen, ob das Interface unterstuetzt wird + ::rtl::OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + if( !x->queryInterface( aClassType ).hasValue() ) + return; + } + + // Alles hat geklappt, dann sal_True liefern + refVar->PutBool( sal_True ); +} + +void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 1 Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Variable fuer Rueckgabewert + SbxVariableRef refVar = rPar.Get(0); + refVar->PutBool( sal_False ); + + // Uno-Objekt holen + SbxVariableRef xParam = rPar.Get( 1 ); + if( !xParam->IsObject() ) + return; + SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject(); + if( !(pObj && pObj->ISA(SbUnoObject)) ) + return; + Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + TypeClass eType = aAny.getValueType().getTypeClass(); + if( eType == TypeClass_STRUCT ) + refVar->PutBool( sal_True ); +} + + +void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Variable fuer Rueckgabewert + SbxVariableRef refVar = rPar.Get(0); + refVar->PutBool( sal_False ); + + // Uno-Objekte holen + SbxVariableRef xParam1 = rPar.Get( 1 ); + if( !xParam1->IsObject() ) + return; + SbxBaseRef pObj1 = (SbxBase*)xParam1->GetObject(); + if( !(pObj1 && pObj1->ISA(SbUnoObject)) ) + return; + Any aAny1 = ((SbUnoObject*)(SbxBase*)pObj1)->getUnoAny(); + TypeClass eType1 = aAny1.getValueType().getTypeClass(); + if( eType1 != TypeClass_INTERFACE ) + return; + Reference< XInterface > x1; + aAny1 >>= x1; + //XInterfaceRef x1 = *(XInterfaceRef*)aAny1.get(); + + SbxVariableRef xParam2 = rPar.Get( 2 ); + if( !xParam2->IsObject() ) + return; + SbxBaseRef pObj2 = (SbxBase*)xParam2->GetObject(); + if( !(pObj2 && pObj2->ISA(SbUnoObject)) ) + return; + Any aAny2 = ((SbUnoObject*)(SbxBase*)pObj2)->getUnoAny(); + TypeClass eType2 = aAny2.getValueType().getTypeClass(); + if( eType2 != TypeClass_INTERFACE ) + return; + Reference< XInterface > x2; + aAny2 >>= x2; + //XInterfaceRef x2 = *(XInterfaceRef*)aAny2.get(); + + if( x1 == x2 ) + refVar->PutBool( sal_True ); +} + +typedef std::hash_map< ::rtl::OUString, std::vector< ::rtl::OUString >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleHash; + + +// 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 + +Reference< XTypeDescriptionEnumeration > +getTypeDescriptorEnumeration( const ::rtl::OUString& sSearchRoot, + const Sequence< TypeClass >& types, TypeDescriptionSearchDepth depth ) +{ + Reference< XTypeDescriptionEnumeration > xEnum; + Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY ); + if ( xTypeEnumAccess.is() ) + { + try + { + xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration( + sSearchRoot, types, depth ); + } + catch( NoSuchTypeNameException& /*nstne*/ ) {} + catch( InvalidTypeNameException& /*nstne*/ ) {} + } + return xEnum; +} + +typedef std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > VBAConstantsHash; + +SbxVariable* getVBAConstant( const String& rName ) +{ + SbxVariable* pConst = NULL; + static VBAConstantsHash aConstCache; + static bool isInited = false; + if ( !isInited ) + { + Sequence< TypeClass > types(1); + types[ 0 ] = TypeClass_CONSTANTS; + Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( defaultNameSpace, types, TypeDescriptionSearchDepth_INFINITE ); + + if ( !xEnum.is() ) + return NULL; + + while ( xEnum->hasMoreElements() ) + { + Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY ); + if ( xConstants.is() ) + { + Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants(); + Reference< XConstantTypeDescription >* pSrc = aConsts.getArray(); + sal_Int32 nLen = aConsts.getLength(); + for ( sal_Int32 index =0; index<nLen; ++pSrc, ++index ) + { + Reference< XConstantTypeDescription >& rXConst = + *pSrc; + ::rtl::OUString sFullName = rXConst->getName(); + sal_Int32 indexLastDot = sFullName.lastIndexOf('.'); + ::rtl::OUString sLeafName; + if ( indexLastDot > -1 ) + sLeafName = sFullName.copy( indexLastDot + 1); + aConstCache[ sLeafName.toAsciiLowerCase() ] = rXConst->getConstantValue(); + } + } + } + isInited = true; + } + ::rtl::OUString sKey( rName ); + VBAConstantsHash::const_iterator it = aConstCache.find( sKey.toAsciiLowerCase() ); + if ( it != aConstCache.end() ) + { + pConst = new SbxVariable( SbxVARIANT ); + pConst->SetName( rName ); + unoToSbxValue( pConst, it->second ); + } + return pConst; +} + +// Funktion, um einen globalen Bezeichner im +// UnoScope zu suchen und fuer Sbx zu wrappen +SbUnoClass* findUnoClass( const String& rName ) +{ + // #105550 Check if module exists + SbUnoClass* pUnoClass = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS ) + pUnoClass = new SbUnoClass( rName ); + } + } + return pUnoClass; +} + +SbxVariable* SbUnoClass::Find( const XubString& rName, SbxClassType t ) +{ + (void)t; + + SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE ); + + // Wenn nichts gefunden wird, ist das Sub-Modul noch nicht bekannt + if( !pRes ) + { + // Wenn es schon eine Klasse ist, nach einen Feld fragen + if( m_xClass.is() ) + { + // Ist es ein Field + ::rtl::OUString aUStr( rName ); + Reference< XIdlField > xField = m_xClass->getField( aUStr ); + Reference< XIdlClass > xClass; + if( xField.is() ) + { + try + { + Any aAny; + aAny = xField->get( aAny ); + + // Nach Sbx wandeln + pRes = new SbxVariable( SbxVARIANT ); + pRes->SetName( rName ); + unoToSbxValue( pRes, aAny ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + else + { + // Vollqualifizierten Namen erweitern + String aNewName = GetName(); + aNewName.AppendAscii( "." ); + aNewName += rName; + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( xCoreReflection.is() ) + { + // Ist es eine Konstante? + Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY ); + if( xHarryName.is() ) + { + try + { + Any aValue = xHarryName->getByHierarchicalName( aNewName ); + TypeClass eType = aValue.getValueType().getTypeClass(); + + // Interface gefunden? Dann ist es eine Klasse + if( eType == TypeClass_INTERFACE ) + { + Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue(); + Reference< XIdlClass > xClass( xIface, UNO_QUERY ); + if( xClass.is() ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass ); + pRes->PutObject( xWrapper ); + } + } + else + { + pRes = new SbxVariable( SbxVARIANT ); + unoToSbxValue( pRes, aValue ); + } + } + catch( NoSuchElementException& e1 ) + { + String aMsg = implGetExceptionMsg( e1 ); + } + } + + // Sonst wieder als Klasse annehmen + if( !pRes ) + { + SbUnoClass* pNewClass = findUnoClass( aNewName ); + if( pNewClass ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pNewClass; + pRes->PutObject( xWrapper ); + } + } + + // An UNO service? + if( !pRes ) + { + SbUnoService* pUnoService = findUnoService( aNewName ); + if( pUnoService ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pUnoService; + pRes->PutObject( xWrapper ); + } + } + + // An UNO singleton? + if( !pRes ) + { + SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName ); + if( pUnoSingleton ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton; + pRes->PutObject( xWrapper ); + } + } + } + } + + if( pRes ) + { + pRes->SetName( rName ); + + // Variable einfuegen, damit sie spaeter im Find gefunden wird + QuickInsert( pRes ); + + // Uns selbst gleich wieder als Listener rausnehmen, + // die Werte sind alle konstant + if( pRes->IsBroadcaster() ) + EndListening( pRes->GetBroadcaster(), sal_True ); + } + } + return pRes; +} + + +SbUnoService* findUnoService( const String& rName ) +{ + SbUnoService* pSbUnoService = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_SERVICE ) + { + Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY ); + if( xServiceTypeDesc.is() ) + pSbUnoService = new SbUnoService( rName, xServiceTypeDesc ); + } + } + } + return pSbUnoService; +} + +SbxVariable* SbUnoService::Find( const String& rName, SbxClassType ) +{ + SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD ); + + if( !pRes ) + { + // Wenn es schon eine Klasse ist, nach einen Feld fragen + if( m_bNeedsInit && m_xServiceTypeDesc.is() ) + { + m_bNeedsInit = false; + + Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors(); + const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray(); + int nCtorCount = aSCDSeq.getLength(); + for( int i = 0 ; i < nCtorCount ; ++i ) + { + Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i]; + + String aName( xCtor->getName() ); + if( !aName.Len() ) + { + if( xCtor->isDefaultConstructor() ) + aName = String::CreateFromAscii( "create" ); + } + + if( aName.Len() ) + { + // Create and insert SbUnoServiceCtor + SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor ); + QuickInsert( (SbxVariable*)xSbCtorRef ); + } + } + + pRes = SbxObject::Find( rName, SbxCLASS_METHOD ); + } + } + + return pRes; +} + +void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pParams = pVar->GetParameters(); + SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar); + if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Parameter count -1 because of Param0 == this + sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0; + Sequence<Any> args; + sal_Bool bOutParams = sal_False; + + Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc(); + Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters(); + const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray(); + sal_uInt32 nUnoParamCount = aParameterSeq.getLength(); + + // 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_uInt16 nSbxParameterOffset = 1; + sal_uInt16 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; + } + + sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext; + sal_uInt32 nAllocParamCount = nEffectiveParamCount; + if( nEffectiveParamCount > nUnoParamCount ) + { + if( !bRestParameterMode ) + { + nEffectiveParamCount = nUnoParamCount; + nAllocParamCount = nUnoParamCount; + } + } + // Not enough parameters? + else if( nUnoParamCount > nEffectiveParamCount ) + { + // RestParameterMode only helps if one (the last) parameter is missing + int nDiff = nUnoParamCount - nEffectiveParamCount; + if( !bRestParameterMode || nDiff > 1 ) + { + bParameterError = true; + StarBASIC::Error( SbERR_NOT_OPTIONAL ); + } + } + + if( !bParameterError ) + { + if( nAllocParamCount > 0 ) + { + args.realloc( nAllocParamCount ); + Any* pAnyArgs = args.getArray(); + for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ ) + { + sal_uInt16 iSbx = (sal_uInt16)(i + nSbxParameterOffset + nParameterOffsetByContext); + + // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount + Reference< XParameter > xParam; + if( i < nUnoParamCount ) + { + xParam = pParameterSeq[i]; + if( !xParam.is() ) + continue; + + Reference< XTypeDescription > xParamTypeDesc = xParam->getType(); + if( !xParamTypeDesc.is() ) + continue; + com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() ); + + // sbx paramter needs offset 1 + pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType ); + + // Check for out parameter if not already done + if( !bOutParams ) + { + if( xParam->isOut() ) + bOutParams = sal_True; + } + } + else + { + pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) ); + } + } + } + + // "Call" ctor using createInstanceWithArgumentsAndContext + Reference < XComponentContext > xContext; + if( xFirstParamContext.is() ) + { + xContext = xFirstParamContext; + } + else + { + Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); + xContext.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW ); + } + Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); + + Any aRetAny; + if( xServiceMgr.is() ) + { + String aServiceName = GetName(); + Reference < XInterface > xRet; + try + { + xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + aRetAny <<= xRet; + } + unoToSbxValue( pVar, aRetAny ); + + // Copy back out parameters? + if( bOutParams ) + { + const Any* pAnyArgs = args.getConstArray(); + + for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ ) + { + Reference< XParameter > xParam = pParameterSeq[j]; + if( !xParam.is() ) + continue; + + if( xParam->isOut() ) + unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] ); + } + } + } + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + + + +static SbUnoServiceCtor* pFirstCtor = NULL; + +void clearUnoServiceCtors( void ) +{ + SbUnoServiceCtor* pCtor = pFirstCtor; + while( pCtor ) + { + pCtor->SbxValue::Clear(); + pCtor = pCtor->pNext; + } +} + +SbUnoServiceCtor::SbUnoServiceCtor( const String& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc ) + : SbxMethod( aName_, SbxOBJECT ) + , m_xServiceCtorDesc( xServiceCtorDesc ) +{ +} + +SbUnoServiceCtor::~SbUnoServiceCtor() +{ +} + +SbxInfo* SbUnoServiceCtor::GetInfo() +{ + SbxInfo* pRet = NULL; + + return pRet; +} + + +SbUnoSingleton* findUnoSingleton( const String& rName ) +{ + SbUnoSingleton* pSbUnoSingleton = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_SINGLETON ) + { + Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY ); + if( xSingletonTypeDesc.is() ) + pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc ); + } + } + } + return pSbUnoSingleton; +} + +SbUnoSingleton::SbUnoSingleton( const String& aName_, + const Reference< XSingletonTypeDescription >& xSingletonTypeDesc ) + : SbxObject( aName_ ) + , m_xSingletonTypeDesc( xSingletonTypeDesc ) +{ + SbxVariableRef xGetMethodRef = + new SbxMethod( String( RTL_CONSTASCII_USTRINGPARAM( "get" ) ), SbxOBJECT ); + QuickInsert( (SbxVariable*)xGetMethodRef ); +} + +void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pParams = pVar->GetParameters(); + sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0; + sal_uInt32 nAllowedParamCount = 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 = xFirstParamContext; + } + + if( !xContextToUse.is() ) + { + Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); + xContextToUse.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW ); + --nAllowedParamCount; + } + + if( nParamCount > nAllowedParamCount ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + Any aRetAny; + if( xContextToUse.is() ) + { + String aSingletonName( RTL_CONSTASCII_USTRINGPARAM("/singletons/") ); + aSingletonName += GetName(); + Reference < XInterface > xRet; + xContextToUse->getValueByName( aSingletonName ) >>= xRet; + aRetAny <<= xRet; + } + unoToSbxValue( pVar, aRetAny ); + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); +} + + +//======================================================================== +//======================================================================== +//======================================================================== + +// Implementation eines EventAttacher-bezogenen AllListeners, der +// nur einzelne Events an einen allgemeinen AllListener weiterleitet +class BasicAllListener_Impl : public BasicAllListenerHelper +{ + virtual void firing_impl(const AllEventObject& Event, Any* pRet); + +public: + SbxObjectRef xSbxObj; + ::rtl::OUString aPrefixName; + + BasicAllListener_Impl( const ::rtl::OUString& aPrefixName ); + ~BasicAllListener_Impl(); + + // Methoden von XInterface + //virtual sal_Bool queryInterface( Uik aUik, Reference< XInterface > & rOut ); + + // Methoden von XAllListener + virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException ); + virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException ); + + // Methoden von XEventListener + virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException ); +}; + + +//======================================================================== +BasicAllListener_Impl::BasicAllListener_Impl +( + const ::rtl::OUString & aPrefixName_ +) + : aPrefixName( aPrefixName_ ) +{ +} + +//======================================================================== +BasicAllListener_Impl::~BasicAllListener_Impl() +{ +} + +//======================================================================== + +void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet ) +{ + vos::OGuard guard( Application::GetSolarMutex() ); + + if( xSbxObj.Is() ) + { + ::rtl::OUString aMethodName = aPrefixName; + aMethodName = aMethodName + Event.MethodName; + + SbxVariable * pP = xSbxObj; + while( pP->GetParent() ) + { + pP = pP->GetParent(); + StarBASIC * pLib = PTR_CAST(StarBASIC,pP); + if( pLib ) + { + // In Basic Array anlegen + SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT ); + const Any * pArgs = Event.Arguments.getConstArray(); + sal_Int32 nCount = Event.Arguments.getLength(); + for( sal_Int32 i = 0; i < nCount; i++ ) + { + // Elemente wandeln + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, pArgs[i] ); + xSbxArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) ); + } + + pLib->Call( aMethodName, xSbxArray ); + + // Return-Wert aus dem Param-Array holen, wenn verlangt + if( pRet ) + { + SbxVariable* pVar = xSbxArray->Get( 0 ); + if( pVar ) + { + // #95792 Avoid a second call + sal_uInt16 nFlags = pVar->GetFlags(); + pVar->SetFlag( SBX_NO_BROADCAST ); + *pRet = sbxToUnoValueImpl( pVar ); + pVar->SetFlags( nFlags ); + } + } + break; + } + } + } +} + + +// Methoden von XAllListener +void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException ) +{ + firing_impl( Event, NULL ); +} + +Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException ) +{ + Any aRetAny; + firing_impl( Event, &aRetAny ); + return aRetAny; +} + +//======================================================================== +// Methoden von XEventListener +void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException ) +{ + vos::OGuard guard( Application::GetSolarMutex() ); + + xSbxObj.Clear(); +} + + + +//************************************************************************* +// class InvocationToAllListenerMapper +// helper class to map XInvocation to XAllListener (also in project eventattacher!) +//************************************************************************* +class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation > +{ +public: + InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType, + const Reference< XAllListener >& AllListener, const Any& Helper ); + + // XInvocation + virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException ); + virtual Any SAL_CALL invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) + throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ); + virtual void SAL_CALL setValue(const ::rtl::OUString& PropertyName, const Any& Value) + throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ); + virtual Any SAL_CALL getValue(const ::rtl::OUString& PropertyName) throw( UnknownPropertyException, RuntimeException ); + virtual sal_Bool SAL_CALL hasMethod(const ::rtl::OUString& Name) throw( RuntimeException ); + virtual sal_Bool SAL_CALL hasProperty(const ::rtl::OUString& Name) throw( RuntimeException ); + +private: + Reference< XIdlReflection > m_xCoreReflection; + Reference< XAllListener > m_xAllListener; + Reference< XIdlClass > m_xListenerType; + Any m_Helper; +}; + + +// Function to replace AllListenerAdapterService::createAllListerAdapter +Reference< XInterface > createAllListenerAdapter +( + const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory, + const Reference< XIdlClass >& xListenerType, + const Reference< XAllListener >& xListener, + const Any& Helper +) +{ + Reference< XInterface > xAdapter; + if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() ) + { + Reference< XInvocation > xInvocationToAllListenerMapper = + (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper ); + Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() ); + xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType ); + } + return xAdapter; +} + + +//-------------------------------------------------------------------------------------------------- +// InvocationToAllListenerMapper +InvocationToAllListenerMapper::InvocationToAllListenerMapper + ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper ) + : m_xAllListener( AllListener ) + , m_xListenerType( ListenerType ) + , m_Helper( Helper ) +{ +} + +//************************************************************************* +Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void) + throw( RuntimeException ) +{ + return Reference< XIntrospectionAccess >(); +} + +//************************************************************************* +Any SAL_CALL InvocationToAllListenerMapper::invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params, + Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) + throw( IllegalArgumentException, CannotConvertException, + InvocationTargetException, RuntimeException ) +{ + (void)OutParamIndex; + (void)OutParam ; + + Any aRet; + + // Check if to firing or approveFiring has to be called + Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName ); + sal_Bool bApproveFiring = sal_False; + if( !xMethod.is() ) + return aRet; + Reference< XIdlClass > xReturnType = xMethod->getReturnType(); + Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes(); + if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) || + aExceptionSeq.getLength() > 0 ) + { + bApproveFiring = sal_True; + } + else + { + Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos(); + sal_uInt32 nParamCount = aParamSeq.getLength(); + if( nParamCount > 1 ) + { + const ParamInfo* pInfos = aParamSeq.getConstArray(); + for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) + { + if( pInfos[ i ].aMode != ParamMode_IN ) + { + bApproveFiring = sal_True; + break; + } + } + } + } + + AllEventObject aAllEvent; + aAllEvent.Source = (OWeakObject*) this; + aAllEvent.Helper = m_Helper; + aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() ); + aAllEvent.MethodName = FunctionName; + aAllEvent.Arguments = Params; + if( bApproveFiring ) + aRet = m_xAllListener->approveFiring( aAllEvent ); + else + m_xAllListener->firing( aAllEvent ); + return aRet; +} + +//************************************************************************* +void SAL_CALL InvocationToAllListenerMapper::setValue(const ::rtl::OUString& PropertyName, const Any& Value) + throw( UnknownPropertyException, CannotConvertException, + InvocationTargetException, RuntimeException ) +{ + (void)PropertyName; + (void)Value; +} + +//************************************************************************* +Any SAL_CALL InvocationToAllListenerMapper::getValue(const ::rtl::OUString& PropertyName) + throw( UnknownPropertyException, RuntimeException ) +{ + (void)PropertyName; + + return Any(); +} + +//************************************************************************* +sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name ); + return xMethod.is(); +} + +//************************************************************************* +sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + Reference< XIdlField > xField = m_xListenerType->getField( Name ); + return xField.is(); +} + +//======================================================================== +// Uno-Service erzeugen +// 1. Parameter == Prefix-Name der Makros +// 2. Parameter == voll qualifizierter Name des Listeners +void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +//RTLFUNC(CreateUnoListener) +{ + (void)bWrite; + + // Wir brauchen 2 Parameter + if ( rPar.Count() != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aPrefixName = rPar.Get(1)->GetString(); + String aListenerClassName = rPar.Get(2)->GetString(); + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( !xCoreReflection.is() ) + return; + + // AllListenerAdapterService holen + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + if( !xFactory.is() ) + return; + + // Klasse suchen + Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName ); + if( !xClass.is() ) + return; + + // AB, 30.11.1999 InvocationAdapterFactory holen + Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( + xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ), UNO_QUERY ); + + BasicAllListener_Impl * p; + Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName ); + Any aTmp; + Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp ); + if( !xLst.is() ) + return; + + ::rtl::OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + aTmp = xLst->queryInterface( aClassType ); + if( !aTmp.hasValue() ) + return; + + SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp ); + p->xSbxObj = pUnoObj; + p->xSbxObj->SetParent( pBasic ); + + // #100326 Register listener object to set Parent NULL in Dtor + SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners(); + xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() ); + + // Objekt zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( p->xSbxObj ); +} + +//======================================================================== +// Represents the DefaultContext property of the ProcessServiceManager +// in the Basic runtime system. +void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + SbxVariableRef refVar = rPar.Get(0); + + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet> xPSMPropertySet( xFactory, UNO_QUERY ); + if( xPSMPropertySet.is() ) + { + Any aContextAny = xPSMPropertySet->getPropertyValue( + String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ); + + SbUnoObjectRef xUnoObj = new SbUnoObject + ( String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ), + aContextAny ); + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } +} + +//======================================================================== +// 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( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) +{ + (void)pBasic; + (void)bWrite; + + static String aTypeTypeString( RTL_CONSTASCII_USTRINGPARAM("type") ); + + // 2 parameters needed + if ( rPar.Count() != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aTypeName = rPar.Get(1)->GetString(); + SbxVariable* pVal = rPar.Get(2); + + if( aTypeName == aTypeTypeString ) + { + SbxDataType eBaseType = pVal->SbxValue::GetType(); + String aValTypeName; + if( eBaseType == SbxSTRING ) + { + aValTypeName = pVal->GetString(); + } + else if( eBaseType == SbxOBJECT ) + { + // XIdlClass? + Reference< XIdlClass > xIdlClass; + + SbxBaseRef pObj = (SbxBase*)pVal->GetObject(); + if( pObj && pObj->ISA(SbUnoObject) ) + { + Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + aUnoAny >>= xIdlClass; + } + + if( xIdlClass.is() ) + aValTypeName = xIdlClass->getName(); + } + Type aType; + bool bSuccess = implGetTypeByName( aValTypeName, aType ); + if( bSuccess ) + { + Any aTypeAny( aType ); + SbxVariableRef refVar = rPar.Get(0); + SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny ); + refVar->PutObject( xUnoAnyObject ); + } + return; + } + + // Check the type + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + Any aRet; + try + { + aRet = xTypeAccess->getByHierarchicalName( aTypeName ); + } + catch( NoSuchElementException& e1 ) + { + String aNoSuchElementExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.NoSuchElementException" ) ); + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e1, aNoSuchElementExceptionName ) ); + return; + } + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + Type aDestType( eTypeClass, aTypeName ); + + + // Preconvert value + Any aVal = sbxToUnoValueImpl( pVal ); + Any aConvertedVal = convertAny( aVal, aDestType ); + + /* + // Convert + Reference< XTypeConverter > xConverter = getTypeConverter_Impl(); + try + { + aConvertedVal = xConverter->convertTo( aVal, aDestType ); + } + catch( IllegalArgumentException& e1 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + return; + } + catch( CannotConvertException& e2 ) + { + String aCannotConvertExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) ); + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e2, aCannotConvertExceptionName ) ); + return; + } + */ + + SbxVariableRef refVar = rPar.Get(0); + SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal ); + refVar->PutObject( xUnoAnyObject ); +} + +//========================================================================== + +namespace { +class OMutexBasis +{ +protected: + // this mutex is necessary for OInterfaceContainerHelper + ::osl::Mutex m_aMutex; +}; +} // namespace + +typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper; + +class ModuleInvocationProxy : public OMutexBasis, + public ModuleInvocationProxyHelper +{ + ::rtl::OUString m_aPrefix; + SbxObjectRef m_xScopeObj; + bool m_bProxyIsClassModuleObject; + + ::cppu::OInterfaceContainerHelper m_aListeners; + +public: + ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ); + ~ModuleInvocationProxy() + {} + + // XInvocation + virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw(); + virtual void SAL_CALL setValue( const ::rtl::OUString& rProperty, const Any& rValue ) + throw( UnknownPropertyException ); + virtual Any SAL_CALL getValue( const ::rtl::OUString& rProperty ) + throw( UnknownPropertyException ); + virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& rName ) throw(); + virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& rProp ) throw(); + + virtual Any SAL_CALL invoke( const ::rtl::OUString& rFunction, + const Sequence< Any >& rParams, + Sequence< sal_Int16 >& rOutParamIndex, + Sequence< Any >& rOutParam ) + throw( CannotConvertException, InvocationTargetException ); + + // XComponent + virtual void SAL_CALL dispose() throw(RuntimeException); + virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException); + virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException); +}; + +ModuleInvocationProxy::ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ) + : m_aPrefix( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") ) ) + , m_xScopeObj( xScopeObj ) + , m_aListeners( m_aMutex ) +{ + m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false; +} + +Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() throw() +{ + return Reference< XIntrospectionAccess >(); +} + +void SAL_CALL ModuleInvocationProxy::setValue( const ::rtl::OUString& rProperty, const Any& rValue ) throw( UnknownPropertyException ) +{ + if( !m_bProxyIsClassModuleObject ) + throw UnknownPropertyException(); + + vos::OGuard guard( Application::GetSolarMutex() ); + + ::rtl::OUString aPropertyFunctionName( RTL_CONSTASCII_USTRINGPARAM( "Property Set ") ); + aPropertyFunctionName += m_aPrefix; + aPropertyFunctionName += rProperty; + + SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD ); + SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL; + if( pMeth == NULL ) + { + // TODO: Check vba behavior concernig missing function + //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName ); + throw UnknownPropertyException(); + } + + // Setup parameter + SbxArrayRef xArray = new SbxArray; + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, rValue ); + xArray->Put( xVar, 1 ); + + // Call property method + SbxVariableRef xValue = new SbxVariable; + pMeth->SetParameters( xArray ); + pMeth->Call( xValue ); + //aRet = sbxToUnoValue( xValue ); + pMeth->SetParameters( NULL ); + + // TODO: OutParameter? + + // throw InvocationTargetException(); + + //return aRet; + +} + +Any SAL_CALL ModuleInvocationProxy::getValue( const ::rtl::OUString& rProperty ) throw( UnknownPropertyException ) +{ + if( !m_bProxyIsClassModuleObject ) + throw UnknownPropertyException(); + + vos::OGuard guard( Application::GetSolarMutex() ); + + ::rtl::OUString aPropertyFunctionName( RTL_CONSTASCII_USTRINGPARAM( "Property Get ") ); + aPropertyFunctionName += m_aPrefix; + aPropertyFunctionName += rProperty; + + SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD ); + SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL; + if( pMeth == NULL ) + { + // TODO: Check vba behavior concernig missing function + //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName ); + throw UnknownPropertyException(); + } + + // Call method + SbxVariableRef xValue = new SbxVariable; + pMeth->Call( xValue ); + Any aRet = sbxToUnoValue( xValue ); + return aRet; +} + +sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const ::rtl::OUString& ) throw() +{ + return sal_False; +} + +sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const ::rtl::OUString& ) throw() +{ + return sal_False; +} + +Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction, + const Sequence< Any >& rParams, + Sequence< sal_Int16 >&, + Sequence< Any >& ) + throw( CannotConvertException, InvocationTargetException ) +{ + vos::OGuard guard( Application::GetSolarMutex() ); + + Any aRet; + SbxObjectRef xScopeObj = m_xScopeObj; + if( !xScopeObj.Is() ) + return aRet; + + ::rtl::OUString aFunctionName = m_aPrefix; + aFunctionName += rFunction; + + sal_Bool bSetRescheduleBack = sal_False; + sal_Bool bOldReschedule = sal_True; + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + bOldReschedule = pInst->IsReschedule(); + if ( bOldReschedule ) + { + pInst->EnableReschedule( sal_False ); + bSetRescheduleBack = sal_True; + } + } + + SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD ); + SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL; + if( pMeth == NULL ) + { + // TODO: Check vba behavior concernig missing function + //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName ); + return aRet; + } + + // Setup parameters + SbxArrayRef xArray; + sal_Int32 nParamCount = rParams.getLength(); + if( nParamCount ) + { + xArray = new SbxArray; + const Any *pArgs = rParams.getConstArray(); + for( sal_Int32 i = 0 ; i < nParamCount ; i++ ) + { + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, pArgs[i] ); + xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) ); + } + } + + // Call method + SbxVariableRef xValue = new SbxVariable; + if( xArray.Is() ) + pMeth->SetParameters( xArray ); + pMeth->Call( xValue ); + aRet = sbxToUnoValue( xValue ); + pMeth->SetParameters( NULL ); + + if( bSetRescheduleBack ) + pInst->EnableReschedule( bOldReschedule ); + + // TODO: OutParameter? + + return aRet; +} + +void SAL_CALL ModuleInvocationProxy::dispose() + throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + EventObject aEvent( (XComponent*)this ); + m_aListeners.disposeAndClear( aEvent ); + + m_xScopeObj = NULL; +} + +void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener ) + throw (RuntimeException) +{ + m_aListeners.addInterface( xListener ); +} + +void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener ) + throw (RuntimeException) +{ + m_aListeners.removeInterface( xListener ); +} + + +Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType, + const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ) +{ + Reference< XInterface > xRet; + + Reference< XComponentContext > xContext = getComponentContext_Impl(); + Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); + + Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj ); + + Sequence<Any> args( 3 ); + args[0] <<= aControlAny; + args[1] <<= aVBAType; + args[2] <<= xProxy; + + try + { + xRet = xServiceMgr->createInstanceWithArgumentsAndContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.custom.UnoComListener")), + args, xContext ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + + return xRet; +} + +typedef std::vector< WeakReference< XComponent > > ComponentRefVector; + +struct StarBasicDisposeItem +{ + StarBASIC* m_pBasic; + SbxArrayRef m_pRegisteredVariables; + ComponentRefVector m_vComImplementsObjects; + + StarBasicDisposeItem( StarBASIC* pBasic ) + : m_pBasic( pBasic ) + { + m_pRegisteredVariables = new SbxArray(); + } +}; + +typedef std::vector< StarBasicDisposeItem* > DisposeItemVector; + +static DisposeItemVector GaDisposeItemVector; + +DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it; + for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it ) + { + StarBasicDisposeItem* pItem = *it; + if( pItem->m_pBasic == pBasic ) + return it; + } + return GaDisposeItemVector.end(); +} + +StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); + StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL; + if( pItem == NULL ) + { + pItem = new StarBasicDisposeItem( pBasic ); + GaDisposeItemVector.push_back( pItem ); + } + return pItem; +} + +void registerComponentToBeDisposedForBasic + ( Reference< XComponent > xComponent, StarBASIC* pBasic ) +{ + StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); + pItem->m_vComImplementsObjects.push_back( xComponent ); +} + +void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic ) +{ + StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); + SbxArray* pArray = pItem->m_pRegisteredVariables; + pArray->Put( pVar, pArray->Count() ); +} + +void disposeComVariablesForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); + if( it != GaDisposeItemVector.end() ) + { + StarBasicDisposeItem* pItem = *it; + + SbxArray* pArray = pItem->m_pRegisteredVariables; + sal_uInt16 nCount = pArray->Count(); + for( sal_uInt16 i = 0 ; i < nCount ; ++i ) + { + SbxVariable* pVar = pArray->Get( i ); + pVar->ClearComListener(); + } + + ComponentRefVector& rv = pItem->m_vComImplementsObjects; + ComponentRefVector::iterator itCRV; + for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV ) + { + try + { + Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW ); + xComponent->dispose(); + } + catch( Exception& ) + {} + } + + 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 + + Reference< XComponentContext > xContext = getComponentContext_Impl(); + Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); + Reference< XSingleServiceFactory > xComImplementsFactory + ( + xServiceMgr->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.custom.ComImplementsFactory")), xContext ), + UNO_QUERY + ); + if( !xComImplementsFactory.is() ) + return false; + + bool bSuccess = false; + + SbxArray* pModIfaces = pClassData->mxIfaces; + sal_uInt16 nCount = pModIfaces->Count(); + for( sal_uInt16 i = 0 ; i < nCount ; ++i ) + { + SbxVariable* pVar = pModIfaces->Get( i ); + ::rtl::OUString aIfaceName = pVar->GetName(); + + if( aIfaceName.getLength() != 0 ) + { + ::rtl::OUString aPureIfaceName = aIfaceName; + sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.'); + if ( indexLastDot > -1 ) + aPureIfaceName = aIfaceName.copy( indexLastDot + 1 ); + + Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject ); + + Sequence<Any> args( 2 ); + args[0] <<= aIfaceName; + args[1] <<= xProxy; + + Reference< XInterface > xRet; + bSuccess = false; + try + { + xRet = xComImplementsFactory->createInstanceWithArguments( args ); + bSuccess = true; + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + + if( bSuccess ) + { + Reference< XComponent > xComponent( xProxy, UNO_QUERY ); + if( xComponent.is() ) + { + StarBASIC* pParentBasic = NULL; + SbxObject* pCurObject = this; + do + { + SbxObject* pObjParent = pCurObject->GetParent(); + pParentBasic = PTR_CAST( StarBASIC, pObjParent ); + pCurObject = pObjParent; + } + while( pParentBasic == NULL && pCurObject != NULL ); + + OSL_ASSERT( pParentBasic != NULL ); + registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); + } + + o_rRetAny <<= xRet; + break; + } + } + } + + return bSuccess; +} + + +// 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; + + SbUnoObject* pUnoObj = NULL; + if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj)) != NULL ) + { + // Only for native COM objects + if( pUnoObj->isNativeCOMObject() ) + { + SbxVariableRef pMeth = pObj->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "toString" ) ), SbxCLASS_METHOD ); + if ( pMeth.Is() ) + { + SbxValues aRes; + pMeth->Get( aRes ); + pVal->Put( aRes ); + bSuccess = true; + } + } + } + return bSuccess; +} + diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx new file mode 100755 index 000000000000..a268568a410d --- /dev/null +++ b/basic/source/classes/sbxmod.cxx @@ -0,0 +1,2626 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <list> + +#include <vos/macros.hxx> +#include <vcl/svapp.hxx> +#include <tools/stream.hxx> +#include <svl/brdcst.hxx> +#include <tools/shl.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include <sbjsmeth.hxx> +#include "sbjsmod.hxx" +#include "sbintern.hxx" +#include "image.hxx" +#include "opcodes.hxx" +#include "runtime.hxx" +#include "token.hxx" +#include "sbunoobj.hxx" +#include "sbtrace.hxx" + + +//#include <basic/hilight.hxx> +#include <svtools/syntaxhighlight.hxx> + +#include <basic/basrdll.hxx> +#include <vos/mutex.hxx> +#include <basic/sbobjmod.hxx> +#include <cppuhelper/implbase2.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/script/ModuleType.hpp> +#include <com/sun/star/script/vba/XVBACompatibility.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +using namespace com::sun::star; + +// for the bsearch +#ifdef WNT +#define CDECL _cdecl +#endif +#if defined(UNX) || defined(OS2) +#define CDECL +#endif +#ifdef UNX +#include <sys/resource.h> +#endif + +#include <stdio.h> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <map> +#include <com/sun/star/reflection/XProxyFactory.hpp> +#include <cppuhelper/implbase1.hxx> +#include <basic/sbobjmod.hxx> +#include <com/sun/star/uno/XAggregation.hpp> +#include <map> +#include <com/sun/star/script/XInvocation.hpp> + + using namespace ::com::sun::star; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::beans; +using namespace com::sun::star::script; + + +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/awt/XDialogProvider.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/anytostring.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> + +typedef ::cppu::WeakImplHelper1< XInvocation > DocObjectWrapper_BASE; +typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap; +::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar ); +void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue ); + +class DocObjectWrapper : public DocObjectWrapper_BASE +{ + Reference< XAggregation > m_xAggProxy; + Reference< XInvocation > m_xAggInv; + Reference< XTypeProvider > m_xAggregateTypeProv; + Sequence< Type > m_Types; + SbModule* m_pMod; + SbMethodRef getMethod( const rtl::OUString& aName ) throw (RuntimeException); + SbPropertyRef getProperty( const rtl::OUString& aName ) throw (RuntimeException); + String mName; // for debugging + +public: + DocObjectWrapper( SbModule* pMod ); + virtual ~DocObjectWrapper(); + + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (RuntimeException) + { + if( !m_xAggregateTypeProv.is() ) + throw RuntimeException(); + return m_xAggregateTypeProv->getImplementationId(); + } + + virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection( ) throw (RuntimeException); + + virtual Any SAL_CALL invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException); + virtual void SAL_CALL setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException); + virtual Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException); + virtual ::sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException); + virtual ::sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException); + virtual Any SAL_CALL queryInterface( const Type& aType ) throw ( RuntimeException ); + + virtual Sequence< Type > SAL_CALL getTypes() throw ( RuntimeException ); +}; + +DocObjectWrapper::DocObjectWrapper( SbModule* pVar ) : m_pMod( pVar ), mName( pVar->GetName() ) +{ + SbObjModule* pMod = PTR_CAST(SbObjModule,pVar); + if ( pMod ) + { + if ( pMod->GetModuleType() == ModuleType::DOCUMENT ) + { + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + // Use proxy factory service to create aggregatable proxy. + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pMod->GetObject() ); + Reference< XInterface > xIf; + if ( pUnoObj ) + { + Any aObj = pUnoObj->getUnoAny(); + aObj >>= xIf; + if ( xIf.is() ) + { + m_xAggregateTypeProv.set( xIf, UNO_QUERY ); + m_xAggInv.set( xIf, UNO_QUERY ); + } + } + if ( xIf.is() ) + { + try + { + Reference< XMultiComponentFactory > xMFac( xFactory, UNO_QUERY_THROW ); + Reference< XPropertySet> xPSMPropertySet( xMFac, UNO_QUERY_THROW ); + Reference< XComponentContext > xCtx; + xPSMPropertySet->getPropertyValue( + String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xCtx; + Reference< XProxyFactory > xProxyFac( xMFac->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.ProxyFactory" ) ), xCtx ), UNO_QUERY_THROW ); + m_xAggProxy = xProxyFac->createProxy( xIf ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "DocObjectWrapper::DocObjectWrapper: Caught exception!" ); + } + } + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + + /* i35609 - Fix crash on Solaris. The setDelegator call needs + to be in its own block to ensure that all temporary Reference + instances that are acquired during the call are released + before m_refCount is decremented again */ + { + m_xAggProxy->setDelegator( static_cast< cppu::OWeakObject * >( this ) ); + } + + osl_decrementInterlockedCount( &m_refCount ); + } + } + } +} + +void SAL_CALL +DocObjectWrapper::acquire() throw () +{ + osl_incrementInterlockedCount( &m_refCount ); + OSL_TRACE("DocObjectWrapper::acquire(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount ); +} +void SAL_CALL +DocObjectWrapper::release() throw () +{ + if ( osl_decrementInterlockedCount( &m_refCount ) == 0 ) + { + OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount ); + delete this; + } + else + OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount ); +} + +DocObjectWrapper::~DocObjectWrapper() +{ +} + +Sequence< Type > SAL_CALL DocObjectWrapper::getTypes() + throw ( RuntimeException ) +{ + if ( m_Types.getLength() == 0 ) + { + Sequence< Type > sTypes; + if ( m_xAggregateTypeProv.is() ) + sTypes = m_xAggregateTypeProv->getTypes(); + m_Types.realloc( sTypes.getLength() + 1 ); + Type* pPtr = m_Types.getArray(); + for ( int i=0; i<m_Types.getLength(); ++i, ++pPtr ) + { + if ( i == 0 ) + *pPtr = XInvocation::static_type( NULL ); + else + *pPtr = sTypes[ i - 1 ]; + } + } + return m_Types; +} + +Reference< XIntrospectionAccess > SAL_CALL +DocObjectWrapper::getIntrospection( ) throw (RuntimeException) +{ + return NULL; +} + +Any SAL_CALL +DocObjectWrapper::invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException) +{ + if ( m_xAggInv.is() && m_xAggInv->hasMethod( aFunctionName ) ) + return m_xAggInv->invoke( aFunctionName, aParams, aOutParamIndex, aOutParam ); + SbMethodRef pMethod = getMethod( aFunctionName ); + if ( !pMethod ) + throw RuntimeException(); + // check number of parameters + sal_Int32 nParamsCount = aParams.getLength(); + SbxInfo* pInfo = pMethod->GetInfo(); + if ( pInfo ) + { + sal_Int32 nSbxOptional = 0; + sal_uInt16 n = 1; + for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) ) + { + if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 ) + ++nSbxOptional; + else + nSbxOptional = 0; + } + sal_Int32 nSbxCount = n - 1; + if ( nParamsCount < nSbxCount - nSbxOptional ) + { + throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "wrong number of parameters!" ) ), Reference< XInterface >() ); + } + } + // set parameters + SbxArrayRef xSbxParams; + if ( nParamsCount > 0 ) + { + xSbxParams = new SbxArray; + const Any* pParams = aParams.getConstArray(); + for ( sal_Int32 i = 0; i < nParamsCount; ++i ) + { + SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] ); + xSbxParams->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 ); + + // Enable passing by ref + if ( xSbxVar->GetType() != SbxVARIANT ) + xSbxVar->SetFlag( SBX_FIXED ); + } + } + if ( xSbxParams.Is() ) + pMethod->SetParameters( xSbxParams ); + + // call method + SbxVariableRef xReturn = new SbxVariable; + ErrCode nErr = SbxERR_OK; + + nErr = pMethod->Call( xReturn ); + Any aReturn; + // get output parameters + if ( xSbxParams.Is() ) + { + SbxInfo* pInfo_ = pMethod->GetInfo(); + if ( pInfo_ ) + { + OutParamMap aOutParamMap; + for ( sal_uInt16 n = 1, nCount = xSbxParams->Count(); n < nCount; ++n ) + { + const SbxParamInfo* pParamInfo = pInfo_->GetParam( n ); + if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 ) + { + SbxVariable* pVar = xSbxParams->Get( n ); + if ( pVar ) + { + SbxVariableRef xVar = pVar; + aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) ); + } + } + } + sal_Int32 nOutParamCount = aOutParamMap.size(); + aOutParamIndex.realloc( nOutParamCount ); + aOutParam.realloc( nOutParamCount ); + sal_Int16* pOutParamIndex = aOutParamIndex.getArray(); + Any* pOutParam = aOutParam.getArray(); + for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam ) + { + *pOutParamIndex = aIt->first; + *pOutParam = aIt->second; + } + } + } + + // get return value + aReturn = sbxToUnoValue( xReturn ); + + pMethod->SetParameters( NULL ); + + return aReturn; +} + +void SAL_CALL +DocObjectWrapper::setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException) +{ + if ( m_xAggInv.is() && m_xAggInv->hasProperty( aPropertyName ) ) + return m_xAggInv->setValue( aPropertyName, aValue ); + + SbPropertyRef pProperty = getProperty( aPropertyName ); + if ( !pProperty.Is() ) + throw UnknownPropertyException(); + unoToSbxValue( (SbxVariable*) pProperty, aValue ); +} + +Any SAL_CALL +DocObjectWrapper::getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException) +{ + if ( m_xAggInv.is() && m_xAggInv->hasProperty( aPropertyName ) ) + return m_xAggInv->getValue( aPropertyName ); + + SbPropertyRef pProperty = getProperty( aPropertyName ); + if ( !pProperty.Is() ) + throw UnknownPropertyException(); + + SbxVariable* pProp = ( SbxVariable* ) pProperty; + if ( pProp->GetType() == SbxEMPTY ) + pProperty->Broadcast( SBX_HINT_DATAWANTED ); + + Any aRet = sbxToUnoValue( pProp ); + return aRet; +} + +::sal_Bool SAL_CALL +DocObjectWrapper::hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException) +{ + if ( m_xAggInv.is() && m_xAggInv->hasMethod( aName ) ) + return sal_True; + return getMethod( aName ).Is(); +} + +::sal_Bool SAL_CALL +DocObjectWrapper::hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException) +{ + sal_Bool bRes = sal_False; + if ( m_xAggInv.is() && m_xAggInv->hasProperty( aName ) ) + bRes = sal_True; + else bRes = getProperty( aName ).Is(); + return bRes; +} + +Any SAL_CALL DocObjectWrapper::queryInterface( const Type& aType ) + throw ( RuntimeException ) +{ + Any aRet = DocObjectWrapper_BASE::queryInterface( aType ); + if ( aRet.hasValue() ) + return aRet; + else if ( m_xAggProxy.is() ) + aRet = m_xAggProxy->queryAggregation( aType ); + return aRet; +} + +SbMethodRef DocObjectWrapper::getMethod( const rtl::OUString& aName ) throw (RuntimeException) +{ + SbMethodRef pMethod = NULL; + if ( m_pMod ) + { + sal_uInt16 nSaveFlgs = m_pMod->GetFlags(); + // Limit search to this module + m_pMod->ResetFlag( SBX_GBLSEARCH ); + pMethod = (SbMethod*) m_pMod->SbModule::Find( aName, SbxCLASS_METHOD ); + m_pMod->SetFlags( nSaveFlgs ); + } + + return pMethod; +} + +SbPropertyRef DocObjectWrapper::getProperty( const rtl::OUString& aName ) throw (RuntimeException) +{ + SbPropertyRef pProperty = NULL; + if ( m_pMod ) + { + sal_uInt16 nSaveFlgs = m_pMod->GetFlags(); + // Limit search to this module. + m_pMod->ResetFlag( SBX_GBLSEARCH ); + pProperty = (SbProperty*)m_pMod->SbModule::Find( aName, SbxCLASS_PROPERTY ); + m_pMod->SetFlag( nSaveFlgs ); + } + + return pProperty; +} + +TYPEINIT1(SbModule,SbxObject) +TYPEINIT1(SbMethod,SbxMethod) +TYPEINIT1(SbProperty,SbxProperty) +TYPEINIT1(SbProcedureProperty,SbxProperty) +TYPEINIT1(SbJScriptModule,SbModule) +TYPEINIT1(SbJScriptMethod,SbMethod) +TYPEINIT1(SbObjModule,SbModule) +TYPEINIT1(SbUserFormModule,SbObjModule) + +typedef std::vector<HighlightPortion> HighlightPortions; + +bool getDefaultVBAMode( StarBASIC* pb ) +{ + bool bResult = false; + if ( pb && pb->IsDocBasic() ) + { + uno::Any aDoc; + if ( pb->GetUNOConstant( "ThisComponent", aDoc ) ) + { + uno::Reference< beans::XPropertySet > xProp( aDoc, uno::UNO_QUERY ); + if ( xProp.is() ) + { + uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProp->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BasicLibraries") ) ), uno::UNO_QUERY ); + if ( xVBAMode.is() ) + bResult = xVBAMode->getVBACompatibilityMode() == sal_True; + } + } + } + return bResult; +} + +class AsyncQuitHandler +{ + AsyncQuitHandler() {} + AsyncQuitHandler( const AsyncQuitHandler&); +public: + static AsyncQuitHandler& instance() + { + static AsyncQuitHandler dInst; + return dInst; + } + + void QuitApplication() + { + uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + if ( xFactory.is() ) + { + uno::Reference< frame::XDesktop > xDeskTop( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ) ), uno::UNO_QUERY ); + if ( xDeskTop.is() ) + xDeskTop->terminate(); + } + } + DECL_LINK( OnAsyncQuit, void* ); +}; + +IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ ) +{ + QuitApplication(); + return 0L; +} + +bool VBAUnlockControllers( StarBASIC* pBasic ) +{ + bool bRes = false; + if ( pBasic && pBasic->IsDocBasic() ) + { + SbUnoObject* pGlobs = dynamic_cast< SbUnoObject* >( pBasic->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ), SbxCLASS_DONTCARE ) ); + if ( pGlobs ) try + { + uno::Reference< frame::XModel > xModel( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW ); + if ( xModel->hasControllersLocked() ) + xModel->unlockControllers(); + bRes = true; + } + catch( uno::Exception& ) + { + } + } + return bRes; +} + +///////////////////////////////////////////////////////////////////////////// + +// Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen +// Elemente von anderen Modulen aus gefunden werden koennen. + +SbModule::SbModule( const String& rName, sal_Bool bVBACompat ) + : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASICModule") ) ), + pImage( NULL ), pBreaks( NULL ), pClassData( NULL ), mbVBACompat( bVBACompat ), pDocObject( NULL ), bIsProxyModule( false ) +{ + SetName( rName ); + SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH ); + SetModuleType( script::ModuleType::NORMAL ); + + // #i92642: Set name property to intitial name + SbxVariable* pNameProp = pProps->Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY ); + if( pNameProp != NULL ) + pNameProp->PutString( GetName() ); +} + +SbModule::~SbModule() +{ + OSL_TRACE("Module named %s is destructing", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr() ); + if( pImage ) + delete pImage; + if( pBreaks ) + delete pBreaks; + if( pClassData ) + delete pClassData; + mxWrapper = NULL; +} + +uno::Reference< script::XInvocation > +SbModule::GetUnoModule() +{ + if ( !mxWrapper.is() ) + mxWrapper = new DocObjectWrapper( this ); + + OSL_TRACE("Module named %s returning wrapper mxWrapper (0x%x)", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), mxWrapper.get() ); + return mxWrapper; +} + +sal_Bool SbModule::IsCompiled() const +{ + return sal_Bool( pImage != 0 ); +} + +const SbxObject* SbModule::FindType( String aTypeName ) const +{ + return pImage ? pImage->FindType( aTypeName ) : NULL; +} + + +// Aus dem Codegenerator: Loeschen des Images und Invalidieren der Entries + +void SbModule::StartDefinitions() +{ + delete pImage; pImage = NULL; + if( pClassData ) + pClassData->clear(); + + // Methoden und Properties bleiben erhalten, sind jedoch ungueltig + // schliesslich sind ja u.U. die Infos belegt + sal_uInt16 i; + for( i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) ); + if( p ) + p->bInvalid = sal_True; + } + for( i = 0; i < pProps->Count(); ) + { + SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) ); + if( p ) + pProps->Remove( i ); + else + i++; + } +} + +// Methode anfordern/anlegen + +SbMethod* SbModule::GetMethod( const String& rName, SbxDataType t ) +{ + SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD ); + SbMethod* pMeth = p ? PTR_CAST(SbMethod,p) : NULL; + if( p && !pMeth ) + pMethods->Remove( p ); + if( !pMeth ) + { + pMeth = new SbMethod( rName, t, this ); + pMeth->SetParent( this ); + pMeth->SetFlags( SBX_READ ); + pMethods->Put( pMeth, pMethods->Count() ); + StartListening( pMeth->GetBroadcaster(), sal_True ); + } + // Per Default ist die Methode GUELTIG, da sie auch vom Compiler + // (Codegenerator) erzeugt werden kann + pMeth->bInvalid = sal_False; + pMeth->ResetFlag( SBX_FIXED ); + pMeth->SetFlag( SBX_WRITE ); + pMeth->SetType( t ); + pMeth->ResetFlag( SBX_WRITE ); + if( t != SbxVARIANT ) + pMeth->SetFlag( SBX_FIXED ); + return pMeth; +} + +// Property anfordern/anlegen + +SbProperty* SbModule::GetProperty( const String& rName, SbxDataType t ) +{ + SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY ); + SbProperty* pProp = p ? PTR_CAST(SbProperty,p) : NULL; + if( p && !pProp ) + pProps->Remove( p ); + if( !pProp ) + { + pProp = new SbProperty( rName, t, this ); + pProp->SetFlag( SBX_READWRITE ); + pProp->SetParent( this ); + pProps->Put( pProp, pProps->Count() ); + StartListening( pProp->GetBroadcaster(), sal_True ); + } + return pProp; +} + +SbProcedureProperty* SbModule::GetProcedureProperty + ( const String& rName, SbxDataType t ) +{ + SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY ); + SbProcedureProperty* pProp = p ? PTR_CAST(SbProcedureProperty,p) : NULL; + if( p && !pProp ) + pProps->Remove( p ); + if( !pProp ) + { + pProp = new SbProcedureProperty( rName, t ); + pProp->SetFlag( SBX_READWRITE ); + pProp->SetParent( this ); + pProps->Put( pProp, pProps->Count() ); + StartListening( pProp->GetBroadcaster(), sal_True ); + } + return pProp; +} + +SbIfaceMapperMethod* SbModule::GetIfaceMapperMethod + ( const String& rName, SbMethod* pImplMeth ) +{ + SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD ); + SbIfaceMapperMethod* pMapperMethod = p ? PTR_CAST(SbIfaceMapperMethod,p) : NULL; + if( p && !pMapperMethod ) + pMethods->Remove( p ); + if( !pMapperMethod ) + { + pMapperMethod = new SbIfaceMapperMethod( rName, pImplMeth ); + pMapperMethod->SetParent( this ); + pMapperMethod->SetFlags( SBX_READ ); + pMethods->Put( pMapperMethod, pMethods->Count() ); + } + pMapperMethod->bInvalid = sal_False; + return pMapperMethod; +} + +SbIfaceMapperMethod::~SbIfaceMapperMethod() +{ +} + +TYPEINIT1(SbIfaceMapperMethod,SbMethod) + + +// Aus dem Codegenerator: Ungueltige Eintraege entfernen + +void SbModule::EndDefinitions( sal_Bool bNewState ) +{ + for( sal_uInt16 i = 0; i < pMethods->Count(); ) + { + SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) ); + if( p ) + { + if( p->bInvalid ) + pMethods->Remove( p ); + else + { + p->bInvalid = bNewState; + i++; + } + } + else + i++; + } + SetModified( sal_True ); +} + +void SbModule::Clear() +{ + delete pImage; pImage = NULL; + if( pClassData ) + pClassData->clear(); + SbxObject::Clear(); +} + + +SbxVariable* SbModule::Find( const XubString& rName, SbxClassType t ) +{ + // make sure a search in an uninstatiated class module will fail + SbxVariable* pRes = SbxObject::Find( rName, t ); + if ( bIsProxyModule && !GetSbData()->bRunInit ) + return NULL; + if( !pRes && pImage ) + { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + // Put enum types as objects into module, + // allows MyEnum.First notation + SbxArrayRef xArray = pImage->GetEnums(); + if( xArray.Is() ) + { + SbxVariable* pEnumVar = xArray->Find( rName, SbxCLASS_DONTCARE ); + SbxObject* pEnumObject = PTR_CAST( SbxObject, pEnumVar ); + if( pEnumObject ) + { + bool bPrivate = pEnumObject->IsSet( SBX_PRIVATE ); + String aEnumName = pEnumObject->GetName(); + + pRes = new SbxVariable( SbxOBJECT ); + pRes->SetName( aEnumName ); + pRes->SetParent( this ); + pRes->SetFlag( SBX_READ ); + if( bPrivate ) + pRes->SetFlag( SBX_PRIVATE ); + pRes->PutObject( pEnumObject ); + } + } + } + } + return pRes; +} + +const ::rtl::OUString& SbModule::GetSource32() const +{ + return aOUSource; +} + +const String& SbModule::GetSource() const +{ + static String aRetStr; + aRetStr = aOUSource; + return aRetStr; +} + +// Parent und BASIC sind eins! + +void SbModule::SetParent( SbxObject* p ) +{ + // #118083: Assertion is not valid any more + // DBG_ASSERT( !p || p->IsA( TYPE(StarBASIC) ), "SbModules nur in BASIC eintragen" ); + pParent = p; +} + +void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbProperty* pProp = PTR_CAST(SbProperty,pVar); + SbMethod* pMeth = PTR_CAST(SbMethod,pVar); + if( pProp ) + { + if( pProp->GetModule() != this ) + SetError( SbxERR_BAD_ACTION ); + } + else if( pMeth ) + { + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + if( pMeth->bInvalid && !Compile() ) + // Auto-Compile hat nicht geklappt! + StarBASIC::Error( SbERR_BAD_PROP_VALUE ); + else + { + // Aufruf eines Unterprogramms + SbModule* pOld = pMOD; + pMOD = this; + Run( (SbMethod*) pVar ); + pMOD = pOld; + } + } + } + else + { + // #i92642: Special handling for name property to avoid + // side effects when using name as variable implicitely + bool bForwardToSbxObject = true; + + sal_uIntPtr nId = pHint->GetId(); + if( (nId == SBX_HINT_DATAWANTED || nId == SBX_HINT_DATACHANGED) && + pVar->GetName().EqualsIgnoreCaseAscii( "name" ) ) + bForwardToSbxObject = false; + + if( bForwardToSbxObject ) + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } + } +} + +// Das Setzen der Source macht das Image ungueltig +// und scant die Methoden-Definitionen neu ein + +void SbModule::SetSource( const String& r ) +{ + SetSource32( r ); +} + +void SbModule::SetSource32( const ::rtl::OUString& r ) +{ + // Default basic mode to library container mode, but.. allow Option VBASupport 0/1 override + SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC*>( GetParent() ) ) ); + aOUSource = r; + StartDefinitions(); + SbiTokenizer aTok( r ); + while( !aTok.IsEof() ) + { + SbiToken eEndTok = NIL; + + // Suchen nach SUB oder FUNCTION + SbiToken eLastTok = NIL; + while( !aTok.IsEof() ) + { + // #32385: Nicht bei declare + SbiToken eCurTok = aTok.Next(); + if( eLastTok != DECLARE ) + { + if( eCurTok == SUB ) + { + eEndTok = ENDSUB; break; + } + if( eCurTok == FUNCTION ) + { + eEndTok = ENDFUNC; break; + } + if( eCurTok == PROPERTY ) + { + eEndTok = ENDPROPERTY; break; + } + if( eCurTok == OPTION ) + { + eCurTok = aTok.Next(); + if( eCurTok == COMPATIBLE ) + aTok.SetCompatible( true ); + else if ( ( eCurTok == VBASUPPORT ) && ( aTok.Next() == NUMBER ) ) + { + sal_Bool bIsVBA = ( aTok.GetDbl()== 1 ); + SetVBACompat( bIsVBA ); + aTok.SetCompatible( bIsVBA ); + } + } + } + eLastTok = eCurTok; + } + // Definition der Methode + SbMethod* pMeth = NULL; + if( eEndTok != NIL ) + { + sal_uInt16 nLine1 = aTok.GetLine(); + if( aTok.Next() == SYMBOL ) + { + String aName_( aTok.GetSym() ); + SbxDataType t = aTok.GetType(); + if( t == SbxVARIANT && eEndTok == ENDSUB ) + t = SbxVOID; + pMeth = GetMethod( aName_, t ); + pMeth->nLine1 = pMeth->nLine2 = nLine1; + // Die Methode ist erst mal GUELTIG + pMeth->bInvalid = sal_False; + } + else + eEndTok = NIL; + } + // Skip bis END SUB/END FUNCTION + if( eEndTok != NIL ) + { + while( !aTok.IsEof() ) + { + if( aTok.Next() == eEndTok ) + { + pMeth->nLine2 = aTok.GetLine(); + break; + } + } + if( aTok.IsEof() ) + pMeth->nLine2 = aTok.GetLine(); + } + } + EndDefinitions( sal_True ); +} + +void SbModule::SetComment( const String& r ) +{ + aComment = r; + SetModified( sal_True ); +} + +SbMethod* SbModule::GetFunctionForLine( sal_uInt16 nLine ) +{ + for( sal_uInt16 i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* p = (SbMethod*) pMethods->Get( i ); + if( p->GetSbxId() == SBXID_BASICMETHOD ) + { + if( nLine >= p->nLine1 && nLine <= p->nLine2 ) + return p; + } + } + return NULL; +} + +// Ausstrahlen eines Hints an alle Basics + +static void _SendHint( SbxObject* pObj, sal_uIntPtr nId, SbMethod* p ) +{ + // Selbst ein BASIC? + if( pObj->IsA( TYPE(StarBASIC) ) && pObj->IsBroadcaster() ) + pObj->GetBroadcaster().Broadcast( SbxHint( nId, p ) ); + // Dann die Unterobjekte fragen + SbxArray* pObjs = pObj->GetObjects(); + for( sal_uInt16 i = 0; i < pObjs->Count(); i++ ) + { + SbxVariable* pVar = pObjs->Get( i ); + if( pVar->IsA( TYPE(SbxObject) ) ) + _SendHint( PTR_CAST(SbxObject,pVar), nId, p ); + } +} + +static void SendHint( SbxObject* pObj, sal_uIntPtr nId, SbMethod* p ) +{ + while( pObj->GetParent() ) + pObj = pObj->GetParent(); + _SendHint( pObj, nId, p ); +} + +// #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, +// beim Programm-Ende freigeben, damit nichts gehalten wird. +void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC* pBasic ) +{ + // return-Wert von CreateUnoService loeschen + static String aName( RTL_CONSTASCII_USTRINGPARAM("CreateUnoService") ); + SbxVariable* pVar = pBasic->GetRtl()->Find( aName, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // return-Wert von CreateUnoDialog loeschen + static String aName2( RTL_CONSTASCII_USTRINGPARAM("CreateUnoDialog") ); + pVar = pBasic->GetRtl()->Find( aName2, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // return-Wert von CDec loeschen + static String aName3( RTL_CONSTASCII_USTRINGPARAM("CDec") ); + pVar = pBasic->GetRtl()->Find( aName3, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // return-Wert von CreateObject loeschen + static String aName4( RTL_CONSTASCII_USTRINGPARAM("CreateObject") ); + pVar = pBasic->GetRtl()->Find( aName4, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // Ueber alle Sub-Basics gehen + SbxArray* pObjs = pBasic->GetObjects(); + sal_uInt16 nCount = pObjs->Count(); + for( sal_uInt16 i = 0 ; i < nCount ; i++ ) + { + SbxVariable* pObjVar = pObjs->Get( i ); + StarBASIC* pSubBasic = PTR_CAST( StarBASIC, pObjVar ); + if( pSubBasic ) + ClearUnoObjectsInRTL_Impl_Rek( pSubBasic ); + } +} + +void ClearUnoObjectsInRTL_Impl( StarBASIC* pBasic ) +{ + // #67781 Rueckgabewerte der Uno-Methoden loeschen + clearUnoMethods(); + clearUnoServiceCtors(); + + ClearUnoObjectsInRTL_Impl_Rek( pBasic ); + + // Oberstes Basic suchen + SbxObject* p = pBasic; + while( p->GetParent() ) + p = p->GetParent(); + if( ((StarBASIC*)p) != pBasic ) + ClearUnoObjectsInRTL_Impl_Rek( (StarBASIC*)p ); +} +sal_Bool SbModule::IsVBACompat() const +{ + return mbVBACompat; +} + +void SbModule::SetVBACompat( sal_Bool bCompat ) +{ + mbVBACompat = bCompat; +} +// Ausfuehren eines BASIC-Unterprogramms +sal_uInt16 SbModule::Run( SbMethod* pMeth ) +{ + static sal_uInt16 nMaxCallLevel = 0; + static String aMSOMacroRuntimeLibName = String::CreateFromAscii( "Launcher" ); + static String aMSOMacroRuntimeAppSymbol = String::CreateFromAscii( "Application" ); + + sal_uInt16 nRes = 0; + sal_Bool bDelInst = sal_Bool( pINST == NULL ); + StarBASICRef xBasic; + if( bDelInst ) + { +#ifdef DBG_TRACE_BASIC + dbg_InitTrace(); +#endif + // #32779: Basic waehrend der Ausfuehrung festhalten + xBasic = (StarBASIC*) GetParent(); + + pINST = new SbiInstance( (StarBASIC*) GetParent() ); + + // Launcher problem + // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already + sal_Bool bWasError = SbxBase::GetError() != 0; + SbxVariable* pMSOMacroRuntimeLibVar = Find( aMSOMacroRuntimeLibName, SbxCLASS_OBJECT ); + if ( !bWasError && (SbxBase::GetError() == SbxERR_PROC_UNDEFINED) ) + SbxBase::ResetError(); + if( pMSOMacroRuntimeLibVar ) + { + StarBASIC* pMSOMacroRuntimeLib = PTR_CAST(StarBASIC,pMSOMacroRuntimeLibVar); + if( pMSOMacroRuntimeLib ) + { + sal_uInt16 nGblFlag = pMSOMacroRuntimeLib->GetFlags() & SBX_GBLSEARCH; + pMSOMacroRuntimeLib->ResetFlag( SBX_GBLSEARCH ); + SbxVariable* pAppSymbol = pMSOMacroRuntimeLib->Find( aMSOMacroRuntimeAppSymbol, SbxCLASS_METHOD ); + pMSOMacroRuntimeLib->SetFlag( nGblFlag ); + if( pAppSymbol ) + { + pMSOMacroRuntimeLib->SetFlag( SBX_EXTSEARCH ); // Could have been disabled before + GetSbData()->pMSOMacroRuntimLib = pMSOMacroRuntimeLib; + } + } + } + + // Error-Stack loeschen + SbErrorStack*& rErrStack = GetSbData()->pErrStack; + delete rErrStack; + rErrStack = NULL; + + if( nMaxCallLevel == 0 ) + { +#ifdef UNX + struct rlimit rl; + getrlimit ( RLIMIT_STACK, &rl ); + // printf( "RLIMIT_STACK = %ld\n", rl.rlim_cur ); +#endif +#if defined LINUX + // Empiric value, 900 = needed bytes/Basic call level + // for Linux including 10% safety margin + nMaxCallLevel = rl.rlim_cur / 900; +#elif defined SOLARIS + // Empiric value, 1650 = needed bytes/Basic call level + // for Solaris including 10% safety margin + nMaxCallLevel = rl.rlim_cur / 1650; +#elif defined WIN32 + nMaxCallLevel = 5800; +#else + nMaxCallLevel = MAXRECURSION; +#endif + } + } + + // Rekursion zu tief? + if( ++pINST->nCallLvl <= nMaxCallLevel ) + { + // Globale Variable in allen Mods definieren + GlobalRunInit( /* bBasicStart = */ bDelInst ); + + // Trat ein Compiler-Fehler auf? Dann starten wir nicht + if( GetSbData()->bGlobalInitErr == sal_False ) + { + if( bDelInst ) + { + SendHint( GetParent(), SBX_HINT_BASICSTART, pMeth ); + + // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out + // Erklaerung siehe runtime.cxx bei SbiInstance::CalcBreakCallLevel() + // BreakCallLevel ermitteln + pINST->CalcBreakCallLevel( pMeth->GetDebugFlags() ); + } + + SbModule* pOldMod = pMOD; + pMOD = this; + SbiRuntime* pRt = new SbiRuntime( this, pMeth, pMeth->nStart ); + +#ifdef DBG_TRACE_BASIC + dbg_traceNotifyCall( this, pMeth, pINST->nCallLvl ); +#endif + + pRt->pNext = pINST->pRun; + if( pRt->pNext ) + pRt->pNext->block(); + pINST->pRun = pRt; + if ( mbVBACompat ) + { + pINST->EnableCompatibility( sal_True ); + } + while( pRt->Step() ) {} + if( pRt->pNext ) + pRt->pNext->unblock(); + +#ifdef DBG_TRACE_BASIC + bool bLeave = true; + dbg_traceNotifyCall( this, pMeth, pINST->nCallLvl, bLeave ); +#endif + + // #63710 Durch ein anderes Thread-Handling bei Events kann es passieren, + // dass show-Aufruf an einem Dialog zurueckkehrt (durch schliessen des + // Dialogs per UI), BEVOR ein per Event ausgeloester weitergehender Call, + // der in Basic weiter oben im Stack steht und auf einen Basic-Breakpoint + // gelaufen ist, zurueckkehrt. Dann wird unten die Instanz zerstoert und + // wenn das noch im Call stehende Basic weiterlaeuft, gibt es einen GPF. + // Daher muss hier gewartet werden, bis andere Call zurueckkehrt. + if( bDelInst ) + { + // Hier mit 1 statt 0 vergleichen, da vor nCallLvl-- + while( pINST->nCallLvl != 1 ) + GetpApp()->Yield(); + } + + nRes = sal_True; + pINST->pRun = pRt->pNext; + pINST->nCallLvl--; // Call-Level wieder runter + + // Gibt es eine uebergeordnete Runtime-Instanz? + // Dann SbDEBUG_BREAK uebernehmen, wenn gesetzt + SbiRuntime* pRtNext = pRt->pNext; + if( pRtNext && (pRt->GetDebugFlags() & SbDEBUG_BREAK) ) + pRtNext->SetDebugFlags( SbDEBUG_BREAK ); + + delete pRt; + pMOD = pOldMod; + if( bDelInst ) + { + // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, + // beim Programm-Ende freigeben, damit nichts gehalten wird. + ClearUnoObjectsInRTL_Impl( xBasic ); + + clearNativeObjectWrapperVector(); + + DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0"); + delete pINST, pINST = NULL, bDelInst = sal_False; + + // #i30690 + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth ); + + GlobalRunDeInit(); + + // VBA always ensures screenupdating is enabled after completing + if ( mbVBACompat ) + VBAUnlockControllers( PTR_CAST( StarBASIC, GetParent() ) ); + +#ifdef DBG_TRACE_BASIC + dbg_DeInitTrace(); +#endif + } + } + else + pINST->nCallLvl--; // Call-Level wieder runter + } + else + { + pINST->nCallLvl--; // Call-Level wieder runter + StarBASIC::FatalError( SbERR_STACK_OVERFLOW ); + } + + StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent()); + if( bDelInst ) + { + // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, + // beim Programm-Ende freigeben, damit nichts gehalten wird. + ClearUnoObjectsInRTL_Impl( xBasic ); + + delete pINST; + pINST = NULL; + } + if ( pBasic && pBasic->IsDocBasic() && pBasic->IsQuitApplication() && !pINST ) + { + Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ), NULL ); + } + + return nRes; +} + +// Ausfuehren der Init-Methode eines Moduls nach dem Laden +// oder der Compilation + +void SbModule::RunInit() +{ + if( pImage + && !pImage->bInit + && pImage->GetFlag( SBIMG_INITCODE ) ) + { + // Flag setzen, dass RunInit aktiv ist (Testtool) + GetSbData()->bRunInit = sal_True; + + // sal_Bool bDelInst = sal_Bool( pINST == NULL ); + // if( bDelInst ) + // pINST = new SbiInstance( (StarBASIC*) GetParent() ); + SbModule* pOldMod = pMOD; + pMOD = this; + // Der Init-Code beginnt immer hier + SbiRuntime* pRt = new SbiRuntime( this, NULL, 0 ); + +#ifdef DBG_TRACE_BASIC + dbg_traceNotifyCall( this, NULL, 0 ); +#endif + + pRt->pNext = pINST->pRun; + pINST->pRun = pRt; + while( pRt->Step() ) {} + +#ifdef DBG_TRACE_BASIC + bool bLeave = true; + dbg_traceNotifyCall( this, NULL, 0, bLeave ); +#endif + + pINST->pRun = pRt->pNext; + delete pRt; + pMOD = pOldMod; + // if( bDelInst ) + // delete pINST, pINST = NULL; + pImage->bInit = sal_True; + pImage->bFirstInit = sal_False; + + // RunInit ist nicht mehr aktiv + GetSbData()->bRunInit = sal_False; + } +} + +// Mit private/dim deklarierte Variablen loeschen + +void SbModule::AddVarName( const String& aName ) +{ + // see if the name is added allready + std::vector< String >::iterator it_end = mModuleVariableNames.end(); + for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it ) + { + if ( aName == *it ) + return; + } + mModuleVariableNames.push_back( aName ); +} + +void SbModule::RemoveVars() +{ + std::vector< String >::iterator it_end = mModuleVariableNames.end(); + for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it ) + { + // We don't want a Find being called in a derived class ( e.g. + // SbUserform because it could trigger say an initialise event + // which would cause basic to be re-run in the middle of the init ( and remember RemoveVars is called from compile and we don't want code to run as part of the compile ) + SbxVariableRef p = SbModule::Find( *it, SbxCLASS_PROPERTY ); + if( p.Is() ) + Remove (p); + } +} + +void SbModule::ClearPrivateVars() +{ + for( sal_uInt16 i = 0 ; i < pProps->Count() ; i++ ) + { + SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) ); + if( p ) + { + // Arrays nicht loeschen, sondern nur deren Inhalt + if( p->GetType() & SbxARRAY ) + { + SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject()); + if( pArray ) + { + for( sal_uInt16 j = 0 ; j < pArray->Count() ; j++ ) + { + SbxVariable* pj = PTR_CAST(SbxVariable,pArray->Get( j )); + pj->SbxValue::Clear(); + /* + sal_uInt16 nFlags = pj->GetFlags(); + pj->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) ); + pj->PutEmpty(); + pj->SetFlags( nFlags ); + */ + } + } + } + else + { + p->SbxValue::Clear(); + /* + sal_uInt16 nFlags = p->GetFlags(); + p->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) ); + p->PutEmpty(); + p->SetFlags( nFlags ); + */ + } + } + } +} + +void SbModule::implClearIfVarDependsOnDeletedBasic( SbxVariable* pVar, StarBASIC* pDeletedBasic ) +{ + if( pVar->SbxValue::GetType() != SbxOBJECT || pVar->ISA( SbProcedureProperty ) ) + return; + + SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject()); + if( pObj != NULL ) + { + SbxObject* p = pObj; + + SbModule* pMod = PTR_CAST( SbModule, p ); + if( pMod != NULL ) + pMod->ClearVarsDependingOnDeletedBasic( pDeletedBasic ); + + while( (p = p->GetParent()) != NULL ) + { + StarBASIC* pBasic = PTR_CAST( StarBASIC, p ); + if( pBasic != NULL && pBasic == pDeletedBasic ) + { + pVar->SbxValue::Clear(); + break; + } + } + } +} + +void SbModule::ClearVarsDependingOnDeletedBasic( StarBASIC* pDeletedBasic ) +{ + (void)pDeletedBasic; + + for( sal_uInt16 i = 0 ; i < pProps->Count() ; i++ ) + { + SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) ); + if( p ) + { + if( p->GetType() & SbxARRAY ) + { + SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject()); + if( pArray ) + { + for( sal_uInt16 j = 0 ; j < pArray->Count() ; j++ ) + { + SbxVariable* pVar = PTR_CAST(SbxVariable,pArray->Get( j )); + implClearIfVarDependsOnDeletedBasic( pVar, pDeletedBasic ); + } + } + } + else + { + implClearIfVarDependsOnDeletedBasic( p, pDeletedBasic ); + } + } + } +} + +// Zunaechst in dieses Modul, um 358-faehig zu bleiben +// (Branch in sb.cxx vermeiden) +void StarBASIC::ClearAllModuleVars( void ) +{ + // Eigene Module initialisieren + for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + // Nur initialisieren, wenn der Startcode schon ausgefuehrt wurde + if( pModule->pImage && pModule->pImage->bInit && !pModule->isProxyModule() && !pModule->ISA(SbObjModule) ) + pModule->ClearPrivateVars(); + } + + /* #88042 This code can delete already used public vars during runtime! + // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt + // Wenn ja, auch dort initialisieren + for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic ) + pBasic->ClearAllModuleVars(); + } + */ +} + +// Ausfuehren des Init-Codes aller Module +void SbModule::GlobalRunInit( sal_Bool bBasicStart ) +{ + // Wenn kein Basic-Start, nur initialisieren, wenn Modul uninitialisiert + if( !bBasicStart ) + if( !(pImage && !pImage->bInit) ) + return; + + // GlobalInitErr-Flag fuer Compiler-Error initialisieren + // Anhand dieses Flags kann in SbModule::Run() nach dem Aufruf + // von GlobalRunInit festgestellt werden, ob beim initialisieren + // der Module ein Fehler auftrat. Dann wird nicht gestartet. + GetSbData()->bGlobalInitErr = sal_False; + + // Parent vom Modul ist ein Basic + StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent()); + if( pBasic ) + { + pBasic->InitAllModules(); + + SbxObject* pParent_ = pBasic->GetParent(); + if( pParent_ ) + { + StarBASIC * pParentBasic = PTR_CAST(StarBASIC,pParent_); + if( pParentBasic ) + { + pParentBasic->InitAllModules( pBasic ); + + // #109018 Parent can also have a parent (library in doc) + SbxObject* pParentParent = pParentBasic->GetParent(); + if( pParentParent ) + { + StarBASIC * pParentParentBasic = PTR_CAST(StarBASIC,pParentParent); + if( pParentParentBasic ) + pParentParentBasic->InitAllModules( pParentBasic ); + } + } + } + } +} + +void SbModule::GlobalRunDeInit( void ) +{ + StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent()); + if( pBasic ) + { + pBasic->DeInitAllModules(); + + SbxObject* pParent_ = pBasic->GetParent(); + if( pParent_ ) + pBasic = PTR_CAST(StarBASIC,pParent_); + if( pBasic ) + pBasic->DeInitAllModules(); + } +} + +// Suche nach dem naechsten STMNT-Befehl im Code. Wird vom STMNT- +// Opcode verwendet, um die Endspalte zu setzen. + +const sal_uInt8* SbModule::FindNextStmnt( const sal_uInt8* p, sal_uInt16& nLine, sal_uInt16& nCol ) const +{ + return FindNextStmnt( p, nLine, nCol, sal_False ); +} + +const sal_uInt8* SbModule::FindNextStmnt( const sal_uInt8* p, sal_uInt16& nLine, sal_uInt16& nCol, + sal_Bool bFollowJumps, const SbiImage* pImg ) const +{ + sal_uInt32 nPC = (sal_uInt32) ( p - (const sal_uInt8*) pImage->GetCode() ); + while( nPC < pImage->GetCodeSize() ) + { + SbiOpcode eOp = (SbiOpcode ) ( *p++ ); + nPC++; + if( bFollowJumps && eOp == _JUMP && pImg ) + { + DBG_ASSERT( pImg, "FindNextStmnt: pImg==NULL with FollowJumps option" ); + sal_uInt32 nOp1 = *p++; nOp1 |= *p++ << 8; + nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; + p = (const sal_uInt8*) pImg->GetCode() + nOp1; + } + else if( eOp >= SbOP1_START && eOp <= SbOP1_END ) + p += 4, nPC += 4; + else if( eOp == _STMNT ) + { + sal_uInt32 nl, nc; + nl = *p++; nl |= *p++ << 8; + nl |= *p++ << 16 ; nl |= *p++ << 24; + nc = *p++; nc |= *p++ << 8; + nc |= *p++ << 16 ; nc |= *p++ << 24; + nLine = (sal_uInt16)nl; nCol = (sal_uInt16)nc; + return p; + } + else if( eOp >= SbOP2_START && eOp <= SbOP2_END ) + p += 8, nPC += 8; + else if( !( eOp >= SbOP0_START && eOp <= SbOP0_END ) ) + { + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + break; + } + } + return NULL; +} + +// Testen, ob eine Zeile STMNT-Opcodes enthaelt + +sal_Bool SbModule::IsBreakable( sal_uInt16 nLine ) const +{ + if( !pImage ) + return sal_False; + const sal_uInt8* p = (const sal_uInt8* ) pImage->GetCode(); + sal_uInt16 nl, nc; + while( ( p = FindNextStmnt( p, nl, nc ) ) != NULL ) + if( nl == nLine ) + return sal_True; + return sal_False; +} + +size_t SbModule::GetBPCount() const +{ + return pBreaks ? pBreaks->size() : 0; +} + +sal_uInt16 SbModule::GetBP( size_t n ) const +{ + if( pBreaks && n < pBreaks->size() ) + return pBreaks->operator[]( n ); + else + return 0; +} + +sal_Bool SbModule::IsBP( sal_uInt16 nLine ) const +{ + if( pBreaks ) + { + for( size_t i = 0; i < pBreaks->size(); i++ ) + { + sal_uInt16 b = pBreaks->operator[]( i ); + if( b == nLine ) + return sal_True; + if( b < nLine ) + break; + } + } + return sal_False; +} + +sal_Bool SbModule::SetBP( sal_uInt16 nLine ) +{ + if( !IsBreakable( nLine ) ) + return sal_False; + if( !pBreaks ) + pBreaks = new SbiBreakpoints; + size_t i; + for( i = 0; i < pBreaks->size(); i++ ) + { + sal_uInt16 b = pBreaks->operator[]( i ); + if( b == nLine ) + return sal_True; + if( b < nLine ) + break; + } + pBreaks->insert( pBreaks->begin() + i, nLine ); + + // #38568: Zur Laufzeit auch hier SbDEBUG_BREAK setzen + if( pINST && pINST->pRun ) + pINST->pRun->SetDebugFlags( SbDEBUG_BREAK ); + + return IsBreakable( nLine ); +} + +sal_Bool SbModule::ClearBP( sal_uInt16 nLine ) +{ + sal_Bool bRes = sal_False; + if( pBreaks ) + { + for( size_t i = 0; i < pBreaks->size(); i++ ) + { + sal_uInt16 b = pBreaks->operator[]( i ); + if( b == nLine ) + { + pBreaks->erase( pBreaks->begin() + i ); + bRes = sal_True; + break; + } + if( b < nLine ) + break; + } + if( pBreaks->empty() ) + delete pBreaks, pBreaks = NULL; + } + return bRes; +} + +void SbModule::ClearAllBP() +{ + delete pBreaks; + pBreaks = NULL; +} + +void +SbModule::fixUpMethodStart( bool bCvtToLegacy, SbiImage* pImg ) const +{ + if ( !pImg ) + pImg = pImage; + for( sal_uInt32 i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* pMeth = PTR_CAST(SbMethod,pMethods->Get( (sal_uInt16)i ) ); + if( pMeth ) + { + //fixup method start positions + if ( bCvtToLegacy ) + pMeth->nStart = pImg->CalcLegacyOffset( pMeth->nStart ); + else + pMeth->nStart = pImg->CalcNewOffset( (sal_uInt16)pMeth->nStart ); + } + } + +} + +sal_Bool SbModule::LoadData( SvStream& rStrm, sal_uInt16 nVer ) +{ + Clear(); + if( !SbxObject::LoadData( rStrm, 1 ) ) + return sal_False; + // Precaution... + SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH ); + sal_uInt8 bImage; + rStrm >> bImage; + if( bImage ) + { + SbiImage* p = new SbiImage; + sal_uInt32 nImgVer = 0; + + if( !p->Load( rStrm, nImgVer ) ) + { + delete p; + return sal_False; + } + // If the image is in old format, we fix up the method start offsets + if ( nImgVer < B_EXT_IMG_VERSION ) + { + fixUpMethodStart( false, p ); + p->ReleaseLegacyBuffer(); + } + aComment = p->aComment; + SetName( p->aName ); + if( p->GetCodeSize() ) + { + aOUSource = p->aOUSource; + // Alte Version: Image weg + if( nVer == 1 ) + { + SetSource32( p->aOUSource ); + delete p; + } + else + pImage = p; + } + else + { + SetSource32( p->aOUSource ); + delete p; + } + } + return sal_True; +} + +sal_Bool SbModule::StoreData( SvStream& rStrm ) const +{ + sal_Bool bFixup = ( pImage && !pImage->ExceedsLegacyLimits() ); + if ( bFixup ) + fixUpMethodStart( true ); + sal_Bool bRet = SbxObject::StoreData( rStrm ); + if ( !bRet ) + return sal_False; + + if( pImage ) + { + pImage->aOUSource = aOUSource; + pImage->aComment = aComment; + pImage->aName = GetName(); + rStrm << (sal_uInt8) 1; + // # PCode is saved only for legacy formats only + // It should be noted that it probably isn't necessary + // It would be better not to store the image ( more flexible with + // formats ) + bool bRes = pImage->Save( rStrm, B_LEGACYVERSION ); + if ( bFixup ) + fixUpMethodStart( false ); // restore method starts + return bRes; + + } + else + { + SbiImage aImg; + aImg.aOUSource = aOUSource; + aImg.aComment = aComment; + aImg.aName = GetName(); + rStrm << (sal_uInt8) 1; + return aImg.Save( rStrm ); + } +} + +sal_Bool SbModule::ExceedsLegacyModuleSize() +{ + if ( !IsCompiled() ) + Compile(); + if ( pImage && pImage->ExceedsLegacyLimits() ) + return true; + return false; +} + + +// Store only image, no source +sal_Bool SbModule::StoreBinaryData( SvStream& rStrm ) +{ + return StoreBinaryData( rStrm, 0 ); +} + +sal_Bool SbModule::StoreBinaryData( SvStream& rStrm, sal_uInt16 nVer ) +{ + sal_Bool bRet = Compile(); + if( bRet ) + { + sal_Bool bFixup = ( !nVer && !pImage->ExceedsLegacyLimits() );// save in old image format, fix up method starts + + if ( bFixup ) // save in old image format, fix up method starts + fixUpMethodStart( true ); + bRet = SbxObject::StoreData( rStrm ); + if( bRet ) + { + pImage->aOUSource = ::rtl::OUString(); + pImage->aComment = aComment; + pImage->aName = GetName(); + + rStrm << (sal_uInt8) 1; + if ( nVer ) + bRet = pImage->Save( rStrm, B_EXT_IMG_VERSION ); + else + bRet = pImage->Save( rStrm, B_LEGACYVERSION ); + if ( bFixup ) + fixUpMethodStart( false ); // restore method starts + + pImage->aOUSource = aOUSource; + } + } + return bRet; +} + +// Called for >= OO 1.0 passwd protected libraries only +// + +sal_Bool SbModule::LoadBinaryData( SvStream& rStrm ) +{ + ::rtl::OUString aKeepSource = aOUSource; + bool bRet = LoadData( rStrm, 2 ); + LoadCompleted(); + aOUSource = aKeepSource; + return bRet; +} + + +sal_Bool SbModule::LoadCompleted() +{ + SbxArray* p = GetMethods(); + sal_uInt16 i; + for( i = 0; i < p->Count(); i++ ) + { + SbMethod* q = PTR_CAST(SbMethod,p->Get( i ) ); + if( q ) + q->pMod = this; + } + p = GetProperties(); + for( i = 0; i < p->Count(); i++ ) + { + SbProperty* q = PTR_CAST(SbProperty,p->Get( i ) ); + if( q ) + q->pMod = this; + } + return sal_True; +} + +void SbModule::handleProcedureProperties( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + bool bDone = false; + + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar ); + if( pProcProperty ) + { + bDone = true; + + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + String aProcName; + aProcName.AppendAscii( "Property Get " ); + aProcName += pProcProperty->GetName(); + + SbxVariable* pMeth = Find( aProcName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + aVals.eType = SbxVARIANT; + + SbxArray* pArg = pVar->GetParameters(); + sal_uInt16 nVarParCount = (pArg != NULL) ? pArg->Count() : 0; + if( nVarParCount > 1 ) + { + SbxArrayRef xMethParameters = new SbxArray; + xMethParameters->Put( pMeth, 0 ); // Method as parameter 0 + for( sal_uInt16 i = 1 ; i < nVarParCount ; ++i ) + { + SbxVariable* pPar = pArg->Get( i ); + xMethParameters->Put( pPar, i ); + } + + pMeth->SetParameters( xMethParameters ); + pMeth->Get( aVals ); + pMeth->SetParameters( NULL ); + } + else + { + pMeth->Get( aVals ); + } + + pVar->Put( aVals ); + } + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + SbxVariable* pMeth = NULL; + + bool bSet = pProcProperty->isSet(); + if( bSet ) + { + pProcProperty->setSet( false ); + + String aProcName; + aProcName.AppendAscii( "Property Set " ); + aProcName += pProcProperty->GetName(); + pMeth = Find( aProcName, SbxCLASS_METHOD ); + } + if( !pMeth ) // Let + { + String aProcName; + aProcName.AppendAscii( "Property Let " ); + aProcName += pProcProperty->GetName(); + pMeth = Find( aProcName, SbxCLASS_METHOD ); + } + + if( pMeth ) + { + // Setup parameters + SbxArrayRef xArray = new SbxArray; + xArray->Put( pMeth, 0 ); // Method as parameter 0 + xArray->Put( pVar, 1 ); + pMeth->SetParameters( xArray ); + + SbxValues aVals; + pMeth->Get( aVals ); + pMeth->SetParameters( NULL ); + } + } + } + } + + if( !bDone ) + SbModule::Notify( rBC, rHint ); +} + + +///////////////////////////////////////////////////////////////////////// +// Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen) +SbJScriptModule::SbJScriptModule( const String& rName ) + :SbModule( rName ) +{ +} + +sal_Bool SbJScriptModule::LoadData( SvStream& rStrm, sal_uInt16 nVer ) +{ + (void)nVer; + + Clear(); + if( !SbxObject::LoadData( rStrm, 1 ) ) + return sal_False; + + // Source-String holen + String aTmp; + rStrm.ReadByteString( aTmp, gsl_getSystemTextEncoding() ); + aOUSource = aTmp; + //rStrm >> aSource; + return sal_True; +} + +sal_Bool SbJScriptModule::StoreData( SvStream& rStrm ) const +{ + if( !SbxObject::StoreData( rStrm ) ) + return sal_False; + + // Source-String schreiben + String aTmp = aOUSource; + rStrm.WriteByteString( aTmp, gsl_getSystemTextEncoding() ); + //rStrm << aSource; + return sal_True; +} + + +///////////////////////////////////////////////////////////////////////// + +SbMethod::SbMethod( const String& r, SbxDataType t, SbModule* p ) + : SbxMethod( r, t ), pMod( p ) +{ + bInvalid = sal_True; + nStart = + nDebugFlags = + nLine1 = + nLine2 = 0; + refStatics = new SbxArray; + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + SetFlag( SBX_NO_MODIFY ); +} + +SbMethod::SbMethod( const SbMethod& r ) + : SvRefBase( r ), SbxMethod( r ) +{ + pMod = r.pMod; + bInvalid = r.bInvalid; + nStart = r.nStart; + nDebugFlags = r.nDebugFlags; + nLine1 = r.nLine1; + nLine2 = r.nLine2; + refStatics = r.refStatics; + SetFlag( SBX_NO_MODIFY ); +} + +SbMethod::~SbMethod() +{ +} + +SbxArray* SbMethod::GetLocals() +{ + if( pINST ) + return pINST->GetLocals( this ); + else + return NULL; +} + +void SbMethod::ClearStatics() +{ + refStatics = new SbxArray; + +} +SbxArray* SbMethod::GetStatics() +{ + return refStatics; +} + +sal_Bool SbMethod::LoadData( SvStream& rStrm, sal_uInt16 nVer ) +{ + if( !SbxMethod::LoadData( rStrm, 1 ) ) + return sal_False; + sal_Int16 n; + rStrm >> n; + sal_Int16 nTempStart = (sal_Int16)nStart; + // nDebugFlags = n; // AB 16.1.96: Nicht mehr uebernehmen + if( nVer == 2 ) + rStrm >> nLine1 >> nLine2 >> nTempStart >> bInvalid; + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + SetFlag( SBX_NO_MODIFY ); + nStart = nTempStart; + return sal_True; +} + +sal_Bool SbMethod::StoreData( SvStream& rStrm ) const +{ + if( !SbxMethod::StoreData( rStrm ) ) + return sal_False; + rStrm << (sal_Int16) nDebugFlags + << (sal_Int16) nLine1 + << (sal_Int16) nLine2 + << (sal_Int16) nStart + << (sal_uInt8) bInvalid; + return sal_True; +} + +void SbMethod::GetLineRange( sal_uInt16& l1, sal_uInt16& l2 ) +{ + l1 = nLine1; l2 = nLine2; +} + +// Kann spaeter mal weg + +SbxInfo* SbMethod::GetInfo() +{ + return pInfo; +} + +// Schnittstelle zum Ausfuehren einer Methode aus den Applikationen +// #34191# Mit speziellem RefCounting, damit das Basic nicht durch CloseDocument() +// abgeschossen werden kann. Rueckgabewert wird als String geliefert. +ErrCode SbMethod::Call( SbxValue* pRet ) +{ + // RefCount vom Modul hochzaehlen + SbModule* pMod_ = (SbModule*)GetParent(); + pMod_->AddRef(); + + // RefCount vom Basic hochzaehlen + StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent(); + pBasic->AddRef(); + + // Values anlegen, um Return-Wert zu erhalten + SbxValues aVals; + aVals.eType = SbxVARIANT; + + // #104083: Compile BEFORE get + if( bInvalid && !pMod_->Compile() ) + StarBASIC::Error( SbERR_BAD_PROP_VALUE ); + + Get( aVals ); + if ( pRet ) + pRet->Put( aVals ); + + // Gab es einen Error + ErrCode nErr = SbxBase::GetError(); + SbxBase::ResetError(); + + // Objekte freigeben + pMod_->ReleaseRef(); + pBasic->ReleaseRef(); + + return nErr; +} + + +// #100883 Own Broadcast for SbMethod +void SbMethod::Broadcast( sal_uIntPtr nHintId ) +{ + if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() ) + { + // Da die Methode von aussen aufrufbar ist, hier noch einmal + // die Berechtigung testen + if( nHintId & SBX_HINT_DATAWANTED ) + if( !CanRead() ) + return; + if( nHintId & SBX_HINT_DATACHANGED ) + if( !CanWrite() ) + return; + + if( pMod && !pMod->IsCompiled() ) + pMod->Compile(); + + // Block broadcasts while creating new method + SfxBroadcaster* pSave = pCst; + pCst = NULL; + SbMethod* pThisCopy = new SbMethod( *this ); + SbMethodRef xHolder = pThisCopy; + if( mpPar.Is() ) + { + // this, als Element 0 eintragen, aber den Parent nicht umsetzen! + if( GetType() != SbxVOID ) + mpPar->PutDirect( pThisCopy, 0 ); + SetParameters( NULL ); + } + + pCst = pSave; + pSave->Broadcast( SbxHint( nHintId, pThisCopy ) ); + + sal_uInt16 nSaveFlags = GetFlags(); + SetFlag( SBX_READWRITE ); + pCst = NULL; + Put( pThisCopy->GetValues_Impl() ); + pCst = pSave; + SetFlags( nSaveFlags ); + } +} + +///////////////////////////////////////////////////////////////////////// + +// Implementation SbJScriptMethod (Method-Klasse als Wrapper fuer JavaScript-Funktionen) + +SbJScriptMethod::SbJScriptMethod( const String& r, SbxDataType t, SbModule* p ) + : SbMethod( r, t, p ) +{ +} + +SbJScriptMethod::~SbJScriptMethod() +{} + + +///////////////////////////////////////////////////////////////////////// +SbObjModule::SbObjModule( const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsVbaCompatible ) + : SbModule( rName, bIsVbaCompatible ) +{ + SetModuleType( mInfo.ModuleType ); + if ( mInfo.ModuleType == script::ModuleType::FORM ) + { + SetClassName( rtl::OUString::createFromAscii( "Form" ) ); + } + else if ( mInfo.ModuleObject.is() ) + SetUnoObject( uno::makeAny( mInfo.ModuleObject ) ); +} + +SbObjModule::~SbObjModule() +{ +} + +void +SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException ) +{ + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxVariable*)pDocObject); + if ( pUnoObj && pUnoObj->getUnoAny() == aObj ) // object is equal, nothing to do + return; + pDocObject = new SbUnoObject( GetName(), uno::makeAny( aObj ) ); + + com::sun::star::uno::Reference< com::sun::star::lang::XServiceInfo > xServiceInfo( aObj, com::sun::star::uno::UNO_QUERY_THROW ); + if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Worksheet" ) ) ) + { + SetClassName( rtl::OUString::createFromAscii( "Worksheet" ) ); + } + else if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Workbook" ) ) ) + { + SetClassName( rtl::OUString::createFromAscii( "Workbook" ) ); + } +} + +SbxVariable* +SbObjModule::GetObject() +{ + return pDocObject; +} +SbxVariable* +SbObjModule::Find( const XubString& rName, SbxClassType t ) +{ + //OSL_TRACE("SbObjectModule find for %s", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() ); + SbxVariable* pVar = NULL; + if ( pDocObject) + pVar = pDocObject->Find( rName, t ); + if ( !pVar ) + pVar = SbModule::Find( rName, t ); + return pVar; +} + +void SbObjModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + SbModule::handleProcedureProperties( rBC, rHint ); +} + + +typedef ::cppu::WeakImplHelper2< awt::XTopWindowListener, awt::XWindowListener > FormObjEventListener_BASE; + +class FormObjEventListenerImpl : public FormObjEventListener_BASE +{ + SbUserFormModule* mpUserForm; + uno::Reference< lang::XComponent > mxComponent; + bool mbDisposed; + sal_Bool mbOpened; + sal_Bool mbActivated; + sal_Bool mbShowing; + FormObjEventListenerImpl(); // not defined + FormObjEventListenerImpl(const FormObjEventListenerImpl&); // not defined + +public: + FormObjEventListenerImpl( SbUserFormModule* pUserForm, const uno::Reference< lang::XComponent >& xComponent ) : + mpUserForm( pUserForm ), mxComponent( xComponent) , + mbDisposed( false ), mbOpened( sal_False ), mbActivated( sal_False ), mbShowing( sal_False ) + { + if ( mxComponent.is() ) + { + OSL_TRACE("*********** Registering the listeners"); + try + { + uno::Reference< awt::XTopWindow >( mxComponent, uno::UNO_QUERY_THROW )->addTopWindowListener( this ); + } + catch( uno::Exception& ) {} + try + { + uno::Reference< awt::XWindow >( mxComponent, uno::UNO_QUERY_THROW )->addWindowListener( this ); + } + catch( uno::Exception& ) {} + } + } + + virtual ~FormObjEventListenerImpl() + { + removeListener(); + } + + sal_Bool isShowing() const { return mbShowing; } + + void removeListener() + { + if ( mxComponent.is() && !mbDisposed ) + { + OSL_TRACE("*********** Removing the listeners"); + try + { + uno::Reference< awt::XTopWindow >( mxComponent, uno::UNO_QUERY_THROW )->removeTopWindowListener( this ); + } + catch( uno::Exception& ) {} + try + { + uno::Reference< awt::XWindow >( mxComponent, uno::UNO_QUERY_THROW )->removeWindowListener( this ); + } + catch( uno::Exception& ) {} + } + mxComponent.clear(); + } + + virtual void SAL_CALL windowOpened( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + if ( mpUserForm ) + { + mbOpened = sal_True; + mbShowing = sal_True; + if ( mbActivated ) + { + mbOpened = mbActivated = sal_False; + mpUserForm->triggerActivateEvent(); + } + } + } + + //liuchen 2009-7-21, support Excel VBA Form_QueryClose event + virtual void SAL_CALL windowClosing( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { +#if IN_THE_FUTURE + uno::Reference< awt::XDialog > xDialog( e.Source, uno::UNO_QUERY ); + if ( xDialog.is() ) + { + uno::Reference< awt::XControl > xControl( xDialog, uno::UNO_QUERY ); + if ( xControl->getPeer().is() ) + { + uno::Reference< document::XVbaMethodParameter > xVbaMethodParameter( xControl->getPeer(), uno::UNO_QUERY ); + if ( xVbaMethodParameter.is() ) + { + sal_Int8 nCancel = 0; + sal_Int8 nCloseMode = 0; + + Sequence< Any > aParams; + aParams.realloc(2); + aParams[0] <<= nCancel; + aParams[1] <<= nCloseMode; + + mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), + aParams); + xVbaMethodParameter->setVbaMethodParameter( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Cancel")), aParams[0]); + return; + + } + } + } + + mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ) ); +#endif + } + //liuchen 2009-7-21 + + virtual void SAL_CALL windowClosed( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + mbOpened = sal_False; + mbShowing = sal_False; + } + + virtual void SAL_CALL windowMinimized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + } + + virtual void SAL_CALL windowNormalized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + } + + virtual void SAL_CALL windowActivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + if ( mpUserForm ) + { + mbActivated = sal_True; + if ( mbOpened ) + { + mbOpened = mbActivated = sal_False; + mpUserForm->triggerActivateEvent(); + } + } + } + + virtual void SAL_CALL windowDeactivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + if ( mpUserForm ) + mpUserForm->triggerDeactivateEvent(); + } + + virtual void SAL_CALL windowResized( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException) + { + if ( mpUserForm ) + { + mpUserForm->triggerResizeEvent(); + mpUserForm->triggerLayoutEvent(); + } + } + + virtual void SAL_CALL windowMoved( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException) + { + if ( mpUserForm ) + mpUserForm->triggerLayoutEvent(); + } + + virtual void SAL_CALL windowShown( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + } + + virtual void SAL_CALL windowHidden( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) + { + } + + virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) + { + OSL_TRACE("** Userform/Dialog disposing"); + mbDisposed = true; + mxComponent.clear(); + if ( mpUserForm ) + mpUserForm->ResetApiObj(); + } +}; + +SbUserFormModule::SbUserFormModule( const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsCompat ) + : SbObjModule( rName, mInfo, bIsCompat ) + , m_mInfo( mInfo ) + , mbInit( false ) +{ + m_xModel.set( mInfo.ModuleObject, uno::UNO_QUERY_THROW ); +} + +SbUserFormModule::~SbUserFormModule() +{ +} + +void SbUserFormModule::ResetApiObj( bool bTriggerTerminateEvent ) +{ + if ( bTriggerTerminateEvent && m_xDialog.is() ) // probably someone close the dialog window + { + triggerTerminateEvent(); + } + pDocObject = NULL; + m_xDialog = NULL; +} + +void SbUserFormModule::triggerMethod( const String& aMethodToRun ) +{ + Sequence< Any > aArguments; + triggerMethod( aMethodToRun, aArguments ); +} +void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any >& /*aArguments*/) +{ + OSL_TRACE("*** trigger %s ***", rtl::OUStringToOString( aMethodToRun, RTL_TEXTENCODING_UTF8 ).getStr() ); + // Search method + SbxVariable* pMeth = SbObjModule::Find( aMethodToRun, SbxCLASS_METHOD ); + if( pMeth ) + { +#if IN_THE_FUTURE + //liuchen 2009-7-21, support Excel VBA UserForm_QueryClose event with parameters + if ( aArguments.getLength() > 0 ) // Setup parameters + { + SbxArrayRef xArray = new SbxArray; + xArray->Put( pMeth, 0 ); // Method as parameter 0 + + for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i ) + { + SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), aArguments[i] ); + xArray->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 ); + + // Enable passing by ref + if ( xSbxVar->GetType() != SbxVARIANT ) + xSbxVar->SetFlag( SBX_FIXED ); + } + pMeth->SetParameters( xArray ); + + SbxValues aVals; + pMeth->Get( aVals ); + + for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i ) + { + aArguments[i] = sbxToUnoValue( xArray->Get( static_cast< sal_uInt16 >(i) + 1) ); + } + pMeth->SetParameters( NULL ); + } + else +//liuchen 2009-7-21 +#endif + { + SbxValues aVals; + pMeth->Get( aVals ); + } + } +} + +void SbUserFormModule::triggerActivateEvent( void ) +{ + OSL_TRACE("**** entering SbUserFormModule::triggerActivate"); + triggerMethod( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm_Activate") ) ); + OSL_TRACE("**** leaving SbUserFormModule::triggerActivate"); +} + +void SbUserFormModule::triggerDeactivateEvent( void ) +{ + OSL_TRACE("**** SbUserFormModule::triggerDeactivate"); + triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_Deactivate") ) ); +} + +void SbUserFormModule::triggerInitializeEvent( void ) +{ + if ( mbInit ) + return; + OSL_TRACE("**** SbUserFormModule::triggerInitializeEvent"); + static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Initialize") ); + triggerMethod( aInitMethodName ); + mbInit = true; +} + +void SbUserFormModule::triggerTerminateEvent( void ) +{ + OSL_TRACE("**** SbUserFormModule::triggerTerminateEvent"); + static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Terminate") ); + triggerMethod( aTermMethodName ); + mbInit=false; +} + +void SbUserFormModule::triggerLayoutEvent( void ) +{ + static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Layout") ); + triggerMethod( aMethodName ); +} + +void SbUserFormModule::triggerResizeEvent( void ) +{ + static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Resize") ); + triggerMethod( aMethodName ); +} + +SbUserFormModuleInstance* SbUserFormModule::CreateInstance() +{ + SbUserFormModuleInstance* pInstance = new SbUserFormModuleInstance( this, GetName(), m_mInfo, IsVBACompat() ); + return pInstance; +} + +SbUserFormModuleInstance::SbUserFormModuleInstance( SbUserFormModule* pParentModule, + const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsVBACompat ) + : SbUserFormModule( rName, mInfo, bIsVBACompat ) + , m_pParentModule( pParentModule ) +{ +} + +sal_Bool SbUserFormModuleInstance::IsClass( const XubString& rName ) const +{ + sal_Bool bParentNameMatches = m_pParentModule->GetName().EqualsIgnoreCaseAscii( rName ); + sal_Bool bRet = bParentNameMatches || SbxObject::IsClass( rName ); + return bRet; +} + +SbxVariable* SbUserFormModuleInstance::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pVar = m_pParentModule->Find( rName, t ); + return pVar; +} + + +void SbUserFormModule::Load() +{ + OSL_TRACE("** load() "); + // forces a load + if ( !pDocObject ) + InitObject(); +} + +//liuchen 2009-7-21 change to accmordate VBA's beheavior +void SbUserFormModule::Unload() +{ + OSL_TRACE("** Unload() "); + + sal_Int8 nCancel = 0; + sal_Int8 nCloseMode = 1; + + Sequence< Any > aParams; + aParams.realloc(2); + aParams[0] <<= nCancel; + aParams[1] <<= nCloseMode; + + triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), aParams); + + aParams[0] >>= nCancel; + if (nCancel == 1) + { + return; + } + + if ( m_xDialog.is() ) + { + triggerTerminateEvent(); + } + // Search method + SbxVariable* pMeth = SbObjModule::Find( String( RTL_CONSTASCII_USTRINGPARAM( "UnloadObject" ) ), SbxCLASS_METHOD ); + if( pMeth ) + { + OSL_TRACE("Attempting too run the UnloadObjectMethod"); + m_xDialog.clear(); //release ref to the uno object + SbxValues aVals; + bool bWaitForDispose = true; // assume dialog is showing + if ( m_DialogListener.get() ) + { + bWaitForDispose = m_DialogListener->isShowing(); + OSL_TRACE("Showing %d", bWaitForDispose ); + } + pMeth->Get( aVals); + if ( !bWaitForDispose ) + { + // we've either already got a dispose or we'er never going to get one + ResetApiObj(); + } // else wait for dispose + OSL_TRACE("UnloadObject completed ( we hope )"); + } +} +//liuchen + +void registerComponentToBeDisposedForBasic( Reference< XComponent > xComponent, StarBASIC* pBasic ); + +void SbUserFormModule::InitObject() +{ + try + { + String aHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) ); + SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE ); + if ( m_xModel.is() && pGlobs ) + { + + uno::Reference< lang::XMultiServiceFactory > xVBAFactory( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW ); + uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + uno::Sequence< uno::Any > aArgs(1); + aArgs[ 0 ] <<= m_xModel; + rtl::OUString sDialogUrl( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.script:" ) ); + rtl::OUString sProjectName( RTL_CONSTASCII_USTRINGPARAM("Standard") ); + if ( this->GetParent()->GetName().Len() ) + sProjectName = this->GetParent()->GetName(); + sDialogUrl = sDialogUrl.concat( sProjectName ).concat( rtl::OUString( '.') ).concat( GetName() ).concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("?location=document") ) ); + + uno::Reference< awt::XDialogProvider > xProvider( xFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.DialogProvider")), aArgs ), uno::UNO_QUERY_THROW ); + m_xDialog = xProvider->createDialog( sDialogUrl ); + + // create vba api object + aArgs.realloc( 4 ); + aArgs[ 0 ] = uno::Any(); + aArgs[ 1 ] <<= m_xDialog; + aArgs[ 2 ] <<= m_xModel; + aArgs[ 3 ] <<= rtl::OUString( GetParent()->GetName() ); + pDocObject = new SbUnoObject( GetName(), uno::makeAny( xVBAFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.UserForm")), aArgs ) ) ); + uno::Reference< lang::XComponent > xComponent( aArgs[ 1 ], uno::UNO_QUERY_THROW ); + + // the dialog must be disposed at the end! + if( xComponent.is() ) + { + StarBASIC* pParentBasic = NULL; + SbxObject* pCurObject = this; + do + { + SbxObject* pObjParent = pCurObject->GetParent(); + pParentBasic = PTR_CAST( StarBASIC, pObjParent ); + pCurObject = pObjParent; + } + while( pParentBasic == NULL && pCurObject != NULL ); + + OSL_ASSERT( pParentBasic != NULL ); + registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); + } + + + // remove old listener if it exists + if ( m_DialogListener.get() ) + m_DialogListener->removeListener(); + m_DialogListener = new FormObjEventListenerImpl( this, xComponent ); + + triggerInitializeEvent(); + } + } + catch( uno::Exception& ) + { + } + +} + +SbxVariable* +SbUserFormModule::Find( const XubString& rName, SbxClassType t ) +{ + if ( !pDocObject && !GetSbData()->bRunInit && pINST ) + InitObject(); + return SbObjModule::Find( rName, t ); +} +///////////////////////////////////////////////////////////////////////// + +SbProperty::SbProperty( const String& r, SbxDataType t, SbModule* p ) + : SbxProperty( r, t ), pMod( p ) +{ + bInvalid = sal_False; +} + +SbProperty::~SbProperty() +{} + +///////////////////////////////////////////////////////////////////////// + +SbProcedureProperty::~SbProcedureProperty() +{} + |