diff options
Diffstat (limited to 'basic/source/runtime')
-rw-r--r-- | basic/source/runtime/basrdll.cxx | 107 | ||||
-rw-r--r-- | basic/source/runtime/ddectrl.cxx | 195 | ||||
-rw-r--r-- | basic/source/runtime/ddectrl.hxx | 67 | ||||
-rw-r--r-- | basic/source/runtime/dllmgr.cxx | 674 | ||||
-rw-r--r-- | basic/source/runtime/dllmgr.hxx | 98 | ||||
-rw-r--r-- | basic/source/runtime/inputbox.cxx | 200 | ||||
-rw-r--r-- | basic/source/runtime/iosys.cxx | 1051 | ||||
-rw-r--r-- | basic/source/runtime/makefile.mk | 93 | ||||
-rw-r--r-- | basic/source/runtime/methods.cxx | 4547 | ||||
-rw-r--r-- | basic/source/runtime/methods1.cxx | 2610 | ||||
-rw-r--r-- | basic/source/runtime/os2.asm | 107 | ||||
-rw-r--r-- | basic/source/runtime/props.cxx | 764 | ||||
-rw-r--r-- | basic/source/runtime/rtlproto.hxx | 350 | ||||
-rw-r--r-- | basic/source/runtime/runtime.cxx | 1158 | ||||
-rw-r--r-- | basic/source/runtime/stdobj.cxx | 783 | ||||
-rw-r--r-- | basic/source/runtime/stdobj1.cxx | 554 | ||||
-rw-r--r-- | basic/source/runtime/step0.cxx | 1273 | ||||
-rw-r--r-- | basic/source/runtime/step1.cxx | 571 | ||||
-rw-r--r-- | basic/source/runtime/step2.cxx | 1216 | ||||
-rw-r--r-- | basic/source/runtime/win.asm | 84 | ||||
-rw-r--r-- | basic/source/runtime/wnt-mingw.s | 97 | ||||
-rw-r--r-- | basic/source/runtime/wnt.asm | 96 |
22 files changed, 16695 insertions, 0 deletions
diff --git a/basic/source/runtime/basrdll.cxx b/basic/source/runtime/basrdll.cxx new file mode 100644 index 000000000000..a13569ee0a9f --- /dev/null +++ b/basic/source/runtime/basrdll.cxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basrdll.cxx,v $ + * $Revision: 1.8 $ + * + * 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..425eec2eaf85 --- /dev/null +++ b/basic/source/runtime/ddectrl.cxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ddectrl.cxx,v $ + * $Revision: 1.6 $ + * + * 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..509e858683ec --- /dev/null +++ b/basic/source/runtime/ddectrl.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ddectrl.hxx,v $ + * $Revision: 1.4 $ + * + * 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..250c8778da9c --- /dev/null +++ b/basic/source/runtime/dllmgr.cxx @@ -0,0 +1,674 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dllmgr.cxx,v $ + * $Revision: 1.14 $ + * + * 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> +#ifdef OS2 +#define INCL_DOSMODULEMGR +#include <svpm.h> +#endif + +#if defined( WIN ) || defined( WNT ) +#ifndef _SVWIN_H +#undef WB_LEFT +#undef WB_RIGHT +#include <tools/svwin.h> +#endif +#endif +#include <tools/debug.hxx> +#include <tools/string.hxx> +#include <tools/errcode.hxx> +#include <basic/sbxvar.hxx> +#include <basic/sbx.hxx> + +#if defined(WIN) +typedef HINSTANCE SbiDllHandle; +typedef FARPROC SbiDllProc; +#elif defined(WNT) +typedef HMODULE SbiDllHandle; +typedef int(*SbiDllProc)(); +#elif defined(OS2) +typedef HMODULE SbiDllHandle; +typedef PFN SbiDllProc; +#else +typedef void* SbiDllHandle; +typedef void* SbiDllProc; +#endif + +#define _DLLMGR_CXX +#include "dllmgr.hxx" +#include <basic/sberrors.hxx> + +#ifndef WINAPI +#ifdef WNT +#define WINAPI __far __pascal +#endif +#endif + +extern "C" { +#if defined(INTEL) && (defined(WIN) || defined(WNT)) + +extern INT16 WINAPI CallINT( SbiDllProc, char *stack, short nstack); +extern INT32 WINAPI CallLNG( SbiDllProc, char *stack, short nstack); +#ifndef WNT +extern float WINAPI CallSNG( SbiDllProc, char *stack, short nstack); +#endif +extern double WINAPI CallDBL( SbiDllProc, char *stack, short nstack); +extern char* WINAPI CallSTR( SbiDllProc, char *stack, short nstack); +// extern CallFIX( SbiDllProc, char *stack, short nstack); + +#else + +INT16 CallINT( SbiDllProc, char *, short ) { return 0; } +INT32 CallLNG( SbiDllProc, char *, short ) { return 0; } +float CallSNG( SbiDllProc, char *, short ) { return 0; } +double CallDBL( SbiDllProc, char *, short) { return 0; } +char* CallSTR( SbiDllProc, char *, short ) { return 0; } +#endif +} + +SV_IMPL_OP_PTRARR_SORT(ImplDllArr,ByteStringPtr) + +/* mit Optimierung An stuerzt unter Win95 folgendes Makro ab: +declare Sub MessageBeep Lib "user32" (ByVal long) +sub main + MessageBeep( 1 ) +end sub +*/ +#if defined (WNT) && defined (MSC) +//#pragma optimize ("", off) +#endif + +// +// *********************************************************************** +// + +class ImplSbiProc : public ByteString +{ + SbiDllProc pProc; + ImplSbiProc(); + ImplSbiProc( const ImplSbiProc& ); + +public: + ImplSbiProc( const ByteString& rName, SbiDllProc pFunc ) + : ByteString( rName ) { pProc = pFunc; } + SbiDllProc GetProc() const { return pProc; } +}; + +// +// *********************************************************************** +// + +class ImplSbiDll : public ByteString +{ + ImplDllArr aProcArr; + SbiDllHandle hDLL; + + ImplSbiDll( const ImplSbiDll& ); +public: + ImplSbiDll( const ByteString& rName, SbiDllHandle hHandle ) + : ByteString( rName ) { hDLL = hHandle; } + ~ImplSbiDll(); + SbiDllHandle GetHandle() const { return hDLL; } + SbiDllProc GetProc( const ByteString& rName ) const; + void InsertProc( const ByteString& rName, SbiDllProc pProc ); +}; + +ImplSbiDll::~ImplSbiDll() +{ + USHORT nCount = aProcArr.Count(); + for( USHORT nCur = 0; nCur < nCount; nCur++ ) + { + ImplSbiProc* pProc = (ImplSbiProc*)aProcArr.GetObject( nCur ); + delete pProc; + } +} + +SbiDllProc ImplSbiDll::GetProc( const ByteString& rName ) const +{ + USHORT nPos; + BOOL bRet = aProcArr.Seek_Entry( (ByteStringPtr)&rName, &nPos ); + if( bRet ) + { + ImplSbiProc* pImplProc = (ImplSbiProc*)aProcArr.GetObject(nPos); + return pImplProc->GetProc(); + } + return (SbiDllProc)0; +} + +void ImplSbiDll::InsertProc( const ByteString& rName, SbiDllProc pProc ) +{ + DBG_ASSERT(aProcArr.Seek_Entry((ByteStringPtr)&rName,0)==0,"InsertProc: Already in table"); + ImplSbiProc* pImplProc = new ImplSbiProc( rName, pProc ); + aProcArr.Insert( (ByteStringPtr)pImplProc ); +} + + +// +// *********************************************************************** +// + +SbiDllMgr::SbiDllMgr( const SbiDllMgr& ) +{ +} + +SbiDllMgr::SbiDllMgr() +{ +} + +SbiDllMgr::~SbiDllMgr() +{ + USHORT nCount = aDllArr.Count(); + for( USHORT nCur = 0; nCur < nCount; nCur++ ) + { + ImplSbiDll* pDll = (ImplSbiDll*)aDllArr.GetObject( nCur ); + FreeDllHandle( pDll->GetHandle() ); + delete pDll; + } +} + +void SbiDllMgr::FreeDll( const ByteString& rDllName ) +{ + USHORT nPos; + BOOL bRet = aDllArr.Seek_Entry( (ByteStringPtr)&rDllName, &nPos ); + if( bRet ) + { + ImplSbiDll* pDll = (ImplSbiDll*)aDllArr.GetObject(nPos); + FreeDllHandle( pDll->GetHandle() ); + delete pDll; + aDllArr.Remove( nPos, 1 ); + } +} + + +ImplSbiDll* SbiDllMgr::GetDll( const ByteString& rDllName ) +{ + USHORT nPos; + ImplSbiDll* pDll = 0; + BOOL bRet = aDllArr.Seek_Entry( (ByteStringPtr)&rDllName, &nPos ); + if( bRet ) + pDll = (ImplSbiDll*)aDllArr.GetObject(nPos); + else + { + SbiDllHandle hDll = CreateDllHandle( rDllName ); + if( hDll ) + { + pDll = new ImplSbiDll( rDllName, hDll ); + aDllArr.Insert( (ByteStringPtr)pDll ); + } + } + return pDll; +} + +SbiDllProc SbiDllMgr::GetProc( ImplSbiDll* pDll, const ByteString& rProcName ) +{ + DBG_ASSERT(pDll,"GetProc: No dll-ptr"); + SbiDllProc pProc; + pProc = pDll->GetProc( rProcName ); + if( !pProc ) + { + pProc = GetProcAddr( pDll->GetHandle(), rProcName ); + if( pProc ) + pDll->InsertProc( rProcName, pProc ); + } + return pProc; +} + + +SbError SbiDllMgr::Call( const char* pProcName, const char* pDllName, + SbxArray* pArgs, SbxVariable& rResult, BOOL bCDecl ) +{ + DBG_ASSERT(pProcName&&pDllName,"Call: Bad parms"); + SbError nSbErr = 0; + ByteString aDllName( pDllName ); + CheckDllName( aDllName ); + ImplSbiDll* pDll = GetDll( aDllName ); + if( pDll ) + { + SbiDllProc pProc = GetProc( pDll, pProcName ); + if( pProc ) + { + if( bCDecl ) + nSbErr = CallProcC( pProc, pArgs, rResult ); + else + nSbErr = CallProc( pProc, pArgs, rResult ); + } + else + nSbErr = SbERR_PROC_UNDEFINED; + } + else + nSbErr = SbERR_BAD_DLL_LOAD; + return nSbErr; +} + +// *********************************************************************** +// ******************* abhaengige Implementationen *********************** +// *********************************************************************** + +void SbiDllMgr::CheckDllName( ByteString& rDllName ) +{ +#if defined(WIN) || defined(WNT) || defined(OS2) + if( rDllName.Search('.') == STRING_NOTFOUND ) + rDllName += ".DLL"; +#else + (void)rDllName; +#endif +} + + +SbiDllHandle SbiDllMgr::CreateDllHandle( const ByteString& rDllName ) +{ + (void)rDllName; + +#if defined(UNX) + SbiDllHandle hLib=0; +#else + SbiDllHandle hLib; +#endif + +#if defined(WIN) + hLib = LoadLibrary( (const char*)rDllName ); + if( (ULONG)hLib < 32 ) + hLib = 0; + +#elif defined(WNT) + hLib = LoadLibrary( rDllName.GetBuffer() ); + if( !(ULONG)hLib ) + { +#ifdef DBG_UTIL + ULONG nLastErr; + nLastErr = GetLastError(); +#endif + hLib = 0; + } + +#elif defined(OS2) + char cErr[ 100 ]; + if( DosLoadModule( (PSZ) cErr, 100, (const char*)rDllName.GetBuffer(), &hLib ) ) + hLib = 0; +#endif + return hLib; +} + +void SbiDllMgr::FreeDllHandle( SbiDllHandle hLib ) +{ +#if defined(WIN) || defined(WNT) + if( hLib ) + FreeLibrary ((HINSTANCE) hLib); +#elif defined(OS2) + if( hLib ) + DosFreeModule( (HMODULE) hLib ); +#else + (void)hLib; +#endif +} + +SbiDllProc SbiDllMgr::GetProcAddr(SbiDllHandle hLib, const ByteString& rProcName) +{ + char buf1 [128] = ""; + char buf2 [128] = ""; + + SbiDllProc pProc = 0; + int nOrd = 0; + + // Ordinal? + if( rProcName.GetBuffer()[0] == '@' ) + nOrd = atoi( rProcName.GetBuffer()+1 ); + + // Moegliche Parameter weg: + DBG_ASSERT( sizeof(buf1) > rProcName.Len(), + "SbiDllMgr::GetProcAddr: buffer to small!" ); + strncpy( buf1, rProcName.GetBuffer(), sizeof(buf1)-1 ); + char *p = strchr( buf1, '#' ); + if( p ) + *p = 0; + + DBG_ASSERT( sizeof(buf2) > strlen(buf1) + 1, + "SbiDllMgr::GetProcAddr: buffer to small!" ); + strncpy( buf2, "_", sizeof(buf2)-1 ); + strncat( buf2, buf1, sizeof(buf2)-1-strlen(buf2) ); + +#if defined(WIN) || defined(WNT) + if( nOrd > 0 ) + pProc = (SbiDllProc)GetProcAddress( hLib, (char*)(long) nOrd ); + else + { + // 2. mit Parametern: + pProc = (SbiDllProc)GetProcAddress ( hLib, rProcName.GetBuffer() ); + // 3. nur der Name: + if (!pProc) + pProc = (SbiDllProc)GetProcAddress( hLib, buf1 ); + // 4. der Name mit Underline vorweg: + if( !pProc ) + pProc = (SbiDllProc)GetProcAddress( hLib, buf2 ); + } + +#elif defined(OS2) + PSZ pp; + APIRET rc; + // 1. Ordinal oder mit Parametern: + rc = DosQueryProcAddr( hLib, nOrd, pp = (char*)rProcName.GetBuffer(), &pProc ); + // 2. nur der Name: + if( rc ) + rc = DosQueryProcAddr( hLib, 0, pp = (PSZ)buf1, &pProc ); + // 3. der Name mit Underline vorweg: + if( rc ) + rc = DosQueryProcAddr( hLib, 0, pp = (PSZ)buf2, &pProc ); + if( rc ) + pProc = NULL; + else + { + // 16-bit oder 32-bit? + ULONG nInfo = 0; + if( DosQueryProcType( hLib, nOrd, pp, &nInfo ) ) + nInfo = 0;; + } +#else + (void)hLib; +#endif + return pProc; +} + +SbError SbiDllMgr::CallProc( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ) +{ +// ByteString aStr("Calling DLL at "); +// aStr += (ULONG)pProc; +// InfoBox( 0, aStr ).Execute(); + INT16 nInt16; int nInt; INT32 nInt32; double nDouble; + char* pStr; + + USHORT nSize; + char* pStack = (char*)CreateStack( pArgs, nSize ); + switch( rResult.GetType() ) + { + case SbxINTEGER: + nInt16 = CallINT(pProc, pStack, (short)nSize ); + rResult.PutInteger( nInt16 ); + break; + + case SbxUINT: + case SbxUSHORT: + nInt16 = (INT16)CallINT(pProc, pStack, (short)nSize ); + rResult.PutUShort( (USHORT)nInt16 ); + break; + + case SbxERROR: + nInt16 = (INT16)CallINT(pProc, pStack, (short)nSize ); + rResult.PutErr( (USHORT)nInt16 ); + break; + + case SbxINT: + nInt = CallINT(pProc, pStack, (short)nSize ); + rResult.PutInt( nInt ); + break; + + case SbxLONG: + nInt32 = CallLNG(pProc, pStack, (short)nSize ); + rResult.PutLong( nInt32 ); + break; + + case SbxULONG: + nInt32 = CallINT(pProc, pStack, (short)nSize ); + rResult.PutULong( (ULONG)nInt32 ); + break; + +#ifndef WNT + case SbxSINGLE: + { + float nSingle = CallSNG(pProc, pStack, (short)nSize ); + rResult.PutSingle( nSingle ); + break; + } +#endif + + case SbxDOUBLE: +#ifdef WNT + case SbxSINGLE: +#endif + nDouble = CallDBL(pProc, pStack, (short)nSize ); + rResult.PutDouble( nDouble ); + break; + + case SbxDATE: + nDouble = CallDBL(pProc, pStack, (short)nSize ); + rResult.PutDate( nDouble ); + break; + + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + nInt16 = CallINT(pProc, pStack, (short)nSize ); + rResult.PutByte( (BYTE)nInt16 ); + break; + + case SbxSTRING: + case SbxLPSTR: + pStr = CallSTR(pProc, pStack, (short)nSize ); + rResult.PutString( String::CreateFromAscii( pStr ) ); + break; + + case SbxNULL: + case SbxEMPTY: + nInt16 = CallINT(pProc, pStack, (short)nSize ); + // Rueckgabe nur zulaessig, wenn variant! + if( !rResult.IsFixed() ) + rResult.PutInteger( nInt16 ); + break; + + case SbxCURRENCY: + case SbxOBJECT: + case SbxDATAOBJECT: + default: + CallINT(pProc, pStack, (short)nSize ); + break; + } + delete [] pStack; + + if( pArgs ) + { + // die Laengen aller uebergebenen Strings anpassen + USHORT nCount = pArgs->Count(); + for( USHORT nCur = 1; nCur < nCount; nCur++ ) + { + SbxVariable* pVar = pArgs->Get( nCur ); + BOOL bIsString = ( pVar->GetType() == SbxSTRING ) || + ( pVar->GetType() == SbxLPSTR ); + + if( pVar->GetFlags() & SBX_REFERENCE ) + { + pVar->ResetFlag( SBX_REFERENCE ); // Sbx moechte es so + if( bIsString ) + { + ByteString aByteStr( (char*)pVar->GetUserData() ); + String aStr( aByteStr, gsl_getSystemTextEncoding() ); + pVar->PutString( aStr ); + } + } + if( bIsString ) + { + delete (char*)(pVar->GetUserData()); + pVar->SetUserData( 0 ); + } + } + } + return 0; +} + +SbError SbiDllMgr::CallProcC( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ) +{ + (void)pProc; + (void)pArgs; + (void)rResult; + + DBG_ERROR("C calling convention not supported"); + return SbERR_BAD_ARGUMENT; +} + +void* SbiDllMgr::CreateStack( SbxArray* pArgs, USHORT& rSize ) +{ + if( !pArgs ) + { + rSize = 0; + return 0; + } + char* pStack = new char[ 2048 ]; + char* pTop = pStack; + USHORT nCount = pArgs->Count(); + // erstes Element ueberspringen +#ifndef WIN + for( USHORT nCur = 1; nCur < nCount; nCur++ ) +#else + // unter 16-Bit Windows anders rum (OS/2 ?????) + for( USHORT nCur = nCount-1; nCur >= 1; nCur-- ) +#endif + { + SbxVariable* pVar = pArgs->Get( nCur ); + // AB 22.1.1996, Referenz + if( pVar->GetFlags() & SBX_REFERENCE ) // Es ist eine Referenz + { + switch( pVar->GetType() ) + { + case SbxINTEGER: + case SbxUINT: + case SbxINT: + case SbxUSHORT: + case SbxLONG: + case SbxULONG: + case SbxSINGLE: + case SbxDOUBLE: + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + *((void**)pTop) = (void*)&(pVar->aData); + pTop += sizeof( void* ); + break; + + case SbxSTRING: + case SbxLPSTR: + { + USHORT nLen = 256; + ByteString rStr( pVar->GetString(), gsl_getSystemTextEncoding() ); + if( rStr.Len() > 255 ) + nLen = rStr.Len() + 1; + + char* pStr = new char[ nLen ]; + strcpy( pStr, rStr.GetBuffer() ); // #100211# - checked + // ist nicht so sauber, aber wir sparen ein Pointerarray + DBG_ASSERT(sizeof(UINT32)>=sizeof(char*),"Gleich krachts im Basic"); + pVar->SetUserData( (sal_uIntPtr)pStr ); + *((const char**)pTop) = pStr; + pTop += sizeof( char* ); + } + break; + + case SbxNULL: + case SbxEMPTY: + case SbxERROR: + case SbxDATE: + case SbxCURRENCY: + case SbxOBJECT: + case SbxDATAOBJECT: + default: + break; + } + } + else + { + // ByVal + switch( pVar->GetType() ) + { + case SbxINTEGER: + case SbxUINT: + case SbxINT: + case SbxUSHORT: + *((INT16*)pTop) = pVar->GetInteger(); + pTop += sizeof( INT16 ); + break; + + case SbxLONG: + case SbxULONG: + *((INT32*)pTop) = pVar->GetLong(); + pTop += sizeof( INT32 ); + break; + + case SbxSINGLE: + *((float*)pTop) = pVar->GetSingle(); + pTop += sizeof( float ); + break; + + case SbxDOUBLE: + *((double*)pTop) = pVar->GetDouble(); + pTop += sizeof( double ); + break; + + case SbxSTRING: + case SbxLPSTR: + { + char* pStr = new char[ pVar->GetString().Len() + 1 ]; + ByteString aByteStr( pVar->GetString(), gsl_getSystemTextEncoding() ); + strcpy( pStr, aByteStr.GetBuffer() ); // #100211# - checked + // ist nicht so sauber, aber wir sparen ein Pointerarray + DBG_ASSERT(sizeof(UINT32)>=sizeof(char*),"Gleich krachts im Basic"); + pVar->SetUserData( (sal_uIntPtr)pStr ); + *((const char**)pTop) = pStr; + pTop += sizeof( char* ); + } + break; + + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + *((BYTE*)pTop) = pVar->GetByte(); + pTop += sizeof( BYTE ); + break; + + case SbxNULL: + case SbxEMPTY: + case SbxERROR: + case SbxDATE: + case SbxCURRENCY: + case SbxOBJECT: + case SbxDATAOBJECT: + default: + break; + } + } + } + rSize = (USHORT)((ULONG)pTop - (ULONG)pStack); + return pStack; +} + + + + diff --git a/basic/source/runtime/dllmgr.hxx b/basic/source/runtime/dllmgr.hxx new file mode 100644 index 000000000000..ae25e570f10c --- /dev/null +++ b/basic/source/runtime/dllmgr.hxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dllmgr.hxx,v $ + * $Revision: 1.5 $ + * + * 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 _DLLMGR_HXX +#define _DLLMGR_HXX + +#define _SVSTDARR_BYTESTRINGSSORT +#include <svl/svarray.hxx> +#ifndef _SVSTDARR_HXX //autogen +#include <svl/svstdarr.hxx> +#endif + +// !!! nur zum debuggen fuer infoboxes !!! +//#ifndef _SV_HXX +//#include <sv.hxx> +//#endif + +//#ifndef _TOOLS_HXX +//#include <tools.hxx> +//#endif +#define _SVSTDARR_STRINGS +//#ifndef _SVSTDARR_HXX +//#include <svstdarr.hxx> +//#endif +#ifndef _SBERRORS_HXX +#include <basic/sberrors.hxx> +#endif + +class SbxArray; +class SbxVariable; + +class ImplSbiDll; +class ImplSbiProc; + +SV_DECL_PTRARR_SORT(ImplDllArr,ByteStringPtr,5,5) + +class SbiDllMgr +{ + ImplDllArr aDllArr; + + SbiDllMgr( const SbiDllMgr& ); + +#ifdef _DLLMGR_CXX + ImplSbiDll* GetDll( const ByteString& rDllName ); + SbiDllProc GetProc( ImplSbiDll*, const ByteString& rProcName ); + + SbiDllHandle CreateDllHandle( const ByteString& rDllName ); + void FreeDllHandle( SbiDllHandle ); + SbiDllProc GetProcAddr( SbiDllHandle, const ByteString& pProcName ); + SbError CallProc( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ); + SbError CallProcC( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ); + void* CreateStack( SbxArray* pArgs, USHORT& rSize ); + void CheckDllName( ByteString& rName ); +#endif + +public: + SbiDllMgr(); + ~SbiDllMgr(); + + SbError Call( const char* pFunc, const char* pDll, + SbxArray* pArgs, SbxVariable& rResult, + BOOL bCDecl ); + + void FreeDll( const ByteString& rDllName ); +}; + + + +#endif diff --git a/basic/source/runtime/inputbox.cxx b/basic/source/runtime/inputbox.cxx new file mode 100644 index 000000000000..a65b5d6d3786 --- /dev/null +++ b/basic/source/runtime/inputbox.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: inputbox.cxx,v $ + * $Revision: 1.10 $ + * + * 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..3e7bfb86bdf1 --- /dev/null +++ b/basic/source/runtime/iosys.cxx @@ -0,0 +1,1051 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: iosys.cxx,v $ + * $Revision: 1.30 $ + * + * 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..9c9886e05f94 --- /dev/null +++ b/basic/source/runtime/makefile.mk @@ -0,0 +1,93 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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 + +# --- 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)$(CPU)" == "WINI" +SLOFILES+= $(SLO)$/win.obj +.ENDIF + +.IF "$(GUI)$(COM)$(CPU)" == "WNTMSCI" +SLOFILES+= $(SLO)$/wnt.obj +.ENDIF + +.IF "$(GUI)$(COM)$(CPU)" == "WNTGCCI" +SLOFILES+= $(SLO)$/wnt-mingw.obj +.ENDIF + +.IF "$(GUI)$(CPU)" == "OS2I" +#FIXME SLOFILES+= $(SLO)$/os2.obj +.ENDIF + +EXCEPTIONSFILES=$(SLO)$/step0.obj \ + $(SLO)$/step2.obj \ + $(SLO)$/methods.obj \ + $(SLO)$/methods1.obj \ + $(SLO)$/iosys.obj \ + $(SLO)$/runtime.obj + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s +#kendy: Cut'n'paste from bridges/source/cpp_uno/mingw_intel/makefile.mk +#cmc: Ideally --noexecstack would be in operations, but with #i51385# pyuno +#remote bridgeing breaks +# $(CC) -Wa,--noexecstack -c -o $(SLO)$/$(@:b).o $< + $(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..6c26409a883c --- /dev/null +++ b/basic/source/runtime/methods.cxx @@ -0,0 +1,4547 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: methods.cxx,v $ + * $Revision: 1.82 $ + * + * 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 + +#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 + +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 Reference< XSimpleFileAccess3 > getFileAccess( void ) +{ + static Reference< XSimpleFileAccess3 > xSFI; + if( !xSFI.is() ) + { + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + if( xSMgr.is() ) + { + xSFI = 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; + if( rPar.Count() == 1 ) + { + nErr = StarBASIC::GetErrBasic(); + aErrorMsg = StarBASIC::GetErrorMsg(); + } + else + { + INT32 nCode = rPar.Get( 1 )->GetLong(); + if( nCode > 65535L ) + StarBASIC::Error( SbERR_CONVERSION ); + else + nErr = StarBASIC::GetSfxFromVBError( (USHORT)nCode ); + } + pBasic->MakeErrorText( nErr, aErrorMsg ); + rPar.Get( 0 )->PutString( pBasic->GetErrorText() ); + } +} + +// 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 ) +{ + 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() ) + { + 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() ) + { + 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() ) + { + 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() ) + { + 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() ) + { + 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 ) + { + 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() ) + { + 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() ) + { + 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() ) + { + 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 ) + { + 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 && 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 && 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() ) + { + 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() ) + { + 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..bac63edb62f9 --- /dev/null +++ b/basic/source/runtime/methods1.cxx @@ -0,0 +1,2610 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: methods1.cxx,v $ + * $Revision: 1.38 $ + * + * 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 "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(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 ); + ByteString aByteDLLName( rPar.Get(1)->GetString(), gsl_getSystemTextEncoding() ); + pINST->GetDllMgr()->FreeDll( aByteDLLName ); +} +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 ); +} + + +typedef ::std::vector< String > StringVector; + +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); + if( pClassModuleObject == NULL ) + { + StarBASIC::Error( SbERR_INVALID_USAGE_OBJECT ); + } + else + { + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( pClassModuleObject ); + } +} + diff --git a/basic/source/runtime/os2.asm b/basic/source/runtime/os2.asm new file mode 100644 index 000000000000..1dd5a296d6b7 --- /dev/null +++ b/basic/source/runtime/os2.asm @@ -0,0 +1,107 @@ +;************************************************************************* +; +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; Copyright 2008 by Sun Microsystems, Inc. +; +; OpenOffice.org - a multi-platform office productivity suite +; +; $RCSfile: os2.asm,v $ +; +; $Revision: 1.4 $ +; +; 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. +; +;************************************************************************* + +; Anmerkungen +; Direktaufruf von C- und PASCAL-Routinen, OS/2 +; +; Inhalt: +; type = CallXXX (far *proc, char *stack, short nstack) +; +; Kopie des Basic-Stacks (nstack Bytes) auf den C-Stack +; und Aufruf der Prozedur. + + .386 + .MODEL FLAT + + .CODE + + PUBLIC CallINT + PUBLIC CallLNG + PUBLIC CallSNG + PUBLIC CallDBL + PUBLIC CallSTR + PUBLIC CallFIX + + PUBLIC _CallINT + PUBLIC _CallLNG + PUBLIC _CallSNG + PUBLIC _CallDBL + PUBLIC _CallSTR + PUBLIC _CallFIX + +_CallINT LABEL byte +_CallLNG LABEL byte +_CallSNG LABEL byte +_CallDBL LABEL byte +_CallSTR LABEL byte +_CallFIX LABEL byte + +CallINT LABEL byte +CallLNG LABEL byte +CallSNG LABEL byte +CallDBL LABEL byte +CallSTR LABEL byte +CallFIX PROC + +p EQU [EBP+8] +stk EQU [EBP+12] +n EQU [EBP+16] + + PUSH EBP + MOV EBP,ESP + PUSH ESI + PUSH EDI + MOV DX,DS + MOVZX ECX,word ptr [n] + SUB ESP,ECX + MOV EDI,ESP + MOV AX,SS + MOV ES,AX + MOV ESI,[stk] + SHR ECX,1 + CLD + JCXZ $1 + REP MOVSW ; Stack uebernehmen +$1: MOV DS,DX + CALL LARGE [p] ; 32-bit + MOV ECX,EBP + SUB ECX,8 ; wegen gepushter Register + MOV ESP,ECX + POP EDI + POP ESI + POP EBP +; Bei Borland C++ Calling Convention: +; RET 12 +; CSet System-Calling Convention + RET +CallFIX ENDP + + END diff --git a/basic/source/runtime/props.cxx b/basic/source/runtime/props.cxx new file mode 100644 index 000000000000..dc890029e6f2 --- /dev/null +++ b/basic/source/runtime/props.cxx @@ -0,0 +1,764 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: props.cxx,v $ + * $Revision: 1.7 $ + * + * 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" + + +// 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( 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(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..2d0092e14eeb --- /dev/null +++ b/basic/source/runtime/rtlproto.hxx @@ -0,0 +1,350 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: rtlproto.hxx,v $ + * $Revision: 1.20 $ + * + * 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(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(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 100644 index 000000000000..6c83c6e2f3f1 --- /dev/null +++ b/basic/source/runtime/runtime.cxx @@ -0,0 +1,1158 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: runtime.cxx,v $ + * $Revision: 1.39 $ + * + * 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" + +bool SbiRuntime::isVBAEnabled() +{ + bool result = false; + SbiInstance* pInst = pINST; + if ( pInst && pINST->pRun ) + result = pInst->pRun->GetImageFlag( SBIMG_VBASUPPORT ); + return result; +} + +// #91147 Global reschedule flag +static BOOL bStaticGlobalEnableReschedule = TRUE; + +void StarBASIC::StaticEnableReschedule( BOOL bReschedule ) +{ + bStaticGlobalEnableReschedule = bReschedule; +} + + +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::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::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; +#if defined GCC + SetParameters( pe ? pe->GetParameters() : (class SbxArray *)NULL ); +#else + SetParameters( pe ? pe->GetParameters() : NULL ); +#endif + pRefSaveList = NULL; + pItemStoreList = NULL; + bVBAEnabled = isVBAEnabled(); +} + +SbiRuntime::~SbiRuntime() +{ + ClearGosubStack(); + ClearArgvStack(); + ClearForStack(); + + // #74254 Items zum Sichern temporaere Referenzen freigeben + ClearRefs(); + while( pItemStoreList ) + { + RefSaveItem* pToDeleteItem = pItemStoreList; + pItemStoreList = pToDeleteItem->pNext; + delete pToDeleteItem; + } +} + +// 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(); + } + 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 ) + { + 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 + { + pInst->Abort(); + } + + // ALT: Nur + // pInst->Abort(); + } + } + } + return bRun; +} + +void SbiRuntime::Error( SbError n ) +{ + if( n ) + nError = n; +} + +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 ); +} + +////////////////////////////////////////////////////////////////////////// +// +// 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(); + ByteString aByteFuncName( aFuncName, gsl_getSystemTextEncoding() ); + ByteString aByteDLLName( aDLLName, gsl_getSystemTextEncoding() ); + SbError nErr = pDllMgr->Call( aByteFuncName.GetBuffer(), aByteDLLName.GetBuffer(), 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..b9b2bee387a6 --- /dev/null +++ b/basic/source/runtime/stdobj.cxx @@ -0,0 +1,783 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stdobj.cxx,v $ + * $Revision: 1.28 $ + * + * 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 }, +{ "DumpAllObjects", SbxEMPTY, 2 | _SUB, RTLNAME(DumpAllObjects),0 }, + { "FileSpec", SbxSTRING, 0,NULL,0 }, + { "DumpAll", SbxINTEGER, _OPT, NULL,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", SbxLONG, _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 }, +{ "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; + } + + 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..7e0fef5cccc9 --- /dev/null +++ b/basic/source/runtime/stdobj1.cxx @@ -0,0 +1,554 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stdobj1.cxx,v $ + * $Revision: 1.10 $ + * + * 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..6ef6db23798c --- /dev/null +++ b/basic/source/runtime/step0.cxx @@ -0,0 +1,1273 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: step0.cxx,v $ + * $Revision: 1.32 $ + * + * 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 "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> + +#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(); + BOOL bRes = BOOL( + refVar1->GetType() == SbxOBJECT + && refVar2->GetType() == 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 + SbxDataType eValType = refVal->GetType(); + SbxDataType eVarType = refVar->GetType(); + if( (eValType != SbxOBJECT + && eValType != SbxEMPTY +// seems like when using the default method its possible for objects +// to be empty ( no broadcast has taken place yet ) or the actual value is + + && !bHandleDefaultProp + && !(eValType & SbxARRAY)) || + (eVarType != SbxOBJECT + && eVarType != SbxEMPTY + && !bHandleDefaultProp + && !(eVarType & SbxARRAY) ) ) + { + Error( SbERR_INVALID_USAGE_OBJECT ); + } + else + { + // Getting in here causes problems with objects with default properties + // if they are SbxEMPTY I guess + if ( !bHandleDefaultProp || ( bHandleDefaultProp && refVal->GetType() == 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; + } + } + + *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 ) ); +} + +// 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; +} + +void SbiRuntime::StepNOERROR() +{ + pInst->aErrorMsg = String(); + pInst->nErr = 0L; + pInst->nErl = 0; + nError = 0L; + bError = FALSE; +} + +// UP verlassen + +void SbiRuntime::StepLEAVE() +{ + bRun = FALSE; +} + +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 ); + Error( error ); +} + diff --git a/basic/source/runtime/step1.cxx b/basic/source/runtime/step1.cxx new file mode 100644 index 000000000000..3c461c1f5541 --- /dev/null +++ b/basic/source/runtime/step1.cxx @@ -0,0 +1,571 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: step1.cxx,v $ + * $Revision: 1.18 $ + * + * 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 "runtime.hxx" +#include "sbintern.hxx" +#include "iosys.hxx" +#include "image.hxx" +#include "sbunoobj.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 unoToSbxValue( SbxVariable* pVar, const Any& aValue ); + +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; +} + +// 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( 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 bOk = true; + + 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 + { + 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 bOk = checkClass_Impl( xObjVal, aClass, false ); + + 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 100644 index 000000000000..fb0b217b76c4 --- /dev/null +++ b/basic/source/runtime/step2.cxx @@ -0,0 +1,1216 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: step2.cxx,v $ + * $Revision: 1.35 $ + * + * 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 + /* + else if( pElem->ISA(SbUnoProperty) ) + { + // 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); + if( pUnoMethod ) + { + 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(); + 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 ); + PushVar( pNew ); +} + + +// 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; + SbxVariable* p = new SbxVariable( t ); + p->SetName( aName ); + 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) nOp2; + 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); + } +} + +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 ) + StepPUBLIC( nOp1, nOp2 ); +} + +// 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; + BOOL bFlag = rBasic.IsSet( SBX_NO_MODIFY ); + rBasic.SetFlag( SBX_NO_MODIFY ); + SbxVariableRef p = rBasic.Find( aName, SbxCLASS_PROPERTY ); + if( p.Is() ) + rBasic.Remove (p); + p = rBasic.Make( aName, SbxCLASS_PROPERTY, t ); + if( !bFlag ) + rBasic.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/win.asm b/basic/source/runtime/win.asm new file mode 100644 index 000000000000..252bb43b5dcf --- /dev/null +++ b/basic/source/runtime/win.asm @@ -0,0 +1,84 @@ +;************************************************************************* +; +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; Copyright 2008 by Sun Microsystems, Inc. +; +; OpenOffice.org - a multi-platform office productivity suite +; +; $RCSfile: win.asm,v $ +; +; $Revision: 1.4 $ +; +; 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. +; +;************************************************************************* + +; Anmerkungen +; Direktaufruf von C- und PASCAL-Routinen, Windows und OS/2 +; +; Inhalt: +; type = CallXXX (far *proc, char *stack, short nstack) +; +; Kopie des Basic-Stacks (nstack Bytes) auf den C-Stack +; und Aufruf der Prozedur. + + .MODEL LARGE,C + + .CODE + + PUBLIC CallINT + PUBLIC CallLNG + PUBLIC CallSNG + PUBLIC CallDBL + PUBLIC CallSTR + PUBLIC CallFIX + +CallINT LABEL byte +CallLNG LABEL byte +CallSNG LABEL byte +CallDBL LABEL byte +CallSTR LABEL byte +CallFIX PROC p:PTR,stk:PTR,n:WORD + + PUSH SI + PUSH DI + MOV DX,DS + SUB SP,[n] + MOV DI,SP + MOV AX,SS + MOV ES,AX + LDS SI,[stk] + MOV CX,[n] + SHR CX,1 + CLD + JCXZ $1 + REP MOVSW ; Stack uebernehmen +$1: MOV DS,DX + CALL [p] ; Aufruf der Prozedur + CLI + MOV SP,BP + SUB SP,4 ; wegen gepushter Register + STI + POP DI + POP SI + RET + +CallFIX ENDP + + END diff --git a/basic/source/runtime/wnt-mingw.s b/basic/source/runtime/wnt-mingw.s new file mode 100644 index 000000000000..b42c5278c7e0 --- /dev/null +++ b/basic/source/runtime/wnt-mingw.s @@ -0,0 +1,97 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: wnt.asm,v $ +# +# $Revision: 1.4 $ +# +# 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. +# +#************************************************************************* + +# Anmerkungen +# Direktaufruf von C- und PASCAL-Routinen, Windows und OS/2 +# +# Inhalt: +# type = CallXXX (far *pProc, char *pStack, short nStack) +# +# Kopie des Basic-Stacks (nStack Bytes) auf den C-Stack +# und Aufruf der Prozedur. + + .intel_syntax + #.386 + +#_TEXT SEGMENT DWORD PUBLIC 'CODE' USE32 + + #ASSUME CS:_TEXT + +.globl _CallINT +.globl _CallLNG +.globl _CallDBL +.globl _CallSTR +.globl _CallFIX + +_CallINT: +_CallLNG: +_CallDBL: +_CallSTR: + +_CallFIX: PUSH EBP + MOV EBP,ESP + PUSH ESI + PUSH EDI + + PUSH ECX + PUSH EDX + + MOV DX,DS + MOVZX EAX,WORD PTR [EBP+16] # EAX == nStack + SUB ESP,EAX # Stack um nStack Bytes vergroessern + MOV EDI,ESP + MOV AX,SS + MOV ES,AX # ES:EDI = Startadresse des fuer + # Parameter reservierten Stackbereichs + MOV ESI,[EBP+12] # DS:ESI == pStack + + MOVZX ECX,WORD PTR [EBP+16] # ECX == nStack + SHR ECX,1 + CLD + JCXZ $1 + REP MOVSW # Stack uebernehmen +$1: MOV DS,DX + CALL DWORD PTR [EBP+8] # Aufruf der Prozedur + # CLI # unter NT nicht erlaubt (privileged instruction) + MOV ESP,EBP + SUB ESP,16 # wegen gepushter Register + # (ESI, EDI) + # STI + POP EDX + POP ECX + POP EDI + POP ESI + POP EBP + RET 12 + +#_TEXT ENDS + + #END diff --git a/basic/source/runtime/wnt.asm b/basic/source/runtime/wnt.asm new file mode 100644 index 000000000000..b4d1bd15d2ed --- /dev/null +++ b/basic/source/runtime/wnt.asm @@ -0,0 +1,96 @@ +;************************************************************************* +; +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; Copyright 2008 by Sun Microsystems, Inc. +; +; OpenOffice.org - a multi-platform office productivity suite +; +; $RCSfile: wnt.asm,v $ +; +; $Revision: 1.4 $ +; +; 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. +; +;************************************************************************* + +; Anmerkungen +; Direktaufruf von C- und PASCAL-Routinen, Windows und OS/2 +; +; Inhalt: +; type = CallXXX (far *pProc, char *pStack, short nStack) +; +; Kopie des Basic-Stacks (nStack Bytes) auf den C-Stack +; und Aufruf der Prozedur. + + .386 + +_TEXT SEGMENT DWORD PUBLIC 'CODE' USE32 + + ASSUME CS:_TEXT + + PUBLIC _CallINT@12 + PUBLIC _CallLNG@12 + PUBLIC _CallDBL@12 + PUBLIC _CallSTR@12 + PUBLIC _CallFIX@12 + +_CallINT@12 LABEL byte +_CallLNG@12 LABEL byte +_CallDBL@12 LABEL byte +_CallSTR@12 LABEL byte + +_CallFIX@12: PUSH EBP + MOV EBP,ESP + PUSH ESI + PUSH EDI + + PUSH ECX + PUSH EDX + + MOV DX,DS + MOVZX EAX,WORD PTR [EBP+16] ; EAX == nStack + SUB ESP,EAX ; Stack um nStack Bytes vergroessern + MOV EDI,ESP + MOV AX,SS + MOV ES,AX ; ES:EDI = Startadresse des fuer + ; Parameter reservierten Stackbereichs + MOV ESI,[EBP+12] ; DS:ESI == pStack + + MOVZX ECX,WORD PTR [EBP+16] ; ECX == nStack + SHR ECX,1 + CLD + JCXZ $1 + REP MOVSW ; Stack uebernehmen +$1: MOV DS,DX + CALL DWORD PTR [EBP+8] ; Aufruf der Prozedur + ; CLI ; unter NT nicht erlaubt (privileged instruction) + MOV ESP,EBP + SUB ESP,16 ; wegen gepushter Register + ; (ESI, EDI) + ; STI + POP EDX + POP ECX + POP EDI + POP ESI + POP EBP + RET 12 + +_TEXT ENDS + + END |