summaryrefslogtreecommitdiff
path: root/basic/source/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/runtime')
-rw-r--r--basic/source/runtime/basrdll.cxx104
-rw-r--r--basic/source/runtime/ddectrl.cxx192
-rw-r--r--basic/source/runtime/ddectrl.hxx64
-rw-r--r--basic/source/runtime/dllmgr.cxx738
-rw-r--r--basic/source/runtime/dllmgr.hxx60
-rw-r--r--basic/source/runtime/inputbox.cxx197
-rw-r--r--basic/source/runtime/iosys.cxx1048
-rw-r--r--basic/source/runtime/makefile.mk71
-rw-r--r--basic/source/runtime/methods.cxx4583
-rw-r--r--basic/source/runtime/methods1.cxx2621
-rw-r--r--basic/source/runtime/props.cxx776
-rw-r--r--basic/source/runtime/rtlproto.hxx349
-rwxr-xr-xbasic/source/runtime/runtime.cxx1268
-rw-r--r--basic/source/runtime/stdobj.cxx788
-rw-r--r--basic/source/runtime/stdobj1.cxx551
-rw-r--r--basic/source/runtime/step0.cxx1332
-rw-r--r--basic/source/runtime/step1.cxx574
-rwxr-xr-xbasic/source/runtime/step2.cxx1261
-rw-r--r--basic/source/runtime/wnt-mingw.s53
-rw-r--r--basic/source/runtime/wnt.asm56
20 files changed, 16686 insertions, 0 deletions
diff --git a/basic/source/runtime/basrdll.cxx b/basic/source/runtime/basrdll.cxx
new file mode 100644
index 000000000000..799caf0cd954
--- /dev/null
+++ b/basic/source/runtime/basrdll.cxx
@@ -0,0 +1,104 @@
+/*************************************************************************
+ *
+ * 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 <vcl/svapp.hxx>
+#include <svl/solar.hrc>
+#include <tools/debug.hxx>
+#include <vcl/msgbox.hxx>
+
+#include <basic/sbstar.hxx>
+#include <basic/basrdll.hxx>
+#include <basrid.hxx>
+#include <sb.hrc>
+
+SttResId::SttResId( sal_uInt32 nId ) :
+ ResId( nId, *((*(BasicDLL**)GetAppData(SHL_BASIC))->GetSttResMgr()) )
+{
+}
+
+BasResId::BasResId( sal_uInt32 nId ) :
+ ResId( nId, *((*(BasicDLL**)GetAppData(SHL_BASIC))->GetBasResMgr()) )
+{
+}
+
+BasicDLL::BasicDLL()
+{
+ *(BasicDLL**)GetAppData(SHL_BASIC) = this;
+ ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale();
+ pSttResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(stt), aLocale );
+ pBasResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(sb), aLocale );
+ bDebugMode = FALSE;
+ bBreakEnabled = TRUE;
+}
+
+BasicDLL::~BasicDLL()
+{
+ delete pSttResMgr;
+ delete pBasResMgr;
+}
+
+void BasicDLL::EnableBreak( BOOL bEnable )
+{
+ BasicDLL* pThis = *(BasicDLL**)GetAppData(SHL_BASIC);
+ DBG_ASSERT( pThis, "BasicDLL::EnableBreak: Noch keine Instanz!" );
+ if ( pThis )
+ pThis->bBreakEnabled = bEnable;
+}
+
+void BasicDLL::SetDebugMode( BOOL bDebugMode )
+{
+ BasicDLL* pThis = *(BasicDLL**)GetAppData(SHL_BASIC);
+ DBG_ASSERT( pThis, "BasicDLL::EnableBreak: Noch keine Instanz!" );
+ if ( pThis )
+ pThis->bDebugMode = bDebugMode;
+}
+
+
+void BasicDLL::BasicBreak()
+{
+ //bJustStopping: Wenn jemand wie wild x-mal STOP drueckt, aber das Basic
+ // nicht schnell genug anhaelt, kommt die Box ggf. oefters...
+ static BOOL bJustStopping = FALSE;
+
+ BasicDLL* pThis = *(BasicDLL**)GetAppData(SHL_BASIC);
+ DBG_ASSERT( pThis, "BasicDLL::EnableBreak: Noch keine Instanz!" );
+ if ( pThis )
+ {
+ if ( StarBASIC::IsRunning() && !bJustStopping && ( pThis->bBreakEnabled || pThis->bDebugMode ) )
+ {
+ bJustStopping = TRUE;
+ StarBASIC::Stop();
+ String aMessageStr( BasResId( IDS_SBERR_TERMINATED ) );
+ InfoBox( 0, aMessageStr ).Execute();
+ bJustStopping = FALSE;
+ }
+ }
+}
+
diff --git a/basic/source/runtime/ddectrl.cxx b/basic/source/runtime/ddectrl.cxx
new file mode 100644
index 000000000000..89d473099f0b
--- /dev/null
+++ b/basic/source/runtime/ddectrl.cxx
@@ -0,0 +1,192 @@
+/*************************************************************************
+ *
+ * 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/errcode.hxx>
+#include <svl/svdde.hxx>
+#include "ddectrl.hxx"
+#ifndef _SBERRORS_HXX
+#include <basic/sberrors.hxx>
+#endif
+
+#define DDE_FREECHANNEL ((DdeConnection*)0xffffffff)
+
+#define DDE_FIRSTERR 0x4000
+#define DDE_LASTERR 0x4011
+
+static const SbError nDdeErrMap[] =
+{
+ /* DMLERR_ADVACKTIMEOUT */ 0x4000, SbERR_DDE_TIMEOUT,
+ /* DMLERR_BUSY */ 0x4001, SbERR_DDE_BUSY,
+ /* DMLERR_DATAACKTIMEOUT */ 0x4002, SbERR_DDE_TIMEOUT,
+ /* DMLERR_DLL_NOT_INITIALIZED */ 0x4003, SbERR_DDE_ERROR,
+ /* DMLERR_DLL_USAGE */ 0x4004, SbERR_DDE_ERROR,
+ /* DMLERR_EXECACKTIMEOUT */ 0x4005, SbERR_DDE_TIMEOUT,
+ /* DMLERR_INVALIDPARAMETER */ 0x4006, SbERR_DDE_ERROR,
+ /* DMLERR_LOW_MEMORY */ 0x4007, SbERR_DDE_ERROR,
+ /* DMLERR_MEMORY_ERROR */ 0x4008, SbERR_DDE_ERROR,
+ /* DMLERR_NOTPROCESSED */ 0x4009, SbERR_DDE_NOTPROCESSED,
+ /* DMLERR_NO_CONV_ESTABLISHED */ 0x400a, SbERR_DDE_NO_CHANNEL,
+ /* DMLERR_POKEACKTIMEOUT */ 0x400b, SbERR_DDE_TIMEOUT,
+ /* DMLERR_POSTMSG_FAILED */ 0x400c, SbERR_DDE_QUEUE_OVERFLOW,
+ /* DMLERR_REENTRANCY */ 0x400d, SbERR_DDE_ERROR,
+ /* DMLERR_SERVER_DIED */ 0x400e, SbERR_DDE_PARTNER_QUIT,
+ /* DMLERR_SYS_ERROR */ 0x400f, SbERR_DDE_ERROR,
+ /* DMLERR_UNADVACKTIMEOUT */ 0x4010, SbERR_DDE_TIMEOUT,
+ /* DMLERR_UNFOUND_QUEUE_ID */ 0x4011, SbERR_DDE_NO_CHANNEL
+};
+
+SbError SbiDdeControl::GetLastErr( DdeConnection* pConv )
+{
+ if( !pConv )
+ return 0;
+ long nErr = pConv->GetError();
+ if( !nErr )
+ return 0;
+ if( nErr < DDE_FIRSTERR || nErr > DDE_LASTERR )
+ return SbERR_DDE_ERROR;
+ return nDdeErrMap[ 2*(nErr - DDE_FIRSTERR) + 1 ];
+}
+
+IMPL_LINK_INLINE( SbiDdeControl,Data , DdeData*, pData,
+{
+ aData = String::CreateFromAscii( (char*)(const void*)*pData );
+ return 1;
+}
+)
+
+SbiDdeControl::SbiDdeControl()
+{
+ pConvList = new DdeConnections;
+ DdeConnection* pPtr = DDE_FREECHANNEL;
+ pConvList->Insert( pPtr );
+}
+
+SbiDdeControl::~SbiDdeControl()
+{
+ TerminateAll();
+ delete pConvList;
+}
+
+INT16 SbiDdeControl::GetFreeChannel()
+{
+ INT16 nListSize = (INT16)pConvList->Count();
+ DdeConnection* pPtr = pConvList->First();
+ pPtr = pConvList->Next(); // nullten eintrag ueberspringen
+ INT16 nChannel;
+ for( nChannel = 1; nChannel < nListSize; nChannel++ )
+ {
+ if( pPtr == DDE_FREECHANNEL )
+ return nChannel;
+ pPtr = pConvList->Next();
+ }
+ pPtr = DDE_FREECHANNEL;
+ pConvList->Insert( pPtr, LIST_APPEND );
+ return nChannel;
+}
+
+SbError SbiDdeControl::Initiate( const String& rService, const String& rTopic,
+ INT16& rnHandle )
+{
+ SbError nErr;
+ DdeConnection* pConv = new DdeConnection( rService, rTopic );
+ nErr = GetLastErr( pConv );
+ if( nErr )
+ {
+ delete pConv;
+ rnHandle = 0;
+ }
+ else
+ {
+ INT16 nChannel = GetFreeChannel();
+ pConvList->Replace( pConv, (ULONG)nChannel );
+ rnHandle = nChannel;
+ }
+ return 0;
+}
+
+SbError SbiDdeControl::Terminate( INT16 nChannel )
+{
+ DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel );
+ if( !nChannel || !pConv || pConv == DDE_FREECHANNEL )
+ return SbERR_DDE_NO_CHANNEL;
+ pConvList->Replace( DDE_FREECHANNEL, (ULONG)nChannel );
+ delete pConv;
+ return 0L;
+}
+
+SbError SbiDdeControl::TerminateAll()
+{
+ INT16 nChannel = (INT16)pConvList->Count();
+ while( nChannel )
+ {
+ nChannel--;
+ Terminate( nChannel );
+ }
+
+ pConvList->Clear();
+ DdeConnection* pPtr = DDE_FREECHANNEL;
+ pConvList->Insert( pPtr );
+
+ return 0;
+}
+
+SbError SbiDdeControl::Request( INT16 nChannel, const String& rItem, String& rResult )
+{
+ DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel );
+ if( !nChannel || !pConv || pConv == DDE_FREECHANNEL )
+ return SbERR_DDE_NO_CHANNEL;
+
+ DdeRequest aRequest( *pConv, rItem, 30000 );
+ aRequest.SetDataHdl( LINK( this, SbiDdeControl, Data ) );
+ aRequest.Execute();
+ rResult = aData;
+ return GetLastErr( pConv );
+}
+
+SbError SbiDdeControl::Execute( INT16 nChannel, const String& rCommand )
+{
+ DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel );
+ if( !nChannel || !pConv || pConv == DDE_FREECHANNEL )
+ return SbERR_DDE_NO_CHANNEL;
+ DdeExecute aRequest( *pConv, rCommand, 30000 );
+ aRequest.Execute();
+ return GetLastErr( pConv );
+}
+
+SbError SbiDdeControl::Poke( INT16 nChannel, const String& rItem, const String& rData )
+{
+ DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel );
+ if( !nChannel || !pConv || pConv == DDE_FREECHANNEL )
+ return SbERR_DDE_NO_CHANNEL;
+ DdePoke aRequest( *pConv, rItem, DdeData(rData), 30000 );
+ aRequest.Execute();
+ return GetLastErr( pConv );
+}
+
+
diff --git a/basic/source/runtime/ddectrl.hxx b/basic/source/runtime/ddectrl.hxx
new file mode 100644
index 000000000000..c1e9da823a20
--- /dev/null
+++ b/basic/source/runtime/ddectrl.hxx
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _DDECTRL_HXX
+#define _DDECTRL_HXX
+
+#include <tools/link.hxx>
+#ifndef _SBERRORS_HXX
+#include <basic/sberrors.hxx>
+#endif
+#include <tools/string.hxx>
+
+class DdeConnection;
+class DdeConnections;
+class DdeData;
+
+class SbiDdeControl
+{
+private:
+ DECL_LINK( Data, DdeData* );
+ SbError GetLastErr( DdeConnection* );
+ INT16 GetFreeChannel();
+ DdeConnections* pConvList;
+ String aData;
+
+public:
+
+ SbiDdeControl();
+ ~SbiDdeControl();
+
+ SbError Initiate( const String& rService, const String& rTopic,
+ INT16& rnHandle );
+ SbError Terminate( INT16 nChannel );
+ SbError TerminateAll();
+ SbError Request( INT16 nChannel, const String& rItem, String& rResult );
+ SbError Execute( INT16 nChannel, const String& rCommand );
+ SbError Poke( INT16 nChannel, const String& rItem, const String& rData );
+};
+
+#endif
diff --git a/basic/source/runtime/dllmgr.cxx b/basic/source/runtime/dllmgr.cxx
new file mode 100644
index 000000000000..04f1ee0a8acc
--- /dev/null
+++ b/basic/source/runtime/dllmgr.cxx
@@ -0,0 +1,738 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "precompiled_basic.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "basic/sbx.hxx"
+#include "basic/sbxvar.hxx"
+#include "osl/thread.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "salhelper/simplereferenceobject.hxx"
+#include "tools/svwin.h"
+
+#undef max
+
+#include "dllmgr.hxx"
+
+/* Open issues:
+
+ Only 32-bit Windows for now.
+
+ Missing support for functions returning structs (see TODO in call()).
+
+ Missing support for additional data types (64 bit integers, Any, ...; would
+ trigger OSL_ASSERT(false) in various switches).
+
+ It is assumed that the variables passed into SbiDllMgr::Call to represent
+ the arguments and return value have types that exactly match the Declare
+ statement; it would be better if this code had access to the function
+ signature from the Declare statement, so that it could convert the passed
+ variables accordingly.
+*/
+
+#if defined WNT // only 32-bit Windows, actually
+
+extern "C" {
+
+int __stdcall DllMgr_call32(FARPROC, void const * stack, std::size_t size);
+double __stdcall DllMgr_callFp(FARPROC, void const * stack, std::size_t size);
+
+}
+
+namespace {
+
+char * address(std::vector< char > & blob) {
+ return blob.empty() ? 0 : &blob[0];
+}
+
+SbError convert(rtl::OUString const & source, rtl::OString * target) {
+ return
+ source.convertToString(
+ target, osl_getThreadTextEncoding(),
+ (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
+ ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
+ //TODO: more specific errcode?
+}
+
+SbError convert(char const * source, sal_Int32 length, rtl::OUString * target) {
+ return
+ rtl_convertStringToUString(
+ &target->pData, source, length, osl_getThreadTextEncoding(),
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))
+ ? ERRCODE_NONE : ERRCODE_BASIC_BAD_ARGUMENT;
+ //TODO: more specific errcode?
+}
+
+struct UnmarshalData {
+ UnmarshalData(SbxVariable * theVariable, void * theBuffer):
+ variable(theVariable), buffer(theBuffer) {}
+
+ SbxVariable * variable;
+ void * buffer;
+};
+
+struct StringData: public UnmarshalData {
+ StringData(SbxVariable * theVariable, void * theBuffer, bool theSpecial):
+ UnmarshalData(theVariable, theBuffer), special(theSpecial) {}
+
+ bool special;
+};
+
+class MarshalData: private boost::noncopyable {
+public:
+ std::vector< char > * newBlob() {
+ blobs_.push_front(std::vector< char >());
+ return &blobs_.front();
+ }
+
+ std::vector< UnmarshalData > unmarshal;
+
+ std::vector< StringData > unmarshalStrings;
+
+private:
+ std::list< std::vector< char > > blobs_;
+};
+
+std::size_t align(std::size_t address, std::size_t alignment) {
+ // alignment = 2^k for some k >= 0
+ return (address + (alignment - 1)) & ~(alignment - 1);
+}
+
+char * align(
+ std::vector< char > & blob, std::size_t alignment, std::size_t offset,
+ std::size_t add)
+{
+ std::vector< char >::size_type n = blob.size();
+ n = align(n - offset, alignment) + offset; //TODO: overflow in align()
+ blob.resize(n + add); //TODO: overflow
+ return address(blob) + n;
+}
+
+template< typename T > void add(
+ std::vector< char > & blob, T const & data, std::size_t alignment,
+ std::size_t offset)
+{
+ *reinterpret_cast< T * >(align(blob, alignment, offset, sizeof (T))) = data;
+}
+
+std::size_t alignment(SbxVariable * variable) {
+ OSL_ASSERT(variable != 0);
+ if ((variable->GetType() & SbxARRAY) == 0) {
+ switch (variable->GetType()) {
+ case SbxINTEGER:
+ return 2;
+ case SbxLONG:
+ case SbxSINGLE:
+ case SbxSTRING:
+ return 4;
+ case SbxDOUBLE:
+ return 8;
+ case SbxOBJECT:
+ {
+ std::size_t n = 1;
+ SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+ GetProperties();
+ for (USHORT i = 0; i < props->Count(); ++i) {
+ n = std::max(n, alignment(props->Get(i)));
+ }
+ return n;
+ }
+ case SbxBOOL:
+ case SbxBYTE:
+ return 1;
+ default:
+ OSL_ASSERT(false);
+ return 1;
+ }
+ } else {
+ SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+ int dims = arr->GetDims();
+ std::vector< INT32 > low(dims);
+ for (int i = 0; i < dims; ++i) {
+ INT32 up;
+ arr->GetDim32(i + 1, low[i], up);
+ }
+ return alignment(arr->Get32(&low[0]));
+ }
+}
+
+SbError marshal(
+ bool outer, SbxVariable * variable, bool special,
+ std::vector< char > & blob, std::size_t offset, MarshalData & data);
+
+SbError marshalString(
+ SbxVariable * variable, bool special, MarshalData & data, void ** buffer)
+{
+ OSL_ASSERT(variable != 0 && buffer != 0);
+ rtl::OString str;
+ SbError e = convert(variable->GetString(), &str);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ std::vector< char > * blob = data.newBlob();
+ blob->insert(blob->begin(), str.getStr(), str.getStr() + str.getLength());
+ *buffer = address(*blob);
+ data.unmarshalStrings.push_back(StringData(variable, *buffer, special));
+ return ERRCODE_NONE;
+}
+
+SbError marshalStruct(
+ SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
+ MarshalData & data)
+{
+ OSL_ASSERT(variable != 0);
+ SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+ GetProperties();
+ for (USHORT i = 0; i < props->Count(); ++i) {
+ SbError e = marshal(false, props->Get(i), false, blob, offset, data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ }
+ return ERRCODE_NONE;
+}
+
+SbError marshalArray(
+ SbxVariable * variable, std::vector< char > & blob, std::size_t offset,
+ MarshalData & data)
+{
+ OSL_ASSERT(variable != 0);
+ SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+ int dims = arr->GetDims();
+ std::vector< INT32 > low(dims);
+ std::vector< INT32 > up(dims);
+ for (int i = 0; i < dims; ++i) {
+ arr->GetDim32(i + 1, low[i], up[i]);
+ }
+ for (std::vector< INT32 > idx = low;;) {
+ SbError e = marshal(
+ false, arr->Get32(&idx[0]), false, blob, offset, data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ int i = dims - 1;
+ while (idx[i] == up[i]) {
+ idx[i] = low[i];
+ if (i == 0) {
+ return ERRCODE_NONE;
+ }
+ --i;
+ }
+ ++idx[i];
+ }
+}
+
+// 8-aligned structs are only 4-aligned on stack, so alignment of members in
+// such structs must take that into account via "offset"
+SbError marshal(
+ bool outer, SbxVariable * variable, bool special,
+ std::vector< char > & blob, std::size_t offset, MarshalData & data)
+{
+ OSL_ASSERT(variable != 0);
+ if ((variable->GetFlags() & SBX_REFERENCE) == 0) {
+ if ((variable->GetType() & SbxARRAY) == 0) {
+ switch (variable->GetType()) {
+ case SbxINTEGER:
+ add(blob, variable->GetInteger(), outer ? 4 : 2, offset);
+ break;
+ case SbxLONG:
+ add(blob, variable->GetLong(), 4, offset);
+ break;
+ case SbxSINGLE:
+ add(blob, variable->GetSingle(), 4, offset);
+ break;
+ case SbxDOUBLE:
+ add(blob, variable->GetDouble(), outer ? 4 : 8, offset);
+ break;
+ case SbxSTRING:
+ {
+ void * p;
+ SbError e = marshalString(variable, special, data, &p);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ add(blob, p, 4, offset);
+ break;
+ }
+ case SbxOBJECT:
+ {
+ align(blob, outer ? 4 : alignment(variable), offset, 0);
+ SbError e = marshalStruct(variable, blob, offset, data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ break;
+ }
+ case SbxBOOL:
+ add(blob, variable->GetBool(), outer ? 4 : 1, offset);
+ break;
+ case SbxBYTE:
+ add(blob, variable->GetByte(), outer ? 4 : 1, offset);
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ } else {
+ SbError e = marshalArray(variable, blob, offset, data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ }
+ } else {
+ if ((variable->GetType() & SbxARRAY) == 0) {
+ switch (variable->GetType()) {
+ case SbxINTEGER:
+ case SbxLONG:
+ case SbxSINGLE:
+ case SbxDOUBLE:
+ case SbxBOOL:
+ case SbxBYTE:
+ add(blob, variable->data(), 4, offset);
+ break;
+ case SbxSTRING:
+ {
+ std::vector< char > * blob2 = data.newBlob();
+ void * p;
+ SbError e = marshalString(variable, special, data, &p);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ add(*blob2, p, 4, 0);
+ add(blob, address(*blob2), 4, offset);
+ break;
+ }
+ case SbxOBJECT:
+ {
+ std::vector< char > * blob2 = data.newBlob();
+ SbError e = marshalStruct(variable, *blob2, 0, data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ void * p = address(*blob2);
+ if (outer) {
+ data.unmarshal.push_back(UnmarshalData(variable, p));
+ }
+ add(blob, p, 4, offset);
+ break;
+ }
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ } else {
+ std::vector< char > * blob2 = data.newBlob();
+ SbError e = marshalArray(variable, *blob2, 0, data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ void * p = address(*blob2);
+ if (outer) {
+ data.unmarshal.push_back(UnmarshalData(variable, p));
+ }
+ add(blob, p, 4, offset);
+ }
+ }
+ return ERRCODE_NONE;
+}
+
+template< typename T > T read(void const ** pointer) {
+ T const * p = static_cast< T const * >(*pointer);
+ *pointer = static_cast< void const * >(p + 1);
+ return *p;
+}
+
+void const * unmarshal(SbxVariable * variable, void const * data) {
+ OSL_ASSERT(variable != 0);
+ if ((variable->GetType() & SbxARRAY) == 0) {
+ switch (variable->GetType()) {
+ case SbxINTEGER:
+ variable->PutInteger(read< sal_Int16 >(&data));
+ break;
+ case SbxLONG:
+ variable->PutLong(read< sal_Int32 >(&data));
+ break;
+ case SbxSINGLE:
+ variable->PutSingle(read< float >(&data));
+ break;
+ case SbxDOUBLE:
+ variable->PutDouble(read< double >(&data));
+ break;
+ case SbxSTRING:
+ read< char * >(&data); // handled by unmarshalString
+ break;
+ case SbxOBJECT:
+ {
+ data = reinterpret_cast< void const * >(
+ align(
+ reinterpret_cast< sal_uIntPtr >(data),
+ alignment(variable)));
+ SbxArray * props = PTR_CAST(SbxObject, variable->GetObject())->
+ GetProperties();
+ for (USHORT i = 0; i < props->Count(); ++i) {
+ data = unmarshal(props->Get(i), data);
+ }
+ break;
+ }
+ case SbxBOOL:
+ variable->PutBool(read< sal_Bool >(&data));
+ break;
+ case SbxBYTE:
+ variable->PutByte(read< sal_uInt8 >(&data));
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ } else {
+ SbxDimArray * arr = PTR_CAST(SbxDimArray, variable->GetObject());
+ int dims = arr->GetDims();
+ std::vector< INT32 > low(dims);
+ std::vector< INT32 > up(dims);
+ for (int i = 0; i < dims; ++i) {
+ arr->GetDim32(i + 1, low[i], up[i]);
+ }
+ for (std::vector< INT32 > idx = low;;) {
+ data = unmarshal(arr->Get32(&idx[0]), data);
+ int i = dims - 1;
+ while (idx[i] == up[i]) {
+ idx[i] = low[i];
+ if (i == 0) {
+ goto done;
+ }
+ --i;
+ }
+ ++idx[i];
+ }
+ done:;
+ }
+ return data;
+}
+
+SbError unmarshalString(StringData const & data, SbxVariable & result) {
+ rtl::OUString str;
+ if (data.buffer != 0) {
+ char const * p = static_cast< char const * >(data.buffer);
+ sal_Int32 len;
+ if (data.special) {
+ len = static_cast< sal_Int32 >(result.GetULong());
+ if (len < 0) { // i.e., DWORD result >= 2^31
+ return ERRCODE_BASIC_BAD_ARGUMENT;
+ //TODO: more specific errcode?
+ }
+ } else {
+ len = rtl_str_getLength(p);
+ }
+ SbError e = convert(p, len, &str);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ }
+ data.variable->PutString(String(str));
+ return ERRCODE_NONE;
+}
+
+struct ProcData {
+ rtl::OString name;
+ FARPROC proc;
+};
+
+SbError call(
+ rtl::OUString const & dll, ProcData const & proc, SbxArray * arguments,
+ SbxVariable & result)
+{
+ std::vector< char > stack;
+ MarshalData data;
+ // For DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
+ // from kernel32, upon return, filled lpBuffer length is result DWORD, which
+ // requires special handling in unmarshalString; other functions might
+ // require similar treatment, too:
+ bool special =
+ dll.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("KERNEL32.DLL")) &&
+ (proc.name ==
+ rtl::OString(RTL_CONSTASCII_STRINGPARAM("GetLogicalDriveStringsA")));
+ for (USHORT i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
+ SbError e = marshal(
+ true, arguments->Get(i), special && i == 2, stack, stack.size(),
+ data);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ align(stack, 4, 0, 0);
+ }
+ switch (result.GetType()) {
+ case SbxEMPTY:
+ DllMgr_call32(proc.proc, address(stack), stack.size());
+ break;
+ case SbxINTEGER:
+ result.PutInteger(
+ static_cast< sal_Int16 >(
+ DllMgr_call32(proc.proc, address(stack), stack.size())));
+ break;
+ case SbxLONG:
+ result.PutLong(
+ static_cast< sal_Int32 >(
+ DllMgr_call32(proc.proc, address(stack), stack.size())));
+ break;
+ case SbxSINGLE:
+ result.PutSingle(
+ static_cast< float >(
+ DllMgr_callFp(proc.proc, address(stack), stack.size())));
+ break;
+ case SbxDOUBLE:
+ result.PutDouble(
+ DllMgr_callFp(proc.proc, address(stack), stack.size()));
+ break;
+ case SbxSTRING:
+ {
+ char const * s1 = reinterpret_cast< char const * >(
+ DllMgr_call32(proc.proc, address(stack), stack.size()));
+ rtl::OUString s2;
+ SbError e = convert(s1, rtl_str_getLength(s1), &s2);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ result.PutString(String(s2));
+ break;
+ }
+ case SbxOBJECT:
+ //TODO
+ DllMgr_call32(proc.proc, address(stack), stack.size());
+ break;
+ case SbxBOOL:
+ result.PutBool(
+ static_cast< sal_Bool >(
+ DllMgr_call32(proc.proc, address(stack), stack.size())));
+ break;
+ case SbxBYTE:
+ result.PutByte(
+ static_cast< sal_uInt8 >(
+ DllMgr_call32(proc.proc, address(stack), stack.size())));
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ for (USHORT i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i) {
+ arguments->Get(i)->ResetFlag(SBX_REFERENCE);
+ //TODO: skipped for errors?!?
+ }
+ for (std::vector< UnmarshalData >::iterator i(data.unmarshal.begin());
+ i != data.unmarshal.end(); ++i)
+ {
+ unmarshal(i->variable, i->buffer);
+ }
+ for (std::vector< StringData >::iterator i(data.unmarshalStrings.begin());
+ i != data.unmarshalStrings.end(); ++i)
+ {
+ SbError e = unmarshalString(*i, result);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ }
+ return ERRCODE_NONE;
+}
+
+SbError getProcData(HMODULE handle, rtl::OUString const & name, ProcData * proc)
+{
+ OSL_ASSERT(proc != 0);
+ if (name.getLength() != 0 && name[0] == '@') { //TODO: "@" vs. "#"???
+ sal_Int32 n = name.copy(1).toInt32(); //TODO: handle bad input
+ if (n <= 0 || n > 0xFFFF) {
+ return ERRCODE_BASIC_BAD_ARGUMENT; //TODO: more specific errcode?
+ }
+ FARPROC p = GetProcAddress(handle, reinterpret_cast< LPCSTR >(n));
+ if (p != 0) {
+ proc->name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("#")) +
+ rtl::OString::valueOf(n);
+ proc->proc = p;
+ return ERRCODE_NONE;
+ }
+ } else {
+ rtl::OString name8;
+ SbError e = convert(name, &name8);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ FARPROC p = GetProcAddress(handle, name8.getStr());
+ if (p != 0) {
+ proc->name = name8;
+ proc->proc = p;
+ return ERRCODE_NONE;
+ }
+ sal_Int32 i = name8.indexOf('#');
+ if (i != -1) {
+ name8 = name8.copy(0, i);
+ p = GetProcAddress(handle, name8.getStr());
+ if (p != 0) {
+ proc->name = name8;
+ proc->proc = p;
+ return ERRCODE_NONE;
+ }
+ }
+ rtl::OString real(
+ rtl::OString(RTL_CONSTASCII_STRINGPARAM("_")) + name8);
+ p = GetProcAddress(handle, real.getStr());
+ if (p != 0) {
+ proc->name = real;
+ proc->proc = p;
+ return ERRCODE_NONE;
+ }
+ real = name8 + rtl::OString(RTL_CONSTASCII_STRINGPARAM("A"));
+ p = GetProcAddress(handle, real.getStr());
+ if (p != 0) {
+ proc->name = real;
+ proc->proc = p;
+ return ERRCODE_NONE;
+ }
+ }
+ return ERRCODE_BASIC_PROC_UNDEFINED;
+}
+
+struct Dll: public salhelper::SimpleReferenceObject {
+private:
+ typedef std::map< rtl::OUString, ProcData > Procs;
+
+ virtual ~Dll();
+
+public:
+ Dll(): handle(0) {}
+
+ SbError getProc(rtl::OUString const & name, ProcData * proc);
+
+ HMODULE handle;
+ Procs procs;
+};
+
+Dll::~Dll() {
+ if (handle != 0 && !FreeLibrary(handle)) {
+ OSL_TRACE("FreeLibrary(%p) failed with %u", handle, GetLastError());
+ }
+}
+
+SbError Dll::getProc(rtl::OUString const & name, ProcData * proc) {
+ Procs::iterator i(procs.find(name));
+ if (i != procs.end()) {
+ *proc = i->second;
+ return ERRCODE_NONE;
+ }
+ SbError e = getProcData(handle, name, proc);
+ if (e == ERRCODE_NONE) {
+ procs.insert(Procs::value_type(name, *proc));
+ }
+ return e;
+}
+
+rtl::OUString fullDllName(rtl::OUString const & name) {
+ rtl::OUString full(name);
+ if (full.indexOf('.') == -1) {
+ full += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".DLL"));
+ }
+ return full;
+}
+
+}
+
+struct SbiDllMgr::Impl: private boost::noncopyable {
+private:
+ typedef std::map< rtl::OUString, rtl::Reference< Dll > > Dlls;
+
+public:
+ Dll * getDll(rtl::OUString const & name);
+
+ Dlls dlls;
+};
+
+Dll * SbiDllMgr::Impl::getDll(rtl::OUString const & name) {
+ Dlls::iterator i(dlls.find(name));
+ if (i == dlls.end()) {
+ i = dlls.insert(Dlls::value_type(name, new Dll)).first;
+ HMODULE h = LoadLibraryW(reinterpret_cast<LPCWSTR>(name.getStr()));
+ if (h == 0) {
+ dlls.erase(i);
+ return 0;
+ }
+ i->second->handle = h;
+ }
+ return i->second.get();
+}
+
+SbError SbiDllMgr::Call(
+ rtl::OUString const & function, rtl::OUString const & library,
+ SbxArray * arguments, SbxVariable & result, bool cdeclConvention)
+{
+ if (cdeclConvention) {
+ return ERRCODE_BASIC_NOT_IMPLEMENTED;
+ }
+ rtl::OUString dllName(fullDllName(library));
+ Dll * dll = impl_->getDll(dllName);
+ if (dll == 0) {
+ return ERRCODE_BASIC_BAD_DLL_LOAD;
+ }
+ ProcData proc;
+ SbError e = dll->getProc(function, &proc);
+ if (e != ERRCODE_NONE) {
+ return e;
+ }
+ return call(dllName, proc, arguments, result);
+}
+
+void SbiDllMgr::FreeDll(rtl::OUString const & library) {
+ impl_->dlls.erase(library);
+}
+
+#else
+
+struct SbiDllMgr::Impl {};
+
+SbError SbiDllMgr::Call(
+ rtl::OUString const &, rtl::OUString const &, SbxArray *, SbxVariable &,
+ bool)
+{
+ return ERRCODE_BASIC_NOT_IMPLEMENTED;
+}
+
+void SbiDllMgr::FreeDll(rtl::OUString const &) {}
+
+#endif
+
+SbiDllMgr::SbiDllMgr(): impl_(new Impl) {}
+
+SbiDllMgr::~SbiDllMgr() {}
diff --git a/basic/source/runtime/dllmgr.hxx b/basic/source/runtime/dllmgr.hxx
new file mode 100644
index 000000000000..fdff8c2849be
--- /dev/null
+++ b/basic/source/runtime/dllmgr.hxx
@@ -0,0 +1,60 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_BASIC_SOURCE_RUNTIME_DLLMGR_HXX
+#define INCLUDED_BASIC_SOURCE_RUNTIME_DLLMGR_HXX
+
+#include "sal/config.h"
+
+#include <memory>
+
+#include "basic/sberrors.hxx"
+#include "boost/noncopyable.hpp"
+
+namespace rtl { class OUString; }
+class SbxArray;
+class SbxVariable;
+
+class SbiDllMgr: private boost::noncopyable {
+public:
+ SbiDllMgr();
+
+ ~SbiDllMgr();
+
+ SbError Call(
+ rtl::OUString const & function, rtl::OUString const & library,
+ SbxArray * arguments, SbxVariable & result, bool cdeclConvention);
+
+ void FreeDll(rtl::OUString const & library);
+
+private:
+ struct Impl;
+
+ std::auto_ptr< Impl > impl_;
+};
+
+#endif
diff --git a/basic/source/runtime/inputbox.cxx b/basic/source/runtime/inputbox.cxx
new file mode 100644
index 000000000000..17b98ad7addd
--- /dev/null
+++ b/basic/source/runtime/inputbox.cxx
@@ -0,0 +1,197 @@
+/*************************************************************************
+ *
+ * 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"
+
+#ifndef _SV_BUTTON_HXX //autogen
+#include <vcl/button.hxx>
+#endif
+#include <vcl/fixed.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/svapp.hxx>
+#include "runtime.hxx"
+#include "stdobj.hxx"
+#include "rtlproto.hxx"
+
+class SvRTLInputBox : public ModalDialog
+{
+ Edit aEdit;
+ OKButton aOk;
+ CancelButton aCancel;
+ FixedText aPromptText;
+ String aText;
+
+ void PositionDialog( long nXTwips, long nYTwips, const Size& rDlgSize );
+ void InitButtons( const Size& rDlgSize );
+ void PositionEdit( const Size& rDlgSize );
+ void PositionPrompt( const String& rPrompt, const Size& rDlgSize );
+ DECL_LINK( OkHdl, Button * );
+ DECL_LINK( CancelHdl, Button * );
+
+public:
+ SvRTLInputBox( Window* pParent, const String& rPrompt, const String& rTitle,
+ const String& rDefault, long nXTwips = -1, long nYTwips = -1 );
+ String GetText() const { return aText; }
+};
+
+SvRTLInputBox::SvRTLInputBox( Window* pParent, const String& rPrompt,
+ const String& rTitle, const String& rDefault,
+ long nXTwips, long nYTwips ) :
+ ModalDialog( pParent,WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ),
+ aEdit( this, WB_LEFT | WB_BORDER ),
+ aOk( this ), aCancel( this ), aPromptText( this, WB_WORDBREAK )
+{
+ SetMapMode( MapMode( MAP_APPFONT ) );
+ Size aDlgSizeApp( 280, 80 );
+ PositionDialog( nXTwips, nYTwips, aDlgSizeApp );
+ InitButtons( aDlgSizeApp );
+ PositionEdit( aDlgSizeApp );
+ PositionPrompt( rPrompt, aDlgSizeApp );
+ aOk.Show();
+ aCancel.Show();
+ aEdit.Show();
+ aPromptText.Show();
+ SetText( rTitle );
+ Font aFont( GetFont());
+ Color aColor( GetBackground().GetColor() );
+ aFont.SetFillColor( aColor );
+ aEdit.SetFont( aFont );
+ aEdit.SetText( rDefault );
+ aEdit.SetSelection( Selection( SELECTION_MIN, SELECTION_MAX ) );
+}
+
+void SvRTLInputBox::InitButtons( const Size& rDlgSize )
+{
+ aOk.SetSizePixel( LogicToPixel( Size( 45, 15) ));
+ aCancel.SetSizePixel( LogicToPixel( Size( 45, 15) ));
+ Point aPos( rDlgSize.Width()-45-10, 5 );
+ aOk.SetPosPixel( LogicToPixel( Point(aPos) ));
+ aPos.Y() += 16;
+ aCancel.SetPosPixel( LogicToPixel( Point(aPos) ));
+ aOk.SetClickHdl(LINK(this,SvRTLInputBox, OkHdl));
+ aCancel.SetClickHdl(LINK(this,SvRTLInputBox,CancelHdl));
+}
+
+void SvRTLInputBox::PositionDialog(long nXTwips, long nYTwips, const Size& rDlgSize)
+{
+ SetSizePixel( LogicToPixel(rDlgSize) );
+ if( nXTwips != -1 && nYTwips != -1 )
+ {
+ Point aDlgPosApp( nXTwips, nYTwips );
+ SetPosPixel( LogicToPixel( aDlgPosApp, MAP_TWIP ) );
+ }
+}
+
+void SvRTLInputBox::PositionEdit( const Size& rDlgSize )
+{
+ aEdit.SetPosPixel( LogicToPixel( Point( 5,rDlgSize.Height()-35)));
+ aEdit.SetSizePixel( LogicToPixel( Size(rDlgSize.Width()-15,12)));
+}
+
+
+void SvRTLInputBox::PositionPrompt(const String& rPrompt,const Size& rDlgSize)
+{
+ if ( rPrompt.Len() == 0 )
+ return;
+ String aText_( rPrompt );
+ aText_.ConvertLineEnd( LINEEND_CR );
+ aPromptText.SetPosPixel( LogicToPixel(Point(5,5)));
+ aPromptText.SetText( aText_ );
+ Size aSize( rDlgSize );
+ aSize.Width() -= 70;
+ aSize.Height() -= 50;
+ aPromptText.SetSizePixel( LogicToPixel(aSize));
+}
+
+
+IMPL_LINK_INLINE_START( SvRTLInputBox, OkHdl, Button *, pButton )
+{
+ (void)pButton;
+
+ aText = aEdit.GetText();
+ EndDialog( 1 );
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvRTLInputBox, OkHdl, Button *, pButton )
+
+IMPL_LINK_INLINE_START( SvRTLInputBox, CancelHdl, Button *, pButton )
+{
+ (void)pButton;
+
+ aText.Erase();
+ EndDialog( 0 );
+ return 0;
+}
+IMPL_LINK_INLINE_END( SvRTLInputBox, CancelHdl, Button *, pButton )
+
+
+// *********************************************************************
+// *********************************************************************
+// *********************************************************************
+
+// Syntax: String InputBox( Prompt, [Title], [Default] [, nXpos, nYpos ] )
+
+RTLFUNC(InputBox)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ ULONG nArgCount = rPar.Count();
+ if ( nArgCount < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aTitle;
+ String aDefault;
+ INT32 nX = -1, nY = -1; // zentrieren
+ const String& rPrompt = rPar.Get(1)->GetString();
+ if ( nArgCount > 2 && !rPar.Get(2)->IsErr() )
+ aTitle = rPar.Get(2)->GetString();
+ if ( nArgCount > 3 && !rPar.Get(3)->IsErr() )
+ aDefault = rPar.Get(3)->GetString();
+ if ( nArgCount > 4 )
+ {
+ if ( nArgCount != 6 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ nX = rPar.Get(4)->GetLong();
+ nY = rPar.Get(5)->GetLong();
+ }
+ SvRTLInputBox *pDlg=new SvRTLInputBox(GetpApp()->GetDefDialogParent(),
+ rPrompt,aTitle,aDefault,nX,nY);
+ pDlg->Execute();
+ rPar.Get(0)->PutString( pDlg->GetText() );
+ delete pDlg;
+ }
+}
+
+
+
diff --git a/basic/source/runtime/iosys.cxx b/basic/source/runtime/iosys.cxx
new file mode 100644
index 000000000000..9940890286b4
--- /dev/null
+++ b/basic/source/runtime/iosys.cxx
@@ -0,0 +1,1048 @@
+/*************************************************************************
+ *
+ * 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 <vcl/dialog.hxx>
+#include <vcl/edit.hxx>
+#ifndef _SV_BUTTON_HXX //autogen
+#include <vcl/button.hxx>
+#endif
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/security.h>
+#include <osl/file.hxx>
+#include <tools/urlobj.hxx>
+#include <vos/mutex.hxx>
+
+#include "runtime.hxx"
+
+#ifdef _USE_UNO
+
+// <-- encoding
+#include <sal/alloca.h>
+
+#include <ctype.h>
+#include <rtl/byteseq.hxx>
+#include <rtl/textenc.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/textenc.h>
+#include <rtl/ustrbuf.hxx>
+// encoding -->
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
+#include <com/sun/star/ucb/XContentProvider.hpp>
+#include <com/sun/star/ucb/XContentProviderManager.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/bridge/XBridge.hpp>
+#include <com/sun/star/bridge/XBridgeFactory.hpp>
+
+using namespace comphelper;
+using namespace osl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::io;
+using namespace com::sun::star::bridge;
+
+#endif /* _USE_UNO */
+
+#include "iosys.hxx"
+#include "sbintern.hxx"
+
+// Der Input-Dialog:
+
+class SbiInputDialog : public ModalDialog {
+ Edit aInput;
+ OKButton aOk;
+ CancelButton aCancel;
+ String aText;
+ DECL_LINK( Ok, Window * );
+ DECL_LINK( Cancel, Window * );
+public:
+ SbiInputDialog( Window*, const String& );
+ const String& GetInput() { return aText; }
+};
+
+SbiInputDialog::SbiInputDialog( Window* pParent, const String& rPrompt )
+ :ModalDialog( pParent, WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ),
+ aInput( this, WB_3DLOOK | WB_LEFT | WB_BORDER ),
+ aOk( this ), aCancel( this )
+{
+ SetText( rPrompt );
+ aOk.SetClickHdl( LINK( this, SbiInputDialog, Ok ) );
+ aCancel.SetClickHdl( LINK( this, SbiInputDialog, Cancel ) );
+ SetMapMode( MapMode( MAP_APPFONT ) );
+
+ Point aPt = LogicToPixel( Point( 50, 50 ) );
+ Size aSz = LogicToPixel( Size( 145, 65 ) );
+ SetPosSizePixel( aPt, aSz );
+ aPt = LogicToPixel( Point( 10, 10 ) );
+ aSz = LogicToPixel( Size( 120, 12 ) );
+ aInput.SetPosSizePixel( aPt, aSz );
+ aPt = LogicToPixel( Point( 15, 30 ) );
+ aSz = LogicToPixel( Size( 45, 15) );
+ aOk.SetPosSizePixel( aPt, aSz );
+ aPt = LogicToPixel( Point( 80, 30 ) );
+ aSz = LogicToPixel( Size( 45, 15) );
+ aCancel.SetPosSizePixel( aPt, aSz );
+
+ aInput.Show();
+ aOk.Show();
+ aCancel.Show();
+}
+
+IMPL_LINK_INLINE_START( SbiInputDialog, Ok, Window *, pWindow )
+{
+ (void)pWindow;
+
+ aText = aInput.GetText();
+ EndDialog( 1 );
+ return 0;
+}
+IMPL_LINK_INLINE_END( SbiInputDialog, Ok, Window *, pWindow )
+
+IMPL_LINK_INLINE_START( SbiInputDialog, Cancel, Window *, pWindow )
+{
+ (void)pWindow;
+
+ EndDialog( 0 );
+ return 0;
+}
+IMPL_LINK_INLINE_END( SbiInputDialog, Cancel, Window *, pWindow )
+
+//////////////////////////////////////////////////////////////////////////
+
+SbiStream::SbiStream()
+ : pStrm( 0 )
+{
+}
+
+SbiStream::~SbiStream()
+{
+ delete pStrm;
+}
+
+// Ummappen eines SvStream-Fehlers auf einen StarBASIC-Code
+
+void SbiStream::MapError()
+{
+ if( pStrm )
+ switch( pStrm->GetError() )
+ {
+ case SVSTREAM_OK:
+ nError = 0; break;
+ case SVSTREAM_FILE_NOT_FOUND:
+ nError = SbERR_FILE_NOT_FOUND; break;
+ case SVSTREAM_PATH_NOT_FOUND:
+ nError = SbERR_PATH_NOT_FOUND; break;
+ case SVSTREAM_TOO_MANY_OPEN_FILES:
+ nError = SbERR_TOO_MANY_FILES; break;
+ case SVSTREAM_ACCESS_DENIED:
+ nError = SbERR_ACCESS_DENIED; break;
+ case SVSTREAM_INVALID_PARAMETER:
+ nError = SbERR_BAD_ARGUMENT; break;
+ case SVSTREAM_OUTOFMEMORY:
+ nError = SbERR_NO_MEMORY; break;
+ default:
+ nError = SbERR_IO_ERROR; break;
+ }
+}
+
+#ifdef _USE_UNO
+
+// TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx
+
+::rtl::OUString findUserInDescription( const ::rtl::OUString& aDescription )
+{
+ ::rtl::OUString user;
+
+ sal_Int32 index;
+ sal_Int32 lastIndex = 0;
+
+ do
+ {
+ index = aDescription.indexOf((sal_Unicode) ',', lastIndex);
+ ::rtl::OUString token = (index == -1) ? aDescription.copy(lastIndex) : aDescription.copy(lastIndex, index - lastIndex);
+
+ lastIndex = index + 1;
+
+ sal_Int32 eindex = token.indexOf((sal_Unicode)'=');
+ ::rtl::OUString left = token.copy(0, eindex).toAsciiLowerCase().trim();
+ ::rtl::OUString right = INetURLObject::decode( token.copy(eindex + 1).trim(), '%',
+ INetURLObject::DECODE_WITH_CHARSET );
+
+ if(left.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user"))))
+ {
+ user = right;
+ break;
+ }
+ }
+ while(index != -1);
+
+ return user;
+}
+
+#endif
+
+
+// Hack for #83750
+BOOL runsInSetup( void );
+
+BOOL needSecurityRestrictions( void )
+{
+#ifdef _USE_UNO
+ static BOOL bNeedInit = TRUE;
+ static BOOL bRetVal = TRUE;
+
+ if( bNeedInit )
+ {
+ // Hack for #83750, use internal flag until
+ // setup provides own service manager
+ if( runsInSetup() )
+ {
+ // Setup is not critical
+ bRetVal = FALSE;
+ return bRetVal;
+ }
+
+ bNeedInit = FALSE;
+
+ // Get system user to compare to portal user
+ oslSecurity aSecurity = osl_getCurrentSecurity();
+ ::rtl::OUString aSystemUser;
+ sal_Bool bRet = osl_getUserName( aSecurity, &aSystemUser.pData );
+ if( !bRet )
+ {
+ // No valid security! -> Secure mode!
+ return TRUE;
+ }
+
+ Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ if( !xSMgr.is() )
+ return TRUE;
+ Reference< XBridgeFactory > xBridgeFac( xSMgr->createInstance
+ ( ::rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" ) ), UNO_QUERY );
+
+ Sequence< Reference< XBridge > > aBridgeSeq;
+ sal_Int32 nBridgeCount = 0;
+ if( xBridgeFac.is() )
+ {
+ aBridgeSeq = xBridgeFac->getExistingBridges();
+ nBridgeCount = aBridgeSeq.getLength();
+ }
+
+ if( nBridgeCount == 0 )
+ {
+ // No bridges -> local
+ bRetVal = FALSE;
+ return bRetVal;
+ }
+
+ // Iterate through all bridges to find (portal) user property
+ const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray();
+ bRetVal = FALSE; // Now only TRUE if user different from portal user is found
+ sal_Int32 i;
+ for( i = 0 ; i < nBridgeCount ; i++ )
+ {
+ const Reference< XBridge >& rxBridge = pBridges[ i ];
+ ::rtl::OUString aDescription = rxBridge->getDescription();
+ ::rtl::OUString aPortalUser = findUserInDescription( aDescription );
+ if( aPortalUser.getLength() > 0 )
+ {
+ // User Found, compare to system user
+ if( aPortalUser == aSystemUser )
+ {
+ // Same user -> system security is ok, bRetVal stays FALSE
+ break;
+ }
+ else
+ {
+ // Different user -> Secure mode!
+ bRetVal = TRUE;
+ break;
+ }
+ }
+ }
+ // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
+ }
+
+ return bRetVal;
+#else
+ return FALSE;
+#endif
+}
+
+// Returns TRUE if UNO is available, otherwise the old file
+// system implementation has to be used
+// #89378 New semantic: Don't just ask for UNO but for UCB
+BOOL hasUno( void )
+{
+#ifdef _USE_UNO
+ static BOOL bNeedInit = TRUE;
+ static BOOL bRetVal = TRUE;
+
+ if( bNeedInit )
+ {
+ bNeedInit = FALSE;
+ Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ if( !xSMgr.is() )
+ {
+ // No service manager at all
+ bRetVal = FALSE;
+ }
+ else
+ {
+ Reference< XContentProviderManager > xManager( xSMgr->createInstance( ::rtl::OUString::createFromAscii
+ ( "com.sun.star.ucb.UniversalContentBroker" ) ), UNO_QUERY );
+
+ if ( !( xManager.is() && xManager->queryContentProvider( ::rtl::OUString::createFromAscii( "file:///" ) ).is() ) )
+ {
+ // No UCB
+ bRetVal = FALSE;
+ }
+ }
+ }
+ return bRetVal;
+#else
+ return FALSE;
+#endif
+}
+
+
+
+#ifndef _OLD_FILE_IMPL
+
+class OslStream : public SvStream
+{
+ File maFile;
+ short mnStrmMode;
+
+public:
+ OslStream( const String& rName, short nStrmMode );
+ ~OslStream();
+ virtual ULONG GetData( void* pData, ULONG nSize );
+ virtual ULONG PutData( const void* pData, ULONG nSize );
+ virtual ULONG SeekPos( ULONG nPos );
+ virtual void FlushData();
+ virtual void SetSize( ULONG nSize );
+};
+
+OslStream::OslStream( const String& rName, short nStrmMode )
+ : maFile( rName )
+ , mnStrmMode( nStrmMode )
+{
+ sal_uInt32 nFlags;
+
+ if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
+ {
+ nFlags = OpenFlag_Read | OpenFlag_Write;
+ }
+ else if( nStrmMode & STREAM_WRITE )
+ {
+ nFlags = OpenFlag_Write;
+ }
+ else //if( nStrmMode & STREAM_READ )
+ {
+ nFlags = OpenFlag_Read;
+ }
+
+ FileBase::RC nRet = maFile.open( nFlags );
+ if( nRet == FileBase::E_NOENT && nFlags != OpenFlag_Read )
+ {
+ nFlags |= OpenFlag_Create;
+ nRet = maFile.open( nFlags );
+ }
+
+ if( nRet != FileBase::E_None )
+ {
+ SetError( ERRCODE_IO_GENERAL );
+ }
+}
+
+
+OslStream::~OslStream()
+{
+ maFile.close();
+}
+
+ULONG OslStream::GetData( void* pData, ULONG nSize )
+{
+ sal_uInt64 nBytesRead = nSize;
+ FileBase::RC nRet = FileBase::E_None;
+ nRet = maFile.read( pData, nBytesRead, nBytesRead );
+ return (ULONG)nBytesRead;
+}
+
+ULONG OslStream::PutData( const void* pData, ULONG nSize )
+{
+ sal_uInt64 nBytesWritten;
+ FileBase::RC nRet = FileBase::E_None;
+ nRet = maFile.write( pData, (sal_uInt64)nSize, nBytesWritten );
+ return (ULONG)nBytesWritten;
+}
+
+ULONG OslStream::SeekPos( ULONG nPos )
+{
+ FileBase::RC nRet;
+ if( nPos == STREAM_SEEK_TO_END )
+ {
+ nRet = maFile.setPos( Pos_End, 0 );
+ }
+ else
+ {
+ nRet = maFile.setPos( Pos_Absolut, (sal_uInt64)nPos );
+ }
+ sal_uInt64 nRealPos;
+ nRet = maFile.getPos( nRealPos );
+ return sal::static_int_cast<ULONG>(nRealPos);
+}
+
+void OslStream::FlushData()
+{
+}
+
+void OslStream::SetSize( ULONG nSize )
+{
+ FileBase::RC nRet = FileBase::E_None;
+ nRet = maFile.setSize( (sal_uInt64)nSize );
+}
+
+#endif
+
+
+#ifdef _USE_UNO
+
+class UCBStream : public SvStream
+{
+ Reference< XInputStream > xIS;
+ Reference< XOutputStream > xOS;
+ Reference< XStream > xS;
+ Reference< XSeekable > xSeek;
+public:
+ UCBStream( Reference< XInputStream > & xIS );
+ UCBStream( Reference< XOutputStream > & xOS );
+ UCBStream( Reference< XStream > & xS );
+ ~UCBStream();
+ virtual ULONG GetData( void* pData, ULONG nSize );
+ virtual ULONG PutData( const void* pData, ULONG nSize );
+ virtual ULONG SeekPos( ULONG nPos );
+ virtual void FlushData();
+ virtual void SetSize( ULONG nSize );
+};
+
+/*
+ULONG UCBErrorToSvStramError( ucb::IOErrorCode nError )
+{
+ ULONG eReturn = ERRCODE_IO_GENERAL;
+ switch( nError )
+ {
+ case ucb::IOErrorCode_ABORT: eReturn = SVSTREAM_GENERALERROR; break;
+ case ucb::IOErrorCode_NOT_EXISTING: eReturn = SVSTREAM_FILE_NOT_FOUND; break;
+ case ucb::IOErrorCode_NOT_EXISTING_PATH: eReturn = SVSTREAM_PATH_NOT_FOUND; break;
+ case ucb::IOErrorCode_OUT_OF_FILE_HANDLES: eReturn = SVSTREAM_TOO_MANY_OPEN_FILES; break;
+ case ucb::IOErrorCode_ACCESS_DENIED: eReturn = SVSTREAM_ACCESS_DENIED; break;
+ case ucb::IOErrorCode_LOCKING_VIOLATION: eReturn = SVSTREAM_SHARING_VIOLATION; break;
+
+ case ucb::IOErrorCode_INVALID_ACCESS: eReturn = SVSTREAM_INVALID_ACCESS; break;
+ case ucb::IOErrorCode_CANT_CREATE: eReturn = SVSTREAM_CANNOT_MAKE; break;
+ case ucb::IOErrorCode_INVALID_PARAMETER: eReturn = SVSTREAM_INVALID_PARAMETER; break;
+
+ case ucb::IOErrorCode_CANT_READ: eReturn = SVSTREAM_READ_ERROR; break;
+ case ucb::IOErrorCode_CANT_WRITE: eReturn = SVSTREAM_WRITE_ERROR; break;
+ case ucb::IOErrorCode_CANT_SEEK: eReturn = SVSTREAM_SEEK_ERROR; break;
+ case ucb::IOErrorCode_CANT_TELL: eReturn = SVSTREAM_TELL_ERROR; break;
+
+ case ucb::IOErrorCode_OUT_OF_MEMORY: eReturn = SVSTREAM_OUTOFMEMORY; break;
+
+ case SVSTREAM_FILEFORMAT_ERROR: eReturn = SVSTREAM_FILEFORMAT_ERROR; break;
+ case ucb::IOErrorCode_WRONG_VERSION: eReturn = SVSTREAM_WRONGVERSION;
+ case ucb::IOErrorCode_OUT_OF_DISK_SPACE: eReturn = SVSTREAM_DISK_FULL; break;
+
+ case ucb::IOErrorCode_BAD_CRC: eReturn = ERRCODE_IO_BADCRC; break;
+ }
+ return eReturn;
+}
+*/
+
+UCBStream::UCBStream( Reference< XInputStream > & rStm )
+ : xIS( rStm )
+ , xSeek( rStm, UNO_QUERY )
+{
+}
+
+UCBStream::UCBStream( Reference< XOutputStream > & rStm )
+ : xOS( rStm )
+ , xSeek( rStm, UNO_QUERY )
+{
+}
+
+UCBStream::UCBStream( Reference< XStream > & rStm )
+ : xS( rStm )
+ , xSeek( rStm, UNO_QUERY )
+{
+}
+
+
+UCBStream::~UCBStream()
+{
+ try
+ {
+ if( xIS.is() )
+ xIS->closeInput();
+ else if( xOS.is() )
+ xOS->closeOutput();
+ else if( xS.is() )
+ {
+ Reference< XInputStream > xIS_ = xS->getInputStream();
+ if( xIS_.is() )
+ xIS_->closeInput();
+ }
+ }
+ catch( Exception & )
+ {
+ SetError( ERRCODE_IO_GENERAL );
+ }
+}
+
+ULONG UCBStream::GetData( void* pData, ULONG nSize )
+{
+ try
+ {
+ Reference< XInputStream > xISFromS;
+ if( xIS.is() )
+ {
+ Sequence<sal_Int8> aData;
+ nSize = xIS->readBytes( aData, nSize );
+ rtl_copyMemory( pData, aData.getConstArray(), nSize );
+ return nSize;
+ }
+ else if( xS.is() && (xISFromS = xS->getInputStream()).is() )
+ {
+ Sequence<sal_Int8> aData;
+ nSize = xISFromS->readBytes( aData, nSize );
+ rtl_copyMemory( pData, aData.getConstArray(), nSize );
+ return nSize;
+ }
+ else
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ catch( Exception & )
+ {
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ return 0;
+}
+
+ULONG UCBStream::PutData( const void* pData, ULONG nSize )
+{
+ try
+ {
+ Reference< XOutputStream > xOSFromS;
+ if( xOS.is() )
+ {
+ Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
+ xOS->writeBytes( aData );
+ return nSize;
+ }
+ else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
+ {
+ Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
+ xOSFromS->writeBytes( aData );
+ return nSize;
+ }
+ else
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ catch( Exception & )
+ {
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ return 0;
+}
+
+ULONG UCBStream::SeekPos( ULONG nPos )
+{
+ try
+ {
+ if( xSeek.is() )
+ {
+ ULONG nLen = sal::static_int_cast<ULONG>( xSeek->getLength() );
+ if( nPos > nLen )
+ nPos = nLen;
+ xSeek->seek( nPos );
+ return nPos;
+ }
+ else
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ catch( Exception & )
+ {
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ return 0;
+}
+
+void UCBStream::FlushData()
+{
+ try
+ {
+ Reference< XOutputStream > xOSFromS;
+ if( xOS.is() )
+ xOS->flush();
+ else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
+ xOSFromS->flush();
+ else
+ SetError( ERRCODE_IO_GENERAL );
+ }
+ catch( Exception & )
+ {
+ SetError( ERRCODE_IO_GENERAL );
+ }
+}
+
+void UCBStream::SetSize( ULONG nSize )
+{
+ (void)nSize;
+
+ DBG_ERROR( "not allowed to call from basic" );
+ SetError( ERRCODE_IO_GENERAL );
+}
+
+#endif
+
+// Oeffnen eines Streams
+SbError SbiStream::Open
+( short nCh, const ByteString& rName, short nStrmMode, short nFlags, short nL )
+{
+ nMode = nFlags;
+ nLen = nL;
+ nChan = nCh;
+ nLine = 0;
+ nExpandOnWriteTo = 0;
+ if( ( nStrmMode & ( STREAM_READ|STREAM_WRITE ) ) == STREAM_READ )
+ nStrmMode |= STREAM_NOCREATE;
+ String aStr( rName, gsl_getSystemTextEncoding() );
+ String aNameStr = getFullPath( aStr );
+
+#ifdef _USE_UNO
+ if( hasUno() )
+ {
+ Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ if( xSMgr.is() )
+ {
+ Reference< XSimpleFileAccess >
+ xSFI( xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY );
+ if( xSFI.is() )
+ {
+ try
+ {
+
+ // #??? For write access delete file if it already exists (not for appending)
+ if( (nStrmMode & STREAM_WRITE) != 0 && !IsAppend() && !IsBinary() &&
+ xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) )
+ {
+ xSFI->kill( aNameStr );
+ }
+
+ if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
+ {
+ Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
+ pStrm = new UCBStream( xIS );
+ }
+ else if( nStrmMode & STREAM_WRITE )
+ {
+ Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
+ pStrm = new UCBStream( xIS );
+ // Open for writing is not implemented in ucb yet!!!
+ //Reference< XOutputStream > xIS = xSFI->openFileWrite( aNameStr );
+ //pStrm = new UCBStream( xIS );
+ }
+ else //if( nStrmMode & STREAM_READ )
+ {
+ Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr );
+ pStrm = new UCBStream( xIS );
+ }
+
+ }
+ catch( Exception & )
+ {
+ nError = ERRCODE_IO_GENERAL;
+ }
+ }
+ }
+ }
+
+#endif
+ if( !pStrm )
+ {
+#ifdef _OLD_FILE_IMPL
+ pStrm = new SvFileStream( aNameStr, nStrmMode );
+#else
+ pStrm = new OslStream( aNameStr, nStrmMode );
+#endif
+ }
+ if( IsAppend() )
+ pStrm->Seek( STREAM_SEEK_TO_END );
+ MapError();
+ if( nError )
+ delete pStrm, pStrm = NULL;
+ return nError;
+}
+
+SbError SbiStream::Close()
+{
+ if( pStrm )
+ {
+ if( !hasUno() )
+ {
+#ifdef _OLD_FILE_IMPL
+ ((SvFileStream *)pStrm)->Close();
+#endif
+ }
+ MapError();
+ delete pStrm;
+ pStrm = NULL;
+ }
+ nChan = 0;
+ return nError;
+}
+
+SbError SbiStream::Read( ByteString& rBuf, USHORT n, bool bForceReadingPerByte )
+{
+ nExpandOnWriteTo = 0;
+ if( !bForceReadingPerByte && IsText() )
+ {
+ pStrm->ReadLine( rBuf );
+ nLine++;
+ }
+ else
+ {
+ if( !n ) n = nLen;
+ if( !n )
+ return nError = SbERR_BAD_RECORD_LENGTH;
+ rBuf.Fill( n, ' ' );
+ pStrm->Read( (void*)rBuf.GetBuffer(), n );
+ }
+ MapError();
+ if( !nError && pStrm->IsEof() )
+ nError = SbERR_READ_PAST_EOF;
+ return nError;
+}
+
+SbError SbiStream::Read( char& ch )
+{
+ nExpandOnWriteTo = 0;
+ if( !aLine.Len() )
+ {
+ Read( aLine, 0 );
+ aLine += '\n';
+ }
+ ch = aLine.GetBuffer()[0];
+ aLine.Erase( 0, 1 );
+ return nError;
+}
+
+void SbiStream::ExpandFile()
+{
+ if ( nExpandOnWriteTo )
+ {
+ ULONG nCur = pStrm->Seek(STREAM_SEEK_TO_END);
+ if( nCur < nExpandOnWriteTo )
+ {
+ ULONG nDiff = nExpandOnWriteTo - nCur;
+ char c = 0;
+ while( nDiff-- )
+ *pStrm << c;
+ }
+ else
+ {
+ pStrm->Seek( nExpandOnWriteTo );
+ }
+ nExpandOnWriteTo = 0;
+ }
+}
+
+SbError SbiStream::Write( const ByteString& rBuf, USHORT n )
+{
+ ExpandFile();
+ if( IsAppend() )
+ pStrm->Seek( STREAM_SEEK_TO_END );
+
+ if( IsText() )
+ {
+ aLine += rBuf;
+ // Raus damit, wenn das Ende ein LF ist, aber CRLF vorher
+ // strippen, da der SvStrm ein CRLF anfuegt!
+ USHORT nLineLen = aLine.Len();
+ if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0A )
+ {
+ aLine.Erase( nLineLen );
+ if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0D )
+ aLine.Erase( nLineLen );
+ pStrm->WriteLines( aLine );
+ aLine.Erase();
+ }
+ }
+ else
+ {
+ if( !n ) n = nLen;
+ if( !n )
+ return nError = SbERR_BAD_RECORD_LENGTH;
+ pStrm->Write( rBuf.GetBuffer(), n );
+ MapError();
+ }
+ return nError;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+// Zugriff auf das aktuelle I/O-System:
+
+SbiIoSystem* SbGetIoSystem()
+{
+ SbiInstance* pInst = pINST;
+ return pInst ? pInst->GetIoSystem() : NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+SbiIoSystem::SbiIoSystem()
+{
+ for( short i = 0; i < CHANNELS; i++ )
+ pChan[ i ] = NULL;
+ nChan = 0;
+ nError = 0;
+}
+
+SbiIoSystem::~SbiIoSystem()
+{
+ Shutdown();
+}
+
+SbError SbiIoSystem::GetError()
+{
+ SbError n = nError; nError = 0;
+ return n;
+}
+
+void SbiIoSystem::Open
+ ( short nCh, const ByteString& rName, short nMode, short nFlags, short nLen )
+{
+ nError = 0;
+ if( nCh >= CHANNELS || !nCh )
+ nError = SbERR_BAD_CHANNEL;
+ else if( pChan[ nCh ] )
+ nError = SbERR_FILE_ALREADY_OPEN;
+ else
+ {
+ pChan[ nCh ] = new SbiStream;
+ nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen );
+ if( nError )
+ delete pChan[ nCh ], pChan[ nCh ] = NULL;
+ }
+ nChan = 0;
+}
+
+// Aktuellen Kanal schliessen
+
+void SbiIoSystem::Close()
+{
+ if( !nChan )
+ nError = SbERR_BAD_CHANNEL;
+ else if( !pChan[ nChan ] )
+ nError = SbERR_BAD_CHANNEL;
+ else
+ {
+ nError = pChan[ nChan ]->Close();
+ delete pChan[ nChan ];
+ pChan[ nChan ] = NULL;
+ }
+ nChan = 0;
+}
+
+// Shutdown nach Programmlauf
+
+void SbiIoSystem::Shutdown()
+{
+ for( short i = 1; i < CHANNELS; i++ )
+ {
+ if( pChan[ i ] )
+ {
+ SbError n = pChan[ i ]->Close();
+ delete pChan[ i ];
+ pChan[ i ] = NULL;
+ if( n && !nError )
+ nError = n;
+ }
+ }
+ nChan = 0;
+ // Noch was zu PRINTen?
+ if( aOut.Len() )
+ {
+ String aOutStr( aOut, gsl_getSystemTextEncoding() );
+#if defined GCC
+ Window* pParent = Application::GetDefDialogParent();
+ MessBox( pParent, WinBits( WB_OK ), String(), aOutStr ).Execute();
+#else
+ MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), String(), aOutStr ).Execute();
+#endif
+ }
+ aOut.Erase();
+}
+
+// Aus aktuellem Kanal lesen
+
+void SbiIoSystem::Read( ByteString& rBuf, short n )
+{
+ if( !nChan )
+ ReadCon( rBuf );
+ else if( !pChan[ nChan ] )
+ nError = SbERR_BAD_CHANNEL;
+ else
+ nError = pChan[ nChan ]->Read( rBuf, n );
+}
+
+char SbiIoSystem::Read()
+{
+ char ch = ' ';
+ if( !nChan )
+ {
+ if( !aIn.Len() )
+ {
+ ReadCon( aIn );
+ aIn += '\n';
+ }
+ ch = aIn.GetBuffer()[0];
+ aIn.Erase( 0, 1 );
+ }
+ else if( !pChan[ nChan ] )
+ nError = SbERR_BAD_CHANNEL;
+ else
+ nError = pChan[ nChan ]->Read( ch );
+ return ch;
+}
+
+void SbiIoSystem::Write( const ByteString& rBuf, short n )
+{
+ if( !nChan )
+ WriteCon( rBuf );
+ else if( !pChan[ nChan ] )
+ nError = SbERR_BAD_CHANNEL;
+ else
+ nError = pChan[ nChan ]->Write( rBuf, n );
+}
+
+short SbiIoSystem::NextChannel()
+{
+ for( short i = 1; i < CHANNELS; i++ )
+ {
+ if( !pChan[ i ] )
+ return i;
+ }
+ nError = SbERR_TOO_MANY_FILES;
+ return CHANNELS;
+}
+
+// nChannel == 0..CHANNELS-1
+
+SbiStream* SbiIoSystem::GetStream( short nChannel ) const
+{
+ SbiStream* pRet = 0;
+ if( nChannel >= 0 && nChannel < CHANNELS )
+ pRet = pChan[ nChannel ];
+ return pRet;
+}
+
+void SbiIoSystem::CloseAll(void)
+{
+ for( short i = 1; i < CHANNELS; i++ )
+ {
+ if( pChan[ i ] )
+ {
+ SbError n = pChan[ i ]->Close();
+ delete pChan[ i ];
+ pChan[ i ] = NULL;
+ if( n && !nError )
+ nError = n;
+ }
+ }
+}
+
+/***************************************************************************
+*
+* Console Support
+*
+***************************************************************************/
+
+// Einlesen einer Zeile von der Console
+
+void SbiIoSystem::ReadCon( ByteString& rIn )
+{
+ String aPromptStr( aPrompt, gsl_getSystemTextEncoding() );
+ SbiInputDialog aDlg( NULL, aPromptStr );
+ if( aDlg.Execute() )
+ rIn = ByteString( aDlg.GetInput(), gsl_getSystemTextEncoding() );
+ else
+ nError = SbERR_USER_ABORT;
+ aPrompt.Erase();
+}
+
+// Ausgabe einer MessageBox, wenn im Console-Puffer ein CR ist
+
+void SbiIoSystem::WriteCon( const ByteString& rText )
+{
+ aOut += rText;
+ USHORT n1 = aOut.Search( '\n' );
+ USHORT n2 = aOut.Search( '\r' );
+ if( n1 != STRING_NOTFOUND || n2 != STRING_NOTFOUND )
+ {
+ if( n1 == STRING_NOTFOUND ) n1 = n2;
+ else
+ if( n2 == STRING_NOTFOUND ) n2 = n1;
+ if( n1 > n2 ) n1 = n2;
+ ByteString s( aOut.Copy( 0, n1 ) );
+ aOut.Erase( 0, n1 );
+ while( aOut.GetBuffer()[0] == '\n' || aOut.GetBuffer()[0] == '\r' )
+ aOut.Erase( 0, 1 );
+ String aStr( s, gsl_getSystemTextEncoding() );
+ {
+ vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ if( !MessBox( GetpApp()->GetDefDialogParent(),
+ WinBits( WB_OK_CANCEL | WB_DEF_OK ),
+ String(), aStr ).Execute() )
+ nError = SbERR_USER_ABORT;
+ }
+ }
+}
+
diff --git a/basic/source/runtime/makefile.mk b/basic/source/runtime/makefile.mk
new file mode 100644
index 000000000000..f2ed11196b28
--- /dev/null
+++ b/basic/source/runtime/makefile.mk
@@ -0,0 +1,71 @@
+#*************************************************************************
+#
+# 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=runtime
+
+ENABLE_EXCEPTIONS = TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+
+# --- Allgemein -----------------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/basrdll.obj \
+ $(SLO)$/inputbox.obj \
+ $(SLO)$/runtime.obj \
+ $(SLO)$/step0.obj \
+ $(SLO)$/step1.obj \
+ $(SLO)$/step2.obj \
+ $(SLO)$/iosys.obj \
+ $(SLO)$/stdobj.obj \
+ $(SLO)$/stdobj1.obj \
+ $(SLO)$/methods.obj \
+ $(SLO)$/methods1.obj \
+ $(SLO)$/props.obj \
+ $(SLO)$/ddectrl.obj \
+ $(SLO)$/dllmgr.obj
+
+.IF "$(GUI)$(COM)$(CPU)" == "WNTMSCI"
+SLOFILES+= $(SLO)$/wnt.obj
+.ELIF "$(GUI)$(COM)$(CPU)" == "WNTGCCI"
+SLOFILES+= $(SLO)$/wnt-mingw.obj
+.ENDIF
+
+# --- Targets -------------------------------------------------------------
+
+.INCLUDE : target.mk
+
+$(SLO)$/%.obj: %.s
+#kendy: Cut'n'paste from bridges/source/cpp_uno/mingw_intel/makefile.mk
+ $(CC) -c -o $(SLO)$/$(@:b).obj $<
+ touch $@
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
new file mode 100644
index 000000000000..1a60a5d79a45
--- /dev/null
+++ b/basic/source/runtime/methods.cxx
@@ -0,0 +1,4583 @@
+/*************************************************************************
+ *
+ * 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/date.hxx>
+#include <basic/sbxvar.hxx>
+#ifndef _VOS_PROCESS_HXX
+#include <vos/process.hxx>
+#endif
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/wintypes.hxx>
+#include <vcl/msgbox.hxx>
+#include <basic/sbx.hxx>
+#include <svl/zforlist.hxx>
+#include <rtl/math.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/time.h>
+#include <unotools/charclass.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <tools/wldcrd.hxx>
+#include <i18npool/lang.h>
+
+#include "runtime.hxx"
+#include "sbunoobj.hxx"
+#ifdef WNT
+#include <tools/prewin.h>
+#include "winbase.h"
+#include <tools/postwin.h>
+#ifndef _FSYS_HXX //autogen
+#include <tools/fsys.hxx>
+#endif
+#else
+#include <osl/file.hxx>
+#endif
+#include "errobject.hxx"
+
+#ifdef _USE_UNO
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+
+using namespace comphelper;
+using namespace osl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::io;
+
+#endif /* _USE_UNO */
+
+//#define _ENABLE_CUR_DIR
+
+#include "stdobj.hxx"
+#include <basic/sbstdobj.hxx>
+#include "rtlproto.hxx"
+#include "basrid.hxx"
+#include "image.hxx"
+#include "sb.hrc"
+#include "iosys.hxx"
+#include "ddectrl.hxx"
+#include <sbintern.hxx>
+
+#include <list>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#if defined (WIN) || defined (WNT) || defined (OS2)
+#include <direct.h> // _getdcwd get current work directory, _chdrive
+#endif
+
+#ifdef WIN
+#include <dos.h> // _dos_getfileattr
+#include <errno.h>
+#endif
+
+#ifdef UNX
+#include <errno.h>
+#include <unistd.h>
+#endif
+
+#ifdef WNT
+#include <io.h>
+#endif
+
+#include <basic/sbobjmod.hxx>
+
+static void FilterWhiteSpace( String& rStr )
+{
+ rStr.EraseAllChars( ' ' );
+ rStr.EraseAllChars( '\t' );
+ rStr.EraseAllChars( '\n' );
+ rStr.EraseAllChars( '\r' );
+}
+
+static long GetDayDiff( const Date& rDate )
+{
+ Date aRefDate( 1,1,1900 );
+ long nDiffDays;
+ if ( aRefDate > rDate )
+ {
+ nDiffDays = (long)(aRefDate - rDate);
+ nDiffDays *= -1;
+ }
+ else
+ nDiffDays = (long)(rDate - aRefDate);
+ nDiffDays += 2; // Anpassung VisualBasic: 1.Jan.1900 == 2
+ return nDiffDays;
+}
+
+static CharClass& GetCharClass( void )
+{
+ static sal_Bool bNeedsInit = sal_True;
+ static ::com::sun::star::lang::Locale aLocale;
+ if( bNeedsInit )
+ {
+ bNeedsInit = sal_False;
+ aLocale = Application::GetSettings().GetLocale();
+ }
+ static CharClass aCharClass( aLocale );
+ return aCharClass;
+}
+
+static inline BOOL isFolder( FileStatus::Type aType )
+{
+ return ( aType == FileStatus::Directory || aType == FileStatus::Volume );
+}
+
+
+//*** UCB file access ***
+
+// Converts possibly relative paths to absolute paths
+// according to the setting done by ChDir/ChDrive
+String getFullPath( const String& aRelPath )
+{
+ ::rtl::OUString aFileURL;
+
+ // #80204 Try first if it already is a valid URL
+ INetURLObject aURLObj( aRelPath );
+ aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
+
+ if( !aFileURL.getLength() )
+ {
+ File::getFileURLFromSystemPath( aRelPath, aFileURL );
+ }
+
+ return aFileURL;
+}
+
+// Sets (virtual) current path for UCB file access
+void implChDir( const String& aDir )
+{
+ (void)aDir;
+ // TODO
+}
+
+// Sets (virtual) current drive for UCB file access
+void implChDrive( const String& aDrive )
+{
+ (void)aDrive;
+ // TODO
+}
+
+// Returns (virtual) current path for UCB file access
+String implGetCurDir( void )
+{
+ String aRetStr;
+
+ return aRetStr;
+}
+
+// TODO: -> SbiGlobals
+static com::sun::star::uno::Reference< XSimpleFileAccess3 > getFileAccess( void )
+{
+ static com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI;
+ if( !xSFI.is() )
+ {
+ com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ if( xSMgr.is() )
+ {
+ xSFI = com::sun::star::uno::Reference< XSimpleFileAccess3 >( xSMgr->createInstance
+ ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY );
+ }
+ }
+ return xSFI;
+}
+
+
+
+// Properties und Methoden legen beim Get (bPut = FALSE) den Returnwert
+// im Element 0 des Argv ab; beim Put (bPut = TRUE) wird der Wert aus
+// Element 0 gespeichert.
+
+// CreateObject( class )
+
+RTLFUNC(CreateObject)
+{
+ (void)bWrite;
+
+ String aClass( rPar.Get( 1 )->GetString() );
+ SbxObjectRef p = SbxBase::CreateObject( aClass );
+ if( !p )
+ StarBASIC::Error( SbERR_CANNOT_LOAD );
+ else
+ {
+ // Convenience: BASIC als Parent eintragen
+ p->SetParent( pBasic );
+ rPar.Get( 0 )->PutObject( p );
+ }
+}
+
+// Error( n )
+
+RTLFUNC(Error)
+{
+ (void)bWrite;
+
+ if( !pBasic )
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ else
+ {
+ String aErrorMsg;
+ SbError nErr = 0L;
+ INT32 nCode = 0;
+ if( rPar.Count() == 1 )
+ {
+ nErr = StarBASIC::GetErrBasic();
+ aErrorMsg = StarBASIC::GetErrorMsg();
+ }
+ else
+ {
+ nCode = rPar.Get( 1 )->GetLong();
+ if( nCode > 65535L )
+ StarBASIC::Error( SbERR_CONVERSION );
+ else
+ nErr = StarBASIC::GetSfxFromVBError( (USHORT)nCode );
+ }
+
+ bool bVBA = SbiRuntime::isVBAEnabled();
+ String tmpErrMsg;
+ if( bVBA && aErrorMsg.Len() > 0 )
+ {
+ tmpErrMsg = aErrorMsg;
+ }
+ else
+ {
+ pBasic->MakeErrorText( nErr, aErrorMsg );
+ tmpErrMsg = pBasic->GetErrorText();
+ }
+ // If this rtlfunc 'Error' passed a errcode the same as the active Err Objects's
+ // current err then return the description for the error message if it is set
+ // ( complicated isn't it ? )
+ if ( bVBA && rPar.Count() > 1 )
+ {
+ com::sun::star::uno::Reference< ooo::vba::XErrObject > xErrObj( SbxErrObject::getUnoErrObject() );
+ if ( xErrObj.is() && xErrObj->getNumber() == nCode && xErrObj->getDescription().getLength() )
+ tmpErrMsg = xErrObj->getDescription();
+ }
+ rPar.Get( 0 )->PutString( tmpErrMsg );
+ }
+}
+
+// Sinus
+
+RTLFUNC(Sin)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ rPar.Get( 0 )->PutDouble( sin( pArg->GetDouble() ) );
+ }
+}
+
+// Cosinus
+
+RTLFUNC(Cos)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ rPar.Get( 0 )->PutDouble( cos( pArg->GetDouble() ) );
+ }
+}
+
+// Atn
+
+RTLFUNC(Atn)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ rPar.Get( 0 )->PutDouble( atan( pArg->GetDouble() ) );
+ }
+}
+
+
+
+RTLFUNC(Abs)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ rPar.Get( 0 )->PutDouble( fabs( pArg->GetDouble() ) );
+ }
+}
+
+
+RTLFUNC(Asc)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ String aStr( pArg->GetString() );
+ if ( aStr.Len() == 0 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ rPar.Get(0)->PutEmpty();
+ }
+ else
+ {
+ sal_Unicode aCh = aStr.GetBuffer()[0];
+ rPar.Get(0)->PutLong( aCh );
+ }
+ }
+}
+
+RTLFUNC(Chr)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ sal_Unicode aCh = (sal_Unicode)pArg->GetUShort();
+ String aStr( aCh );
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+
+#ifdef UNX
+#define _MAX_PATH 260
+#define _PATH_INCR 250
+#endif
+
+RTLFUNC(CurDir)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von
+ // der Anpassung an virtuelle URLs nich betroffen, da bei Nutzung der
+ // DirEntry-Funktionalitaet keine Moeglichkeit besteht, das aktuelle so
+ // zu ermitteln, dass eine virtuelle URL geliefert werden koennte.
+
+// rPar.Get(0)->PutEmpty();
+#if defined (WIN) || defined (WNT) || defined (OS2)
+ int nCurDir = 0; // Current dir // JSM
+ if ( rPar.Count() == 2 )
+ {
+ String aDrive = rPar.Get(1)->GetString();
+ if ( aDrive.Len() != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ else
+ {
+ nCurDir = (int)aDrive.GetBuffer()[0];
+ if ( !isalpha( nCurDir ) )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ else
+ nCurDir -= ( 'A' - 1 );
+ }
+ }
+ char* pBuffer = new char[ _MAX_PATH ];
+#ifdef OS2
+ if( !nCurDir )
+ nCurDir = _getdrive();
+#endif
+ if ( _getdcwd( nCurDir, pBuffer, _MAX_PATH ) != 0 )
+ rPar.Get(0)->PutString( String::CreateFromAscii( pBuffer ) );
+ else
+ StarBASIC::Error( SbERR_NO_DEVICE );
+ delete [] pBuffer;
+
+#elif defined( UNX )
+
+ int nSize = _PATH_INCR;
+ char* pMem;
+ while( TRUE )
+ {
+ pMem = new char[nSize];
+ if( !pMem )
+ {
+ StarBASIC::Error( SbERR_NO_MEMORY );
+ return;
+ }
+ if( getcwd( pMem, nSize-1 ) != NULL )
+ {
+ rPar.Get(0)->PutString( String::CreateFromAscii(pMem) );
+ delete [] pMem;
+ return;
+ }
+ if( errno != ERANGE )
+ {
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ delete [] pMem;
+ return;
+ }
+ delete [] pMem;
+ nSize += _PATH_INCR;
+ };
+
+#endif
+}
+
+RTLFUNC(ChDir) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if (rPar.Count() == 2)
+ {
+#ifdef _ENABLE_CUR_DIR
+ String aPath = rPar.Get(1)->GetString();
+ BOOL bError = FALSE;
+#ifdef WNT
+ // #55997 Laut MI hilft es bei File-URLs einen DirEntry zwischenzuschalten
+ // #40996 Harmoniert bei Verwendung der WIN32-Funktion nicht mit getdir
+ DirEntry aEntry( aPath );
+ ByteString aFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() );
+ if( chdir( aFullPath.GetBuffer()) )
+ bError = TRUE;
+#else
+ if (!DirEntry(aPath).SetCWD())
+ bError = TRUE;
+#endif
+ if( bError )
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+#endif
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(ChDrive) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if (rPar.Count() == 2)
+ {
+#ifdef _ENABLE_CUR_DIR
+ // Keine Laufwerke in Unix
+#ifndef UNX
+ String aPar1 = rPar.Get(1)->GetString();
+
+#if defined (WIN) || defined (WNT) || defined (OS2)
+ if (aPar1.Len() > 0)
+ {
+ int nCurDrive = (int)aPar1.GetBuffer()[0]; ;
+ if ( !isalpha( nCurDrive ) )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ else
+ nCurDrive -= ( 'A' - 1 );
+ if (_chdrive(nCurDrive))
+ StarBASIC::Error( SbERR_NO_DEVICE );
+ }
+#endif
+
+#endif
+ // #ifndef UNX
+#endif
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+
+// Implementation of StepRENAME with UCB
+void implStepRenameUCB( const String& aSource, const String& aDest )
+{
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ String aSourceFullPath = getFullPath( aSource );
+ if( !xSFI->exists( aSourceFullPath ) )
+ {
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ return;
+ }
+
+ String aDestFullPath = getFullPath( aDest );
+ if( xSFI->exists( aDestFullPath ) )
+ StarBASIC::Error( SbERR_FILE_EXISTS );
+ else
+ xSFI->move( aSourceFullPath, aDestFullPath );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ }
+ }
+}
+
+// Implementation of StepRENAME with OSL
+void implStepRenameOSL( const String& aSource, const String& aDest )
+{
+ FileBase::RC nRet = File::move( getFullPathUNC( aSource ), getFullPathUNC( aDest ) );
+ if( nRet != FileBase::E_None )
+ {
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ }
+}
+
+RTLFUNC(FileCopy) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if (rPar.Count() == 3)
+ {
+ String aSource = rPar.Get(1)->GetString();
+ String aDest = rPar.Get(2)->GetString();
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ DirEntry aSourceDirEntry(aSource);
+ if (aSourceDirEntry.Exists())
+ {
+ if (aSourceDirEntry.CopyTo(DirEntry(aDest),FSYS_ACTION_COPYFILE) != FSYS_ERR_OK)
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ }
+ else
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+#else
+ FileBase::RC nRet = File::copy( getFullPathUNC( aSource ), getFullPathUNC( aDest ) );
+ if( nRet != FileBase::E_None )
+ {
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ }
+#endif
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(Kill) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if (rPar.Count() == 2)
+ {
+ String aFileSpec = rPar.Get(1)->GetString();
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ String aFullPath = getFullPath( aFileSpec );
+ if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) )
+ {
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ return;
+ }
+ try
+ {
+ xSFI->kill( aFullPath );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ if(DirEntry(aFileSpec).Kill() != FSYS_ERR_OK)
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+#else
+ File::remove( getFullPathUNC( aFileSpec ) );
+#endif
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(MkDir) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if (rPar.Count() == 2)
+ {
+ String aPath = rPar.Get(1)->GetString();
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ xSFI->createFolder( getFullPath( aPath ) );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ if (!DirEntry(aPath).MakeDir())
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+#else
+ Directory::create( getFullPathUNC( aPath ) );
+#endif
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+
+#ifndef _OLD_FILE_IMPL
+
+// In OSL only empty directories can be deleted
+// so we have to delete all files recursively
+void implRemoveDirRecursive( const String& aDirPath )
+{
+ DirectoryItem aItem;
+ FileBase::RC nRet = DirectoryItem::get( aDirPath, aItem );
+ sal_Bool bExists = (nRet == FileBase::E_None);
+
+ FileStatus aFileStatus( FileStatusMask_Type );
+ nRet = aItem.getFileStatus( aFileStatus );
+ FileStatus::Type aType = aFileStatus.getFileType();
+ sal_Bool bFolder = isFolder( aType );
+
+ if( !bExists || !bFolder )
+ {
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ return;
+ }
+
+ Directory aDir( aDirPath );
+ nRet = aDir.open();
+ if( nRet != FileBase::E_None )
+ {
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ return;
+ }
+
+ for( ;; )
+ {
+ DirectoryItem aItem2;
+ nRet = aDir.getNextItem( aItem2 );
+ if( nRet != FileBase::E_None )
+ break;
+
+ // Handle flags
+ FileStatus aFileStatus2( FileStatusMask_Type | FileStatusMask_FileURL );
+ nRet = aItem2.getFileStatus( aFileStatus2 );
+ ::rtl::OUString aPath = aFileStatus2.getFileURL();
+
+ // Directory?
+ FileStatus::Type aType2 = aFileStatus2.getFileType();
+ sal_Bool bFolder2 = isFolder( aType2 );
+ if( bFolder2 )
+ {
+ implRemoveDirRecursive( aPath );
+ }
+ else
+ {
+ File::remove( aPath );
+ }
+ }
+ nRet = aDir.close();
+
+ nRet = Directory::remove( aDirPath );
+}
+#endif
+
+
+RTLFUNC(RmDir) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if (rPar.Count() == 2)
+ {
+ String aPath = rPar.Get(1)->GetString();
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ if( !xSFI->isFolder( aPath ) )
+ {
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ return;
+ }
+ SbiInstance* pInst = pINST;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ Sequence< ::rtl::OUString > aContent = xSFI->getFolderContents( aPath, true );
+ sal_Int32 nCount = aContent.getLength();
+ if( nCount > 0 )
+ {
+ StarBASIC::Error( SbERR_ACCESS_ERROR );
+ return;
+ }
+ }
+
+ xSFI->kill( getFullPath( aPath ) );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ DirEntry aDirEntry(aPath);
+ if (aDirEntry.Kill() != FSYS_ERR_OK)
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+#else
+ implRemoveDirRecursive( getFullPathUNC( aPath ) );
+#endif
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(SendKeys) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+}
+
+RTLFUNC(Exp)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double aDouble = rPar.Get( 1 )->GetDouble();
+ aDouble = exp( aDouble );
+ checkArithmeticOverflow( aDouble );
+ rPar.Get( 0 )->PutDouble( aDouble );
+ }
+}
+
+RTLFUNC(FileLen)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ String aStr( pArg->GetString() );
+ INT32 nLen = 0;
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ nLen = xSFI->getSize( getFullPath( aStr ) );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ FileStat aStat = DirEntry( aStr );
+ nLen = aStat.GetSize();
+#else
+ DirectoryItem aItem;
+ FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem );
+ FileStatus aFileStatus( FileStatusMask_FileSize );
+ nRet = aItem.getFileStatus( aFileStatus );
+ nLen = (INT32)aFileStatus.getFileSize();
+#endif
+ }
+ rPar.Get(0)->PutLong( (long)nLen );
+ }
+}
+
+
+RTLFUNC(Hex)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ char aBuffer[16];
+ SbxVariableRef pArg = rPar.Get( 1 );
+ if ( pArg->IsInteger() )
+ snprintf( aBuffer, sizeof(aBuffer), "%X", pArg->GetInteger() );
+ else
+ snprintf( aBuffer, sizeof(aBuffer), "%lX", static_cast<long unsigned int>(pArg->GetLong()) );
+ rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) );
+ }
+}
+
+// InStr( [start],string,string,[compare] )
+
+RTLFUNC(InStr)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ ULONG nArgCount = rPar.Count()-1;
+ if ( nArgCount < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ USHORT nStartPos = 1;
+
+ USHORT nFirstStringPos = 1;
+ if ( nArgCount >= 3 )
+ {
+ INT32 lStartPos = rPar.Get(1)->GetLong();
+ if( lStartPos <= 0 || lStartPos > 0xffff )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ lStartPos = 1;
+ }
+ nStartPos = (USHORT)lStartPos;
+ nFirstStringPos++;
+ }
+
+ SbiInstance* pInst = pINST;
+ int bTextMode;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
+ bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE;
+ }
+ else
+ {
+ bTextMode = 1;;
+ }
+ if ( nArgCount == 4 )
+ bTextMode = rPar.Get(4)->GetInteger();
+
+ USHORT nPos;
+ const String& rToken = rPar.Get(nFirstStringPos+1)->GetString();
+
+ // #97545 Always find empty string
+ if( !rToken.Len() )
+ {
+ nPos = nStartPos;
+ }
+ else
+ {
+ if( !bTextMode )
+ {
+ const String& rStr1 = rPar.Get(nFirstStringPos)->GetString();
+
+ nPos = rStr1.Search( rToken, nStartPos-1 );
+ if ( nPos == STRING_NOTFOUND )
+ nPos = 0;
+ else
+ nPos++;
+ }
+ else
+ {
+ String aStr1 = rPar.Get(nFirstStringPos)->GetString();
+ String aToken = rToken;
+
+ aStr1.ToUpperAscii();
+ aToken.ToUpperAscii();
+
+ nPos = aStr1.Search( aToken, nStartPos-1 );
+ if ( nPos == STRING_NOTFOUND )
+ nPos = 0;
+ else
+ nPos++;
+ }
+ }
+ rPar.Get(0)->PutLong( nPos );
+ }
+}
+
+
+// InstrRev(string1, string2[, start[, compare]])
+
+RTLFUNC(InStrRev)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ ULONG nArgCount = rPar.Count()-1;
+ if ( nArgCount < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr1 = rPar.Get(1)->GetString();
+ String aToken = rPar.Get(2)->GetString();
+
+ INT32 lStartPos = -1;
+ if ( nArgCount >= 3 )
+ {
+ lStartPos = rPar.Get(3)->GetLong();
+ if( (lStartPos <= 0 && lStartPos != -1) || lStartPos > 0xffff )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ lStartPos = -1;
+ }
+ }
+
+ SbiInstance* pInst = pINST;
+ int bTextMode;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
+ bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE;
+ }
+ else
+ {
+ bTextMode = 1;;
+ }
+ if ( nArgCount == 4 )
+ bTextMode = rPar.Get(4)->GetInteger();
+
+ USHORT nStrLen = aStr1.Len();
+ USHORT nStartPos = lStartPos == -1 ? nStrLen : (USHORT)lStartPos;
+
+ USHORT nPos = 0;
+ if( nStartPos <= nStrLen )
+ {
+ USHORT nTokenLen = aToken.Len();
+ if( !nTokenLen )
+ {
+ // Always find empty string
+ nPos = nStartPos;
+ }
+ else if( nStrLen > 0 )
+ {
+ if( !bTextMode )
+ {
+ ::rtl::OUString aOUStr1 ( aStr1 );
+ ::rtl::OUString aOUToken( aToken );
+ sal_Int32 nRet = aOUStr1.lastIndexOf( aOUToken, nStartPos );
+ if( nRet == -1 )
+ nPos = 0;
+ else
+ nPos = (USHORT)nRet + 1;
+ }
+ else
+ {
+ aStr1.ToUpperAscii();
+ aToken.ToUpperAscii();
+
+ ::rtl::OUString aOUStr1 ( aStr1 );
+ ::rtl::OUString aOUToken( aToken );
+ sal_Int32 nRet = aOUStr1.lastIndexOf( aOUToken, nStartPos );
+
+ if( nRet == -1 )
+ nPos = 0;
+ else
+ nPos = (USHORT)nRet + 1;
+ }
+ }
+ }
+ rPar.Get(0)->PutLong( nPos );
+ }
+}
+
+
+/*
+ Int( 2.8 ) = 2.0
+ Int( -2.8 ) = -3.0
+ Fix( 2.8 ) = 2.0
+ Fix( -2.8 ) = -2.0 <- !!
+*/
+
+RTLFUNC(Int)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ double aDouble= pArg->GetDouble();
+ /*
+ floor( 2.8 ) = 2.0
+ floor( -2.8 ) = -3.0
+ */
+ aDouble = floor( aDouble );
+ rPar.Get(0)->PutDouble( aDouble );
+ }
+}
+
+
+
+RTLFUNC(Fix)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ double aDouble = pArg->GetDouble();
+ if ( aDouble >= 0.0 )
+ aDouble = floor( aDouble );
+ else
+ aDouble = ceil( aDouble );
+ rPar.Get(0)->PutDouble( aDouble );
+ }
+}
+
+
+RTLFUNC(LCase)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ CharClass& rCharClass = GetCharClass();
+ String aStr( rPar.Get(1)->GetString() );
+ rCharClass.toLower( aStr );
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(Left)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 3 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr( rPar.Get(1)->GetString() );
+ INT32 lResultLen = rPar.Get(2)->GetLong();
+ if( lResultLen > 0xffff )
+ {
+ lResultLen = 0xffff;
+ }
+ else if( lResultLen < 0 )
+ {
+ lResultLen = 0;
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ }
+ aStr.Erase( (USHORT)lResultLen );
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(Log)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double aArg = rPar.Get(1)->GetDouble();
+ if ( aArg > 0 )
+ {
+ double d = log( aArg );
+ checkArithmeticOverflow( d );
+ rPar.Get( 0 )->PutDouble( d );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ }
+}
+
+RTLFUNC(LTrim)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr( rPar.Get(1)->GetString() );
+ aStr.EraseLeadingChars();
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+
+// Mid( String, nStart, nLength )
+
+RTLFUNC(Mid)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ ULONG nArgCount = rPar.Count()-1;
+ if ( nArgCount < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // #23178: Funktionalitaet von Mid$ als Anweisung nachbilden, indem
+ // als weiterer (4.) Parameter ein Ersetzungsstring aufgenommen wird.
+ // Anders als im Original kann in dieser Variante der 3. Parameter
+ // nLength nicht weggelassen werden. Ist ueber bWrite schon vorgesehen.
+ if( nArgCount == 4 )
+ bWrite = TRUE;
+
+ String aArgStr = rPar.Get(1)->GetString();
+ USHORT nStartPos = (USHORT)(rPar.Get(2)->GetLong() );
+ if ( nStartPos == 0 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ nStartPos--;
+ USHORT nLen = 0xffff;
+ bool bWriteNoLenParam = false;
+ if ( nArgCount == 3 || bWrite )
+ {
+ INT32 n = rPar.Get(3)->GetLong();
+ if( bWrite && n == -1 )
+ bWriteNoLenParam = true;
+ nLen = (USHORT)n;
+ }
+ String aResultStr;
+ if ( bWrite )
+ {
+ SbiInstance* pInst = pINST;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ USHORT nArgLen = aArgStr.Len();
+ if( nStartPos + 1 > nArgLen )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aReplaceStr = rPar.Get(4)->GetString();
+ USHORT nReplaceStrLen = aReplaceStr.Len();
+ USHORT nReplaceLen;
+ if( bWriteNoLenParam )
+ {
+ nReplaceLen = nReplaceStrLen;
+ }
+ else
+ {
+ nReplaceLen = nLen;
+ if( nReplaceLen > nReplaceStrLen )
+ nReplaceLen = nReplaceStrLen;
+ }
+
+ USHORT nReplaceEndPos = nStartPos + nReplaceLen;
+ if( nReplaceEndPos > nArgLen )
+ nReplaceLen -= (nReplaceEndPos - nArgLen);
+
+ aResultStr = aArgStr;
+ USHORT nErase = nReplaceLen;
+ aResultStr.Erase( nStartPos, nErase );
+ aResultStr.Insert( aReplaceStr, 0, nReplaceLen, nStartPos );
+ }
+ else
+ {
+ aResultStr = aArgStr;
+ aResultStr.Erase( nStartPos, nLen );
+ aResultStr.Insert(rPar.Get(4)->GetString(),0,nLen,nStartPos);
+ }
+
+ rPar.Get(1)->PutString( aResultStr );
+ }
+ else
+ {
+ aResultStr = aArgStr.Copy( nStartPos, nLen );
+ rPar.Get(0)->PutString( aResultStr );
+ }
+ }
+ }
+}
+
+RTLFUNC(Oct)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ char aBuffer[16];
+ SbxVariableRef pArg = rPar.Get( 1 );
+ if ( pArg->IsInteger() )
+ snprintf( aBuffer, sizeof(aBuffer), "%o", pArg->GetInteger() );
+ else
+ snprintf( aBuffer, sizeof(aBuffer), "%lo", static_cast<long unsigned int>(pArg->GetLong()) );
+ rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) );
+ }
+}
+
+// Replace(expression, find, replace[, start[, count[, compare]]])
+
+RTLFUNC(Replace)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ ULONG nArgCount = rPar.Count()-1;
+ if ( nArgCount < 3 || nArgCount > 6 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aExpStr = rPar.Get(1)->GetString();
+ String aFindStr = rPar.Get(2)->GetString();
+ String aReplaceStr = rPar.Get(3)->GetString();
+
+ INT32 lStartPos = 1;
+ if ( nArgCount >= 4 )
+ {
+ if( rPar.Get(4)->GetType() != SbxEMPTY )
+ lStartPos = rPar.Get(4)->GetLong();
+ if( lStartPos < 1 || lStartPos > 0xffff )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ lStartPos = 1;
+ }
+ }
+
+ INT32 lCount = -1;
+ if( nArgCount >=5 )
+ {
+ if( rPar.Get(5)->GetType() != SbxEMPTY )
+ lCount = rPar.Get(5)->GetLong();
+ if( lCount < -1 || lCount > 0xffff )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ lCount = -1;
+ }
+ }
+
+ SbiInstance* pInst = pINST;
+ int bTextMode;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
+ bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE;
+ }
+ else
+ {
+ bTextMode = 1;
+ }
+ if ( nArgCount == 6 )
+ bTextMode = rPar.Get(6)->GetInteger();
+
+ USHORT nExpStrLen = aExpStr.Len();
+ USHORT nFindStrLen = aFindStr.Len();
+ USHORT nReplaceStrLen = aReplaceStr.Len();
+
+ if( lStartPos <= nExpStrLen )
+ {
+ USHORT nPos = static_cast<USHORT>( lStartPos - 1 );
+ USHORT nCounts = 0;
+ while( lCount == -1 || lCount > nCounts )
+ {
+ String aSrcStr( aExpStr );
+ if( bTextMode )
+ {
+ aSrcStr.ToUpperAscii();
+ aFindStr.ToUpperAscii();
+ }
+ nPos = aSrcStr.Search( aFindStr, nPos );
+ if( nPos != STRING_NOTFOUND )
+ {
+ aExpStr.Replace( nPos, nFindStrLen, aReplaceStr );
+ nPos = nPos - nFindStrLen + nReplaceStrLen + 1;
+ nCounts++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ rPar.Get(0)->PutString( aExpStr.Copy( static_cast<USHORT>(lStartPos - 1) ) );
+ }
+}
+
+RTLFUNC(Right)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 3 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ const String& rStr = rPar.Get(1)->GetString();
+ INT32 lResultLen = rPar.Get(2)->GetLong();
+ if( lResultLen > 0xffff )
+ {
+ lResultLen = 0xffff;
+ }
+ else if( lResultLen < 0 )
+ {
+ lResultLen = 0;
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ }
+ USHORT nResultLen = (USHORT)lResultLen;
+ USHORT nStrLen = rStr.Len();
+ if ( nResultLen > nStrLen )
+ nResultLen = nStrLen;
+ String aResultStr = rStr.Copy( nStrLen-nResultLen );
+ rPar.Get(0)->PutString( aResultStr );
+ }
+}
+
+RTLFUNC(RTL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get( 0 )->PutObject( pBasic->getRTL() );
+}
+
+RTLFUNC(RTrim)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr( rPar.Get(1)->GetString() );
+ aStr.EraseTrailingChars();
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(Sgn)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double aDouble = rPar.Get(1)->GetDouble();
+ INT16 nResult = 0;
+ if ( aDouble > 0 )
+ nResult = 1;
+ else if ( aDouble < 0 )
+ nResult = -1;
+ rPar.Get(0)->PutInteger( nResult );
+ }
+}
+
+RTLFUNC(Space)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr;
+ aStr.Fill( (USHORT)(rPar.Get(1)->GetLong() ));
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(Spc)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr;
+ aStr.Fill( (USHORT)(rPar.Get(1)->GetLong() ));
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(Sqr)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double aDouble = rPar.Get(1)->GetDouble();
+ if ( aDouble >= 0 )
+ rPar.Get(0)->PutDouble( sqrt( aDouble ));
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ }
+}
+
+RTLFUNC(Str)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr;
+ SbxVariableRef pArg = rPar.Get( 1 );
+ pArg->Format( aStr );
+
+ // Numbers start with a space
+ if( pArg->IsNumericRTL() )
+ {
+ // Kommas durch Punkte ersetzen, damit es symmetrisch zu Val ist!
+ aStr.SearchAndReplace( ',', '.' );
+
+ SbiInstance* pInst = pINST;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ xub_StrLen nLen = aStr.Len();
+
+ const sal_Unicode* pBuf = aStr.GetBuffer();
+
+ bool bNeg = ( pBuf[0] == '-' );
+ USHORT iZeroSearch = 0;
+ if( bNeg )
+ iZeroSearch++;
+
+ USHORT iNext = iZeroSearch + 1;
+ if( pBuf[iZeroSearch] == '0' && nLen > iNext && pBuf[iNext] == '.' )
+ {
+ aStr.Erase( iZeroSearch, 1 );
+ pBuf = aStr.GetBuffer();
+ }
+ if( !bNeg )
+ aStr.Insert( ' ', 0 );
+ }
+ else
+ aStr.Insert( ' ', 0 );
+ }
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(StrComp)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ rPar.Get(0)->PutEmpty();
+ return;
+ }
+ const String& rStr1 = rPar.Get(1)->GetString();
+ const String& rStr2 = rPar.Get(2)->GetString();
+
+ SbiInstance* pInst = pINST;
+ INT16 nTextCompare;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
+ nTextCompare = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE;
+ }
+ else
+ {
+ nTextCompare = TRUE;
+ }
+ if ( rPar.Count() == 4 )
+ nTextCompare = rPar.Get(3)->GetInteger();
+
+ if( !bCompatibility )
+ nTextCompare = !nTextCompare;
+
+ StringCompare aResult;
+ sal_Int32 nRetValue = 0;
+ if( nTextCompare )
+ {
+ ::utl::TransliterationWrapper* pTransliterationWrapper = GetSbData()->pTransliterationWrapper;
+ if( !pTransliterationWrapper )
+ {
+ com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ pTransliterationWrapper = GetSbData()->pTransliterationWrapper =
+ new ::utl::TransliterationWrapper( xSMgr,
+ ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE |
+ ::com::sun::star::i18n::TransliterationModules_IGNORE_KANA |
+ ::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH );
+ }
+
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ pTransliterationWrapper->loadModuleIfNeeded( eLangType );
+ nRetValue = pTransliterationWrapper->compareString( rStr1, rStr2 );
+ }
+ else
+ {
+ aResult = rStr1.CompareTo( rStr2 );
+ if ( aResult == COMPARE_LESS )
+ nRetValue = -1;
+ else if ( aResult == COMPARE_GREATER )
+ nRetValue = 1;
+ }
+
+ rPar.Get(0)->PutInteger( sal::static_int_cast< INT16 >( nRetValue ) );
+}
+
+RTLFUNC(String)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr;
+ sal_Unicode aFiller;
+ INT32 lCount = rPar.Get(1)->GetLong();
+ if( lCount < 0 || lCount > 0xffff )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ USHORT nCount = (USHORT)lCount;
+ if( rPar.Get(2)->GetType() == SbxINTEGER )
+ aFiller = (sal_Unicode)rPar.Get(2)->GetInteger();
+ else
+ {
+ const String& rStr = rPar.Get(2)->GetString();
+ aFiller = rStr.GetBuffer()[0];
+ }
+ aStr.Fill( nCount, aFiller );
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(Tan)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ rPar.Get( 0 )->PutDouble( tan( pArg->GetDouble() ) );
+ }
+}
+
+RTLFUNC(UCase)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ CharClass& rCharClass = GetCharClass();
+ String aStr( rPar.Get(1)->GetString() );
+ rCharClass.toUpper( aStr );
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+
+RTLFUNC(Val)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double nResult = 0.0;
+ char* pEndPtr;
+
+ String aStr( rPar.Get(1)->GetString() );
+// lt. Mikkysoft bei Kommas abbrechen!
+// for( USHORT n=0; n < aStr.Len(); n++ )
+// if( aStr[n] == ',' ) aStr[n] = '.';
+
+ FilterWhiteSpace( aStr );
+ if ( aStr.GetBuffer()[0] == '&' && aStr.Len() > 1 )
+ {
+ int nRadix = 10;
+ char aChar = (char)aStr.GetBuffer()[1];
+ if ( aChar == 'h' || aChar == 'H' )
+ nRadix = 16;
+ else if ( aChar == 'o' || aChar == 'O' )
+ nRadix = 8;
+ if ( nRadix != 10 )
+ {
+ ByteString aByteStr( aStr, gsl_getSystemTextEncoding() );
+ INT16 nlResult = (INT16)strtol( aByteStr.GetBuffer()+2, &pEndPtr, nRadix);
+ nResult = (double)nlResult;
+ }
+ }
+ else
+ {
+ // #57844 Lokalisierte Funktion benutzen
+ nResult = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
+ checkArithmeticOverflow( nResult );
+ // ATL: nResult = strtod( aStr.GetStr(), &pEndPtr );
+ }
+
+ rPar.Get(0)->PutDouble( nResult );
+ }
+}
+
+
+// Helper functions for date conversion
+INT16 implGetDateDay( double aDate )
+{
+ aDate -= 2.0; // normieren: 1.1.1900 => 0.0
+ Date aRefDate( 1, 1, 1900 );
+ if ( aDate >= 0.0 )
+ {
+ aDate = floor( aDate );
+ aRefDate += (ULONG)aDate;
+ }
+ else
+ {
+ aDate = ceil( aDate );
+ aRefDate -= (ULONG)(-1.0 * aDate);
+ }
+
+ INT16 nRet = (INT16)( aRefDate.GetDay() );
+ return nRet;
+}
+
+INT16 implGetDateMonth( double aDate )
+{
+ Date aRefDate( 1,1,1900 );
+ long nDays = (long)aDate;
+ nDays -= 2; // normieren: 1.1.1900 => 0.0
+ aRefDate += nDays;
+ INT16 nRet = (INT16)( aRefDate.GetMonth() );
+ return nRet;
+}
+
+INT16 implGetDateYear( double aDate )
+{
+ Date aRefDate( 1,1,1900 );
+ long nDays = (long) aDate;
+ nDays -= 2; // normieren: 1.1.1900 => 0.0
+ aRefDate += nDays;
+ INT16 nRet = (INT16)( aRefDate.GetYear() );
+ return nRet;
+}
+
+BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet )
+{
+ if ( nYear < 30 && SbiRuntime::isVBAEnabled() )
+ nYear += 2000;
+ else if ( nYear < 100 )
+ nYear += 1900;
+ Date aCurDate( nDay, nMonth, nYear );
+ if ((nYear < 100 || nYear > 9999) )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return FALSE;
+ }
+ if ( !SbiRuntime::isVBAEnabled() )
+ {
+ if ( (nMonth < 1 || nMonth > 12 )||
+ (nDay < 1 || nDay > 31 ) )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return FALSE;
+ }
+ }
+ else
+ {
+ // grab the year & month
+ aCurDate = Date( 1, (( nMonth % 12 ) > 0 ) ? ( nMonth % 12 ) : 12 + ( nMonth % 12 ), nYear );
+
+ // adjust year based on month value
+ // e.g. 2000, 0, xx = 1999, 12, xx ( or December of the previous year )
+ // 2000, 13, xx = 2001, 1, xx ( or January of the following year )
+ if( ( nMonth < 1 ) || ( nMonth > 12 ) )
+ {
+ // inacurrate around leap year, don't use days to calculate,
+ // just modify the months directory
+ INT16 nYearAdj = ( nMonth /12 ); // default to positive months inputed
+ if ( nMonth <=0 )
+ nYearAdj = ( ( nMonth -12 ) / 12 );
+ aCurDate.SetYear( aCurDate.GetYear() + nYearAdj );
+ }
+
+ // adjust day value,
+ // e.g. 2000, 2, 0 = 2000, 1, 31 or the last day of the previous month
+ // 2000, 1, 32 = 2000, 2, 1 or the first day of the following month
+ if( ( nDay < 1 ) || ( nDay > aCurDate.GetDaysInMonth() ) )
+ aCurDate += nDay - 1;
+ else
+ aCurDate.SetDay( nDay );
+ }
+
+ long nDiffDays = GetDayDiff( aCurDate );
+ rdRet = (double)nDiffDays;
+ return TRUE;
+}
+
+// Function to convert date to ISO 8601 date format
+RTLFUNC(CDateToIso)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ double aDate = rPar.Get(1)->GetDate();
+
+ char Buffer[9];
+ snprintf( Buffer, sizeof( Buffer ), "%04d%02d%02d",
+ implGetDateYear( aDate ),
+ implGetDateMonth( aDate ),
+ implGetDateDay( aDate ) );
+ String aRetStr = String::CreateFromAscii( Buffer );
+ rPar.Get(0)->PutString( aRetStr );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+// Function to convert date from ISO 8601 date format
+RTLFUNC(CDateFromIso)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ String aStr = rPar.Get(1)->GetString();
+ INT16 iMonthStart = aStr.Len() - 4;
+ String aYearStr = aStr.Copy( 0, iMonthStart );
+ String aMonthStr = aStr.Copy( iMonthStart, 2 );
+ String aDayStr = aStr.Copy( iMonthStart+2, 2 );
+
+ double dDate;
+ if( implDateSerial( (INT16)aYearStr.ToInt32(),
+ (INT16)aMonthStr.ToInt32(), (INT16)aDayStr.ToInt32(), dDate ) )
+ {
+ rPar.Get(0)->PutDate( dDate );
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(DateSerial)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nYear = rPar.Get(1)->GetInteger();
+ INT16 nMonth = rPar.Get(2)->GetInteger();
+ INT16 nDay = rPar.Get(3)->GetInteger();
+
+ double dDate;
+ if( implDateSerial( nYear, nMonth, nDay, dDate ) )
+ rPar.Get(0)->PutDate( dDate );
+}
+
+RTLFUNC(TimeSerial)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nHour = rPar.Get(1)->GetInteger();
+ if ( nHour == 24 )
+ nHour = 0; // Wegen UNO DateTimes, die bis 24 Uhr gehen
+ INT16 nMinute = rPar.Get(2)->GetInteger();
+ INT16 nSecond = rPar.Get(3)->GetInteger();
+ if ((nHour < 0 || nHour > 23) ||
+ (nMinute < 0 || nMinute > 59 ) ||
+ (nSecond < 0 || nSecond > 59 ))
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ INT32 nSeconds = nHour;
+ nSeconds *= 3600;
+ nSeconds += nMinute * 60;
+ nSeconds += nSecond;
+ double nDays = ((double)nSeconds) / (double)(86400.0);
+ rPar.Get(0)->PutDate( nDays ); // JSM
+}
+
+RTLFUNC(DateValue)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
+ SvNumberFormatter* pFormatter = NULL;
+ if( pINST )
+ pFormatter = pINST->GetNumberFormatter();
+ else
+ {
+ sal_uInt32 n; // Dummy
+ SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
+ }
+
+ sal_uInt32 nIndex;
+ double fResult;
+ String aStr( rPar.Get(1)->GetString() );
+ BOOL bSuccess = pFormatter->IsNumberFormat( aStr, nIndex, fResult );
+ short nType = pFormatter->GetType( nIndex );
+
+ // DateValue("February 12, 1969") raises error if the system locale is not en_US
+ // by using SbiInstance::GetNumberFormatter.
+ // It seems that both locale number formatter and English number formatter
+ // are supported in Visual Basic.
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ if( !bSuccess && ( eLangType != LANGUAGE_ENGLISH_US ) )
+ {
+ // Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value;
+ com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
+ xFactory = comphelper::getProcessServiceFactory();
+ SvNumberFormatter aFormatter( xFactory, LANGUAGE_ENGLISH_US );
+ bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, fResult );
+ nType = aFormatter.GetType( nIndex );
+ }
+
+ if(bSuccess && (nType==NUMBERFORMAT_DATE || nType==NUMBERFORMAT_DATETIME))
+ {
+ if ( nType == NUMBERFORMAT_DATETIME )
+ {
+ // Zeit abschneiden
+ if ( fResult > 0.0 )
+ fResult = floor( fResult );
+ else
+ fResult = ceil( fResult );
+ }
+ // fResult += 2.0; // Anpassung StarCalcFormatter
+ rPar.Get(0)->PutDate( fResult ); // JSM
+ }
+ else
+ StarBASIC::Error( SbERR_CONVERSION );
+
+ // #39629 pFormatter kann selbst angefordert sein
+ if( !pINST )
+ delete pFormatter;
+ }
+}
+
+RTLFUNC(TimeValue)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
+ SvNumberFormatter* pFormatter = NULL;
+ if( pINST )
+ pFormatter = pINST->GetNumberFormatter();
+ else
+ {
+ sal_uInt32 n; // Dummy
+ SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
+ }
+
+ sal_uInt32 nIndex;
+ double fResult;
+ BOOL bSuccess = pFormatter->IsNumberFormat( rPar.Get(1)->GetString(),
+ nIndex, fResult );
+ short nType = pFormatter->GetType(nIndex);
+ if(bSuccess && (nType==NUMBERFORMAT_TIME||nType==NUMBERFORMAT_DATETIME))
+ {
+ if ( nType == NUMBERFORMAT_DATETIME )
+ // Tage abschneiden
+ fResult = fmod( fResult, 1 );
+ rPar.Get(0)->PutDate( fResult ); // JSM
+ }
+ else
+ StarBASIC::Error( SbERR_CONVERSION );
+
+ // #39629 pFormatter kann selbst angefordert sein
+ if( !pINST )
+ delete pFormatter;
+ }
+}
+
+RTLFUNC(Day)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariableRef pArg = rPar.Get( 1 );
+ double aDate = pArg->GetDate();
+
+ INT16 nDay = implGetDateDay( aDate );
+ rPar.Get(0)->PutInteger( nDay );
+ }
+}
+
+RTLFUNC(Year)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ INT16 nYear = implGetDateYear( rPar.Get(1)->GetDate() );
+ rPar.Get(0)->PutInteger( nYear );
+ }
+}
+
+INT16 implGetHour( double dDate )
+{
+ if( dDate < 0.0 )
+ dDate *= -1.0;
+ double nFrac = dDate - floor( dDate );
+ nFrac *= 86400.0;
+ INT32 nSeconds = (INT32)(nFrac + 0.5);
+ INT16 nHour = (INT16)(nSeconds / 3600);
+ return nHour;
+}
+
+RTLFUNC(Hour)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double nArg = rPar.Get(1)->GetDate();
+ INT16 nHour = implGetHour( nArg );
+ rPar.Get(0)->PutInteger( nHour );
+ }
+}
+
+INT16 implGetMinute( double dDate )
+{
+ if( dDate < 0.0 )
+ dDate *= -1.0;
+ double nFrac = dDate - floor( dDate );
+ nFrac *= 86400.0;
+ INT32 nSeconds = (INT32)(nFrac + 0.5);
+ INT16 nTemp = (INT16)(nSeconds % 3600);
+ INT16 nMin = nTemp / 60;
+ return nMin;
+}
+
+RTLFUNC(Minute)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double nArg = rPar.Get(1)->GetDate();
+ INT16 nMin = implGetMinute( nArg );
+ rPar.Get(0)->PutInteger( nMin );
+ }
+}
+
+RTLFUNC(Month)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ INT16 nMonth = implGetDateMonth( rPar.Get(1)->GetDate() );
+ rPar.Get(0)->PutInteger( nMonth );
+ }
+}
+
+INT16 implGetSecond( double dDate )
+{
+ if( dDate < 0.0 )
+ dDate *= -1.0;
+ double nFrac = dDate - floor( dDate );
+ nFrac *= 86400.0;
+ INT32 nSeconds = (INT32)(nFrac + 0.5);
+ INT16 nTemp = (INT16)(nSeconds / 3600);
+ nSeconds -= nTemp * 3600;
+ nTemp = (INT16)(nSeconds / 60);
+ nSeconds -= nTemp * 60;
+
+ INT16 nRet = (INT16)nSeconds;
+ return nRet;
+}
+
+RTLFUNC(Second)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double nArg = rPar.Get(1)->GetDate();
+ INT16 nSecond = implGetSecond( nArg );
+ rPar.Get(0)->PutInteger( nSecond );
+ }
+}
+
+double Now_Impl()
+{
+ Date aDate;
+ Time aTime;
+ double aSerial = (double)GetDayDiff( aDate );
+ long nSeconds = aTime.GetHour();
+ nSeconds *= 3600;
+ nSeconds += aTime.GetMin() * 60;
+ nSeconds += aTime.GetSec();
+ double nDays = ((double)nSeconds) / (double)(24.0*3600.0);
+ aSerial += nDays;
+ return aSerial;
+}
+
+// Date Now(void)
+
+RTLFUNC(Now)
+{
+ (void)pBasic;
+ (void)bWrite;
+ rPar.Get(0)->PutDate( Now_Impl() );
+}
+
+// Date Time(void)
+
+RTLFUNC(Time)
+{
+ (void)pBasic;
+
+ if ( !bWrite )
+ {
+ Time aTime;
+ SbxVariable* pMeth = rPar.Get( 0 );
+ String aRes;
+ if( pMeth->IsFixed() )
+ {
+ // Time$: hh:mm:ss
+ char buf[ 20 ];
+ snprintf( buf, sizeof(buf), "%02d:%02d:%02d",
+ aTime.GetHour(), aTime.GetMin(), aTime.GetSec() );
+ aRes = String::CreateFromAscii( buf );
+ }
+ else
+ {
+ // Time: system dependent
+ long nSeconds=aTime.GetHour();
+ nSeconds *= 3600;
+ nSeconds += aTime.GetMin() * 60;
+ nSeconds += aTime.GetSec();
+ double nDays = (double)nSeconds * ( 1.0 / (24.0*3600.0) );
+ Color* pCol;
+
+ // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
+ SvNumberFormatter* pFormatter = NULL;
+ sal_uInt32 nIndex;
+ if( pINST )
+ {
+ pFormatter = pINST->GetNumberFormatter();
+ nIndex = pINST->GetStdTimeIdx();
+ }
+ else
+ {
+ sal_uInt32 n; // Dummy
+ SbiInstance::PrepareNumberFormatter( pFormatter, n, nIndex, n );
+ }
+
+ pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
+
+ // #39629 pFormatter kann selbst angefordert sein
+ if( !pINST )
+ delete pFormatter;
+ }
+ pMeth->PutString( aRes );
+ }
+ else
+ {
+ StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
+ }
+}
+
+RTLFUNC(Timer)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ Time aTime;
+ long nSeconds = aTime.GetHour();
+ nSeconds *= 3600;
+ nSeconds += aTime.GetMin() * 60;
+ nSeconds += aTime.GetSec();
+ rPar.Get(0)->PutDate( (double)nSeconds );
+}
+
+
+RTLFUNC(Date)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( !bWrite )
+ {
+ Date aToday;
+ double nDays = (double)GetDayDiff( aToday );
+ SbxVariable* pMeth = rPar.Get( 0 );
+ if( pMeth->IsString() )
+ {
+ String aRes;
+ Color* pCol;
+
+ // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
+ SvNumberFormatter* pFormatter = NULL;
+ sal_uInt32 nIndex;
+ if( pINST )
+ {
+ pFormatter = pINST->GetNumberFormatter();
+ nIndex = pINST->GetStdDateIdx();
+ }
+ else
+ {
+ sal_uInt32 n; // Dummy
+ SbiInstance::PrepareNumberFormatter( pFormatter, nIndex, n, n );
+ }
+
+ pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
+ pMeth->PutString( aRes );
+
+ // #39629 pFormatter kann selbst angefordert sein
+ if( !pINST )
+ delete pFormatter;
+ }
+ else
+ pMeth->PutDate( nDays );
+ }
+ else
+ {
+ StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
+ }
+}
+
+RTLFUNC(IsArray)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ rPar.Get(0)->PutBool((rPar.Get(1)->GetType() & SbxARRAY) ? TRUE : FALSE );
+}
+
+RTLFUNC(IsObject)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxVariable* pVar = rPar.Get(1);
+ SbxBase* pObj = (SbxBase*)pVar->GetObject();
+
+ // #100385: GetObject can result in an error, so reset it
+ SbxBase::ResetError();
+
+ SbUnoClass* pUnoClass;
+ BOOL bObject;
+ if( pObj && NULL != ( pUnoClass=PTR_CAST(SbUnoClass,pObj) ) )
+ {
+ bObject = pUnoClass->getUnoClass().is();
+ }
+ else
+ {
+ bObject = pVar->IsObject();
+ }
+ rPar.Get( 0 )->PutBool( bObject );
+ }
+}
+
+RTLFUNC(IsDate)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // #46134 Nur String wird konvertiert, andere Typen ergeben FALSE
+ SbxVariableRef xArg = rPar.Get( 1 );
+ SbxDataType eType = xArg->GetType();
+ BOOL bDate = FALSE;
+
+ if( eType == SbxDATE )
+ {
+ bDate = TRUE;
+ }
+ else if( eType == SbxSTRING )
+ {
+ // Error loeschen
+ SbxError nPrevError = SbxBase::GetError();
+ SbxBase::ResetError();
+
+ // Konvertierung des Parameters nach SbxDATE erzwingen
+ xArg->SbxValue::GetDate();
+
+ // Bei Fehler ist es kein Date
+ bDate = !SbxBase::IsError();
+
+ // Error-Situation wiederherstellen
+ SbxBase::ResetError();
+ SbxBase::SetError( nPrevError );
+ }
+ rPar.Get( 0 )->PutBool( bDate );
+ }
+}
+
+RTLFUNC(IsEmpty)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ rPar.Get( 0 )->PutBool( rPar.Get(1)->IsEmpty() );
+}
+
+RTLFUNC(IsError)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
+}
+
+RTLFUNC(IsNull)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // #51475 Wegen Uno-Objekten auch true liefern,
+ // wenn der pObj-Wert NULL ist
+ SbxVariableRef pArg = rPar.Get( 1 );
+ BOOL bNull = rPar.Get(1)->IsNull();
+ if( !bNull && pArg->GetType() == SbxOBJECT )
+ {
+ SbxBase* pObj = pArg->GetObject();
+ if( !pObj )
+ bNull = TRUE;
+ }
+ rPar.Get( 0 )->PutBool( bNull );
+ }
+}
+
+RTLFUNC(IsNumeric)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ rPar.Get( 0 )->PutBool( rPar.Get( 1 )->IsNumericRTL() );
+}
+
+// Das machen wir auf die billige Tour
+
+RTLFUNC(IsMissing)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ // #57915 Missing wird durch Error angezeigt
+ rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
+}
+
+// Dir( [Maske] [,Attrs] )
+// ToDo: Library-globaler Datenbereich fuer Dir-Objekt und Flags
+
+
+String getDirectoryPath( String aPathStr )
+{
+ String aRetStr;
+
+ DirectoryItem aItem;
+ FileBase::RC nRet = DirectoryItem::get( aPathStr, aItem );
+ if( nRet == FileBase::E_None )
+ {
+ FileStatus aFileStatus( FileStatusMask_Type );
+ nRet = aItem.getFileStatus( aFileStatus );
+ if( nRet == FileBase::E_None )
+ {
+ FileStatus::Type aType = aFileStatus.getFileType();
+ if( isFolder( aType ) )
+ {
+ aRetStr = aPathStr;
+ }
+ else if( aType == FileStatus::Link )
+ {
+ FileStatus aFileStatus2( FileStatusMask_LinkTargetURL );
+ nRet = aItem.getFileStatus( aFileStatus2 );
+ if( nRet == FileBase::E_None )
+ aRetStr = getDirectoryPath( aFileStatus2.getLinkTargetURL() );
+ }
+ }
+ }
+ return aRetStr;
+}
+
+// Function looks for wildcards, removes them and always returns the pure path
+String implSetupWildcard( const String& rFileParam, SbiRTLData* pRTLData )
+{
+ static String aAsterisk = String::CreateFromAscii( "*" );
+ static sal_Char cDelim1 = (sal_Char)'/';
+ static sal_Char cDelim2 = (sal_Char)'\\';
+ static sal_Char cWild1 = '*';
+ static sal_Char cWild2 = '?';
+
+ delete pRTLData->pWildCard;
+ pRTLData->pWildCard = NULL;
+ pRTLData->sFullNameToBeChecked = String();
+
+ String aFileParam = rFileParam;
+ xub_StrLen nLastWild = aFileParam.SearchBackward( cWild1 );
+ if( nLastWild == STRING_NOTFOUND )
+ nLastWild = aFileParam.SearchBackward( cWild2 );
+ sal_Bool bHasWildcards = ( nLastWild != STRING_NOTFOUND );
+
+
+ xub_StrLen nLastDelim = aFileParam.SearchBackward( cDelim1 );
+ if( nLastDelim == STRING_NOTFOUND )
+ nLastDelim = aFileParam.SearchBackward( cDelim2 );
+
+ if( bHasWildcards )
+ {
+ // Wildcards in path?
+ if( nLastDelim != STRING_NOTFOUND && nLastDelim > nLastWild )
+ return aFileParam;
+ }
+ else
+ {
+ String aPathStr = getFullPath( aFileParam );
+ if( nLastDelim != aFileParam.Len() - 1 )
+ pRTLData->sFullNameToBeChecked = aPathStr;
+ return aPathStr;
+ }
+
+ String aPureFileName;
+ if( nLastDelim == STRING_NOTFOUND )
+ {
+ aPureFileName = aFileParam;
+ aFileParam = String();
+ }
+ else
+ {
+ aPureFileName = aFileParam.Copy( nLastDelim + 1 );
+ aFileParam = aFileParam.Copy( 0, nLastDelim );
+ }
+
+ // Try again to get a valid URL/UNC-path with only the path
+ String aPathStr = getFullPath( aFileParam );
+ xub_StrLen nPureLen = aPureFileName.Len();
+
+ // Is there a pure file name left? Otherwise the path is
+ // invalid anyway because it was not accepted by OSL before
+ if( nPureLen && aPureFileName != aAsterisk )
+ {
+ pRTLData->pWildCard = new WildCard( aPureFileName );
+ }
+ return aPathStr;
+}
+
+inline sal_Bool implCheckWildcard( const String& rName, SbiRTLData* pRTLData )
+{
+ sal_Bool bMatch = sal_True;
+
+ if( pRTLData->pWildCard )
+ bMatch = pRTLData->pWildCard->Matches( rName );
+ return bMatch;
+}
+
+
+bool isRootDir( String aDirURLStr )
+{
+ INetURLObject aDirURLObj( aDirURLStr );
+ BOOL bRoot = FALSE;
+
+ // Check if it's a root directory
+ sal_Int32 nCount = aDirURLObj.getSegmentCount();
+
+ // No segment means Unix root directory "file:///"
+ if( nCount == 0 )
+ {
+ bRoot = TRUE;
+ }
+ // Exactly one segment needs further checking, because it
+ // can be Unix "file:///foo/" -> no root
+ // or Windows "file:///c:/" -> root
+ else if( nCount == 1 )
+ {
+ ::rtl::OUString aSeg1 = aDirURLObj.getName( 0, TRUE,
+ INetURLObject::DECODE_WITH_CHARSET );
+ if( aSeg1.getStr()[1] == (sal_Unicode)':' )
+ {
+ bRoot = TRUE;
+ }
+ }
+ // More than one segments can never be root
+ // so bRoot remains FALSE
+
+ return bRoot;
+}
+
+RTLFUNC(Dir)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ String aPath;
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount > 3 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbiRTLData* pRTLData = pINST->GetRTLData();
+
+ // #34645: Kann auch von der URL-Zeile ueber 'macro: Dir' aufgerufen werden
+ // dann existiert kein pRTLData und die Methode muss verlassen werden
+ if( !pRTLData )
+ return;
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ if ( nParCount >= 2 )
+ {
+ String aFileParam = rPar.Get(1)->GetString();
+
+ String aFileURLStr = implSetupWildcard( aFileParam, pRTLData );
+ if( pRTLData->sFullNameToBeChecked.Len() > 0 )
+ {
+ sal_Bool bExists = sal_False;
+ try { bExists = xSFI->exists( aFileURLStr ); }
+ catch( Exception & ) {}
+
+ String aNameOnlyStr;
+ if( bExists )
+ {
+ INetURLObject aFileURL( aFileURLStr );
+ aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT,
+ true, INetURLObject::DECODE_WITH_CHARSET );
+ }
+ rPar.Get(0)->PutString( aNameOnlyStr );
+ return;
+ }
+
+ try
+ {
+ String aDirURLStr;
+ sal_Bool bFolder = xSFI->isFolder( aFileURLStr );
+
+ if( bFolder )
+ {
+ aDirURLStr = aFileURLStr;
+ }
+ else
+ {
+ String aEmptyStr;
+ rPar.Get(0)->PutString( aEmptyStr );
+ }
+
+ USHORT nFlags = 0;
+ if ( nParCount > 2 )
+ pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
+ else
+ pRTLData->nDirFlags = 0;
+
+ // Read directory
+ sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0);
+ pRTLData->aDirSeq = xSFI->getFolderContents( aDirURLStr, bIncludeFolders );
+ pRTLData->nCurDirPos = 0;
+
+ // #78651 Add "." and ".." directories for VB compatibility
+ if( bIncludeFolders )
+ {
+ BOOL bRoot = isRootDir( aDirURLStr );
+
+ // If it's no root directory we flag the need for
+ // the "." and ".." directories by the value -2
+ // for the actual position. Later for -2 will be
+ // returned "." and for -1 ".."
+ if( !bRoot )
+ {
+ pRTLData->nCurDirPos = -2;
+ }
+ }
+ }
+ catch( Exception & )
+ {
+ //StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+
+
+ if( pRTLData->aDirSeq.getLength() > 0 )
+ {
+ sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
+
+ SbiInstance* pInst = pINST;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ for( ;; )
+ {
+ if( pRTLData->nCurDirPos < 0 )
+ {
+ if( pRTLData->nCurDirPos == -2 )
+ {
+ aPath = ::rtl::OUString::createFromAscii( "." );
+ }
+ else if( pRTLData->nCurDirPos == -1 )
+ {
+ aPath = ::rtl::OUString::createFromAscii( ".." );
+ }
+ pRTLData->nCurDirPos++;
+ }
+ else if( pRTLData->nCurDirPos >= pRTLData->aDirSeq.getLength() )
+ {
+ pRTLData->aDirSeq.realloc( 0 );
+ aPath.Erase();
+ break;
+ }
+ else
+ {
+ ::rtl::OUString aFile = pRTLData->aDirSeq.getConstArray()[pRTLData->nCurDirPos++];
+
+ if( bCompatibility )
+ {
+ if( !bFolderFlag )
+ {
+ sal_Bool bFolder = xSFI->isFolder( aFile );
+ if( bFolder )
+ continue;
+ }
+ }
+ else
+ {
+ // Only directories
+ if( bFolderFlag )
+ {
+ sal_Bool bFolder = xSFI->isFolder( aFile );
+ if( !bFolder )
+ continue;
+ }
+ }
+
+ INetURLObject aURL( aFile );
+ aPath = aURL.getName( INetURLObject::LAST_SEGMENT, TRUE,
+ INetURLObject::DECODE_WITH_CHARSET );
+ }
+
+ sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
+ if( !bMatch )
+ continue;
+
+ break;
+ }
+ }
+ rPar.Get(0)->PutString( aPath );
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ if ( nParCount >= 2 )
+ {
+ delete pRTLData->pDir;
+ pRTLData->pDir = 0; // wg. Sonderbehandlung Sb_ATTR_VOLUME
+ DirEntry aEntry( rPar.Get(1)->GetString() );
+ FileStat aStat( aEntry );
+ if(!aStat.GetError() && (aStat.GetKind() & FSYS_KIND_FILE))
+ {
+ // ah ja, ist nur ein dateiname
+ // Pfad abschneiden (wg. VB4)
+ rPar.Get(0)->PutString( aEntry.GetName() );
+ return;
+ }
+ USHORT nFlags = 0;
+ if ( nParCount > 2 )
+ pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
+ else
+ pRTLData->nDirFlags = 0;
+ // Nur diese Bitmaske ist unter Windows erlaubt
+ #ifdef WIN
+ if( nFlags & ~0x1E )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT ), pRTLData->nDirFlags = 0;
+ #endif
+ // Sb_ATTR_VOLUME wird getrennt gehandelt
+ if( pRTLData->nDirFlags & Sb_ATTR_VOLUME )
+ aPath = aEntry.GetVolume();
+ else
+ {
+ // Die richtige Auswahl treffen
+ USHORT nMode = FSYS_KIND_FILE;
+ if( nFlags & Sb_ATTR_DIRECTORY )
+ nMode |= FSYS_KIND_DIR;
+ if( nFlags == Sb_ATTR_DIRECTORY )
+ nMode = FSYS_KIND_DIR;
+ pRTLData->pDir = new Dir( aEntry, (DirEntryKind) nMode );
+ pRTLData->nCurDirPos = 0;
+ }
+ }
+
+ if( pRTLData->pDir )
+ {
+ for( ;; )
+ {
+ if( pRTLData->nCurDirPos >= pRTLData->pDir->Count() )
+ {
+ delete pRTLData->pDir;
+ pRTLData->pDir = 0;
+ aPath.Erase();
+ break;
+ }
+ DirEntry aNextEntry=(*(pRTLData->pDir))[pRTLData->nCurDirPos++];
+ aPath = aNextEntry.GetName(); //Full();
+ #ifdef WIN
+ aNextEntry.ToAbs();
+ String sFull(aNextEntry.GetFull());
+ unsigned nFlags;
+
+ if (_dos_getfileattr( sFull.GetStr(), &nFlags ))
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ else
+ {
+ INT16 nCurFlags = pRTLData->nDirFlags;
+ if( (nCurFlags == Sb_ATTR_NORMAL)
+ && !(nFlags & ( _A_HIDDEN | _A_SYSTEM | _A_VOLID | _A_SUBDIR ) ) )
+ break;
+ else if( (nCurFlags & Sb_ATTR_HIDDEN) && (nFlags & _A_HIDDEN) )
+ break;
+ else if( (nCurFlags & Sb_ATTR_SYSTEM) && (nFlags & _A_SYSTEM) )
+ break;
+ else if( (nCurFlags & Sb_ATTR_VOLUME) && (nFlags & _A_VOLID) )
+ break;
+ else if( (nCurFlags & Sb_ATTR_DIRECTORY) && (nFlags & _A_SUBDIR) )
+ break;
+ }
+ #else
+ break;
+ #endif
+ }
+ }
+ rPar.Get(0)->PutString( aPath );
+#else
+ // TODO: OSL
+ if ( nParCount >= 2 )
+ {
+ String aFileParam = rPar.Get(1)->GetString();
+
+ String aDirURL = implSetupWildcard( aFileParam, pRTLData );
+
+ USHORT nFlags = 0;
+ if ( nParCount > 2 )
+ pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
+ else
+ pRTLData->nDirFlags = 0;
+
+ // Read directory
+ sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0);
+ pRTLData->pDir = new Directory( aDirURL );
+ FileBase::RC nRet = pRTLData->pDir->open();
+ if( nRet != FileBase::E_None )
+ {
+ delete pRTLData->pDir;
+ pRTLData->pDir = NULL;
+ rPar.Get(0)->PutString( String() );
+ return;
+ }
+
+ // #86950 Add "." and ".." directories for VB compatibility
+ pRTLData->nCurDirPos = 0;
+ if( bIncludeFolders )
+ {
+ BOOL bRoot = isRootDir( aDirURL );
+
+ // If it's no root directory we flag the need for
+ // the "." and ".." directories by the value -2
+ // for the actual position. Later for -2 will be
+ // returned "." and for -1 ".."
+ if( !bRoot )
+ {
+ pRTLData->nCurDirPos = -2;
+ }
+ }
+
+ }
+
+ if( pRTLData->pDir )
+ {
+ sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
+ for( ;; )
+ {
+ if( pRTLData->nCurDirPos < 0 )
+ {
+ if( pRTLData->nCurDirPos == -2 )
+ {
+ aPath = ::rtl::OUString::createFromAscii( "." );
+ }
+ else if( pRTLData->nCurDirPos == -1 )
+ {
+ aPath = ::rtl::OUString::createFromAscii( ".." );
+ }
+ pRTLData->nCurDirPos++;
+ }
+ else
+ {
+ DirectoryItem aItem;
+ FileBase::RC nRet = pRTLData->pDir->getNextItem( aItem );
+ if( nRet != FileBase::E_None )
+ {
+ delete pRTLData->pDir;
+ pRTLData->pDir = NULL;
+ aPath.Erase();
+ break;
+ }
+
+ // Handle flags
+ FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileName );
+ nRet = aItem.getFileStatus( aFileStatus );
+
+ // Only directories?
+ if( bFolderFlag )
+ {
+ FileStatus::Type aType = aFileStatus.getFileType();
+ sal_Bool bFolder = isFolder( aType );
+ if( !bFolder )
+ continue;
+ }
+
+ aPath = aFileStatus.getFileName();
+ }
+
+ sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
+ if( !bMatch )
+ continue;
+
+ break;
+ }
+ }
+ rPar.Get(0)->PutString( aPath );
+#endif
+ }
+ }
+}
+
+
+RTLFUNC(GetAttr)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ INT16 nFlags = 0;
+
+ // In Windows, We want to use Windows API to get the file attributes
+ // for VBA interoperability.
+ #if defined( WNT )
+ if( SbiRuntime::isVBAEnabled() )
+ {
+ DirEntry aEntry( rPar.Get(1)->GetString() );
+ aEntry.ToAbs();
+
+ // #57064 Bei virtuellen URLs den Real-Path extrahieren
+ ByteString aByteStrFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() );
+ DWORD nRealFlags = GetFileAttributes (aByteStrFullPath.GetBuffer());
+ if (nRealFlags != 0xffffffff)
+ {
+ if (nRealFlags == FILE_ATTRIBUTE_NORMAL)
+ nRealFlags = 0;
+ nFlags = (INT16) (nRealFlags);
+ }
+ else
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+
+ rPar.Get(0)->PutInteger( nFlags );
+
+ return;
+ }
+ #endif
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ String aPath = getFullPath( rPar.Get(1)->GetString() );
+ sal_Bool bExists = sal_False;
+ try { bExists = xSFI->exists( aPath ); }
+ catch( Exception & ) {}
+ if( !bExists )
+ {
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ return;
+ }
+
+ sal_Bool bReadOnly = xSFI->isReadOnly( aPath );
+ sal_Bool bHidden = xSFI->isHidden( aPath );
+ sal_Bool bDirectory = xSFI->isFolder( aPath );
+ if( bReadOnly )
+ nFlags |= 0x0001; // ATTR_READONLY
+ if( bHidden )
+ nFlags |= 0x0002; // ATTR_HIDDEN
+ if( bDirectory )
+ nFlags |= 0x0010; // ATTR_DIRECTORY
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+ DirectoryItem aItem;
+ FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetString() ), aItem );
+ FileStatus aFileStatus( FileStatusMask_Attributes | FileStatusMask_Type );
+ nRet = aItem.getFileStatus( aFileStatus );
+ sal_uInt64 nAttributes = aFileStatus.getAttributes();
+ sal_Bool bReadOnly = (nAttributes & Attribute_ReadOnly) != 0;
+
+ FileStatus::Type aType = aFileStatus.getFileType();
+ sal_Bool bDirectory = isFolder( aType );
+ if( bReadOnly )
+ nFlags |= 0x0001; // ATTR_READONLY
+ if( bDirectory )
+ nFlags |= 0x0010; // ATTR_DIRECTORY
+ }
+ rPar.Get(0)->PutInteger( nFlags );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+
+RTLFUNC(FileDateTime)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // <-- UCB
+ String aPath = rPar.Get(1)->GetString();
+ Time aTime;
+ Date aDate;
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ com::sun::star::util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath );
+ aTime = Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds );
+ aDate = Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ DirEntry aEntry( aPath );
+ FileStat aStat( aEntry );
+ aTime = Time( aStat.TimeModified() );
+ aDate = Date( aStat.DateModified() );
+#else
+ DirectoryItem aItem;
+ FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aPath ), aItem );
+ FileStatus aFileStatus( FileStatusMask_ModifyTime );
+ nRet = aItem.getFileStatus( aFileStatus );
+ TimeValue aTimeVal = aFileStatus.getModifyTime();
+ oslDateTime aDT;
+ osl_getDateTimeFromTimeValue( &aTimeVal, &aDT );
+
+ aTime = Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 10000000*aDT.NanoSeconds );
+ aDate = Date( aDT.Day, aDT.Month, aDT.Year );
+#endif
+ }
+
+ double fSerial = (double)GetDayDiff( aDate );
+ long nSeconds = aTime.GetHour();
+ nSeconds *= 3600;
+ nSeconds += aTime.GetMin() * 60;
+ nSeconds += aTime.GetSec();
+ double nDays = ((double)nSeconds) / (double)(24.0*3600.0);
+ fSerial += nDays;
+
+ Color* pCol;
+
+ // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
+ SvNumberFormatter* pFormatter = NULL;
+ sal_uInt32 nIndex;
+ if( pINST )
+ {
+ pFormatter = pINST->GetNumberFormatter();
+ nIndex = pINST->GetStdDateTimeIdx();
+ }
+ else
+ {
+ sal_uInt32 n; // Dummy
+ SbiInstance::PrepareNumberFormatter( pFormatter, n, n, nIndex );
+ }
+
+ String aRes;
+ pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol );
+ rPar.Get(0)->PutString( aRes );
+
+ // #39629 pFormatter kann selbst angefordert sein
+ if( !pINST )
+ delete pFormatter;
+ }
+}
+
+
+RTLFUNC(EOF)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // AB 08/16/2000: No changes for UCB
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ // nChannel--; // macht MD beim Oeffnen auch nicht
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIO->GetStream( nChannel );
+ if ( !pSbStrm )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+ BOOL bIsEof;
+ SvStream* pSvStrm = pSbStrm->GetStrm();
+ if ( pSbStrm->IsText() )
+ {
+ char cBla;
+ (*pSvStrm) >> cBla; // koennen wir noch ein Zeichen lesen
+ bIsEof = pSvStrm->IsEof();
+ if ( !bIsEof )
+ pSvStrm->SeekRel( -1 );
+ }
+ else
+ bIsEof = pSvStrm->IsEof(); // fuer binaerdateien!
+ rPar.Get(0)->PutBool( bIsEof );
+ }
+}
+
+RTLFUNC(FileAttr)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // AB 08/16/2000: No changes for UCB
+
+ // #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von
+ // der Anpassung an virtuelle URLs nich betroffen, da sie nur auf bereits
+ // geoeffneten Dateien arbeitet und der Name hier keine Rolle spielt.
+
+ if ( rPar.Count() != 3 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+// nChannel--;
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIO->GetStream( nChannel );
+ if ( !pSbStrm )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+ INT16 nRet;
+ if ( rPar.Get(2)->GetInteger() == 1 )
+ nRet = (INT16)(pSbStrm->GetMode());
+ else
+ nRet = 0; // System file handle not supported
+
+ rPar.Get(0)->PutInteger( nRet );
+ }
+}
+RTLFUNC(Loc)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // AB 08/16/2000: No changes for UCB
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIO->GetStream( nChannel );
+ if ( !pSbStrm )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+ SvStream* pSvStrm = pSbStrm->GetStrm();
+ ULONG nPos;
+ if( pSbStrm->IsRandom())
+ {
+ short nBlockLen = pSbStrm->GetBlockLen();
+ nPos = nBlockLen ? (pSvStrm->Tell() / nBlockLen) : 0;
+ nPos++; // Blockpositionen beginnen bei 1
+ }
+ else if ( pSbStrm->IsText() )
+ nPos = pSbStrm->GetLine();
+ else if( pSbStrm->IsBinary() )
+ nPos = pSvStrm->Tell();
+ else if ( pSbStrm->IsSeq() )
+ nPos = ( pSvStrm->Tell()+1 ) / 128;
+ else
+ nPos = pSvStrm->Tell();
+ rPar.Get(0)->PutLong( (INT32)nPos );
+ }
+}
+
+RTLFUNC(Lof)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // AB 08/16/2000: No changes for UCB
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIO->GetStream( nChannel );
+ if ( !pSbStrm )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+ SvStream* pSvStrm = pSbStrm->GetStrm();
+ ULONG nOldPos = pSvStrm->Tell();
+ ULONG nLen = pSvStrm->Seek( STREAM_SEEK_TO_END );
+ pSvStrm->Seek( nOldPos );
+ rPar.Get(0)->PutLong( (INT32)nLen );
+ }
+}
+
+
+RTLFUNC(Seek)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // AB 08/16/2000: No changes for UCB
+ int nArgs = (int)rPar.Count();
+ if ( nArgs < 2 || nArgs > 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+// nChannel--;
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIO->GetStream( nChannel );
+ if ( !pSbStrm )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+ SvStream* pStrm = pSbStrm->GetStrm();
+
+ if ( nArgs == 2 ) // Seek-Function
+ {
+ ULONG nPos = pStrm->Tell();
+ if( pSbStrm->IsRandom() )
+ nPos = nPos / pSbStrm->GetBlockLen();
+ nPos++; // Basic zaehlt ab 1
+ rPar.Get(0)->PutLong( (INT32)nPos );
+ }
+ else // Seek-Statement
+ {
+ INT32 nPos = rPar.Get(2)->GetLong();
+ if ( nPos < 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ nPos--; // Basic zaehlt ab 1, SvStreams zaehlen ab 0
+ pSbStrm->SetExpandOnWriteTo( 0 );
+ if ( pSbStrm->IsRandom() )
+ nPos *= pSbStrm->GetBlockLen();
+ pStrm->Seek( (ULONG)nPos );
+ pSbStrm->SetExpandOnWriteTo( nPos );
+ }
+}
+
+RTLFUNC(Format)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nArgCount = (USHORT)rPar.Count();
+ if ( nArgCount < 2 || nArgCount > 3 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aResult;
+ if( nArgCount == 2 )
+ rPar.Get(1)->Format( aResult );
+ else
+ {
+ String aFmt( rPar.Get(2)->GetString() );
+ rPar.Get(1)->Format( aResult, &aFmt );
+ }
+ rPar.Get(0)->PutString( aResult );
+ }
+}
+
+RTLFUNC(Randomize)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() > 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ INT16 nSeed;
+ if( rPar.Count() == 2 )
+ nSeed = (INT16)rPar.Get(1)->GetInteger();
+ else
+ nSeed = (INT16)rand();
+ srand( nSeed );
+}
+
+RTLFUNC(Rnd)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() > 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double nRand = (double)rand();
+ nRand = ( nRand / (double)RAND_MAX );
+ rPar.Get(0)->PutDouble( nRand );
+ }
+}
+
+
+//
+// Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = FALSE ]]])
+//
+// WindowStyles (VBA-kompatibel):
+// 2 == Minimized
+// 3 == Maximized
+// 10 == Full-Screen (Textmodus-Anwendungen OS/2, WIN95, WNT)
+//
+// !!!HACK der WindowStyle wird im Creator an Application::StartApp
+// uebergeben. Format: "xxxx2"
+//
+
+
+RTLFUNC(Shell)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No shell command for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ ULONG nArgCount = rPar.Count();
+ if ( nArgCount < 2 || nArgCount > 5 )
+ {
+ rPar.Get(0)->PutLong(0);
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ }
+ else
+ {
+ USHORT nOptions = NAMESPACE_VOS(OProcess)::TOption_SearchPath|
+ NAMESPACE_VOS(OProcess)::TOption_Detached;
+ String aCmdLine = rPar.Get(1)->GetString();
+ // Zusaetzliche Parameter anhaengen, es muss eh alles geparsed werden
+ if( nArgCount >= 4 )
+ {
+ aCmdLine.AppendAscii( " " );
+ aCmdLine += rPar.Get(3)->GetString();
+ }
+ else if( !aCmdLine.Len() )
+ {
+ // Spezial-Behandlung (leere Liste) vermeiden
+ aCmdLine.AppendAscii( " " );
+ }
+ USHORT nLen = aCmdLine.Len();
+
+ // #55735 Wenn Parameter dabei sind, muessen die abgetrennt werden
+ // #72471 Auch die einzelnen Parameter trennen
+ std::list<String> aTokenList;
+ String aToken;
+ USHORT i = 0;
+ sal_Unicode c;
+ while( i < nLen )
+ {
+ // Spaces weg
+ for ( ;; ++i )
+ {
+ c = aCmdLine.GetBuffer()[ i ];
+ if ( c != ' ' && c != '\t' )
+ break;
+ }
+
+ if( c == '\"' || c == '\'' )
+ {
+ USHORT iFoundPos = aCmdLine.Search( c, i + 1 );
+
+ // Wenn nichts gefunden wurde, Rest kopieren
+ if( iFoundPos == STRING_NOTFOUND )
+ {
+ aToken = aCmdLine.Copy( i, STRING_LEN );
+ i = nLen;
+ }
+ else
+ {
+ aToken = aCmdLine.Copy( i + 1, (iFoundPos - i - 1) );
+ i = iFoundPos + 1;
+ }
+ }
+ else
+ {
+ USHORT iFoundSpacePos = aCmdLine.Search( ' ', i );
+ USHORT iFoundTabPos = aCmdLine.Search( '\t', i );
+ USHORT iFoundPos = Min( iFoundSpacePos, iFoundTabPos );
+
+ // Wenn nichts gefunden wurde, Rest kopieren
+ if( iFoundPos == STRING_NOTFOUND )
+ {
+ aToken = aCmdLine.Copy( i, STRING_LEN );
+ i = nLen;
+ }
+ else
+ {
+ aToken = aCmdLine.Copy( i, (iFoundPos - i) );
+ i = iFoundPos;
+ }
+ }
+
+ // In die Liste uebernehmen
+ aTokenList.push_back( aToken );
+ }
+ // #55735 / #72471 Ende
+
+ INT16 nWinStyle = 0;
+ if( nArgCount >= 3 )
+ {
+ nWinStyle = rPar.Get(2)->GetInteger();
+ switch( nWinStyle )
+ {
+ case 2:
+ nOptions |= NAMESPACE_VOS(OProcess)::TOption_Minimized;
+ break;
+ case 3:
+ nOptions |= NAMESPACE_VOS(OProcess)::TOption_Maximized;
+ break;
+ case 10:
+ nOptions |= NAMESPACE_VOS(OProcess)::TOption_FullScreen;
+ break;
+ }
+
+ BOOL bSync = FALSE;
+ if( nArgCount >= 5 )
+ bSync = rPar.Get(4)->GetBool();
+ if( bSync )
+ nOptions |= NAMESPACE_VOS(OProcess)::TOption_Wait;
+ }
+ NAMESPACE_VOS(OProcess)::TProcessOption eOptions =
+ (NAMESPACE_VOS(OProcess)::TProcessOption)nOptions;
+
+
+ // #72471 Parameter aufbereiten
+ std::list<String>::const_iterator iter = aTokenList.begin();
+ const String& rStr = *iter;
+ ::rtl::OUString aOUStrProg( rStr.GetBuffer(), rStr.Len() );
+ String aOUStrProgUNC = getFullPathUNC( aOUStrProg );
+
+ iter++;
+
+ USHORT nParamCount = sal::static_int_cast< USHORT >(
+ aTokenList.size() - 1 );
+ ::rtl::OUString* pArgumentList = NULL;
+ //const char** pParamList = NULL;
+ if( nParamCount )
+ {
+ pArgumentList = new ::rtl::OUString[ nParamCount ];
+ //pParamList = new const char*[ nParamCount ];
+ USHORT iList = 0;
+ while( iter != aTokenList.end() )
+ {
+ const String& rParamStr = (*iter);
+ pArgumentList[iList++] = ::rtl::OUString( rParamStr.GetBuffer(), rParamStr.Len() );
+ //pParamList[iList++] = (*iter).GetStr();
+ iter++;
+ }
+ }
+
+ //const char* pParams = aParams.Len() ? aParams.GetStr() : 0;
+ NAMESPACE_VOS(OProcess)* pApp;
+ pApp = new NAMESPACE_VOS(OProcess)( aOUStrProgUNC );
+ BOOL bSucc;
+ if( nParamCount == 0 )
+ {
+ bSucc = pApp->execute( eOptions ) == NAMESPACE_VOS(OProcess)::E_None;
+ }
+ else
+ {
+ NAMESPACE_VOS(OArgumentList) aArgList( pArgumentList, nParamCount );
+ bSucc = pApp->execute( eOptions, aArgList ) == NAMESPACE_VOS(OProcess)::E_None;
+ }
+
+ /*
+ if( nParamCount == 0 )
+ pApp = new NAMESPACE_VOS(OProcess)( pProg );
+ else
+ pApp = new NAMESPACE_VOS(OProcess)( pProg, pParamList, nParamCount );
+ BOOL bSucc = pApp->execute( eOptions ) == NAMESPACE_VOS(OProcess)::E_None;
+ */
+
+ delete pApp;
+ delete[] pArgumentList;
+ if( !bSucc )
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ else
+ rPar.Get(0)->PutLong( 0 );
+ }
+}
+
+RTLFUNC(VarType)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxDataType eType = rPar.Get(1)->GetType();
+ rPar.Get(0)->PutInteger( (INT16)eType );
+ }
+}
+
+// Exported function
+String getBasicTypeName( SbxDataType eType )
+{
+ static const char* pTypeNames[] =
+ {
+ "Empty", // SbxEMPTY
+ "Null", // SbxNULL
+ "Integer", // SbxINTEGER
+ "Long", // SbxLONG
+ "Single", // SbxSINGLE
+ "Double", // SbxDOUBLE
+ "Currency", // SbxCURRENCY
+ "Date", // SbxDATE
+ "String", // SbxSTRING
+ "Object", // SbxOBJECT
+ "Error", // SbxERROR
+ "Boolean", // SbxBOOL
+ "Variant", // SbxVARIANT
+ "DataObject", // SbxDATAOBJECT
+ "Unknown Type", //
+ "Unknown Type", //
+ "Char", // SbxCHAR
+ "Byte", // SbxBYTE
+ "UShort", // SbxUSHORT
+ "ULong", // SbxULONG
+ "Long64", // SbxLONG64
+ "ULong64", // SbxULONG64
+ "Int", // SbxINT
+ "UInt", // SbxUINT
+ "Void", // SbxVOID
+ "HResult", // SbxHRESULT
+ "Pointer", // SbxPOINTER
+ "DimArray", // SbxDIMARRAY
+ "CArray", // SbxCARRAY
+ "Userdef", // SbxUSERDEF
+ "Lpstr", // SbxLPSTR
+ "Lpwstr", // SbxLPWSTR
+ "Unknown Type", // SbxCoreSTRING
+ "WString", // SbxWSTRING
+ "WChar", // SbxWCHAR
+ "Int64", // SbxSALINT64
+ "UInt64", // SbxSALUINT64
+ "Decimal", // SbxDECIMAL
+ };
+
+ int nPos = ((int)eType) & 0x0FFF;
+ USHORT nTypeNameCount = sizeof( pTypeNames ) / sizeof( char* );
+ if ( nPos < 0 || nPos >= nTypeNameCount )
+ nPos = nTypeNameCount - 1;
+ String aRetStr = String::CreateFromAscii( pTypeNames[nPos] );
+ return aRetStr;
+}
+
+RTLFUNC(TypeName)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxDataType eType = rPar.Get(1)->GetType();
+ BOOL bIsArray = ( ( eType & SbxARRAY ) != 0 );
+ String aRetStr = getBasicTypeName( eType );
+ if( bIsArray )
+ aRetStr.AppendAscii( "()" );
+ rPar.Get(0)->PutString( aRetStr );
+ }
+}
+
+RTLFUNC(Len)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ const String& rStr = rPar.Get(1)->GetString();
+ rPar.Get(0)->PutLong( (INT32)rStr.Len() );
+ }
+}
+
+RTLFUNC(DDEInitiate)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No DDE for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ int nArgs = (int)rPar.Count();
+ if ( nArgs != 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ const String& rApp = rPar.Get(1)->GetString();
+ const String& rTopic = rPar.Get(2)->GetString();
+
+ SbiDdeControl* pDDE = pINST->GetDdeControl();
+ INT16 nChannel;
+ SbError nDdeErr = pDDE->Initiate( rApp, rTopic, nChannel );
+ if( nDdeErr )
+ StarBASIC::Error( nDdeErr );
+ else
+ rPar.Get(0)->PutInteger( nChannel );
+}
+
+RTLFUNC(DDETerminate)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No DDE for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ rPar.Get(0)->PutEmpty();
+ int nArgs = (int)rPar.Count();
+ if ( nArgs != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ SbiDdeControl* pDDE = pINST->GetDdeControl();
+ SbError nDdeErr = pDDE->Terminate( nChannel );
+ if( nDdeErr )
+ StarBASIC::Error( nDdeErr );
+}
+
+RTLFUNC(DDETerminateAll)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No DDE for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ rPar.Get(0)->PutEmpty();
+ int nArgs = (int)rPar.Count();
+ if ( nArgs != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ SbiDdeControl* pDDE = pINST->GetDdeControl();
+ SbError nDdeErr = pDDE->TerminateAll();
+ if( nDdeErr )
+ StarBASIC::Error( nDdeErr );
+
+}
+
+RTLFUNC(DDERequest)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No DDE for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ int nArgs = (int)rPar.Count();
+ if ( nArgs != 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ const String& rItem = rPar.Get(2)->GetString();
+ SbiDdeControl* pDDE = pINST->GetDdeControl();
+ String aResult;
+ SbError nDdeErr = pDDE->Request( nChannel, rItem, aResult );
+ if( nDdeErr )
+ StarBASIC::Error( nDdeErr );
+ else
+ rPar.Get(0)->PutString( aResult );
+}
+
+RTLFUNC(DDEExecute)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No DDE for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ rPar.Get(0)->PutEmpty();
+ int nArgs = (int)rPar.Count();
+ if ( nArgs != 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ const String& rCommand = rPar.Get(2)->GetString();
+ SbiDdeControl* pDDE = pINST->GetDdeControl();
+ SbError nDdeErr = pDDE->Execute( nChannel, rCommand );
+ if( nDdeErr )
+ StarBASIC::Error( nDdeErr );
+}
+
+RTLFUNC(DDEPoke)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // No DDE for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ rPar.Get(0)->PutEmpty();
+ int nArgs = (int)rPar.Count();
+ if ( nArgs != 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nChannel = rPar.Get(1)->GetInteger();
+ const String& rItem = rPar.Get(2)->GetString();
+ const String& rData = rPar.Get(3)->GetString();
+ SbiDdeControl* pDDE = pINST->GetDdeControl();
+ SbError nDdeErr = pDDE->Poke( nChannel, rItem, rData );
+ if( nDdeErr )
+ StarBASIC::Error( nDdeErr );
+}
+
+
+RTLFUNC(FreeFile)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ short nChannel = 1;
+ while( nChannel < CHANNELS )
+ {
+ SbiStream* pStrm = pIO->GetStream( nChannel );
+ if( !pStrm )
+ {
+ rPar.Get(0)->PutInteger( nChannel );
+ return;
+ }
+ nChannel++;
+ }
+ StarBASIC::Error( SbERR_TOO_MANY_FILES );
+}
+
+RTLFUNC(LBound)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if ( nParCount != 3 && nParCount != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ SbxBase* pParObj = rPar.Get(1)->GetObject();
+ SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
+ if( pArr )
+ {
+ INT32 nLower, nUpper;
+ short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1;
+ if( !pArr->GetDim32( nDim, nLower, nUpper ) )
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ else
+ rPar.Get(0)->PutLong( nLower );
+ }
+ else
+ StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
+}
+
+RTLFUNC(UBound)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if ( nParCount != 3 && nParCount != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ SbxBase* pParObj = rPar.Get(1)->GetObject();
+ SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
+ if( pArr )
+ {
+ INT32 nLower, nUpper;
+ short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1;
+ if( !pArr->GetDim32( nDim, nLower, nUpper ) )
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ else
+ rPar.Get(0)->PutLong( nUpper );
+ }
+ else
+ StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
+}
+
+RTLFUNC(RGB)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ ULONG nRed = rPar.Get(1)->GetInteger() & 0xFF;
+ ULONG nGreen = rPar.Get(2)->GetInteger() & 0xFF;
+ ULONG nBlue = rPar.Get(3)->GetInteger() & 0xFF;
+ ULONG nRGB;
+
+ SbiInstance* pInst = pINST;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ nRGB = (nBlue << 16) | (nGreen << 8) | nRed;
+ }
+ else
+ {
+ nRGB = (nRed << 16) | (nGreen << 8) | nBlue;
+ }
+ rPar.Get(0)->PutLong( nRGB );
+}
+
+RTLFUNC(QBColor)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ static const INT32 pRGB[] =
+ {
+ 0x000000,
+ 0x800000,
+ 0x008000,
+ 0x808000,
+ 0x000080,
+ 0x800080,
+ 0x008080,
+ 0xC0C0C0,
+ 0x808080,
+ 0xFF0000,
+ 0x00FF00,
+ 0xFFFF00,
+ 0x0000FF,
+ 0xFF00FF,
+ 0x00FFFF,
+ 0xFFFFFF,
+ };
+
+ if ( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ INT16 nCol = rPar.Get(1)->GetInteger();
+ if( nCol < 0 || nCol > 15 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT32 nRGB = pRGB[ nCol ];
+ rPar.Get(0)->PutLong( nRGB );
+}
+
+// StrConv(string, conversion, LCID)
+RTLFUNC(StrConv)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ ULONG nArgCount = rPar.Count()-1;
+ if( nArgCount < 2 || nArgCount > 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aOldStr = rPar.Get(1)->GetString();
+ INT32 nConversion = rPar.Get(2)->GetLong();
+
+ USHORT nLanguage = LANGUAGE_SYSTEM;
+ if( nArgCount == 3 )
+ {
+ // LCID not supported now
+ //nLanguage = rPar.Get(3)->GetInteger();
+ }
+
+ USHORT nOldLen = aOldStr.Len();
+ if( nOldLen == 0 )
+ {
+ // null string,return
+ rPar.Get(0)->PutString(aOldStr);
+ return;
+ }
+
+ INT32 nType = 0;
+ if ( (nConversion & 0x03) == 3 ) // vbProperCase
+ {
+ CharClass& rCharClass = GetCharClass();
+ aOldStr = rCharClass.toTitle( aOldStr.ToLowerAscii(), 0, nOldLen );
+ }
+ else if ( (nConversion & 0x01) == 1 ) // vbUpperCase
+ nType |= ::com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE;
+ else if ( (nConversion & 0x02) == 2 ) // vbLowerCase
+ nType |= ::com::sun::star::i18n::TransliterationModules_UPPERCASE_LOWERCASE;
+
+ if ( (nConversion & 0x04) == 4 ) // vbWide
+ nType |= ::com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
+ else if ( (nConversion & 0x08) == 8 ) // vbNarrow
+ nType |= ::com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
+
+ if ( (nConversion & 0x10) == 16) // vbKatakana
+ nType |= ::com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
+ else if ( (nConversion & 0x20) == 32 ) // vbHiragana
+ nType |= ::com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA;
+
+ String aNewStr( aOldStr );
+ if( nType != 0 )
+ {
+ com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ ::utl::TransliterationWrapper aTransliterationWrapper( xSMgr,nType );
+ com::sun::star::uno::Sequence<sal_Int32> aOffsets;
+ aTransliterationWrapper.loadModuleIfNeeded( nLanguage );
+ aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
+ }
+
+ if ( (nConversion & 0x40) == 64 ) // vbUnicode
+ {
+ // convert the string to byte string, preserving unicode (2 bytes per character)
+ USHORT nSize = aNewStr.Len()*2;
+ const sal_Unicode* pSrc = aNewStr.GetBuffer();
+ sal_Char* pChar = new sal_Char[nSize+1];
+ for( USHORT i=0; i < nSize; i++ )
+ {
+ pChar[i] = static_cast< sal_Char >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
+ if( i%2 )
+ pSrc++;
+ }
+ pChar[nSize] = '\0';
+ ::rtl::OString aOStr(pChar);
+
+ // there is no concept about default codepage in unix. so it is incorrectly in unix
+ ::rtl::OUString aOUStr = ::rtl::OStringToOUString(aOStr, osl_getThreadTextEncoding());
+ aNewStr = String(aOUStr);
+ rPar.Get(0)->PutString( aNewStr );
+ return;
+ }
+ else if ( (nConversion & 0x80) == 128 ) // vbFromUnicode
+ {
+ ::rtl::OUString aOUStr(aNewStr);
+ // there is no concept about default codepage in unix. so it is incorrectly in unix
+ ::rtl::OString aOStr = ::rtl::OUStringToOString(aNewStr,osl_getThreadTextEncoding());
+ const sal_Char* pChar = aOStr.getStr();
+ USHORT nArraySize = static_cast< USHORT >( aOStr.getLength() );
+ SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
+ bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
+ if(nArraySize)
+ {
+ if( bIncIndex )
+ pArray->AddDim( 1, nArraySize );
+ else
+ pArray->AddDim( 0, nArraySize-1 );
+ }
+ else
+ {
+ pArray->unoAddDim( 0, -1 );
+ }
+
+ for( USHORT i=0; i< nArraySize; i++)
+ {
+ SbxVariable* pNew = new SbxVariable( SbxBYTE );
+ pNew->PutByte(*pChar);
+ pChar++;
+ pNew->SetFlag( SBX_WRITE );
+ short index = i;
+ if( bIncIndex )
+ ++index;
+ pArray->Put( pNew, &index );
+ }
+
+ SbxVariableRef refVar = rPar.Get(0);
+ USHORT nFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->PutObject( pArray );
+ refVar->SetFlags( nFlags );
+ refVar->SetParameters( NULL );
+ return;
+ }
+
+ rPar.Get(0)->PutString(aNewStr);
+}
+
+
+RTLFUNC(Beep)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ Sound::Beep();
+}
+
+RTLFUNC(Load)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ // Diesen Call einfach an das Object weiterreichen
+ SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
+ if ( pObj )
+ {
+ if( pObj->IsA( TYPE( SbUserFormModule ) ) )
+ {
+ ((SbUserFormModule*)pObj)->Load();
+ }
+ else if( pObj->IsA( TYPE( SbxObject ) ) )
+ {
+ SbxVariable* pVar = ((SbxObject*)pObj)->
+ Find( String( RTL_CONSTASCII_USTRINGPARAM("Load") ), SbxCLASS_METHOD );
+ if( pVar )
+ pVar->GetInteger();
+ }
+ }
+}
+
+RTLFUNC(Unload)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ // Diesen Call einfach an das Object weitereichen
+ SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
+ if ( pObj )
+ {
+ if( pObj->IsA( TYPE( SbUserFormModule ) ) )
+ {
+ SbUserFormModule* pFormModule = ( SbUserFormModule* )pObj;
+ pFormModule->Unload();
+ }
+ else if( pObj->IsA( TYPE( SbxObject ) ) )
+ {
+ SbxVariable* pVar = ((SbxObject*)pObj)->
+ Find( String( RTL_CONSTASCII_USTRINGPARAM("Unload") ), SbxCLASS_METHOD );
+ if( pVar )
+ pVar->GetInteger();
+ }
+ }
+}
+
+RTLFUNC(LoadPicture)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aFileURL = getFullPath( rPar.Get(1)->GetString() );
+ SvStream* pStream = utl::UcbStreamHelper::CreateStream( aFileURL, STREAM_READ );
+ if( pStream != NULL )
+ {
+ Bitmap aBmp;
+ *pStream >> aBmp;
+ Graphic aGraphic( aBmp );
+
+ SbxObjectRef xRef = new SbStdPicture;
+ ((SbStdPicture*)(SbxObject*)xRef)->SetGraphic( aGraphic );
+ rPar.Get(0)->PutObject( xRef );
+ }
+ delete pStream;
+}
+
+RTLFUNC(SavePicture)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if( rPar.Count() != 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
+ if( pObj->IsA( TYPE( SbStdPicture ) ) )
+ {
+ SvFileStream aOStream( rPar.Get(2)->GetString(), STREAM_WRITE | STREAM_TRUNC );
+ Graphic aGraphic = ((SbStdPicture*)pObj)->GetGraphic();
+ aOStream << aGraphic;
+ }
+}
+
+
+//-----------------------------------------------------------------------------------------
+
+RTLFUNC(AboutStarBasic)
+{
+ (void)pBasic;
+ (void)bWrite;
+ (void)rPar;
+}
+
+RTLFUNC(MsgBox)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ static const WinBits nStyleMap[] =
+ {
+ WB_OK, // MB_OK
+ WB_OK_CANCEL, // MB_OKCANCEL
+ WB_ABORT_RETRY_IGNORE, // MB_ABORTRETRYIGNORE
+ WB_YES_NO_CANCEL, // MB_YESNOCANCEL
+ WB_YES_NO, // MB_YESNO
+ WB_RETRY_CANCEL // MB_RETRYCANCEL
+ };
+ static const INT16 nButtonMap[] =
+ {
+ 2, // #define RET_CANCEL FALSE
+ 1, // #define RET_OK TRUE
+ 6, // #define RET_YES 2
+ 7, // #define RET_NO 3
+ 4 // #define RET_RETRY 4
+ };
+
+
+ USHORT nArgCount = (USHORT)rPar.Count();
+ if( nArgCount < 2 || nArgCount > 6 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ WinBits nWinBits;
+ WinBits nType = 0; // MB_OK
+ if( nArgCount >= 3 )
+ nType = (WinBits)rPar.Get(2)->GetInteger();
+ WinBits nStyle = nType;
+ nStyle &= 15; // Bits 4-16 loeschen
+ if( nStyle > 5 )
+ nStyle = 0;
+
+ nWinBits = nStyleMap[ nStyle ];
+
+ WinBits nWinDefBits;
+ nWinDefBits = (WB_DEF_OK | WB_DEF_RETRY | WB_DEF_YES);
+ if( nType & 256 )
+ {
+ if( nStyle == 5 )
+ nWinDefBits = WB_DEF_CANCEL;
+ else if( nStyle == 2 )
+ nWinDefBits = WB_DEF_RETRY;
+ else
+ nWinDefBits = (WB_DEF_CANCEL | WB_DEF_RETRY | WB_DEF_NO);
+ }
+ else if( nType & 512 )
+ {
+ if( nStyle == 2)
+ nWinDefBits = WB_DEF_IGNORE;
+ else
+ nWinDefBits = WB_DEF_CANCEL;
+ }
+ else if( nStyle == 2)
+ nWinDefBits = WB_DEF_CANCEL;
+ nWinBits |= nWinDefBits;
+
+ String aMsg = rPar.Get(1)->GetString();
+ String aTitle;
+ if( nArgCount >= 4 )
+ aTitle = rPar.Get(3)->GetString();
+ else
+ aTitle = GetpApp()->GetAppName();
+
+ nType &= (16+32+64);
+ MessBox* pBox = 0;
+ Window* pParent = GetpApp()->GetDefDialogParent();
+ switch( nType )
+ {
+ case 16:
+ pBox = new ErrorBox( pParent, nWinBits, aMsg );
+ break;
+ case 32:
+ pBox = new QueryBox( pParent, nWinBits, aMsg );
+ break;
+ case 48:
+ pBox = new WarningBox( pParent, nWinBits, aMsg );
+ break;
+ case 64:
+ pBox = new InfoBox( pParent, aMsg );
+ break;
+ default:
+ pBox = new MessBox( pParent, nWinBits, aTitle, aMsg );
+ }
+ pBox->SetText( aTitle );
+ USHORT nRet = (USHORT)pBox->Execute();
+ if( nRet == TRUE )
+ nRet = 1;
+
+ INT16 nMappedRet;
+ if( nStyle == 2 )
+ {
+ nMappedRet = nRet;
+ if( nMappedRet == 0 )
+ nMappedRet = 3; // Abort
+ }
+ else
+ nMappedRet = nButtonMap[ nRet ];
+
+ rPar.Get(0)->PutInteger( nMappedRet );
+ delete pBox;
+}
+
+RTLFUNC(SetAttr) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if ( rPar.Count() == 3 )
+ {
+ String aStr = rPar.Get(1)->GetString();
+ INT16 nFlags = rPar.Get(2)->GetInteger();
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ sal_Bool bReadOnly = (nFlags & 0x0001) != 0; // ATTR_READONLY
+ xSFI->setReadOnly( aStr, bReadOnly );
+ sal_Bool bHidden = (nFlags & 0x0002) != 0; // ATTR_HIDDEN
+ xSFI->setHidden( aStr, bHidden );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ // #57064 Bei virtuellen URLs den Real-Path extrahieren
+ DirEntry aEntry( aStr );
+ String aFile = aEntry.GetFull();
+ #ifdef WIN
+ int nErr = _dos_setfileattr( aFile.GetStr(),(unsigned ) nFlags );
+ if ( nErr )
+ {
+ if (errno == EACCES)
+ StarBASIC::Error( SbERR_ACCESS_DENIED );
+ else
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ }
+ #endif
+ ByteString aByteFile( aFile, gsl_getSystemTextEncoding() );
+ #ifdef WNT
+ if (!SetFileAttributes (aByteFile.GetBuffer(),(DWORD)nFlags))
+ StarBASIC::Error(SbERR_FILE_NOT_FOUND);
+ #endif
+ #ifdef OS2
+ FILESTATUS3 aFileStatus;
+ APIRET rc = DosQueryPathInfo(aByteFile.GetBuffer(),1,
+ &aFileStatus,sizeof(FILESTATUS3));
+ if (!rc)
+ {
+ if (aFileStatus.attrFile != nFlags)
+ {
+ aFileStatus.attrFile = nFlags;
+ rc = DosSetPathInfo(aFile.GetStr(),1,
+ &aFileStatus,sizeof(FILESTATUS3),0);
+ if (rc)
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_FILE_NOT_FOUND );
+ #endif
+#else
+ // Not implemented
+#endif
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(Reset) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+ (void)rPar;
+
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ if (pIO)
+ pIO->CloseAll();
+}
+
+RTLFUNC(DumpAllObjects)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nArgCount = (USHORT)rPar.Count();
+ if( nArgCount < 2 || nArgCount > 3 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else if( !pBasic )
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ else
+ {
+ SbxObject* p = pBasic;
+ while( p->GetParent() )
+ p = p->GetParent();
+ SvFileStream aStrm( rPar.Get( 1 )->GetString(),
+ STREAM_WRITE | STREAM_TRUNC );
+ p->Dump( aStrm, rPar.Get( 2 )->GetBool() );
+ aStrm.Close();
+ if( aStrm.GetError() != SVSTREAM_OK )
+ StarBASIC::Error( SbERR_IO_ERROR );
+ }
+}
+
+
+RTLFUNC(FileExists)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ String aStr = rPar.Get(1)->GetString();
+ BOOL bExists = FALSE;
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
+ if( xSFI.is() )
+ {
+ try
+ {
+ bExists = xSFI->exists( aStr );
+ }
+ catch( Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
+ }
+ }
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ DirEntry aEntry( aStr );
+ bExists = aEntry.Exists();
+#else
+ DirectoryItem aItem;
+ FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem );
+ bExists = (nRet == FileBase::E_None);
+#endif
+ }
+ rPar.Get(0)->PutBool( bExists );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(Partition)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 5 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ INT32 nNumber = rPar.Get(1)->GetLong();
+ INT32 nStart = rPar.Get(2)->GetLong();
+ INT32 nStop = rPar.Get(3)->GetLong();
+ INT32 nInterval = rPar.Get(4)->GetLong();
+
+ if( nStart < 0 || nStop <= nStart || nInterval < 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ // the Partition function inserts leading spaces before lowervalue and uppervalue
+ // so that they both have the same number of characters as the string
+ // representation of the value (Stop + 1). This ensures that if you use the output
+ // of the Partition function with several values of Number, the resulting text
+ // will be handled properly during any subsequent sort operation.
+
+ // calculate the maximun number of characters before lowervalue and uppervalue
+ ::rtl::OUString aBeforeStart = ::rtl::OUString::valueOf( nStart - 1 );
+ ::rtl::OUString aAfterStop = ::rtl::OUString::valueOf( nStop + 1 );
+ INT32 nLen1 = aBeforeStart.getLength();
+ INT32 nLen2 = aAfterStop.getLength();
+ INT32 nLen = nLen1 >= nLen2 ? nLen1:nLen2;
+
+ ::rtl::OUStringBuffer aRetStr( nLen * 2 + 1);
+ ::rtl::OUString aLowerValue;
+ ::rtl::OUString aUpperValue;
+ if( nNumber < nStart )
+ {
+ aUpperValue = aBeforeStart;
+ }
+ else if( nNumber > nStop )
+ {
+ aLowerValue = aAfterStop;
+ }
+ else
+ {
+ INT32 nLowerValue = nNumber;
+ INT32 nUpperValue = nLowerValue;
+ if( nInterval > 1 )
+ {
+ nLowerValue = ((( nNumber - nStart ) / nInterval ) * nInterval ) + nStart;
+ nUpperValue = nLowerValue + nInterval - 1;
+ }
+
+ aLowerValue = ::rtl::OUString::valueOf( nLowerValue );
+ aUpperValue = ::rtl::OUString::valueOf( nUpperValue );
+ }
+
+ nLen1 = aLowerValue.getLength();
+ nLen2 = aUpperValue.getLength();
+
+ if( nLen > nLen1 )
+ {
+ // appending the leading spaces for the lowervalue
+ for ( INT32 i= (nLen - nLen1) ; i > 0; --i )
+ aRetStr.appendAscii(" ");
+ }
+ aRetStr.append( aLowerValue ).appendAscii(":");
+ if( nLen > nLen2 )
+ {
+ // appending the leading spaces for the uppervalue
+ for ( INT32 i= (nLen - nLen2) ; i > 0; --i )
+ aRetStr.appendAscii(" ");
+ }
+ aRetStr.append( aUpperValue );
+ rPar.Get(0)->PutString( String(aRetStr.makeStringAndClear()) );
+}
diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx
new file mode 100644
index 000000000000..62e9c388f5c5
--- /dev/null
+++ b/basic/source/runtime/methods1.cxx
@@ -0,0 +1,2621 @@
+/*************************************************************************
+ *
+ * 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"
+
+#if defined(WIN)
+#include <string.h>
+#else
+#include <stdlib.h> // getenv
+#endif
+#include <vcl/svapp.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/timer.hxx>
+#include <basic/sbxvar.hxx>
+#ifndef _SBX_HXX
+#include <basic/sbx.hxx>
+#endif
+#include <svl/zforlist.hxx>
+#include <tools/fsys.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/file.hxx>
+
+#ifdef OS2
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#include <svpm.h>
+#endif
+
+#if defined(WIN)
+#include <tools/svwin.h>
+#endif
+
+#ifndef CLK_TCK
+#define CLK_TCK CLOCKS_PER_SEC
+#endif
+
+#include <vcl/jobset.hxx>
+#include <basic/sbobjmod.hxx>
+
+#include "sbintern.hxx"
+#include "runtime.hxx"
+#include "stdobj.hxx"
+#include "rtlproto.hxx"
+#include "dllmgr.hxx"
+#include <iosys.hxx>
+#include "sbunoobj.hxx"
+#include "propacc.hxx"
+
+
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/i18n/XCalendar.hpp>
+
+using namespace comphelper;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::i18n;
+
+
+static Reference< XCalendar > getLocaleCalendar( void )
+{
+ static Reference< XCalendar > xCalendar;
+ if( !xCalendar.is() )
+ {
+ Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
+ if( xSMgr.is() )
+ {
+ xCalendar = Reference< XCalendar >( xSMgr->createInstance
+ ( ::rtl::OUString::createFromAscii( "com.sun.star.i18n.LocaleCalendar" ) ), UNO_QUERY );
+ }
+ }
+
+ static com::sun::star::lang::Locale aLastLocale;
+ static bool bNeedsInit = true;
+
+ com::sun::star::lang::Locale aLocale = Application::GetSettings().GetLocale();
+ bool bNeedsReload = false;
+ if( bNeedsInit )
+ {
+ bNeedsInit = false;
+ bNeedsReload = true;
+ }
+ else if( aLocale.Language != aLastLocale.Language ||
+ aLocale.Country != aLastLocale.Country )
+ {
+ bNeedsReload = true;
+ }
+ if( bNeedsReload )
+ {
+ aLastLocale = aLocale;
+ xCalendar->loadDefaultCalendar( aLocale );
+ }
+ return xCalendar;
+}
+
+
+RTLFUNC(CBool) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ BOOL bVal = FALSE;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ bVal = pSbxVariable->GetBool();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutBool(bVal);
+}
+
+RTLFUNC(CByte) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ BYTE nByte = 0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ nByte = pSbxVariable->GetByte();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutByte(nByte);
+}
+
+RTLFUNC(CCur) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ SbxINT64 nCur;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ nCur = pSbxVariable->GetCurrency();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutCurrency( nCur );
+}
+
+RTLFUNC(CDec) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+#ifdef WNT
+ SbxDecimal* pDec = NULL;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ pDec = pSbxVariable->GetDecimal();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutDecimal( pDec );
+#else
+ rPar.Get(0)->PutEmpty();
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+#endif
+}
+
+RTLFUNC(CDate) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ double nVal = 0.0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ nVal = pSbxVariable->GetDate();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutDate(nVal);
+}
+
+RTLFUNC(CDbl) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ double nVal = 0.0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ if( pSbxVariable->GetType() == SbxSTRING )
+ {
+ // AB #41690 , String holen
+ String aScanStr = pSbxVariable->GetString();
+ SbError Error = SbxValue::ScanNumIntnl( aScanStr, nVal );
+ if( Error != SbxERR_OK )
+ StarBASIC::Error( Error );
+ }
+ else
+ {
+ nVal = pSbxVariable->GetDouble();
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutDouble(nVal);
+}
+
+RTLFUNC(CInt) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ INT16 nVal = 0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ nVal = pSbxVariable->GetInteger();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutInteger(nVal);
+}
+
+RTLFUNC(CLng) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ INT32 nVal = 0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ nVal = pSbxVariable->GetLong();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutLong(nVal);
+}
+
+RTLFUNC(CSng) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ float nVal = (float)0.0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ if( pSbxVariable->GetType() == SbxSTRING )
+ {
+ // AB #41690 , String holen
+ double dVal = 0.0;
+ String aScanStr = pSbxVariable->GetString();
+ SbError Error = SbxValue::ScanNumIntnl( aScanStr, dVal, /*bSingle=*/TRUE );
+ if( SbxBase::GetError() == SbxERR_OK && Error != SbxERR_OK )
+ StarBASIC::Error( Error );
+ nVal = (float)dVal;
+ }
+ else
+ {
+ nVal = pSbxVariable->GetSingle();
+ }
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutSingle(nVal);
+}
+
+RTLFUNC(CStr) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ String aString;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ aString = pSbxVariable->GetString();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutString(aString);
+}
+
+RTLFUNC(CVar) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ SbxValues aVals( SbxVARIANT );
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ pSbxVariable->Get( aVals );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->Put( aVals );
+}
+
+RTLFUNC(CVErr)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ INT16 nErrCode = 0;
+ if ( rPar.Count() == 2 )
+ {
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ nErrCode = pSbxVariable->GetInteger();
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutErr( nErrCode );
+}
+
+RTLFUNC(Iif) // JSM
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 4 )
+ {
+ if (rPar.Get(1)->GetBool())
+ *rPar.Get(0) = *rPar.Get(2);
+ else
+ *rPar.Get(0) = *rPar.Get(3);
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(GetSystemType)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ // Removed for SRC595
+ rPar.Get(0)->PutInteger( -1 );
+}
+
+RTLFUNC(GetGUIType)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // 17.7.2000 Make simple solution for testtool / fat office
+#if defined (WNT)
+ rPar.Get(0)->PutInteger( 1 );
+#elif defined OS2
+ rPar.Get(0)->PutInteger( 2 );
+#elif defined UNX
+ rPar.Get(0)->PutInteger( 4 );
+#else
+ rPar.Get(0)->PutInteger( -1 );
+#endif
+ }
+}
+
+RTLFUNC(Red)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ ULONG nRGB = (ULONG)rPar.Get(1)->GetLong();
+ nRGB &= 0x00FF0000;
+ nRGB >>= 16;
+ rPar.Get(0)->PutInteger( (INT16)nRGB );
+ }
+}
+
+RTLFUNC(Green)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ ULONG nRGB = (ULONG)rPar.Get(1)->GetLong();
+ nRGB &= 0x0000FF00;
+ nRGB >>= 8;
+ rPar.Get(0)->PutInteger( (INT16)nRGB );
+ }
+}
+
+RTLFUNC(Blue)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ ULONG nRGB = (ULONG)rPar.Get(1)->GetLong();
+ nRGB &= 0x000000FF;
+ rPar.Get(0)->PutInteger( (INT16)nRGB );
+ }
+}
+
+
+RTLFUNC(Switch)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nCount = rPar.Count();
+ if( !(nCount & 0x0001 ))
+ // Anzahl der Argumente muss ungerade sein
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ USHORT nCurExpr = 1;
+ while( nCurExpr < (nCount-1) )
+ {
+ if( rPar.Get( nCurExpr )->GetBool())
+ {
+ (*rPar.Get(0)) = *(rPar.Get(nCurExpr+1));
+ return;
+ }
+ nCurExpr += 2;
+ }
+ rPar.Get(0)->PutNull();
+}
+
+//i#64882# Common wait impl for existing Wait and new WaitUntil
+// rtl functions
+void Wait_Impl( bool bDurationBased, SbxArray& rPar )
+{
+ if( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ long nWait = 0;
+ if ( bDurationBased )
+ {
+ double dWait = rPar.Get(1)->GetDouble();
+ double dNow = Now_Impl();
+ double dSecs = (double)( ( dWait - dNow ) * (double)( 24.0*3600.0) );
+ nWait = (long)( dSecs * 1000 ); // wait in thousands of sec
+ }
+ else
+ nWait = rPar.Get(1)->GetLong();
+ if( nWait < 0 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ Timer aTimer;
+ aTimer.SetTimeout( nWait );
+ aTimer.Start();
+ while ( aTimer.IsActive() )
+ Application::Yield();
+}
+
+//i#64882#
+RTLFUNC(Wait)
+{
+ (void)pBasic;
+ (void)bWrite;
+ Wait_Impl( false, rPar );
+}
+
+//i#64882# add new WaitUntil ( for application.wait )
+// share wait_impl with 'normal' oobasic wait
+RTLFUNC(WaitUntil)
+{
+ (void)pBasic;
+ (void)bWrite;
+ Wait_Impl( true, rPar );
+}
+
+RTLFUNC(DoEvents)
+{
+ (void)pBasic;
+ (void)bWrite;
+ (void)rPar;
+ // Dummy implementation as the following code leads
+ // to performance problems for unknown reasons
+ //Timer aTimer;
+ //aTimer.SetTimeout( 1 );
+ //aTimer.Start();
+ //while ( aTimer.IsActive() )
+ // Application::Reschedule();
+}
+
+RTLFUNC(GetGUIVersion)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ // Removed for SRC595
+ rPar.Get(0)->PutLong( -1 );
+ }
+}
+
+RTLFUNC(Choose)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ INT16 nIndex = rPar.Get(1)->GetInteger();
+ USHORT nCount = rPar.Count();
+ nCount--;
+ if( nCount == 1 || nIndex > (nCount-1) || nIndex < 1 )
+ {
+ rPar.Get(0)->PutNull();
+ return;
+ }
+ (*rPar.Get(0)) = *(rPar.Get(nIndex+1));
+}
+
+
+RTLFUNC(Trim)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ String aStr( rPar.Get(1)->GetString() );
+ aStr.EraseLeadingChars();
+ aStr.EraseTrailingChars();
+ rPar.Get(0)->PutString( aStr );
+ }
+}
+
+RTLFUNC(GetSolarVersion)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutLong( (INT32)SUPD );
+}
+
+RTLFUNC(TwipsPerPixelX)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ INT32 nResult = 0;
+ Size aSize( 100,0 );
+ MapMode aMap( MAP_TWIP );
+ OutputDevice* pDevice = Application::GetDefaultDevice();
+ if( pDevice )
+ {
+ aSize = pDevice->PixelToLogic( aSize, aMap );
+ nResult = aSize.Width() / 100;
+ }
+ rPar.Get(0)->PutLong( nResult );
+}
+
+RTLFUNC(TwipsPerPixelY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ INT32 nResult = 0;
+ Size aSize( 0,100 );
+ MapMode aMap( MAP_TWIP );
+ OutputDevice* pDevice = Application::GetDefaultDevice();
+ if( pDevice )
+ {
+ aSize = pDevice->PixelToLogic( aSize, aMap );
+ nResult = aSize.Height() / 100;
+ }
+ rPar.Get(0)->PutLong( nResult );
+}
+
+
+RTLFUNC(FreeLibrary)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ pINST->GetDllMgr()->FreeDll( rPar.Get(1)->GetString() );
+}
+bool IsBaseIndexOne()
+{
+ bool result = false;
+ if ( pINST && pINST->pRun )
+ {
+ USHORT res = pINST->pRun->GetBase();
+ if ( res )
+ result = true;
+ }
+ return result;
+}
+
+RTLFUNC(Array)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
+ USHORT nArraySize = rPar.Count() - 1;
+
+ // Option Base zunaechst ignorieren (kennt leider nur der Compiler)
+ bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
+ if( nArraySize )
+ {
+ if ( bIncIndex )
+ pArray->AddDim( 1, nArraySize );
+ else
+ pArray->AddDim( 0, nArraySize-1 );
+ }
+ else
+ {
+ pArray->unoAddDim( 0, -1 );
+ }
+
+ // Parameter ins Array uebernehmen
+ // ATTENTION: Using type USHORT for loop variable is
+ // mandatory to workaround a problem with the
+ // Solaris Intel compiler optimizer! See i104354
+ for( USHORT i = 0 ; i < nArraySize ; i++ )
+ {
+ SbxVariable* pVar = rPar.Get(i+1);
+ SbxVariable* pNew = new SbxVariable( *pVar );
+ pNew->SetFlag( SBX_WRITE );
+ short index = static_cast< short >(i);
+ if ( bIncIndex )
+ ++index;
+ pArray->Put( pNew, &index );
+ }
+
+ // Array zurueckliefern
+ SbxVariableRef refVar = rPar.Get(0);
+ USHORT nFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->PutObject( pArray );
+ refVar->SetFlags( nFlags );
+ refVar->SetParameters( NULL );
+}
+
+
+// Featurewunsch #57868
+// Die Funktion liefert ein Variant-Array, wenn keine Parameter angegeben
+// werden, wird ein leeres Array erzeugt (entsprechend dim a(), entspricht
+// einer Sequence der Laenge 0 in Uno).
+// Wenn Parameter angegeben sind, wird fuer jeden eine Dimension erzeugt
+// DimArray( 2, 2, 4 ) entspricht DIM a( 2, 2, 4 )
+// Das Array ist immer vom Typ Variant
+RTLFUNC(DimArray)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ SbxDimArray * pArray = new SbxDimArray( SbxVARIANT );
+ USHORT nArrayDims = rPar.Count() - 1;
+ if( nArrayDims > 0 )
+ {
+ for( USHORT i = 0; i < nArrayDims ; i++ )
+ {
+ INT32 ub = rPar.Get(i+1)->GetLong();
+ if( ub < 0 )
+ {
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ ub = 0;
+ }
+ pArray->AddDim32( 0, ub );
+ }
+ }
+ else
+ pArray->unoAddDim( 0, -1 );
+
+ // Array zurueckliefern
+ SbxVariableRef refVar = rPar.Get(0);
+ USHORT nFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->PutObject( pArray );
+ refVar->SetFlags( nFlags );
+ refVar->SetParameters( NULL );
+}
+
+/*
+ * FindObject und FindPropertyObject ermoeglichen es,
+ * Objekte und Properties vom Typ Objekt zur Laufzeit
+ * ueber ihren Namen als String-Parameter anzusprechen.
+ *
+ * Bsp.:
+ * MyObj.Prop1.Bla = 5
+ *
+ * entspricht:
+ * dim ObjVar as Object
+ * dim ObjProp as Object
+ * ObjName$ = "MyObj"
+ * ObjVar = FindObject( ObjName$ )
+ * PropName$ = "Prop1"
+ * ObjProp = FindPropertyObject( ObjVar, PropName$ )
+ * ObjProp.Bla = 5
+ *
+ * Dabei koennen die Namen zur Laufzeit dynamisch
+ * erzeugt werden und, so dass z.B. ueber Controls
+ * "TextEdit1" bis "TextEdit5" in einem Dialog in
+ * einer Schleife iteriert werden kann.
+ */
+
+// Objekt ueber den Namen ansprechen
+// 1. Parameter = Name des Objekts als String
+RTLFUNC(FindObject)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // Wir brauchen einen Parameter
+ if ( rPar.Count() < 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ // 1. Parameter ist der Name
+ String aNameStr = rPar.Get(1)->GetString();
+
+ // Basic-Suchfunktion benutzen
+ SbxBase* pFind = StarBASIC::FindSBXInCurrentScope( aNameStr );
+ SbxObject* pFindObj = NULL;
+ if( pFind )
+ pFindObj = PTR_CAST(SbxObject,pFind);
+ /*
+ if( !pFindObj )
+ {
+ StarBASIC::Error( SbERR_VAR_UNDEFINED );
+ return;
+ }
+ */
+
+ // Objekt zurueckliefern
+ SbxVariableRef refVar = rPar.Get(0);
+ refVar->PutObject( pFindObj );
+}
+
+// Objekt-Property in einem Objekt ansprechen
+// 1. Parameter = Objekt
+// 2. Parameter = Name der Property als String
+RTLFUNC(FindPropertyObject)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // Wir brauchen 2 Parameter
+ if ( rPar.Count() < 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ // 1. Parameter holen, muss Objekt sein
+ SbxBase* pObjVar = (SbxObject*)rPar.Get(1)->GetObject();
+ SbxObject* pObj = NULL;
+ if( pObjVar )
+ pObj = PTR_CAST(SbxObject,pObjVar);
+ if( !pObj && pObjVar && pObjVar->ISA(SbxVariable) )
+ {
+ SbxBase* pObjVarObj = ((SbxVariable*)pObjVar)->GetObject();
+ pObj = PTR_CAST(SbxObject,pObjVarObj);
+ }
+ /*
+ if( !pObj )
+ {
+ StarBASIC::Error( SbERR_VAR_UNDEFINED );
+ return;
+ }
+ */
+
+ // 2. Parameter ist der Name
+ String aNameStr = rPar.Get(2)->GetString();
+
+ // Jetzt muss ein Objekt da sein, sonst Error
+ SbxObject* pFindObj = NULL;
+ if( pObj )
+ {
+ // Im Objekt nach Objekt suchen
+ SbxVariable* pFindVar = pObj->Find( aNameStr, SbxCLASS_OBJECT );
+ pFindObj = PTR_CAST(SbxObject,pFindVar);
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_PARAMETER );
+
+ // Objekt zurueckliefern
+ SbxVariableRef refVar = rPar.Get(0);
+ refVar->PutObject( pFindObj );
+}
+
+
+
+BOOL lcl_WriteSbxVariable( const SbxVariable& rVar, SvStream* pStrm,
+ BOOL bBinary, short nBlockLen, BOOL bIsArray )
+{
+ ULONG nFPos = pStrm->Tell();
+
+ BOOL bIsVariant = !rVar.IsFixed();
+ SbxDataType eType = rVar.GetType();
+
+ switch( eType )
+ {
+ case SbxBOOL:
+ case SbxCHAR:
+ case SbxBYTE:
+ if( bIsVariant )
+ *pStrm << (USHORT)SbxBYTE; // VarType Id
+ *pStrm << rVar.GetByte();
+ break;
+
+ case SbxEMPTY:
+ case SbxNULL:
+ case SbxVOID:
+ case SbxINTEGER:
+ case SbxUSHORT:
+ case SbxINT:
+ case SbxUINT:
+ if( bIsVariant )
+ *pStrm << (USHORT)SbxINTEGER; // VarType Id
+ *pStrm << rVar.GetInteger();
+ break;
+
+ case SbxLONG:
+ case SbxULONG:
+ case SbxLONG64:
+ case SbxULONG64:
+ if( bIsVariant )
+ *pStrm << (USHORT)SbxLONG; // VarType Id
+ *pStrm << rVar.GetLong();
+ break;
+
+ case SbxSINGLE:
+ if( bIsVariant )
+ *pStrm << (USHORT)eType; // VarType Id
+ *pStrm << rVar.GetSingle();
+ break;
+
+ case SbxDOUBLE:
+ case SbxCURRENCY:
+ case SbxDATE:
+ if( bIsVariant )
+ *pStrm << (USHORT)eType; // VarType Id
+ *pStrm << rVar.GetDouble();
+ break;
+
+ case SbxSTRING:
+ case SbxLPSTR:
+ {
+ const String& rStr = rVar.GetString();
+ if( !bBinary || bIsArray )
+ {
+ if( bIsVariant )
+ *pStrm << (USHORT)SbxSTRING;
+ pStrm->WriteByteString( rStr, gsl_getSystemTextEncoding() );
+ //*pStrm << rStr;
+ }
+ else
+ {
+ // ohne Laengenangabe! ohne Endekennung!
+ // What does that mean for Unicode?! Choosing conversion to ByteString...
+ ByteString aByteStr( rStr, gsl_getSystemTextEncoding() );
+ *pStrm << (const char*)aByteStr.GetBuffer();
+ //*pStrm << (const char*)rStr.GetStr();
+ }
+ }
+ break;
+
+ default:
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return FALSE;
+ }
+
+ if( nBlockLen )
+ pStrm->Seek( nFPos + nBlockLen );
+ return pStrm->GetErrorCode() ? FALSE : TRUE;
+}
+
+BOOL lcl_ReadSbxVariable( SbxVariable& rVar, SvStream* pStrm,
+ BOOL bBinary, short nBlockLen, BOOL bIsArray )
+{
+ (void)bBinary;
+ (void)bIsArray;
+
+ double aDouble;
+
+ ULONG nFPos = pStrm->Tell();
+
+ BOOL bIsVariant = !rVar.IsFixed();
+ SbxDataType eVarType = rVar.GetType();
+
+ SbxDataType eSrcType = eVarType;
+ if( bIsVariant )
+ {
+ USHORT nTemp;
+ *pStrm >> nTemp;
+ eSrcType = (SbxDataType)nTemp;
+ }
+
+ switch( eSrcType )
+ {
+ case SbxBOOL:
+ case SbxCHAR:
+ case SbxBYTE:
+ {
+ BYTE aByte;
+ *pStrm >> aByte;
+ rVar.PutByte( aByte );
+ }
+ break;
+
+ case SbxEMPTY:
+ case SbxNULL:
+ case SbxVOID:
+ case SbxINTEGER:
+ case SbxUSHORT:
+ case SbxINT:
+ case SbxUINT:
+ {
+ INT16 aInt;
+ *pStrm >> aInt;
+ rVar.PutInteger( aInt );
+ }
+ break;
+
+ case SbxLONG:
+ case SbxULONG:
+ case SbxLONG64:
+ case SbxULONG64:
+ {
+ INT32 aInt;
+ *pStrm >> aInt;
+ rVar.PutLong( aInt );
+ }
+ break;
+
+ case SbxSINGLE:
+ {
+ float nS;
+ *pStrm >> nS;
+ rVar.PutSingle( nS );
+ }
+ break;
+
+ case SbxDOUBLE:
+ case SbxCURRENCY:
+ {
+ *pStrm >> aDouble;
+ rVar.PutDouble( aDouble );
+ }
+ break;
+
+ case SbxDATE:
+ {
+ *pStrm >> aDouble;
+ rVar.PutDate( aDouble );
+ }
+ break;
+
+ case SbxSTRING:
+ case SbxLPSTR:
+ {
+ String aStr;
+ pStrm->ReadByteString( aStr, gsl_getSystemTextEncoding() );
+ rVar.PutString( aStr );
+ }
+ break;
+
+ default:
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return FALSE;
+ }
+
+ if( nBlockLen )
+ pStrm->Seek( nFPos + nBlockLen );
+ return pStrm->GetErrorCode() ? FALSE : TRUE;
+}
+
+
+// nCurDim = 1...n
+BOOL lcl_WriteReadSbxArray( SbxDimArray& rArr, SvStream* pStrm,
+ BOOL bBinary, short nCurDim, short* pOtherDims, BOOL bWrite )
+{
+ DBG_ASSERT( nCurDim > 0,"Bad Dim");
+ short nLower, nUpper;
+ if( !rArr.GetDim( nCurDim, nLower, nUpper ) )
+ return FALSE;
+ for( short nCur = nLower; nCur <= nUpper; nCur++ )
+ {
+ pOtherDims[ nCurDim-1 ] = nCur;
+ if( nCurDim != 1 )
+ lcl_WriteReadSbxArray(rArr, pStrm, bBinary, nCurDim-1, pOtherDims, bWrite);
+ else
+ {
+ SbxVariable* pVar = rArr.Get( (const short*)pOtherDims );
+ BOOL bRet;
+ if( bWrite )
+ bRet = lcl_WriteSbxVariable(*pVar, pStrm, bBinary, 0, TRUE );
+ else
+ bRet = lcl_ReadSbxVariable(*pVar, pStrm, bBinary, 0, TRUE );
+ if( !bRet )
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void PutGet( SbxArray& rPar, BOOL bPut )
+{
+ // Wir brauchen 3 Parameter
+ if ( rPar.Count() != 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nFileNo = rPar.Get(1)->GetInteger();
+ SbxVariable* pVar2 = rPar.Get(2);
+ BOOL bHasRecordNo = (BOOL)(pVar2->GetType() != SbxEMPTY);
+ long nRecordNo = pVar2->GetLong();
+ if ( nFileNo < 1 || ( bHasRecordNo && nRecordNo < 1 ) )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ nRecordNo--; // wir moegen's ab 0!
+ SbiIoSystem* pIO = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIO->GetStream( nFileNo );
+ // das File muss Random (feste Record-Laenge) oder Binary sein
+ if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_RANDOM)) )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+
+ SvStream* pStrm = pSbStrm->GetStrm();
+ BOOL bRandom = pSbStrm->IsRandom();
+ short nBlockLen = bRandom ? pSbStrm->GetBlockLen() : 0;
+
+ if( bPut )
+ {
+ // Datei aufplustern, falls jemand uebers Dateiende hinaus geseekt hat
+ pSbStrm->ExpandFile();
+ }
+
+ // auf die Startposition seeken
+ if( bHasRecordNo )
+ {
+ ULONG nFilePos = bRandom ? (ULONG)(nBlockLen*nRecordNo) : (ULONG)nRecordNo;
+ pStrm->Seek( nFilePos );
+ }
+
+ SbxDimArray* pArr = 0;
+ SbxVariable* pVar = rPar.Get(3);
+ if( pVar->GetType() & SbxARRAY )
+ {
+ SbxBase* pParObj = pVar->GetObject();
+ pArr = PTR_CAST(SbxDimArray,pParObj);
+ }
+
+ BOOL bRet;
+
+ if( pArr )
+ {
+ ULONG nFPos = pStrm->Tell();
+ short nDims = pArr->GetDims();
+ short* pDims = new short[ nDims ];
+ bRet = lcl_WriteReadSbxArray(*pArr,pStrm,!bRandom,nDims,pDims,bPut);
+ delete [] pDims;
+ if( nBlockLen )
+ pStrm->Seek( nFPos + nBlockLen );
+ }
+ else
+ {
+ if( bPut )
+ bRet = lcl_WriteSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, FALSE);
+ else
+ bRet = lcl_ReadSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, FALSE);
+ }
+ if( !bRet || pStrm->GetErrorCode() )
+ StarBASIC::Error( SbERR_IO_ERROR );
+}
+
+RTLFUNC(Put)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ PutGet( rPar, TRUE );
+}
+
+RTLFUNC(Get)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ PutGet( rPar, FALSE );
+}
+
+RTLFUNC(Environ)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ String aResult;
+ // sollte ANSI sein, aber unter Win16 in DLL nicht moeglich
+#if defined(WIN)
+ LPSTR lpszEnv = GetDOSEnvironment();
+ String aCompareStr( rPar.Get(1)->GetString() );
+ aCompareStr += '=';
+ const char* pCompare = aCompareStr.GetStr();
+ int nCompareLen = aCompareStr.Len();
+ while ( *lpszEnv )
+ {
+ // Es werden alle EnvString in der Form ENV=VAL 0-terminiert
+ // aneinander gehaengt.
+
+ if ( strnicmp( pCompare, lpszEnv, nCompareLen ) == 0 )
+ {
+ aResult = (const char*)(lpszEnv+nCompareLen);
+ rPar.Get(0)->PutString( aResult );
+ return;
+ }
+ lpszEnv += lstrlen( lpszEnv ) + 1; // Next Enviroment-String
+ }
+#else
+ ByteString aByteStr( rPar.Get(1)->GetString(), gsl_getSystemTextEncoding() );
+ const char* pEnvStr = getenv( aByteStr.GetBuffer() );
+ if ( pEnvStr )
+ aResult = String::CreateFromAscii( pEnvStr );
+#endif
+ rPar.Get(0)->PutString( aResult );
+}
+
+static double GetDialogZoomFactor( BOOL bX, long nValue )
+{
+ OutputDevice* pDevice = Application::GetDefaultDevice();
+ double nResult = 0;
+ if( pDevice )
+ {
+ Size aRefSize( nValue, nValue );
+#ifndef WIN
+ Fraction aFracX( 1, 26 );
+#else
+ Fraction aFracX( 1, 23 );
+#endif
+ Fraction aFracY( 1, 24 );
+ MapMode aMap( MAP_APPFONT, Point(), aFracX, aFracY );
+ Size aScaledSize = pDevice->LogicToPixel( aRefSize, aMap );
+ aRefSize = pDevice->LogicToPixel( aRefSize, MapMode(MAP_TWIP) );
+
+ double nRef, nScaled;
+ if( bX )
+ {
+ nRef = aRefSize.Width();
+ nScaled = aScaledSize.Width();
+ }
+ else
+ {
+ nRef = aRefSize.Height();
+ nScaled = aScaledSize.Height();
+ }
+ nResult = nScaled / nRef;
+ }
+ return nResult;
+}
+
+
+RTLFUNC(GetDialogZoomFactorX)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ rPar.Get(0)->PutDouble( GetDialogZoomFactor( TRUE, rPar.Get(1)->GetLong() ));
+}
+
+RTLFUNC(GetDialogZoomFactorY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ rPar.Get(0)->PutDouble( GetDialogZoomFactor( FALSE, rPar.Get(1)->GetLong()));
+}
+
+
+RTLFUNC(EnableReschedule)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutEmpty();
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ if( pINST )
+ pINST->EnableReschedule( rPar.Get(1)->GetBool() );
+}
+
+RTLFUNC(GetSystemTicks)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ rPar.Get(0)->PutLong( Time::GetSystemTicks() );
+}
+
+RTLFUNC(GetPathSeparator)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ rPar.Get(0)->PutString( DirEntry::GetAccessDelimiter() );
+}
+
+RTLFUNC(ResolvePath)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ String aStr = rPar.Get(1)->GetString();
+ DirEntry aEntry( aStr );
+ //if( aEntry.IsVirtual() )
+ //aStr = aEntry.GetRealPathFromVirtualURL();
+ rPar.Get(0)->PutString( aStr );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(TypeLen)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ SbxDataType eType = rPar.Get(1)->GetType();
+ INT16 nLen = 0;
+ switch( eType )
+ {
+ case SbxEMPTY:
+ case SbxNULL:
+ case SbxVECTOR:
+ case SbxARRAY:
+ case SbxBYREF:
+ case SbxVOID:
+ case SbxHRESULT:
+ case SbxPOINTER:
+ case SbxDIMARRAY:
+ case SbxCARRAY:
+ case SbxUSERDEF:
+ nLen = 0;
+ break;
+
+ case SbxINTEGER:
+ case SbxERROR:
+ case SbxUSHORT:
+ case SbxINT:
+ case SbxUINT:
+ nLen = 2;
+ break;
+
+ case SbxLONG:
+ case SbxSINGLE:
+ case SbxULONG:
+ nLen = 4;
+ break;
+
+ case SbxDOUBLE:
+ case SbxCURRENCY:
+ case SbxDATE:
+ case SbxLONG64:
+ case SbxULONG64:
+ nLen = 8;
+ break;
+
+ case SbxOBJECT:
+ case SbxVARIANT:
+ case SbxDATAOBJECT:
+ nLen = 0;
+ break;
+
+ case SbxCHAR:
+ case SbxBYTE:
+ case SbxBOOL:
+ nLen = 1;
+ break;
+
+ case SbxLPSTR:
+ case SbxLPWSTR:
+ case SbxCoreSTRING:
+ case SbxSTRING:
+ nLen = (INT16)rPar.Get(1)->GetString().Len();
+ break;
+
+ default:
+ nLen = 0;
+ }
+ rPar.Get(0)->PutInteger( nLen );
+ }
+}
+
+
+// Uno-Struct eines beliebigen Typs erzeugen
+// 1. Parameter == Klassename, weitere Parameter zur Initialisierung
+RTLFUNC(CreateUnoStruct)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_CreateUnoStruct( pBasic, rPar, bWrite );
+}
+
+// Uno-Service erzeugen
+// 1. Parameter == Service-Name
+RTLFUNC(CreateUnoService)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_CreateUnoService( pBasic, rPar, bWrite );
+}
+
+RTLFUNC(CreateUnoServiceWithArguments)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_CreateUnoServiceWithArguments( pBasic, rPar, bWrite );
+}
+
+
+RTLFUNC(CreateUnoValue)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_CreateUnoValue( pBasic, rPar, bWrite );
+}
+
+
+// ServiceManager liefern (keine Parameter)
+RTLFUNC(GetProcessServiceManager)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_GetProcessServiceManager( pBasic, rPar, bWrite );
+}
+
+// PropertySet erzeugen
+// 1. Parameter == Sequence<PropertyValue>
+RTLFUNC(CreatePropertySet)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_CreatePropertySet( pBasic, rPar, bWrite );
+}
+
+// Abfragen, ob ein Interface unterstuetzt wird
+// Mehrere Interface-Namen als Parameter
+RTLFUNC(HasUnoInterfaces)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_HasInterfaces( pBasic, rPar, bWrite );
+}
+
+// Abfragen, ob ein Basic-Objekt ein Uno-Struct repraesentiert
+RTLFUNC(IsUnoStruct)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_IsUnoStruct( pBasic, rPar, bWrite );
+}
+
+// Abfragen, ob zwei Uno-Objekte identisch sind
+RTLFUNC(EqualUnoObjects)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_EqualUnoObjects( pBasic, rPar, bWrite );
+}
+
+// Instanciate "com.sun.star.awt.UnoControlDialog" on basis
+// of a DialogLibrary entry: Convert from XML-ByteSequence
+// and attach events. Implemented in classes\eventatt.cxx
+void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite );
+
+RTLFUNC(CreateUnoDialog)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_CreateUnoDialog( pBasic, rPar, bWrite );
+}
+
+// Return the application standard lib as root scope
+RTLFUNC(GlobalScope)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ SbxObject* p = pBasic;
+ while( p->GetParent() )
+ p = p->GetParent();
+
+ SbxVariableRef refVar = rPar.Get(0);
+ refVar->PutObject( p );
+}
+
+// Helper functions to convert Url from/to system paths
+RTLFUNC(ConvertToUrl)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ String aStr = rPar.Get(1)->GetString();
+ INetURLObject aURLObj( aStr, INET_PROT_FILE );
+ ::rtl::OUString aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
+ if( !aFileURL.getLength() )
+ ::osl::File::getFileURLFromSystemPath( aFileURL, aFileURL );
+ if( !aFileURL.getLength() )
+ aFileURL = aStr;
+ rPar.Get(0)->PutString( String(aFileURL) );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+RTLFUNC(ConvertFromUrl)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() == 2 )
+ {
+ String aStr = rPar.Get(1)->GetString();
+ ::rtl::OUString aSysPath;
+ ::osl::File::getSystemPathFromFileURL( aStr, aSysPath );
+ if( !aSysPath.getLength() )
+ aSysPath = aStr;
+ rPar.Get(0)->PutString( String(aSysPath) );
+ }
+ else
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+}
+
+
+// Provide DefaultContext
+RTLFUNC(GetDefaultContext)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ RTL_Impl_GetDefaultContext( pBasic, rPar, bWrite );
+}
+
+
+RTLFUNC(Join)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if ( nParCount != 3 && nParCount != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ SbxBase* pParObj = rPar.Get(1)->GetObject();
+ SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
+ if( pArr )
+ {
+ if( pArr->GetDims() != 1 )
+ StarBASIC::Error( SbERR_WRONG_DIMS ); // Syntax Error?!
+
+ String aDelim;
+ if( nParCount == 3 )
+ aDelim = rPar.Get(2)->GetString();
+ else
+ aDelim = String::CreateFromAscii( " " );
+
+ String aRetStr;
+ short nLower, nUpper;
+ pArr->GetDim( 1, nLower, nUpper );
+ for( short i = nLower ; i <= nUpper ; ++i )
+ {
+ String aStr = pArr->Get( &i )->GetString();
+ aRetStr += aStr;
+ if( i != nUpper )
+ aRetStr += aDelim;
+ }
+ rPar.Get(0)->PutString( aRetStr );
+ }
+ else
+ StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
+}
+
+
+RTLFUNC(Split)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if ( nParCount < 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aExpression = rPar.Get(1)->GetString();
+ short nArraySize = 0;
+ StringVector vRet;
+ if( aExpression.Len() )
+ {
+ String aDelim;
+ if( nParCount >= 3 )
+ aDelim = rPar.Get(2)->GetString();
+ else
+ aDelim = String::CreateFromAscii( " " );
+
+ INT32 nCount = -1;
+ if( nParCount == 4 )
+ nCount = rPar.Get(3)->GetLong();
+
+ xub_StrLen nDelimLen = aDelim.Len();
+ if( nDelimLen )
+ {
+ xub_StrLen iSearch = STRING_NOTFOUND;
+ xub_StrLen iStart = 0;
+ do
+ {
+ bool bBreak = false;
+ if( nCount >= 0 && nArraySize == nCount - 1 )
+ bBreak = true;
+
+ iSearch = aExpression.Search( aDelim, iStart );
+ String aSubStr;
+ if( iSearch != STRING_NOTFOUND && !bBreak )
+ {
+ aSubStr = aExpression.Copy( iStart, iSearch - iStart );
+ iStart = iSearch + nDelimLen;
+ }
+ else
+ {
+ aSubStr = aExpression.Copy( iStart );
+ }
+ vRet.push_back( aSubStr );
+ nArraySize++;
+
+ if( bBreak )
+ break;
+ }
+ while( iSearch != STRING_NOTFOUND );
+ }
+ else
+ {
+ vRet.push_back( aExpression );
+ nArraySize = 1;
+ }
+ }
+
+ SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
+ pArray->unoAddDim( 0, nArraySize-1 );
+
+ // Parameter ins Array uebernehmen
+ for( short i = 0 ; i < nArraySize ; i++ )
+ {
+ SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
+ xVar->PutString( vRet[i] );
+ pArray->Put( (SbxVariable*)xVar, &i );
+ }
+
+ // Array zurueckliefern
+ SbxVariableRef refVar = rPar.Get(0);
+ USHORT nFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->PutObject( pArray );
+ refVar->SetFlags( nFlags );
+ refVar->SetParameters( NULL );
+}
+
+// MonthName(month[, abbreviate])
+RTLFUNC(MonthName)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount != 2 && nParCount != 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ Reference< XCalendar > xCalendar = getLocaleCalendar();
+ if( !xCalendar.is() )
+ {
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ return;
+ }
+ Sequence< CalendarItem > aMonthSeq = xCalendar->getMonths();
+ sal_Int32 nMonthCount = aMonthSeq.getLength();
+
+ INT16 nVal = rPar.Get(1)->GetInteger();
+ if( nVal < 1 || nVal > nMonthCount )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ BOOL bAbbreviate = false;
+ if( nParCount == 3 )
+ bAbbreviate = rPar.Get(2)->GetBool();
+
+ const CalendarItem* pCalendarItems = aMonthSeq.getConstArray();
+ const CalendarItem& rItem = pCalendarItems[nVal - 1];
+
+ ::rtl::OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName );
+ rPar.Get(0)->PutString( String(aRetStr) );
+}
+
+// WeekdayName(weekday, abbreviate, firstdayofweek)
+RTLFUNC(WeekdayName)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount < 2 || nParCount > 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ Reference< XCalendar > xCalendar = getLocaleCalendar();
+ if( !xCalendar.is() )
+ {
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ return;
+ }
+
+ Sequence< CalendarItem > aDaySeq = xCalendar->getDays();
+ INT16 nDayCount = (INT16)aDaySeq.getLength();
+ INT16 nDay = rPar.Get(1)->GetInteger();
+ INT16 nFirstDay = 0;
+ if( nParCount == 4 )
+ {
+ nFirstDay = rPar.Get(3)->GetInteger();
+ if( nFirstDay < 0 || nFirstDay > 7 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ }
+ if( nFirstDay == 0 )
+ nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
+
+ nDay = 1 + (nDay + nDayCount + nFirstDay - 2) % nDayCount;
+ if( nDay < 1 || nDay > nDayCount )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ BOOL bAbbreviate = false;
+ if( nParCount >= 3 )
+ {
+ SbxVariable* pPar2 = rPar.Get(2);
+ if( !pPar2->IsErr() )
+ bAbbreviate = pPar2->GetBool();
+ }
+
+ const CalendarItem* pCalendarItems = aDaySeq.getConstArray();
+ const CalendarItem& rItem = pCalendarItems[nDay - 1];
+
+ ::rtl::OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName );
+ rPar.Get(0)->PutString( String(aRetStr) );
+}
+
+INT16 implGetWeekDay( double aDate, bool bFirstDayParam = false, INT16 nFirstDay = 0 )
+{
+ Date aRefDate( 1,1,1900 );
+ long nDays = (long) aDate;
+ nDays -= 2; // normieren: 1.1.1900 => 0
+ aRefDate += nDays;
+ DayOfWeek aDay = aRefDate.GetDayOfWeek();
+ INT16 nDay;
+ if ( aDay != SUNDAY )
+ nDay = (INT16)aDay + 2;
+ else
+ nDay = 1; // 1==Sonntag
+
+ // #117253 Optional 2. parameter "firstdayofweek"
+ if( bFirstDayParam )
+ {
+ if( nFirstDay < 0 || nFirstDay > 7 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return 0;
+ }
+ if( nFirstDay == 0 )
+ {
+ Reference< XCalendar > xCalendar = getLocaleCalendar();
+ if( !xCalendar.is() )
+ {
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ return 0;
+ }
+ nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
+ }
+ nDay = 1 + (nDay + 7 - nFirstDay) % 7;
+ }
+ return nDay;
+}
+
+RTLFUNC(Weekday)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if ( nParCount < 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ else
+ {
+ double aDate = rPar.Get(1)->GetDate();
+
+ bool bFirstDay = false;
+ INT16 nFirstDay = 0;
+ if ( nParCount > 2 )
+ {
+ nFirstDay = rPar.Get(2)->GetInteger();
+ bFirstDay = true;
+ }
+ INT16 nDay = implGetWeekDay( aDate, bFirstDay, nFirstDay );
+ rPar.Get(0)->PutInteger( nDay );
+ }
+}
+
+
+enum Interval
+{
+ INTERVAL_NONE,
+ INTERVAL_YYYY,
+ INTERVAL_Q,
+ INTERVAL_M,
+ INTERVAL_Y,
+ INTERVAL_D,
+ INTERVAL_W,
+ INTERVAL_WW,
+ INTERVAL_H,
+ INTERVAL_N,
+ INTERVAL_S
+};
+
+struct IntervalInfo
+{
+ Interval meInterval;
+ const char* mpStringCode;
+ double mdValue;
+ bool mbSimple;
+
+ IntervalInfo( Interval eInterval, const char* pStringCode, double dValue, bool bSimple )
+ : meInterval( eInterval )
+ , mpStringCode( pStringCode )
+ , mdValue( dValue )
+ , mbSimple( bSimple )
+ {}
+};
+
+static IntervalInfo pIntervalTable[] =
+{
+ IntervalInfo( INTERVAL_YYYY, "yyyy", 0.0, false ), // Year
+ IntervalInfo( INTERVAL_Q, "q", 0.0, false ), // Quarter
+ IntervalInfo( INTERVAL_M, "m", 0.0, false ), // Month
+ IntervalInfo( INTERVAL_Y, "y", 1.0, true ), // Day of year
+ IntervalInfo( INTERVAL_D, "d", 1.0, true ), // Day
+ IntervalInfo( INTERVAL_W, "w", 1.0, true ), // Weekday
+ IntervalInfo( INTERVAL_WW, "ww", 7.0, true ), // Week
+ IntervalInfo( INTERVAL_H, "h", (1.0 / 24.0), true ), // Hour
+ IntervalInfo( INTERVAL_N, "n", (1.0 / 1440.0), true), // Minute
+ IntervalInfo( INTERVAL_S, "s", (1.0 / 86400.0), true ), // Second
+ IntervalInfo( INTERVAL_NONE, NULL, 0.0, false )
+};
+
+IntervalInfo* getIntervalInfo( const String& rStringCode )
+{
+ IntervalInfo* pInfo = NULL;
+ INT16 i = 0;
+ while( (pInfo = pIntervalTable + i)->mpStringCode != NULL )
+ {
+ if( rStringCode.EqualsIgnoreCaseAscii( pInfo->mpStringCode ) )
+ break;
+ i++;
+ }
+ return pInfo;
+}
+
+// From methods.cxx
+BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet );
+INT16 implGetDateDay( double aDate );
+INT16 implGetDateMonth( double aDate );
+INT16 implGetDateYear( double aDate );
+
+INT16 implGetHour( double dDate );
+INT16 implGetMinute( double dDate );
+INT16 implGetSecond( double dDate );
+
+
+inline void implGetDayMonthYear( INT16& rnYear, INT16& rnMonth, INT16& rnDay, double dDate )
+{
+ rnDay = implGetDateDay( dDate );
+ rnMonth = implGetDateMonth( dDate );
+ rnYear = implGetDateYear( dDate );
+}
+
+inline INT16 limitToINT16( INT32 n32 )
+{
+ if( n32 > 32767 )
+ n32 = 32767;
+ else if( n32 < -32768 )
+ n32 = -32768;
+ return (INT16)n32;
+}
+
+RTLFUNC(DateAdd)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount != 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aStringCode = rPar.Get(1)->GetString();
+ IntervalInfo* pInfo = getIntervalInfo( aStringCode );
+ if( !pInfo )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ INT32 lNumber = rPar.Get(2)->GetLong();
+ double dDate = rPar.Get(3)->GetDate();
+ double dNewDate = 0;
+ if( pInfo->mbSimple )
+ {
+ double dAdd = pInfo->mdValue * lNumber;
+ dNewDate = dDate + dAdd;
+ }
+ else
+ {
+ // Keep hours, minutes, seconds
+ double dHoursMinutesSeconds = dDate - floor( dDate );
+
+ BOOL bOk = TRUE;
+ INT16 nYear, nMonth, nDay;
+ INT16 nTargetYear16 = 0, nTargetMonth = 0;
+ implGetDayMonthYear( nYear, nMonth, nDay, dDate );
+ switch( pInfo->meInterval )
+ {
+ case INTERVAL_YYYY:
+ {
+ INT32 nTargetYear = lNumber + nYear;
+ nTargetYear16 = limitToINT16( nTargetYear );
+ nTargetMonth = nMonth;
+ bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate );
+ break;
+ }
+ case INTERVAL_Q:
+ case INTERVAL_M:
+ {
+ bool bNeg = (lNumber < 0);
+ if( bNeg )
+ lNumber = -lNumber;
+ INT32 nYearsAdd;
+ INT16 nMonthAdd;
+ if( pInfo->meInterval == INTERVAL_Q )
+ {
+ nYearsAdd = lNumber / 4;
+ nMonthAdd = (INT16)( 3 * (lNumber % 4) );
+ }
+ else
+ {
+ nYearsAdd = lNumber / 12;
+ nMonthAdd = (INT16)( lNumber % 12 );
+ }
+
+ INT32 nTargetYear;
+ if( bNeg )
+ {
+ nTargetMonth = nMonth - nMonthAdd;
+ if( nTargetMonth <= 0 )
+ {
+ nTargetMonth += 12;
+ nYearsAdd++;
+ }
+ nTargetYear = (INT32)nYear - nYearsAdd;
+ }
+ else
+ {
+ nTargetMonth = nMonth + nMonthAdd;
+ if( nTargetMonth > 12 )
+ {
+ nTargetMonth -= 12;
+ nYearsAdd++;
+ }
+ nTargetYear = (INT32)nYear + nYearsAdd;
+ }
+ nTargetYear16 = limitToINT16( nTargetYear );
+ bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate );
+ break;
+ }
+ default: break;
+ }
+
+ if( bOk )
+ {
+ // Overflow?
+ INT16 nNewYear, nNewMonth, nNewDay;
+ implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
+ if( nNewYear > 9999 || nNewYear < 100 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ INT16 nCorrectionDay = nDay;
+ while( nNewMonth > nTargetMonth )
+ {
+ nCorrectionDay--;
+ implDateSerial( nTargetYear16, nTargetMonth, nCorrectionDay, dNewDate );
+ implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
+ }
+ dNewDate += dHoursMinutesSeconds;
+ }
+ }
+
+ rPar.Get(0)->PutDate( dNewDate );
+}
+
+inline double RoundImpl( double d )
+{
+ return ( d >= 0 ) ? floor( d + 0.5 ) : -floor( -d + 0.5 );
+}
+
+RTLFUNC(DateDiff)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]])
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount < 4 || nParCount > 6 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aStringCode = rPar.Get(1)->GetString();
+ IntervalInfo* pInfo = getIntervalInfo( aStringCode );
+ if( !pInfo )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ double dDate1 = rPar.Get(2)->GetDate();
+ double dDate2 = rPar.Get(3)->GetDate();
+
+ double dRet = 0.0;
+ switch( pInfo->meInterval )
+ {
+ case INTERVAL_YYYY:
+ {
+ INT16 nYear1 = implGetDateYear( dDate1 );
+ INT16 nYear2 = implGetDateYear( dDate2 );
+ dRet = nYear2 - nYear1;
+ break;
+ }
+ case INTERVAL_Q:
+ {
+ INT16 nYear1 = implGetDateYear( dDate1 );
+ INT16 nYear2 = implGetDateYear( dDate2 );
+ INT16 nQ1 = 1 + (implGetDateMonth( dDate1 ) - 1) / 3;
+ INT16 nQ2 = 1 + (implGetDateMonth( dDate2 ) - 1) / 3;
+ INT16 nQGes1 = 4 * nYear1 + nQ1;
+ INT16 nQGes2 = 4 * nYear2 + nQ2;
+ dRet = nQGes2 - nQGes1;
+ break;
+ }
+ case INTERVAL_M:
+ {
+ INT16 nYear1 = implGetDateYear( dDate1 );
+ INT16 nYear2 = implGetDateYear( dDate2 );
+ INT16 nMonth1 = implGetDateMonth( dDate1 );
+ INT16 nMonth2 = implGetDateMonth( dDate2 );
+ INT16 nMonthGes1 = 12 * nYear1 + nMonth1;
+ INT16 nMonthGes2 = 12 * nYear2 + nMonth2;
+ dRet = nMonthGes2 - nMonthGes1;
+ break;
+ }
+ case INTERVAL_Y:
+ case INTERVAL_D:
+ {
+ double dDays1 = floor( dDate1 );
+ double dDays2 = floor( dDate2 );
+ dRet = dDays2 - dDays1;
+ break;
+ }
+ case INTERVAL_W:
+ case INTERVAL_WW:
+ {
+ double dDays1 = floor( dDate1 );
+ double dDays2 = floor( dDate2 );
+ if( pInfo->meInterval == INTERVAL_WW )
+ {
+ INT16 nFirstDay = 1; // Default
+ if( nParCount >= 5 )
+ {
+ nFirstDay = rPar.Get(4)->GetInteger();
+ if( nFirstDay < 0 || nFirstDay > 7 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ if( nFirstDay == 0 )
+ {
+ Reference< XCalendar > xCalendar = getLocaleCalendar();
+ if( !xCalendar.is() )
+ {
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ return;
+ }
+ nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
+ }
+ }
+ INT16 nDay1 = implGetWeekDay( dDate1 );
+ INT16 nDay1_Diff = nDay1 - nFirstDay;
+ if( nDay1_Diff < 0 )
+ nDay1_Diff += 7;
+ dDays1 -= nDay1_Diff;
+
+ INT16 nDay2 = implGetWeekDay( dDate2 );
+ INT16 nDay2_Diff = nDay2 - nFirstDay;
+ if( nDay2_Diff < 0 )
+ nDay2_Diff += 7;
+ dDays2 -= nDay2_Diff;
+ }
+
+ double dDiff = dDays2 - dDays1;
+ dRet = ( dDiff >= 0 ) ? floor( dDiff / 7.0 ) : -floor( -dDiff / 7.0 );
+ break;
+ }
+ case INTERVAL_H:
+ {
+ double dFactor = 24.0;
+ dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
+ break;
+ }
+ case INTERVAL_N:
+ {
+ double dFactor =1440.0;
+ dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
+ break;
+ }
+ case INTERVAL_S:
+ {
+ double dFactor = 86400.0;
+ dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
+ break;
+ }
+ case INTERVAL_NONE:
+ break;
+ }
+ rPar.Get(0)->PutDouble( dRet );
+}
+
+double implGetDateOfFirstDayInFirstWeek
+ ( INT16 nYear, INT16& nFirstDay, INT16& nFirstWeek, bool* pbError = NULL )
+{
+ SbError nError = 0;
+ if( nFirstDay < 0 || nFirstDay > 7 )
+ nError = SbERR_BAD_ARGUMENT;
+
+ if( nFirstWeek < 0 || nFirstWeek > 3 )
+ nError = SbERR_BAD_ARGUMENT;
+
+ Reference< XCalendar > xCalendar;
+ if( nFirstDay == 0 || nFirstWeek == 0 )
+ {
+ xCalendar = getLocaleCalendar();
+ if( !xCalendar.is() )
+ nError = SbERR_BAD_ARGUMENT;
+ }
+
+ if( nError != 0 )
+ {
+ StarBASIC::Error( nError );
+ if( pbError )
+ *pbError = true;
+ return 0.0;
+ }
+
+ if( nFirstDay == 0 )
+ nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
+
+ INT16 nFirstWeekMinDays = 0; // Not used for vbFirstJan1 = default
+ if( nFirstWeek == 0 )
+ {
+ nFirstWeekMinDays = xCalendar->getMinimumNumberOfDaysForFirstWeek();
+ if( nFirstWeekMinDays == 1 )
+ {
+ nFirstWeekMinDays = 0;
+ nFirstWeek = 1;
+ }
+ else if( nFirstWeekMinDays == 4 )
+ nFirstWeek = 2;
+ else if( nFirstWeekMinDays == 7 )
+ nFirstWeek = 3;
+ }
+ else if( nFirstWeek == 2 )
+ nFirstWeekMinDays = 4; // vbFirstFourDays
+ else if( nFirstWeek == 3 )
+ nFirstWeekMinDays = 7; // vbFirstFourDays
+
+ double dBaseDate;
+ implDateSerial( nYear, 1, 1, dBaseDate );
+ double dRetDate = dBaseDate;
+
+ INT16 nWeekDay0101 = implGetWeekDay( dBaseDate );
+ INT16 nDayDiff = nWeekDay0101 - nFirstDay;
+ if( nDayDiff < 0 )
+ nDayDiff += 7;
+
+ if( nFirstWeekMinDays )
+ {
+ INT16 nThisWeeksDaysInYearCount = 7 - nDayDiff;
+ if( nThisWeeksDaysInYearCount < nFirstWeekMinDays )
+ nDayDiff -= 7;
+ }
+ dRetDate = dBaseDate - nDayDiff;
+ return dRetDate;
+}
+
+RTLFUNC(DatePart)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // DatePart(interval, date[,firstdayofweek[, firstweekofyear]])
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount < 3 || nParCount > 5 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aStringCode = rPar.Get(1)->GetString();
+ IntervalInfo* pInfo = getIntervalInfo( aStringCode );
+ if( !pInfo )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ double dDate = rPar.Get(2)->GetDate();
+
+ INT32 nRet = 0;
+ switch( pInfo->meInterval )
+ {
+ case INTERVAL_YYYY:
+ {
+ nRet = implGetDateYear( dDate );
+ break;
+ }
+ case INTERVAL_Q:
+ {
+ nRet = 1 + (implGetDateMonth( dDate ) - 1) / 3;
+ break;
+ }
+ case INTERVAL_M:
+ {
+ nRet = implGetDateMonth( dDate );
+ break;
+ }
+ case INTERVAL_Y:
+ {
+ INT16 nYear = implGetDateYear( dDate );
+ double dBaseDate;
+ implDateSerial( nYear, 1, 1, dBaseDate );
+ nRet = 1 + INT32( dDate - dBaseDate );
+ break;
+ }
+ case INTERVAL_D:
+ {
+ nRet = implGetDateDay( dDate );
+ break;
+ }
+ case INTERVAL_W:
+ {
+ bool bFirstDay = false;
+ INT16 nFirstDay = 1; // Default
+ if( nParCount >= 4 )
+ {
+ nFirstDay = rPar.Get(3)->GetInteger();
+ bFirstDay = true;
+ }
+ nRet = implGetWeekDay( dDate, bFirstDay, nFirstDay );
+ break;
+ }
+ case INTERVAL_WW:
+ {
+ INT16 nFirstDay = 1; // Default
+ if( nParCount >= 4 )
+ nFirstDay = rPar.Get(3)->GetInteger();
+
+ INT16 nFirstWeek = 1; // Default
+ if( nParCount == 5 )
+ nFirstWeek = rPar.Get(4)->GetInteger();
+
+ INT16 nYear = implGetDateYear( dDate );
+ bool bError = false;
+ double dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear, nFirstDay, nFirstWeek, &bError );
+ if( !bError )
+ {
+ if( dYearFirstDay > dDate )
+ {
+ // Date belongs to last year's week
+ dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear - 1, nFirstDay, nFirstWeek );
+ }
+ else if( nFirstWeek != 1 )
+ {
+ // Check if date belongs to next year
+ double dNextYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear + 1, nFirstDay, nFirstWeek );
+ if( dDate >= dNextYearFirstDay )
+ dYearFirstDay = dNextYearFirstDay;
+ }
+
+ // Calculate week
+ double dDiff = dDate - dYearFirstDay;
+ nRet = 1 + INT32( dDiff / 7 );
+ }
+ break;
+ }
+ case INTERVAL_H:
+ {
+ nRet = implGetHour( dDate );
+ break;
+ }
+ case INTERVAL_N:
+ {
+ nRet = implGetMinute( dDate );
+ break;
+ }
+ case INTERVAL_S:
+ {
+ nRet = implGetSecond( dDate );
+ break;
+ }
+ case INTERVAL_NONE:
+ break;
+ }
+ rPar.Get(0)->PutLong( nRet );
+}
+
+// FormatDateTime(Date[,NamedFormat])
+RTLFUNC(FormatDateTime)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount < 2 || nParCount > 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ double dDate = rPar.Get(1)->GetDate();
+ INT16 nNamedFormat = 0;
+ if( nParCount > 2 )
+ {
+ nNamedFormat = rPar.Get(2)->GetInteger();
+ if( nNamedFormat < 0 || nNamedFormat > 4 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ }
+
+ Reference< XCalendar > xCalendar = getLocaleCalendar();
+ if( !xCalendar.is() )
+ {
+ StarBASIC::Error( SbERR_INTERNAL_ERROR );
+ return;
+ }
+
+ String aRetStr;
+ SbxVariableRef pSbxVar = new SbxVariable( SbxSTRING );
+ switch( nNamedFormat )
+ {
+ // GeneralDate:
+ // Display a date and/or time. If there is a date part,
+ // display it as a short date. If there is a time part,
+ // display it as a long time. If present, both parts are displayed.
+
+ // 12/21/2004 11:24:50 AM
+ // 21.12.2004 12:13:51
+ case 0:
+ pSbxVar->PutDate( dDate );
+ aRetStr = pSbxVar->GetString();
+ break;
+
+ // LongDate: Display a date using the long date format specified
+ // in your computer's regional settings.
+ // Tuesday, December 21, 2004
+ // Dienstag, 21. December 2004
+ case 1:
+ {
+ SvNumberFormatter* pFormatter = NULL;
+ if( pINST )
+ pFormatter = pINST->GetNumberFormatter();
+ else
+ {
+ sal_uInt32 n; // Dummy
+ SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
+ }
+
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ ULONG nIndex = pFormatter->GetFormatIndex( NF_DATE_SYSTEM_LONG, eLangType );
+ Color* pCol;
+ pFormatter->GetOutputString( dDate, nIndex, aRetStr, &pCol );
+
+ if( !pINST )
+ delete pFormatter;
+
+ break;
+ }
+
+ // ShortDate: Display a date using the short date format specified
+ // in your computer's regional settings.
+ // 12/21/2004
+ // 21.12.2004
+ case 2:
+ pSbxVar->PutDate( floor(dDate) );
+ aRetStr = pSbxVar->GetString();
+ break;
+
+ // LongTime: Display a time using the time format specified
+ // in your computer's regional settings.
+ // 11:24:50 AM
+ // 12:13:51
+ case 3:
+ // ShortTime: Display a time using the 24-hour format (hh:mm).
+ // 11:24
+ case 4:
+ double n;
+ double dTime = modf( dDate, &n );
+ pSbxVar->PutDate( dTime );
+ if( nNamedFormat == 3 )
+ aRetStr = pSbxVar->GetString();
+ else
+ aRetStr = pSbxVar->GetString().Copy( 0, 5 );
+ break;
+ }
+
+ rPar.Get(0)->PutString( aRetStr );
+}
+
+RTLFUNC(Round)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ USHORT nParCount = rPar.Count();
+ if( nParCount != 2 && nParCount != 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ double dVal = pSbxVariable->GetDouble();
+ double dRes = 0.0;
+ if( dVal != 0.0 )
+ {
+ bool bNeg = false;
+ if( dVal < 0.0 )
+ {
+ bNeg = true;
+ dVal = -dVal;
+ }
+
+ INT16 numdecimalplaces = 0;
+ if( nParCount == 3 )
+ {
+ numdecimalplaces = rPar.Get(2)->GetInteger();
+ if( numdecimalplaces < 0 || numdecimalplaces > 22 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+ }
+
+ if( numdecimalplaces == 0 )
+ {
+ dRes = floor( dVal + 0.5 );
+ }
+ else
+ {
+ double dFactor = pow( 10.0, numdecimalplaces );
+ dVal *= dFactor;
+ dRes = floor( dVal + 0.5 );
+ dRes /= dFactor;
+ }
+
+ if( bNeg )
+ dRes = -dRes;
+ }
+ rPar.Get(0)->PutDouble( dRes );
+}
+
+RTLFUNC(StrReverse)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if ( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ SbxVariable *pSbxVariable = rPar.Get(1);
+ if( pSbxVariable->IsNull() )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ String aStr = pSbxVariable->GetString();
+ aStr.Reverse();
+ rPar.Get(0)->PutString( aStr );
+}
+
+RTLFUNC(CompatibilityMode)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ bool bEnabled = false;
+ USHORT nCount = rPar.Count();
+ if ( nCount != 1 && nCount != 2 )
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+
+ SbiInstance* pInst = pINST;
+ if( pInst )
+ {
+ if ( nCount == 2 )
+ pInst->EnableCompatibility( rPar.Get(1)->GetBool() );
+
+ bEnabled = pInst->IsCompatibility();
+ }
+ rPar.Get(0)->PutBool( bEnabled );
+}
+
+RTLFUNC(Input)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // 2 parameters needed
+ if ( rPar.Count() < 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ USHORT nByteCount = rPar.Get(1)->GetUShort();
+ INT16 nFileNumber = rPar.Get(2)->GetInteger();
+
+ SbiIoSystem* pIosys = pINST->GetIoSystem();
+ SbiStream* pSbStrm = pIosys->GetStream( nFileNumber );
+ if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_INPUT)) )
+ {
+ StarBASIC::Error( SbERR_BAD_CHANNEL );
+ return;
+ }
+
+ ByteString aByteBuffer;
+ SbError err = pSbStrm->Read( aByteBuffer, nByteCount, true );
+ if( !err )
+ err = pIosys->GetError();
+
+ if( err )
+ {
+ StarBASIC::Error( err );
+ return;
+ }
+ rPar.Get(0)->PutString( String( aByteBuffer, gsl_getSystemTextEncoding() ) );
+}
+
+// #115824
+RTLFUNC(Me)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ SbModule* pActiveModule = pINST->GetActiveModule();
+ SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pActiveModule);
+ SbxVariableRef refVar = rPar.Get(0);
+ if( pClassModuleObject == NULL )
+ {
+ SbObjModule* pMod = PTR_CAST(SbObjModule,pActiveModule);
+ if ( pMod )
+ refVar->PutObject( pMod );
+ else
+ StarBASIC::Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ else
+ refVar->PutObject( pClassModuleObject );
+}
+
diff --git a/basic/source/runtime/props.cxx b/basic/source/runtime/props.cxx
new file mode 100644
index 000000000000..663d12fbcd72
--- /dev/null
+++ b/basic/source/runtime/props.cxx
@@ -0,0 +1,776 @@
+/*************************************************************************
+ *
+ * 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 "runtime.hxx"
+#include "stdobj.hxx"
+#include "rtlproto.hxx"
+#include "errobject.hxx"
+
+
+// Properties und Methoden legen beim Get (bWrite = FALSE) den Returnwert
+// im Element 0 des Argv ab; beim Put (bWrite = TRUE) wird der Wert aus
+// Element 0 gespeichert.
+
+RTLFUNC(Erl)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get( 0 )->PutLong( StarBASIC::GetErl() );
+}
+
+RTLFUNC(Err)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ if( SbiRuntime::isVBAEnabled() )
+ {
+ rPar.Get( 0 )->PutObject( SbxErrObject::getErrObject() );
+ }
+ else
+ {
+ if( bWrite )
+ {
+ INT32 nVal = rPar.Get( 0 )->GetLong();
+ if( nVal <= 65535L )
+ StarBASIC::Error( StarBASIC::GetSfxFromVBError( (USHORT) nVal ) );
+ }
+ else
+ rPar.Get( 0 )->PutLong( StarBASIC::GetVBErrorCode( StarBASIC::GetErrBasic() ) );
+ }
+}
+
+RTLFUNC(False)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutBool( FALSE );
+}
+
+RTLFUNC(Empty)
+{
+ (void)pBasic;
+ (void)bWrite;
+ (void)rPar;
+}
+
+RTLFUNC(Nothing)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // liefert eine leere Objekt-Variable.
+ rPar.Get( 0 )->PutObject( NULL );
+}
+
+RTLFUNC(Null)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ // liefert eine leere Objekt-Variable.
+ rPar.Get( 0 )->PutNull();
+}
+
+RTLFUNC(PI)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get( 0 )->PutDouble( F_PI );
+}
+
+RTLFUNC(True)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get( 0 )->PutBool( TRUE );
+}
+
+RTLFUNC(ATTR_NORMAL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(ATTR_READONLY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(ATTR_HIDDEN)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(ATTR_SYSTEM)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(4);
+}
+RTLFUNC(ATTR_VOLUME)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(8);
+}
+RTLFUNC(ATTR_DIRECTORY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(16);
+}
+RTLFUNC(ATTR_ARCHIVE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(32);
+}
+
+RTLFUNC(V_EMPTY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(V_NULL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(V_INTEGER)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(V_LONG)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(3);
+}
+RTLFUNC(V_SINGLE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(4);
+}
+RTLFUNC(V_DOUBLE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(5);
+}
+RTLFUNC(V_CURRENCY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(6);
+}
+RTLFUNC(V_DATE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(7);
+}
+RTLFUNC(V_STRING)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(8);
+}
+
+RTLFUNC(MB_OK)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(MB_OKCANCEL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(MB_ABORTRETRYIGNORE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(MB_YESNOCANCEL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(3);
+}
+RTLFUNC(MB_YESNO)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(4);
+}
+RTLFUNC(MB_RETRYCANCEL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(5);
+}
+RTLFUNC(MB_ICONSTOP)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(16);
+}
+RTLFUNC(MB_ICONQUESTION)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(32);
+}
+RTLFUNC(MB_ICONEXCLAMATION)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(48);
+}
+RTLFUNC(MB_ICONINFORMATION)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(64);
+}
+RTLFUNC(MB_DEFBUTTON1)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(MB_DEFBUTTON2)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(256);
+}
+RTLFUNC(MB_DEFBUTTON3)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(512);
+}
+RTLFUNC(MB_APPLMODAL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(MB_SYSTEMMODAL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(4096);
+}
+
+RTLFUNC(IDOK)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+
+RTLFUNC(IDCANCEL)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(IDABORT)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(3);
+}
+RTLFUNC(IDRETRY)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(4);
+}
+RTLFUNC(IDYES)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(6);
+}
+RTLFUNC(IDNO)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(7);
+}
+
+RTLFUNC(CF_TEXT)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(CF_BITMAP)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(CF_METAFILEPICT)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(3);
+}
+
+RTLFUNC(TYP_AUTHORFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(7);
+}
+RTLFUNC(TYP_CHAPTERFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(4);
+}
+RTLFUNC(TYP_CONDTXTFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(27);
+}
+RTLFUNC(TYP_DATEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(TYP_DBFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(19);
+}
+RTLFUNC(TYP_DBNAMEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(3);
+}
+RTLFUNC(TYP_DBNEXTSETFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(24);
+}
+RTLFUNC(TYP_DBNUMSETFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(25);
+}
+RTLFUNC(TYP_DBSETNUMBERFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(26);
+}
+RTLFUNC(TYP_DDEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(14);
+}
+RTLFUNC(TYP_DOCINFOFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(18);
+}
+RTLFUNC(TYP_DOCSTATFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(6);
+}
+RTLFUNC(TYP_EXTUSERFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(30);
+}
+RTLFUNC(TYP_FILENAMEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(TYP_FIXDATEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(31);
+}
+RTLFUNC(TYP_FIXTIMEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(32);
+}
+RTLFUNC(TYP_FORMELFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(10);
+}
+RTLFUNC(TYP_GETFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(9);
+}
+RTLFUNC(TYP_GETREFFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(13);
+}
+RTLFUNC(TYP_HIDDENPARAFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(17);
+}
+RTLFUNC(TYP_HIDDENTXTFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(11);
+}
+RTLFUNC(TYP_INPUTFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(16);
+}
+RTLFUNC(TYP_MACROFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(15);
+}
+RTLFUNC(TYP_NEXTPAGEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(28);
+}
+RTLFUNC(TYP_PAGENUMBERFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(5);
+}
+RTLFUNC(TYP_POSTITFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(21);
+}
+RTLFUNC(TYP_PREVPAGEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(29);
+}
+RTLFUNC(TYP_SEQFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(23);
+}
+RTLFUNC(TYP_SETFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(8);
+}
+RTLFUNC(TYP_SETINPFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(33);
+}
+RTLFUNC(TYP_SETREFFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(12);
+}
+RTLFUNC(TYP_TEMPLNAMEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(22);
+}
+RTLFUNC(TYP_TIMEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(TYP_USERFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(20);
+}
+RTLFUNC(TYP_USRINPFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(34);
+}
+RTLFUNC(TYP_SETREFPAGEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(35);
+}
+RTLFUNC(TYP_GETREFPAGEFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(36);
+}
+RTLFUNC(TYP_INTERNETFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(37);
+}
+
+RTLFUNC(SET_ON)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(SET_OFF)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(TOGGLE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+
+RTLFUNC(FRAMEANCHORPAGE)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(FRAMEANCHORPARA)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(14);
+}
+RTLFUNC(FRAMEANCHORCHAR)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(15);
+}
+
+RTLFUNC(CLEAR_ALLTABS)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(CLEAR_TAB)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(SET_TAB)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+
+RTLFUNC(LINEPROP)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(0);
+}
+RTLFUNC(LINE_1)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(1);
+}
+RTLFUNC(LINE_15)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(2);
+}
+RTLFUNC(LINE_2)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(3);
+}
+
+RTLFUNC(TYP_JUMPEDITFLD)
+{
+ (void)pBasic;
+ (void)bWrite;
+
+ rPar.Get(0)->PutInteger(38);
+}
+
+
diff --git a/basic/source/runtime/rtlproto.hxx b/basic/source/runtime/rtlproto.hxx
new file mode 100644
index 000000000000..5437654f69a0
--- /dev/null
+++ b/basic/source/runtime/rtlproto.hxx
@@ -0,0 +1,349 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <basic/sbstar.hxx>
+
+#define RTLFUNC( name ) void SbRtl_##name( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite )
+#define RTLNAME( name ) &SbRtl_##name
+
+typedef void( *RtlCall ) ( StarBASIC* p, SbxArray& rArgs, BOOL bWrite );
+
+// Properties
+
+extern RTLFUNC(Date);
+extern RTLFUNC(Err);
+extern RTLFUNC(Erl);
+extern RTLFUNC(False);
+extern RTLFUNC(Empty);
+extern RTLFUNC(Nothing);
+extern RTLFUNC(Null);
+extern RTLFUNC(True);
+
+extern RTLFUNC(ATTR_NORMAL);
+extern RTLFUNC(ATTR_READONLY);
+extern RTLFUNC(ATTR_HIDDEN);
+extern RTLFUNC(ATTR_SYSTEM);
+extern RTLFUNC(ATTR_VOLUME);
+extern RTLFUNC(ATTR_DIRECTORY);
+extern RTLFUNC(ATTR_ARCHIVE);
+
+extern RTLFUNC(V_EMPTY);
+extern RTLFUNC(V_NULL);
+extern RTLFUNC(V_INTEGER);
+extern RTLFUNC(V_LONG);
+extern RTLFUNC(V_SINGLE);
+extern RTLFUNC(V_DOUBLE);
+extern RTLFUNC(V_CURRENCY);
+extern RTLFUNC(V_DATE);
+extern RTLFUNC(V_STRING);
+
+extern RTLFUNC(MB_OK);
+extern RTLFUNC(MB_OKCANCEL);
+extern RTLFUNC(MB_ABORTRETRYIGNORE);
+extern RTLFUNC(MB_YESNOCANCEL);
+extern RTLFUNC(MB_YESNO);
+extern RTLFUNC(MB_RETRYCANCEL);
+extern RTLFUNC(MB_ICONSTOP);
+extern RTLFUNC(MB_ICONQUESTION);
+extern RTLFUNC(MB_ICONEXCLAMATION);
+extern RTLFUNC(MB_ICONINFORMATION);
+extern RTLFUNC(MB_DEFBUTTON1);
+extern RTLFUNC(MB_DEFBUTTON2);
+extern RTLFUNC(MB_DEFBUTTON3);
+extern RTLFUNC(MB_APPLMODAL);
+extern RTLFUNC(MB_SYSTEMMODAL);
+
+extern RTLFUNC(IDOK);
+extern RTLFUNC(IDCANCEL);
+extern RTLFUNC(IDABORT);
+extern RTLFUNC(IDRETRY);
+extern RTLFUNC(IDYES);
+extern RTLFUNC(IDNO);
+
+extern RTLFUNC(CF_TEXT);
+extern RTLFUNC(CF_BITMAP);
+extern RTLFUNC(CF_METAFILEPICT);
+
+extern RTLFUNC(PI);
+
+extern RTLFUNC(SET_OFF);
+extern RTLFUNC(SET_ON);
+extern RTLFUNC(TOGGLE);
+
+extern RTLFUNC(TYP_AUTHORFLD);
+extern RTLFUNC(TYP_CHAPTERFLD);
+extern RTLFUNC(TYP_CONDTXTFLD);
+extern RTLFUNC(TYP_DATEFLD);
+extern RTLFUNC(TYP_DBFLD);
+extern RTLFUNC(TYP_DBNAMEFLD);
+extern RTLFUNC(TYP_DBNEXTSETFLD);
+extern RTLFUNC(TYP_DBNUMSETFLD);
+extern RTLFUNC(TYP_DBSETNUMBERFLD);
+extern RTLFUNC(TYP_DDEFLD);
+extern RTLFUNC(TYP_DOCINFOFLD);
+extern RTLFUNC(TYP_DOCSTATFLD);
+extern RTLFUNC(TYP_EXTUSERFLD);
+extern RTLFUNC(TYP_FILENAMEFLD);
+extern RTLFUNC(TYP_FIXDATEFLD);
+extern RTLFUNC(TYP_FIXTIMEFLD);
+extern RTLFUNC(TYP_FORMELFLD);
+extern RTLFUNC(TYP_GETFLD);
+extern RTLFUNC(TYP_GETREFFLD);
+extern RTLFUNC(TYP_HIDDENPARAFLD);
+extern RTLFUNC(TYP_HIDDENTXTFLD);
+extern RTLFUNC(TYP_INPUTFLD);
+extern RTLFUNC(TYP_MACROFLD);
+extern RTLFUNC(TYP_NEXTPAGEFLD);
+extern RTLFUNC(TYP_PAGENUMBERFLD);
+extern RTLFUNC(TYP_POSTITFLD);
+extern RTLFUNC(TYP_PREVPAGEFLD);
+extern RTLFUNC(TYP_SEQFLD);
+extern RTLFUNC(TYP_SETFLD);
+extern RTLFUNC(TYP_SETINPFLD);
+extern RTLFUNC(TYP_SETREFFLD);
+extern RTLFUNC(TYP_TEMPLNAMEFLD);
+extern RTLFUNC(TYP_TIMEFLD);
+extern RTLFUNC(TYP_USERFLD);
+extern RTLFUNC(TYP_USRINPFLD);
+extern RTLFUNC(TYP_SETREFPAGEFLD);
+extern RTLFUNC(TYP_GETREFPAGEFLD);
+extern RTLFUNC(TYP_INTERNETFLD);
+extern RTLFUNC(TYP_JUMPEDITFLD);
+
+extern RTLFUNC(FRAMEANCHORPAGE);
+extern RTLFUNC(FRAMEANCHORPARA);
+extern RTLFUNC(FRAMEANCHORCHAR);
+
+extern RTLFUNC(CLEAR_ALLTABS);
+extern RTLFUNC(CLEAR_TAB);
+extern RTLFUNC(SET_TAB);
+
+extern RTLFUNC(LINEPROP);
+extern RTLFUNC(LINE_1);
+extern RTLFUNC(LINE_15);
+extern RTLFUNC(LINE_2);
+
+// Methoden
+
+extern RTLFUNC(CreateObject);
+extern RTLFUNC(Error);
+extern RTLFUNC(Sin);
+extern RTLFUNC(Abs);
+extern RTLFUNC(Asc);
+extern RTLFUNC(Atn);
+extern RTLFUNC(Chr);
+extern RTLFUNC(Cos);
+extern RTLFUNC(CurDir);
+extern RTLFUNC(ChDir); // JSM
+extern RTLFUNC(ChDrive); // JSM
+extern RTLFUNC(FileCopy); // JSM
+extern RTLFUNC(Kill); // JSM
+extern RTLFUNC(MkDir); // JSM
+extern RTLFUNC(RmDir); // JSM
+extern RTLFUNC(SendKeys); // JSM
+extern RTLFUNC(DimArray);
+extern RTLFUNC(Dir);
+extern RTLFUNC(DoEvents);
+extern RTLFUNC(Exp);
+extern RTLFUNC(FileLen);
+extern RTLFUNC(Fix);
+extern RTLFUNC(Hex);
+extern RTLFUNC(Input);
+extern RTLFUNC(InStr);
+extern RTLFUNC(InStrRev);
+extern RTLFUNC(Int);
+extern RTLFUNC(Join);
+extern RTLFUNC(LCase);
+extern RTLFUNC(Left);
+extern RTLFUNC(Log);
+extern RTLFUNC(LTrim);
+extern RTLFUNC(Mid);
+extern RTLFUNC(Oct);
+extern RTLFUNC(Replace);
+extern RTLFUNC(Right);
+extern RTLFUNC(RTrim);
+extern RTLFUNC(RTL);
+extern RTLFUNC(Sgn);
+extern RTLFUNC(Space);
+extern RTLFUNC(Split);
+extern RTLFUNC(Sqr);
+extern RTLFUNC(Str);
+extern RTLFUNC(StrComp);
+extern RTLFUNC(String);
+extern RTLFUNC(StrReverse);
+extern RTLFUNC(Tan);
+extern RTLFUNC(UCase);
+extern RTLFUNC(Val);
+extern RTLFUNC(Len);
+extern RTLFUNC(Spc);
+extern RTLFUNC(DateSerial);
+extern RTLFUNC(TimeSerial);
+extern RTLFUNC(DateValue);
+extern RTLFUNC(TimeValue);
+extern RTLFUNC(Day);
+extern RTLFUNC(Hour);
+extern RTLFUNC(Minute);
+extern RTLFUNC(Month);
+extern RTLFUNC(MonthName);
+extern RTLFUNC(Now);
+extern RTLFUNC(Second);
+extern RTLFUNC(Time);
+extern RTLFUNC(Timer);
+extern RTLFUNC(Weekday);
+extern RTLFUNC(WeekdayName);
+extern RTLFUNC(Year);
+extern RTLFUNC(Date);
+extern RTLFUNC(InputBox);
+extern RTLFUNC(Me);
+extern RTLFUNC(MsgBox);
+extern RTLFUNC(IsArray);
+extern RTLFUNC(IsDate);
+extern RTLFUNC(IsEmpty);
+extern RTLFUNC(IsError);
+extern RTLFUNC(IsNull);
+extern RTLFUNC(IsNumeric);
+extern RTLFUNC(IsObject);
+extern RTLFUNC(IsUnoStruct);
+
+extern RTLFUNC(FileDateTime);
+extern RTLFUNC(Format);
+extern RTLFUNC(GetAttr);
+extern RTLFUNC(Randomize); // JSM
+extern RTLFUNC(Round);
+extern RTLFUNC(Rnd);
+extern RTLFUNC(Shell);
+extern RTLFUNC(VarType);
+extern RTLFUNC(TypeName);
+extern RTLFUNC(TypeLen);
+
+extern RTLFUNC(EOF);
+extern RTLFUNC(FileAttr);
+extern RTLFUNC(Loc);
+extern RTLFUNC(Lof);
+extern RTLFUNC(Seek);
+extern RTLFUNC(SetAttr); // JSM
+extern RTLFUNC(Reset); // JSM
+
+extern RTLFUNC(DDEInitiate);
+extern RTLFUNC(DDETerminate);
+extern RTLFUNC(DDETerminateAll);
+extern RTLFUNC(DDERequest);
+extern RTLFUNC(DDEExecute);
+extern RTLFUNC(DDEPoke);
+
+extern RTLFUNC(FreeFile);
+extern RTLFUNC(IsMissing);
+extern RTLFUNC(LBound);
+extern RTLFUNC(UBound);
+extern RTLFUNC(RGB);
+extern RTLFUNC(QBColor);
+extern RTLFUNC(StrConv);
+
+extern RTLFUNC(Beep);
+
+extern RTLFUNC(Load);
+extern RTLFUNC(Unload);
+extern RTLFUNC(AboutStarBasic);
+extern RTLFUNC(LoadPicture);
+extern RTLFUNC(SavePicture);
+
+extern RTLFUNC(CBool); // JSM
+extern RTLFUNC(CByte); // JSM
+extern RTLFUNC(CCur); // JSM
+extern RTLFUNC(CDate); // JSM
+extern RTLFUNC(CDbl); // JSM
+extern RTLFUNC(CInt); // JSM
+extern RTLFUNC(CLng); // JSM
+extern RTLFUNC(CSng); // JSM
+extern RTLFUNC(CStr); // JSM
+extern RTLFUNC(CVar); // JSM
+extern RTLFUNC(CVErr); // JSM
+
+extern RTLFUNC(Iif); // JSM
+
+extern RTLFUNC(DumpAllObjects);
+
+extern RTLFUNC(GetSystemType);
+extern RTLFUNC(GetGUIType);
+extern RTLFUNC(Red);
+extern RTLFUNC(Green);
+extern RTLFUNC(Blue);
+
+extern RTLFUNC(Switch);
+extern RTLFUNC(Wait);
+//i#64882# add new WaitUntil
+extern RTLFUNC(WaitUntil);
+
+extern RTLFUNC(GetGUIVersion);
+extern RTLFUNC(Choose);
+extern RTLFUNC(Trim);
+
+extern RTLFUNC(DateAdd);
+extern RTLFUNC(DateDiff);
+extern RTLFUNC(DatePart);
+extern RTLFUNC(FormatDateTime);
+extern RTLFUNC(GetSolarVersion);
+extern RTLFUNC(TwipsPerPixelX);
+extern RTLFUNC(TwipsPerPixelY);
+extern RTLFUNC(FreeLibrary);
+extern RTLFUNC(Array);
+extern RTLFUNC(FindObject);
+extern RTLFUNC(FindPropertyObject);
+extern RTLFUNC(EnableReschedule);
+
+extern RTLFUNC(Put);
+extern RTLFUNC(Get);
+extern RTLFUNC(Environ);
+extern RTLFUNC(GetDialogZoomFactorX);
+extern RTLFUNC(GetDialogZoomFactorY);
+extern RTLFUNC(GetSystemTicks);
+extern RTLFUNC(GetPathSeparator);
+extern RTLFUNC(ResolvePath);
+extern RTLFUNC(CreateUnoStruct);
+extern RTLFUNC(CreateUnoService);
+extern RTLFUNC(CreateUnoServiceWithArguments);
+extern RTLFUNC(CreateUnoValue);
+extern RTLFUNC(GetProcessServiceManager);
+extern RTLFUNC(GetDefaultContext);
+extern RTLFUNC(CreatePropertySet);
+extern RTLFUNC(CreateUnoListener);
+extern RTLFUNC(HasUnoInterfaces);
+extern RTLFUNC(EqualUnoObjects);
+extern RTLFUNC(CreateUnoDialog);
+extern RTLFUNC(GlobalScope);
+extern RTLFUNC(FileExists);
+extern RTLFUNC(ConvertToUrl);
+extern RTLFUNC(ConvertFromUrl);
+extern RTLFUNC(CDateToIso);
+extern RTLFUNC(CDateFromIso);
+extern RTLFUNC(CompatibilityMode);
+extern RTLFUNC(CDec);
+
+extern RTLFUNC(Partition); // Fong
+
+extern double Now_Impl();
+extern void Wait_Impl( bool bDurationBased, SbxArray& rPar );
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
new file mode 100755
index 000000000000..1bb6fb82e113
--- /dev/null
+++ b/basic/source/runtime/runtime.cxx
@@ -0,0 +1,1268 @@
+/*************************************************************************
+ *
+ * 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/fsys.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/wldcrd.hxx>
+#include <svl/zforlist.hxx>
+#include <unotools/syslocale.hxx>
+#include "runtime.hxx"
+#include "sbintern.hxx"
+#include "opcodes.hxx"
+#include "codegen.hxx"
+#include "iosys.hxx"
+#include "image.hxx"
+#include "ddectrl.hxx"
+#include "dllmgr.hxx"
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include "sbunoobj.hxx"
+#include "errobject.hxx"
+#include "sbtrace.hxx"
+
+using namespace ::com::sun::star;
+
+bool SbiRuntime::isVBAEnabled()
+{
+ bool result = false;
+ SbiInstance* pInst = pINST;
+ if ( pInst && pINST->pRun )
+ result = pInst->pRun->bVBAEnabled;
+ return result;
+}
+
+// #91147 Global reschedule flag
+static BOOL bStaticGlobalEnableReschedule = TRUE;
+
+void StarBASIC::StaticEnableReschedule( BOOL bReschedule )
+{
+ bStaticGlobalEnableReschedule = bReschedule;
+}
+void StarBASIC::SetVBAEnabled( BOOL bEnabled )
+{
+ if ( bDocBasic )
+ {
+ bVBAEnabled = bEnabled;
+ }
+}
+
+BOOL StarBASIC::isVBAEnabled()
+{
+ if ( bDocBasic )
+ {
+ if( SbiRuntime::isVBAEnabled() )
+ return TRUE;
+ return bVBAEnabled;
+ }
+ return FALSE;
+}
+
+
+struct SbiArgvStack { // Argv stack:
+ SbiArgvStack* pNext; // Stack Chain
+ SbxArrayRef refArgv; // Argv
+ short nArgc; // Argc
+};
+
+SbiRuntime::pStep0 SbiRuntime::aStep0[] = { // Alle Opcodes ohne Operanden
+ &SbiRuntime::StepNOP,
+ &SbiRuntime::StepEXP,
+ &SbiRuntime::StepMUL,
+ &SbiRuntime::StepDIV,
+ &SbiRuntime::StepMOD,
+ &SbiRuntime::StepPLUS,
+ &SbiRuntime::StepMINUS,
+ &SbiRuntime::StepNEG,
+ &SbiRuntime::StepEQ,
+ &SbiRuntime::StepNE,
+ &SbiRuntime::StepLT,
+ &SbiRuntime::StepGT,
+ &SbiRuntime::StepLE,
+ &SbiRuntime::StepGE,
+ &SbiRuntime::StepIDIV,
+ &SbiRuntime::StepAND,
+ &SbiRuntime::StepOR,
+ &SbiRuntime::StepXOR,
+ &SbiRuntime::StepEQV,
+ &SbiRuntime::StepIMP,
+ &SbiRuntime::StepNOT,
+ &SbiRuntime::StepCAT,
+
+ &SbiRuntime::StepLIKE,
+ &SbiRuntime::StepIS,
+ // Laden/speichern
+ &SbiRuntime::StepARGC, // neuen Argv einrichten
+ &SbiRuntime::StepARGV, // TOS ==> aktueller Argv
+ &SbiRuntime::StepINPUT, // Input ==> TOS
+ &SbiRuntime::StepLINPUT, // Line Input ==> TOS
+ &SbiRuntime::StepGET, // TOS anfassen
+ &SbiRuntime::StepSET, // Speichern Objekt TOS ==> TOS-1
+ &SbiRuntime::StepPUT, // TOS ==> TOS-1
+ &SbiRuntime::StepPUTC, // TOS ==> TOS-1, dann ReadOnly
+ &SbiRuntime::StepDIM, // DIM
+ &SbiRuntime::StepREDIM, // REDIM
+ &SbiRuntime::StepREDIMP, // REDIM PRESERVE
+ &SbiRuntime::StepERASE, // TOS loeschen
+ // Verzweigen
+ &SbiRuntime::StepSTOP, // Programmende
+ &SbiRuntime::StepINITFOR, // FOR-Variable initialisieren
+ &SbiRuntime::StepNEXT, // FOR-Variable inkrementieren
+ &SbiRuntime::StepCASE, // Anfang CASE
+ &SbiRuntime::StepENDCASE, // Ende CASE
+ &SbiRuntime::StepSTDERROR, // Standard-Fehlerbehandlung
+ &SbiRuntime::StepNOERROR, // keine Fehlerbehandlung
+ &SbiRuntime::StepLEAVE, // UP verlassen
+ // E/A
+ &SbiRuntime::StepCHANNEL, // TOS = Kanalnummer
+ &SbiRuntime::StepPRINT, // print TOS
+ &SbiRuntime::StepPRINTF, // print TOS in field
+ &SbiRuntime::StepWRITE, // write TOS
+ &SbiRuntime::StepRENAME, // Rename Tos+1 to Tos
+ &SbiRuntime::StepPROMPT, // Input Prompt aus TOS definieren
+ &SbiRuntime::StepRESTART, // Set restart point
+ &SbiRuntime::StepCHANNEL0, // E/A-Kanal 0 einstellen
+ &SbiRuntime::StepEMPTY, // Leeren Ausdruck auf Stack
+ &SbiRuntime::StepERROR, // TOS = Fehlercode
+ &SbiRuntime::StepLSET, // Speichern Objekt TOS ==> TOS-1
+ &SbiRuntime::StepRSET, // Speichern Objekt TOS ==> TOS-1
+ &SbiRuntime::StepREDIMP_ERASE,// Copy array object for REDIMP
+ &SbiRuntime::StepINITFOREACH,// Init for each loop
+ &SbiRuntime::StepVBASET,// vba-like set statement
+ &SbiRuntime::StepERASE_CLEAR,// vba-like set statement
+ &SbiRuntime::StepARRAYACCESS,// access TOS as array
+ &SbiRuntime::StepBYVAL, // access TOS as array
+};
+
+SbiRuntime::pStep1 SbiRuntime::aStep1[] = { // Alle Opcodes mit einem Operanden
+ &SbiRuntime::StepLOADNC, // Laden einer numerischen Konstanten (+ID)
+ &SbiRuntime::StepLOADSC, // Laden einer Stringkonstanten (+ID)
+ &SbiRuntime::StepLOADI, // Immediate Load (+Wert)
+ &SbiRuntime::StepARGN, // Speichern eines named Args in Argv (+StringID)
+ &SbiRuntime::StepPAD, // String auf feste Laenge bringen (+Laenge)
+ // Verzweigungen
+ &SbiRuntime::StepJUMP, // Sprung (+Target)
+ &SbiRuntime::StepJUMPT, // TOS auswerten), bedingter Sprung (+Target)
+ &SbiRuntime::StepJUMPF, // TOS auswerten), bedingter Sprung (+Target)
+ &SbiRuntime::StepONJUMP, // TOS auswerten), Sprung in JUMP-Tabelle (+MaxVal)
+ &SbiRuntime::StepGOSUB, // UP-Aufruf (+Target)
+ &SbiRuntime::StepRETURN, // UP-Return (+0 oder Target)
+ &SbiRuntime::StepTESTFOR, // FOR-Variable testen), inkrementieren (+Endlabel)
+ &SbiRuntime::StepCASETO, // Tos+1 <= Case <= Tos), 2xremove (+Target)
+ &SbiRuntime::StepERRHDL, // Fehler-Handler (+Offset)
+ &SbiRuntime::StepRESUME, // Resume nach Fehlern (+0 or 1 or Label)
+ // E/A
+ &SbiRuntime::StepCLOSE, // (+Kanal/0)
+ &SbiRuntime::StepPRCHAR, // (+char)
+ // Verwaltung
+ &SbiRuntime::StepSETCLASS, // Set + Klassennamen testen (+StringId)
+ &SbiRuntime::StepTESTCLASS, // Check TOS class (+StringId)
+ &SbiRuntime::StepLIB, // Lib fuer Declare-Call (+StringId)
+ &SbiRuntime::StepBASED, // TOS wird um BASE erhoeht, BASE davor gepusht
+ &SbiRuntime::StepARGTYP, // Letzten Parameter in Argv konvertieren (+Typ)
+ &SbiRuntime::StepVBASETCLASS,// vba-like set statement
+};
+
+SbiRuntime::pStep2 SbiRuntime::aStep2[] = {// Alle Opcodes mit zwei Operanden
+ &SbiRuntime::StepRTL, // Laden aus RTL (+StringID+Typ)
+ &SbiRuntime::StepFIND, // Laden (+StringID+Typ)
+ &SbiRuntime::StepELEM, // Laden Element (+StringID+Typ)
+ &SbiRuntime::StepPARAM, // Parameter (+Offset+Typ)
+ // Verzweigen
+ &SbiRuntime::StepCALL, // Declare-Call (+StringID+Typ)
+ &SbiRuntime::StepCALLC, // CDecl-Declare-Call (+StringID+Typ)
+ &SbiRuntime::StepCASEIS, // Case-Test (+Test-Opcode+False-Target)
+ // Verwaltung
+ &SbiRuntime::StepSTMNT, // Beginn eines Statements (+Line+Col)
+ // E/A
+ &SbiRuntime::StepOPEN, // (+SvStreamFlags+Flags)
+ // Objekte
+ &SbiRuntime::StepLOCAL, // Lokale Variable definieren (+StringId+Typ)
+ &SbiRuntime::StepPUBLIC, // Modulglobale Variable (+StringID+Typ)
+ &SbiRuntime::StepGLOBAL, // Globale Variable definieren (+StringID+Typ)
+ &SbiRuntime::StepCREATE, // Objekt kreieren (+StringId+StringId)
+ &SbiRuntime::StepSTATIC, // Statische Variable (+StringId+StringId)
+ &SbiRuntime::StepTCREATE, // User Defined Objekte (+StringId+StringId)
+ &SbiRuntime::StepDCREATE, // Objekt-Array kreieren (+StringID+StringID)
+ &SbiRuntime::StepGLOBAL_P, // Globale Variable definieren, die beim Neustart
+ // von Basic nicht ueberschrieben wird (+StringID+Typ)
+ &SbiRuntime::StepFIND_G, // Sucht globale Variable mit Spezialbehandlung wegen _GLOBAL_P
+ &SbiRuntime::StepDCREATE_REDIMP, // Objekt-Array redimensionieren (+StringID+StringID)
+ &SbiRuntime::StepFIND_CM, // Search inside a class module (CM) to enable global search in time
+ &SbiRuntime::StepPUBLIC_P, // Search inside a class module (CM) to enable global search in time
+ &SbiRuntime::StepFIND_STATIC, // Search inside a class module (CM) to enable global search in time
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+// SbiRTLData //
+//////////////////////////////////////////////////////////////////////////
+
+SbiRTLData::SbiRTLData()
+{
+ pDir = 0;
+ nDirFlags = 0;
+ nCurDirPos = 0;
+ pWildCard = NULL;
+}
+
+SbiRTLData::~SbiRTLData()
+{
+ delete pDir;
+ pDir = 0;
+ delete pWildCard;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// SbiInstance //
+//////////////////////////////////////////////////////////////////////////
+
+// 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out
+// Die Entscheidung, ob StepPoint aufgerufen werden soll, wird anhand des
+// CallLevels getroffen. Angehalten wird, wenn der aktuelle CallLevel <=
+// nBreakCallLvl ist. Der aktuelle CallLevel kann niemals kleiner als 1
+// sein, da er beim Aufruf einer Methode (auch main) inkrementiert wird.
+// Daher bedeutet ein BreakCallLvl von 0, dass das Programm gar nicht
+// angehalten wird.
+// (siehe auch step2.cxx, SbiRuntime::StepSTMNT() )
+
+// Hilfsfunktion, um den BreakCallLevel gemaess der der Debug-Flags zu ermitteln
+void SbiInstance::CalcBreakCallLevel( USHORT nFlags )
+{
+ // Break-Flag wegfiltern
+ nFlags &= ~((USHORT)SbDEBUG_BREAK);
+
+ USHORT nRet;
+ switch( nFlags )
+ {
+ case SbDEBUG_STEPINTO:
+ nRet = nCallLvl + 1; // CallLevel+1 wird auch angehalten
+ break;
+ case SbDEBUG_STEPOVER | SbDEBUG_STEPINTO:
+ nRet = nCallLvl; // Aktueller CallLevel wird angehalten
+ break;
+ case SbDEBUG_STEPOUT:
+ nRet = nCallLvl - 1; // Kleinerer CallLevel wird angehalten
+ break;
+ case SbDEBUG_CONTINUE:
+ // Basic-IDE liefert 0 statt SbDEBUG_CONTINUE, also auch default=continue
+ default:
+ nRet = 0; // CallLevel ist immer >0 -> kein StepPoint
+ }
+ nBreakCallLvl = nRet; // Ergebnis uebernehmen
+}
+
+SbiInstance::SbiInstance( StarBASIC* p )
+{
+ pBasic = p;
+ pNext = NULL;
+ pRun = NULL;
+ pIosys = new SbiIoSystem;
+ pDdeCtrl = new SbiDdeControl;
+ pDllMgr = 0; // on demand
+ pNumberFormatter = 0; // on demand
+ nCallLvl = 0;
+ nBreakCallLvl = 0;
+ nErr =
+ nErl = 0;
+ bReschedule = TRUE;
+ bCompatibility = FALSE;
+}
+
+SbiInstance::~SbiInstance()
+{
+ while( pRun )
+ {
+ SbiRuntime* p = pRun->pNext;
+ delete pRun;
+ pRun = p;
+ }
+ delete pIosys;
+ delete pDdeCtrl;
+ delete pDllMgr;
+ delete pNumberFormatter;
+
+ try
+ {
+ int nSize = ComponentVector.size();
+ if( nSize )
+ {
+ for( int i = nSize - 1 ; i >= 0 ; --i )
+ {
+ Reference< XComponent > xDlgComponent = ComponentVector[i];
+ if( xDlgComponent.is() )
+ xDlgComponent->dispose();
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "SbiInstance::~SbiInstance: caught an exception while disposing the components!" );
+ }
+
+ ComponentVector.clear();
+}
+
+SbiDllMgr* SbiInstance::GetDllMgr()
+{
+ if( !pDllMgr )
+ pDllMgr = new SbiDllMgr;
+ return pDllMgr;
+}
+
+// #39629 NumberFormatter jetzt ueber statische Methode anlegen
+SvNumberFormatter* SbiInstance::GetNumberFormatter()
+{
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ SvtSysLocale aSysLocale;
+ DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat();
+ if( pNumberFormatter )
+ {
+ if( eLangType != meFormatterLangType ||
+ eDate != meFormatterDateFormat )
+ {
+ delete pNumberFormatter;
+ pNumberFormatter = NULL;
+ }
+ }
+ meFormatterLangType = eLangType;
+ meFormatterDateFormat = eDate;
+ if( !pNumberFormatter )
+ PrepareNumberFormatter( pNumberFormatter, nStdDateIdx, nStdTimeIdx, nStdDateTimeIdx,
+ &meFormatterLangType, &meFormatterDateFormat );
+ return pNumberFormatter;
+}
+
+// #39629 NumberFormatter auch statisch anbieten
+void SbiInstance::PrepareNumberFormatter( SvNumberFormatter*& rpNumberFormatter,
+ sal_uInt32 &rnStdDateIdx, sal_uInt32 &rnStdTimeIdx, sal_uInt32 &rnStdDateTimeIdx,
+ LanguageType* peFormatterLangType, DateFormat* peFormatterDateFormat )
+{
+ com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
+ xFactory = comphelper::getProcessServiceFactory();
+
+ LanguageType eLangType;
+ if( peFormatterLangType )
+ eLangType = *peFormatterLangType;
+ else
+ eLangType = GetpApp()->GetSettings().GetLanguage();
+
+ DateFormat eDate;
+ if( peFormatterDateFormat )
+ eDate = *peFormatterDateFormat;
+ else
+ {
+ SvtSysLocale aSysLocale;
+ eDate = aSysLocale.GetLocaleData().getDateFormat();
+ }
+
+ rpNumberFormatter = new SvNumberFormatter( xFactory, eLangType );
+
+ xub_StrLen nCheckPos = 0; short nType;
+ rnStdTimeIdx = rpNumberFormatter->GetStandardFormat( NUMBERFORMAT_TIME, eLangType );
+
+ // Standard-Vorlagen des Formatters haben nur zweistellige
+ // Jahreszahl. Deshalb eigenes Format registrieren
+
+ // HACK, da der Numberformatter in PutandConvertEntry die Platzhalter
+ // fuer Monat, Tag, Jahr nicht entsprechend der Systemeinstellung
+ // austauscht. Problem: Print Year(Date) unter engl. BS
+ // siehe auch svtools\source\sbx\sbxdate.cxx
+
+ String aDateStr;
+ switch( eDate )
+ {
+ case MDY: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("MM.TT.JJJJ") ); break;
+ case DMY: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("TT.MM.JJJJ") ); break;
+ case YMD: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("JJJJ.MM.TT") ); break;
+ default: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("MM.TT.JJJJ") );
+ }
+ String aStr( aDateStr );
+ rpNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
+ rnStdDateIdx, LANGUAGE_GERMAN, eLangType );
+ nCheckPos = 0;
+ String aStrHHMMSS( RTL_CONSTASCII_USTRINGPARAM(" HH:MM:SS") );
+ aStr = aDateStr;
+ aStr += aStrHHMMSS;
+ rpNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
+ rnStdDateTimeIdx, LANGUAGE_GERMAN, eLangType );
+}
+
+
+
+// Engine laufenlassen. Falls Flags == SbDEBUG_CONTINUE, Flags uebernehmen
+
+void SbiInstance::Stop()
+{
+ for( SbiRuntime* p = pRun; p; p = p->pNext )
+ p->Stop();
+}
+
+// Allows Basic IDE to set watch mode to suppress errors
+static bool bWatchMode = false;
+
+void setBasicWatchMode( bool bOn )
+{
+ bWatchMode = bOn;
+}
+
+void SbiInstance::Error( SbError n )
+{
+ Error( n, String() );
+}
+
+void SbiInstance::Error( SbError n, const String& rMsg )
+{
+ if( !bWatchMode )
+ {
+ aErrorMsg = rMsg;
+ pRun->Error( n );
+ }
+}
+
+void SbiInstance::ErrorVB( sal_Int32 nVBNumber, const String& rMsg )
+{
+ if( !bWatchMode )
+ {
+ SbError n = StarBASIC::GetSfxFromVBError( static_cast< USHORT >( nVBNumber ) );
+ if ( !n )
+ n = nVBNumber; // force orig number, probably should have a specific table of vb ( localized ) errors
+
+ aErrorMsg = rMsg;
+ SbiRuntime::translateErrorToVba( n, aErrorMsg );
+
+ bool bVBATranslationAlreadyDone = true;
+ pRun->Error( SbERR_BASIC_COMPAT, bVBATranslationAlreadyDone );
+ }
+}
+
+void SbiInstance::setErrorVB( sal_Int32 nVBNumber, const String& rMsg )
+{
+ SbError n = StarBASIC::GetSfxFromVBError( static_cast< USHORT >( nVBNumber ) );
+ if( !n )
+ n = nVBNumber; // force orig number, probably should have a specific table of vb ( localized ) errors
+
+ aErrorMsg = rMsg;
+ SbiRuntime::translateErrorToVba( n, aErrorMsg );
+
+ nErr = n;
+}
+
+
+void SbiInstance::FatalError( SbError n )
+{
+ pRun->FatalError( n );
+}
+
+void SbiInstance::FatalError( SbError _errCode, const String& _details )
+{
+ pRun->FatalError( _errCode, _details );
+}
+
+void SbiInstance::Abort()
+{
+ // Basic suchen, in dem der Fehler auftrat
+ StarBASIC* pErrBasic = GetCurrentBasic( pBasic );
+ pErrBasic->RTError( nErr, aErrorMsg, pRun->nLine, pRun->nCol1, pRun->nCol2 );
+ pBasic->Stop();
+}
+
+// Hilfsfunktion, um aktives Basic zu finden, kann ungleich pRTBasic sein
+StarBASIC* GetCurrentBasic( StarBASIC* pRTBasic )
+{
+ StarBASIC* pCurBasic = pRTBasic;
+ SbModule* pActiveModule = pRTBasic->GetActiveModule();
+ if( pActiveModule )
+ {
+ SbxObject* pParent = pActiveModule->GetParent();
+ if( pParent && pParent->ISA(StarBASIC) )
+ pCurBasic = (StarBASIC*)pParent;
+ }
+ return pCurBasic;
+}
+
+SbModule* SbiInstance::GetActiveModule()
+{
+ if( pRun )
+ return pRun->GetModule();
+ else
+ return NULL;
+}
+
+SbMethod* SbiInstance::GetCaller( USHORT nLevel )
+{
+ SbiRuntime* p = pRun;
+ while( nLevel-- && p )
+ p = p->pNext;
+ if( p )
+ return p->GetCaller();
+ else
+ return NULL;
+}
+
+SbxArray* SbiInstance::GetLocals( SbMethod* pMeth )
+{
+ SbiRuntime* p = pRun;
+ while( p && p->GetMethod() != pMeth )
+ p = p->pNext;
+ if( p )
+ return p->GetLocals();
+ else
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// SbiInstance //
+//////////////////////////////////////////////////////////////////////////
+
+// Achtung: pMeth kann auch NULL sein (beim Aufruf des Init-Codes)
+
+SbiRuntime::SbiRuntime( SbModule* pm, SbMethod* pe, UINT32 nStart )
+ : rBasic( *(StarBASIC*)pm->pParent ), pInst( pINST ),
+ pMod( pm ), pMeth( pe ), pImg( pMod->pImage ), m_nLastTime(0)
+{
+ nFlags = pe ? pe->GetDebugFlags() : 0;
+ pIosys = pInst->pIosys;
+ pArgvStk = NULL;
+ pGosubStk = NULL;
+ pForStk = NULL;
+ pError = NULL;
+ pErrCode =
+ pErrStmnt =
+ pRestart = NULL;
+ pNext = NULL;
+ pCode =
+ pStmnt = (const BYTE* ) pImg->GetCode() + nStart;
+ bRun =
+ bError = TRUE;
+ bInError = FALSE;
+ bBlocked = FALSE;
+ nLine = 0;
+ nCol1 = 0;
+ nCol2 = 0;
+ nExprLvl = 0;
+ nArgc = 0;
+ nError = 0;
+ nGosubLvl = 0;
+ nForLvl = 0;
+ nOps = 0;
+ refExprStk = new SbxArray;
+ SetVBAEnabled( pMod->IsVBACompat() );
+#if defined GCC
+ SetParameters( pe ? pe->GetParameters() : (class SbxArray *)NULL );
+#else
+ SetParameters( pe ? pe->GetParameters() : NULL );
+#endif
+ pRefSaveList = NULL;
+ pItemStoreList = NULL;
+}
+
+SbiRuntime::~SbiRuntime()
+{
+ ClearGosubStack();
+ ClearArgvStack();
+ ClearForStack();
+
+ // #74254 Items zum Sichern temporaere Referenzen freigeben
+ ClearRefs();
+ while( pItemStoreList )
+ {
+ RefSaveItem* pToDeleteItem = pItemStoreList;
+ pItemStoreList = pToDeleteItem->pNext;
+ delete pToDeleteItem;
+ }
+}
+
+void SbiRuntime::SetVBAEnabled(bool bEnabled )
+{
+ bVBAEnabled = bEnabled;
+}
+
+// Aufbau der Parameterliste. Alle ByRef-Parameter werden direkt
+// uebernommen; von ByVal-Parametern werden Kopien angelegt. Falls
+// ein bestimmter Datentyp verlangt wird, wird konvertiert.
+
+void SbiRuntime::SetParameters( SbxArray* pParams )
+{
+ refParams = new SbxArray;
+ // fuer den Returnwert
+ refParams->Put( pMeth, 0 );
+
+ SbxInfo* pInfo = pMeth ? pMeth->GetInfo() : NULL;
+ USHORT nParamCount = pParams ? pParams->Count() : 1;
+ if( nParamCount > 1 )
+ {
+ for( USHORT i = 1 ; i < nParamCount ; i++ )
+ {
+ const SbxParamInfo* p = pInfo ? pInfo->GetParam( i ) : NULL;
+
+ // #111897 ParamArray
+ if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 )
+ {
+ SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
+ USHORT nParamArrayParamCount = nParamCount - i;
+ pArray->unoAddDim( 0, nParamArrayParamCount - 1 );
+ for( USHORT j = i ; j < nParamCount ; j++ )
+ {
+ SbxVariable* v = pParams->Get( j );
+ short nDimIndex = j - i;
+ pArray->Put( v, &nDimIndex );
+ }
+ SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT );
+ pArrayVar->SetFlag( SBX_READWRITE );
+ pArrayVar->PutObject( pArray );
+ refParams->Put( pArrayVar, i );
+
+ // Block ParamArray for missing parameter
+ pInfo = NULL;
+ break;
+ }
+
+ SbxVariable* v = pParams->Get( i );
+ // Methoden sind immer byval!
+ BOOL bByVal = v->IsA( TYPE(SbxMethod) );
+ SbxDataType t = v->GetType();
+ if( p )
+ {
+ bByVal |= BOOL( ( p->eType & SbxBYREF ) == 0 );
+ t = (SbxDataType) ( p->eType & 0x0FFF );
+
+ if( !bByVal && t != SbxVARIANT &&
+ (!v->IsFixed() || (SbxDataType)(v->GetType() & 0x0FFF ) != t) )
+ bByVal = TRUE;
+ }
+ if( bByVal )
+ {
+ SbxVariable* v2 = new SbxVariable( t );
+ v2->SetFlag( SBX_READWRITE );
+ *v2 = *v;
+ refParams->Put( v2, i );
+ }
+ else
+ {
+ if( t != SbxVARIANT && t != ( v->GetType() & 0x0FFF ) )
+ {
+ // Array konvertieren??
+ if( p && (p->eType & SbxARRAY) )
+ Error( SbERR_CONVERSION );
+ else
+ v->Convert( t );
+ }
+ refParams->Put( v, i );
+ }
+ if( p )
+ refParams->PutAlias( p->aName, i );
+ }
+ }
+
+ // ParamArray for missing parameter
+ if( pInfo )
+ {
+ // #111897 Check first missing parameter for ParamArray
+ const SbxParamInfo* p = pInfo->GetParam( nParamCount );
+ if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 )
+ {
+ SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
+ pArray->unoAddDim( 0, -1 );
+ SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT );
+ pArrayVar->SetFlag( SBX_READWRITE );
+ pArrayVar->PutObject( pArray );
+ refParams->Put( pArrayVar, nParamCount );
+ }
+ }
+}
+
+
+// Einen P-Code ausfuehren
+
+BOOL SbiRuntime::Step()
+{
+ if( bRun )
+ {
+ // Unbedingt gelegentlich die Kontrolle abgeben!
+ if( !( ++nOps & 0xF ) && pInst->IsReschedule() && bStaticGlobalEnableReschedule )
+ {
+ sal_uInt32 nTime = osl_getGlobalTimer();
+ if (nTime - m_nLastTime > 5 ) // 20 ms
+ {
+ Application::Reschedule();
+ m_nLastTime = nTime;
+ }
+ }
+
+ // #i48868 blocked by next call level?
+ while( bBlocked )
+ {
+ if( pInst->IsReschedule() && bStaticGlobalEnableReschedule )
+ Application::Reschedule();
+ }
+
+#ifdef DBG_TRACE_BASIC
+ UINT32 nPC = ( pCode - (const BYTE* )pImg->GetCode() );
+ dbg_traceStep( pMod, nPC, pINST->nCallLvl );
+#endif
+
+ SbiOpcode eOp = (SbiOpcode ) ( *pCode++ );
+ UINT32 nOp1, nOp2;
+ if( eOp <= SbOP0_END )
+ {
+ (this->*( aStep0[ eOp ] ) )();
+ }
+ else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
+ {
+ nOp1 = *pCode++; nOp1 |= *pCode++ << 8; nOp1 |= *pCode++ << 16; nOp1 |= *pCode++ << 24;
+
+ (this->*( aStep1[ eOp - SbOP1_START ] ) )( nOp1 );
+ }
+ else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
+ {
+ nOp1 = *pCode++; nOp1 |= *pCode++ << 8; nOp1 |= *pCode++ << 16; nOp1 |= *pCode++ << 24;
+ nOp2 = *pCode++; nOp2 |= *pCode++ << 8; nOp2 |= *pCode++ << 16; nOp2 |= *pCode++ << 24;
+ (this->*( aStep2[ eOp - SbOP2_START ] ) )( nOp1, nOp2 );
+ }
+ else
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+
+ // SBX-Fehler aufgetreten?
+ SbError nSbError = SbxBase::GetError();
+ Error( ERRCODE_TOERROR(nSbError) ); // Warnings rausfiltern
+
+ // AB 13.2.1997, neues Error-Handling:
+ // ACHTUNG: Hier kann nError auch dann gesetzt sein, wenn !nSbError,
+ // da nError jetzt auch von anderen RT-Instanzen gesetzt werden kann
+
+ if( nError )
+ SbxBase::ResetError();
+
+ // AB,15.3.96: Fehler nur anzeigen, wenn BASIC noch aktiv
+ // (insbesondere nicht nach Compiler-Fehlern zur Laufzeit)
+ if( nError && bRun )
+ {
+#ifdef DBG_TRACE_BASIC
+ SbError nTraceErr = nError;
+ String aTraceErrMsg = GetSbData()->aErrMsg;
+ bool bTraceErrHandled = true;
+#endif
+ SbError err = nError;
+ ClearExprStack();
+ nError = 0;
+ pInst->nErr = err;
+ pInst->nErl = nLine;
+ pErrCode = pCode;
+ pErrStmnt = pStmnt;
+ // An error occured in an error handler
+ // force parent handler ( if there is one )
+ // to handle the error
+ bool bLetParentHandleThis = false;
+
+ // Im Error Handler? Dann Std-Error
+ if ( !bInError )
+ {
+ bInError = TRUE;
+
+ if( !bError ) // On Error Resume Next
+ StepRESUME( 1 );
+ else if( pError ) // On Error Goto ...
+ pCode = pError;
+ else
+ bLetParentHandleThis = true;
+ }
+ else
+ {
+ bLetParentHandleThis = true;
+ pError = NULL; //terminate the handler
+ }
+ if ( bLetParentHandleThis )
+ {
+ // AB 13.2.1997, neues Error-Handling:
+ // Uebergeordnete Error-Handler beruecksichtigen
+
+ // Wir haben keinen Error-Handler -> weiter oben suchen
+ SbiRuntime* pRtErrHdl = NULL;
+ SbiRuntime* pRt = this;
+ while( NULL != (pRt = pRt->pNext) )
+ {
+ // Gibt es einen Error-Handler?
+ if( pRt->bError == FALSE || pRt->pError != NULL )
+ {
+ pRtErrHdl = pRt;
+ break;
+ }
+ }
+
+ // Error-Hdl gefunden?
+ if( pRtErrHdl )
+ {
+ // (Neuen) Error-Stack anlegen
+ SbErrorStack*& rErrStack = GetSbData()->pErrStack;
+ if( rErrStack )
+ delete rErrStack;
+ rErrStack = new SbErrorStack();
+
+ // Alle im Call-Stack darunter stehenden RTs manipulieren
+ pRt = this;
+ do
+ {
+ // Fehler setzen
+ pRt->nError = err;
+ if( pRt != pRtErrHdl )
+ pRt->bRun = FALSE;
+
+ // In Error-Stack eintragen
+ SbErrorStackEntry *pEntry = new SbErrorStackEntry
+ ( pRt->pMeth, pRt->nLine, pRt->nCol1, pRt->nCol2 );
+ rErrStack->C40_INSERT(SbErrorStackEntry, pEntry, rErrStack->Count() );
+
+ // Nach RT mit Error-Handler aufhoeren
+ if( pRt == pRtErrHdl )
+ break;
+ pRt = pRt->pNext;
+ }
+ while( pRt );
+ }
+ // Kein Error-Hdl gefunden -> altes Vorgehen
+ else
+ {
+#ifdef DBG_TRACE_BASIC
+ bTraceErrHandled = false;
+#endif
+ pInst->Abort();
+ }
+
+ // ALT: Nur
+ // pInst->Abort();
+ }
+
+#ifdef DBG_TRACE_BASIC
+ dbg_traceNotifyError( nTraceErr, aTraceErrMsg, bTraceErrHandled, pINST->nCallLvl );
+#endif
+ }
+ }
+ return bRun;
+}
+
+void SbiRuntime::Error( SbError n, bool bVBATranslationAlreadyDone )
+{
+ if( n )
+ {
+ nError = n;
+ if( isVBAEnabled() && !bVBATranslationAlreadyDone )
+ {
+ String aMsg = pInst->GetErrorMsg();
+ sal_Int32 nVBAErrorNumber = translateErrorToVba( nError, aMsg );
+ SbxVariable* pSbxErrObjVar = SbxErrObject::getErrObject();
+ SbxErrObject* pGlobErr = static_cast< SbxErrObject* >( pSbxErrObjVar );
+ if( pGlobErr != NULL )
+ pGlobErr->setNumberAndDescription( nVBAErrorNumber, aMsg );
+
+ pInst->aErrorMsg = aMsg;
+ nError = SbERR_BASIC_COMPAT;
+ }
+ }
+}
+
+void SbiRuntime::Error( SbError _errCode, const String& _details )
+{
+ if ( _errCode )
+ {
+ OSL_ENSURE( pInst->pRun == this, "SbiRuntime::Error: can't propagate the error message details!" );
+ if ( pInst->pRun == this )
+ {
+ pInst->Error( _errCode, _details );
+ OSL_POSTCOND( nError == _errCode, "SbiRuntime::Error: the instance is expecte to propagate the error code back to me!" );
+ }
+ else
+ {
+ nError = _errCode;
+ }
+ }
+}
+
+void SbiRuntime::FatalError( SbError n )
+{
+ StepSTDERROR();
+ Error( n );
+}
+
+void SbiRuntime::FatalError( SbError _errCode, const String& _details )
+{
+ StepSTDERROR();
+ Error( _errCode, _details );
+}
+
+sal_Int32 SbiRuntime::translateErrorToVba( SbError nError, String& rMsg )
+{
+ // If a message is defined use that ( in preference to
+ // the defined one for the error ) NB #TODO
+ // if there is an error defined it more than likely
+ // is not the one you want ( some are the same though )
+ // we really need a new vba compatible error list
+ if ( !rMsg.Len() )
+ {
+ // TEST, has to be vb here always
+#ifdef DBG_UTIL
+ SbError nTmp = StarBASIC::GetSfxFromVBError( (USHORT)nError );
+ DBG_ASSERT( nTmp, "No VB error!" );
+#endif
+
+ StarBASIC::MakeErrorText( nError, rMsg );
+ rMsg = StarBASIC::GetErrorText();
+ if ( !rMsg.Len() ) // no message for err no, need localized resource here
+ rMsg = String( RTL_CONSTASCII_USTRINGPARAM("Internal Object Error:") );
+ }
+ // no num? most likely then it *is* really a vba err
+ USHORT nVBErrorCode = StarBASIC::GetVBErrorCode( nError );
+ sal_Int32 nVBAErrorNumber = ( nVBErrorCode == 0 ) ? nError : nVBErrorCode;
+ return nVBAErrorNumber;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Parameter, Locals, Caller
+//
+//////////////////////////////////////////////////////////////////////////
+
+SbMethod* SbiRuntime::GetCaller()
+{
+ return pMeth;
+}
+
+SbxArray* SbiRuntime::GetLocals()
+{
+ return refLocals;
+}
+
+SbxArray* SbiRuntime::GetParams()
+{
+ return refParams;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Stacks
+//
+//////////////////////////////////////////////////////////////////////////
+
+// Der Expression-Stack steht fuer die laufende Auswertung von Expressions
+// zur Verfuegung.
+
+void SbiRuntime::PushVar( SbxVariable* pVar )
+{
+ if( pVar )
+ refExprStk->Put( pVar, nExprLvl++ );
+}
+
+SbxVariableRef SbiRuntime::PopVar()
+{
+#ifdef DBG_UTIL
+ if( !nExprLvl )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return new SbxVariable;
+ }
+#endif
+ SbxVariableRef xVar = refExprStk->Get( --nExprLvl );
+#ifdef DBG_UTIL
+ if ( xVar->GetName().EqualsAscii( "Cells" ) )
+ DBG_TRACE( "" );
+#endif
+ // Methods halten im 0.Parameter sich selbst, also weghauen
+ if( xVar->IsA( TYPE(SbxMethod) ) )
+ xVar->SetParameters(0);
+ return xVar;
+}
+
+BOOL SbiRuntime::ClearExprStack()
+{
+ // Achtung: Clear() reicht nicht, da Methods geloescht werden muessen
+ while ( nExprLvl )
+ {
+ PopVar();
+ }
+ refExprStk->Clear();
+ return FALSE;
+}
+
+// Variable auf dem Expression-Stack holen, ohne sie zu entfernen
+// n zaehlt ab 0.
+
+SbxVariable* SbiRuntime::GetTOS( short n )
+{
+ n = nExprLvl - n - 1;
+#ifdef DBG_UTIL
+ if( n < 0 )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return new SbxVariable;
+ }
+#endif
+ return refExprStk->Get( (USHORT) n );
+}
+
+// Sicherstellen, dass TOS eine temporaere Variable ist
+
+void SbiRuntime::TOSMakeTemp()
+{
+ SbxVariable* p = refExprStk->Get( nExprLvl - 1 );
+ if( p->GetRefCount() != 1 )
+ {
+ SbxVariable* pNew = new SbxVariable( *p );
+ pNew->SetFlag( SBX_READWRITE );
+ refExprStk->Put( pNew, nExprLvl - 1 );
+ }
+}
+
+// Der GOSUB-Stack nimmt Returnadressen fuer GOSUBs auf
+
+void SbiRuntime::PushGosub( const BYTE* pc )
+{
+ if( ++nGosubLvl > MAXRECURSION )
+ StarBASIC::FatalError( SbERR_STACK_OVERFLOW );
+ SbiGosubStack* p = new SbiGosubStack;
+ p->pCode = pc;
+ p->pNext = pGosubStk;
+ p->nStartForLvl = nForLvl;
+ pGosubStk = p;
+}
+
+void SbiRuntime::PopGosub()
+{
+ if( !pGosubStk )
+ Error( SbERR_NO_GOSUB );
+ else
+ {
+ SbiGosubStack* p = pGosubStk;
+ pCode = p->pCode;
+ pGosubStk = p->pNext;
+ delete p;
+ nGosubLvl--;
+ }
+}
+
+// Entleeren des GOSUB-Stacks
+
+void SbiRuntime::ClearGosubStack()
+{
+ SbiGosubStack* p;
+ while(( p = pGosubStk ) != NULL )
+ pGosubStk = p->pNext, delete p;
+ nGosubLvl = 0;
+}
+
+// Der Argv-Stack nimmt aktuelle Argument-Vektoren auf
+
+void SbiRuntime::PushArgv()
+{
+ SbiArgvStack* p = new SbiArgvStack;
+ p->refArgv = refArgv;
+ p->nArgc = nArgc;
+ nArgc = 1;
+ refArgv.Clear();
+ p->pNext = pArgvStk;
+ pArgvStk = p;
+}
+
+void SbiRuntime::PopArgv()
+{
+ if( pArgvStk )
+ {
+ SbiArgvStack* p = pArgvStk;
+ pArgvStk = p->pNext;
+ refArgv = p->refArgv;
+ nArgc = p->nArgc;
+ delete p;
+ }
+}
+
+// Entleeren des Argv-Stacks
+
+void SbiRuntime::ClearArgvStack()
+{
+ while( pArgvStk )
+ PopArgv();
+}
+
+// Push des For-Stacks. Der Stack hat Inkrement, Ende, Beginn und Variable.
+// Nach Aufbau des Stack-Elements ist der Stack leer.
+
+void SbiRuntime::PushFor()
+{
+ SbiForStack* p = new SbiForStack;
+ p->eForType = FOR_TO;
+ p->pNext = pForStk;
+ pForStk = p;
+ // Der Stack ist wie folgt aufgebaut:
+ p->refInc = PopVar();
+ p->refEnd = PopVar();
+ SbxVariableRef xBgn = PopVar();
+ p->refVar = PopVar();
+ *(p->refVar) = *xBgn;
+ nForLvl++;
+}
+
+void SbiRuntime::PushForEach()
+{
+ SbiForStack* p = new SbiForStack;
+ p->pNext = pForStk;
+ pForStk = p;
+
+ SbxVariableRef xObjVar = PopVar();
+ SbxBase* pObj = xObjVar.Is() ? xObjVar->GetObject() : NULL;
+ if( pObj == NULL )
+ {
+ Error( SbERR_NO_OBJECT );
+ return;
+ }
+
+ bool bError_ = false;
+ BasicCollection* pCollection;
+ SbxDimArray* pArray;
+ SbUnoObject* pUnoObj;
+ if( (pArray = PTR_CAST(SbxDimArray,pObj)) != NULL )
+ {
+ p->eForType = FOR_EACH_ARRAY;
+ p->refEnd = (SbxVariable*)pArray;
+
+ short nDims = pArray->GetDims();
+ p->pArrayLowerBounds = new sal_Int32[nDims];
+ p->pArrayUpperBounds = new sal_Int32[nDims];
+ p->pArrayCurIndices = new sal_Int32[nDims];
+ sal_Int32 lBound, uBound;
+ for( short i = 0 ; i < nDims ; i++ )
+ {
+ pArray->GetDim32( i+1, lBound, uBound );
+ p->pArrayCurIndices[i] = p->pArrayLowerBounds[i] = lBound;
+ p->pArrayUpperBounds[i] = uBound;
+ }
+ }
+ else if( (pCollection = PTR_CAST(BasicCollection,pObj)) != NULL )
+ {
+ p->eForType = FOR_EACH_COLLECTION;
+ p->refEnd = pCollection;
+ p->nCurCollectionIndex = 0;
+ }
+ else if( (pUnoObj = PTR_CAST(SbUnoObject,pObj)) != NULL )
+ {
+ // XEnumerationAccess?
+ Any aAny = pUnoObj->getUnoAny();
+ Reference< XEnumerationAccess > xEnumerationAccess;
+ if( (aAny >>= xEnumerationAccess) )
+ {
+ p->xEnumeration = xEnumerationAccess->createEnumeration();
+ p->eForType = FOR_EACH_XENUMERATION;
+ }
+ else
+ {
+ bError_ = true;
+ }
+ }
+ else
+ {
+ bError_ = true;
+ }
+
+ if( bError_ )
+ {
+ Error( SbERR_CONVERSION );
+ return;
+ }
+
+ // Container variable
+ p->refVar = PopVar();
+ nForLvl++;
+}
+
+// Poppen des FOR-Stacks
+
+void SbiRuntime::PopFor()
+{
+ if( pForStk )
+ {
+ SbiForStack* p = pForStk;
+ pForStk = p->pNext;
+ delete p;
+ nForLvl--;
+ }
+}
+
+// Entleeren des FOR-Stacks
+
+void SbiRuntime::ClearForStack()
+{
+ while( pForStk )
+ PopFor();
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// DLL-Aufrufe
+//
+//////////////////////////////////////////////////////////////////////////
+
+void SbiRuntime::DllCall
+ ( const String& aFuncName, // Funktionsname
+ const String& aDLLName, // Name der DLL
+ SbxArray* pArgs, // Parameter (ab Index 1, kann NULL sein)
+ SbxDataType eResType, // Returnwert
+ BOOL bCDecl ) // TRUE: nach C-Konventionen
+{
+ // No DllCall for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ // MUSS NOCH IMPLEMENTIERT WERDEN
+ /*
+ String aMsg;
+ aMsg = "FUNC=";
+ aMsg += pFunc;
+ aMsg += " DLL=";
+ aMsg += pDLL;
+ MessBox( NULL, WB_OK, String( "DLL-CALL" ), aMsg ).Execute();
+ Error( SbERR_NOT_IMPLEMENTED );
+ */
+
+ SbxVariable* pRes = new SbxVariable( eResType );
+ SbiDllMgr* pDllMgr = pInst->GetDllMgr();
+ SbError nErr = pDllMgr->Call( aFuncName, aDLLName, pArgs, *pRes, bCDecl );
+ if( nErr )
+ Error( nErr );
+ PushVar( pRes );
+}
+USHORT
+SbiRuntime::GetImageFlag( USHORT n ) const
+{
+ return pImg->GetFlag( n );
+}
+USHORT
+SbiRuntime::GetBase()
+{
+ return pImg->GetBase();
+}
diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx
new file mode 100644
index 000000000000..4455901bfeba
--- /dev/null
+++ b/basic/source/runtime/stdobj.cxx
@@ -0,0 +1,788 @@
+/*************************************************************************
+ *
+ * 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 "runtime.hxx"
+#include "stdobj.hxx"
+#include <basic/sbstdobj.hxx>
+#include "rtlproto.hxx"
+#include "sbintern.hxx"
+
+// Das nArgs-Feld eines Tabelleneintrags ist wie folgt verschluesselt:
+// Zur Zeit wird davon ausgegangen, dass Properties keine Parameter
+// benoetigen!
+
+#define _ARGSMASK 0x007F // Bis zu 127 Argumente
+#define _COMPTMASK 0x0080 // Only valid in compatibility mode
+#define _RWMASK 0x0F00 // Maske fuer R/W-Bits
+#define _TYPEMASK 0xF000 // Maske fuer den Typ des Eintrags
+
+#define _READ 0x0100 // kann gelesen werden
+#define _BWRITE 0x0200 // kann as Lvalue verwendet werden
+#define _LVALUE _BWRITE // kann as Lvalue verwendet werden
+#define _READWRITE 0x0300 // beides
+#define _OPT 0x0400 // Parameter ist optional
+#define _CONST 0x0800 // Property ist const
+#define _METHOD 0x3000 // Masken-Bits fuer eine Methode
+#define _PROPERTY 0x4000 // Masken-Bit fuer eine Property
+#define _OBJECT 0x8000 // Masken-Bit fuer ein Objekt
+ // Kombination von oberen Bits:
+#define _FUNCTION 0x1100 // Maske fuer Function
+#define _LFUNCTION 0x1300 // Maske fuer Function, die auch als Lvalue geht
+#define _SUB 0x2100 // Maske fuer Sub
+#define _ROPROP 0x4100 // Maske Read Only-Property
+#define _WOPROP 0x4200 // Maske Write Only-Property
+#define _RWPROP 0x4300 // Maske Read/Write-Property
+#define _CPROP 0x4900 // Maske fuer Konstante
+
+struct Methods {
+ const char* pName; // Name des Eintrags
+ SbxDataType eType; // Datentyp
+ short nArgs; // Argumente und Flags
+ RtlCall pFunc; // Function Pointer
+ USHORT nHash; // Hashcode
+};
+
+static Methods aMethods[] = {
+
+{ "AboutStarBasic", SbxNULL, 1 | _FUNCTION, RTLNAME(AboutStarBasic),0 },
+ { "Name", SbxSTRING, 0,NULL,0 },
+{ "Abs", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Abs),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "Array", SbxOBJECT, _FUNCTION, RTLNAME(Array),0 },
+{ "Asc", SbxLONG, 1 | _FUNCTION, RTLNAME(Asc),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "AscW", SbxLONG, 1 | _FUNCTION | _COMPTMASK, RTLNAME(Asc),0},
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "Atn", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Atn),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "ATTR_ARCHIVE", SbxINTEGER, _CPROP, RTLNAME(ATTR_ARCHIVE),0 },
+{ "ATTR_DIRECTORY", SbxINTEGER, _CPROP, RTLNAME(ATTR_DIRECTORY),0 },
+{ "ATTR_HIDDEN", SbxINTEGER, _CPROP, RTLNAME(ATTR_HIDDEN),0 },
+{ "ATTR_NORMAL", SbxINTEGER, _CPROP, RTLNAME(ATTR_NORMAL),0 },
+{ "ATTR_READONLY", SbxINTEGER, _CPROP, RTLNAME(ATTR_READONLY),0 },
+{ "ATTR_SYSTEM", SbxINTEGER, _CPROP, RTLNAME(ATTR_SYSTEM),0 },
+{ "ATTR_VOLUME", SbxINTEGER, _CPROP, RTLNAME(ATTR_VOLUME),0 },
+
+{ "Beep", SbxNULL, _FUNCTION, RTLNAME(Beep),0 },
+{ "Blue", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Blue),0 },
+ { "RGB-Value", SbxLONG, 0,NULL,0 },
+
+{ "CBool", SbxBOOL, 1 | _FUNCTION, RTLNAME(CBool),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CByte", SbxBYTE, 1 | _FUNCTION, RTLNAME(CByte),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CCur", SbxCURRENCY, 1 | _FUNCTION, RTLNAME(CCur),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CDate", SbxDATE, 1 | _FUNCTION, RTLNAME(CDate),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CDateFromIso", SbxDATE, 1 | _FUNCTION, RTLNAME(CDateFromIso),0 },
+ { "IsoDate", SbxSTRING, 0,NULL,0 },
+{ "CDateToIso", SbxSTRING, 1 | _FUNCTION, RTLNAME(CDateToIso),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+{ "CDec", SbxDECIMAL, 1 | _FUNCTION, RTLNAME(CDec),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CDbl", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(CDbl),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CF_BITMAP", SbxINTEGER, _CPROP, RTLNAME(CF_BITMAP),0 },
+{ "CF_METAFILEPICT",SbxINTEGER, _CPROP, RTLNAME(CF_METAFILEPICT),0 },
+{ "CF_TEXT", SbxINTEGER, _CPROP, RTLNAME(CF_TEXT),0 },
+{ "ChDir", SbxNULL, 1 | _FUNCTION, RTLNAME(ChDir),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "ChDrive", SbxNULL, 1 | _FUNCTION, RTLNAME(ChDrive),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+
+{ "Choose", SbxVARIANT, 2 | _FUNCTION, RTLNAME(Choose),0 },
+ { "Index", SbxINTEGER, 0,NULL,0 },
+ { "Expression", SbxVARIANT, 0,NULL,0 },
+
+{ "Chr", SbxSTRING, 1 | _FUNCTION, RTLNAME(Chr),0 },
+ { "string", SbxINTEGER, 0,NULL,0 },
+{ "ChrW", SbxSTRING, 1 | _FUNCTION | _COMPTMASK, RTLNAME(Chr),0},
+ { "string", SbxINTEGER, 0,NULL,0 },
+
+{ "CInt", SbxINTEGER, 1 | _FUNCTION, RTLNAME(CInt),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CLEAR_ALLTABS", SbxINTEGER, _CPROP, RTLNAME(CLEAR_ALLTABS),0 },
+{ "CLEAR_TAB", SbxINTEGER, _CPROP, RTLNAME(CLEAR_TAB),0 },
+{ "CLng", SbxLONG, 1 | _FUNCTION, RTLNAME(CLng),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CompatibilityMode", SbxBOOL, 1 | _FUNCTION, RTLNAME(CompatibilityMode),0},
+ { "bEnable", SbxBOOL, 0,NULL,0 },
+{ "ConvertFromUrl", SbxSTRING, 1 | _FUNCTION, RTLNAME(ConvertFromUrl),0 },
+ { "Url", SbxSTRING, 0,NULL,0 },
+{ "ConvertToUrl", SbxSTRING, 1 | _FUNCTION, RTLNAME(ConvertToUrl),0 },
+ { "SystemPath", SbxSTRING, 0,NULL,0 },
+{ "Cos", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Cos),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "CreateObject", SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateObject ),0 },
+ { "class", SbxSTRING, 0,NULL,0 },
+{ "CreateUnoListener",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoListener ),0 },
+ { "prefix", SbxSTRING, 0,NULL,0 },
+ { "typename", SbxSTRING, 0,NULL,0 },
+{ "CreateUnoDialog",SbxOBJECT, 2 | _FUNCTION, RTLNAME( CreateUnoDialog ),0 },
+ { "dialoglibrary",SbxOBJECT, 0,NULL,0 },
+ { "dialogname", SbxSTRING, 0,NULL,0 },
+{ "CreateUnoService",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoService ),0 },
+ { "servicename", SbxSTRING, 0,NULL,0 },
+{ "CreateUnoServiceWithArguments",SbxOBJECT, 2 | _FUNCTION, RTLNAME( CreateUnoServiceWithArguments ),0 },
+ { "servicename", SbxSTRING, 0,NULL,0 },
+ { "arguments", SbxARRAY, 0,NULL,0 },
+{ "CreateUnoStruct",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoStruct ),0 },
+ { "classname", SbxSTRING, 0,NULL,0 },
+{ "CreateUnoValue", SbxOBJECT, 2 | _FUNCTION, RTLNAME( CreateUnoValue ),0 },
+ { "type", SbxSTRING, 0,NULL,0 },
+ { "value", SbxVARIANT, 0,NULL,0 },
+{ "CreatePropertySet",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreatePropertySet ),0 },
+ { "values", SbxARRAY, 0,NULL,0 },
+{ "CSng", SbxSINGLE, 1 | _FUNCTION, RTLNAME(CSng),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CStr", SbxSTRING, 1 | _FUNCTION, RTLNAME(CStr),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CurDir", SbxSTRING, 1 | _FUNCTION, RTLNAME(CurDir),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "CVar", SbxVARIANT, 1 | _FUNCTION, RTLNAME(CVar),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+{ "CVErr", SbxVARIANT, 1 | _FUNCTION, RTLNAME(CVErr),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+
+{ "Date", SbxDATE, _LFUNCTION,RTLNAME(Date),0 },
+{ "DateAdd", SbxDATE, 3 | _FUNCTION, RTLNAME(DateAdd),0 },
+ { "Interval", SbxSTRING, 0,NULL,0 },
+ { "Number", SbxLONG, 0,NULL,0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+{ "DateDiff", SbxDOUBLE, 5 | _FUNCTION, RTLNAME(DateDiff),0 },
+ { "Interval", SbxSTRING, 0,NULL,0 },
+ { "Date1", SbxDATE, 0,NULL,0 },
+ { "Date2", SbxDATE, 0,NULL,0 },
+ { "Firstdayofweek" , SbxINTEGER, _OPT,NULL,0 },
+ { "Firstweekofyear", SbxINTEGER, _OPT,NULL,0 },
+{ "DatePart", SbxLONG, 4 | _FUNCTION, RTLNAME(DatePart),0 },
+ { "Interval", SbxSTRING, 0,NULL,0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+ { "Firstdayofweek" , SbxINTEGER, _OPT, NULL,0 },
+ { "Firstweekofyear", SbxINTEGER, _OPT, NULL,0 },
+{ "DateSerial", SbxDATE, 3 | _FUNCTION, RTLNAME(DateSerial),0 },
+ { "Year", SbxINTEGER, 0,NULL,0 },
+ { "Month", SbxINTEGER, 0,NULL,0 },
+ { "Day", SbxINTEGER, 0,NULL,0 },
+{ "DateValue", SbxDATE, 1 | _FUNCTION, RTLNAME(DateValue),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+{ "Day", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Day),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+{ "Ddeexecute", SbxNULL, 2 | _FUNCTION, RTLNAME(DDEExecute),0 },
+ { "Channel", SbxLONG, 0,NULL,0 },
+ { "Command", SbxSTRING, 0,NULL,0 },
+{ "Ddeinitiate", SbxINTEGER, 2 | _FUNCTION, RTLNAME(DDEInitiate),0 },
+ { "Application", SbxSTRING, 0,NULL,0 },
+ { "Topic", SbxSTRING, 0,NULL,0 },
+{ "Ddepoke", SbxNULL, 3 | _FUNCTION, RTLNAME(DDEPoke),0 },
+ { "Channel", SbxLONG, 0,NULL,0 },
+ { "Item", SbxSTRING, 0,NULL,0 },
+ { "Data", SbxSTRING, 0,NULL,0 },
+{ "Dderequest", SbxSTRING, 2 | _FUNCTION, RTLNAME(DDERequest),0 },
+ { "Channel", SbxLONG, 0,NULL,0 },
+ { "Item", SbxSTRING, 0,NULL,0 },
+{ "Ddeterminate", SbxNULL, 1 | _FUNCTION, RTLNAME(DDETerminate),0 },
+ { "Channel", SbxLONG, 0,NULL,0 },
+{ "Ddeterminateall", SbxNULL, _FUNCTION, RTLNAME(DDETerminateAll),0 },
+{ "DimArray", SbxOBJECT, _FUNCTION, RTLNAME(DimArray),0 },
+{ "Dir", SbxSTRING, 2 | _FUNCTION, RTLNAME(Dir),0 },
+ { "FileSpec", SbxSTRING, _OPT, NULL,0 },
+ { "attrmask", SbxINTEGER, _OPT, NULL,0 },
+{ "DoEvents", SbxEMPTY, _FUNCTION, RTLNAME(DoEvents),0 },
+{ "DumpAllObjects", SbxEMPTY, 2 | _SUB, RTLNAME(DumpAllObjects),0 },
+ { "FileSpec", SbxSTRING, 0,NULL,0 },
+ { "DumpAll", SbxINTEGER, _OPT, NULL,0 },
+
+{ "Empty", SbxVARIANT, _CPROP, RTLNAME(Empty),0 },
+{ "EqualUnoObjects",SbxBOOL, 2 | _FUNCTION, RTLNAME(EqualUnoObjects),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "EnableReschedule", SbxNULL, 1 | _FUNCTION, RTLNAME(EnableReschedule),0},
+ { "bEnable", SbxBOOL, 0,NULL,0 },
+{ "Environ", SbxSTRING, 1 | _FUNCTION, RTLNAME(Environ),0 },
+ { "Environmentstring",SbxSTRING, 0,NULL,0 },
+{ "EOF", SbxBOOL, 1 | _FUNCTION, RTLNAME(EOF),0 },
+ { "Channel", SbxINTEGER, 0,NULL,0 },
+{ "Erl", SbxLONG, _ROPROP, RTLNAME( Erl ),0 },
+{ "Err", SbxVARIANT, _RWPROP, RTLNAME( Err ),0 },
+{ "Error", SbxSTRING, 1 | _FUNCTION, RTLNAME( Error ),0 },
+ { "code", SbxLONG, 0,NULL,0 },
+{ "Exp", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Exp),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+
+{ "False", SbxBOOL, _CPROP, RTLNAME(False),0 },
+{ "FileAttr", SbxINTEGER, 2 | _FUNCTION, RTLNAME(FileAttr),0 },
+ { "Channel", SbxINTEGER, 0,NULL,0 },
+ { "Attributes", SbxINTEGER, 0,NULL,0 },
+{ "FileCopy", SbxNULL, 2 | _FUNCTION, RTLNAME(FileCopy),0 },
+ { "Source", SbxSTRING, 0,NULL,0 },
+ { "Destination", SbxSTRING, 0,NULL,0 },
+{ "FileDateTime", SbxSTRING, 1 | _FUNCTION, RTLNAME(FileDateTime),0 },
+ { "filename", SbxSTRING, 0,NULL,0 },
+{ "FileExists", SbxBOOL, 1 | _FUNCTION, RTLNAME(FileExists),0 },
+ { "filename", SbxSTRING, 0,NULL,0 },
+{ "FileLen", SbxLONG, 1 | _FUNCTION, RTLNAME(FileLen),0 },
+ { "filename", SbxSTRING, 0,NULL,0 },
+{ "FindObject", SbxOBJECT, 1 | _FUNCTION, RTLNAME(FindObject),0 },
+ { "Name", SbxSTRING, 0,NULL,0 },
+{ "FindPropertyObject", SbxOBJECT, 2 | _FUNCTION, RTLNAME(FindPropertyObject),0 },
+ { "Object", SbxOBJECT, 0,NULL,0 },
+ { "Name", SbxSTRING, 0,NULL,0 },
+{ "Fix", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Fix),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "Format", SbxSTRING, 2 | _FUNCTION, RTLNAME(Format),0 },
+ { "expression", SbxVARIANT, 0,NULL,0 },
+ { "format", SbxSTRING, _OPT, NULL,0 },
+{ "FormatDateTime", SbxSTRING, 2 | _FUNCTION | _COMPTMASK, RTLNAME(FormatDateTime),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+ { "NamedFormat", SbxINTEGER, _OPT, NULL,0 },
+{ "FRAMEANCHORCHAR", SbxINTEGER, _CPROP, RTLNAME(FRAMEANCHORCHAR),0 },
+{ "FRAMEANCHORPAGE", SbxINTEGER, _CPROP, RTLNAME(FRAMEANCHORPAGE),0 },
+{ "FRAMEANCHORPARA", SbxINTEGER, _CPROP, RTLNAME(FRAMEANCHORPARA),0 },
+{ "FreeFile", SbxINTEGER, _FUNCTION, RTLNAME(FreeFile),0 },
+{ "FreeLibrary", SbxNULL, 1 | _FUNCTION, RTLNAME(FreeLibrary),0 },
+ { "Modulename", SbxSTRING, 0,NULL,0 },
+
+{ "Get", SbxNULL, 3 | _FUNCTION, RTLNAME(Get),0 },
+ { "filenumber", SbxINTEGER, 0,NULL,0 },
+ { "recordnumber", SbxLONG, 0,NULL,0 },
+ { "variablename", SbxVARIANT, 0,NULL,0 },
+{ "GetAttr", SbxINTEGER, 1 | _FUNCTION, RTLNAME(GetAttr),0 },
+ { "filename", SbxSTRING, 0,NULL,0 },
+{ "GetDefaultContext", SbxOBJECT, 0 | _FUNCTION, RTLNAME(GetDefaultContext),0 },
+{ "GetDialogZoomFactorX", SbxDOUBLE, _FUNCTION,RTLNAME(GetDialogZoomFactorX),0 },
+{ "GetDialogZoomFactorY", SbxDOUBLE, _FUNCTION,RTLNAME(GetDialogZoomFactorY),0 },
+{ "GetGUIType", SbxINTEGER, _FUNCTION,RTLNAME(GetGUIType),0 },
+{ "GetGUIVersion", SbxLONG, _FUNCTION,RTLNAME(GetGUIVersion),0 },
+{ "GetPathSeparator", SbxSTRING, _FUNCTION,RTLNAME(GetPathSeparator),0 },
+{ "GetProcessServiceManager", SbxOBJECT, 0 | _FUNCTION, RTLNAME(GetProcessServiceManager),0 },
+{ "GetSolarVersion", SbxLONG, _FUNCTION,RTLNAME(GetSolarVersion),0 },
+{ "GetSystemTicks", SbxLONG, _FUNCTION,RTLNAME(GetSystemTicks),0 },
+{ "GetSystemType", SbxINTEGER, _FUNCTION,RTLNAME(GetSystemType),0 },
+{ "GlobalScope", SbxOBJECT, _FUNCTION,RTLNAME(GlobalScope),0 },
+{ "Green", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Green),0 },
+ { "RGB-Value", SbxLONG, 0,NULL,0 },
+
+{ "HasUnoInterfaces", SbxBOOL, 1 | _FUNCTION, RTLNAME(HasUnoInterfaces),0},
+ { "InterfaceName",SbxSTRING, 0,NULL,0 },
+{ "Hex", SbxSTRING, 1 | _FUNCTION, RTLNAME(Hex),0 },
+ { "number", SbxLONG, 0,NULL,0 },
+{ "Hour", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Hour),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+
+{ "IDABORT", SbxINTEGER, _CPROP, RTLNAME(IDABORT),0 },
+{ "IDCANCEL", SbxINTEGER, _CPROP, RTLNAME(IDCANCEL),0 },
+{ "IDNO", SbxINTEGER, _CPROP, RTLNAME(IDNO),0 },
+{ "IDOK", SbxINTEGER, _CPROP, RTLNAME(IDOK),0 },
+{ "IDRETRY", SbxINTEGER, _CPROP, RTLNAME(IDRETRY),0 },
+{ "IDYES", SbxINTEGER, _CPROP, RTLNAME(IDYES),0 },
+
+{ "Iif", SbxVARIANT, 3 | _FUNCTION, RTLNAME(Iif),0 },
+ { "Bool", SbxBOOL, 0,NULL,0 },
+ { "Variant1", SbxVARIANT, 0,NULL,0 },
+ { "Variant2", SbxVARIANT, 0,NULL,0 },
+
+{ "Input", SbxSTRING, 2 | _FUNCTION | _COMPTMASK, RTLNAME(Input),0},
+ { "Number", SbxLONG, 0,NULL,0 },
+ { "FileNumber", SbxLONG, 0,NULL,0 },
+{ "InputBox", SbxSTRING, 5 | _FUNCTION, RTLNAME(InputBox),0 },
+ { "Prompt", SbxSTRING, 0,NULL,0 },
+ { "Title", SbxSTRING, _OPT, NULL,0 },
+ { "Default", SbxSTRING, _OPT, NULL,0 },
+ { "XPosTwips", SbxLONG, _OPT, NULL,0 },
+ { "YPosTwips", SbxLONG, _OPT, NULL,0 },
+{ "InStr", SbxLONG, 4 | _FUNCTION, RTLNAME(InStr),0 },
+ { "Start", SbxSTRING, _OPT, NULL,0 },
+ { "String1", SbxSTRING, 0,NULL,0 },
+ { "String2", SbxSTRING, 0,NULL,0 },
+ { "Compare", SbxINTEGER, _OPT, NULL,0 },
+{ "InStrRev", SbxLONG, 4 | _FUNCTION | _COMPTMASK, RTLNAME(InStrRev),0},
+ { "String1", SbxSTRING, 0,NULL,0 },
+ { "String2", SbxSTRING, 0,NULL,0 },
+ { "Start", SbxSTRING, _OPT, NULL,0 },
+ { "Compare", SbxINTEGER, _OPT, NULL,0 },
+{ "Int", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Int),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "IsArray", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsArray),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsDate", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsDate),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsEmpty", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsEmpty),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsError", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsError),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsMissing", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsMissing),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsNull", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsNull),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsNumeric", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsNumeric),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsObject", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsObject),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "IsUnoStruct", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsUnoStruct),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "Join", SbxSTRING, 2 | _FUNCTION, RTLNAME(Join),0 },
+ { "list", SbxOBJECT, 0,NULL,0 },
+ { "delimiter", SbxSTRING, 0,NULL,0 },
+{ "Kill", SbxNULL, 1 | _FUNCTION, RTLNAME(Kill),0 },
+ { "filespec", SbxSTRING, 0,NULL,0 },
+{ "LBound", SbxLONG, 1 | _FUNCTION, RTLNAME(LBound),0 },
+ { "Variant", SbxVARIANT, 0,NULL,0 },
+{ "LCase", SbxSTRING, 1 | _FUNCTION, RTLNAME(LCase),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "Left", SbxSTRING, 2 | _FUNCTION, RTLNAME(Left),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+ { "Count", SbxLONG, 0,NULL,0 },
+{ "Len", SbxLONG, 1 | _FUNCTION, RTLNAME(Len),0 },
+ { "StringOrVariant", SbxVARIANT, 0,NULL,0 },
+{ "LenB", SbxLONG, 1 | _FUNCTION, RTLNAME(Len),0 },
+ { "StringOrVariant", SbxVARIANT, 0,NULL,0 },
+{ "Load", SbxNULL, 1 | _FUNCTION, RTLNAME(Load),0 },
+ { "object", SbxOBJECT, 0,NULL,0 },
+{ "LoadPicture", SbxOBJECT, 1 | _FUNCTION, RTLNAME(LoadPicture),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "Loc", SbxLONG, 1 | _FUNCTION, RTLNAME(Loc),0 },
+ { "Channel", SbxINTEGER, 0,NULL,0 },
+{ "Lof", SbxLONG, 1 | _FUNCTION, RTLNAME(Lof),0 },
+ { "Channel", SbxINTEGER, 0,NULL,0 },
+{ "Log", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Log),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "LTrim", SbxSTRING, 1 | _FUNCTION, RTLNAME(LTrim),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+
+{ "MB_ABORTRETRYIGNORE", SbxINTEGER, _CPROP, RTLNAME(MB_ABORTRETRYIGNORE),0},
+{ "MB_APPLMODAL", SbxINTEGER, _CPROP, RTLNAME(MB_APPLMODAL),0 },
+{ "MB_DEFBUTTON1", SbxINTEGER, _CPROP, RTLNAME(MB_DEFBUTTON1),0 },
+{ "MB_DEFBUTTON2", SbxINTEGER, _CPROP, RTLNAME(MB_DEFBUTTON2),0 },
+{ "MB_DEFBUTTON3", SbxINTEGER, _CPROP, RTLNAME(MB_DEFBUTTON3),0 },
+{ "MB_ICONEXCLAMATION", SbxINTEGER, _CPROP, RTLNAME(MB_ICONEXCLAMATION),0},
+{ "MB_ICONINFORMATION", SbxINTEGER, _CPROP, RTLNAME(MB_ICONINFORMATION),0},
+{ "MB_ICONQUESTION",SbxINTEGER, _CPROP, RTLNAME(MB_ICONQUESTION),0 },
+{ "MB_ICONSTOP", SbxINTEGER, _CPROP, RTLNAME(MB_ICONSTOP),0 },
+{ "MB_OK", SbxINTEGER, _CPROP, RTLNAME(MB_OK),0 },
+{ "MB_OKCANCEL", SbxINTEGER, _CPROP, RTLNAME(MB_OKCANCEL),0 },
+{ "MB_RETRYCANCEL", SbxINTEGER, _CPROP, RTLNAME(MB_RETRYCANCEL),0 },
+{ "MB_SYSTEMMODAL", SbxINTEGER, _CPROP, RTLNAME(MB_SYSTEMMODAL),0 },
+{ "MB_YESNO", SbxINTEGER, _CPROP, RTLNAME(MB_YESNO),0 },
+{ "MB_YESNOCANCEL", SbxINTEGER, _CPROP, RTLNAME(MB_YESNOCANCEL),0 },
+
+{ "Me", SbxOBJECT, 0 | _FUNCTION | _COMPTMASK, RTLNAME(Me),0 },
+{ "Mid", SbxSTRING, 3 | _LFUNCTION,RTLNAME(Mid),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+ { "StartPos", SbxLONG, 0,NULL,0 },
+ { "Length", SbxLONG, _OPT, NULL,0 },
+{ "Minute", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Minute),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+{ "MkDir", SbxNULL, 1 | _FUNCTION, RTLNAME(MkDir),0 },
+ { "pathname", SbxSTRING, 0,NULL,0 },
+{ "Month", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Month),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+{ "MonthName", SbxSTRING, 2 | _FUNCTION | _COMPTMASK, RTLNAME(MonthName),0 },
+ { "Month", SbxINTEGER, 0,NULL,0 },
+ { "Abbreviate", SbxBOOL, _OPT, NULL,0 },
+{ "MsgBox", SbxINTEGER, 5 | _FUNCTION, RTLNAME(MsgBox),0 },
+ { "Prompt", SbxSTRING, 0,NULL,0 },
+ { "Buttons", SbxINTEGER, _OPT, NULL,0 },
+ { "Title", SbxSTRING, _OPT, NULL,0 },
+ { "Helpfile", SbxSTRING, _OPT, NULL,0 },
+ { "Context", SbxINTEGER, _OPT, NULL,0 },
+
+{ "Nothing", SbxOBJECT, _CPROP, RTLNAME(Nothing),0 },
+{ "Now", SbxDATE, _FUNCTION, RTLNAME(Now),0 },
+{ "Null", SbxNULL, _CPROP, RTLNAME(Null),0 },
+
+{ "Oct", SbxSTRING, 1 | _FUNCTION, RTLNAME(Oct),0 },
+ { "number", SbxLONG, 0,NULL,0 },
+
+{ "Partition", SbxSTRING, 4 | _FUNCTION, RTLNAME(Partition),0 },
+ { "number", SbxLONG, 0,NULL,0 },
+ { "start", SbxLONG, 0,NULL,0 },
+ { "stop", SbxLONG, 0,NULL,0 },
+ { "interval", SbxLONG, 0,NULL,0 },
+{ "Pi", SbxDOUBLE, _CPROP, RTLNAME(PI),0 },
+{ "Put", SbxNULL, 3 | _FUNCTION, RTLNAME(Put),0 },
+ { "filenumber", SbxINTEGER, 0,NULL,0 },
+ { "recordnumber", SbxLONG, 0,NULL,0 },
+ { "variablename", SbxVARIANT, 0,NULL,0 },
+
+{ "QBColor", SbxLONG, 1 | _FUNCTION, RTLNAME(QBColor),0 },
+ { "number", SbxINTEGER, 0,NULL,0 },
+
+{ "Randomize", SbxNULL, 1 | _FUNCTION, RTLNAME(Randomize),0 },
+ { "Number", SbxDOUBLE, _OPT, NULL,0 },
+{ "Red", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Red),0 },
+ { "RGB-Value", SbxLONG, 0,NULL,0 },
+{ "Reset", SbxNULL, 0 | _FUNCTION, RTLNAME(Reset),0 },
+{ "ResolvePath", SbxSTRING, 1 | _FUNCTION, RTLNAME(ResolvePath),0 },
+ { "Path", SbxSTRING, 0,NULL,0 },
+{ "RGB", SbxLONG, 3 | _FUNCTION, RTLNAME(RGB),0 },
+ { "Red", SbxINTEGER, 0,NULL,0 },
+ { "Green", SbxINTEGER, 0,NULL,0 },
+ { "Blue", SbxINTEGER, 0,NULL,0 },
+{ "Replace", SbxSTRING, 6 | _FUNCTION, RTLNAME(Replace),0 },
+ { "Expression", SbxSTRING, 0,NULL,0 },
+ { "Find", SbxSTRING, 0,NULL,0 },
+ { "Replace", SbxSTRING, 0,NULL,0 },
+ { "Start", SbxINTEGER, _OPT, NULL,0 },
+ { "Count", SbxINTEGER, _OPT, NULL,0 },
+ { "Compare", SbxINTEGER, _OPT, NULL,0 },
+{ "Right", SbxSTRING, 2 | _FUNCTION, RTLNAME(Right),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+ { "Count", SbxLONG, 0,NULL,0 },
+{ "RmDir", SbxNULL, 1 | _FUNCTION, RTLNAME(RmDir),0 },
+ { "pathname", SbxSTRING, 0,NULL,0 },
+{ "Round", SbxDOUBLE, 2 | _FUNCTION | _COMPTMASK, RTLNAME(Round),0},
+ { "Expression", SbxDOUBLE, 0,NULL,0 },
+ { "Numdecimalplaces", SbxINTEGER, _OPT, NULL,0 },
+{ "Rnd", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Rnd),0 },
+ { "Number", SbxDOUBLE, _OPT, NULL,0 },
+{ "RTL", SbxOBJECT, 0 | _FUNCTION | _COMPTMASK, RTLNAME(RTL),0},
+{ "RTrim", SbxSTRING, 1 | _FUNCTION, RTLNAME(RTrim),0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+
+{ "SavePicture", SbxNULL, 2 | _FUNCTION, RTLNAME(SavePicture),0 },
+ { "object", SbxOBJECT, 0,NULL,0 },
+ { "string", SbxSTRING, 0,NULL,0 },
+{ "Second", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Second),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+{ "Seek", SbxLONG, 1 | _FUNCTION, RTLNAME(Seek),0 },
+ { "Channel", SbxINTEGER, 0,NULL,0 },
+{ "SendKeys", SbxNULL, 2 | _FUNCTION, RTLNAME(SendKeys),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+ { "Wait", SbxBOOL, _OPT, NULL,0 },
+{ "SetAttr", SbxNULL, 2 | _FUNCTION, RTLNAME(SetAttr),0 },
+ { "File" , SbxSTRING, 0,NULL,0 },
+ { "Attributes", SbxINTEGER, 0,NULL,0 },
+{ "SET_OFF", SbxINTEGER, _CPROP, RTLNAME(SET_OFF),0 },
+{ "SET_ON", SbxINTEGER, _CPROP, RTLNAME(SET_ON),0 },
+{ "SET_TAB", SbxINTEGER, _CPROP, RTLNAME(SET_TAB),0 },
+{ "Sgn", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Sgn),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "Shell", SbxLONG, 2 | _FUNCTION, RTLNAME(Shell),0 },
+ { "Commandstring",SbxSTRING, 0,NULL,0 },
+ { "WindowStyle", SbxINTEGER, _OPT, NULL,0 },
+{ "Sin", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Sin),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "Space", SbxSTRING, 1 | _FUNCTION, RTLNAME(Space),0 },
+ { "string", SbxLONG, 0,NULL,0 },
+{ "Spc", SbxSTRING, 1 | _FUNCTION, RTLNAME(Spc),0 },
+ { "Count", SbxLONG, 0,NULL,0 },
+{ "Split", SbxOBJECT, 3 | _FUNCTION, RTLNAME(Split),0 },
+ { "expression", SbxSTRING, 0,NULL,0 },
+ { "delimiter", SbxSTRING, 0,NULL,0 },
+ { "count", SbxLONG, 0,NULL,0 },
+{ "Sqr", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Sqr),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "Str", SbxSTRING, 1 | _FUNCTION, RTLNAME(Str),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "StrComp", SbxINTEGER, 3 | _FUNCTION, RTLNAME(StrComp),0 },
+ { "String1", SbxSTRING, 0,NULL,0 },
+ { "String2", SbxSTRING, 0,NULL,0 },
+ { "Compare", SbxINTEGER, _OPT, NULL,0 },
+{ "StrConv", SbxOBJECT, 3 | _FUNCTION, RTLNAME(StrConv),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+ { "Conversion", SbxSTRING, 0,NULL,0 },
+ { "LCID", SbxINTEGER, _OPT,NULL,0 },
+{ "String", SbxSTRING, 2 | _FUNCTION, RTLNAME(String),0 },
+ { "Count", SbxLONG, 0,NULL,0 },
+ { "Filler", SbxVARIANT, 0,NULL,0 },
+{ "StrReverse", SbxSTRING, 1 | _FUNCTION | _COMPTMASK, RTLNAME(StrReverse),0 },
+ { "String1", SbxSTRING, 0,NULL,0 },
+{ "Switch", SbxVARIANT, 2 | _FUNCTION, RTLNAME(Switch),0 },
+ { "Expression", SbxVARIANT, 0,NULL,0 },
+ { "Value", SbxVARIANT, 0,NULL,0 },
+
+{ "Tan", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Tan),0 },
+ { "number", SbxDOUBLE, 0,NULL,0 },
+{ "Time", SbxVARIANT, _LFUNCTION,RTLNAME(Time),0 },
+{ "Timer", SbxDATE, _FUNCTION, RTLNAME(Timer),0 },
+{ "TimeSerial", SbxDATE, 3 | _FUNCTION, RTLNAME(TimeSerial),0 },
+ { "Hour", SbxLONG, 0,NULL,0 },
+ { "Minute", SbxLONG, 0,NULL,0 },
+ { "Second", SbxLONG, 0,NULL,0 },
+{ "TimeValue", SbxDATE, 1 | _FUNCTION, RTLNAME(TimeValue),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+{ "TOGGLE", SbxINTEGER, _CPROP, RTLNAME(TOGGLE),0 },
+{ "Trim", SbxSTRING, 1 | _FUNCTION, RTLNAME(Trim),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+{ "True", SbxBOOL, _CPROP, RTLNAME(True),0 },
+{ "TwipsPerPixelX", SbxLONG, _FUNCTION, RTLNAME(TwipsPerPixelX),0 },
+{ "TwipsPerPixelY", SbxLONG, _FUNCTION, RTLNAME(TwipsPerPixelY),0 },
+
+{ "TYP_AUTHORFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_AUTHORFLD),0 },
+{ "TYP_CHAPTERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_CHAPTERFLD),0 },
+{ "TYP_CONDTXTFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_CONDTXTFLD),0 },
+{ "TYP_DATEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DATEFLD),0 },
+{ "TYP_DBFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBFLD),0 },
+{ "TYP_DBNAMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBNAMEFLD),0 },
+{ "TYP_DBNEXTSETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBNEXTSETFLD),0 },
+{ "TYP_DBNUMSETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBNUMSETFLD),0 },
+{ "TYP_DBSETNUMBERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBSETNUMBERFLD),0 },
+{ "TYP_DDEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DDEFLD),0 },
+{ "TYP_DOCINFOFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DOCINFOFLD),0 },
+{ "TYP_DOCSTATFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DOCSTATFLD),0 },
+{ "TYP_EXTUSERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_EXTUSERFLD),0 },
+{ "TYP_FILENAMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FILENAMEFLD),0 },
+{ "TYP_FIXDATEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FIXDATEFLD),0 },
+{ "TYP_FIXTIMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FIXTIMEFLD),0 },
+{ "TYP_FORMELFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FORMELFLD),0 },
+{ "TYP_GETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_GETFLD),0 },
+{ "TYP_GETREFFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_GETREFFLD),0 },
+{ "TYP_GETREFPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_GETREFPAGEFLD),0 },
+{ "TYP_HIDDENPARAFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_HIDDENPARAFLD),0 },
+{ "TYP_HIDDENTXTFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_HIDDENTXTFLD),0 },
+{ "TYP_INPUTFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_INPUTFLD),0 },
+{ "TYP_INTERNETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_INTERNETFLD),0 },
+{ "TYP_JUMPEDITFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_JUMPEDITFLD),0 },
+{ "TYP_MACROFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_MACROFLD),0 },
+{ "TYP_NEXTPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_NEXTPAGEFLD),0 },
+{ "TYP_PAGENUMBERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_PAGENUMBERFLD),0 },
+{ "TYP_POSTITFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_POSTITFLD),0 },
+{ "TYP_PREVPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_PREVPAGEFLD),0 },
+{ "TYP_SEQFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SEQFLD),0 },
+{ "TYP_SETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETFLD),0 },
+{ "TYP_SETINPFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETINPFLD),0 },
+{ "TYP_SETREFFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETREFFLD),0 },
+{ "TYP_SETREFPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETREFPAGEFLD),0 },
+{ "TYP_TEMPLNAMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_TEMPLNAMEFLD),0},
+{ "TYP_TIMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_TIMEFLD),0 },
+{ "TYP_USERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_USERFLD),0 },
+{ "TYP_USRINPFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_USRINPFLD),0 },
+
+{ "TypeLen", SbxINTEGER, 1 | _FUNCTION, RTLNAME(TypeLen),0 },
+ { "Var", SbxVARIANT, 0,NULL,0 },
+{ "TypeName", SbxSTRING, 1 | _FUNCTION, RTLNAME(TypeName),0 },
+ { "Var", SbxVARIANT, 0,NULL,0 },
+
+{ "UBound", SbxLONG, 1 | _FUNCTION, RTLNAME(UBound),0 },
+ { "Var", SbxVARIANT, 0,NULL,0 },
+{ "UCase", SbxSTRING, 1 | _FUNCTION, RTLNAME(UCase),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+{ "Unload", SbxNULL, 1 | _FUNCTION, RTLNAME(Unload),0 },
+ { "Dialog", SbxOBJECT, 0,NULL,0 },
+
+{ "Val", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Val),0 },
+ { "String", SbxSTRING, 0,NULL,0 },
+{ "VarType", SbxINTEGER, 1 | _FUNCTION, RTLNAME(VarType),0 },
+ { "Var", SbxVARIANT, 0,NULL,0 },
+{ "V_EMPTY", SbxINTEGER, _CPROP, RTLNAME(V_EMPTY),0 },
+{ "V_NULL", SbxINTEGER, _CPROP, RTLNAME(V_NULL),0 },
+{ "V_INTEGER", SbxINTEGER, _CPROP, RTLNAME(V_INTEGER),0 },
+{ "V_LONG", SbxINTEGER, _CPROP, RTLNAME(V_LONG),0 },
+{ "V_SINGLE", SbxINTEGER, _CPROP, RTLNAME(V_SINGLE),0 },
+{ "V_DOUBLE", SbxINTEGER, _CPROP, RTLNAME(V_DOUBLE),0 },
+{ "V_CURRENCY", SbxINTEGER, _CPROP, RTLNAME(V_CURRENCY),0 },
+{ "V_DATE", SbxINTEGER, _CPROP, RTLNAME(V_DATE),0 },
+{ "V_STRING", SbxINTEGER, _CPROP, RTLNAME(V_STRING),0 },
+
+{ "Wait", SbxNULL, 1 | _FUNCTION, RTLNAME(Wait),0 },
+ { "Milliseconds", SbxLONG, 0,NULL,0 },
+//#i64882#
+{ "WaitUntil", SbxNULL, 1 | _FUNCTION, RTLNAME(WaitUntil),0 },
+ { "Date", SbxDOUBLE, 0,NULL,0 },
+{ "Weekday", SbxINTEGER, 2 | _FUNCTION, RTLNAME(Weekday),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+ { "Firstdayofweek", SbxINTEGER, _OPT, NULL,0 },
+{ "WeekdayName", SbxSTRING, 3 | _FUNCTION | _COMPTMASK, RTLNAME(WeekdayName),0 },
+ { "Weekday", SbxINTEGER, 0,NULL,0 },
+ { "Abbreviate", SbxBOOL, _OPT, NULL,0 },
+ { "Firstdayofweek", SbxINTEGER, _OPT, NULL,0 },
+{ "Year", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Year),0 },
+ { "Date", SbxDATE, 0,NULL,0 },
+
+{ NULL, SbxNULL, -1,NULL,0 }}; // Tabellenende
+
+SbiStdObject::SbiStdObject( const String& r, StarBASIC* pb ) : SbxObject( r )
+{
+ // Muessen wir die Hashcodes initialisieren?
+ Methods* p = aMethods;
+ if( !p->nHash )
+ while( p->nArgs != -1 )
+ {
+ String aName_ = String::CreateFromAscii( p->pName );
+ p->nHash = SbxVariable::MakeHashCode( aName_ );
+ p += ( p->nArgs & _ARGSMASK ) + 1;
+ }
+
+ // #i92642: Remove default properties
+ Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
+ Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );
+
+ SetParent( pb );
+
+ pStdFactory = new SbStdFactory;
+ SbxBase::AddFactory( pStdFactory );
+
+ Insert( new SbStdClipboard );
+}
+
+SbiStdObject::~SbiStdObject()
+{
+ SbxBase::RemoveFactory( pStdFactory );
+ delete pStdFactory;
+}
+
+// Suche nach einem Element:
+// Hier wird linear durch die Methodentabelle gegangen, bis eine
+// passende Methode gefunden wurde. Auf Grund der Bits im nArgs-Feld
+// wird dann die passende Instanz eines SbxObjElement generiert.
+// Wenn die Methode/Property nicht gefunden wurde, nur NULL ohne
+// Fehlercode zurueckliefern, da so auch eine ganze Chain von
+// Objekten nach der Methode/Property befragt werden kann.
+
+SbxVariable* SbiStdObject::Find( const String& rName, SbxClassType t )
+{
+ // Bereits eingetragen?
+ SbxVariable* pVar = SbxObject::Find( rName, t );
+ if( !pVar )
+ {
+ // sonst suchen
+ USHORT nHash_ = SbxVariable::MakeHashCode( rName );
+ Methods* p = aMethods;
+ BOOL bFound = FALSE;
+ short nIndex = 0;
+ USHORT nSrchMask = _TYPEMASK;
+ switch( t )
+ {
+ case SbxCLASS_METHOD: nSrchMask = _METHOD; break;
+ case SbxCLASS_PROPERTY: nSrchMask = _PROPERTY; break;
+ case SbxCLASS_OBJECT: nSrchMask = _OBJECT; break;
+ default: break;
+ }
+ while( p->nArgs != -1 )
+ {
+ if( ( p->nArgs & nSrchMask )
+ && ( p->nHash == nHash_ )
+ && ( rName.EqualsIgnoreCaseAscii( p->pName ) ) )
+ {
+ bFound = TRUE;
+ if( p->nArgs & _COMPTMASK )
+ {
+ SbiInstance* pInst = pINST;
+ if( !pInst || !pInst->IsCompatibility() )
+ bFound = FALSE;
+ }
+ break;
+ }
+ nIndex += ( p->nArgs & _ARGSMASK ) + 1;
+ p = aMethods + nIndex;
+ }
+
+ if( bFound )
+ {
+ // Args-Felder isolieren:
+ short nAccess = ( p->nArgs & _RWMASK ) >> 8;
+ short nType = ( p->nArgs & _TYPEMASK );
+ if( p->nArgs & _CONST )
+ nAccess |= SBX_CONST;
+ String aName_ = String::CreateFromAscii( p->pName );
+ SbxClassType eCT = SbxCLASS_OBJECT;
+ if( nType & _PROPERTY )
+ eCT = SbxCLASS_PROPERTY;
+ else if( nType & _METHOD )
+ eCT = SbxCLASS_METHOD;
+ pVar = Make( aName_, eCT, p->eType );
+ pVar->SetUserData( nIndex + 1 );
+ pVar->SetFlags( nAccess );
+ }
+ }
+ return pVar;
+}
+
+// SetModified muß bei der RTL abgklemmt werden
+void SbiStdObject::SetModified( BOOL )
+{
+}
+
+// Aufruf einer Property oder Methode.
+
+void SbiStdObject::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* pPar_ = pVar->GetParameters();
+ ULONG t = pHint->GetId();
+ USHORT nCallId = (USHORT) pVar->GetUserData();
+ if( nCallId )
+ {
+ if( t == SBX_HINT_INFOWANTED )
+ pVar->SetInfo( GetInfo( (short) pVar->GetUserData() ) );
+ else
+ {
+ BOOL bWrite = FALSE;
+ if( t == SBX_HINT_DATACHANGED )
+ bWrite = TRUE;
+ if( t == SBX_HINT_DATAWANTED || bWrite )
+ {
+ RtlCall p = (RtlCall) aMethods[ nCallId-1 ].pFunc;
+ SbxArrayRef rPar( pPar_ );
+ if( !pPar_ )
+ {
+ rPar = pPar_ = new SbxArray;
+ pPar_->Put( pVar, 0 );
+ }
+ p( (StarBASIC*) GetParent(), *pPar_, bWrite );
+ return;
+ }
+ }
+ }
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ }
+}
+
+// Zusammenbau der Infostruktur fuer einzelne Elemente
+// Falls nIdx = 0, nix erzeugen (sind Std-Props!)
+
+SbxInfo* SbiStdObject::GetInfo( short nIdx )
+{
+ if( !nIdx )
+ return NULL;
+ Methods* p = &aMethods[ --nIdx ];
+ // Wenn mal eine Hilfedatei zur Verfuegung steht:
+ // SbxInfo* pInfo_ = new SbxInfo( Hilfedateiname, p->nHelpId );
+ SbxInfo* pInfo_ = new SbxInfo;
+ short nPar = p->nArgs & _ARGSMASK;
+ for( short i = 0; i < nPar; i++ )
+ {
+ p++;
+ String aName_ = String::CreateFromAscii( p->pName );
+ USHORT nFlags_ = ( p->nArgs >> 8 ) & 0x03;
+ if( p->nArgs & _OPT )
+ nFlags_ |= SBX_OPTIONAL;
+ pInfo_->AddParam( aName_, p->eType, nFlags_ );
+ }
+ return pInfo_;
+}
+
diff --git a/basic/source/runtime/stdobj1.cxx b/basic/source/runtime/stdobj1.cxx
new file mode 100644
index 000000000000..94b7973c7e77
--- /dev/null
+++ b/basic/source/runtime/stdobj1.cxx
@@ -0,0 +1,551 @@
+/*************************************************************************
+ *
+ * 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 <vcl/wrkwin.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/transfer.hxx>
+#include "runtime.hxx"
+#include <basic/sbstdobj.hxx>
+
+#define ATTR_IMP_TYPE 1
+#define ATTR_IMP_WIDTH 2
+#define ATTR_IMP_HEIGHT 3
+#define ATTR_IMP_BOLD 4
+#define ATTR_IMP_ITALIC 5
+#define ATTR_IMP_STRIKETHROUGH 6
+#define ATTR_IMP_UNDERLINE 7
+#define ATTR_IMP_WEIGHT 8
+#define ATTR_IMP_SIZE 9
+#define ATTR_IMP_NAME 10
+
+#define METH_CLEAR 20
+#define METH_GETDATA 21
+#define METH_GETFORMAT 22
+#define METH_GETTEXT 23
+#define METH_SETDATA 24
+#define METH_SETTEXT 25
+
+//------------------------------------------------------------------------------
+SbStdFactory::SbStdFactory()
+{
+}
+
+SbxObject* SbStdFactory::CreateObject( const String& rClassName )
+{
+ if( rClassName.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("Picture") ) ) )
+ return new SbStdPicture;
+ else
+ if( rClassName.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("Font") ) ) )
+ return new SbStdFont;
+ else
+ return NULL;
+}
+
+//------------------------------------------------------------------------------
+
+
+
+void SbStdPicture::PropType( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ {
+ StarBASIC::Error( SbERR_PROP_READONLY );
+ return;
+ }
+
+ GraphicType eType = aGraphic.GetType();
+ INT16 nType = 0;
+
+ if( eType == GRAPHIC_BITMAP )
+ nType = 1;
+ else
+ if( eType != GRAPHIC_NONE )
+ nType = 2;
+
+ pVar->PutInteger( nType );
+}
+
+
+void SbStdPicture::PropWidth( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ {
+ StarBASIC::Error( SbERR_PROP_READONLY );
+ return;
+ }
+
+ Size aSize = aGraphic.GetPrefSize();
+ aSize = GetpApp()->GetAppWindow()->LogicToPixel( aSize, aGraphic.GetPrefMapMode() );
+ aSize = GetpApp()->GetAppWindow()->PixelToLogic( aSize, MapMode( MAP_TWIP ) );
+
+ pVar->PutInteger( (INT16)aSize.Width() );
+}
+
+void SbStdPicture::PropHeight( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ {
+ StarBASIC::Error( SbERR_PROP_READONLY );
+ return;
+ }
+
+ Size aSize = aGraphic.GetPrefSize();
+ aSize = GetpApp()->GetAppWindow()->LogicToPixel( aSize, aGraphic.GetPrefMapMode() );
+ aSize = GetpApp()->GetAppWindow()->PixelToLogic( aSize, MapMode( MAP_TWIP ) );
+
+ pVar->PutInteger( (INT16)aSize.Height() );
+}
+
+
+TYPEINIT1( SbStdPicture, SbxObject );
+
+SbStdPicture::SbStdPicture() :
+ SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("Picture") ) )
+{
+ // Properties
+ SbxVariable* p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Type") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READ | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_TYPE );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Width") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READ | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_WIDTH );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Height") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READ | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_HEIGHT );
+}
+
+SbStdPicture::~SbStdPicture()
+{
+}
+
+
+SbxVariable* SbStdPicture::Find( const String& rName, SbxClassType t )
+{
+ // Bereits eingetragen?
+ return SbxObject::Find( rName, t );
+}
+
+
+
+void SbStdPicture::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
+ const SfxHint& rHint, const TypeId& rHintType )
+
+{
+ const SbxHint* pHint = PTR_CAST( SbxHint, &rHint );
+
+ if( pHint )
+ {
+ if( pHint->GetId() == SBX_HINT_INFOWANTED )
+ {
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ return;
+ }
+
+ SbxVariable* pVar = pHint->GetVar();
+ SbxArray* pPar_ = pVar->GetParameters();
+ USHORT nWhich = (USHORT)pVar->GetUserData();
+ BOOL bWrite = pHint->GetId() == SBX_HINT_DATACHANGED;
+
+ // Propteries
+ switch( nWhich )
+ {
+ case ATTR_IMP_TYPE: PropType( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_WIDTH: PropWidth( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_HEIGHT: PropHeight( pVar, pPar_, bWrite ); return;
+ }
+
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void SbStdFont::PropBold( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ SetBold( pVar->GetBool() );
+ else
+ pVar->PutBool( IsBold() );
+}
+
+void SbStdFont::PropItalic( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ SetItalic( pVar->GetBool() );
+ else
+ pVar->PutBool( IsItalic() );
+}
+
+void SbStdFont::PropStrikeThrough( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ SetStrikeThrough( pVar->GetBool() );
+ else
+ pVar->PutBool( IsStrikeThrough() );
+}
+
+void SbStdFont::PropUnderline( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ SetUnderline( pVar->GetBool() );
+ else
+ pVar->PutBool( IsUnderline() );
+}
+
+void SbStdFont::PropSize( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ SetSize( (USHORT)pVar->GetInteger() );
+ else
+ pVar->PutInteger( (INT16)GetSize() );
+}
+
+void SbStdFont::PropName( SbxVariable* pVar, SbxArray*, BOOL bWrite )
+{
+ if( bWrite )
+ SetFontName( pVar->GetString() );
+ else
+ pVar->PutString( GetFontName() );
+}
+
+
+TYPEINIT1( SbStdFont, SbxObject );
+
+SbStdFont::SbStdFont() :
+ SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("Font") ) )
+{
+ // Properties
+ SbxVariable* p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Bold") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READWRITE | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_BOLD );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Italic") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READWRITE | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_ITALIC );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("StrikeThrough") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READWRITE | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_STRIKETHROUGH );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Underline") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READWRITE | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_UNDERLINE );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Size") ), SbxCLASS_PROPERTY, SbxVARIANT );
+ p->SetFlags( SBX_READWRITE | SBX_DONTSTORE );
+ p->SetUserData( ATTR_IMP_SIZE );
+
+ // Name Property selbst verarbeiten
+ p = Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY );
+ DBG_ASSERT( p, "Keine Name Property" );
+ p->SetUserData( ATTR_IMP_NAME );
+}
+
+SbStdFont::~SbStdFont()
+{
+}
+
+
+SbxVariable* SbStdFont::Find( const String& rName, SbxClassType t )
+{
+ // Bereits eingetragen?
+ return SbxObject::Find( rName, t );
+}
+
+
+
+void SbStdFont::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
+ const SfxHint& rHint, const TypeId& rHintType )
+{
+ const SbxHint* pHint = PTR_CAST( SbxHint, &rHint );
+
+ if( pHint )
+ {
+ if( pHint->GetId() == SBX_HINT_INFOWANTED )
+ {
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ return;
+ }
+
+ SbxVariable* pVar = pHint->GetVar();
+ SbxArray* pPar_ = pVar->GetParameters();
+ USHORT nWhich = (USHORT)pVar->GetUserData();
+ BOOL bWrite = pHint->GetId() == SBX_HINT_DATACHANGED;
+
+ // Propteries
+ switch( nWhich )
+ {
+ case ATTR_IMP_BOLD: PropBold( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_ITALIC: PropItalic( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_STRIKETHROUGH:PropStrikeThrough( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_UNDERLINE: PropUnderline( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_SIZE: PropSize( pVar, pPar_, bWrite ); return;
+ case ATTR_IMP_NAME: PropName( pVar, pPar_, bWrite ); return;
+ }
+
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+
+/*
+class TransferableHelperImpl : public TransferableHelper
+{
+ SotFormatStringId mFormat;
+ String mString;
+ Graphic mGraphic;
+
+ virtual void AddSupportedFormats();
+ virtual sal_Bool GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
+
+public:
+ TransferableHelperImpl( void ) { mFormat = 0; }
+ TransferableHelperImpl( const String& rStr )
+ mFormat( FORMAT_STRING ), mString( rStr ) {}
+ TransferableHelperImpl( const Graphic& rGraphic );
+ mFormat( FORMAT_BITMAP ), mGraphic( rGraphic ) {}
+
+};
+
+void TransferableHelperImpl::AddSupportedFormats()
+{
+}
+
+sal_Bool TransferableHelperImpl::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
+{
+ sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
+ if( nFormat == FORMAT_STRING )
+ {
+ }
+ else if( nFormat == FORMAT_BITMAP ||
+ nFormat == FORMAT_GDIMETAFILE )
+ {
+ }
+}
+*/
+
+void SbStdClipboard::MethClear( SbxVariable*, SbxArray* pPar_, BOOL )
+{
+ if( pPar_ && (pPar_->Count() > 1) )
+ {
+ StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS );
+ return;
+ }
+
+ //Clipboard::Clear();
+}
+
+void SbStdClipboard::MethGetData( SbxVariable* pVar, SbxArray* pPar_, BOOL )
+{
+ (void)pVar;
+
+ if( !pPar_ || (pPar_->Count() != 2) )
+ {
+ StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS );
+ return;
+ }
+
+ USHORT nFormat = pPar_->Get(1)->GetInteger();
+ if( !nFormat || nFormat > 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ /*
+ if( nFormat == FORMAT_STRING )
+ pVar->PutString( Clipboard::PasteString() );
+ else
+ if( (nFormat == FORMAT_BITMAP) ||
+ (nFormat == FORMAT_GDIMETAFILE ) )
+ {
+ SbxObjectRef xPic = new SbStdPicture;
+ Graphic aGraph;
+ aGraph.Paste();
+ ((SbStdPicture*)(SbxObject*)xPic)->SetGraphic( aGraph );
+ pVar->PutObject( xPic );
+ }
+ */
+}
+
+void SbStdClipboard::MethGetFormat( SbxVariable* pVar, SbxArray* pPar_, BOOL )
+{
+ if( !pPar_ || (pPar_->Count() != 2) )
+ {
+ StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS );
+ return;
+ }
+
+ USHORT nFormat = pPar_->Get(1)->GetInteger();
+ if( !nFormat || nFormat > 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ pVar->PutBool( FALSE );
+ //pVar->PutBool( Clipboard::HasFormat( nFormat ) );
+}
+
+void SbStdClipboard::MethGetText( SbxVariable* pVar, SbxArray* pPar_, BOOL )
+{
+ if( pPar_ && (pPar_->Count() > 1) )
+ {
+ StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS );
+ return;
+ }
+
+ pVar->PutString( String() );
+ //pVar->PutString( Clipboard::PasteString() );
+}
+
+void SbStdClipboard::MethSetData( SbxVariable* pVar, SbxArray* pPar_, BOOL )
+{
+ (void)pVar;
+
+ if( !pPar_ || (pPar_->Count() != 3) )
+ {
+ StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS );
+ return;
+ }
+
+ USHORT nFormat = pPar_->Get(2)->GetInteger();
+ if( !nFormat || nFormat > 3 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+ /*
+ if( nFormat == FORMAT_STRING )
+ {
+ Clipboard::CopyString( pPar_->Get(1)->GetString() );
+ }
+ else
+ if( (nFormat == FORMAT_BITMAP) ||
+ (nFormat == FORMAT_GDIMETAFILE) )
+ {
+ SbxObject* pObj = (SbxObject*)pPar_->Get(1)->GetObject();
+
+ if( pObj && pObj->IsA( TYPE( SbStdPicture ) ) )
+ ((SbStdPicture*)(SbxObject*)pObj)->GetGraphic().Copy();
+ }
+ */
+}
+
+void SbStdClipboard::MethSetText( SbxVariable* pVar, SbxArray* pPar_, BOOL )
+{
+ (void)pVar;
+
+ if( !pPar_ || (pPar_->Count() != 2) )
+ {
+ StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS );
+ return;
+ }
+
+ // Clipboard::CopyString( pPar_->Get(1)->GetString() );
+}
+
+
+TYPEINIT1( SbStdClipboard, SbxObject );
+
+SbStdClipboard::SbStdClipboard() :
+ SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("Clipboard") ) )
+{
+ // Name Property selbst verarbeiten
+ SbxVariable* p = Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY );
+ DBG_ASSERT( p, "Keine Name Property" );
+ p->SetUserData( ATTR_IMP_NAME );
+
+ //Methoden registrieren
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Clear") ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p->SetUserData( METH_CLEAR );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("GetData") ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p->SetUserData( METH_GETDATA );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("GetFormat") ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p->SetUserData( METH_GETFORMAT );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("GetText") ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p->SetUserData( METH_GETTEXT );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("SetData") ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p->SetUserData( METH_SETDATA );
+ p = Make( String( RTL_CONSTASCII_USTRINGPARAM("SetText") ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p->SetUserData( METH_SETTEXT );
+}
+
+SbStdClipboard::~SbStdClipboard()
+{
+}
+
+
+SbxVariable* SbStdClipboard::Find( const String& rName, SbxClassType t )
+{
+ // Bereits eingetragen?
+ return SbxObject::Find( rName, t );
+}
+
+
+
+void SbStdClipboard::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
+ const SfxHint& rHint, const TypeId& rHintType )
+{
+ const SbxHint* pHint = PTR_CAST( SbxHint, &rHint );
+
+ if( pHint )
+ {
+ if( pHint->GetId() == SBX_HINT_INFOWANTED )
+ {
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ return;
+ }
+
+ SbxVariable* pVar = pHint->GetVar();
+ SbxArray* pPar_ = pVar->GetParameters();
+ USHORT nWhich = (USHORT)pVar->GetUserData();
+ BOOL bWrite = pHint->GetId() == SBX_HINT_DATACHANGED;
+
+ // Methods
+ switch( nWhich )
+ {
+ case METH_CLEAR: MethClear( pVar, pPar_, bWrite ); return;
+ case METH_GETDATA: MethGetData( pVar, pPar_, bWrite ); return;
+ case METH_GETFORMAT: MethGetFormat( pVar, pPar_, bWrite ); return;
+ case METH_GETTEXT: MethGetText( pVar, pPar_, bWrite ); return;
+ case METH_SETDATA: MethSetData( pVar, pPar_, bWrite ); return;
+ case METH_SETTEXT: MethSetText( pVar, pPar_, bWrite ); return;
+ }
+
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ }
+}
+
+
diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx
new file mode 100644
index 000000000000..06a8bb19af00
--- /dev/null
+++ b/basic/source/runtime/step0.cxx
@@ -0,0 +1,1332 @@
+/*************************************************************************
+ *
+ * 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 <vcl/msgbox.hxx>
+#include <tools/fsys.hxx>
+
+#include "errobject.hxx"
+#include "runtime.hxx"
+#include "sbintern.hxx"
+#include "iosys.hxx"
+#include <sb.hrc>
+#include <basrid.hxx>
+#include "sbunoobj.hxx"
+#include "image.hxx"
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/util/SearchOptions.hdl>
+#include <vcl/svapp.hxx>
+#include <unotools/textsearch.hxx>
+
+Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType,
+ const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj );
+
+#include <algorithm>
+
+SbxVariable* getDefaultProp( SbxVariable* pRef );
+
+void SbiRuntime::StepNOP()
+{}
+
+void SbiRuntime::StepArith( SbxOperator eOp )
+{
+ SbxVariableRef p1 = PopVar();
+ TOSMakeTemp();
+ SbxVariable* p2 = GetTOS();
+
+
+ // This could & should be moved to the MakeTempTOS() method in runtime.cxx
+ // In the code which this is cut'npaste from there is a check for a ref
+ // count != 1 based on which the copy of the SbxVariable is done.
+ // see orig code in MakeTempTOS ( and I'm not sure what the significance,
+ // of that is )
+ // here we alway seem to have a refcount of 1. Also it seems that
+ // MakeTempTOS is called for other operation, so I hold off for now
+ // until I have a better idea
+ if ( bVBAEnabled
+ && ( p2->GetType() == SbxOBJECT || p2->GetType() == SbxVARIANT )
+ )
+ {
+ SbxVariable* pDflt = getDefaultProp( p2 );
+ if ( pDflt )
+ {
+ pDflt->Broadcast( SBX_HINT_DATAWANTED );
+ // replacing new p2 on stack causes object pointed by
+ // pDft->pParent to be deleted, when p2->Compute() is
+ // called below pParent is accessed ( but its deleted )
+ // so set it to NULL now
+ pDflt->SetParent( NULL );
+ p2 = new SbxVariable( *pDflt );
+ p2->SetFlag( SBX_READWRITE );
+ refExprStk->Put( p2, nExprLvl - 1 );
+ }
+ }
+
+ p2->ResetFlag( SBX_FIXED );
+ p2->Compute( eOp, *p1 );
+
+ checkArithmeticOverflow( p2 );
+}
+
+void SbiRuntime::StepUnary( SbxOperator eOp )
+{
+ TOSMakeTemp();
+ SbxVariable* p = GetTOS();
+ p->Compute( eOp, *p );
+}
+
+void SbiRuntime::StepCompare( SbxOperator eOp )
+{
+ SbxVariableRef p1 = PopVar();
+ SbxVariableRef p2 = PopVar();
+
+ // Make sure objects with default params have
+ // values ( and type ) set as appropriate
+ SbxDataType p1Type = p1->GetType();
+ SbxDataType p2Type = p2->GetType();
+ if ( p1Type == p2Type )
+ {
+ if ( p1Type == SbxEMPTY )
+ {
+ p1->Broadcast( SBX_HINT_DATAWANTED );
+ p2->Broadcast( SBX_HINT_DATAWANTED );
+ }
+ // if both sides are an object and have default props
+ // then we need to use the default props
+ // we don't need to worry if only one side ( lhs, rhs ) is an
+ // object ( object side will get coerced to correct type in
+ // Compare )
+ else if ( p1Type == SbxOBJECT )
+ {
+ SbxVariable* pDflt = getDefaultProp( p1 );
+ if ( pDflt )
+ {
+ p1 = pDflt;
+ p1->Broadcast( SBX_HINT_DATAWANTED );
+ }
+ pDflt = getDefaultProp( p2 );
+ if ( pDflt )
+ {
+ p2 = pDflt;
+ p2->Broadcast( SBX_HINT_DATAWANTED );
+ }
+ }
+
+ }
+#ifndef WIN
+ static SbxVariable* pTRUE = NULL;
+ static SbxVariable* pFALSE = NULL;
+
+ if( p2->Compare( eOp, *p1 ) )
+ {
+ if( !pTRUE )
+ {
+ pTRUE = new SbxVariable;
+ pTRUE->PutBool( TRUE );
+ pTRUE->AddRef();
+ }
+ PushVar( pTRUE );
+ }
+ else
+ {
+ if( !pFALSE )
+ {
+ pFALSE = new SbxVariable;
+ pFALSE->PutBool( FALSE );
+ pFALSE->AddRef();
+ }
+ PushVar( pFALSE );
+ }
+#else
+ BOOL bRes = p2->Compare( eOp, *p1 );
+ SbxVariable* pRes = new SbxVariable;
+ pRes->PutBool( bRes );
+ PushVar( pRes );
+#endif
+}
+
+void SbiRuntime::StepEXP() { StepArith( SbxEXP ); }
+void SbiRuntime::StepMUL() { StepArith( SbxMUL ); }
+void SbiRuntime::StepDIV() { StepArith( SbxDIV ); }
+void SbiRuntime::StepIDIV() { StepArith( SbxIDIV ); }
+void SbiRuntime::StepMOD() { StepArith( SbxMOD ); }
+void SbiRuntime::StepPLUS() { StepArith( SbxPLUS ); }
+void SbiRuntime::StepMINUS() { StepArith( SbxMINUS ); }
+void SbiRuntime::StepCAT() { StepArith( SbxCAT ); }
+void SbiRuntime::StepAND() { StepArith( SbxAND ); }
+void SbiRuntime::StepOR() { StepArith( SbxOR ); }
+void SbiRuntime::StepXOR() { StepArith( SbxXOR ); }
+void SbiRuntime::StepEQV() { StepArith( SbxEQV ); }
+void SbiRuntime::StepIMP() { StepArith( SbxIMP ); }
+
+void SbiRuntime::StepNEG() { StepUnary( SbxNEG ); }
+void SbiRuntime::StepNOT() { StepUnary( SbxNOT ); }
+
+void SbiRuntime::StepEQ() { StepCompare( SbxEQ ); }
+void SbiRuntime::StepNE() { StepCompare( SbxNE ); }
+void SbiRuntime::StepLT() { StepCompare( SbxLT ); }
+void SbiRuntime::StepGT() { StepCompare( SbxGT ); }
+void SbiRuntime::StepLE() { StepCompare( SbxLE ); }
+void SbiRuntime::StepGE() { StepCompare( SbxGE ); }
+
+namespace
+{
+ bool NeedEsc(sal_Unicode cCode)
+ {
+ String sEsc(RTL_CONSTASCII_USTRINGPARAM(".^$+\\|{}()"));
+ return (STRING_NOTFOUND != sEsc.Search(cCode));
+ }
+
+ String VBALikeToRegexp(const String &rIn)
+ {
+ String sResult;
+ const sal_Unicode *start = rIn.GetBuffer();
+ const sal_Unicode *end = start + rIn.Len();
+
+ int seenright = 0;
+
+ sResult.Append('^');
+
+ while (start < end)
+ {
+ switch (*start)
+ {
+ case '?':
+ sResult.Append('.');
+ start++;
+ break;
+ case '*':
+ sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM(".*")));
+ start++;
+ break;
+ case '#':
+ sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM("[0-9]")));
+ start++;
+ break;
+ case ']':
+ sResult.Append('\\');
+ sResult.Append(*start++);
+ break;
+ case '[':
+ sResult.Append(*start++);
+ seenright = 0;
+ while (start < end && !seenright)
+ {
+ switch (*start)
+ {
+ case '[':
+ case '?':
+ case '*':
+ sResult.Append('\\');
+ sResult.Append(*start);
+ break;
+ case ']':
+ sResult.Append(*start);
+ seenright = 1;
+ break;
+ case '!':
+ sResult.Append('^');
+ break;
+ default:
+ if (NeedEsc(*start))
+ sResult.Append('\\');
+ sResult.Append(*start);
+ break;
+ }
+ start++;
+ }
+ break;
+ default:
+ if (NeedEsc(*start))
+ sResult.Append('\\');
+ sResult.Append(*start++);
+ }
+ }
+
+ sResult.Append('$');
+
+ return sResult;
+ }
+}
+
+void SbiRuntime::StepLIKE()
+{
+ SbxVariableRef refVar1 = PopVar();
+ SbxVariableRef refVar2 = PopVar();
+
+ String pattern = VBALikeToRegexp(refVar1->GetString());
+ String value = refVar2->GetString();
+
+ com::sun::star::util::SearchOptions aSearchOpt;
+
+ aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP;
+
+ aSearchOpt.Locale = Application::GetSettings().GetLocale();
+ aSearchOpt.searchString = pattern;
+
+ int bTextMode(1);
+ bool bCompatibility = ( pINST && pINST->IsCompatibility() );
+ if( bCompatibility )
+ bTextMode = GetImageFlag( SBIMG_COMPARETEXT );
+
+ if( bTextMode )
+ aSearchOpt.transliterateFlags |= com::sun::star::i18n::TransliterationModules_IGNORE_CASE;
+
+ SbxVariable* pRes = new SbxVariable;
+ utl::TextSearch aSearch(aSearchOpt);
+ xub_StrLen nStart=0, nEnd=value.Len();
+ int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd);
+ pRes->PutBool( bRes != 0 );
+
+ PushVar( pRes );
+}
+
+// TOS und TOS-1 sind beides Objektvariable und enthalten den selben Pointer
+
+void SbiRuntime::StepIS()
+{
+ SbxVariableRef refVar1 = PopVar();
+ SbxVariableRef refVar2 = PopVar();
+
+ SbxDataType eType1 = refVar1->GetType();
+ SbxDataType eType2 = refVar2->GetType();
+ if ( eType1 == SbxEMPTY )
+ {
+ refVar1->Broadcast( SBX_HINT_DATAWANTED );
+ eType1 = refVar1->GetType();
+ }
+ if ( eType2 == SbxEMPTY )
+ {
+ refVar2->Broadcast( SBX_HINT_DATAWANTED );
+ eType2 = refVar2->GetType();
+ }
+
+ BOOL bRes = BOOL( eType1 == SbxOBJECT && eType2 == SbxOBJECT );
+ if ( bVBAEnabled && !bRes )
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ bRes = ( bRes && refVar1->GetObject() == refVar2->GetObject() );
+ SbxVariable* pRes = new SbxVariable;
+ pRes->PutBool( bRes );
+ PushVar( pRes );
+}
+
+// Aktualisieren des Wertes von TOS
+
+void SbiRuntime::StepGET()
+{
+ SbxVariable* p = GetTOS();
+ p->Broadcast( SBX_HINT_DATAWANTED );
+}
+
+// #67607 Uno-Structs kopieren
+inline void checkUnoStructCopy( SbxVariableRef& refVal, SbxVariableRef& refVar )
+{
+ SbxDataType eVarType = refVar->GetType();
+ if( eVarType != SbxOBJECT )
+ return;
+
+ SbxObjectRef xValObj = (SbxObject*)refVal->GetObject();
+ if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) )
+ return;
+
+ // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
+ if( refVar->ISA(SbProcedureProperty) )
+ return;
+
+ SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject();
+ SbxDataType eValType = refVal->GetType();
+ if( eValType == SbxOBJECT && xVarObj == xValObj )
+ {
+ SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)xVarObj);
+ if( pUnoObj )
+ {
+ Any aAny = pUnoObj->getUnoAny();
+ if( aAny.getValueType().getTypeClass() == TypeClass_STRUCT )
+ {
+ SbUnoObject* pNewUnoObj = new SbUnoObject( pUnoObj->GetName(), aAny );
+ // #70324: ClassName uebernehmen
+ pNewUnoObj->SetClassName( pUnoObj->GetClassName() );
+ refVar->PutObject( pNewUnoObj );
+ }
+ }
+ }
+}
+
+
+// Ablage von TOS in TOS-1
+
+void SbiRuntime::StepPUT()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ // Store auf die eigene Methode (innerhalb einer Function)?
+ BOOL bFlagsChanged = FALSE;
+ USHORT n = 0;
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ {
+ bFlagsChanged = TRUE;
+ n = refVar->GetFlags();
+ refVar->SetFlag( SBX_WRITE );
+ }
+
+ // if left side arg is an object or variant and right handside isn't
+ // either an object or a variant then try and see if a default
+ // property exists.
+ // to use e.g. Range{"A1") = 34
+ // could equate to Range("A1").Value = 34
+ if ( bVBAEnabled )
+ {
+ if ( refVar->GetType() == SbxOBJECT )
+ {
+ SbxVariable* pDflt = getDefaultProp( refVar );
+ if ( pDflt )
+ refVar = pDflt;
+ }
+ if ( refVal->GetType() == SbxOBJECT )
+ {
+ SbxVariable* pDflt = getDefaultProp( refVal );
+ if ( pDflt )
+ refVal = pDflt;
+ }
+ }
+
+ *refVar = *refVal;
+ // lhs is a property who's value is currently null
+ if ( !bVBAEnabled || ( bVBAEnabled && refVar->GetType() != SbxEMPTY ) )
+ // #67607 Uno-Structs kopieren
+ checkUnoStructCopy( refVal, refVar );
+ if( bFlagsChanged )
+ refVar->SetFlags( n );
+}
+
+
+// Speichern Objektvariable
+// Nicht-Objekt-Variable fuehren zu Fehlern
+
+void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
+{
+ // #67733 Typen mit Array-Flag sind auch ok
+
+ // Check var, !object is no error for sure if, only if type is fixed
+ SbxDataType eVarType = refVar->GetType();
+ if( !bHandleDefaultProp && eVarType != SbxOBJECT && !(eVarType & SbxARRAY) && refVar->IsFixed() )
+ {
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ return;
+ }
+
+ // Check value, !object is no error for sure if, only if type is fixed
+ SbxDataType eValType = refVal->GetType();
+// bool bGetValObject = false;
+ if( !bHandleDefaultProp && eValType != SbxOBJECT && !(eValType & SbxARRAY) && refVal->IsFixed() )
+ {
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ return;
+ }
+
+ // Getting in here causes problems with objects with default properties
+ // if they are SbxEMPTY I guess
+ if ( !bHandleDefaultProp || ( bHandleDefaultProp && eValType == SbxOBJECT ) )
+ {
+ // Auf refVal GetObject fuer Collections ausloesen
+ SbxBase* pObjVarObj = refVal->GetObject();
+ if( pObjVarObj )
+ {
+ SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj);
+
+ // #67733 Typen mit Array-Flag sind auch ok
+ if( refObjVal )
+ refVal = refObjVal;
+ else if( !(eValType & SbxARRAY) )
+ refVal = NULL;
+ }
+ }
+
+ // #52896 Wenn Uno-Sequences bzw. allgemein Arrays einer als
+ // Object deklarierten Variable zugewiesen werden, kann hier
+ // refVal ungueltig sein!
+ if( !refVal )
+ {
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ else
+ {
+ // Store auf die eigene Methode (innerhalb einer Function)?
+ BOOL bFlagsChanged = FALSE;
+ USHORT n = 0;
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ {
+ bFlagsChanged = TRUE;
+ n = refVar->GetFlags();
+ refVar->SetFlag( SBX_WRITE );
+ }
+ SbProcedureProperty* pProcProperty = PTR_CAST(SbProcedureProperty,(SbxVariable*)refVar);
+ if( pProcProperty )
+ pProcProperty->setSet( true );
+
+ if ( bHandleDefaultProp )
+ {
+ // get default properties for lhs & rhs where necessary
+ // SbxVariable* defaultProp = NULL; unused variable
+ bool bLHSHasDefaultProp = false;
+ // LHS try determine if a default prop exists
+ if ( refVar->GetType() == SbxOBJECT )
+ {
+ SbxVariable* pDflt = getDefaultProp( refVar );
+ if ( pDflt )
+ {
+ refVar = pDflt;
+ bLHSHasDefaultProp = true;
+ }
+ }
+ // RHS only get a default prop is the rhs has one
+ if ( refVal->GetType() == SbxOBJECT )
+ {
+ // check if lhs is a null object
+ // if it is then use the object not the default property
+ SbxObject* pObj = NULL;
+
+
+ pObj = PTR_CAST(SbxObject,(SbxVariable*)refVar);
+
+ // calling GetObject on a SbxEMPTY variable raises
+ // object not set errors, make sure its an Object
+ if ( !pObj && refVar->GetType() == SbxOBJECT )
+ {
+ SbxBase* pObjVarObj = refVar->GetObject();
+ pObj = PTR_CAST(SbxObject,pObjVarObj);
+ }
+ SbxVariable* pDflt = NULL;
+ if ( pObj || bLHSHasDefaultProp )
+ // lhs is either a valid object || or has a defaultProp
+ pDflt = getDefaultProp( refVal );
+ if ( pDflt )
+ refVal = pDflt;
+ }
+ }
+
+ // Handle withevents
+ BOOL bWithEvents = refVar->IsSet( SBX_WITH_EVENTS );
+ if ( bWithEvents )
+ {
+ Reference< XInterface > xComListener;
+
+ SbxBase* pObj = refVal->GetObject();
+ SbUnoObject* pUnoObj = (pObj != NULL) ? PTR_CAST(SbUnoObject,pObj) : NULL;
+ if( pUnoObj != NULL )
+ {
+ Any aControlAny = pUnoObj->getUnoAny();
+ String aDeclareClassName = refVar->GetDeclareClassName();
+ ::rtl::OUString aVBAType = aDeclareClassName;
+ ::rtl::OUString aPrefix = refVar->GetName();
+ SbxObjectRef xScopeObj = refVar->GetParent();
+ xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj );
+
+ refVal->SetDeclareClassName( aDeclareClassName );
+ refVal->SetComListener( xComListener ); // Hold reference
+ }
+
+ *refVar = *refVal;
+ }
+ else
+ {
+ *refVar = *refVal;
+ }
+
+ // lhs is a property who's value is currently (Empty e.g. no broadcast yet)
+ // in this case if there is a default prop involved the value of the
+ // default property may infact be void so the type will also be SbxEMPTY
+ // in this case we do not want to call checkUnoStructCopy 'cause that will
+ // cause an error also
+ if ( !bHandleDefaultProp || ( bHandleDefaultProp && ( refVar->GetType() != SbxEMPTY ) ) )
+ // #67607 Uno-Structs kopieren
+ checkUnoStructCopy( refVal, refVar );
+ if( bFlagsChanged )
+ refVar->SetFlags( n );
+ }
+}
+
+void SbiRuntime::StepSET()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ StepSET_Impl( refVal, refVar, bVBAEnabled ); // this is really assigment
+}
+
+void SbiRuntime::StepVBASET()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ // don't handle default property
+ StepSET_Impl( refVal, refVar, false ); // set obj = something
+}
+
+
+// JSM 07.10.95
+void SbiRuntime::StepLSET()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ if( refVar->GetType() != SbxSTRING
+ || refVal->GetType() != SbxSTRING )
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ else
+ {
+ // Store auf die eigene Methode (innerhalb einer Function)?
+ USHORT n = refVar->GetFlags();
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ refVar->SetFlag( SBX_WRITE );
+ String aRefVarString = refVar->GetString();
+ String aRefValString = refVal->GetString();
+
+ USHORT nVarStrLen = aRefVarString.Len();
+ USHORT nValStrLen = aRefValString.Len();
+ String aNewStr;
+ if( nVarStrLen > nValStrLen )
+ {
+ aRefVarString.Fill(nVarStrLen,' ');
+ aNewStr = aRefValString.Copy( 0, nValStrLen );
+ aNewStr += aRefVarString.Copy( nValStrLen, nVarStrLen - nValStrLen );
+ }
+ else
+ {
+ aNewStr = aRefValString.Copy( 0, nVarStrLen );
+ }
+
+ refVar->PutString( aNewStr );
+ refVar->SetFlags( n );
+ }
+}
+
+// JSM 07.10.95
+void SbiRuntime::StepRSET()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ if( refVar->GetType() != SbxSTRING
+ || refVal->GetType() != SbxSTRING )
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ else
+ {
+ // Store auf die eigene Methode (innerhalb einer Function)?
+ USHORT n = refVar->GetFlags();
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ refVar->SetFlag( SBX_WRITE );
+ String aRefVarString = refVar->GetString();
+ String aRefValString = refVal->GetString();
+
+ USHORT nPos = 0;
+ USHORT nVarStrLen = aRefVarString.Len();
+ if( nVarStrLen > aRefValString.Len() )
+ {
+ aRefVarString.Fill(nVarStrLen,' ');
+ nPos = nVarStrLen - aRefValString.Len();
+ }
+ aRefVarString = aRefVarString.Copy( 0, nPos );
+ aRefVarString += aRefValString.Copy( 0, nVarStrLen - nPos );
+ refVar->PutString(aRefVarString);
+
+ refVar->SetFlags( n );
+ }
+}
+
+// Ablage von TOS in TOS-1, dann ReadOnly-Bit setzen
+
+void SbiRuntime::StepPUTC()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ refVar->SetFlag( SBX_WRITE );
+ *refVar = *refVal;
+ refVar->ResetFlag( SBX_WRITE );
+ refVar->SetFlag( SBX_CONST );
+}
+
+// DIM
+// TOS = Variable fuer das Array mit Dimensionsangaben als Parameter
+
+void SbiRuntime::StepDIM()
+{
+ SbxVariableRef refVar = PopVar();
+ DimImpl( refVar );
+}
+
+// #56204 DIM-Funktionalitaet in Hilfsmethode auslagern (step0.cxx)
+void SbiRuntime::DimImpl( SbxVariableRef refVar )
+{
+ SbxArray* pDims = refVar->GetParameters();
+ // Muss eine gerade Anzahl Argumente haben
+ // Man denke daran, dass Arg[0] nicht zaehlt!
+ if( pDims && !( pDims->Count() & 1 ) )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
+ SbxDimArray* pArray = new SbxDimArray( eType );
+ // AB 2.4.1996, auch Arrays ohne Dimensionsangaben zulassen (VB-komp.)
+ if( pDims )
+ {
+ for( USHORT i = 1; i < pDims->Count(); )
+ {
+ INT32 lb = pDims->Get( i++ )->GetLong();
+ INT32 ub = pDims->Get( i++ )->GetLong();
+ if( ub < lb )
+ Error( SbERR_OUT_OF_RANGE ), ub = lb;
+ pArray->AddDim32( lb, ub );
+ if ( lb != ub )
+ pArray->setHasFixedSize( true );
+ }
+ }
+ else
+ {
+ // #62867 Beim Anlegen eines Arrays der Laenge 0 wie bei
+ // Uno-Sequences der Laenge 0 eine Dimension anlegen
+ pArray->unoAddDim( 0, -1 );
+ }
+ USHORT nSavFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->PutObject( pArray );
+ refVar->SetFlags( nSavFlags );
+ refVar->SetParameters( NULL );
+ }
+}
+
+// REDIM
+// TOS = Variable fuer das Array
+// argv = Dimensionsangaben
+
+void SbiRuntime::StepREDIM()
+{
+ // Im Moment ist es nichts anderes als Dim, da doppeltes Dim
+ // bereits vom Compiler erkannt wird.
+ StepDIM();
+}
+
+
+// Helper function for StepREDIMP
+void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex,
+ short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
+{
+ sal_Int32& ri = pActualIndices[nActualDim];
+ for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
+ {
+ if( nActualDim < nMaxDimIndex )
+ {
+ implCopyDimArray( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
+ pActualIndices, pLowerBounds, pUpperBounds );
+ }
+ else
+ {
+ SbxVariable* pSource = pOldArray->Get32( pActualIndices );
+ SbxVariable* pDest = pNewArray->Get32( pActualIndices );
+ if( pSource && pDest )
+ *pDest = *pSource;
+ }
+ }
+}
+
+// REDIM PRESERVE
+// TOS = Variable fuer das Array
+// argv = Dimensionsangaben
+
+void SbiRuntime::StepREDIMP()
+{
+ SbxVariableRef refVar = PopVar();
+ DimImpl( refVar );
+
+ // Now check, if we can copy from the old array
+ if( refRedimpArray.Is() )
+ {
+ SbxBase* pElemObj = refVar->GetObject();
+ SbxDimArray* pNewArray = PTR_CAST(SbxDimArray,pElemObj);
+ SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
+ if( pNewArray )
+ {
+ short nDimsNew = pNewArray->GetDims();
+ short nDimsOld = pOldArray->GetDims();
+ short nDims = nDimsNew;
+ BOOL bRangeError = FALSE;
+
+ // Store dims to use them for copying later
+ sal_Int32* pLowerBounds = new sal_Int32[nDims];
+ sal_Int32* pUpperBounds = new sal_Int32[nDims];
+ sal_Int32* pActualIndices = new sal_Int32[nDims];
+
+ if( nDimsOld != nDimsNew )
+ {
+ bRangeError = TRUE;
+ }
+ else
+ {
+ // Compare bounds
+ for( short i = 1 ; i <= nDims ; i++ )
+ {
+ sal_Int32 lBoundNew, uBoundNew;
+ sal_Int32 lBoundOld, uBoundOld;
+ pNewArray->GetDim32( i, lBoundNew, uBoundNew );
+ pOldArray->GetDim32( i, lBoundOld, uBoundOld );
+
+ /* #69094 Allow all dimensions to be changed
+ although Visual Basic is not able to do so.
+ // All bounds but the last have to be the same
+ if( i < nDims && ( lBoundNew != lBoundOld || uBoundNew != uBoundOld ) )
+ {
+ bRangeError = TRUE;
+ break;
+ }
+ else
+ */
+ {
+ // #69094: if( i == nDims )
+ {
+ lBoundNew = std::max( lBoundNew, lBoundOld );
+ uBoundNew = std::min( uBoundNew, uBoundOld );
+ }
+ short j = i - 1;
+ pActualIndices[j] = pLowerBounds[j] = lBoundNew;
+ pUpperBounds[j] = uBoundNew;
+ }
+ }
+ }
+
+ if( bRangeError )
+ {
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ }
+ else
+ {
+ // Copy data from old array by going recursively through all dimensions
+ // (It would be faster to work on the flat internal data array of an
+ // SbyArray but this solution is clearer and easier)
+ implCopyDimArray( pNewArray, pOldArray, nDims - 1,
+ 0, pActualIndices, pLowerBounds, pUpperBounds );
+ }
+
+ delete[] pUpperBounds;
+ delete[] pLowerBounds;
+ delete[] pActualIndices;
+ refRedimpArray = NULL;
+ }
+ }
+
+ //StarBASIC::FatalError( SbERR_NOT_IMPLEMENTED );
+}
+
+// REDIM_COPY
+// TOS = Array-Variable, Reference to array is copied
+// Variable is cleared as in ERASE
+
+void SbiRuntime::StepREDIMP_ERASE()
+{
+ SbxVariableRef refVar = PopVar();
+ SbxDataType eType = refVar->GetType();
+ if( eType & SbxARRAY )
+ {
+ SbxBase* pElemObj = refVar->GetObject();
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
+ if( pDimArray )
+ {
+ refRedimpArray = pDimArray;
+ }
+
+ // As in ERASE
+ USHORT nSavFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->SetType( SbxDataType(eType & 0x0FFF) );
+ refVar->SetFlags( nSavFlags );
+ refVar->Clear();
+ }
+ else
+ if( refVar->IsFixed() )
+ refVar->Clear();
+ else
+ refVar->SetType( SbxEMPTY );
+}
+
+void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType )
+{
+ USHORT nSavFlags = refVar->GetFlags();
+ refVar->ResetFlag( SBX_FIXED );
+ refVar->SetType( SbxDataType(eType & 0x0FFF) );
+ refVar->SetFlags( nSavFlags );
+ refVar->Clear();
+}
+
+void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled )
+{
+ SbxDataType eType = refVar->GetType();
+ if( eType & SbxARRAY )
+ {
+ if ( bVBAEnabled )
+ {
+ SbxBase* pElemObj = refVar->GetObject();
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
+ bool bClearValues = true;
+ if( pDimArray )
+ {
+ if ( pDimArray->hasFixedSize() )
+ {
+ // Clear all Value(s)
+ pDimArray->SbxArray::Clear();
+ bClearValues = false;
+ }
+ else
+ pDimArray->Clear(); // clear Dims
+ }
+ if ( bClearValues )
+ {
+ SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
+ if ( pArray )
+ pArray->Clear();
+ }
+ }
+ else
+ // AB 2.4.1996
+ // Arrays haben bei Erase nach VB ein recht komplexes Verhalten. Hier
+ // werden zunaechst nur die Typ-Probleme bei REDIM (#26295) beseitigt:
+ // Typ hart auf den Array-Typ setzen, da eine Variable mit Array
+ // SbxOBJECT ist. Bei REDIM entsteht dann ein SbxOBJECT-Array und
+ // der ursruengliche Typ geht verloren -> Laufzeitfehler
+ lcl_clearImpl( refVar, eType );
+ }
+ else
+ if( refVar->IsFixed() )
+ refVar->Clear();
+ else
+ refVar->SetType( SbxEMPTY );
+}
+
+// Variable loeschen
+// TOS = Variable
+
+void SbiRuntime::StepERASE()
+{
+ SbxVariableRef refVar = PopVar();
+ lcl_eraseImpl( refVar, bVBAEnabled );
+}
+
+void SbiRuntime::StepERASE_CLEAR()
+{
+ SbxVariableRef refVar = PopVar();
+ lcl_eraseImpl( refVar, bVBAEnabled );
+ SbxDataType eType = refVar->GetType();
+ lcl_clearImpl( refVar, eType );
+}
+
+void SbiRuntime::StepARRAYACCESS()
+{
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ SbxVariableRef refVar = PopVar();
+ refVar->SetParameters( refArgv );
+ PopArgv();
+ PushVar( CheckArray( refVar ) );
+}
+
+void SbiRuntime::StepBYVAL()
+{
+ // Copy variable on stack to break call by reference
+ SbxVariableRef pVar = PopVar();
+ SbxDataType t = pVar->GetType();
+
+ SbxVariable* pCopyVar = new SbxVariable( t );
+ pCopyVar->SetFlag( SBX_READWRITE );
+ *pCopyVar = *pVar;
+
+ PushVar( pCopyVar );
+}
+
+// Einrichten eines Argvs
+// nOp1 bleibt so -> 1. Element ist Returnwert
+
+void SbiRuntime::StepARGC()
+{
+ PushArgv();
+ refArgv = new SbxArray;
+ nArgc = 1;
+}
+
+// Speichern eines Arguments in Argv
+
+void SbiRuntime::StepARGV()
+{
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ SbxVariableRef pVal = PopVar();
+
+ // Before fix of #94916:
+ // if( pVal->ISA(SbxMethod) || pVal->ISA(SbxProperty) )
+ if( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) )
+ {
+ // Methoden und Properties evaluieren!
+ SbxVariable* pRes = new SbxVariable( *pVal );
+ pVal = pRes;
+ }
+ refArgv->Put( pVal, nArgc++ );
+ }
+}
+
+// Input to Variable. Die Variable ist auf TOS und wird
+// anschliessend entfernt.
+
+void SbiRuntime::StepINPUT()
+{
+ String s;
+ char ch = 0;
+ SbError err;
+ // Skip whitespace
+ while( ( err = pIosys->GetError() ) == 0 )
+ {
+ ch = pIosys->Read();
+ if( ch != ' ' && ch != '\t' && ch != '\n' )
+ break;
+ }
+ if( !err )
+ {
+ // Scan until comma or whitespace
+ char sep = ( ch == '"' ) ? ch : 0;
+ if( sep ) ch = pIosys->Read();
+ while( ( err = pIosys->GetError() ) == 0 )
+ {
+ if( ch == sep )
+ {
+ ch = pIosys->Read();
+ if( ch != sep )
+ break;
+ }
+ else if( !sep && (ch == ',' || ch == '\n') )
+ break;
+ s += ch;
+ ch = pIosys->Read();
+ }
+ // skip whitespace
+ if( ch == ' ' || ch == '\t' )
+ while( ( err = pIosys->GetError() ) == 0 )
+ {
+ if( ch != ' ' && ch != '\t' && ch != '\n' )
+ break;
+ ch = pIosys->Read();
+ }
+ }
+ if( !err )
+ {
+ SbxVariableRef pVar = GetTOS();
+ // Zuerst versuchen, die Variable mit einem numerischen Wert
+ // zu fuellen, dann mit einem Stringwert
+ if( !pVar->IsFixed() || pVar->IsNumeric() )
+ {
+ USHORT nLen = 0;
+ if( !pVar->Scan( s, &nLen ) )
+ {
+ err = SbxBase::GetError();
+ SbxBase::ResetError();
+ }
+ // Der Wert muss komplett eingescant werden
+ else if( nLen != s.Len() && !pVar->PutString( s ) )
+ {
+ err = SbxBase::GetError();
+ SbxBase::ResetError();
+ }
+ else if( nLen != s.Len() && pVar->IsNumeric() )
+ {
+ err = SbxBase::GetError();
+ SbxBase::ResetError();
+ if( !err )
+ err = SbERR_CONVERSION;
+ }
+ }
+ else
+ {
+ pVar->PutString( s );
+ err = SbxBase::GetError();
+ SbxBase::ResetError();
+ }
+ }
+ if( err == SbERR_USER_ABORT )
+ Error( err );
+ else if( err )
+ {
+ if( pRestart && !pIosys->GetChannel() )
+ {
+ BasResId aId( IDS_SBERR_START + 4 );
+ String aMsg( aId );
+
+ //****** DONT CHECK IN, TEST ONLY *******
+ //****** DONT CHECK IN, TEST ONLY *******
+ // ErrorBox( NULL, WB_OK, aMsg ).Execute();
+ //****** DONT CHECK IN, TEST ONLY *******
+ //****** DONT CHECK IN, TEST ONLY *******
+
+ pCode = pRestart;
+ }
+ else
+ Error( err );
+ }
+ else
+ {
+ // pIosys->ResetChannel();
+ PopVar();
+ }
+}
+
+// Line Input to Variable. Die Variable ist auf TOS und wird
+// anschliessend entfernt.
+
+void SbiRuntime::StepLINPUT()
+{
+ ByteString aInput;
+ pIosys->Read( aInput );
+ Error( pIosys->GetError() );
+ SbxVariableRef p = PopVar();
+ p->PutString( String( aInput, gsl_getSystemTextEncoding() ) );
+ // pIosys->ResetChannel();
+}
+
+// Programmende
+
+void SbiRuntime::StepSTOP()
+{
+ pInst->Stop();
+}
+
+// FOR-Variable initialisieren
+
+void SbiRuntime::StepINITFOR()
+{
+ PushFor();
+}
+
+void SbiRuntime::StepINITFOREACH()
+{
+ PushForEach();
+}
+
+// FOR-Variable inkrementieren
+
+void SbiRuntime::StepNEXT()
+{
+ if( !pForStk )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return;
+ }
+ if( pForStk->eForType == FOR_TO )
+ pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
+}
+
+// Anfang CASE: TOS in CASE-Stack
+
+void SbiRuntime::StepCASE()
+{
+ if( !refCaseStk.Is() )
+ refCaseStk = new SbxArray;
+ SbxVariableRef xVar = PopVar();
+ refCaseStk->Put( xVar, refCaseStk->Count() );
+}
+
+// Ende CASE: Variable freigeben
+
+void SbiRuntime::StepENDCASE()
+{
+ if( !refCaseStk || !refCaseStk->Count() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ refCaseStk->Remove( refCaseStk->Count() - 1 );
+}
+
+// Standard-Fehlerbehandlung
+
+void SbiRuntime::StepSTDERROR()
+{
+ pError = NULL; bError = TRUE;
+ pInst->aErrorMsg = String();
+ pInst->nErr = 0L;
+ pInst->nErl = 0;
+ nError = 0L;
+ SbxErrObject::getUnoErrObject()->Clear();
+}
+
+void SbiRuntime::StepNOERROR()
+{
+ pInst->aErrorMsg = String();
+ pInst->nErr = 0L;
+ pInst->nErl = 0;
+ nError = 0L;
+ SbxErrObject::getUnoErrObject()->Clear();
+ bError = FALSE;
+}
+
+// UP verlassen
+
+void SbiRuntime::StepLEAVE()
+{
+ bRun = FALSE;
+ // If VBA and we are leaving an ErrorHandler then clear the error ( it's been processed )
+ if ( bInError && pError )
+ SbxErrObject::getUnoErrObject()->Clear();
+}
+
+void SbiRuntime::StepCHANNEL() // TOS = Kanalnummer
+{
+ SbxVariableRef pChan = PopVar();
+ short nChan = pChan->GetInteger();
+ pIosys->SetChannel( nChan );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepCHANNEL0()
+{
+ pIosys->ResetChannel();
+}
+
+void SbiRuntime::StepPRINT() // print TOS
+{
+ SbxVariableRef p = PopVar();
+ String s1 = p->GetString();
+ String s;
+ if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
+ s = ' '; // ein Blank davor
+ s += s1;
+ ByteString aByteStr( s, gsl_getSystemTextEncoding() );
+ pIosys->Write( aByteStr );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepPRINTF() // print TOS in field
+{
+ SbxVariableRef p = PopVar();
+ String s1 = p->GetString();
+ String s;
+ if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
+ s = ' '; // ein Blank davor
+ s += s1;
+ s.Expand( 14, ' ' );
+ ByteString aByteStr( s, gsl_getSystemTextEncoding() );
+ pIosys->Write( aByteStr );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepWRITE() // write TOS
+{
+ SbxVariableRef p = PopVar();
+ // Muss der String gekapselt werden?
+ char ch = 0;
+ switch (p->GetType() )
+ {
+ case SbxSTRING: ch = '"'; break;
+ case SbxCURRENCY:
+ case SbxBOOL:
+ case SbxDATE: ch = '#'; break;
+ default: break;
+ }
+ String s;
+ if( ch )
+ s += ch;
+ s += p->GetString();
+ if( ch )
+ s += ch;
+ ByteString aByteStr( s, gsl_getSystemTextEncoding() );
+ pIosys->Write( aByteStr );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos
+{
+ SbxVariableRef pTos1 = PopVar();
+ SbxVariableRef pTos = PopVar();
+ String aDest = pTos1->GetString();
+ String aSource = pTos->GetString();
+
+ // <-- UCB
+ if( hasUno() )
+ {
+ implStepRenameUCB( aSource, aDest );
+ }
+ else
+ // --> UCB
+ {
+#ifdef _OLD_FILE_IMPL
+ DirEntry aSourceDirEntry( aSource );
+ if( aSourceDirEntry.Exists() )
+ {
+ if( aSourceDirEntry.MoveTo( DirEntry(aDest) ) != FSYS_ERR_OK )
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+ }
+ else
+ StarBASIC::Error( SbERR_PATH_NOT_FOUND );
+#else
+ implStepRenameOSL( aSource, aDest );
+#endif
+ }
+}
+
+// TOS = Prompt
+
+void SbiRuntime::StepPROMPT()
+{
+ SbxVariableRef p = PopVar();
+ ByteString aStr( p->GetString(), gsl_getSystemTextEncoding() );
+ pIosys->SetPrompt( aStr );
+}
+
+// Set Restart point
+
+void SbiRuntime::StepRESTART()
+{
+ pRestart = pCode;
+}
+
+// Leerer Ausdruck auf Stack fuer fehlenden Parameter
+
+void SbiRuntime::StepEMPTY()
+{
+ // #57915 Die Semantik von StepEMPTY() ist die Repraesentation eines fehlenden
+ // Arguments. Dies wird in VB durch ein durch den Wert 448 (SbERR_NAMED_NOT_FOUND)
+ // vom Typ Error repraesentiert. StepEmpty jetzt muesste besser StepMISSING()
+ // heissen, aber der Name wird der Einfachkeit halber beibehalten.
+ SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
+ xVar->PutErr( 448 );
+ PushVar( xVar );
+ // ALT: PushVar( new SbxVariable( SbxEMPTY ) );
+}
+
+// TOS = Fehlercode
+
+void SbiRuntime::StepERROR()
+{
+ SbxVariableRef refCode = PopVar();
+ USHORT n = refCode->GetUShort();
+ SbError error = StarBASIC::GetSfxFromVBError( n );
+ if ( bVBAEnabled )
+ pInst->Error( error );
+ else
+ Error( error );
+}
+
diff --git a/basic/source/runtime/step1.cxx b/basic/source/runtime/step1.cxx
new file mode 100644
index 000000000000..e23ef864218e
--- /dev/null
+++ b/basic/source/runtime/step1.cxx
@@ -0,0 +1,574 @@
+/*************************************************************************
+ *
+ * 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 <stdlib.h>
+#include <rtl/math.hxx>
+#include <basic/sbuno.hxx>
+#include "runtime.hxx"
+#include "sbintern.hxx"
+#include "iosys.hxx"
+#include "image.hxx"
+#include "sbunoobj.hxx"
+#include "errobject.hxx"
+
+bool checkUnoObjectType( SbUnoObject* refVal,
+ const String& aClass );
+
+// Laden einer numerischen Konstanten (+ID)
+
+void SbiRuntime::StepLOADNC( UINT32 nOp1 )
+{
+ SbxVariable* p = new SbxVariable( SbxDOUBLE );
+
+ // #57844 Lokalisierte Funktion benutzen
+ String aStr = pImg->GetString( static_cast<short>( nOp1 ) );
+ // Auch , zulassen !!!
+ USHORT iComma = aStr.Search( ',' );
+ if( iComma != STRING_NOTFOUND )
+ {
+ String aStr1 = aStr.Copy( 0, iComma );
+ String aStr2 = aStr.Copy( iComma + 1 );
+ aStr = aStr1;
+ aStr += '.';
+ aStr += aStr2;
+ }
+ double n = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
+
+ p->PutDouble( n );
+ PushVar( p );
+}
+
+// Laden einer Stringkonstanten (+ID)
+
+void SbiRuntime::StepLOADSC( UINT32 nOp1 )
+{
+ SbxVariable* p = new SbxVariable;
+ p->PutString( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ PushVar( p );
+}
+
+// Immediate Load (+Wert)
+
+void SbiRuntime::StepLOADI( UINT32 nOp1 )
+{
+ SbxVariable* p = new SbxVariable;
+ p->PutInteger( static_cast<INT16>( nOp1 ) );
+ PushVar( p );
+}
+
+// Speichern eines named Arguments in Argv (+Arg-Nr ab 1!)
+
+void SbiRuntime::StepARGN( UINT32 nOp1 )
+{
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ String aAlias( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxVariableRef pVal = PopVar();
+ refArgv->Put( pVal, nArgc );
+ refArgv->PutAlias( aAlias, nArgc++ );
+ }
+}
+
+// Konvertierung des Typs eines Arguments in Argv fuer DECLARE-Fkt. (+Typ)
+
+void SbiRuntime::StepARGTYP( UINT32 nOp1 )
+{
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ BOOL bByVal = (nOp1 & 0x8000) != 0; // Ist BYVAL verlangt?
+ SbxDataType t = (SbxDataType) (nOp1 & 0x7FFF);
+ SbxVariable* pVar = refArgv->Get( refArgv->Count() - 1 ); // letztes Arg
+
+ // BYVAL prüfen
+ if( pVar->GetRefCount() > 2 ) // 2 ist normal für BYVAL
+ {
+ // Parameter ist eine Referenz
+ if( bByVal )
+ {
+ // Call by Value ist verlangt -> Kopie anlegen
+ pVar = new SbxVariable( *pVar );
+ pVar->SetFlag( SBX_READWRITE );
+ refExprStk->Put( pVar, refArgv->Count() - 1 );
+ }
+ else
+ pVar->SetFlag( SBX_REFERENCE ); // Ref-Flag für DllMgr
+ }
+ else
+ {
+ // Parameter ist KEINE Referenz
+ if( bByVal )
+ pVar->ResetFlag( SBX_REFERENCE ); // Keine Referenz -> OK
+ else
+ Error( SbERR_BAD_PARAMETERS ); // Referenz verlangt
+ }
+
+ if( pVar->GetType() != t )
+ {
+ // Variant, damit richtige Konvertierung
+ // Ausserdem Fehler, wenn SbxBYREF
+ pVar->Convert( SbxVARIANT );
+ pVar->Convert( t );
+ }
+ }
+}
+
+// String auf feste Laenge bringen (+Laenge)
+
+void SbiRuntime::StepPAD( UINT32 nOp1 )
+{
+ SbxVariable* p = GetTOS();
+ String& s = (String&)(const String&) *p;
+ if( s.Len() > nOp1 )
+ s.Erase( static_cast<xub_StrLen>( nOp1 ) );
+ else
+ s.Expand( static_cast<xub_StrLen>( nOp1 ), ' ' );
+}
+
+// Sprung (+Target)
+
+void SbiRuntime::StepJUMP( UINT32 nOp1 )
+{
+#ifdef DBG_UTIL
+ // #QUESTION shouln't this be
+ // if( (BYTE*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() )
+ if( nOp1 >= pImg->GetCodeSize() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+#endif
+ pCode = (const BYTE*) pImg->GetCode() + nOp1;
+}
+
+// TOS auswerten, bedingter Sprung (+Target)
+
+void SbiRuntime::StepJUMPT( UINT32 nOp1 )
+{
+ SbxVariableRef p = PopVar();
+ if( p->GetBool() )
+ StepJUMP( nOp1 );
+}
+
+// TOS auswerten, bedingter Sprung (+Target)
+
+void SbiRuntime::StepJUMPF( UINT32 nOp1 )
+{
+ SbxVariableRef p = PopVar();
+ if( !p->GetBool() )
+ StepJUMP( nOp1 );
+}
+
+// TOS auswerten, Sprung in JUMP-Tabelle (+MaxVal)
+// Sieht so aus:
+// ONJUMP 2
+// JUMP target1
+// JUMP target2
+// ...
+//Falls im Operanden 0x8000 gesetzt ist, Returnadresse pushen (ON..GOSUB)
+
+void SbiRuntime::StepONJUMP( UINT32 nOp1 )
+{
+ SbxVariableRef p = PopVar();
+ INT16 n = p->GetInteger();
+ if( nOp1 & 0x8000 )
+ {
+ nOp1 &= 0x7FFF;
+ //PushGosub( pCode + 3 * nOp1 );
+ PushGosub( pCode + 5 * nOp1 );
+ }
+ if( n < 1 || static_cast<UINT32>(n) > nOp1 )
+ n = static_cast<INT16>( nOp1 + 1 );
+ //nOp1 = (UINT32) ( (const char*) pCode - pImg->GetCode() ) + 3 * --n;
+ nOp1 = (UINT32) ( (const char*) pCode - pImg->GetCode() ) + 5 * --n;
+ StepJUMP( nOp1 );
+}
+
+// UP-Aufruf (+Target)
+
+void SbiRuntime::StepGOSUB( UINT32 nOp1 )
+{
+ PushGosub( pCode );
+ if( nOp1 >= pImg->GetCodeSize() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ pCode = (const BYTE*) pImg->GetCode() + nOp1;
+}
+
+// UP-Return (+0 oder Target)
+
+void SbiRuntime::StepRETURN( UINT32 nOp1 )
+{
+ PopGosub();
+ if( nOp1 )
+ StepJUMP( nOp1 );
+}
+
+// FOR-Variable testen (+Endlabel)
+
+void SbiRuntime::StepTESTFOR( UINT32 nOp1 )
+{
+ if( !pForStk )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return;
+ }
+
+ bool bEndLoop = false;
+ switch( pForStk->eForType )
+ {
+ case FOR_TO:
+ {
+ SbxOperator eOp = ( pForStk->refInc->GetDouble() < 0 ) ? SbxLT : SbxGT;
+ if( pForStk->refVar->Compare( eOp, *pForStk->refEnd ) )
+ bEndLoop = true;
+ break;
+ }
+ case FOR_EACH_ARRAY:
+ {
+ SbiForStack* p = pForStk;
+ if( p->pArrayCurIndices == NULL )
+ {
+ bEndLoop = true;
+ }
+ else
+ {
+ SbxDimArray* pArray = (SbxDimArray*)(SbxVariable*)p->refEnd;
+ short nDims = pArray->GetDims();
+
+ // Empty array?
+ if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] )
+ {
+ bEndLoop = true;
+ break;
+ }
+ SbxVariable* pVal = pArray->Get32( p->pArrayCurIndices );
+ *(p->refVar) = *pVal;
+
+ bool bFoundNext = false;
+ for( short i = 0 ; i < nDims ; i++ )
+ {
+ if( p->pArrayCurIndices[i] < p->pArrayUpperBounds[i] )
+ {
+ bFoundNext = true;
+ p->pArrayCurIndices[i]++;
+ for( short j = i - 1 ; j >= 0 ; j-- )
+ p->pArrayCurIndices[j] = p->pArrayLowerBounds[j];
+ break;
+ }
+ }
+ if( !bFoundNext )
+ {
+ delete[] p->pArrayCurIndices;
+ p->pArrayCurIndices = NULL;
+ }
+ }
+ break;
+ }
+ case FOR_EACH_COLLECTION:
+ {
+ BasicCollection* pCollection = (BasicCollection*)(SbxVariable*)pForStk->refEnd;
+ SbxArrayRef xItemArray = pCollection->xItemArray;
+ INT32 nCount = xItemArray->Count32();
+ if( pForStk->nCurCollectionIndex < nCount )
+ {
+ SbxVariable* pRes = xItemArray->Get32( pForStk->nCurCollectionIndex );
+ pForStk->nCurCollectionIndex++;
+ (*pForStk->refVar) = *pRes;
+ }
+ else
+ {
+ bEndLoop = true;
+ }
+ break;
+ }
+ case FOR_EACH_XENUMERATION:
+ {
+ SbiForStack* p = pForStk;
+ if( p->xEnumeration->hasMoreElements() )
+ {
+ Any aElem = p->xEnumeration->nextElement();
+ SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
+ unoToSbxValue( (SbxVariable*)xVar, aElem );
+ (*pForStk->refVar) = *xVar;
+ }
+ else
+ {
+ bEndLoop = true;
+ }
+ break;
+ }
+ }
+ if( bEndLoop )
+ {
+ PopFor();
+ StepJUMP( nOp1 );
+ }
+}
+
+// Tos+1 <= Tos+2 <= Tos, 2xremove (+Target)
+
+void SbiRuntime::StepCASETO( UINT32 nOp1 )
+{
+ if( !refCaseStk || !refCaseStk->Count() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ SbxVariableRef xTo = PopVar();
+ SbxVariableRef xFrom = PopVar();
+ SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
+ if( *xCase >= *xFrom && *xCase <= *xTo )
+ StepJUMP( nOp1 );
+ }
+}
+
+// Fehler-Handler
+
+void SbiRuntime::StepERRHDL( UINT32 nOp1 )
+{
+ const BYTE* p = pCode;
+ StepJUMP( nOp1 );
+ pError = pCode;
+ pCode = p;
+ pInst->aErrorMsg = String();
+ pInst->nErr = 0;
+ pInst->nErl = 0;
+ nError = 0;
+ SbxErrObject::getUnoErrObject()->Clear();
+}
+
+// Resume nach Fehlern (+0=statement, 1=next or Label)
+
+void SbiRuntime::StepRESUME( UINT32 nOp1 )
+{
+ // AB #32714 Resume ohne Error? -> Fehler
+ if( !bInError )
+ {
+ Error( SbERR_BAD_RESUME );
+ return;
+ }
+ if( nOp1 )
+ {
+ // Code-Zeiger auf naechstes Statement setzen
+ USHORT n1, n2;
+ pCode = pMod->FindNextStmnt( pErrCode, n1, n2, TRUE, pImg );
+ }
+ else
+ pCode = pErrStmnt;
+ if ( pError ) // current in error handler ( and got a Resume Next statment )
+ SbxErrObject::getUnoErrObject()->Clear();
+
+ if( nOp1 > 1 )
+ StepJUMP( nOp1 );
+ pInst->aErrorMsg = String();
+ pInst->nErr = 0;
+ pInst->nErl = 0;
+ nError = 0;
+ bInError = FALSE;
+
+ // Error-Stack loeschen
+ SbErrorStack*& rErrStack = GetSbData()->pErrStack;
+ delete rErrStack;
+ rErrStack = NULL;
+}
+
+// Kanal schliessen (+Kanal, 0=Alle)
+void SbiRuntime::StepCLOSE( UINT32 nOp1 )
+{
+ SbError err;
+ if( !nOp1 )
+ pIosys->Shutdown();
+ else
+ {
+ err = pIosys->GetError();
+ if( !err )
+ {
+ pIosys->Close();
+ }
+ }
+ err = pIosys->GetError();
+ Error( err );
+}
+
+// Zeichen ausgeben (+char)
+
+void SbiRuntime::StepPRCHAR( UINT32 nOp1 )
+{
+ ByteString s( (char) nOp1 );
+ pIosys->Write( s );
+ Error( pIosys->GetError() );
+}
+
+// Check, ob TOS eine bestimmte Objektklasse ist (+StringID)
+
+bool SbiRuntime::implIsClass( SbxObject* pObj, const String& aClass )
+{
+ bool bRet = true;
+
+ if( aClass.Len() != 0 )
+ {
+ bRet = pObj->IsClass( aClass );
+ if( !bRet )
+ bRet = aClass.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("object") ) );
+ if( !bRet )
+ {
+ String aObjClass = pObj->GetClassName();
+ SbModule* pClassMod = pCLASSFAC->FindClass( aObjClass );
+ SbClassData* pClassData;
+ if( pClassMod && (pClassData=pClassMod->pClassData) != NULL )
+ {
+ SbxVariable* pClassVar =
+ pClassData->mxIfaces->Find( aClass, SbxCLASS_DONTCARE );
+ bRet = (pClassVar != NULL);
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SbiRuntime::checkClass_Impl( const SbxVariableRef& refVal,
+ const String& aClass, bool bRaiseErrors, bool bDefault )
+{
+ bool bOk = bDefault;
+
+ SbxDataType t = refVal->GetType();
+ if( t == SbxOBJECT )
+ {
+ SbxObject* pObj;
+ SbxVariable* pVal = (SbxVariable*)refVal;
+ if( pVal->IsA( TYPE(SbxObject) ) )
+ pObj = (SbxObject*) pVal;
+ else
+ {
+ pObj = (SbxObject*) refVal->GetObject();
+ if( pObj && !pObj->IsA( TYPE(SbxObject) ) )
+ pObj = NULL;
+ }
+ if( pObj )
+ {
+ if( !implIsClass( pObj, aClass ) )
+ {
+ if ( bVBAEnabled && pObj->IsA( TYPE(SbUnoObject) ) )
+ {
+ SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
+ bOk = checkUnoObjectType( pUnoObj, aClass );
+ }
+ else
+ bOk = false;
+ if ( !bOk )
+ {
+ if( bRaiseErrors )
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ }
+ else
+ {
+ bOk = true;
+
+ SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pObj);
+ if( pClassModuleObject != NULL )
+ pClassModuleObject->triggerInitializeEvent();
+ }
+ }
+ }
+ else
+ {
+ if ( !bVBAEnabled )
+ {
+ if( bRaiseErrors )
+ Error( SbERR_NEEDS_OBJECT );
+ bOk = false;
+ }
+ }
+ return bOk;
+}
+
+void SbiRuntime::StepSETCLASS_impl( UINT32 nOp1, bool bHandleDflt )
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ String aClass( pImg->GetString( static_cast<short>( nOp1 ) ) );
+
+ bool bOk = checkClass_Impl( refVal, aClass, true );
+ if( bOk )
+ StepSET_Impl( refVal, refVar, bHandleDflt ); // don't do handle dflt prop for a "proper" set
+}
+
+void SbiRuntime::StepVBASETCLASS( UINT32 nOp1 )
+{
+ StepSETCLASS_impl( nOp1, false );
+}
+
+void SbiRuntime::StepSETCLASS( UINT32 nOp1 )
+{
+ StepSETCLASS_impl( nOp1, true );
+}
+
+void SbiRuntime::StepTESTCLASS( UINT32 nOp1 )
+{
+ SbxVariableRef xObjVal = PopVar();
+ String aClass( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ bool bDefault = !bVBAEnabled;
+ bool bOk = checkClass_Impl( xObjVal, aClass, false, bDefault );
+
+ SbxVariable* pRet = new SbxVariable;
+ pRet->PutBool( bOk );
+ PushVar( pRet );
+}
+
+// Library fuer anschliessenden Declare-Call definieren
+
+void SbiRuntime::StepLIB( UINT32 nOp1 )
+{
+ aLibName = pImg->GetString( static_cast<short>( nOp1 ) );
+}
+
+// TOS wird um BASE erhoeht, BASE davor gepusht (+BASE)
+// Dieser Opcode wird vor DIM/REDIM-Anweisungen gepusht,
+// wenn nur ein Index angegeben wurde.
+
+void SbiRuntime::StepBASED( UINT32 nOp1 )
+{
+ SbxVariable* p1 = new SbxVariable;
+ SbxVariableRef x2 = PopVar();
+
+ // #109275 Check compatiblity mode
+ bool bCompatible = ((nOp1 & 0x8000) != 0);
+ USHORT uBase = static_cast<USHORT>(nOp1 & 1); // Can only be 0 or 1
+ p1->PutInteger( uBase );
+ if( !bCompatible )
+ x2->Compute( SbxPLUS, *p1 );
+ PushVar( x2 ); // erst die Expr
+ PushVar( p1 ); // dann die Base
+}
+
+
+
+
+
diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx
new file mode 100755
index 000000000000..587b0ae7a590
--- /dev/null
+++ b/basic/source/runtime/step2.cxx
@@ -0,0 +1,1261 @@
+/*************************************************************************
+ *
+ * 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 "runtime.hxx"
+#ifndef GCC
+#endif
+#include "iosys.hxx"
+#include "image.hxx"
+#include "sbintern.hxx"
+#include "sbunoobj.hxx"
+#include "opcodes.hxx"
+
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/script/XDefaultMethod.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <comphelper/processfactory.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::container;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::script;
+
+using com::sun::star::uno::Reference;
+
+SbxVariable* getVBAConstant( const String& rName );
+
+// Suchen eines Elements
+// Die Bits im String-ID:
+// 0x8000 - Argv ist belegt
+
+SbxVariable* SbiRuntime::FindElement
+ ( SbxObject* pObj, UINT32 nOp1, UINT32 nOp2, SbError nNotFound, BOOL bLocal, BOOL bStatic )
+{
+ bool bIsVBAInterOp = SbiRuntime::isVBAEnabled();
+ if( bIsVBAInterOp )
+ {
+ StarBASIC* pMSOMacroRuntimeLib = GetSbData()->pMSOMacroRuntimLib;
+ if( pMSOMacroRuntimeLib != NULL )
+ pMSOMacroRuntimeLib->ResetFlag( SBX_EXTSEARCH );
+ }
+
+ SbxVariable* pElem = NULL;
+ if( !pObj )
+ {
+ Error( SbERR_NO_OBJECT );
+ pElem = new SbxVariable;
+ }
+ else
+ {
+ BOOL bFatalError = FALSE;
+ SbxDataType t = (SbxDataType) nOp2;
+ String aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
+ // Hacky capture of Evaluate [] syntax
+ // this should be tackled I feel at the pcode level
+ if ( bIsVBAInterOp && aName.Search('[') == 0 )
+ {
+ // emulate pcode here
+ StepARGC();
+ // psuedo StepLOADSC
+ String sArg = aName.Copy( 1, aName.Len() - 2 );
+ SbxVariable* p = new SbxVariable;
+ p->PutString( sArg );
+ PushVar( p );
+ //
+ StepARGV();
+ nOp1 = nOp1 | 0x8000; // indicate params are present
+ aName = String::CreateFromAscii("Evaluate");
+ }
+ if( bLocal )
+ {
+ if ( bStatic )
+ {
+ if ( pMeth )
+ pElem = pMeth->GetStatics()->Find( aName, SbxCLASS_DONTCARE );
+ }
+
+ if ( !pElem )
+ pElem = refLocals->Find( aName, SbxCLASS_DONTCARE );
+ }
+ if( !pElem )
+ {
+ // Die RTL brauchen wir nicht mehr zu durchsuchen!
+ BOOL bSave = rBasic.bNoRtl;
+ rBasic.bNoRtl = TRUE;
+ pElem = pObj->Find( aName, SbxCLASS_DONTCARE );
+
+ // #110004, #112015: Make private really private
+ if( bLocal && pElem ) // Local as flag for global search
+ {
+ if( pElem->IsSet( SBX_PRIVATE ) )
+ {
+ SbiInstance* pInst_ = pINST;
+ if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() )
+ pElem = NULL; // Found but in wrong module!
+
+ // Interfaces: Use SBX_EXTFOUND
+ }
+ }
+ rBasic.bNoRtl = bSave;
+
+ // Ist es ein globaler Uno-Bezeichner?
+ if( bLocal && !pElem )
+ {
+ bool bSetName = true; // preserve normal behaviour
+
+ // i#i68894# if VBAInterOp favour searching vba globals
+ // over searching for uno classess
+ if ( bVBAEnabled )
+ {
+ // Try Find in VBA symbols space
+ pElem = rBasic.VBAFind( aName, SbxCLASS_DONTCARE );
+ if ( pElem )
+ bSetName = false; // don't overwrite uno name
+ else
+ pElem = getVBAConstant( aName );
+ }
+ // #72382 VORSICHT! Liefert jetzt wegen unbekannten
+ // Modulen IMMER ein Ergebnis!
+ SbUnoClass* pUnoClass = findUnoClass( aName );
+ if( pUnoClass )
+ {
+ pElem = new SbxVariable( t );
+ SbxValues aRes( SbxOBJECT );
+ aRes.pObj = pUnoClass;
+ pElem->SbxVariable::Put( aRes );
+ }
+
+ // #62939 Wenn eine Uno-Klasse gefunden wurde, muss
+ // das Wrapper-Objekt gehalten werden, da sonst auch
+ // die Uno-Klasse, z.B. "stardiv" immer wieder neu
+ // aus der Registry gelesen werden muss
+ if( pElem )
+ {
+ // #63774 Darf nicht mit gespeichert werden!!!
+ pElem->SetFlag( SBX_DONTSTORE );
+ pElem->SetFlag( SBX_NO_MODIFY);
+
+ // #72382 Lokal speichern, sonst werden alle implizit
+ // deklarierten Vars automatisch global !
+ if ( bSetName )
+ pElem->SetName( aName );
+ refLocals->Put( pElem, refLocals->Count() );
+ }
+ }
+
+ if( !pElem )
+ {
+ // Nicht da und nicht im Objekt?
+ // Hat das Ding Parameter, nicht einrichten!
+ if( nOp1 & 0x8000 )
+ bFatalError = TRUE;
+ // ALT: StarBASIC::FatalError( nNotFound );
+
+ // Sonst, falls keine Parameter sind, anderen Error Code verwenden
+ if( !bLocal || pImg->GetFlag( SBIMG_EXPLICIT ) )
+ {
+ // #39108 Bei explizit und als ELEM immer ein Fatal Error
+ bFatalError = TRUE;
+
+ // Falls keine Parameter sind, anderen Error Code verwenden
+ if( !( nOp1 & 0x8000 ) && nNotFound == SbERR_PROC_UNDEFINED )
+ nNotFound = SbERR_VAR_UNDEFINED;
+ }
+ if( bFatalError )
+ {
+ // #39108 Statt FatalError zu setzen, Dummy-Variable liefern
+ if( !xDummyVar.Is() )
+ xDummyVar = new SbxVariable( SbxVARIANT );
+ pElem = xDummyVar;
+
+ // Parameter von Hand loeschen
+ ClearArgvStack();
+
+ // Normalen Error setzen
+ Error( nNotFound, aName );
+ }
+ else
+ {
+ if ( bStatic )
+ pElem = StepSTATIC_Impl( aName, t );
+ if ( !pElem )
+ {
+ // Sonst Variable neu anlegen
+ pElem = new SbxVariable( t );
+ if( t != SbxVARIANT )
+ pElem->SetFlag( SBX_FIXED );
+ pElem->SetName( aName );
+ refLocals->Put( pElem, refLocals->Count() );
+ }
+ }
+ }
+ }
+ // #39108 Args koennen schon geloescht sein!
+ if( !bFatalError )
+ SetupArgs( pElem, nOp1 );
+ // Ein bestimmter Call-Type wurde gewuenscht, daher muessen
+ // wir hier den Typ setzen und das Ding anfassen, um den
+ // korrekten Returnwert zu erhalten!
+ if( pElem->IsA( TYPE(SbxMethod) ) )
+ {
+ // Soll der Typ konvertiert werden?
+ SbxDataType t2 = pElem->GetType();
+ BOOL bSet = FALSE;
+ if( !( pElem->GetFlags() & SBX_FIXED ) )
+ {
+ if( t != SbxVARIANT && t != t2 &&
+ t >= SbxINTEGER && t <= SbxSTRING )
+ pElem->SetType( t ), bSet = TRUE;
+ }
+ // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen
+ SbxVariableRef refTemp = pElem;
+
+ // Moegliche Reste vom letzten Aufruf der SbxMethod beseitigen
+ // Vorher Schreiben freigeben, damit kein Error gesetzt wird.
+ USHORT nSavFlags = pElem->GetFlags();
+ pElem->SetFlag( SBX_READWRITE | SBX_NO_BROADCAST );
+ pElem->SbxValue::Clear();
+ pElem->SetFlags( nSavFlags );
+
+ // Erst nach dem Setzen anfassen, da z.B. LEFT()
+ // den Unterschied zwischen Left$() und Left() kennen muss
+
+ // AB 12.8.96: Da in PopVar() die Parameter von Methoden weggehauen
+ // werden, muessen wir hier explizit eine neue SbxMethod anlegen
+ SbxVariable* pNew = new SbxMethod( *((SbxMethod*)pElem) ); // das ist der Call!
+ //ALT: SbxVariable* pNew = new SbxVariable( *pElem ); // das ist der Call!
+
+ pElem->SetParameters(0); // sonst bleibt Ref auf sich selbst
+ pNew->SetFlag( SBX_READWRITE );
+
+ // den Datentypen zuruecksetzen?
+ if( bSet )
+ pElem->SetType( t2 );
+ pElem = pNew;
+ }
+ // Index-Access bei UnoObjekten beruecksichtigen
+ // definitely we want this for VBA where properties are often
+ // collections ( which need index access ), but lets only do
+ // this if we actually have params following
+ else if( bVBAEnabled && pElem->ISA(SbUnoProperty) && pElem->GetParameters() )
+ {
+ // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen
+ SbxVariableRef refTemp = pElem;
+
+ // Variable kopieren und dabei den Notify aufloesen
+ SbxVariable* pNew = new SbxVariable( *((SbxVariable*)pElem) ); // das ist der Call!
+ pElem->SetParameters( NULL ); // sonst bleibt Ref auf sich selbst
+ pElem = pNew;
+ }
+ }
+ return CheckArray( pElem );
+}
+
+// Find-Funktion ueber Name fuer aktuellen Scope (z.B. Abfrage aus BASIC-IDE)
+SbxBase* SbiRuntime::FindElementExtern( const String& rName )
+{
+ // Hinweis zu #35281#: Es darf nicht davon ausgegangen werden, dass
+ // pMeth != null, da im RunInit noch keine gesetzt ist.
+
+ SbxVariable* pElem = NULL;
+ if( !pMod || !rName.Len() )
+ return NULL;
+
+ // Lokal suchen
+ if( refLocals )
+ pElem = refLocals->Find( rName, SbxCLASS_DONTCARE );
+
+ // In Statics suchen
+ if ( !pElem && pMeth )
+ {
+ // Bei Statics, Name der Methode davor setzen
+ String aMethName = pMeth->GetName();
+ aMethName += ':';
+ aMethName += rName;
+ pElem = pMod->Find(aMethName, SbxCLASS_DONTCARE);
+ }
+
+ // In Parameter-Liste suchen
+ if( !pElem && pMeth )
+ {
+ SbxInfo* pInfo = pMeth->GetInfo();
+ if( pInfo && refParams )
+ {
+ USHORT nParamCount = refParams->Count();
+ USHORT j = 1;
+ const SbxParamInfo* pParam = pInfo->GetParam( j );
+ while( pParam )
+ {
+ if( pParam->aName.EqualsIgnoreCaseAscii( rName ) )
+ {
+ if( j >= nParamCount )
+ {
+ // Parameter is missing
+ pElem = new SbxVariable( SbxSTRING );
+ pElem->PutString( String( RTL_CONSTASCII_USTRINGPARAM("<missing parameter>" ) ) );
+ }
+ else
+ {
+ pElem = refParams->Get( j );
+ }
+ break;
+ }
+ pParam = pInfo->GetParam( ++j );
+ }
+ }
+ }
+
+ // Im Modul suchen
+ if( !pElem )
+ {
+ // RTL nicht durchsuchen!
+ BOOL bSave = rBasic.bNoRtl;
+ rBasic.bNoRtl = TRUE;
+ pElem = pMod->Find( rName, SbxCLASS_DONTCARE );
+ rBasic.bNoRtl = bSave;
+ }
+ return pElem;
+}
+
+
+// Argumente eines Elements setzen
+// Dabei auch die Argumente umsetzen, falls benannte Parameter
+// verwendet wurden
+
+void SbiRuntime::SetupArgs( SbxVariable* p, UINT32 nOp1 )
+{
+ if( nOp1 & 0x8000 )
+ {
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ BOOL bHasNamed = FALSE;
+ USHORT i;
+ USHORT nArgCount = refArgv->Count();
+ for( i = 1 ; i < nArgCount ; i++ )
+ {
+ if( refArgv->GetAlias( i ).Len() )
+ {
+ bHasNamed = TRUE; break;
+ }
+ }
+ if( bHasNamed )
+ {
+ // Wir haben mindestens einen benannten Parameter!
+ // Wir muessen also umsortieren
+ // Gibt es Parameter-Infos?
+ SbxInfo* pInfo = p->GetInfo();
+ if( !pInfo )
+ {
+ bool bError_ = true;
+
+ SbUnoMethod* pUnoMethod = PTR_CAST(SbUnoMethod,p);
+ SbUnoProperty* pUnoProperty = PTR_CAST(SbUnoProperty,p);
+ if( pUnoMethod || pUnoProperty )
+ {
+ SbUnoObject* pParentUnoObj = PTR_CAST( SbUnoObject,p->GetParent() );
+ if( pParentUnoObj )
+ {
+ Any aUnoAny = pParentUnoObj->getUnoAny();
+ Reference< XInvocation > xInvocation;
+ aUnoAny >>= xInvocation;
+ if( xInvocation.is() ) // TODO: if( xOLEAutomation.is() )
+ {
+ bError_ = false;
+
+ USHORT nCurPar = 1;
+ AutomationNamedArgsSbxArray* pArg =
+ new AutomationNamedArgsSbxArray( nArgCount );
+ ::rtl::OUString* pNames = pArg->getNames().getArray();
+ for( i = 1 ; i < nArgCount ; i++ )
+ {
+ SbxVariable* pVar = refArgv->Get( i );
+ const String& rName = refArgv->GetAlias( i );
+ if( rName.Len() )
+ pNames[i] = rName;
+ pArg->Put( pVar, nCurPar++ );
+ }
+ refArgv = pArg;
+ }
+ }
+ }
+ if( bError_ )
+ Error( SbERR_NO_NAMED_ARGS );
+ }
+ else
+ {
+ USHORT nCurPar = 1;
+ SbxArray* pArg = new SbxArray;
+ for( i = 1 ; i < nArgCount ; i++ )
+ {
+ SbxVariable* pVar = refArgv->Get( i );
+ const String& rName = refArgv->GetAlias( i );
+ if( rName.Len() )
+ {
+ // nCurPar wird auf den gefundenen Parameter gesetzt
+ USHORT j = 1;
+ const SbxParamInfo* pParam = pInfo->GetParam( j );
+ while( pParam )
+ {
+ if( pParam->aName.EqualsIgnoreCaseAscii( rName ) )
+ {
+ nCurPar = j;
+ break;
+ }
+ pParam = pInfo->GetParam( ++j );
+ }
+ if( !pParam )
+ {
+ Error( SbERR_NAMED_NOT_FOUND ); break;
+ }
+ }
+ pArg->Put( pVar, nCurPar++ );
+ }
+ refArgv = pArg;
+ }
+ }
+ // Eigene Var als Parameter 0
+ refArgv->Put( p, 0 );
+ p->SetParameters( refArgv );
+ PopArgv();
+ }
+ else
+ p->SetParameters( NULL );
+}
+
+// Holen eines Array-Elements
+
+SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem )
+{
+ // Falls wir ein Array haben, wollen wir bitte das Array-Element!
+ SbxArray* pPar;
+ if( pElem->GetType() & SbxARRAY )
+ {
+ SbxBase* pElemObj = pElem->GetObject();
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
+ pPar = pElem->GetParameters();
+ if( pDimArray )
+ {
+ // Die Parameter koennen fehlen, wenn ein Array als
+ // Argument uebergeben wird.
+ if( pPar )
+ pElem = pDimArray->Get( pPar );
+ }
+ else
+ {
+ SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
+ if( pArray )
+ {
+ if( !pPar )
+ {
+ Error( SbERR_OUT_OF_RANGE );
+ pElem = new SbxVariable;
+ }
+ else
+ pElem = pArray->Get( pPar->Get( 1 )->GetInteger() );
+ }
+ }
+
+ // #42940, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt
+ if( pPar )
+ pPar->Put( NULL, 0 );
+ }
+ // Index-Access bei UnoObjekten beruecksichtigen
+ else if( pElem->GetType() == SbxOBJECT && !pElem->ISA(SbxMethod) )
+ {
+ pPar = pElem->GetParameters();
+ if ( pPar )
+ {
+ // Ist es ein Uno-Objekt?
+ SbxBaseRef pObj = (SbxBase*)pElem->GetObject();
+ if( pObj )
+ {
+ if( pObj->ISA(SbUnoObject) )
+ {
+ SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
+ Any aAny = pUnoObj->getUnoAny();
+
+ if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
+ Reference< XIndexAccess > xIndexAccess( x, UNO_QUERY );
+ if ( !bVBAEnabled )
+ {
+ // Haben wir Index-Access?
+ if( xIndexAccess.is() )
+ {
+ UINT32 nParamCount = (UINT32)pPar->Count() - 1;
+ if( nParamCount != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return pElem;
+ }
+
+ // Index holen
+ INT32 nIndex = pPar->Get( 1 )->GetLong();
+ Reference< XInterface > xRet;
+ try
+ {
+ Any aAny2 = xIndexAccess->getByIndex( nIndex );
+ TypeClass eType = aAny2.getValueType().getTypeClass();
+ if( eType == TypeClass_INTERFACE )
+ xRet = *(Reference< XInterface >*)aAny2.getValue();
+ }
+ catch (IndexOutOfBoundsException&)
+ {
+ // Bei Exception erstmal immer von Konvertierungs-Problem ausgehen
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ }
+
+ // #57847 Immer neue Variable anlegen, sonst Fehler
+ // durch PutObject(NULL) bei ReadOnly-Properties.
+ pElem = new SbxVariable( SbxVARIANT );
+ if( xRet.is() )
+ {
+ aAny <<= xRet;
+
+ // #67173 Kein Namen angeben, damit echter Klassen-Namen eintragen wird
+ String aName;
+ SbxObjectRef xWrapper = (SbxObject*)new SbUnoObject( aName, aAny );
+ pElem->PutObject( xWrapper );
+ }
+ else
+ {
+ pElem->PutObject( NULL );
+ }
+ }
+ }
+ else
+ {
+ rtl::OUString sDefaultMethod;
+
+ Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
+
+ if ( xDfltMethod.is() )
+ sDefaultMethod = xDfltMethod->getDefaultMethodName();
+ else if( xIndexAccess.is() )
+ sDefaultMethod = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getByIndex" ) );
+
+ if ( sDefaultMethod.getLength() )
+ {
+ SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
+ SbxVariableRef refTemp = meth;
+ if ( refTemp )
+ {
+ meth->SetParameters( pPar );
+ SbxVariable* pNew = new SbxMethod( *(SbxMethod*)meth );
+ pElem = pNew;
+ }
+ }
+ }
+ }
+
+ // #42940, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt
+ pPar->Put( NULL, 0 );
+ }
+ else if( pObj->ISA(BasicCollection) )
+ {
+ BasicCollection* pCol = (BasicCollection*)(SbxBase*)pObj;
+ pElem = new SbxVariable( SbxVARIANT );
+ pPar->Put( pElem, 0 );
+ pCol->CollItem( pPar );
+ }
+ }
+ }
+ }
+
+ return pElem;
+}
+
+// Laden eines Elements aus der Runtime-Library (+StringID+Typ)
+
+void SbiRuntime::StepRTL( UINT32 nOp1, UINT32 nOp2 )
+{
+ PushVar( FindElement( rBasic.pRtl, nOp1, nOp2, SbERR_PROC_UNDEFINED, FALSE ) );
+}
+
+void
+SbiRuntime::StepFIND_Impl( SbxObject* pObj, UINT32 nOp1, UINT32 nOp2, SbError nNotFound, BOOL bLocal, BOOL bStatic )
+{
+ if( !refLocals )
+ refLocals = new SbxArray;
+ PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, bLocal, bStatic ) );
+}
+// Laden einer lokalen/globalen Variablen (+StringID+Typ)
+
+void SbiRuntime::StepFIND( UINT32 nOp1, UINT32 nOp2 )
+{
+ StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, TRUE );
+}
+
+// Search inside a class module (CM) to enable global search in time
+void SbiRuntime::StepFIND_CM( UINT32 nOp1, UINT32 nOp2 )
+{
+
+ SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pMod);
+ if( pClassModuleObject )
+ pMod->SetFlag( SBX_GBLSEARCH );
+
+ StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, TRUE );
+
+ if( pClassModuleObject )
+ pMod->ResetFlag( SBX_GBLSEARCH );
+}
+
+void SbiRuntime::StepFIND_STATIC( UINT32 nOp1, UINT32 nOp2 )
+{
+ StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, TRUE, TRUE );
+}
+
+// Laden eines Objekt-Elements (+StringID+Typ)
+// Das Objekt liegt auf TOS
+
+void SbiRuntime::StepELEM( UINT32 nOp1, UINT32 nOp2 )
+{
+ // Liegt auf dem TOS ein Objekt?
+ SbxVariableRef pObjVar = PopVar();
+
+ SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pObjVar);
+ if( !pObj )
+ {
+ SbxBase* pObjVarObj = pObjVar->GetObject();
+ pObj = PTR_CAST(SbxObject,pObjVarObj);
+ }
+
+ // #56368 Bei StepElem Referenz sichern, sonst koennen Objekte
+ // in Qualifizierungsketten wie ActiveComponent.Selection(0).Text
+ // zu fueh die Referenz verlieren
+ // #74254 Jetzt per Liste
+ if( pObj )
+ SaveRef( (SbxVariable*)pObj );
+
+ PushVar( FindElement( pObj, nOp1, nOp2, SbERR_NO_METHOD, FALSE ) );
+}
+
+// Laden eines Parameters (+Offset+Typ)
+// Wenn der Datentyp nicht stimmen sollte, eine Kopie anlegen
+// Der Datentyp SbxEMPTY zeigt an, daa kein Parameter angegeben ist.
+// Get( 0 ) darf EMPTY sein
+
+void SbiRuntime::StepPARAM( UINT32 nOp1, UINT32 nOp2 )
+{
+ USHORT i = static_cast<USHORT>( nOp1 & 0x7FFF );
+ SbxDataType t = (SbxDataType) nOp2;
+ SbxVariable* p;
+
+ // #57915 Missing sauberer loesen
+ USHORT nParamCount = refParams->Count();
+ if( i >= nParamCount )
+ {
+ INT16 iLoop = i;
+ while( iLoop >= nParamCount )
+ {
+ p = new SbxVariable();
+
+ if( SbiRuntime::isVBAEnabled() &&
+ (t == SbxOBJECT || t == SbxSTRING) )
+ {
+ if( t == SbxOBJECT )
+ p->PutObject( NULL );
+ else
+ p->PutString( String() );
+ }
+ else
+ p->PutErr( 448 ); // Wie in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND)
+
+ refParams->Put( p, iLoop );
+ iLoop--;
+ }
+ }
+ p = refParams->Get( i );
+
+ if( p->GetType() == SbxERROR && ( i ) )
+ //if( p->GetType() == SbxEMPTY && ( i ) )
+ {
+ // Wenn ein Parameter fehlt, kann er OPTIONAL sein
+ BOOL bOpt = FALSE;
+ if( pMeth )
+ {
+ SbxInfo* pInfo = pMeth->GetInfo();
+ if ( pInfo )
+ {
+ const SbxParamInfo* pParam = pInfo->GetParam( i );
+ if( pParam && ( (pParam->nFlags & SBX_OPTIONAL) != 0 ) )
+ {
+ // Default value?
+ USHORT nDefaultId = sal::static_int_cast< USHORT >(
+ pParam->nUserData & 0xffff );
+ if( nDefaultId > 0 )
+ {
+ String aDefaultStr = pImg->GetString( nDefaultId );
+ p = new SbxVariable();
+ p->PutString( aDefaultStr );
+ refParams->Put( p, i );
+ }
+ bOpt = TRUE;
+ }
+ }
+ }
+ if( bOpt == FALSE )
+ Error( SbERR_NOT_OPTIONAL );
+ }
+ else if( t != SbxVARIANT && (SbxDataType)(p->GetType() & 0x0FFF ) != t )
+ {
+ SbxVariable* q = new SbxVariable( t );
+ SaveRef( q );
+ *q = *p;
+ p = q;
+ }
+ SetupArgs( p, nOp1 );
+ PushVar( CheckArray( p ) );
+}
+
+// Case-Test (+True-Target+Test-Opcode)
+
+void SbiRuntime::StepCASEIS( UINT32 nOp1, UINT32 nOp2 )
+{
+ if( !refCaseStk || !refCaseStk->Count() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ SbxVariableRef xComp = PopVar();
+ SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
+ if( xCase->Compare( (SbxOperator) nOp2, *xComp ) )
+ StepJUMP( nOp1 );
+ }
+}
+
+// Aufruf einer DLL-Prozedur (+StringID+Typ)
+// Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist
+
+void SbiRuntime::StepCALL( UINT32 nOp1, UINT32 nOp2 )
+{
+ String aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
+ SbxArray* pArgs = NULL;
+ if( nOp1 & 0x8000 )
+ pArgs = refArgv;
+ DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, FALSE );
+ aLibName = String();
+ if( nOp1 & 0x8000 )
+ PopArgv();
+}
+
+// Aufruf einer DLL-Prozedur nach CDecl (+StringID+Typ)
+// Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist
+
+void SbiRuntime::StepCALLC( UINT32 nOp1, UINT32 nOp2 )
+{
+ String aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
+ SbxArray* pArgs = NULL;
+ if( nOp1 & 0x8000 )
+ pArgs = refArgv;
+ DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, TRUE );
+ aLibName = String();
+ if( nOp1 & 0x8000 )
+ PopArgv();
+}
+
+
+// Beginn eines Statements (+Line+Col)
+
+void SbiRuntime::StepSTMNT( UINT32 nOp1, UINT32 nOp2 )
+{
+ // Wenn der Expr-Stack am Anfang einen Statements eine Variable enthaelt,
+ // hat ein Trottel X als Funktion aufgerufen, obwohl es eine Variable ist!
+ BOOL bFatalExpr = FALSE;
+ String sUnknownMethodName;
+ if( nExprLvl > 1 )
+ bFatalExpr = TRUE;
+ else if( nExprLvl )
+ {
+ SbxVariable* p = refExprStk->Get( 0 );
+ if( p->GetRefCount() > 1
+ && refLocals.Is() && refLocals->Find( p->GetName(), p->GetClass() ) )
+ {
+ sUnknownMethodName = p->GetName();
+ bFatalExpr = TRUE;
+ }
+ }
+ // Der Expr-Stack ist nun nicht mehr notwendig
+ ClearExprStack();
+
+ // #56368 Kuenstliche Referenz fuer StepElem wieder freigeben,
+ // damit sie nicht ueber ein Statement hinaus erhalten bleibt
+ //refSaveObj = NULL;
+ // #74254 Jetzt per Liste
+ ClearRefs();
+
+ // Wir muessen hier hart abbrechen, da sonst Zeile und Spalte nicht mehr
+ // stimmen!
+ if( bFatalExpr)
+ {
+ StarBASIC::FatalError( SbERR_NO_METHOD, sUnknownMethodName );
+ return;
+ }
+ pStmnt = pCode - 9;
+ USHORT nOld = nLine;
+ nLine = static_cast<short>( nOp1 );
+
+ // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern
+ nCol1 = static_cast<short>( nOp2 & 0xFF );
+
+ // Suchen des naechsten STMNT-Befehls,
+ // um die End-Spalte dieses Statements zu setzen
+ // Searches of the next STMNT instruction,
+ // around the final column of this statement to set
+
+ nCol2 = 0xffff;
+ USHORT n1, n2;
+ const BYTE* p = pMod->FindNextStmnt( pCode, n1, n2 );
+ if( p )
+ {
+ if( n1 == nOp1 )
+ {
+ // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern
+ nCol2 = (n2 & 0xFF) - 1;
+ }
+ }
+
+ // #29955 for-Schleifen-Ebene korrigieren, #67452 NICHT im Error-Handler sonst Chaos
+ if( !bInError )
+ {
+ // (Bei Sprüngen aus Schleifen tritt hier eine Differenz auf)
+ USHORT nExspectedForLevel = static_cast<USHORT>( nOp2 / 0x100 );
+ if( pGosubStk )
+ nExspectedForLevel = nExspectedForLevel + pGosubStk->nStartForLvl;
+
+ // Wenn der tatsaechliche For-Level zu klein ist, wurde aus
+ // einer Schleife heraus gesprungen -> korrigieren
+ while( nForLvl > nExspectedForLevel )
+ PopFor();
+ }
+
+ // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out
+ // Erklärung siehe bei _ImplGetBreakCallLevel.
+ if( pInst->nCallLvl <= pInst->nBreakCallLvl )
+ //if( nFlags & SbDEBUG_STEPINTO )
+ {
+ StarBASIC* pStepBasic = GetCurrentBasic( &rBasic );
+ USHORT nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 );
+
+ // Neuen BreakCallLevel ermitteln
+ pInst->CalcBreakCallLevel( nNewFlags );
+ }
+
+ // Breakpoints nur bei STMNT-Befehlen in neuer Zeile!
+ else if( ( nOp1 != nOld )
+ && ( nFlags & SbDEBUG_BREAK )
+ && pMod->IsBP( static_cast<USHORT>( nOp1 ) ) )
+ {
+ StarBASIC* pBreakBasic = GetCurrentBasic( &rBasic );
+ USHORT nNewFlags = pBreakBasic->BreakPoint( nLine, nCol1, nCol2 );
+
+ // Neuen BreakCallLevel ermitteln
+ pInst->CalcBreakCallLevel( nNewFlags );
+ //16.10.96, ALT:
+ //if( nNewFlags != SbDEBUG_CONTINUE )
+ // nFlags = nNewFlags;
+ }
+}
+
+// (+SvStreamFlags+Flags)
+// Stack: Blocklaenge
+// Kanalnummer
+// Dateiname
+
+void SbiRuntime::StepOPEN( UINT32 nOp1, UINT32 nOp2 )
+{
+ SbxVariableRef pName = PopVar();
+ SbxVariableRef pChan = PopVar();
+ SbxVariableRef pLen = PopVar();
+ short nBlkLen = pLen->GetInteger();
+ short nChan = pChan->GetInteger();
+ ByteString aName( pName->GetString(), gsl_getSystemTextEncoding() );
+ pIosys->Open( nChan, aName, static_cast<short>( nOp1 ),
+ static_cast<short>( nOp2 ), nBlkLen );
+ Error( pIosys->GetError() );
+}
+
+// Objekt kreieren (+StringID+StringID)
+
+void SbiRuntime::StepCREATE( UINT32 nOp1, UINT32 nOp2 )
+{
+ String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
+ SbxObject *pObj = SbxBase::CreateObject( aClass );
+ if( !pObj )
+ Error( SbERR_INVALID_OBJECT );
+ else
+ {
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ pObj->SetName( aName );
+ // Das Objekt muss BASIC rufen koennen
+ pObj->SetParent( &rBasic );
+ SbxVariable* pNew = new SbxVariable;
+ pNew->PutObject( pObj );
+ PushVar( pNew );
+ }
+}
+
+void SbiRuntime::StepDCREATE( UINT32 nOp1, UINT32 nOp2 )
+{
+ StepDCREATE_IMPL( nOp1, nOp2 );
+}
+
+void SbiRuntime::StepDCREATE_REDIMP( UINT32 nOp1, UINT32 nOp2 )
+{
+ StepDCREATE_IMPL( nOp1, nOp2 );
+}
+
+
+// Helper function for StepDCREATE_IMPL / bRedimp = true
+void implCopyDimArray_DCREATE( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex,
+ short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
+{
+ sal_Int32& ri = pActualIndices[nActualDim];
+ for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
+ {
+ if( nActualDim < nMaxDimIndex )
+ {
+ implCopyDimArray_DCREATE( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
+ pActualIndices, pLowerBounds, pUpperBounds );
+ }
+ else
+ {
+ SbxVariable* pSource = pOldArray->Get32( pActualIndices );
+ pNewArray->Put32( pSource, pActualIndices );
+ }
+ }
+}
+
+// #56204 Objekt-Array kreieren (+StringID+StringID), DCREATE == Dim-Create
+void SbiRuntime::StepDCREATE_IMPL( UINT32 nOp1, UINT32 nOp2 )
+{
+ SbxVariableRef refVar = PopVar();
+
+ DimImpl( refVar );
+
+ // Das Array mit Instanzen der geforderten Klasse fuellen
+ SbxBaseRef xObj = (SbxBase*)refVar->GetObject();
+ if( !xObj )
+ {
+ StarBASIC::Error( SbERR_INVALID_OBJECT );
+ return;
+ }
+
+ SbxDimArray* pArray = 0;
+ if( xObj->ISA(SbxDimArray) )
+ {
+ SbxBase* pObj = (SbxBase*)xObj;
+ pArray = (SbxDimArray*)pObj;
+
+ // Dimensionen auswerten
+ short nDims = pArray->GetDims();
+ INT32 nTotalSize = 0;
+
+ // es muss ein eindimensionales Array sein
+ INT32 nLower, nUpper, nSize;
+ INT32 i;
+ for( i = 0 ; i < nDims ; i++ )
+ {
+ pArray->GetDim32( i+1, nLower, nUpper );
+ nSize = nUpper - nLower + 1;
+ if( i == 0 )
+ nTotalSize = nSize;
+ else
+ nTotalSize *= nSize;
+ }
+
+ // Objekte anlegen und ins Array eintragen
+ String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
+ for( i = 0 ; i < nTotalSize ; i++ )
+ {
+ SbxObject *pClassObj = SbxBase::CreateObject( aClass );
+ if( !pClassObj )
+ {
+ Error( SbERR_INVALID_OBJECT );
+ break;
+ }
+ else
+ {
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ pClassObj->SetName( aName );
+ // Das Objekt muss BASIC rufen koennen
+ pClassObj->SetParent( &rBasic );
+ pArray->SbxArray::Put32( pClassObj, i );
+ }
+ }
+ }
+
+ SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
+ if( pArray && pOldArray )
+ {
+ short nDimsNew = pArray->GetDims();
+ short nDimsOld = pOldArray->GetDims();
+ short nDims = nDimsNew;
+ BOOL bRangeError = FALSE;
+
+ // Store dims to use them for copying later
+ sal_Int32* pLowerBounds = new sal_Int32[nDims];
+ sal_Int32* pUpperBounds = new sal_Int32[nDims];
+ sal_Int32* pActualIndices = new sal_Int32[nDims];
+ if( nDimsOld != nDimsNew )
+ {
+ bRangeError = TRUE;
+ }
+ else
+ {
+ // Compare bounds
+ for( short i = 1 ; i <= nDims ; i++ )
+ {
+ sal_Int32 lBoundNew, uBoundNew;
+ sal_Int32 lBoundOld, uBoundOld;
+ pArray->GetDim32( i, lBoundNew, uBoundNew );
+ pOldArray->GetDim32( i, lBoundOld, uBoundOld );
+
+ lBoundNew = std::max( lBoundNew, lBoundOld );
+ uBoundNew = std::min( uBoundNew, uBoundOld );
+ short j = i - 1;
+ pActualIndices[j] = pLowerBounds[j] = lBoundNew;
+ pUpperBounds[j] = uBoundNew;
+ }
+ }
+
+ if( bRangeError )
+ {
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ }
+ else
+ {
+ // Copy data from old array by going recursively through all dimensions
+ // (It would be faster to work on the flat internal data array of an
+ // SbyArray but this solution is clearer and easier)
+ implCopyDimArray_DCREATE( pArray, pOldArray, nDims - 1,
+ 0, pActualIndices, pLowerBounds, pUpperBounds );
+ }
+ delete [] pUpperBounds;
+ delete [] pLowerBounds;
+ delete [] pActualIndices;
+ refRedimpArray = NULL;
+ }
+}
+
+// Objekt aus User-Type kreieren (+StringID+StringID)
+
+SbxObject* createUserTypeImpl( const String& rClassName ); // sb.cxx
+
+void SbiRuntime::StepTCREATE( UINT32 nOp1, UINT32 nOp2 )
+{
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
+
+ SbxObject* pCopyObj = createUserTypeImpl( aClass );
+ if( pCopyObj )
+ pCopyObj->SetName( aName );
+ SbxVariable* pNew = new SbxVariable;
+ pNew->PutObject( pCopyObj );
+ pNew->SetDeclareClassName( aClass );
+ PushVar( pNew );
+}
+
+void SbiRuntime::implCreateFixedString( SbxVariable* pStrVar, UINT32 nOp2 )
+{
+ USHORT nCount = static_cast<USHORT>( nOp2 >> 17 ); // len = all bits above 0x10000
+ String aStr;
+ aStr.Fill( nCount, 0 );
+ pStrVar->PutString( aStr );
+}
+
+// Einrichten einer lokalen Variablen (+StringID+Typ)
+
+void SbiRuntime::StepLOCAL( UINT32 nOp1, UINT32 nOp2 )
+{
+ if( !refLocals.Is() )
+ refLocals = new SbxArray;
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ if( refLocals->Find( aName, SbxCLASS_DONTCARE ) == NULL )
+ {
+ SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
+ SbxVariable* p = new SbxVariable( t );
+ p->SetName( aName );
+ bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0);
+ if( bWithEvents )
+ p->SetFlag( SBX_WITH_EVENTS );
+ bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0);
+ if( bFixedString )
+ implCreateFixedString( p, nOp2 );
+ refLocals->Put( p, refLocals->Count() );
+ }
+}
+
+// Einrichten einer modulglobalen Variablen (+StringID+Typ)
+
+void SbiRuntime::StepPUBLIC_Impl( UINT32 nOp1, UINT32 nOp2, bool bUsedForClassModule )
+{
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxDataType t = (SbxDataType)(SbxDataType)(nOp2 & 0xffff);;
+ BOOL bFlag = pMod->IsSet( SBX_NO_MODIFY );
+ pMod->SetFlag( SBX_NO_MODIFY );
+ SbxVariableRef p = pMod->Find( aName, SbxCLASS_PROPERTY );
+ if( p.Is() )
+ pMod->Remove (p);
+ SbProperty* pProp = pMod->GetProperty( aName, t );
+ if( !bUsedForClassModule )
+ pProp->SetFlag( SBX_PRIVATE );
+ if( !bFlag )
+ pMod->ResetFlag( SBX_NO_MODIFY );
+ if( pProp )
+ {
+ pProp->SetFlag( SBX_DONTSTORE );
+ // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
+ pProp->SetFlag( SBX_NO_MODIFY);
+
+ bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0);
+ if( bWithEvents )
+ pProp->SetFlag( SBX_WITH_EVENTS );
+ bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0);
+ if( bFixedString )
+ implCreateFixedString( p, nOp2 );
+ }
+}
+
+void SbiRuntime::StepPUBLIC( UINT32 nOp1, UINT32 nOp2 )
+{
+ StepPUBLIC_Impl( nOp1, nOp2, false );
+}
+
+void SbiRuntime::StepPUBLIC_P( UINT32 nOp1, UINT32 nOp2 )
+{
+ // Creates module variable that isn't reinitialised when
+ // between invocations ( for VBASupport & document basic only )
+ if( pMod->pImage->bFirstInit )
+ {
+ bool bUsedForClassModule = pImg->GetFlag( SBIMG_CLASSMODULE );
+ StepPUBLIC_Impl( nOp1, nOp2, bUsedForClassModule );
+ }
+}
+
+// Einrichten einer globalen Variablen (+StringID+Typ)
+
+void SbiRuntime::StepGLOBAL( UINT32 nOp1, UINT32 nOp2 )
+{
+ if( pImg->GetFlag( SBIMG_CLASSMODULE ) )
+ StepPUBLIC_Impl( nOp1, nOp2, true );
+
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
+
+ // Store module scope variables at module scope
+ // in non vba mode these are stored at the library level :/
+ // not sure if this really should not be enabled for ALL basic
+ SbxObject* pStorage = &rBasic;
+ if ( SbiRuntime::isVBAEnabled() )
+ {
+ pStorage = pMod;
+ pMod->AddVarName( aName );
+ }
+
+ BOOL bFlag = pStorage->IsSet( SBX_NO_MODIFY );
+ rBasic.SetFlag( SBX_NO_MODIFY );
+ SbxVariableRef p = pStorage->Find( aName, SbxCLASS_PROPERTY );
+ if( p.Is() )
+ pStorage->Remove (p);
+ p = pStorage->Make( aName, SbxCLASS_PROPERTY, t );
+ if( !bFlag )
+ pStorage->ResetFlag( SBX_NO_MODIFY );
+ if( p )
+ {
+ p->SetFlag( SBX_DONTSTORE );
+ // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
+ p->SetFlag( SBX_NO_MODIFY);
+ }
+}
+
+
+// Creates global variable that isn't reinitialised when
+// basic is restarted, P=PERSIST (+StringID+Typ)
+
+void SbiRuntime::StepGLOBAL_P( UINT32 nOp1, UINT32 nOp2 )
+{
+ if( pMod->pImage->bFirstInit )
+ {
+ StepGLOBAL( nOp1, nOp2 );
+ }
+}
+
+
+// Searches for global variable, behavior depends on the fact
+// if the variable is initialised for the first time
+
+void SbiRuntime::StepFIND_G( UINT32 nOp1, UINT32 nOp2 )
+{
+ if( pMod->pImage->bFirstInit )
+ {
+ // Behave like always during first init
+ StepFIND( nOp1, nOp2 );
+ }
+ else
+ {
+ // Return dummy variable
+ SbxDataType t = (SbxDataType) nOp2;
+ String aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
+
+ SbxVariable* pDummyVar = new SbxVariable( t );
+ pDummyVar->SetName( aName );
+ PushVar( pDummyVar );
+ }
+}
+
+
+SbxVariable* SbiRuntime::StepSTATIC_Impl( String& aName, SbxDataType& t )
+{
+ SbxVariable* p = NULL;
+ if ( pMeth )
+ {
+ SbxArray* pStatics = pMeth->GetStatics();
+ if( pStatics && ( pStatics->Find( aName, SbxCLASS_DONTCARE ) == NULL ) )
+ {
+ p = new SbxVariable( t );
+ if( t != SbxVARIANT )
+ p->SetFlag( SBX_FIXED );
+ p->SetName( aName );
+ pStatics->Put( p, pStatics->Count() );
+ }
+ }
+ return p;
+}
+// Einrichten einer statischen Variablen (+StringID+Typ)
+void SbiRuntime::StepSTATIC( UINT32 nOp1, UINT32 nOp2 )
+{
+ String aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxDataType t = (SbxDataType) nOp2;
+ StepSTATIC_Impl( aName, t );
+}
+
diff --git a/basic/source/runtime/wnt-mingw.s b/basic/source/runtime/wnt-mingw.s
new file mode 100644
index 000000000000..8c332c1a8ce8
--- /dev/null
+++ b/basic/source/runtime/wnt-mingw.s
@@ -0,0 +1,53 @@
+#*************************************************************************
+#
+# 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.
+#
+#***********************************************************************/
+
+.intel_syntax
+
+.globl _DllMgr_call32
+.globl _DllMgr_callFp
+
+_DllMgr_call32:
+_DllMgr_callFp:
+ push ebp
+ mov ebp, esp
+ push esi
+ push edi
+ mov ecx, [ebp+16]
+ jecxz $1
+ sub esp, ecx
+ mov edi, esp
+ mov esi, [ebp+12]
+ shr ecx, 2
+ rep movsd
+$1: call DWORD PTR [ebp+8]
+ # for extra safety, do not trust esp after call (in case the Basic Declare
+ # signature is wrong):
+ mov edi, [ebp-8]
+ mov esi, [ebp-4]
+ mov esp, ebp
+ pop ebp
+ ret 12
diff --git a/basic/source/runtime/wnt.asm b/basic/source/runtime/wnt.asm
new file mode 100644
index 000000000000..2a8710e34243
--- /dev/null
+++ b/basic/source/runtime/wnt.asm
@@ -0,0 +1,56 @@
+;*************************************************************************
+;
+; 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.
+;
+;***********************************************************************/
+
+.386
+
+PUBLIC _DllMgr_call32@12
+PUBLIC _DllMgr_callFp@12
+
+_TEXT SEGMENT
+_DllMgr_call32@12:
+_DllMgr_callFp@12:
+ push ebp
+ mov ebp, esp
+ push esi
+ push edi
+ mov ecx, [ebp+16]
+ jecxz $1
+ sub esp, ecx
+ mov edi, esp
+ mov esi, [ebp+12]
+ shr ecx, 2
+ rep movsd
+$1: call DWORD PTR [ebp+8]
+ ; for extra safety, do not trust esp after call (in case the Basic Declare
+ ; signature is wrong):
+ mov edi, [ebp-8]
+ mov esi, [ebp-4]
+ mov esp, ebp
+ pop ebp
+ ret 12
+_TEXT ENDS
+END