diff options
Diffstat (limited to 'binfilter/bf_basic')
55 files changed, 24694 insertions, 0 deletions
diff --git a/binfilter/bf_basic/source/basmgr/basmgr.cxx b/binfilter/bf_basic/source/basmgr/basmgr.cxx new file mode 100644 index 000000000000..cc1b0e1f7da4 --- /dev/null +++ b/binfilter/bf_basic/source/basmgr/basmgr.cxx @@ -0,0 +1,2668 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/stream.hxx> +#include <sot/storage.hxx> +#include <tools/urlobj.hxx> +#include <bf_svtools/smplhint.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/msgbox.hxx> +#include <sbx.hxx> +#include <sot/storinfo.hxx> +#include <bf_svtools/pathoptions.hxx> +#include <tools/debug.hxx> + +#include <sbmod.hxx> + +#include "basmgr.hxx" +#include "sbintern.hxx" + + +#define LIB_SEP 0x01 +#define LIBINFO_SEP 0x02 +#define LIBINFO_ID 0x1491 +#define PASSWORD_MARKER 0x31452134 + + +// Library API, implemented for XML import/export + +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/script/XStarBasicAccess.hpp> +#include <com/sun/star/script/XStarBasicModuleInfo.hpp> +#include <com/sun/star/script/XStarBasicDialogInfo.hpp> +#include <com/sun/star/script/XStarBasicLibraryInfo.hpp> + +#include <cppuhelper/implbase1.hxx> + +namespace binfilter { + +using namespace com::sun::star::container; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::script; +using namespace cppu; +using namespace rtl; + +typedef WeakImplHelper1< XNameContainer > NameContainerHelper; +typedef WeakImplHelper1< XStarBasicModuleInfo > ModuleInfoHelper; +typedef WeakImplHelper1< XStarBasicDialogInfo > DialogInfoHelper; +typedef WeakImplHelper1< XStarBasicLibraryInfo > LibraryInfoHelper; +typedef WeakImplHelper1< XStarBasicAccess > StarBasicAccessHelper; + + +#define CURR_VER 2 + +// Version 1 +// ULONG nEndPos +// USHORT nId +// USHORT nVer +// BOOL bDoLoad +// String LibName +// String AbsStorageName +// String RelStorageName +// Version 2 +// + BOOL bReference + +static const char szStdLibName[] = "Standard"; +static const char szBasicStorage[] = "StarBASIC"; +static const char szOldManagerStream[] = "BasicManager"; +static const char szManagerStream[] = "BasicManager2"; +static const char szImbedded[] = "LIBIMBEDDED"; +static const char szCryptingKey[] = "CryptedBasic"; +static const char szScriptLanguage[] = "StarBasic"; + +static const String BasicStreamName( RTL_CONSTASCII_USTRINGPARAM(szBasicStorage) ); +static const String ManagerStreamName( RTL_CONSTASCII_USTRINGPARAM(szManagerStream) ); + +#define DEFINE_CONST_UNICODE(CONSTASCII) UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) + + +TYPEINIT1( BasicManager, SfxBroadcaster ); +DBG_NAME( BasicManager ); + +StreamMode eStreamReadMode = STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYALL; +StreamMode eStorageReadMode = STREAM_READ | STREAM_SHARE_DENYWRITE; + +DECLARE_LIST( BasErrorLst, BasicError* ) + + +//---------------------------------------------------------------------------- +// BasicManager impl data +struct BasicManagerImpl +{ + LibraryContainerInfo* mpInfo; + + // Save stream data + SvMemoryStream* mpManagerStream; + SvMemoryStream** mppLibStreams; + sal_Int32 mnLibStreamCount; + sal_Bool mbModifiedByLibraryContainer; + sal_Bool mbError; + + BasicManagerImpl( void ) + : mpInfo( NULL ) + , mpManagerStream( NULL ) + , mppLibStreams( NULL ) + , mnLibStreamCount( 0 ) + , mbModifiedByLibraryContainer( sal_False ) + , mbError( sal_False ) + {} + ~BasicManagerImpl(); +}; + +BasicManagerImpl::~BasicManagerImpl() +{ + delete mpInfo; + delete mpManagerStream; + if( mppLibStreams ) + { + for( sal_Int32 i = 0 ; i < mnLibStreamCount ; i++ ) + delete mppLibStreams[i]; + delete[] mppLibStreams; + } +} + +//============================================================================ +// BasMgrContainerListenerImpl +//============================================================================ + +typedef ::cppu::WeakImplHelper1< ::com::sun::star::container::XContainerListener > ContainerListenerHelper; + +class BasMgrContainerListenerImpl: public ContainerListenerHelper +{ + BasicManager* mpMgr; + OUString maLibName; // empty -> no lib, but lib container + +public: + BasMgrContainerListenerImpl( BasicManager* pMgr, OUString aLibName ) + : mpMgr( pMgr ) + , maLibName( aLibName ) {} + + static void insertLibraryImpl( const Reference< XLibraryContainer >& xScriptCont, BasicManager* pMgr, + Any aLibAny, OUString aLibName ); + static void addLibraryModulesImpl( BasicManager* pMgr, Reference< XNameAccess > xLibNameAccess, + OUString aLibName ); + + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw(::com::sun::star::uno::RuntimeException); + + // XContainerListener + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) + throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) + throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) + throw(::com::sun::star::uno::RuntimeException); +}; + + +//============================================================================ +// BasMgrContainerListenerImpl +//============================================================================ + +void BasMgrContainerListenerImpl::insertLibraryImpl( const Reference< XLibraryContainer >& xScriptCont, + BasicManager* pMgr, Any aLibAny, OUString aLibName ) +{ + Reference< XNameAccess > xLibNameAccess; + aLibAny >>= xLibNameAccess; + + if( !pMgr->GetLib( aLibName ) ) + { + BasicManager* pBasMgr = static_cast< BasicManager* >( pMgr ); +#ifdef DBG_UTIL + StarBASIC* pLib = +#endif + pBasMgr->CreateLibForLibContainer( aLibName, xScriptCont ); + DBG_ASSERT( pLib, "XML Import: Basic library could not be created"); + } + + Reference< XContainer> xLibContainer( xLibNameAccess, UNO_QUERY ); + if( xLibContainer.is() ) + { + // Register listener for library + Reference< XContainerListener > xLibraryListener + = static_cast< XContainerListener* > + ( new BasMgrContainerListenerImpl( pMgr, aLibName ) ); + xLibContainer->addContainerListener( xLibraryListener ); + } + + if( xScriptCont->isLibraryLoaded( aLibName ) ) + { + addLibraryModulesImpl( pMgr, xLibNameAccess, aLibName ); + } +} + + +void BasMgrContainerListenerImpl::addLibraryModulesImpl( BasicManager* pMgr, + Reference< XNameAccess > xLibNameAccess, OUString aLibName ) +{ + OUString aScriptLanguage = DEFINE_CONST_UNICODE( szScriptLanguage ); + Sequence< OUString > aModuleNames = xLibNameAccess->getElementNames(); + sal_Int32 nModuleCount = aModuleNames.getLength(); + + StarBASIC* pLib = pMgr->GetLib( aLibName ); + DBG_ASSERT( pLib, "BasMgrContainerListenerImpl::addLibraryModulesImpl: Unknown lib!"); + if( pLib ) + { + const OUString* pNames = aModuleNames.getConstArray(); + for( sal_Int32 j = 0 ; j < nModuleCount ; j++ ) + { + OUString aModuleName = pNames[ j ]; + Any aElement = xLibNameAccess->getByName( aModuleName ); + OUString aMod; + aElement >>= aMod; + pLib->MakeModule32( aModuleName, aMod ); + } + } + + pLib->SetModified( FALSE ); +} + + + +// XEventListener +//---------------------------------------------------------------------------- + +void SAL_CALL BasMgrContainerListenerImpl::disposing( const EventObject& Source ) + throw( RuntimeException ) +{ + (void)Source; +} + +// XContainerListener +//---------------------------------------------------------------------------- + +void SAL_CALL BasMgrContainerListenerImpl::elementInserted( const ContainerEvent& Event ) + throw( RuntimeException ) +{ + sal_Bool bLibContainer = ( maLibName.getLength() == 0 ); + OUString aName; + Event.Accessor >>= aName; + + mpMgr->mpImpl->mbModifiedByLibraryContainer = sal_True; + + if( bLibContainer ) + { + Reference< XLibraryContainer > xScriptCont( Event.Source, UNO_QUERY ); + insertLibraryImpl( xScriptCont, mpMgr, Event.Element, aName ); + } + else + { + OUString aScriptLanguage = DEFINE_CONST_UNICODE( szScriptLanguage ); + OUString aMod; + Event.Element >>= aMod; + + StarBASIC* pLib = mpMgr->GetLib( maLibName ); + DBG_ASSERT( pLib, "BasMgrContainerListenerImpl::elementInserted: Unknown lib!"); + if( pLib ) + { + SbModule* pMod = pLib->FindModule( aName ); + if( !pMod ) + { + pLib->MakeModule32( aName, aMod ); + pLib->SetModified( FALSE ); + } + } + } +} + +//---------------------------------------------------------------------------- + +void SAL_CALL BasMgrContainerListenerImpl::elementReplaced( const ContainerEvent& Event ) + throw( RuntimeException ) +{ + OUString aName; + Event.Accessor >>= aName; + + mpMgr->mpImpl->mbModifiedByLibraryContainer = sal_True; + + // Replace not possible for library container +#ifdef DBG_UTIL + sal_Bool bLibContainer = ( maLibName.getLength() == 0 ); +#endif + DBG_ASSERT( !bLibContainer, "library container fired elementReplaced()"); + + StarBASIC* pLib = mpMgr->GetLib( maLibName ); + if( pLib ) + { + SbModule* pMod = pLib->FindModule( aName ); + OUString aMod; + Event.Element >>= aMod; + if( pMod ) + pMod->SetSource32( aMod ); + else + pLib->MakeModule32( aName, aMod ); + + pLib->SetModified( FALSE ); + } +} + +//---------------------------------------------------------------------------- + +void SAL_CALL BasMgrContainerListenerImpl::elementRemoved( const ContainerEvent& Event ) + throw( RuntimeException ) +{ + OUString aName; + Event.Accessor >>= aName; + + mpMgr->mpImpl->mbModifiedByLibraryContainer = sal_True; + + sal_Bool bLibContainer = ( maLibName.getLength() == 0 ); + if( bLibContainer ) + { + StarBASIC* pLib = mpMgr->GetLib( aName ); + if( pLib ) + { + USHORT nLibId = mpMgr->GetLibId( aName ); + mpMgr->RemoveLib( nLibId, FALSE ); + } + } + else + { + StarBASIC* pLib = mpMgr->GetLib( maLibName ); + SbModule* pMod = pLib ? pLib->FindModule( aName ) : NULL; + if( pMod ) + { + pLib->Remove( pMod ); + pLib->SetModified( FALSE ); + } + } +} + + +//===================================================================== + +class BasicErrorManager +{ +private: + BasErrorLst aErrorList; + +public: + ~BasicErrorManager(); + + void Reset(); + void InsertError( const BasicError& rError ); + + BOOL HasErrors() { return (BOOL)aErrorList.Count(); } + BasicError* GetFirstError() { return aErrorList.First(); } + BasicError* GetNextError() { return aErrorList.Next(); } +}; + + +BasicErrorManager::~BasicErrorManager() +{ + Reset(); +} + +void BasicErrorManager::Reset() +{ + BasicError* pError = (BasicError*)aErrorList.First(); + while ( pError ) + { + delete pError; + pError = (BasicError*)aErrorList.Next(); + } + aErrorList.Clear(); +} + +void BasicErrorManager::InsertError( const BasicError& rError ) +{ + aErrorList.Insert( new BasicError( rError ), LIST_APPEND ); +} + +BasicError::BasicError( ULONG nId, USHORT nR, const String& rErrStr ) : + aErrStr( rErrStr ) +{ + nErrorId = nId; + nReason = nR; +} + +BasicError::BasicError( const BasicError& rErr ) : + aErrStr( rErr.aErrStr ) +{ + nErrorId = rErr.nErrorId; + nReason = rErr.nReason; +} + + +class BasicLibInfo +{ +private: + StarBASICRef xLib; + String aLibName; + String aStorageName; // String reicht, da zur Laufzeit eindeutig. + String aRelStorageName; + String aPassword; + + BOOL bDoLoad; + BOOL bReference; + BOOL bPasswordVerified; + BOOL bFoundInPath; // Darf dann nicht neu relativiert werden! + + // Lib represents library in new UNO library container + Reference< XLibraryContainer > mxScriptCont; + +public: + BasicLibInfo(); + + BOOL IsReference() const { return bReference; } + BOOL& IsReference() { return bReference; } + + BOOL IsExtern() const { return ! aStorageName.EqualsAscii(szImbedded); } + + void SetStorageName( const String& rName ) { aStorageName = rName; } + const String& GetStorageName() const { return aStorageName; } + + void SetRelStorageName( const String& rN ) { aRelStorageName = rN; } + const String& GetRelStorageName() const { return aRelStorageName; } + void CalcRelStorageName( const String& rMgrStorageName ); + + StarBASICRef GetLib() const + { + if( mxScriptCont.is() && mxScriptCont->hasByName( aLibName ) && + !mxScriptCont->isLibraryLoaded( aLibName ) ) + return StarBASICRef(); + return xLib; + } + StarBASICRef& GetLibRef() { return xLib; } + void SetLib( StarBASIC* pBasic ) { xLib = pBasic; } + + const String& GetLibName() const { return aLibName; } + void SetLibName( const String& rName ) { aLibName = rName; } + + // Nur temporaer fuer Laden/Speichern.... + BOOL DoLoad() { return bDoLoad; } + + BOOL HasPassword() const { return aPassword.Len() != 0; } + const String& GetPassword() const { return aPassword; } + void SetPassword( const String& rNewPassword ) + { aPassword = rNewPassword; } + BOOL IsPasswordVerified() const { return bPasswordVerified; } + void SetPasswordVerified() { bPasswordVerified = TRUE; } + + BOOL IsFoundInPath() const { return bFoundInPath; } + void SetFoundInPath( BOOL bInPath ) { bFoundInPath = bInPath; } + + void Store( SotStorageStream& rSStream, const String& rBasMgrStorageName, BOOL bUseOldReloadInfo ); + static BasicLibInfo* Create( SotStorageStream& rSStream ); + + Reference< XLibraryContainer > GetLibraryContainer( void ) + { return mxScriptCont; } + void SetLibraryContainer( const Reference< XLibraryContainer >& xScriptCont ) + { mxScriptCont = xScriptCont; } +}; + +DECLARE_LIST( BasicLibsBase, BasicLibInfo* ) + +class BasicLibs : public BasicLibsBase +{ +public: + String aBasicLibPath; // soll eigentlich Member vom Manager werden, aber jetzt nicht inkompatibel! +}; + +BasicLibInfo::BasicLibInfo() +{ + bReference = FALSE; + bPasswordVerified = FALSE; + bDoLoad = FALSE; + bFoundInPath = FALSE; + mxScriptCont = NULL; + aStorageName = String::CreateFromAscii(szImbedded); + aRelStorageName = String::CreateFromAscii(szImbedded); +} + +void BasicLibInfo::Store( SotStorageStream& rSStream, const String& rBasMgrStorageName, BOOL bUseOldReloadInfo ) +{ + ULONG nStartPos = rSStream.Tell(); + sal_uInt32 nEndPos = 0; + + USHORT nId = LIBINFO_ID; + USHORT nVer = CURR_VER; + + rSStream << nEndPos; + rSStream << nId; + rSStream << nVer; + + String aCurStorageName = INetURLObject(rBasMgrStorageName, INET_PROT_FILE).GetMainURL( INetURLObject::NO_DECODE ); + DBG_ASSERT(aCurStorageName.Len() != 0, "Bad storage name"); + + // Falls nicht gesetzt, StorageName initialisieren + if ( aStorageName.Len() == 0 ) + aStorageName = aCurStorageName; + + // Wieder laden? + BOOL bDoLoad_ = xLib.Is(); + if ( bUseOldReloadInfo ) + bDoLoad_ = DoLoad(); + rSStream << bDoLoad_; + + // Den Namen der Lib... + rSStream.WriteByteString(GetLibName()); + + // Absoluter Pfad.... + if ( ! GetStorageName().EqualsAscii(szImbedded) ) + { + String aSName = INetURLObject( GetStorageName(), INET_PROT_FILE).GetMainURL( INetURLObject::NO_DECODE ); + DBG_ASSERT(aSName.Len() != 0, "Bad storage name"); + rSStream.WriteByteString( aSName ); + } + else + rSStream.WriteByteString( szImbedded ); + + // Relativer Pfad... + if ( ( aStorageName == aCurStorageName ) || ( aStorageName.EqualsAscii(szImbedded) ) ) + rSStream.WriteByteString( szImbedded ); + else + { + // Nicht den relativen Pfad ermitteln, wenn die Datei nur im Pfad + // gefunden wurde: Dann andert sich der relative Pfad und nach einem + // verschieben der Libs in einen anderen Pfad werden sie nicht gefunden. + if ( !IsFoundInPath() ) + CalcRelStorageName( aCurStorageName ); + rSStream.WriteByteString(aRelStorageName); + } + + // ------------------------------ + // Version 2 + // ------------------------------ + + // Referenz... + rSStream << bReference; + + // ------------------------------ + // Schluss + // ------------------------------ + + nEndPos = rSStream.Tell(); + rSStream.Seek( nStartPos ); + rSStream << nEndPos; + rSStream.Seek( nEndPos ); +} + +BasicLibInfo* BasicLibInfo::Create( SotStorageStream& rSStream ) +{ + BasicLibInfo* pInfo = new BasicLibInfo; + + sal_uInt32 nEndPos; + USHORT nId; + USHORT nVer; + + rSStream >> nEndPos; + rSStream >> nId; + rSStream >> nVer; + + DBG_ASSERT( nId == LIBINFO_ID, "Keine BasicLibInfo !?" ); + if( nId == LIBINFO_ID ) + { + // Wieder laden? + BOOL bDoLoad; + rSStream >> bDoLoad; + pInfo->bDoLoad = bDoLoad; + + // Den Namen der Lib... + String aName; + rSStream.ReadByteString(aName); + pInfo->SetLibName( aName ); + + // Absoluter Pfad.... + String aStorageName; + rSStream.ReadByteString(aStorageName); + pInfo->SetStorageName( aStorageName ); + + // Relativer Pfad... + String aRelStorageName; + rSStream.ReadByteString(aRelStorageName); + pInfo->SetRelStorageName( aRelStorageName ); + + if ( nVer >= 2 ) + { + BOOL bReferenz; + rSStream >> bReferenz; + pInfo->IsReference() = bReferenz; + } + + rSStream.Seek( nEndPos ); + } + return pInfo; +} + +void BasicLibInfo::CalcRelStorageName( const String& rMgrStorageName ) +{ + if ( rMgrStorageName.Len() ) + { + INetURLObject aAbsURLObj( rMgrStorageName ); + aAbsURLObj.removeSegment(); + String aPath = aAbsURLObj.GetMainURL( INetURLObject::NO_DECODE ); + UniString aRelURL = INetURLObject::GetRelURL( aPath, GetStorageName() ); + SetRelStorageName( aRelURL ); + } + else + SetRelStorageName( String() ); +} + +BasicManager::BasicManager( SotStorage& rStorage, const String& rBaseURL, StarBASIC* pParentFromStdLib, String* pLibPath ) +{ + DBG_CTOR( BasicManager, 0 ); + + Init(); + + if( pLibPath ) + pLibs->aBasicLibPath = *pLibPath; + + String aStorName( rStorage.GetName() ); + maStorageName = INetURLObject(aStorName, INET_PROT_FILE).GetMainURL( INetURLObject::NO_DECODE ); + + // #91251: Storage name not longer available for documents < 5.0 + // Should be no real problem, because only relative storage names + // (links) can be affected. + // DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + // DBG_ASSERT(aStorageName.Len() != 0, "Bad storage name"); + + // Wenn es den Manager-Stream nicht gibt, sind keine weiteren + // Aktionen noetig. + if ( rStorage.IsStream( ManagerStreamName ) ) + { + LoadBasicManager( rStorage, rBaseURL ); + // StdLib erhaelt gewuenschten Parent: + StarBASIC* pStdLib = GetStdLib(); + DBG_ASSERT( pStdLib, "Standard-Lib nicht geladen?" ); + if ( !pStdLib ) + { + // Sollte eigentlich nie passieren, aber dann wenigstens nicht abstuerzen... + pStdLib = new StarBASIC; + BasicLibInfo* pStdLibInfo = pLibs->GetObject( 0 ); + if ( !pStdLibInfo ) + pStdLibInfo = CreateLibInfo(); + pStdLibInfo->SetLib( pStdLib ); + StarBASICRef xStdLib = pStdLibInfo->GetLib(); + xStdLib->SetName( String::CreateFromAscii(szStdLibName) ); + pStdLibInfo->SetLibName( String::CreateFromAscii(szStdLibName) ); + xStdLib->SetFlag( SBX_DONTSTORE | SBX_EXTSEARCH ); + xStdLib->SetModified( FALSE ); + } + else + { + pStdLib->SetParent( pParentFromStdLib ); + // Die anderen erhalten die StdLib als Parent: + for ( USHORT nBasic = 1; nBasic < GetLibCount(); nBasic++ ) + { + StarBASIC* pBasic = GetLib( nBasic ); + if ( pBasic ) + { +// pBasic->SetParent( pStdLib ); + pStdLib->Insert( pBasic ); + pBasic->SetFlag( SBX_EXTSEARCH ); + } + } + // Durch das Insert modified: + pStdLib->SetModified( FALSE ); + } + + // #91626 Save all stream data to save it unmodified if basic isn't modified + // in an 6.0+ office. So also the old basic dialogs can be saved. + SotStorageStreamRef xManagerStream = rStorage.OpenSotStream + ( ManagerStreamName, eStreamReadMode ); + mpImpl->mpManagerStream = new SvMemoryStream(); + *static_cast<SvStream*>(&xManagerStream) >> *mpImpl->mpManagerStream; + + SotStorageRef xBasicStorage = rStorage.OpenSotStorage + ( BasicStreamName, eStorageReadMode, FALSE ); + if( xBasicStorage.Is() && !xBasicStorage->GetError() ) + { + USHORT nLibs = GetLibCount(); + mpImpl->mppLibStreams = new SvMemoryStream*[ nLibs ]; + for( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pLibs->GetObject( nL ); + DBG_ASSERT( pInfo, "pInfo?!" ); + SotStorageStreamRef xBasicStream = xBasicStorage->OpenSotStream( pInfo->GetLibName(), eStreamReadMode ); + mpImpl->mppLibStreams[nL] = new SvMemoryStream(); + *static_cast<SvStream*>(&xBasicStream) >> *( mpImpl->mppLibStreams[nL] ); + } + } + else + mpImpl->mbError = sal_True; + } + else + { + ImpCreateStdLib( pParentFromStdLib ); + if ( rStorage.IsStream( String::CreateFromAscii(szOldManagerStream) ) ) + LoadOldBasicManager( rStorage ); + } + + bBasMgrModified = FALSE; +} + + +void copyToLibraryContainer( StarBASIC* pBasic, LibraryContainerInfo* pInfo ) +{ + Reference< XLibraryContainer > xScriptCont; + String aLibName = pBasic->GetName(); + if( pInfo && (xScriptCont = pInfo->mxScriptCont).is() ) + { + if( !xScriptCont->hasByName( aLibName ) ) + xScriptCont->createLibrary( aLibName ); + + Any aLibAny = xScriptCont->getByName( aLibName ); + Reference< XNameContainer > xLib; + aLibAny >>= xLib; + if( xLib.is() ) + { + USHORT nModCount = pBasic->GetModules()->Count(); + for ( USHORT nMod = 0 ; nMod < nModCount ; nMod++ ) + { + SbModule* pModule = (SbModule*)pBasic->GetModules()->Get( nMod ); + DBG_ASSERT( pModule, "Modul nicht erhalten!" ); + + String aModName = pModule->GetName(); + if( !xLib->hasByName( aModName ) ) + { + OUString aSource = pModule->GetSource32(); + Any aSourceAny; + aSourceAny <<= aSource; + xLib->insertByName( aModName, aSourceAny ); + } + } + } + } +} + +void BasicManager::SetLibraryContainerInfo( LibraryContainerInfo* pInfo ) +{ + if( !pInfo ) + return; + mpImpl->mpInfo = pInfo; + + Reference< XLibraryContainer > xScriptCont; + StarBASIC* pStdLib = GetStdLib(); + String aLibName = pStdLib->GetName(); + if( mpImpl->mpInfo && (xScriptCont = mpImpl->mpInfo->mxScriptCont).is() ) + { + OUString aScriptLanguage = DEFINE_CONST_UNICODE( "StarBasic" ); + + // Register listener for lib container + OUString aEmptyLibName; + Reference< XContainerListener > xLibContainerListener + = static_cast< XContainerListener* > + ( new BasMgrContainerListenerImpl( this, aEmptyLibName ) ); + + Reference< XContainer> xLibContainer( xScriptCont, UNO_QUERY ); + xLibContainer->addContainerListener( xLibContainerListener ); + + Sequence< OUString > aNames = xScriptCont->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 i, nNameCount = aNames.getLength(); + + if( nNameCount ) + { + for( i = 0 ; i < nNameCount ; i++ ) + { + OUString aLibName2 = pNames[ i ]; + Any aLibAny = xScriptCont->getByName( aLibName2 ); + + if( String( aLibName2 ).EqualsAscii( "Standard" ) ) + xScriptCont->loadLibrary( aLibName2 ); + + BasMgrContainerListenerImpl::insertLibraryImpl + ( xScriptCont, this, aLibAny, aLibName2 ); + } + } + else + { + // No libs? Maybe an 5.2 document already loaded + USHORT nLibs = GetLibCount(); + for( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pBasLibInfo = pLibs->GetObject( nL ); + StarBASIC* pLib = pBasLibInfo->GetLib(); + if( !pLib ) + { + BOOL bLoaded = ImpLoadLibary( pBasLibInfo, NULL, FALSE ); + if( bLoaded ) + pLib = pBasLibInfo->GetLib(); + } + if( pLib ) + { + copyToLibraryContainer( pLib, mpImpl->mpInfo ); + if( pBasLibInfo->HasPassword() ) + { + OldBasicPassword* pOldBasicPassword = + mpImpl->mpInfo->mpOldBasicPassword; + if( pOldBasicPassword ) + { + pOldBasicPassword->setLibraryPassword + ( pLib->GetName(), pBasLibInfo->GetPassword() ); + pBasLibInfo->SetPasswordVerified(); + } + } + } + } + + mpImpl->mbModifiedByLibraryContainer = sal_False; + } + } +} + +BasicManager::BasicManager( StarBASIC* pSLib, String* pLibPath ) +{ + DBG_CTOR( BasicManager, 0 ); + Init(); + DBG_ASSERT( pSLib, "BasicManager kann nicht mit einem NULL-Pointer erzeugt werden!" ); + + if( pLibPath ) + pLibs->aBasicLibPath = *pLibPath; + + BasicLibInfo* pStdLibInfo = CreateLibInfo(); + pStdLibInfo->SetLib( pSLib ); + StarBASICRef xStdLib = pStdLibInfo->GetLib(); + xStdLib->SetName( String::CreateFromAscii(szStdLibName)); + pStdLibInfo->SetLibName( String::CreateFromAscii(szStdLibName) ); + pSLib->SetFlag( SBX_DONTSTORE | SBX_EXTSEARCH ); + + // Speichern lohnt sich nur, wenn sich das Basic aendert. + xStdLib->SetModified( FALSE ); + bBasMgrModified = FALSE; +} + +BasicManager::BasicManager() +{ + DBG_CTOR( BasicManager, 0 ); + // Diese CTOR darf nur verwendet werden um bei 'Speichern unter' + // die relativen Pfade anzupassen, das gibt kein AppBasic und somit + // duerfen auch keine Libs geladen werden... + Init(); +} + +BOOL BasicManager::HasBasicWithModules( const SotStorage& rStorage, const String& rBaseURL ) +{ + if( !rStorage.IsStream( ManagerStreamName ) ) + return FALSE; + + StarBASIC* pDummyParentBasic = new StarBASIC(); + BasicManager* pBasMgr = new BasicManager( (SotStorage&)rStorage, rBaseURL, pDummyParentBasic ); + BOOL bRet = FALSE; + + USHORT nLibs = pBasMgr->GetLibCount(); + for( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pBasMgr->pLibs->GetObject( nL ); + StarBASIC* pLib = pInfo->GetLib(); + if( !pLib ) + { + BOOL bLoaded = pBasMgr->ImpLoadLibary( pInfo, NULL, FALSE ); + if( bLoaded ) + pLib = pInfo->GetLib(); + } + if( pLib ) + { + SbxArray* pModules = pLib->GetModules(); + if( pModules->Count() ) + { + bRet = TRUE; + break; + } + } + } + + delete pBasMgr; + return bRet; +} + +void BasicManager::ImpMgrNotLoaded( const String& rStorageName ) +{ + // pErrInf wird nur zerstoert, wenn der Fehler von einem ErrorHandler + // gehandelt wird! +// String aErrorText( BasicResId( IDS_SBERR_MGROPEN ) ); +// aErrorText.SearchAndReplace( "XX", rStorageName ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, rStorageName, ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENMGRSTREAM, rStorageName ) ); + + // Eine STD-Lib erzeugen, sonst macht es Peng! + BasicLibInfo* pStdLibInfo = CreateLibInfo(); + pStdLibInfo->SetLib( new StarBASIC ); + StarBASICRef xStdLib = pStdLibInfo->GetLib(); + xStdLib->SetName( String::CreateFromAscii(szStdLibName) ); + pStdLibInfo->SetLibName( String::CreateFromAscii(szStdLibName) ); + xStdLib->SetFlag( SBX_DONTSTORE | SBX_EXTSEARCH ); + xStdLib->SetModified( FALSE ); +} + + +void BasicManager::ImpCreateStdLib( StarBASIC* pParentFromStdLib ) +{ + BasicLibInfo* pStdLibInfo = CreateLibInfo(); + StarBASIC* pStdLib = new StarBASIC( pParentFromStdLib ); + pStdLibInfo->SetLib( pStdLib ); + pStdLib->SetName( String::CreateFromAscii(szStdLibName) ); + pStdLibInfo->SetLibName( String::CreateFromAscii(szStdLibName) ); + pStdLib->SetFlag( SBX_DONTSTORE | SBX_EXTSEARCH ); +} + + +void BasicManager::LoadBasicManager( SotStorage& rStorage, const String& rBaseURL, BOOL bLoadLibs ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + +// StreamMode eStreamMode = STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE; + + SotStorageStreamRef xManagerStream = rStorage.OpenSotStream + ( ManagerStreamName, eStreamReadMode ); + + String aStorName( rStorage.GetName() ); + // #i13114 removed, DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + + if ( !xManagerStream.Is() || xManagerStream->GetError() || ( xManagerStream->Seek( STREAM_SEEK_TO_END ) == 0 ) ) + { + ImpMgrNotLoaded( aStorName ); + return; + } + + maStorageName = INetURLObject(aStorName, INET_PROT_FILE).GetMainURL( INetURLObject::NO_DECODE ); + // #i13114 removed, DBG_ASSERT(aStorageName.Len() != 0, "Bad storage name"); + + String aRealStorageName = maStorageName; // fuer relative Pfade, kann durch BaseURL umgebogen werden. + + // Wenn aus Vorlagen geladen wird, gilt nur die BaseURL: + //String aBaseURL = INetURLObject::GetBaseURL(); + if ( rBaseURL.Len() ) + { + INetURLObject aObj( rBaseURL ); + if ( aObj.GetProtocol() == INET_PROT_FILE ) + aRealStorageName = aObj.PathToFileName(); + } + + xManagerStream->SetBufferSize( 1024 ); + xManagerStream->Seek( STREAM_SEEK_TO_BEGIN ); + + sal_uInt32 nEndPos; + *xManagerStream >> nEndPos; + + USHORT nLibs; + *xManagerStream >> nLibs; + // Plausi! + if( nLibs & 0xF000 ) + { + DBG_ASSERT( !this, "BasicManager-Stream defekt!" ); + return; + } + for ( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = BasicLibInfo::Create( *xManagerStream ); + + // ggf. absoluten Pfad-Namen korrigieren, wenn rel. existiert + // Immer erst den relativen versuchen, falls zwei Staende auf der Platte + if ( pInfo->GetRelStorageName().Len() && ( ! pInfo->GetRelStorageName().EqualsAscii(szImbedded) ) ) + { + INetURLObject aObj( aRealStorageName, INET_PROT_FILE ); + aObj.removeSegment(); + bool bWasAbsolute = FALSE; + aObj = aObj.smartRel2Abs( pInfo->GetRelStorageName(), bWasAbsolute ); + + //*** TODO: Replace if still necessary + /* if ( SfxContentHelper::Exists( aObj.GetMainURL() ) ) + pInfo->SetStorageName( aObj.GetMainURL() ); + else */ + //*** TODO-End + if ( pLibs->aBasicLibPath.Len() ) + { + // Lib im Pfad suchen... + String aSearchFile = pInfo->GetRelStorageName(); + SvtPathOptions aPathCFG; + if( aPathCFG.SearchFile( aSearchFile, SvtPathOptions::PATH_BASIC ) ) + { + pInfo->SetStorageName( aSearchFile ); + pInfo->SetFoundInPath( TRUE ); + } + } + } + + pLibs->Insert( pInfo, LIST_APPEND ); + // Libs aus externen Dateien sollen erst bei Bedarf geladen werden. + // Aber Referenzen werden gleich geladen, sonst bekommen die Grosskunden + // vielleicht Probleme... + if ( bLoadLibs && pInfo->DoLoad() && + ( ( !pInfo->IsExtern() ) || ( pInfo->IsReference() ) ) ) + { + ImpLoadLibary( pInfo, &rStorage ); + } + } + + xManagerStream->Seek( nEndPos ); + xManagerStream->SetBufferSize( 0 ); + xManagerStream.Clear(); +} + +void BasicManager::LoadOldBasicManager( SotStorage& rStorage ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + +// StreamMode eStreamMode = STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE; + + SotStorageStreamRef xManagerStream = rStorage.OpenSotStream + ( String::CreateFromAscii(szOldManagerStream), eStreamReadMode ); + + String aStorName( rStorage.GetName() ); + DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + + if ( !xManagerStream.Is() || xManagerStream->GetError() || ( xManagerStream->Seek( STREAM_SEEK_TO_END ) == 0 ) ) + { + ImpMgrNotLoaded( aStorName ); + return; + } + + xManagerStream->SetBufferSize( 1024 ); + xManagerStream->Seek( STREAM_SEEK_TO_BEGIN ); + sal_uInt32 nBasicStartOff, nBasicEndOff; + *xManagerStream >> nBasicStartOff; + *xManagerStream >> nBasicEndOff; + + DBG_ASSERT( !xManagerStream->GetError(), "Ungueltiger Manager-Stream!" ); + + xManagerStream->Seek( nBasicStartOff ); + if( !ImplLoadBasic( *xManagerStream, pLibs->GetObject(0)->GetLibRef() ) ) + { +// String aErrorText( BasicResId( IDS_SBERR_MGROPEN ) ); +// aErrorText.SearchAndReplace( "XX", aStorName ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, aStorName, ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENMGRSTREAM, aStorName ) ); + // und es geht weiter... + } + xManagerStream->Seek( nBasicEndOff+1 ); // +1: 0x00 als Trenner + String aLibs; + xManagerStream->ReadByteString(aLibs); + xManagerStream->SetBufferSize( 0 ); + xManagerStream.Clear(); // Sream schliessen + + if ( aLibs.Len() ) + { + String aCurStorageName( aStorName ); + INetURLObject aCurStorage( aCurStorageName, INET_PROT_FILE ); + USHORT nLibs = aLibs.GetTokenCount( LIB_SEP ); + for ( USHORT nLib = 0; nLib < nLibs; nLib++ ) + { + String aLibInfo( aLibs.GetToken( nLib, LIB_SEP ) ); + // == 2 soll irgendwann weg! + DBG_ASSERT( ( aLibInfo.GetTokenCount( LIBINFO_SEP ) == 2 ) || ( aLibInfo.GetTokenCount( LIBINFO_SEP ) == 3 ), "Ungueltige Lib-Info!" ); + String aLibName( aLibInfo.GetToken( 0, LIBINFO_SEP ) ); + String aLibAbsStorageName( aLibInfo.GetToken( 1, LIBINFO_SEP ) ); + String aLibRelStorageName( aLibInfo.GetToken( 2, LIBINFO_SEP ) ); + INetURLObject aLibAbsStorage( aLibAbsStorageName, INET_PROT_FILE ); + + INetURLObject aLibRelStorage( aStorName ); + aLibRelStorage.removeSegment(); + bool bWasAbsolute = FALSE; + aLibRelStorage = aLibRelStorage.smartRel2Abs( aLibRelStorageName, bWasAbsolute); + DBG_ASSERT(!bWasAbsolute, "RelStorageName was absolute!" ); + + SotStorageRef xStorageRef; + if ( ( aLibAbsStorage == aCurStorage ) || ( aLibRelStorageName.EqualsAscii(szImbedded) ) ) + xStorageRef = &rStorage; + else + { + xStorageRef = new SotStorage( FALSE, aLibAbsStorage.GetMainURL + ( INetURLObject::NO_DECODE ), eStorageReadMode, TRUE ); + if ( xStorageRef->GetError() != ERRCODE_NONE ) + xStorageRef = new SotStorage( FALSE, aLibRelStorage. + GetMainURL( INetURLObject::NO_DECODE ), eStorageReadMode, TRUE ); + } + if ( xStorageRef.Is() ) + AddLib( *xStorageRef, aLibName, FALSE ); + else + { +// String aErrorText( BasicResId( IDS_SBERR_LIBLOAD ) ); +// aErrorText.SearchAndReplace( "XX", aLibName ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD, aStorName, ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_STORAGENOTFOUND, aStorName ) ); + } + } + } +} + +BasicManager::~BasicManager() +{ + DBG_DTOR( BasicManager, 0 ); + + // Listener benachrichtigen, falls noch etwas zu Speichern... + Broadcast( SfxSimpleHint( SFX_HINT_DYING) ); + + // Basic-Infos zerstoeren... + // In umgekehrter Reihenfolge, weil die StdLib Referenzen haelt, die + // anderen nur die StdLib als Parent haben. + BasicLibInfo* pInf = pLibs->Last(); + while ( pInf ) + { + delete pInf; + pInf = pLibs->Prev(); + } + pLibs->Clear(); + delete pLibs; + delete pErrorMgr; + delete mpImpl; +} + +void BasicManager::LegacyDeleteBasicManager( BasicManager*& _rpManager ) +{ + delete _rpManager; + _rpManager = NULL; +} + +void BasicManager::Init() +{ + DBG_CHKTHIS( BasicManager, 0 ); + + bBasMgrModified = FALSE; + pErrorMgr = new BasicErrorManager; + pLibs = new BasicLibs; + mpImpl = new BasicManagerImpl(); +} + +BasicLibInfo* BasicManager::CreateLibInfo() +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pInf = new BasicLibInfo; + pLibs->Insert( pInf, LIST_APPEND ); + return pInf; +} + +BOOL BasicManager::CopyBasicData( SotStorage* pStorFrom, const String& rSourceURL, const String& rBaseURL, SotStorage* pStorTo ) +{ + /*----------------------------------------------------------------- + Diese Methode wird vom SXF gerufen bei 'Datei speichern unter', + damit die Basic-Storages kopiert werden. + Neu: ggf. muessen relative Pfade angepasst werden! + ------------------------------------------------------------------*/ + BOOL bOk = TRUE; + + // bei remote Dokumenten identische Storage + if ( pStorFrom != pStorTo ) + { + if( pStorFrom->IsStorage( BasicStreamName ) ) + bOk = pStorFrom->CopyTo( BasicStreamName, pStorTo, BasicStreamName ); + if( bOk && pStorFrom->IsStream( ManagerStreamName ) ) + { + // bOk = pStorFrom->CopyTo( szManagerStream, pStorTo, szManagerStream ); + BasicManager aBasMgr; + // Die aktuelle Base-URL ist die vom speichern... + String aStorName( pStorFrom->GetName() ); + DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + + aBasMgr.LoadBasicManager( *pStorFrom, rSourceURL, FALSE ); + aBasMgr.Store( *pStorTo, rBaseURL, FALSE ); + } + } + + return bOk; +} + +void BasicManager::Store( SotStorage& rStorage, const String& rBaseURL ) +{ + Store( rStorage, rBaseURL, TRUE ); +} + +void BasicManager::Store( SotStorage& rStorage, const String& rBaseURL, BOOL bStoreLibs ) +{ + // #91626 + sal_Bool bModified = mpImpl->mbModifiedByLibraryContainer || mpImpl->mbError; + + // #92172 Password handling + OldBasicPassword* pOldBasicPassword = NULL; + USHORT nLibs = GetLibCount(); + if( mpImpl->mpInfo ) + pOldBasicPassword = mpImpl->mpInfo->mpOldBasicPassword; + if( pOldBasicPassword ) + { + Reference< XLibraryContainer > xScriptCont = mpImpl->mpInfo->mxScriptCont; + for( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pLibs->GetObject( nL ); + DBG_ASSERT( pInfo, "pInfo?!" ); + + String aLibName = pInfo->GetLibName(); + sal_Bool bPassword = pOldBasicPassword->hasLibraryPassword( aLibName ); + String aPassword = pOldBasicPassword->getLibraryPassword( aLibName ); + if( pInfo->GetPassword() != aPassword ) + bModified = sal_True; + + if( xScriptCont.is() && xScriptCont->hasByName( aLibName ) ) + xScriptCont->loadLibrary( aLibName ); + + if( bPassword && aPassword.Len() == 0 ) + { + String aDummySource( String::CreateFromAscii( + "REM This module belonged to a password protected library that was exported without\n" + "REM verifying the password. So the original module source could not be exported!\n" + "sub main\n" + "end sub\n" ) ); + Any aDummySourceAny; + aDummySourceAny <<= OUString( aDummySource ); + + if( xScriptCont.is() && xScriptCont->hasByName( aLibName ) ) + { + // Now the library isn't password protected any more + // but the modules don't contain any source + pOldBasicPassword->clearLibraryPassword( aLibName ); + + Any aLibAny = xScriptCont->getByName( aLibName ); + Reference< XNameContainer > xLib; + aLibAny >>= xLib; + + Sequence< OUString > aNames = xLib->getElementNames(); + sal_Int32 nNameCount = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + xLib->replaceByName( aElementName, aDummySourceAny ); + } + } + + StarBASIC* pBasic = GetLib( aLibName ); + if( pBasic ) + { + SbxArray* pModules = pBasic->GetModules(); + USHORT nModCount = pModules->Count(); + for( USHORT j = 0; j < nModCount ; j++ ) + { + SbModule* pMod = (SbModule*)pModules->Get( j ); + pMod->SetSource32( aDummySource ); + pMod->Compile(); + } + } + + bModified = sal_True; + } + else + { + if( pInfo->GetPassword().Len() != 0 ) + bModified = sal_True; + pInfo->SetPassword( aPassword ); + } + } + } + + // #91626 + if( !bModified && bStoreLibs && mpImpl->mpManagerStream ) + { + // Store saved streams + SotStorageStreamRef xManagerStream = rStorage.OpenSotStream( + ManagerStreamName, STREAM_STD_READWRITE | STREAM_TRUNC ); + //ManagerStreamName, STREAM_STD_READWRITE /* | STREAM_TRUNC */ ); + // STREAM_TRUNC buggy??!!! Then + // xManagerStream->Seek( 0 ); + mpImpl->mpManagerStream->Seek( 0 ); + *static_cast<SvStream*>(&xManagerStream) << *mpImpl->mpManagerStream; + + SotStorageRef xBasicStorage = rStorage.OpenSotStorage + ( BasicStreamName, STREAM_STD_READWRITE, FALSE ); + + if ( xBasicStorage.Is() && !xBasicStorage->GetError() ) + { + for( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pLibs->GetObject( nL ); + DBG_ASSERT( pInfo, "pInfo?!" ); + SotStorageStreamRef xBasicStream = xBasicStorage->OpenSotStream( pInfo->GetLibName(), STREAM_STD_READWRITE ); + mpImpl->mppLibStreams[nL]->Seek( 0 ); + *static_cast<SvStream*>(&xBasicStream) << *( mpImpl->mppLibStreams[nL] ); + } + + xBasicStorage->Commit(); + } + return; + } + + + DBG_CHKTHIS( BasicManager, 0 ); + // Neue Bibliotheken sind nicht unbedingt modified, muessen aber trotzdem + // gespeichert werden. + BOOL bStoreAll = FALSE; + if ( bStoreLibs && !rStorage.IsStorage( BasicStreamName ) ) + bStoreAll = TRUE; + + SotStorageStreamRef xManagerStream = rStorage.OpenSotStream( ManagerStreamName, STREAM_STD_READWRITE /* | STREAM_TRUNC */ ); + // Assertion, weil es eigentlich nie vorkommen darf. + DBG_ASSERT( xManagerStream.Is(), "Kein ManagerStream!"); + + ClearErrors(); + + String aStorName( rStorage.GetName() ); + DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + + if ( !xManagerStream.Is() || xManagerStream->GetError() ) + { +// String aErrorText( BasicResId( IDS_SBERR_MGRSAVE ) ); +// aErrorText.SearchAndReplace( "XX", aStorName ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGRSAVE, aStorName, ERRCODE_BUTTON_OK ); + ((BasicManager*)this)->pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENMGRSTREAM, aStorName ) ); + } + else + { + maStorageName = aStorName; + + // Funktioniert nicht, auber auch OPEN_TRUNC nicht (UAE in OLE32) + // => Erst mal den alten Schrott stehen lassen! +// xManagerStream->SetSize( 0 ); + xManagerStream->SetBufferSize( 1024 ); + xManagerStream->Seek( 0 ); + + ULONG nStartPos = 0; + sal_uInt32 nEndPos = 0; + *xManagerStream << nEndPos; + + // Fehlerabfrage, falls schreiben nicht moeglich ? + DBG_ASSERT( !xManagerStream->GetError(), "Unerwarteter Fehler beim Schreiben des Manager-Streams" ); + + + // Die Namen der Libs und der Storages... +// DirEntry aCurStorage( aStorName() ); +// aCurStorage.ToAbs(); + String aLibInfo; + *xManagerStream << nLibs; + for ( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pLibs->GetObject( nL ); + DBG_ASSERT( pInfo, "pInfo?!" ); + + String aStrgName = GetStorageName(); + + // Falls ins Temp-Verzeichniss gesichert wird, sollte der richtige + // Storage-Name an der globalen URL haengen... + //String aBaseURL = INetURLObject::GetBaseURL(); + if ( rBaseURL.Len() ) + { + INetURLObject aObj( rBaseURL ); + if ( aObj.GetProtocol() == INET_PROT_FILE ) + aStrgName = aObj.PathToFileName(); + } + + pInfo->Store( *xManagerStream, aStrgName, !bStoreLibs ); + } + + nEndPos = xManagerStream->Tell(); + xManagerStream->Seek( nStartPos ); + *xManagerStream << nEndPos; + xManagerStream->Seek( nEndPos ); + xManagerStream->SetBufferSize( 0 ); + xManagerStream.Clear(); + } + + // Und dann die Libs in den entsprechenden Storages... + if ( bStoreLibs ) + { + String aCurStorage( aStorName ); + for ( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pLibs->GetObject( nL ); + DBG_ASSERT( pInfo, "Info?!" ); + StarBASIC* pLib = pInfo->GetLib(); + if ( pLib && ( pLib->IsModified() || bStoreAll ) ) // 0, wenn nicht geladen... + { + if ( pInfo->IsReference() ) + { + // Vielleicht nicht modified, aber bStoreAll. + // Fehlermeldung nicht, wenn Macro lauft + // (also speichern durch Macro) + if ( pLib->IsModified() && !StarBASIC::IsRunning() ) + { + String sTemp( String::CreateFromAscii( "Reference will not be saved: " ) ); + sTemp += pLib->GetName(); + WarningBox( NULL, WB_OK, sTemp ).Execute(); + // Einmal meckern reicht. + pLib->SetModified( FALSE ); + } + } + else + { + SotStorageRef xStorage; + if ( ( pInfo->GetStorageName() != aCurStorage ) && ( !pInfo->GetStorageName().EqualsAscii(szImbedded) ) ) + xStorage = new SotStorage( FALSE, pInfo->GetStorageName() ); + else + xStorage = &rStorage; + ImpStoreLibary( pLib, *xStorage ); + } + } + } + } + + if ( !HasErrors() ) + bBasMgrModified = FALSE; +} + + +BOOL BasicManager::ImpStoreLibary( StarBASIC* pLib, SotStorage& rStorage ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + DBG_ASSERT( pLib, "pLib = 0 (ImpStorageLibary)" ); + + SotStorageRef xBasicStorage = rStorage.OpenSotStorage + ( BasicStreamName, STREAM_STD_READWRITE, FALSE ); + + String aStorName( rStorage.GetName() ); + DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + if ( !xBasicStorage.Is() || xBasicStorage->GetError() ) + { +// String aErrorText( BasicResId( IDS_SBERR_MGRSAVE ) ); +// aErrorText.SearchAndReplace( "XX", aStorName ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGRSAVE, aStorName, ERRCODE_BUTTON_OK ); + ((BasicManager*)this)->pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENLIBSTORAGE, pLib->GetName() ) ); + } + else + { + // In dem Basic-Storage liegt jede Lib in einem Stream... + SotStorageStreamRef xBasicStream = xBasicStorage->OpenSotStream( pLib->GetName(), STREAM_STD_READWRITE ); + if ( !xBasicStream.Is() || xBasicStream->GetError() ) + { +// String aErrorText( BasicResId( IDS_SBERR_LIBSAVE ) ); +// aErrorText.SearchAndReplace( "XX", pLib->GetName() ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBSAVE, pLib->GetName(), ERRCODE_BUTTON_OK ); + ((BasicManager*)this)->pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENLIBSTREAM, pLib->GetName() ) ); + } + else + { + BasicLibInfo* pLibInfo = FindLibInfo( pLib ); + DBG_ASSERT( pLibInfo, "ImpStoreLibary: LibInfo?!" ); + + xBasicStream->SetSize( 0 ); + xBasicStream->SetBufferSize( 1024 ); + + // SBX_DONTSTORE, damit Child-Basics nicht gespeichert werden + SetFlagToAllLibs( SBX_DONTSTORE, TRUE ); + // Aber das hier will ich jetzt speichern: + pLib->ResetFlag( SBX_DONTSTORE ); + if ( pLibInfo->HasPassword() ) + xBasicStream->SetKey( szCryptingKey ); + BOOL bDone = pLib->Store( *xBasicStream ); + xBasicStream->SetBufferSize( 0 ); + if ( bDone ) + { + // Diese Informationen immer verschluesseln... + xBasicStream->SetBufferSize( 1024 ); + xBasicStream->SetKey( szCryptingKey ); + *xBasicStream << static_cast<sal_uInt32>(PASSWORD_MARKER); + String aTmpPassword = pLibInfo->GetPassword(); + xBasicStream->WriteByteString( aTmpPassword, RTL_TEXTENCODING_MS_1252 ); + xBasicStream->SetBufferSize( 0 ); + } + // Vorsichtshalber alle Dont't Store lassen... + pLib->SetFlag( SBX_DONTSTORE ); +// SetFlagToAllLibs( SBX_DONTSTORE, FALSE ); + pLib->SetModified( FALSE ); + if( !xBasicStorage->Commit() ) + bDone = FALSE; + xBasicStream->SetKey( ByteString() ); + DBG_ASSERT( bDone, "Warum geht Basic::Store() nicht ?" ); + return bDone; + } + } + return FALSE; +} + +BOOL BasicManager::ImpLoadLibary( BasicLibInfo* pLibInfo, SotStorage* pCurStorage, BOOL bInfosOnly ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + DBG_ASSERT( pLibInfo, "LibInfo!?" ); + + String aStorageName( pLibInfo->GetStorageName() ); + if ( !aStorageName.Len() || ( aStorageName.EqualsAscii(szImbedded) ) ) + aStorageName = GetStorageName(); + + SotStorageRef xStorage; + // Der aktuelle darf nicht nochmal geoffnet werden... + if ( pCurStorage ) + { + String aStorName( pCurStorage->GetName() ); + // #i13114 removed, DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + + INetURLObject aCurStorageEntry(aStorName, INET_PROT_FILE); + // #i13114 removed, DBG_ASSERT(aCurStorageEntry.GetMainURL( INetURLObject::NO_DECODE ).Len() != 0, "Bad storage name"); + + INetURLObject aStorageEntry(aStorageName, INET_PROT_FILE); + // #i13114 removed, DBG_ASSERT(aCurStorageEntry.GetMainURL( INetURLObject::NO_DECODE ).Len() != 0, "Bad storage name"); + + if ( aCurStorageEntry == aStorageEntry ) + xStorage = pCurStorage; + } + + if ( !xStorage.Is() ) + xStorage = new SotStorage( FALSE, aStorageName, eStorageReadMode ); + + SotStorageRef xBasicStorage = xStorage->OpenSotStorage + ( BasicStreamName, eStorageReadMode, FALSE ); + + if ( !xBasicStorage.Is() || xBasicStorage->GetError() ) + { + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, xStorage->GetName(), ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENLIBSTORAGE, pLibInfo->GetLibName() ) ); + } + else + { + // In dem Basic-Storage liegt jede Lib in einem Stream... + SotStorageStreamRef xBasicStream = xBasicStorage->OpenSotStream( pLibInfo->GetLibName(), eStreamReadMode ); + if ( !xBasicStream.Is() || xBasicStream->GetError() ) + { + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD , pLibInfo->GetLibName(), ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENLIBSTREAM, pLibInfo->GetLibName() ) ); + } + else + { + BOOL bLoaded = FALSE; + if ( xBasicStream->Seek( STREAM_SEEK_TO_END ) != 0 ) + { + if ( !bInfosOnly ) + { + if ( !pLibInfo->GetLib().Is() ) + pLibInfo->SetLib( new StarBASIC( GetStdLib() ) ); + xBasicStream->SetBufferSize( 1024 ); + xBasicStream->Seek( STREAM_SEEK_TO_BEGIN ); + bLoaded = ImplLoadBasic( *xBasicStream, pLibInfo->GetLibRef() ); + xBasicStream->SetBufferSize( 0 ); + StarBASICRef xStdLib = pLibInfo->GetLib(); + xStdLib->SetName( pLibInfo->GetLibName() ); + xStdLib->SetModified( FALSE ); + xStdLib->SetFlag( SBX_DONTSTORE ); + } + else + { + // Das Basic skippen... + xBasicStream->Seek( STREAM_SEEK_TO_BEGIN ); + ImplEncryptStream( *xBasicStream ); + SbxBase::Skip( *xBasicStream ); + bLoaded = TRUE; + } + } + if ( !bLoaded ) + { + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD, pLibInfo->GetLibName(), ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_BASICLOADERROR, pLibInfo->GetLibName() ) ); + } + else + { + // Ggf. stehen weitere Informationen im Stream... + xBasicStream->SetKey( szCryptingKey ); + xBasicStream->RefreshBuffer(); + sal_uInt32 nPasswordMarker = 0; + *xBasicStream >> nPasswordMarker; + if ( ( nPasswordMarker == PASSWORD_MARKER ) && !xBasicStream->IsEof() ) + { + String aPassword; + xBasicStream->ReadByteString(aPassword); + pLibInfo->SetPassword( aPassword ); + } + xBasicStream->SetKey( ByteString() ); + CheckModules( pLibInfo->GetLib(), pLibInfo->IsReference() ); + } +// bBasMgrModified = TRUE; // Warum? + return bLoaded; + } + } + return FALSE; +} + +BOOL BasicManager::ImplEncryptStream( SvStream& rStrm ) const +{ + ULONG nPos = rStrm.Tell(); + UINT32 nCreator; + rStrm >> nCreator; + rStrm.Seek( nPos ); + BOOL bProtected = FALSE; + if ( nCreator != SBXCR_SBX ) + { + // sollte nur bei verschluesselten Streams nicht stimmen. + bProtected = TRUE; + rStrm.SetKey( szCryptingKey ); + rStrm.RefreshBuffer(); + } + return bProtected; +} + + +// Dieser Code ist notwendig, um das BASIC der Beta 1 laden zu koennen +BOOL BasicManager::ImplLoadBasic( SvStream& rStrm, StarBASICRef& rOldBasic ) const +{ + BOOL bProtected = ImplEncryptStream( rStrm ); + SbxBaseRef xNew = SbxBase::Load( rStrm ); + BOOL bLoaded = FALSE; + if( xNew.Is() ) + { + if( xNew->IsA( TYPE(StarBASIC) ) ) + { + StarBASIC* pNew = (StarBASIC*)(SbxBase*) xNew; + // Den Parent des alten BASICs uebernehmen + if( rOldBasic.Is() ) + { + pNew->SetParent( rOldBasic->GetParent() ); + if( pNew->GetParent() ) + pNew->GetParent()->Insert( pNew ); + pNew->SetFlag( SBX_EXTSEARCH ); + } + rOldBasic = pNew; + + // Fill new libray container (5.2 -> 6.0) + copyToLibraryContainer( pNew, mpImpl->mpInfo ); + +/* + if( rOldBasic->GetParent() ) + { + rOldBasic->GetParent()->Insert( rOldBasic ); + rOldBasic->SetFlag( SBX_EXTSEARCH ); + } +*/ + pNew->SetModified( FALSE ); + bLoaded = TRUE; + } + } + if ( bProtected ) + rStrm.SetKey( ByteString() ); + return bLoaded; +} + +void BasicManager::CheckModules( StarBASIC* pLib, BOOL bReference ) const +{ + if ( !pLib ) + return; + + BOOL bModified = pLib->IsModified(); + +/*?*/ // for ( USHORT nMod = 0; nMod < pLib->GetModules()->Count(); nMod++ ) +/*?*/ // { +/*?*/ // SbModule* pModule = (SbModule*)pLib->GetModules()->Get( nMod ); +/*?*/ // DBG_ASSERT( pModule, "Modul nicht erhalten!" ); +/*?*/ // if ( !pModule->IsCompiled() && !StarBASIC::GetErrorCode() ) +/*?*/ // pLib->Compile( pModule ); +/*?*/ // } + + // #67477, AB 8.12.99 On demand Compilieren bei referenzierten + // Libraries sollte nicht zu modified fuehren + if( !bModified && bReference ) + { + DBG_ERROR( "Per Reference eingebundene Basic-Library ist nicht compiliert!" ); + pLib->SetModified( FALSE ); + } +} + + +StarBASIC* BasicManager::AddLib( SotStorage& rStorage, const String& rLibName, BOOL bReference ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + + String aStorName( rStorage.GetName() ); + DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); + + String aStorageName = INetURLObject(aStorName, INET_PROT_FILE).GetMainURL( INetURLObject::NO_DECODE ); + DBG_ASSERT(aStorageName.Len() != 0, "Bad storage name"); + + String aNewLibName( rLibName ); + while ( HasLib( aNewLibName ) ) + aNewLibName += '_'; + + BasicLibInfo* pLibInfo = CreateLibInfo(); + // Erstmal mit dem Original-Namen, da sonst ImpLoadLibary nicht geht... + pLibInfo->SetLibName( rLibName ); + // Funktioniert so aber nicht, wenn Name doppelt +// USHORT nLibId = GetLibId( rLibName ); + USHORT nLibId = (USHORT) pLibs->GetPos( pLibInfo ); + + // Vorm Laden StorageNamen setzen, da er mit pCurStorage verglichen wird. + pLibInfo->SetStorageName( aStorageName ); + BOOL bLoaded = ImpLoadLibary( pLibInfo, &rStorage ); + + if ( bLoaded ) + { + if ( aNewLibName != rLibName ) + SetLibName( nLibId, aNewLibName ); + + if ( bReference ) + { + pLibInfo->GetLib()->SetModified( FALSE ); // Dann nicht speichern + pLibInfo->SetRelStorageName( String() ); +// pLibInfo->CalcRelStorageName( GetStorageName() ); + pLibInfo->IsReference() = TRUE; + } + else + { + pLibInfo->GetLib()->SetModified( TRUE ); // Muss nach Add gespeichert werden! + pLibInfo->SetStorageName( String::CreateFromAscii(szImbedded) ); // Im BasicManager-Storage speichern + } + bBasMgrModified = TRUE; + } + else + { + RemoveLib( nLibId, FALSE ); + pLibInfo = 0; + } + + if( pLibInfo ) + return &*pLibInfo->GetLib() ; + else + return 0; +} +BOOL BasicManager::IsReference( USHORT nLib ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pLibInfo = pLibs->GetObject( nLib ); + DBG_ASSERT( pLibInfo, "Lib?!" ); + if ( pLibInfo ) + return pLibInfo->IsReference(); + + return FALSE; +} + +BOOL BasicManager::RemoveLib( USHORT nLib ) +{ + // Nur physikalisch loeschen, wenn keine Referenz. + return RemoveLib( nLib, !IsReference( nLib ) ); +} + +BOOL BasicManager::RemoveLib( USHORT nLib, BOOL bDelBasicFromStorage ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + DBG_ASSERT( nLib, "Standard-Lib kann nicht entfernt werden!" ); + + BasicLibInfo* pLibInfo = pLibs->GetObject( nLib ); + DBG_ASSERT( pLibInfo, "Lib nicht gefunden!" ); + + if ( !pLibInfo || !nLib ) + { +// String aErrorText( BasicResId( IDS_SBERR_REMOVELIB ) ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_REMOVELIB, String(), ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_STDLIB, pLibInfo->GetLibName() ) ); + return FALSE; + } + + // Wenn einer der Streams nicht geoeffnet werden kann, ist es kein + // Fehler, es gibt halt noch nichts zum loeschen, weil das Basic noch + // nie geschrieben wurde... + if ( bDelBasicFromStorage && !pLibInfo->IsReference() && + ( !pLibInfo->IsExtern() || SotStorage::IsStorageFile( pLibInfo->GetStorageName() ) ) ) + { + SotStorageRef xStorage; + if ( !pLibInfo->IsExtern() ) + xStorage = new SotStorage( FALSE, GetStorageName() ); + else + xStorage = new SotStorage( FALSE, pLibInfo->GetStorageName() ); + + if ( xStorage->IsStorage( BasicStreamName ) ) + { + SotStorageRef xBasicStorage = xStorage->OpenSotStorage + ( BasicStreamName, STREAM_STD_READWRITE, FALSE ); + + if ( !xBasicStorage.Is() || xBasicStorage->GetError() ) + { +// String aErrorText( BasicResId( IDS_SBERR_REMOVELIB ) ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_REMOVELIB, String(), ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENLIBSTORAGE, pLibInfo->GetLibName() ) ); + } + else if ( xBasicStorage->IsStream( pLibInfo->GetLibName() ) ) + { + xBasicStorage->Remove( pLibInfo->GetLibName() ); + xBasicStorage->Commit(); + + // Wenn kein weiterer Stream vorhanden, + // dann auch den SubStorage loeschen. + SvStorageInfoList aInfoList( 0, 4 ); + xBasicStorage->FillInfoList( &aInfoList ); + if ( !aInfoList.Count() ) + { + xBasicStorage.Clear(); + xStorage->Remove( BasicStreamName ); + xStorage->Commit(); + // Wenn kein weiterer Streams oder SubStorages vorhanden, + // dann auch den Storage loeschen. + aInfoList.Clear(); + xStorage->FillInfoList( &aInfoList ); + if ( !aInfoList.Count() ) + { + String aName_( xStorage->GetName() ); + xStorage.Clear(); + //*** TODO: Replace if still necessary + //SfxContentHelper::Kill( aName ); + //*** TODO-End + } + } + } + } + } + bBasMgrModified = TRUE; + if ( pLibInfo->GetLib().Is() ) + GetStdLib()->Remove( pLibInfo->GetLib() ); + delete pLibs->Remove( pLibInfo ); + return TRUE; // Remove hat geklappt, Del unwichtig. +} + +USHORT BasicManager::GetLibCount() const +{ + DBG_CHKTHIS( BasicManager, 0 ); + return (USHORT)pLibs->Count(); +} + +StarBASIC* BasicManager::GetLib( USHORT nLib ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + BasicLibInfo* pInf = pLibs->GetObject( nLib ); + DBG_ASSERT( pInf, "Lib existiert nicht!" ); + if ( pInf ) + return pInf->GetLib(); + return 0; +} + +StarBASIC* BasicManager::GetStdLib() const +{ + DBG_CHKTHIS( BasicManager, 0 ); + StarBASIC* pLib = GetLib( 0 ); + return pLib; +} + +StarBASIC* BasicManager::GetLib( const String& rName ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pInf = pLibs->First(); + while ( pInf ) + { + if ( pInf->GetLibName().CompareIgnoreCaseToAscii( rName ) == COMPARE_EQUAL ) // prueffen, ob vorhanden... + return pInf->GetLib(); + + pInf = pLibs->Next(); + } + return 0; +} + +USHORT BasicManager::GetLibId( const String& rName ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pInf = pLibs->First(); + while ( pInf ) + { + if ( pInf->GetLibName().CompareIgnoreCaseToAscii( rName ) == COMPARE_EQUAL ) + return (USHORT)pLibs->GetCurPos(); + + pInf = pLibs->Next(); + } + return LIB_NOTFOUND; +} + +BOOL BasicManager::HasLib( const String& rName ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pInf = pLibs->First(); + while ( pInf ) + { + if ( pInf->GetLibName().CompareIgnoreCaseToAscii( rName ) == COMPARE_EQUAL ) + return TRUE; + + pInf = pLibs->Next(); + } + return FALSE; +} + +BOOL BasicManager::SetLibName( USHORT nLib, const String& rName ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pLibInfo = pLibs->GetObject( nLib ); + DBG_ASSERT( pLibInfo, "Lib?!" ); + if ( pLibInfo ) + { + pLibInfo->SetLibName( rName ); + if ( pLibInfo->GetLib().Is() ) + { + StarBASICRef xStdLib = pLibInfo->GetLib(); + xStdLib->SetName( rName ); + xStdLib->SetModified( TRUE ); + } + bBasMgrModified = TRUE; + return TRUE; + } + return FALSE; +} + +String BasicManager::GetLibName( USHORT nLib ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pLibInfo = pLibs->GetObject( nLib ); + DBG_ASSERT( pLibInfo, "Lib?!" ); + if ( pLibInfo ) + return pLibInfo->GetLibName(); + return String(); +} + +StarBASIC* BasicManager::CreateLib( const String& rLibName ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + if ( GetLib( rLibName ) ) + return 0; + + BasicLibInfo* pLibInfo = CreateLibInfo(); + StarBASIC* pNew = new StarBASIC( GetStdLib() ); + GetStdLib()->Insert( pNew ); + pNew->SetFlag( SBX_EXTSEARCH | SBX_DONTSTORE ); + pLibInfo->SetLib( pNew ); + pLibInfo->SetLibName( rLibName ); + pLibInfo->GetLib()->SetName( rLibName ); + return pLibInfo->GetLib(); +} + +// For XML import/export: +StarBASIC* BasicManager::CreateLib + ( const String& rLibName, const String& Password, const String& LinkTargetURL ) +{ + // Ask if lib exists because standard lib is always there + StarBASIC* pLib = GetLib( rLibName ); + if( !pLib ) + { + if( LinkTargetURL.Len() != 0 ) + { + SotStorageRef xStorage = new SotStorage( FALSE, LinkTargetURL, STREAM_READ | STREAM_SHARE_DENYWRITE ); + if( !xStorage->GetError() ) + { + pLib = AddLib( *xStorage, rLibName, TRUE ); + + //if( !pLibInfo ) + //pLibInfo = FindLibInfo( pLib ); + //pLibInfo->SetStorageName( LinkTargetURL ); + //pLibInfo->GetLib()->SetModified( FALSE ); // Dann nicht speichern + //pLibInfo->SetRelStorageName( String() ); + //pLibInfo->IsReference() = TRUE; + } + //else + //Message? + + DBG_ASSERT( pLib, "XML Import: Linked basic library could not be loaded"); + } + else + { + pLib = CreateLib( rLibName ); + if( Password.Len() != 0 ) + { + BasicLibInfo* pLibInfo = FindLibInfo( pLib ); + pLibInfo ->SetPassword( Password ); + } + } + //ExternalSourceURL ? + } + return pLib; +} + +StarBASIC* BasicManager::CreateLibForLibContainer( const String& rLibName, + const Reference< XLibraryContainer >& xScriptCont ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + if ( GetLib( rLibName ) ) + return 0; + + BasicLibInfo* pLibInfo = CreateLibInfo(); + StarBASIC* pNew = new StarBASIC( GetStdLib() ); + GetStdLib()->Insert( pNew ); + pNew->SetFlag( SBX_EXTSEARCH | SBX_DONTSTORE ); + pLibInfo->SetLib( pNew ); + pLibInfo->SetLibName( rLibName ); + pLibInfo->GetLib()->SetName( rLibName ); + pLibInfo->SetLibraryContainer( xScriptCont ); + return pNew; +} + + +BasicLibInfo* BasicManager::FindLibInfo( StarBASIC* pBasic ) const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pInf = ((BasicManager*)this)->pLibs->First(); + while ( pInf ) + { + if ( pInf->GetLib() == pBasic ) + return pInf; + + pInf = ((BasicManager*)this)->pLibs->Next(); + } + return 0; +} + +void BasicManager::SetFlagToAllLibs( short nFlag, BOOL bSet ) const +{ + USHORT nLibs = GetLibCount(); + for ( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = pLibs->GetObject( nL ); + DBG_ASSERT( pInfo, "Info?!" ); + StarBASIC* pLib = pInfo->GetLib(); + if ( pLib ) + { + if ( bSet ) + pLib->SetFlag( nFlag ); + else + pLib->ResetFlag( nFlag ); + } + } +} + +BOOL BasicManager::HasErrors() +{ + DBG_CHKTHIS( BasicManager, 0 ); + return pErrorMgr->HasErrors(); +} + +void BasicManager::ClearErrors() +{ + DBG_CHKTHIS( BasicManager, 0 ); + pErrorMgr->Reset(); +} + +//===================================================================== + +class ModuleInfo_Impl : public ModuleInfoHelper +{ + OUString maName; + OUString maLanguage; + OUString maSource; + +public: + ModuleInfo_Impl( const OUString& aName, const OUString& aLanguage, const OUString& aSource ) + : maName( aName ), maLanguage( aLanguage), maSource( aSource ) {} + + // Methods XStarBasicModuleInfo + virtual OUString SAL_CALL getName() throw(RuntimeException) + { return maName; } + virtual OUString SAL_CALL getLanguage() throw(RuntimeException) + { return maLanguage; } + virtual OUString SAL_CALL getSource() throw(RuntimeException) + { return maSource; } +}; + + +//===================================================================== + +class DialogInfo_Impl : public DialogInfoHelper +{ + OUString maName; + Sequence< sal_Int8 > mData; + +public: + DialogInfo_Impl( const OUString& aName, Sequence< sal_Int8 > Data ) + : maName( aName ), mData( Data ) {} + + // Methods XStarBasicDialogInfo + virtual OUString SAL_CALL getName() throw(RuntimeException) + { return maName; } + virtual Sequence< sal_Int8 > SAL_CALL getData() throw(RuntimeException) + { return mData; } +}; + + +//===================================================================== + +class LibraryInfo_Impl : public LibraryInfoHelper +{ + OUString maName; + Reference< XNameContainer > mxModuleContainer; + Reference< XNameContainer > mxDialogContainer; + OUString maPassword; + OUString maExternaleSourceURL; + OUString maLinkTargetURL; + +public: + LibraryInfo_Impl + ( + const OUString& aName, + Reference< XNameContainer > xModuleContainer, + Reference< XNameContainer > xDialogContainer, + const OUString& aPassword, + const OUString& aExternaleSourceURL, + const OUString& aLinkTargetURL + ) + : maName( aName ) + , mxModuleContainer( xModuleContainer ) + , mxDialogContainer( xDialogContainer ) + , maPassword( aPassword ) + , maExternaleSourceURL( aExternaleSourceURL ) + , maLinkTargetURL( aLinkTargetURL ) + {} + + // Methods XStarBasicLibraryInfo + virtual OUString SAL_CALL getName() throw(RuntimeException) + { return maName; } + virtual Reference< XNameContainer > SAL_CALL getModuleContainer() throw(RuntimeException) + { return mxModuleContainer; } + virtual Reference< XNameContainer > SAL_CALL getDialogContainer() throw(RuntimeException) + { return mxDialogContainer; } + virtual OUString SAL_CALL getPassword() throw(RuntimeException) + { return maPassword; } + virtual OUString SAL_CALL getExternalSourceURL() throw(RuntimeException) + { return maExternaleSourceURL; } + virtual OUString SAL_CALL getLinkTargetURL() throw(RuntimeException) + { return maLinkTargetURL; } +}; + +//===================================================================== + +class ModuleContainer_Impl : public NameContainerHelper +{ + StarBASIC* mpLib; + +public: + ModuleContainer_Impl( StarBASIC* pLib ) + :mpLib( pLib ) {} + + // Methods XElementAccess + virtual Type SAL_CALL getElementType() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasElements() + throw(RuntimeException); + + // Methods XNameAccess + virtual Any SAL_CALL getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getElementNames() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) + throw(RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); +}; + +// Methods XElementAccess +Type ModuleContainer_Impl::getElementType() + throw(RuntimeException) +{ + Type aModuleType = ::getCppuType( (const Reference< XStarBasicModuleInfo > *)0 ); + return aModuleType; +} + +sal_Bool ModuleContainer_Impl::hasElements() + throw(RuntimeException) +{ + SbxArray* pMods = mpLib ? mpLib->GetModules() : NULL; + return pMods && pMods->Count() > 0; +} + +// Methods XNameAccess +Any ModuleContainer_Impl::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + SbModule* pMod = mpLib ? mpLib->FindModule( aName ) : NULL; + if( !pMod ) + throw NoSuchElementException(); + Reference< XStarBasicModuleInfo > xMod = (XStarBasicModuleInfo*)new ModuleInfo_Impl + ( aName, OUString::createFromAscii( "StarBasic" ), pMod->GetSource32() ); + Any aRetAny; + aRetAny <<= xMod; + return aRetAny; +} + +Sequence< OUString > ModuleContainer_Impl::getElementNames() + throw(RuntimeException) +{ + SbxArray* pMods = mpLib ? mpLib->GetModules() : NULL; + USHORT nMods = pMods ? pMods->Count() : 0; + Sequence< OUString > aRetSeq( nMods ); + OUString* pRetSeq = aRetSeq.getArray(); + for( USHORT i = 0 ; i < nMods ; i++ ) + { + SbxVariable* pMod = pMods->Get( i ); + pRetSeq[i] = OUString( pMod->GetName() ); + } + return aRetSeq; +} + +sal_Bool ModuleContainer_Impl::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + SbModule* pMod = mpLib ? mpLib->FindModule( aName ) : NULL; + sal_Bool bRet = (pMod != NULL); + return bRet; +} + + +// Methods XNameReplace +void ModuleContainer_Impl::replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + removeByName( aName ); + insertByName( aName, aElement ); +} + + +// Methods XNameContainer +void ModuleContainer_Impl::insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + Type aModuleType = ::getCppuType( (const Reference< XStarBasicModuleInfo > *)0 ); + Type aAnyType = aElement.getValueType(); + if( aModuleType != aAnyType ) + throw IllegalArgumentException(); + Reference< XStarBasicModuleInfo > xMod; + aElement >>= xMod; + mpLib->MakeModule32( aName, xMod->getSource() ); +} + +void ModuleContainer_Impl::removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + SbModule* pMod = mpLib ? mpLib->FindModule( Name ) : NULL; + if( !pMod ) + throw NoSuchElementException(); + mpLib->Remove( pMod ); +} + + +//===================================================================== + +Sequence< sal_Int8 > implGetDialogData( SbxObject* pDialog ) +{ + SvMemoryStream aMemStream; + pDialog->Store( aMemStream ); + sal_Int32 nLen = aMemStream.Tell(); + Sequence< sal_Int8 > aData( nLen ); + sal_Int8* pDestData = aData.getArray(); + const sal_Int8* pSrcData = (const sal_Int8*)aMemStream.GetData(); + rtl_copyMemory( pDestData, pSrcData, nLen ); + return aData; +} + +SbxObject* implCreateDialog( Sequence< sal_Int8 > aData ) +{ + sal_Int8* pData = aData.getArray(); + SvMemoryStream aMemStream( pData, aData.getLength(), STREAM_READ ); + SbxObject* pDialog = (SbxObject*)SbxBase::Load( aMemStream ); + return pDialog; +} + +// HACK! Because this value is defined in basctl/inc/vcsbxdef.hxx +// which we can't include here, we have to use the value directly +#define SBXID_DIALOG 101 + + +class DialogContainer_Impl : public NameContainerHelper +{ + StarBASIC* mpLib; + +public: + DialogContainer_Impl( StarBASIC* pLib ) + :mpLib( pLib ) {} + + // Methods XElementAccess + virtual Type SAL_CALL getElementType() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasElements() + throw(RuntimeException); + + // Methods XNameAccess + virtual Any SAL_CALL getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getElementNames() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) + throw(RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); +}; + +// Methods XElementAccess +Type DialogContainer_Impl::getElementType() + throw(RuntimeException) +{ + Type aModuleType = ::getCppuType( (const Reference< XStarBasicDialogInfo > *)0 ); + return aModuleType; +} + +sal_Bool DialogContainer_Impl::hasElements() + throw(RuntimeException) +{ + sal_Bool bRet = sal_False; + + mpLib->GetAll( SbxCLASS_OBJECT ); + sal_Int16 nCount = mpLib->GetObjects()->Count(); + for( sal_Int16 nObj = 0; nObj < nCount ; nObj++ ) + { + SbxVariable* pVar = mpLib->GetObjects()->Get( nObj ); + if ( pVar->ISA( SbxObject ) && ( ((SbxObject*)pVar)->GetSbxId() == SBXID_DIALOG ) ) + { + bRet = sal_True; + break; + } + } + return bRet; +} + +// Methods XNameAccess +Any DialogContainer_Impl::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + SbxVariable* pVar = mpLib->GetObjects()->Find( aName, SbxCLASS_DONTCARE ); + if( !( pVar && pVar->ISA( SbxObject ) && + ( ((SbxObject*)pVar)->GetSbxId() == SBXID_DIALOG ) ) ) + { + throw NoSuchElementException(); + } + + Reference< XStarBasicDialogInfo > xDialog = + (XStarBasicDialogInfo*)new DialogInfo_Impl + ( aName, implGetDialogData( (SbxObject*)pVar ) ); + + Any aRetAny; + aRetAny <<= xDialog; + return aRetAny; +} + +Sequence< OUString > DialogContainer_Impl::getElementNames() + throw(RuntimeException) +{ + mpLib->GetAll( SbxCLASS_OBJECT ); + sal_Int16 nCount = mpLib->GetObjects()->Count(); + Sequence< OUString > aRetSeq( nCount ); + OUString* pRetSeq = aRetSeq.getArray(); + sal_Int32 nDialogCounter = 0; + + for( sal_Int16 nObj = 0; nObj < nCount ; nObj++ ) + { + SbxVariable* pVar = mpLib->GetObjects()->Get( nObj ); + if ( pVar->ISA( SbxObject ) && ( ((SbxObject*)pVar)->GetSbxId() == SBXID_DIALOG ) ) + { + pRetSeq[ nDialogCounter ] = OUString( pVar->GetName() ); + nDialogCounter++; + } + } + aRetSeq.realloc( nDialogCounter ); + return aRetSeq; +} + +sal_Bool DialogContainer_Impl::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + sal_Bool bRet = sal_False; + SbxVariable* pVar = mpLib->GetObjects()->Find( aName, SbxCLASS_DONTCARE ); + if( pVar && pVar->ISA( SbxObject ) && + ( ((SbxObject*)pVar)->GetSbxId() == SBXID_DIALOG ) ) + { + bRet = sal_True; + } + return bRet; +} + + +// Methods XNameReplace +void DialogContainer_Impl::replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + removeByName( aName ); + insertByName( aName, aElement ); +} + + +// Methods XNameContainer +void DialogContainer_Impl::insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + (void)aName; + Type aModuleType = ::getCppuType( (const Reference< XStarBasicDialogInfo > *)0 ); + Type aAnyType = aElement.getValueType(); + if( aModuleType != aAnyType ) + throw IllegalArgumentException(); + Reference< XStarBasicDialogInfo > xMod; + aElement >>= xMod; + SbxObjectRef xDialog = implCreateDialog( xMod->getData() ); + mpLib->Insert( xDialog ); +} + +void DialogContainer_Impl::removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + (void)Name; + SbxVariable* pVar = mpLib->GetObjects()->Find( Name, SbxCLASS_DONTCARE ); + if( !( pVar && pVar->ISA( SbxObject ) && + ( ((SbxObject*)pVar)->GetSbxId() == SBXID_DIALOG ) ) ) + { + throw NoSuchElementException(); + } + mpLib->Remove( pVar ); +} + + +//===================================================================== + + +class LibraryContainer_Impl : public NameContainerHelper +{ + BasicManager* mpMgr; + +public: + LibraryContainer_Impl( BasicManager* pMgr ) + :mpMgr( pMgr ) {} + + // Methods XElementAccess + virtual Type SAL_CALL getElementType() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasElements() + throw(RuntimeException); + + // Methods XNameAccess + virtual Any SAL_CALL getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getElementNames() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) + throw(RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); +}; + + +// Methods XElementAccess +Type LibraryContainer_Impl::getElementType() + throw(RuntimeException) +{ + Type aType = ::getCppuType( (const Reference< XStarBasicLibraryInfo > *)0 ); + return aType; +} + +sal_Bool LibraryContainer_Impl::hasElements() + throw(RuntimeException) +{ + sal_Int32 nLibs = mpMgr->GetLibCount(); + sal_Bool bRet = (nLibs > 0); + return bRet; +} + +// Methods XNameAccess +Any LibraryContainer_Impl::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + Any aRetAny; + if( !mpMgr->HasLib( aName ) ) + throw NoSuchElementException(); + StarBASIC* pLib = mpMgr->GetLib( aName ); + + Reference< XNameContainer > xModuleContainer = + (XNameContainer*)new ModuleContainer_Impl( pLib ); + + Reference< XNameContainer > xDialogContainer; + (XNameContainer*)new DialogContainer_Impl( pLib ); + + BasicLibInfo* pLibInfo = mpMgr->FindLibInfo( pLib ); + + OUString aPassword = pLibInfo->GetPassword(); + + // TODO Nur extern-Info liefern! + OUString aExternaleSourceURL; + OUString aLinkTargetURL; + if( pLibInfo->IsReference() ) + aLinkTargetURL = pLibInfo->GetStorageName(); + else if( pLibInfo->IsExtern() ) + aExternaleSourceURL = pLibInfo->GetStorageName(); + + Reference< XStarBasicLibraryInfo > xLibInfo = new LibraryInfo_Impl + ( + aName, + xModuleContainer, + xDialogContainer, + aPassword, + aExternaleSourceURL, + aLinkTargetURL + ); + + aRetAny <<= xLibInfo; + return aRetAny; +} + +Sequence< OUString > LibraryContainer_Impl::getElementNames() + throw(RuntimeException) +{ + USHORT nLibs = mpMgr->GetLibCount(); + Sequence< OUString > aRetSeq( nLibs ); + OUString* pRetSeq = aRetSeq.getArray(); + for( USHORT i = 0 ; i < nLibs ; i++ ) + { + pRetSeq[i] = OUString( mpMgr->GetLibName( i ) ); + } + return aRetSeq; +} + +sal_Bool LibraryContainer_Impl::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + sal_Bool bRet = mpMgr->HasLib( aName ); + return bRet; +} + +// Methods XNameReplace +void LibraryContainer_Impl::replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + removeByName( aName ); + insertByName( aName, aElement ); +} + +// Methods XNameContainer +void LibraryContainer_Impl::insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + (void)aName; + (void)aElement; + // TODO: Insert a complete Library?! +} + +void LibraryContainer_Impl::removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + StarBASIC* pLib = mpMgr->GetLib( Name ); + if( !pLib ) + throw NoSuchElementException(); + USHORT nLibId = mpMgr->GetLibId( Name ); + mpMgr->RemoveLib( nLibId ); +} + +//===================================================================== + +typedef WeakImplHelper1< XStarBasicAccess > StarBasicAccessHelper; + + +class StarBasicAccess_Impl : public StarBasicAccessHelper +{ + BasicManager* mpMgr; + Reference< XNameContainer > mxLibContainer; + +public: + StarBasicAccess_Impl( BasicManager* pMgr ) + :mpMgr( pMgr ) {} + +public: + + // Methods + virtual Reference< XNameContainer > SAL_CALL getLibraryContainer() + throw(RuntimeException); + virtual void SAL_CALL createLibrary( const OUString& LibName, const OUString& Password, + const OUString& ExternalSourceURL, const OUString& LinkTargetURL ) + throw(ElementExistException, RuntimeException); + virtual void SAL_CALL addModule( const OUString& LibraryName, const OUString& ModuleName, + const OUString& Language, const OUString& Source ) + throw(NoSuchElementException, RuntimeException); + virtual void SAL_CALL addDialog( const OUString& LibraryName, const OUString& DialogName, + const Sequence< sal_Int8 >& Data ) + throw(NoSuchElementException, RuntimeException); + +}; + +Reference< XNameContainer > SAL_CALL StarBasicAccess_Impl::getLibraryContainer() + throw(RuntimeException) +{ + if( !mxLibContainer.is() ) + mxLibContainer = (XNameContainer*)new LibraryContainer_Impl( mpMgr ); + return mxLibContainer; +} + +void SAL_CALL StarBasicAccess_Impl::createLibrary +( + const OUString& LibName, + const OUString& Password, + const OUString& ExternalSourceURL, + const OUString& LinkTargetURL +) + throw(ElementExistException, RuntimeException) +{ + (void)ExternalSourceURL; +#ifdef DBG_UTIL + StarBASIC* pLib = +#endif + mpMgr->CreateLib( LibName, Password, LinkTargetURL ); + DBG_ASSERT( pLib, "XML Import: Basic library could not be created"); +} + +void SAL_CALL StarBasicAccess_Impl::addModule +( + const OUString& LibraryName, + const OUString& ModuleName, + const OUString& Language, + const OUString& Source +) + throw(NoSuchElementException, RuntimeException) +{ + (void)Language; + StarBASIC* pLib = mpMgr->GetLib( LibraryName ); + DBG_ASSERT( pLib, "XML Import: Lib for module unknown"); + if( pLib ) + pLib->MakeModule32( ModuleName, Source ); +} + +void SAL_CALL StarBasicAccess_Impl::addDialog +( + const OUString& LibraryName, + const OUString& DialogName, + const Sequence< sal_Int8 >& Data +) + throw(NoSuchElementException, RuntimeException) +{ + (void)LibraryName; + (void)DialogName; + (void)Data; +} + +// Basic XML Import/Export +Reference< XStarBasicAccess > getStarBasicAccess( BasicManager* pMgr ) +{ + Reference< XStarBasicAccess > xRet = + new StarBasicAccess_Impl( (BasicManager*)pMgr ); + return xRet; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/basmgr/makefile.mk b/binfilter/bf_basic/source/basmgr/makefile.mk new file mode 100644 index 000000000000..bfa54fc07b4d --- /dev/null +++ b/binfilter/bf_basic/source/basmgr/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=binfilter +TARGET=basic_basicmgr +ENABLE_EXCEPTIONS=TRUE + +NO_HIDS=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +INC+= -I$(PRJ)$/inc$/bf_basic + +# --- Allgemein ----------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/basmgr.obj + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/binfilter/bf_basic/source/classes/image.cxx b/binfilter/bf_basic/source/classes/image.cxx new file mode 100644 index 000000000000..65cb44c939aa --- /dev/null +++ b/binfilter/bf_basic/source/classes/image.cxx @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/stream.hxx> +#include <tools/tenccvt.hxx> +#include "sbx.hxx" +#include "sb.hxx" +#include <string.h> // memset() etc +#include "image.hxx" +#include "codegen.hxx" + +namespace binfilter { + +SbiImage::SbiImage() +{ + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + pLegacyPCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nCodeSize = 0; + nLegacyCodeSize = + nDimBase = 0; + bInit = + bError = FALSE; + bFirstInit = TRUE; + eCharSet = gsl_getSystemTextEncoding(); +} + +SbiImage::~SbiImage() +{ + Clear(); +} + +void SbiImage::Clear() +{ + delete[] pStringOff; + delete[] pStrings; + delete[] pCode; + ReleaseLegacyBuffer(); + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nLegacyCodeSize = 0; + nCodeSize = 0; + eCharSet = gsl_getSystemTextEncoding(); + nDimBase = 0; + bError = FALSE; +} + +/************************************************************************** +* +* Service-Routinen fuer das Laden und Speichern +* +**************************************************************************/ + +BOOL SbiGood( SvStream& r ) +{ + return BOOL( !r.IsEof() && r.GetError() == SVSTREAM_OK ); +} + +// Oeffnen eines Records + +ULONG SbiOpenRecord( SvStream& r, UINT16 nSignature, UINT16 nElem ) +{ + ULONG nPos = r.Tell(); + r << nSignature << (INT32) 0 << nElem; + return nPos; +} + +// Schliessen eines Records + +void SbiCloseRecord( SvStream& r, ULONG nOff ) +{ + ULONG nPos = r.Tell(); + r.Seek( nOff + 2 ); + r << (INT32) ( nPos - nOff - 8 ); + r.Seek( nPos ); +} + +/************************************************************************** +* +* Laden und Speichern +* +**************************************************************************/ + +// Falls die Versionsnummer nicht passt, werden die binaeren Teile +// nicht geladen, wohl aber Source, Kommentar und Name. + +BOOL SbiImage::Load( SvStream& r, UINT32& nVersion ) +{ + + UINT16 nSign, nCount; + UINT32 nLen, nOff; + + Clear(); + // Master-Record einlesen + r >> nSign >> nLen >> nCount; + ULONG nLast = r.Tell() + nLen; + UINT32 nCharSet; // System-Zeichensatz + UINT32 lDimBase; + UINT16 nReserved1; + UINT32 nReserved2; + UINT32 nReserved3; + BOOL bBadVer = FALSE; + if( nSign == B_MODULE ) + { + r >> nVersion >> nCharSet >> lDimBase + >> nFlags >> nReserved1 >> nReserved2 >> nReserved3; + eCharSet = (CharSet) nCharSet; + eCharSet = GetSOLoadTextEncoding( eCharSet ); + bBadVer = BOOL( nVersion > B_CURVERSION ); + nDimBase = (USHORT) lDimBase; + } + + bool bLegacy = ( nVersion < B_EXT_IMG_VERSION ); + + ULONG nNext; + while( ( nNext = r.Tell() ) < nLast ) + { + short i; + + r >> nSign >> nLen >> nCount; + nNext += nLen + 8; + if( r.GetError() == SVSTREAM_OK ) + switch( nSign ) + { + case B_NAME: + r.ReadByteString( aName, eCharSet ); + //r >> aName; + break; + case B_COMMENT: + r.ReadByteString( aComment, eCharSet ); + //r >> aComment; + break; + case B_SOURCE: + { + String aTmp; + r.ReadByteString( aTmp, eCharSet ); + aOUSource = aTmp; + //r >> aSource; + break; + } +#ifdef EXTENDED_BINARY_MODULES + case B_EXTSOURCE: + { + for( UINT16 j = 0 ; j < nCount ; j++ ) + { + String aTmp; + r.ReadByteString( aTmp, eCharSet ); + aOUSource += aTmp; + } + break; + } +#endif + case B_PCODE: + if( bBadVer ) break; + pCode = new char[ nLen ]; + nCodeSize = nLen; + r.Read( pCode, nCodeSize ); + if ( bLegacy ) + { + ReleaseLegacyBuffer(); // release any previously held buffer + nLegacyCodeSize = (UINT16) nCodeSize; + pLegacyPCode = pCode; + + PCodeBuffConvertor< UINT16, UINT32 > aLegacyToNew( (BYTE*)pLegacyPCode, nLegacyCodeSize ); + aLegacyToNew.convert(); + pCode = (char*)aLegacyToNew.GetBuffer(); + nCodeSize = aLegacyToNew.GetSize(); + // we don't release the legacy buffer + // right now, thats because the module + // needs it to fix up the method + // nStart members. When that is done + // the module can release the buffer + // or it can wait until this routine + // is called again or when this class // destructs all of which will trigger + // release of the buffer. + } + break; + case B_PUBLICS: + case B_POOLDIR: + case B_SYMPOOL: + case B_LINERANGES: + break; + case B_STRINGPOOL: + if( bBadVer ) break; + MakeStrings( nCount ); + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + { + r >> nOff; + pStringOff[ i ] = (USHORT) nOff; + } + r >> nLen; + if( SbiGood( r ) ) + { + delete [] pStrings; + pStrings = new sal_Unicode[ nLen ]; + nStringSize = (USHORT) nLen; + + char* pByteStrings = new char[ nLen ]; + r.Read( pByteStrings, nStringSize ); + for( short j = 0; j < nStrings; j++ ) + { + USHORT nOff2 = (USHORT) pStringOff[ j ]; + String aStr( pByteStrings + nOff2, eCharSet ); + memcpy( pStrings + nOff2, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( sal_Unicode ) ); + } + delete[] pByteStrings; + } break; + case B_MODEND: + goto done; + default: + break; + } + else + break; + r.Seek( nNext ); + } +done: + r.Seek( nLast ); + //if( eCharSet != ::GetSystemCharSet() ) + //ConvertStrings(); + if( !SbiGood( r ) ) + bError = TRUE; + return BOOL( !bError ); +} + +BOOL SbiImage::Save( SvStream& r, UINT32 nVer ) +{ + bool bLegacy = ( nVer < B_EXT_IMG_VERSION ); + + // detect if old code exceeds legacy limits + // if so, then disallow save + if ( bLegacy && ExceedsLegacyLimits() ) + { + SbiImage aEmptyImg; + aEmptyImg.aName = aName; + aEmptyImg.Save( r, B_LEGACYVERSION ); + return TRUE; + } + // Erst mal der Header: + ULONG nStart = SbiOpenRecord( r, B_MODULE, 1 ); + ULONG nPos; + + eCharSet = GetSOStoreTextEncoding( eCharSet ); + if ( bLegacy ) + r << (INT32) B_LEGACYVERSION; + else + r << (INT32) B_CURVERSION; + r << (INT32) eCharSet + << (INT32) nDimBase + << (INT16) nFlags + << (INT16) 0 + << (INT32) 0 + << (INT32) 0; + + // Name? + if( aName.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_NAME, 1 ); + r.WriteByteString( aName, eCharSet ); + //r << aName; + SbiCloseRecord( r, nPos ); + } + // Kommentar? + if( aComment.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_COMMENT, 1 ); + r.WriteByteString( aComment, eCharSet ); + //r << aComment; + SbiCloseRecord( r, nPos ); + } + // Source? + if( aOUSource.getLength() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_SOURCE, 1 ); + String aTmp; + sal_Int32 nLen = aOUSource.getLength(); + const sal_Int32 nMaxUnitSize = STRING_MAXLEN - 1; + if( nLen > STRING_MAXLEN ) + aTmp = aOUSource.copy( 0, nMaxUnitSize ); + else + aTmp = aOUSource; + r.WriteByteString( aTmp, eCharSet ); + //r << aSource; + SbiCloseRecord( r, nPos ); + +#ifdef EXTENDED_BINARY_MODULES + if( nLen > STRING_MAXLEN ) + { + sal_Int32 nRemainingLen = nLen - nMaxUnitSize; + UINT16 nUnitCount = UINT16( (nRemainingLen + nMaxUnitSize - 1) / nMaxUnitSize ); + nPos = SbiOpenRecord( r, B_EXTSOURCE, nUnitCount ); + for( UINT16 i = 0 ; i < nUnitCount ; i++ ) + { + sal_Int32 nCopyLen = + (nRemainingLen > nMaxUnitSize) ? nMaxUnitSize : nRemainingLen; + String aTmp2 = aOUSource.copy( (i+1) * nMaxUnitSize, nCopyLen ); + nRemainingLen -= nCopyLen; + r.WriteByteString( aTmp2, eCharSet ); + } + SbiCloseRecord( r, nPos ); + } +#endif + } + // Binaere Daten? + if( pCode && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_PCODE, 1 ); + if ( bLegacy ) + { + ReleaseLegacyBuffer(); // release any previously held buffer + PCodeBuffConvertor< UINT32, UINT16 > aNewToLegacy( (BYTE*)pCode, nCodeSize ); + aNewToLegacy.convert(); + pLegacyPCode = (char*)aNewToLegacy.GetBuffer(); + nLegacyCodeSize = aNewToLegacy.GetSize(); + r.Write( pLegacyPCode, nLegacyCodeSize ); + } + else + r.Write( pCode, nCodeSize ); + SbiCloseRecord( r, nPos ); + } + // String-Pool? + if( nStrings ) + { + nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings ); + // Fuer jeden String: + // UINT32 Offset des Strings im Stringblock + short i; + + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + r << (UINT32) pStringOff[ i ]; + + // Danach der String-Block + char* pByteStrings = new char[ nStringSize ]; + for( i = 0; i < nStrings; i++ ) + { + USHORT nOff = (USHORT) pStringOff[ i ]; + ByteString aStr( pStrings + nOff, eCharSet ); + memcpy( pByteStrings + nOff, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( char ) ); + } + r << (UINT32) nStringSize; + r.Write( pByteStrings, nStringSize ); + + delete[] pByteStrings; + SbiCloseRecord( r, nPos ); + } + // Und die Gesamtlaenge setzen + SbiCloseRecord( r, nStart ); + if( !SbiGood( r ) ) + bError = TRUE; + return BOOL( !bError ); +} + +/************************************************************************** +* +* Routinen, die auch vom Compiler gerufen werden +* +**************************************************************************/ + +void SbiImage::MakeStrings( short nSize ) +{ + nStrings = 0; + nStringIdx = 0; + nStringOff = 0; + nStringSize = 1024; + pStrings = new sal_Unicode[ nStringSize ]; + pStringOff = new UINT32[ nSize ]; + if( pStrings && pStringOff ) + { + nStrings = nSize; + memset( pStringOff, 0, nSize * sizeof( UINT32 ) ); + memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) ); + } + else + bError = TRUE; +} + +/************************************************************************** +* +* Zugriffe auf das Image +* +**************************************************************************/ + +const SbxObject* SbiImage::FindType (String aTypeName) const +{ + return rTypes.Is() ? (SbxObject*)rTypes->Find(aTypeName,SbxCLASS_OBJECT) : NULL; +} + +UINT16 +SbiImage::CalcLegacyOffset( INT32 nOffset ) +{ + return SbiCodeGen::calcLegacyOffSet( (BYTE*)pCode, nOffset ) ; +} +UINT32 +SbiImage::CalcNewOffset( INT16 nOffset ) +{ + return SbiCodeGen::calcNewOffSet( (BYTE*)pLegacyPCode, nOffset ) ; +} + +void +SbiImage::ReleaseLegacyBuffer() +{ + delete[] pLegacyPCode; + pLegacyPCode = NULL; + nLegacyCodeSize = 0; +} + +BOOL +SbiImage::ExceedsLegacyLimits() +{ + if ( ( nStringSize > 0xFF00L ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00L ) ) + return TRUE; + return FALSE; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/classes/makefile.mk b/binfilter/bf_basic/source/classes/makefile.mk new file mode 100644 index 000000000000..51a6dc023dbc --- /dev/null +++ b/binfilter/bf_basic/source/classes/makefile.mk @@ -0,0 +1,59 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=binfilter +TARGET=basic_classes + +NO_HIDS=TRUE + +# --- Settings ----------------------------------------------------------- + +ENABLE_EXCEPTIONS=TRUE + +.INCLUDE : settings.mk + +INC+= -I$(PRJ)$/inc$/bf_basic + +# --- Allgemein ----------------------------------------------------------- + +SLOFILES=\ + $(SLO)$/sb.obj \ + $(SLO)$/sbxmod.obj \ + $(SLO)$/sbunoobj.obj \ + $(SLO)$/image.obj \ + $(SLO)$/sbintern.obj \ + +# $(SLO)$/propacc.obj \ + $(SLO)$/disas.obj \ + $(SLO)$/eventatt.obj + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/binfilter/bf_basic/source/classes/sb.cxx b/binfilter/bf_basic/source/classes/sb.cxx new file mode 100644 index 000000000000..df3f3f4dc784 --- /dev/null +++ b/binfilter/bf_basic/source/classes/sb.cxx @@ -0,0 +1,1416 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <stdio.h> + +#include "sb.hxx" +#include <tools/rcid.h> +#include <tools/config.hxx> + +#include <tools/stream.hxx> +#ifndef __RSC //autogen +#include <tools/errinf.hxx> +#endif +#include <sbx.hxx> +#include <tools/list.hxx> +#include <tools/rc.hxx> +#include <vcl/svapp.hxx> +#include "sbunoobj.hxx" +#include "sbjsmeth.hxx" +#include "sbjsmod.hxx" +#include "sbintern.hxx" +#include "image.hxx" +#include "filefmt.hxx" + +#include <osl/mutex.hxx> + +namespace binfilter { + +// #pragma SW_SEGMENT_CLASS( SBASIC, SBASIC_CODE ) + +TYPEINIT1(StarBASIC,SbxObject) + +#define RTLNAME "@SBRTL" + + +//======================================================================== +// Array zur Umrechnung SFX <-> VB-Fehlercodes anlegen + +struct SFX_VB_ErrorItem +{ + USHORT nErrorVB; + SbError nErrorSFX; +}; + +const SFX_VB_ErrorItem __FAR_DATA SFX_VB_ErrorTab[] = +{ + { 1, SbERR_BASIC_EXCEPTION }, // #87844 Map exception to error code 1 + { 2, SbERR_SYNTAX }, + { 3, SbERR_NO_GOSUB }, + { 4, SbERR_REDO_FROM_START }, + { 5, SbERR_BAD_ARGUMENT }, + { 6, SbERR_MATH_OVERFLOW }, + { 7, SbERR_NO_MEMORY }, + { 8, SbERR_ALREADY_DIM }, + { 9, SbERR_OUT_OF_RANGE }, + { 10, SbERR_DUPLICATE_DEF }, + { 11, SbERR_ZERODIV }, + { 12, SbERR_VAR_UNDEFINED }, + { 13, SbERR_CONVERSION }, + { 14, SbERR_BAD_PARAMETER }, + { 18, SbERR_USER_ABORT }, + { 20, SbERR_BAD_RESUME }, + { 28, SbERR_STACK_OVERFLOW }, + { 35, SbERR_PROC_UNDEFINED }, + { 48, SbERR_BAD_DLL_LOAD }, + { 49, SbERR_BAD_DLL_CALL }, + { 51, SbERR_INTERNAL_ERROR }, + { 52, SbERR_BAD_CHANNEL }, + { 53, SbERR_FILE_NOT_FOUND }, + { 54, SbERR_BAD_FILE_MODE }, + { 55, SbERR_FILE_ALREADY_OPEN }, + { 57, SbERR_IO_ERROR }, + { 58, SbERR_FILE_EXISTS }, + { 59, SbERR_BAD_RECORD_LENGTH }, + { 61, SbERR_DISK_FULL }, + { 62, SbERR_READ_PAST_EOF }, + { 63, SbERR_BAD_RECORD_NUMBER }, + { 67, SbERR_TOO_MANY_FILES }, + { 68, SbERR_NO_DEVICE }, + { 70, SbERR_ACCESS_DENIED }, + { 71, SbERR_NOT_READY }, + { 73, SbERR_NOT_IMPLEMENTED }, + { 74, SbERR_DIFFERENT_DRIVE }, + { 75, SbERR_ACCESS_ERROR }, + { 76, SbERR_PATH_NOT_FOUND }, + { 91, SbERR_NO_OBJECT }, + { 93, SbERR_BAD_PATTERN }, + { 94, SBERR_IS_NULL }, + { 250, SbERR_DDE_ERROR }, + { 280, SbERR_DDE_WAITINGACK }, + { 281, SbERR_DDE_OUTOFCHANNELS }, + { 282, SbERR_DDE_NO_RESPONSE }, + { 283, SbERR_DDE_MULT_RESPONSES }, + { 284, SbERR_DDE_CHANNEL_LOCKED }, + { 285, SbERR_DDE_NOTPROCESSED }, + { 286, SbERR_DDE_TIMEOUT }, + { 287, SbERR_DDE_USER_INTERRUPT }, + { 288, SbERR_DDE_BUSY }, + { 289, SbERR_DDE_NO_DATA }, + { 290, SbERR_DDE_WRONG_DATA_FORMAT }, + { 291, SbERR_DDE_PARTNER_QUIT }, + { 292, SbERR_DDE_CONV_CLOSED }, + { 293, SbERR_DDE_NO_CHANNEL }, + { 294, SbERR_DDE_INVALID_LINK }, + { 295, SbERR_DDE_QUEUE_OVERFLOW }, + { 296, SbERR_DDE_LINK_ALREADY_EST }, + { 297, SbERR_DDE_LINK_INV_TOPIC }, + { 298, SbERR_DDE_DLL_NOT_FOUND }, + { 323, SbERR_CANNOT_LOAD }, + { 341, SbERR_BAD_INDEX }, + { 366, SbERR_NO_ACTIVE_OBJECT }, + { 380, SbERR_BAD_PROP_VALUE }, + { 382, SbERR_PROP_READONLY }, + { 394, SbERR_PROP_WRITEONLY }, + { 420, SbERR_INVALID_OBJECT }, + { 423, SbERR_NO_METHOD }, + { 424, SbERR_NEEDS_OBJECT }, + { 425, SbERR_INVALID_USAGE_OBJECT }, + { 430, SbERR_NO_OLE }, + { 438, SbERR_BAD_METHOD }, + { 440, SbERR_OLE_ERROR }, + { 445, SbERR_BAD_ACTION }, + { 446, SbERR_NO_NAMED_ARGS }, + { 447, SbERR_BAD_LOCALE }, + { 448, SbERR_NAMED_NOT_FOUND }, + { 449, SbERR_NOT_OPTIONAL }, + { 450, SbERR_WRONG_ARGS }, + { 451, SbERR_NOT_A_COLL }, + { 452, SbERR_BAD_ORDINAL }, + { 453, SbERR_DLLPROC_NOT_FOUND }, + { 460, SbERR_BAD_CLIPBD_FORMAT }, + { 951, SbERR_UNEXPECTED }, + { 952, SbERR_EXPECTED }, + { 953, SbERR_SYMBOL_EXPECTED }, + { 954, SbERR_VAR_EXPECTED }, + { 955, SbERR_LABEL_EXPECTED }, + { 956, SbERR_LVALUE_EXPECTED }, + { 957, SbERR_VAR_DEFINED }, + { 958, SbERR_PROC_DEFINED }, + { 959, SbERR_LABEL_DEFINED }, + { 960, SbERR_UNDEF_VAR }, + { 961, SbERR_UNDEF_ARRAY }, + { 962, SbERR_UNDEF_PROC }, + { 963, SbERR_UNDEF_LABEL }, + { 964, SbERR_UNDEF_TYPE }, + { 965, SbERR_BAD_EXIT }, + { 966, SbERR_BAD_BLOCK }, + { 967, SbERR_BAD_BRACKETS }, + { 968, SbERR_BAD_DECLARATION }, + { 969, SbERR_BAD_PARAMETERS }, + { 970, SbERR_BAD_CHAR_IN_NUMBER }, + { 971, SbERR_MUST_HAVE_DIMS }, + { 972, SbERR_NO_IF }, + { 973, SbERR_NOT_IN_SUBR }, + { 974, SbERR_NOT_IN_MAIN }, + { 975, SbERR_WRONG_DIMS }, + { 976, SbERR_BAD_OPTION }, + { 977, SbERR_CONSTANT_REDECLARED }, + { 978, SbERR_PROG_TOO_LARGE }, + { 979, SbERR_NO_STRINGS_ARRAYS }, + { 1000, SbERR_PROPERTY_NOT_FOUND }, + { 1001, SbERR_METHOD_NOT_FOUND }, + { 1002, SbERR_ARG_MISSING }, + { 1003, SbERR_BAD_NUMBER_OF_ARGS }, + { 1004, SbERR_METHOD_FAILED }, + { 1005, SbERR_SETPROP_FAILED }, + { 1006, SbERR_GETPROP_FAILED }, + { 0xFFFF, 0xFFFFFFFFL } // End-Marke +}; + + +//////////////////////////////////////////////////////////////////////////// + +// Die StarBASIC-Factory hat einen Hack. Wenn ein SbModule eingerichtet wird, +// wird der Pointer gespeichert und an nachfolgende SbProperties/SbMethods +// uebergeben. Dadurch wird die Modul-Relationship wiederhergestellt. Das +// klappt aber nur, wenn ein Modul geladen wird. Fuer getrennt geladene +// Properties kann es Probleme geben! + +SbxBase* SbiFactory::Create( UINT16 nSbxId, UINT32 nCreator ) +{ + if( nCreator == SBXCR_SBX ) + { + String aEmpty; + switch( nSbxId ) + { + case SBXID_BASIC: + return new StarBASIC( NULL ); + case SBXID_BASICMOD: + return new SbModule( aEmpty ); + case SBXID_BASICPROP: + return new SbProperty( aEmpty, SbxVARIANT, NULL ); + case SBXID_BASICMETHOD: + return new SbMethod( aEmpty, SbxVARIANT, NULL ); + case SBXID_JSCRIPTMOD: + return new SbJScriptModule( aEmpty ); + case SBXID_JSCRIPTMETH: + return new SbJScriptMethod( aEmpty, SbxVARIANT, NULL ); + } + } + return NULL; +} + +SbxObject* SbiFactory::CreateObject( const String& rClass ) +{ + if( rClass.EqualsIgnoreCaseAscii( "StarBASIC" ) ) + return new StarBASIC( NULL ); + else + if( rClass.EqualsIgnoreCaseAscii( "StarBASICModule" ) ) + { + String aEmpty; + return new SbModule( aEmpty ); + } + else + if( rClass.EqualsIgnoreCaseAscii( "Collection" ) ) + { + String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") ); + return new BasicCollection( aCollectionName ); + } + else + return NULL; +} + + +// Factory class to create OLE objects +class SbOLEFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +SbxBase* SbOLEFactory::Create( UINT16, UINT32 ) +{ + // Not supported + return NULL; +} + +SbUnoObject* createOLEObject_Impl( const String& aType ); // sbunoobj.cxx + +SbxObject* SbOLEFactory::CreateObject( const String& rClassName ) +{ + SbxObject* pRet = createOLEObject_Impl( rClassName ); + return pRet; +} + + +// Factory class to create user defined objects (type command) +class SbTypeFactory : public SbxFactory +{ + SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj ); + +public: + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +SbxBase* SbTypeFactory::Create( UINT16, UINT32 ) +{ + // Not supported + return NULL; +} + +SbxObject* SbTypeFactory::cloneTypeObjectImpl( const SbxObject& rTypeObj ) +{ + SbxObject* pRet = new SbxObject( rTypeObj ); + pRet->PutObject( pRet ); + + // Copy the properties, not only the reference to them + SbxArray* pProps = pRet->GetProperties(); + UINT32 nCount = pProps->Count32(); + for( UINT32 i = 0 ; i < nCount ; i++ ) + { + SbxVariable* pVar = pProps->Get32( i ); + SbxProperty* pProp = PTR_CAST( SbxProperty, pVar ); + if( pProp ) + { + SbxProperty* pNewProp = new SbxProperty( *pProp ); + pProps->PutDirect( pNewProp, i ); + } + } + return pRet; +} + +SbxObject* SbTypeFactory::CreateObject( const String& rClassName ) +{ + SbxObject* pRet = NULL; + SbModule* pMod = pMOD; + if( pMod ) + { + const SbxObject* pObj = pMod->FindType( rClassName ); + if( pObj ) + pRet = cloneTypeObjectImpl( *pObj ); + } + return pRet; +} + +TYPEINIT1(SbClassModuleObject,SbModule) + +SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule ) + : SbModule( pClassModule->GetName() ) + , mpClassModule( pClassModule ) + , mbInitializeEventDone( false ) +{ + aOUSource = pClassModule->aOUSource; + aComment = pClassModule->aComment; + pImage = pClassModule->pImage; + + SetClassName( pClassModule->GetName() ); + + // Allow search only internally + ResetFlag( SBX_GBLSEARCH ); + + // Copy the methods from original class module + SbxArray* pClassMethods = pClassModule->GetMethods(); + UINT32 nMethodCount = pClassMethods->Count32(); + UINT32 i; + for( i = 0 ; i < nMethodCount ; i++ ) + { + SbxVariable* pVar = pClassMethods->Get32( i ); + + // Exclude SbIfaceMapperMethod to copy them in a second step + SbIfaceMapperMethod* pIfaceMethod = PTR_CAST( SbIfaceMapperMethod, pVar ); + if( !pIfaceMethod ) + { + SbMethod* pMethod = PTR_CAST(SbMethod, pVar ); + if( pMethod ) + { + USHORT nFlags_ = pMethod->GetFlags(); + pMethod->SetFlag( SBX_NO_BROADCAST ); + SbMethod* pNewMethod = new SbMethod( *pMethod ); + pNewMethod->ResetFlag( SBX_NO_BROADCAST ); + pMethod->SetFlags( nFlags_ ); + pNewMethod->pMod = this; + pNewMethod->SetParent( this ); + pMethods->PutDirect( pNewMethod, i ); + StartListening( pNewMethod->GetBroadcaster(), TRUE ); + } + } + } + + // Copy SbIfaceMapperMethod in a second step to ensure that + // the corresponding base methods have already been copied + for( i = 0 ; i < nMethodCount ; i++ ) + { + SbxVariable* pVar = pClassMethods->Get32( i ); + + SbIfaceMapperMethod* pIfaceMethod = PTR_CAST( SbIfaceMapperMethod, pVar ); + if( pIfaceMethod ) + { + SbMethod* pImplMethod = pIfaceMethod->getImplMethod(); + if( !pImplMethod ) + { + DBG_ERROR( "No ImplMethod" ); + continue; + } + + // Search for own copy of ImplMethod + String aImplMethodName = pImplMethod->GetName(); + SbxVariable* p = pMethods->Find( aImplMethodName, SbxCLASS_METHOD ); + SbMethod* pImplMethodCopy = p ? PTR_CAST(SbMethod,p) : NULL; + if( !pImplMethodCopy ) + { + DBG_ERROR( "Found no ImplMethod copy" ); + continue; + } + SbIfaceMapperMethod* pNewIfaceMethod = + new SbIfaceMapperMethod( pIfaceMethod->GetName(), pImplMethodCopy ); + pMethods->PutDirect( pNewIfaceMethod, i ); + } + } + + // Copy the properties from original class module + SbxArray* pClassProps = pClassModule->GetProperties(); + UINT32 nPropertyCount = pClassProps->Count32(); + for( i = 0 ; i < nPropertyCount ; i++ ) + { + SbxVariable* pVar = pClassProps->Get32( i ); + SbProcedureProperty* pProcedureProp = PTR_CAST( SbProcedureProperty, pVar ); + if( pProcedureProp ) + { + USHORT nFlags_ = pProcedureProp->GetFlags(); + pProcedureProp->SetFlag( SBX_NO_BROADCAST ); + SbProcedureProperty* pNewProp = new SbProcedureProperty + ( pProcedureProp->GetName(), pProcedureProp->GetType() ); + // ( pProcedureProp->GetName(), pProcedureProp->GetType(), this ); + pNewProp->ResetFlag( SBX_NO_BROADCAST ); + pProcedureProp->SetFlags( nFlags_ ); + pProps->PutDirect( pNewProp, i ); + StartListening( pNewProp->GetBroadcaster(), TRUE ); + } + else + { + SbxProperty* pProp = PTR_CAST( SbxProperty, pVar ); + if( pProp ) + { + USHORT nFlags_ = pProp->GetFlags(); + pProp->SetFlag( SBX_NO_BROADCAST ); + SbxProperty* pNewProp = new SbxProperty( *pProp ); + pNewProp->ResetFlag( SBX_NO_BROADCAST ); + pNewProp->SetParent( this ); + pProps->PutDirect( pNewProp, i ); + pProp->SetFlags( nFlags_ ); + } + } + } +} + +SbClassModuleObject::~SbClassModuleObject() +{ + triggerTerminateEvent(); + + // Must be deleted by base class dtor because this data + // is not owned by the SbClassModuleObject object + pImage = NULL; +} + +void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + bool bDone = false; + + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar ); + if( pProcProperty ) + { + bDone = true; + + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + String aProcName; + aProcName.AppendAscii( "Property Get " ); + aProcName += pProcProperty->GetName(); + + SbxVariable* pMeth = Find( aProcName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + aVals.eType = SbxVARIANT; + pMeth->Get( aVals ); + pVar->Put( aVals ); + } + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + SbxVariable* pMeth = NULL; + + bool bSet = pProcProperty->isSet(); + if( bSet ) + { + pProcProperty->setSet( false ); + + String aProcName; + aProcName.AppendAscii( "Property Set " ); + aProcName += pProcProperty->GetName(); + pMeth = Find( aProcName, SbxCLASS_METHOD ); + } + if( !pMeth ) // Let + { + String aProcName; + aProcName.AppendAscii( "Property Let " ); + aProcName += pProcProperty->GetName(); + pMeth = Find( aProcName, SbxCLASS_METHOD ); + } + + if( pMeth ) + { + // Setup parameters + SbxArrayRef xArray = new SbxArray; + xArray->Put( pMeth, 0 ); // Method as parameter 0 + xArray->Put( pVar, 1 ); + pMeth->SetParameters( xArray ); + + SbxValues aVals; + pMeth->Get( aVals ); + pMeth->SetParameters( NULL ); + } + } + } + } + + if( !bDone ) + SbModule::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); +} + +SbxVariable* SbClassModuleObject::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pRes = SbxObject::Find( rName, t ); + if( pRes ) + { + triggerInitializeEvent(); + + SbIfaceMapperMethod* pIfaceMapperMethod = PTR_CAST(SbIfaceMapperMethod,pRes); + if( pIfaceMapperMethod ) + { + pRes = pIfaceMapperMethod->getImplMethod(); + pRes->SetFlag( SBX_EXTFOUND ); + } + } + return pRes; +} + +void SbClassModuleObject::triggerInitializeEvent( void ) +{ + static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Initialize") ); + + if( mbInitializeEventDone ) + return; + + mbInitializeEventDone = true; + + // Search method + SbxVariable* pMeth = SbxObject::Find( aInitMethodName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + pMeth->Get( aVals ); + } +} + +void SbClassModuleObject::triggerTerminateEvent( void ) +{ + static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Terminate") ); + + if( !mbInitializeEventDone || GetSbData()->bRunInit ) + return; + + // Search method + SbxVariable* pMeth = SbxObject::Find( aTermMethodName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + pMeth->Get( aVals ); + } +} + + +void SbClassData::clear( void ) +{ + mxIfaces->Clear(); +} + +SbClassFactory::SbClassFactory( void ) +{ + String aDummyName; + xClassModules = new SbxObject( aDummyName ); +} + +SbClassFactory::~SbClassFactory() +{} + +SbxBase* SbClassFactory::Create( UINT16, UINT32 ) +{ + // Not supported + return NULL; +} + +SbxObject* SbClassFactory::CreateObject( const String& rClassName ) +{ + SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE ); + SbxObject* pRet = NULL; + if( pVar ) + { + SbModule* pMod = (SbModule*)pVar; + pRet = new SbClassModuleObject( pMod ); + } + return pRet; +} + +//////////////////////////////////////////////////////////////////////////// + +StarBASIC::StarBASIC( StarBASIC* p ) + : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ) +{ + SetParent( p ); + pLibInfo = NULL; + bNoRtl = bBreak = FALSE; + pModules = new SbxArray; + + if( !GetSbData()->nInst++ ) + { + pSBFAC = new SbiFactory; + AddFactory( pSBFAC ); + pUNOFAC = new SbUnoFactory; + AddFactory( pUNOFAC ); + pTYPEFAC = new SbTypeFactory; + AddFactory( pTYPEFAC ); + pCLASSFAC = new SbClassFactory; + AddFactory( pCLASSFAC ); + pOLEFAC = new SbOLEFactory; + AddFactory( pOLEFAC ); + } +// pRtl = new SbiStdObject( String( RTL_CONSTASCII_USTRINGPARAM(RTLNAME) ), this ); + // Suche ueber StarBASIC ist immer global + SetFlag( SBX_GBLSEARCH ); +} + +// #51727 SetModified ueberladen, damit der Modified- +// Zustand nicht an den Parent weitergegeben wird. +void StarBASIC::SetModified( BOOL b ) +{ + SbxBase::SetModified( b ); +} + +//*** + +StarBASIC::~StarBASIC() +{ + if( !--GetSbData()->nInst ) + { + RemoveFactory( pSBFAC ); + pSBFAC = NULL; + RemoveFactory( pUNOFAC ); + pUNOFAC = NULL; + RemoveFactory( pTYPEFAC ); + pTYPEFAC = NULL; + RemoveFactory( pCLASSFAC ); + pCLASSFAC = NULL; + RemoveFactory( pOLEFAC ); + pOLEFAC = NULL; + } + + // #100326 Set Parent NULL in registered listeners + if( xUnoListeners.Is() ) + { + USHORT uCount = xUnoListeners->Count(); + for( USHORT i = 0 ; i < uCount ; i++ ) + { + SbxVariable* pListenerObj = xUnoListeners->Get( i ); + pListenerObj->SetParent( NULL ); + } + xUnoListeners = NULL; + } +} + +// operator new() wird hier versenkt, damit jeder eine Instanz +// anlegen kann, ohne neu zu bilden. + +void* StarBASIC::operator new( size_t n ) +{ + if( n < sizeof( StarBASIC ) ) + { +// DBG_ASSERT( FALSE, "Warnung: inkompatibler BASIC-Stand!" ); + n = sizeof( StarBASIC ); + } + return ::operator new( n ); +} + +void StarBASIC::operator delete( void* p ) +{ + ::operator delete( p ); +} + +/************************************************************************** +* +* Erzeugen/Verwalten von Modulen +* +**************************************************************************/ + +SbModule* StarBASIC::MakeModule32( const String& rName, const ::rtl::OUString& rSrc ) +{ + SbModule* p = new SbModule( rName ); + p->SetSource32( rSrc ); + p->SetParent( this ); + pModules->Insert( p, pModules->Count() ); + SetModified( TRUE ); + return p; +} + +void StarBASIC::Insert( SbxVariable* pVar ) +{ + if( pVar->IsA( TYPE(SbModule) ) ) + { + pModules->Insert( pVar, pModules->Count() ); + pVar->SetParent( this ); + StartListening( pVar->GetBroadcaster(), TRUE ); + } + else + { + BOOL bWasModified = IsModified(); + SbxObject::Insert( pVar ); + if( !bWasModified && pVar->IsSet( SBX_DONTSTORE ) ) + SetModified( FALSE ); + } +} + +void StarBASIC::Remove( SbxVariable* pVar ) +{ + if( pVar->IsA( TYPE(SbModule) ) ) + { + // #87540 Can be last reference! + SbxVariableRef xVar = pVar; + pModules->Remove( pVar ); + pVar->SetParent( 0 ); + EndListening( pVar->GetBroadcaster() ); + } + else + SbxObject::Remove( pVar ); +} + +void StarBASIC::Clear() +{ + while( pModules->Count() ) + pModules->Remove( pModules->Count() - 1 ); +} + +SbModule* StarBASIC::FindModule( const String& rName ) +{ + for( USHORT i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) + return p; + } + return NULL; +} + +// Init-Code aller Module ausfuehren (auch in inserteten Bibliotheken) +void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) +{ + // Eigene Module initialisieren +/*?*/ // for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) +/*?*/ // { +/*?*/ // SbModule* pModule = (SbModule*)pModules->Get( nMod ); +/*?*/ // if( !pModule->IsCompiled() ) +/*?*/ // pModule->Compile(); +/*?*/ // pModule->RunInit(); +/*?*/ // } + DBG_ERROR( "StarBASIC::InitAllModules: dead code!" ); + // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt + // Wenn ja, auch dort initialisieren + for ( USHORT nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic && pBasic != pBasicNotToInit ) + pBasic->InitAllModules(); + } +} + +// #88329 Put modules back to not initialised state to +// force reinitialisation at next start +void StarBASIC::DeInitAllModules( void ) +{ + // Eigene Module initialisieren + for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( pModule->pImage ) + pModule->pImage->bInit = false; + } + // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt + // Wenn ja, auch dort initialisieren + for ( USHORT nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic ) + pBasic->DeInitAllModules(); + } +} + +// Diese Implementation sucht erst innerhalb der Runtime-Library, dann +// nach einem Element innerhalb eines Moduls. Dieses Element kann eine +// Public-Variable oder ein Entrypoint sein. Wenn nicht gefunden, wird, +// falls nach einer Methode gesucht wird und ein Modul mit dem angege- +// benen Namen gefunden wurde, der Entrypoint "Main" gesucht. Wenn das +// auch nicht klappt, laeuft die traditionelle Suche ueber Objekte an. + +SbxVariable* StarBASIC::Find( const String& rName, SbxClassType t ) +{ + static String aMainStr( RTL_CONSTASCII_USTRINGPARAM("Main") ); + + SbxVariable* pRes = NULL; + SbModule* pNamed = NULL; + // "Extended" search in Runtime Lib + // aber nur, wenn SbiRuntime nicht das Flag gesetzt hat + if( !bNoRtl ) + { + if( t == SbxCLASS_DONTCARE || t == SbxCLASS_OBJECT ) + { + if( rName.EqualsIgnoreCaseAscii( RTLNAME ) ) + pRes = pRtl; + } +/*?*/ // if( !pRes ) +/*?*/ // pRes = ((SbiStdObject*) (SbxObject*) pRtl)->Find( rName, t ); + if( pRes ) + pRes->SetFlag( SBX_EXTFOUND ); + } + // Module durchsuchen + if( !pRes ) + for( USHORT i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( p->IsVisible() ) + { + // Modul merken fuer Main()-Aufruf + // oder stimmt etwa der Name ueberein?!? + if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) + { + if( t == SbxCLASS_OBJECT || t == SbxCLASS_DONTCARE ) + { + pRes = p; break; + } + pNamed = p; + } + // Sonst testen, ob das Element vorhanden ist + // GBLSEARCH-Flag rausnehmen (wg. Rekursion) + USHORT nGblFlag = p->GetFlags() & SBX_GBLSEARCH; + p->ResetFlag( SBX_GBLSEARCH ); + pRes = p->Find( rName, t ); + p->SetFlag( nGblFlag ); + if( pRes ) + break; + } + } + if( !pRes && pNamed && ( t == SbxCLASS_METHOD || t == SbxCLASS_DONTCARE ) && + !pNamed->GetName().EqualsIgnoreCaseAscii( aMainStr ) ) + pRes = pNamed->Find( aMainStr, SbxCLASS_METHOD ); + if( !pRes ) + pRes = SbxObject::Find( rName, t ); + return pRes; +} + +BOOL StarBASIC::Call( const String& rName, SbxArray* pParam ) +{ + BOOL bRes = SbxObject::Call( rName, pParam ); + if( !bRes ) + { + SbxError eErr = SbxBase::GetError(); + SbxBase::ResetError(); + if( eErr != SbxERR_OK ) + RTError( (SbError)eErr, 0, 0, 0 ); + } + return bRes; +} + +void StarBASIC::Stop() +{ +/*?*/ // SbiInstance* p = pINST; +/*?*/ // while( p ) +/*?*/ // { +/*?*/ // p->Stop(); +/*?*/ // p = p->pNext; +/*?*/ // } +} + +BOOL StarBASIC::IsRunning() +{ + return BOOL( pINST != NULL ); +} + +/************************************************************************** +* +* Debugging und Fehlerbehandlung +* +**************************************************************************/ + +USHORT __EXPORT StarBASIC::BreakHdl() +{ + return (USHORT) ( aBreakHdl.IsSet() + ? aBreakHdl.Call( this ) : SbDEBUG_CONTINUE ); +} + +// AB: 29.3.96 +// Das Mapping zwischen alten und neuen Fehlercodes erfolgt, indem die Tabelle +// SFX_VB_ErrorTab[] durchsucht wird. Dies ist zwar nicht besonders performant, +// verbraucht aber viel weniger Speicher als entsprechende switch-Bloecke. +// Die Umrechnung von Fehlercodes muss nicht schnell sein, daher auch keine +// binaere Suche bei VB-Error -> SFX-Error. + +// Neue Fehler-Codes auf alte, Sbx-Kompatible zurueckmappen +USHORT StarBASIC::GetVBErrorCode( SbError nError ) +{ + USHORT nRet = 0; + + // Suchschleife + const SFX_VB_ErrorItem* pErrItem; + USHORT nIndex = 0; + do + { + pErrItem = SFX_VB_ErrorTab + nIndex; + if( pErrItem->nErrorSFX == nError ) + { + nRet = pErrItem->nErrorVB; + break; + } + nIndex++; + } + while( pErrItem->nErrorVB != 0xFFFF ); // bis End-Marke + return nRet; +} + +SbError StarBASIC::GetSfxFromVBError( USHORT nError ) +{ + SbError nRet = 0L; + + // Suchschleife + const SFX_VB_ErrorItem* pErrItem; + USHORT nIndex = 0; + do + { + pErrItem = SFX_VB_ErrorTab + nIndex; + if( pErrItem->nErrorVB == nError ) + { + nRet = pErrItem->nErrorSFX; + break; + } + else if( pErrItem->nErrorVB > nError ) + break; // kann nicht mehr gefunden werden + + nIndex++; + } + while( pErrItem->nErrorVB != 0xFFFF ); // bis End-Marke + return nRet; +} + +// Error- / Break-Daten setzen +void StarBASIC::SetErrorData +( SbError nCode, USHORT nLine, USHORT nCol1, USHORT nCol2 ) +{ + SbiGlobals& aGlobals = *GetSbData(); + aGlobals.nCode = nCode; + aGlobals.nLine = nLine; + aGlobals.nCol1 = nCol1; + aGlobals.nCol2 = nCol2; +} + +//---------------------------------------------------------------- +// Hilfsklasse zum Zugriff auf String SubResourcen einer Resource. +// Quelle: sfx2\source\doc\docfile.cxx (TLX) +struct BasicStringList_Impl : private Resource +{ + ResId aResId; + + BasicStringList_Impl( ResId& rErrIdP, USHORT nId) + : Resource( rErrIdP ),aResId(nId,*rErrIdP.GetResMgr()){} + ~BasicStringList_Impl() { FreeResource(); } + + String GetString(){ return String( aResId ); } + BOOL IsErrorTextAvailable( void ) + { return IsAvailableRes(aResId.SetRT(RSC_STRING)); } +}; +//---------------------------------------------------------------- + +// #60175 Flag, das bei Basic-Fehlern das Anziehen der SFX-Resourcen verhindert +static BOOL bStaticSuppressSfxResource = FALSE; + +void StarBASIC::MakeErrorText( SbError nId, const String& /*aMsg*/ ) +{ + SolarMutexGuard aSolarGuard; + + if( bStaticSuppressSfxResource ) + { + GetSbData()->aErrMsg = String( RTL_CONSTASCII_USTRINGPARAM("No resource: Error message not available") ); + return; + } + + USHORT nOldID = GetVBErrorCode( nId ); + + // Hilfsklasse instanzieren +/*?*/ // BasicResId aId( RID_BASIC_START ); +/*?*/ // BasicStringList_Impl aMyStringList( aId, USHORT(nId & ERRCODE_RES_MASK) ); + +/*?*/ // if( aMyStringList.IsErrorTextAvailable() ) +/*?*/ ///*?*/ // { +/*?*/ // // Merge Message mit Zusatztext +/*?*/ // String aMsg1 = aMyStringList.GetString(); +/*?*/ // // Argument-Platzhalter durch %s ersetzen +/*?*/ // String aSrgStr( RTL_CONSTASCII_USTRINGPARAM("$(ARG1)") ); +/*?*/ // USHORT nResult = aMsg1.Search( aSrgStr ); +/*?*/ // +/*?*/ // if( nResult != STRING_NOTFOUND ) +/*?*/ // { +/*?*/ // aMsg1.Erase( nResult, aSrgStr.Len() ); +/*?*/ // aMsg1.Insert( aMsg, nResult ); +/*?*/ // } +/*?*/ // GetSbData()->aErrMsg = aMsg1; +/*?*/ // } +/*?*/ // else if( nOldID != 0 ) + if( nOldID != 0 ) + { + String aStdMsg( RTL_CONSTASCII_USTRINGPARAM("error ") ); + aStdMsg += String::CreateFromInt32( nOldID); + aStdMsg += String( RTL_CONSTASCII_USTRINGPARAM(": no error message available!") ); + GetSbData()->aErrMsg = aStdMsg; + } + else + GetSbData()->aErrMsg = String::EmptyString(); +} + +BOOL StarBASIC::CError + ( SbError code, const String& rMsg, USHORT l, USHORT c1, USHORT c2 ) +{ + SolarMutexGuard aSolarGuard; + + // Compiler-Fehler waehrend der Laufzeit -> Programm anhalten + if( IsRunning() ) + { + // #109018 Check if running Basic is affected +/*?*/ // StarBASIC* pStartedBasic = pINST->GetBasic(); +/*?*/ // if( pStartedBasic != this ) +/*?*/ // return FALSE; + + Stop(); + } + + // Flag setzen, damit GlobalRunInit den Fehler mitbekommt + GetSbData()->bGlobalInitErr = TRUE; + + // Fehlertext basteln + MakeErrorText( code, rMsg ); + + // Umsetzung des Codes fuer String-Transport in SFX-Error + if( rMsg.Len() ) + code = (ULONG)*new StringErrorInfo( code, String(rMsg) ); + + SetErrorData( code, l, c1, c2 ); + GetSbData()->bCompiler = TRUE; + BOOL bRet; + if( GetSbData()->aErrHdl.IsSet() ) + bRet = (BOOL) GetSbData()->aErrHdl.Call( this ); + else + bRet = ErrorHdl(); + GetSbData()->bCompiler = FALSE; // nur TRUE fuer Error-Handler + return bRet; +} + +BOOL StarBASIC::RTError + ( SbError code, USHORT l, USHORT c1, USHORT c2 ) +{ + return RTError( code, String(), l, c1, c2 ); +} + +BOOL StarBASIC::RTError( SbError code, const String& rMsg, USHORT l, USHORT c1, USHORT c2 ) +{ + SolarMutexGuard aSolarGuard; + + SbError c = code; + if( (c & ERRCODE_CLASS_MASK) == ERRCODE_CLASS_COMPILER ) + c = 0; + MakeErrorText( c, rMsg ); + + // Umsetzung des Codes fuer String-Transport in SFX-Error + if( rMsg.Len() ) + code = (ULONG)*new StringErrorInfo( code, String(rMsg) ); + + SetErrorData( code, l, c1, c2 ); + if( GetSbData()->aErrHdl.IsSet() ) + return (BOOL) GetSbData()->aErrHdl.Call( this ); + else + return ErrorHdl(); +} + +void StarBASIC::Error( SbError n ) +{ + Error( n, String() ); +} + +void StarBASIC::Error( SbError /*n*/, const String& /*rMsg*/ ) +{ +/*?*/ // if( pINST ) +/*?*/ // pINST->Error( n, rMsg ); +} + +void StarBASIC::FatalError( SbError /*n*/ ) +{ +/*?*/ // if( pINST ) +/*?*/ // pINST->FatalError( n ); +} + +BOOL __EXPORT StarBASIC::ErrorHdl() +{ + return (BOOL) ( aErrorHdl.IsSet() + ? aErrorHdl.Call( this ) : FALSE ); +} + +/************************************************************************** +* +* Laden und Speichern +* +**************************************************************************/ + +BOOL StarBASIC::LoadData( SvStream& r, USHORT nVer ) +{ + if( !SbxObject::LoadData( r, nVer ) ) + return FALSE; + + // #95459 Delete dialogs, otherwise endless recursion + // in SbxVarable::GetType() if dialogs are accessed + USHORT nObjCount = pObjs->Count(); + SbxVariable** ppDeleteTab = new SbxVariable*[ nObjCount ]; + USHORT nObj; + + for( nObj = 0 ; nObj < nObjCount ; nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST( StarBASIC, pVar ); + ppDeleteTab[nObj] = pBasic ? NULL : pVar; + } + for( nObj = 0 ; nObj < nObjCount ; nObj++ ) + { + SbxVariable* pVar = ppDeleteTab[nObj]; + if( pVar ) + pObjs->Remove( pVar ); + } + delete[] ppDeleteTab; + + UINT16 nMod; + pModules->Clear(); + r >> nMod; + for( USHORT i = 0; i < nMod; i++ ) + { + SbModule* pMod = (SbModule*) SbxBase::Load( r ); + if( !pMod ) + return FALSE; + else if( pMod->ISA(SbJScriptModule) ) + { + // Ref zuweisen, damit pMod deleted wird + SbModuleRef xRef = pMod; + } + else + { + pMod->SetParent( this ); + pModules->Put( pMod, i ); + } + } + // HACK fuer SFX-Mist! + SbxVariable* p = Find( String( RTL_CONSTASCII_USTRINGPARAM("FALSE") ), SbxCLASS_PROPERTY ); + if( p ) + Remove( p ); + p = Find( String( RTL_CONSTASCII_USTRINGPARAM("TRUE") ), SbxCLASS_PROPERTY ); + if( p ) + Remove( p ); + // Ende des Hacks! + // Suche ueber StarBASIC ist immer global + DBG_ASSERT( IsSet( SBX_GBLSEARCH ), "Basic ohne GBLSEARCH geladen" ); + SetFlag( SBX_GBLSEARCH ); + return TRUE; +} + +BOOL StarBASIC::StoreData( SvStream& r ) const +{ + if( !SbxObject::StoreData( r ) ) + return FALSE; + r << (UINT16) pModules->Count(); + for( USHORT i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( !p->Store( r ) ) + return FALSE; + } + return TRUE; +} + +//======================================================================== +// #118116 Implementation Collection object + +TYPEINIT1(BasicCollection,SbxObject) + +static const char pCountStr[] = "Count"; +static const char pAddStr[] = "Add"; +static const char pItemStr[] = "Item"; +static const char pRemoveStr[] = "Remove"; +static USHORT nCountHash = 0, nAddHash, nItemHash, nRemoveHash; + +BasicCollection::BasicCollection( const XubString& rClass ) + : SbxObject( rClass ) +{ + if( !nCountHash ) + { + nCountHash = MakeHashCode( String::CreateFromAscii( pCountStr ) ); + nAddHash = MakeHashCode( String::CreateFromAscii( pAddStr ) ); + nItemHash = MakeHashCode( String::CreateFromAscii( pItemStr ) ); + nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemoveStr ) ); + } + Initialize(); +} + +BasicCollection::~BasicCollection() +{} + +void BasicCollection::Clear() +{ + SbxObject::Clear(); + Initialize(); +} + +void BasicCollection::Initialize() +{ + xItemArray = new SbxArray(); + SetType( SbxOBJECT ); + SetFlag( SBX_FIXED ); + ResetFlag( SBX_WRITE ); + SbxVariable* p; + p = Make( String::CreateFromAscii( pCountStr ), SbxCLASS_PROPERTY, SbxINTEGER ); + p->ResetFlag( SBX_WRITE ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pAddStr ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pItemStr ), SbxCLASS_METHOD, SbxVARIANT ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pRemoveStr ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); +} + +SbxVariable* BasicCollection::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pFind = SbxObject::Find( rName, t ); + return pFind; +} + +void BasicCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1, + const SfxHint& rHint, const TypeId& rId2 ) +{ + const SbxHint* p = PTR_CAST(SbxHint,&rHint); + if( p ) + { + ULONG nId = p->GetId(); + BOOL bRead = BOOL( nId == SBX_HINT_DATAWANTED ); + BOOL bWrite = BOOL( nId == SBX_HINT_DATACHANGED ); + SbxVariable* pVar = p->GetVar(); + SbxArray* pArg = pVar->GetParameters(); + if( bRead || bWrite ) + { + XubString aVarName( pVar->GetName() ); + if( pVar->GetHashCode() == nCountHash + && aVarName.EqualsIgnoreCaseAscii( pCountStr ) ) + pVar->PutLong( xItemArray->Count32() ); + else if( pVar->GetHashCode() == nAddHash + && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) + CollAdd( pArg ); + else if( pVar->GetHashCode() == nItemHash + && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) + CollItem( pArg ); + else if( pVar->GetHashCode() == nRemoveHash + && aVarName.EqualsIgnoreCaseAscii( pRemoveStr ) ) + CollRemove( pArg ); + else + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); + return; + } + } + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); +} + +INT32 BasicCollection::implGetIndex( SbxVariable* pIndexVar ) +{ + INT32 nIndex = -1; + if( pIndexVar->GetType() == SbxSTRING ) + nIndex = implGetIndexForName( pIndexVar->GetString() ); + else + nIndex = pIndexVar->GetLong() - 1; + return nIndex; +} + +INT32 BasicCollection::implGetIndexForName( const String& rName ) +{ + INT32 nIndex = -1; + INT32 nCount = xItemArray->Count32(); + INT32 nNameHash = MakeHashCode( rName ); + for( INT32 i = 0 ; i < nCount ; i++ ) + { + SbxVariable* pVar = xItemArray->Get32( i ); + if( pVar->GetHashCode() == nNameHash && + pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) + { + nIndex = i; + break; + } + } + return nIndex; +} + +void BasicCollection::CollAdd( SbxArray* pPar_ ) +{ + USHORT nCount = pPar_->Count(); + if( nCount < 2 || nCount > 5 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + + SbxVariable* pItem = pPar_->Get(1); + if( pItem ) + { + int nNextIndex; + if( nCount < 4 ) + { + nNextIndex = xItemArray->Count(); + } + else + { + SbxVariable* pBefore = pPar_->Get(3); + if( nCount == 5 ) + { + if( !pBefore->IsErr() ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + SbxVariable* pAfter = pPar_->Get(4); + INT32 nAfterIndex = implGetIndex( pAfter ); + if( nAfterIndex == -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + nNextIndex = nAfterIndex + 1; + } + else // if( nCount == 4 ) + { + INT32 nBeforeIndex = implGetIndex( pBefore ); + if( nBeforeIndex == -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + nNextIndex = nBeforeIndex; + } + } + + SbxVariableRef pNewItem = new SbxVariable( *pItem ); + if( nCount >= 3 ) + { + SbxVariable* pKey = pPar_->Get(2); + if( !pKey->IsErr() ) + { + if( pKey->GetType() != SbxSTRING ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + String aKey = pKey->GetString(); + if( implGetIndexForName( aKey ) != -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + pNewItem->SetName( aKey ); + } + } + pNewItem->SetFlag( SBX_READWRITE ); + xItemArray->Insert32( pNewItem, nNextIndex ); + } + else + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } +} + +void BasicCollection::CollItem( SbxArray* pPar_ ) +{ + if( pPar_->Count() != 2 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + SbxVariable* pRes = NULL; + SbxVariable* p = pPar_->Get( 1 ); + INT32 nIndex = implGetIndex( p ); + if( nIndex >= 0 && nIndex < (INT32)xItemArray->Count32() ) + pRes = xItemArray->Get32( nIndex ); + if( !pRes ) + SetError( SbxERR_BAD_INDEX ); + *(pPar_->Get(0)) = *pRes; +} + +void BasicCollection::CollRemove( SbxArray* pPar_ ) +{ + if( pPar_ == NULL || pPar_->Count() != 2 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + + SbxVariable* p = pPar_->Get( 1 ); + INT32 nIndex = implGetIndex( p ); + if( nIndex >= 0 && nIndex < (INT32)xItemArray->Count32() ) + xItemArray->Remove32( nIndex ); + else + SetError( SbxERR_BAD_INDEX ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/classes/sbintern.cxx b/binfilter/bf_basic/source/classes/sbintern.cxx new file mode 100644 index 000000000000..1fdb6f5c1cde --- /dev/null +++ b/binfilter/bf_basic/source/classes/sbintern.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sbintern.hxx" +#include "sbunoobj.hxx" +#include "token.hxx" // Tokenizer +#include "codegen.hxx" // Code-Generator +#include "basmgr.hxx" + +namespace binfilter { + +SV_IMPL_PTRARR(SbErrorStack, SbErrorStackEntry*) + +SbiGlobals* GetSbData() +{ + DBG_TESTSOLARMUTEX(); + static SbiGlobals* s_pGlobals = new SbiGlobals; + return s_pGlobals; +} + +SbiGlobals::SbiGlobals() +{ + pInst = NULL; + pMod = NULL; + pSbFac= NULL; + pUnoFac = NULL; + pTypeFac = NULL; + pOLEFac = NULL; + pCompMod = NULL; // JSM + nInst = 0; + nCode = 0; + nLine = 0; + nCol1 = nCol2 = 0; + bCompiler = FALSE; + bGlobalInitErr = FALSE; + bRunInit = FALSE; + eLanguageMode = SB_LANG_BASIC; + pErrStack = NULL; + pTransliterationWrapper = NULL; + bBlockCompilerError = FALSE; + pAppBasMgr = NULL; +} + +SbiGlobals::~SbiGlobals() +{ + delete pErrStack; + delete pSbFac; + delete pUnoFac; + delete pTransliterationWrapper; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/classes/sbunoobj.cxx b/binfilter/bf_basic/source/classes/sbunoobj.cxx new file mode 100644 index 000000000000..4853691c678d --- /dev/null +++ b/binfilter/bf_basic/source/classes/sbunoobj.cxx @@ -0,0 +1,2710 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <tools/errcode.hxx> +#include <bf_svtools/hint.hxx> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/extract.hxx> + +#include <comphelper/processfactory.hxx> + +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> + +#include <com/sun/star/script/ArrayWrapper.hpp> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/uno/DeploymentException.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyConcept.hpp> +#include <com/sun/star/beans/MethodConcept.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/script/BasicErrorException.hpp> +#include <com/sun/star/script/XAllListener.hpp> +#include <com/sun/star/script/XInvocationAdapterFactory.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/script/XDefaultProperty.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/reflection/XIdlArray.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +#include <com/sun/star/reflection/XIdlClassProvider.hpp> +#include <com/sun/star/reflection/XTypeDescription.hpp> +#include <com/sun/star/bridge/oleautomation/NamedArgument.hpp> +#include <com/sun/star/bridge/oleautomation/Date.hpp> +#include <com/sun/star/bridge/oleautomation/Decimal.hpp> +#include <com/sun/star/bridge/oleautomation/Currency.hpp> + + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::beans; +using namespace com::sun::star::script; +using namespace com::sun::star::container; +using namespace com::sun::star::bridge; +using namespace cppu; +using namespace rtl; + + +#include "sbstar.hxx" +#include "sberrors.hxx" +#include "sbunoobj.hxx" +#include "sbjsmod.hxx" +#include "basmgr.hxx" +#include "sbintern.hxx" + +#include<math.h> + +namespace binfilter { + +TYPEINIT1(SbUnoMethod,SbxMethod) +TYPEINIT1(SbUnoProperty,SbxProperty) +TYPEINIT1(SbUnoObject,SbxObject) +TYPEINIT1(SbUnoClass,SbxObject) + +typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper; + +// Flag, um immer ueber Invocation zu gehen +//#define INVOCATION_ONLY + + +// Identifier fuer die dbg_-Properies als Strings anlegen +static String ID_DBG_SUPPORTEDINTERFACES( RTL_CONSTASCII_USTRINGPARAM("Dbg_SupportedInterfaces") ); +static String ID_DBG_PROPERTIES( RTL_CONSTASCII_USTRINGPARAM("Dbg_Properties") ); +static String ID_DBG_METHODS( RTL_CONSTASCII_USTRINGPARAM("Dbg_Methods") ); + +static String aIllegalArgumentExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) ); +static OUString aSeqLevelStr( RTL_CONSTASCII_USTRINGPARAM("[]") ); + +Reference< XComponentContext > getComponentContext_Impl( void ) +{ + static Reference< XComponentContext > xContext; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xContext.is() ) + { + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; + OSL_ASSERT( xContext.is() ); + } + } + return xContext; +} + +// CoreReflection statisch speichern +Reference< XIdlReflection > getCoreReflection_Impl( void ) +{ + static Reference< XIdlReflection > xCoreReflection; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xCoreReflection.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + xContext->getValueByName( + OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) ) + >>= xCoreReflection; + OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessable!?" ); + } + if( !xCoreReflection.is() ) + { + throw DeploymentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessable") ), + Reference< XInterface >() ); + } + } + return xCoreReflection; +} + +// CoreReflection statisch speichern +Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl( void ) +{ + static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess; + + if( !xCoreReflection_HierarchicalNameAccess.is() ) + { + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( xCoreReflection.is() ) + { + xCoreReflection_HierarchicalNameAccess = + Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY ); + } + } + return xCoreReflection_HierarchicalNameAccess; +} + +// Hold TypeProvider statically +Reference< XHierarchicalNameAccess > getTypeProvider_Impl( void ) +{ + static Reference< XHierarchicalNameAccess > xAccess; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xAccess.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + xContext->getValueByName( + OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) ) + >>= xAccess; + OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessable!?" ); + } + if( !xAccess.is() ) + { + throw DeploymentException( + OUString( RTL_CONSTASCII_USTRINGPARAM + ("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessable") ), + Reference< XInterface >() ); + } + } + return xAccess; +} + +// #111851 factory function to create an OLE object +SbUnoObject* createOLEObject_Impl( const String& aType ) +{ + static Reference< XMultiServiceFactory > xOLEFactory; + static bool bNeedsInit = true; + + if( bNeedsInit ) + { + bNeedsInit = false; + + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); + xOLEFactory = Reference<XMultiServiceFactory>( + xSMgr->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.OleObjectFactory")), + xContext ), UNO_QUERY ); + } + } + + SbUnoObject* pUnoObj = NULL; + if( xOLEFactory.is() ) + { + Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aType ); + if( xOLEObject.is() ) + { + Any aAny; + aAny <<= xOLEObject; + pUnoObj = new SbUnoObject( aType, aAny ); + } + } + return pUnoObj; +} + + +String implGetExceptionMsg( Exception& e, const String& aExceptionType_ ); + +// #105565 Special Object to wrap a strongly typed Uno Any +TYPEINIT1(SbUnoAnyObject,SbxObject) + +// TODO: Spaeter auslagern +Reference<XIdlClass> TypeToIdlClass( const Type& rType ) +{ + // void als Default-Klasse eintragen + Reference<XIdlClass> xRetClass; + typelib_TypeDescription * pTD = 0; + rType.getDescription( &pTD ); + + if( pTD ) + { + OUString sOWName( pTD->pTypeName ); + Reference< XIdlReflection > xRefl = getCoreReflection_Impl(); + xRetClass = xRefl->forName( sOWName ); + } + return xRetClass; +} + +// Fehlermeldungs-Message bei Exception zusammenbauen +String implGetExceptionMsg( Exception& e, const String& aExceptionType_ ) +{ + String aExceptionType = aExceptionType_; + if( aExceptionType.Len() == 0 ) + aExceptionType = String( RTL_CONSTASCII_USTRINGPARAM("Unknown" ) ); + + String aTypeLine( RTL_CONSTASCII_USTRINGPARAM("\nType: " ) ); + aTypeLine += aExceptionType; + + String aMessageLine( RTL_CONSTASCII_USTRINGPARAM("\nMessage: " ) ); + aMessageLine += String( e.Message ); + + String aMsg = aTypeLine; + aMsg += aMessageLine; + return aMsg; +} + +// Exception type unknown +String implGetExceptionMsg( Exception& e ) +{ + String aMsg = implGetExceptionMsg( e, String() ); + return aMsg; +} + +// Error-Message fuer WrappedTargetExceptions +String implGetWrappedMsg( WrappedTargetException& e ) +{ + String aMsg; + Any aWrappedAny = e.TargetException; + Type aExceptionType = aWrappedAny.getValueType(); + + // Really an Exception? + if( aExceptionType.getTypeClass() == TypeClass_EXCEPTION ) + { + RuntimeException& e_ = *( (RuntimeException*)aWrappedAny.getValue() ); + aMsg = implGetExceptionMsg( e_, String( aExceptionType.getTypeName() ) ); + } + // Otherwise use WrappedTargetException itself + else + { + aMsg = implGetExceptionMsg( e ); + } + + return aMsg; +} + +void implHandleBasicErrorException( BasicErrorException& e ) +{ + SbError nError = StarBASIC::GetSfxFromVBError( (USHORT)e.ErrorCode ); + StarBASIC::Error( nError, e.ErrorMessageArgument ); +} + +void implHandleWrappedTargetException( WrappedTargetException& e ) +{ + SbError nError; + String aMessage; + Any aWrappedAny = e.TargetException; + if ( aWrappedAny.getValueType() == ::getCppuType( (BasicErrorException*)NULL ) ) + { + BasicErrorException& be = *( (BasicErrorException*)aWrappedAny.getValue() ); + nError = StarBASIC::GetSfxFromVBError( (USHORT)be.ErrorCode ); + aMessage = be.ErrorMessageArgument; + } + else + { + nError = ERRCODE_BASIC_EXCEPTION; + aMessage = implGetWrappedMsg( e ); + } + StarBASIC::Error( nError, aMessage ); +} + +// Von Uno nach Sbx wandeln +SbxDataType unoToSbxType( TypeClass eType ) +{ + SbxDataType eRetType = SbxVOID; + + switch( eType ) + { + case TypeClass_INTERFACE: + case TypeClass_TYPE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ARRAY: break; + */ + case TypeClass_ENUM: eRetType = SbxLONG; break; + case TypeClass_SEQUENCE: + eRetType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: break; + */ + + case TypeClass_ANY: eRetType = SbxVARIANT; break; + case TypeClass_BOOLEAN: eRetType = SbxBOOL; break; + case TypeClass_CHAR: eRetType = SbxCHAR; break; + case TypeClass_STRING: eRetType = SbxSTRING; break; + case TypeClass_FLOAT: eRetType = SbxSINGLE; break; + case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break; + //case TypeClass_OCTET: break; + case TypeClass_BYTE: eRetType = SbxINTEGER; break; + //case TypeClass_INT: eRetType = SbxINT; break; + case TypeClass_SHORT: eRetType = SbxINTEGER; break; + case TypeClass_LONG: eRetType = SbxLONG; break; + case TypeClass_HYPER: eRetType = SbxSALINT64; break; + //case TypeClass_UNSIGNED_OCTET: break; + case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break; + case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break; + case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break; + //case TypeClass_UNSIGNED_INT: eRetType = SbxUINT; break; + //case TypeClass_UNSIGNED_BYTE: eRetType = SbxUSHORT; break; + default: break; + } + return eRetType; +} + +SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass ) +{ + SbxDataType eRetType = SbxVOID; + if( xIdlClass.is() ) + { + TypeClass eType = xIdlClass->getTypeClass(); + eRetType = unoToSbxType( eType ); + } + return eRetType; +} +void unoToSbxValue( SbxVariable* pVar, const Any& aValue ); +static void implSequenceToMultiDimArray( SbxDimArray*& pArray, Sequence< sal_Int32 >& indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32& dimension, sal_Bool bIsZeroIndex ) +{ + Type aType = aValue.getValueType(); + TypeClass eTypeClass = aType.getTypeClass(); + + sal_Int32 indicesIndex = indices.getLength() -1; + sal_Int32 dimCopy = dimension; + + if ( eTypeClass == TypeClass_SEQUENCE ) + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); + Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); + sal_Int32 nLen = xIdlArray->getLen( aValue ); + for ( sal_Int32 index = 0; index < nLen; ++index ) + { + Any aElementAny = xIdlArray->get( aValue, (UINT32)index ); + // This detects the dimension were currently processing + if ( dimCopy == dimension ) + { + ++dimCopy; + if ( sizes.getLength() < dimCopy ) + { + sizes.realloc( sizes.getLength() + 1 ); + sizes[ sizes.getLength() - 1 ] = nLen; + indices.realloc( indices.getLength() + 1 ); + indicesIndex = indices.getLength() - 1; + } + } + + if ( bIsZeroIndex ) + indices[ dimCopy - 1 ] = index; + else + indices[ dimCopy - 1] = index + 1; + + implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex ); + } + + } + else + { + if ( indices.getLength() < 1 ) + { + // Should never ever get here ( indices.getLength() + // should equal number of dimensions in the array ) + // And that should at least be 1 ! + // #QUESTION is there a better error? + StarBASIC::Error( SbERR_INVALID_OBJECT ); + return; + } + + if ( !pArray ) + { + SbxDataType eSbxElementType = unoToSbxType( aValue.getValueTypeClass() ); + pArray = new SbxDimArray( eSbxElementType ); + sal_Int32 nIndexLen = indices.getLength(); + + // Dimension the array + for ( sal_Int32 index = 0; index < nIndexLen; ++index ) + { + if ( bIsZeroIndex ) + pArray->unoAddDim32( 0, sizes[ index ] - 1); + else + pArray->unoAddDim32( 1, sizes[ index ] ); + + } + } + + if ( pArray ) + { + SbxDataType eSbxElementType = unoToSbxType( aValue.getValueTypeClass() ); + SbxVariableRef xVar = new SbxVariable( eSbxElementType ); + unoToSbxValue( (SbxVariable*)xVar, aValue ); + + sal_Int32* pIndices = indices.getArray(); + pArray->Put32( (SbxVariable*)xVar, pIndices ); + + } + } +} + +void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) +{ + Type aType = aValue.getValueType(); + TypeClass eTypeClass = aType.getTypeClass(); + switch( eTypeClass ) + { + case TypeClass_TYPE: + { + // Map Type to IdlClass + Type aType_; + aValue >>= aType_; + Reference<XIdlClass> xClass = TypeToIdlClass( aType_ ); + Any aClassAny; + aClassAny <<= xClass; + + // SbUnoObject instanzieren + String aName; + SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny ); + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + + // #51475 Wenn das Objekt ungueltig ist null liefern + if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID ) + { + pVar->PutObject( NULL ); + } + else + { + pVar->PutObject( xWrapper ); + } + } + break; + // Interfaces und Structs muessen in ein SbUnoObject gewrappt werden + case TypeClass_INTERFACE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + { + if( eTypeClass == TypeClass_STRUCT ) + { + ArrayWrapper aWrap; + if ( (aValue >>= aWrap) ) + { + SbxDimArray* pArray = NULL; + Sequence< sal_Int32 > indices; + Sequence< sal_Int32 > sizes; + sal_Int32 dimension = 0; + implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, dimension, aWrap.IsZeroIndex ); + if ( pArray ) + { + SbxDimArrayRef xArray = pArray; + USHORT nFlags = pVar->GetFlags(); + pVar->ResetFlag( SBX_FIXED ); + pVar->PutObject( (SbxDimArray*)xArray ); + pVar->SetFlags( nFlags ); + } + else + pVar->PutEmpty(); + break; + } + } + // SbUnoObject instanzieren + String aName; + SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aValue ); + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + + // #51475 Wenn das Objekt ungueltig ist null liefern + if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID ) + { + pVar->PutObject( NULL ); + } + else + { + pVar->PutObject( xWrapper ); + } + } + break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_ARRAY: break; + */ + + case TypeClass_ENUM: + { + sal_Int32 nEnum = 0; + enum2int( nEnum, aValue ); + pVar->PutLong( nEnum ); + } + break; + + case TypeClass_SEQUENCE: + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); + Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); + sal_Int32 i, nLen = xIdlArray->getLen( aValue ); + + typelib_TypeDescription * pTD = 0; + aType.getDescription( &pTD ); + OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE ); + Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType ); + ::typelib_typedescription_release( pTD ); + + // In Basic Array anlegen + SbxDimArrayRef xArray; + SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() ); + xArray = new SbxDimArray( eSbxElementType ); + if( nLen > 0 ) + { + xArray->unoAddDim32( 0, nLen - 1 ); + + // Elemente als Variablen eintragen + for( i = 0 ; i < nLen ; i++ ) + { + // Elemente wandeln + Any aElementAny = xIdlArray->get( aValue, (UINT32)i ); + SbxVariableRef xVar = new SbxVariable( eSbxElementType ); + unoToSbxValue( (SbxVariable*)xVar, aElementAny ); + + // Ins Array braten + xArray->Put32( (SbxVariable*)xVar, &i ); + } + } + else + { + xArray->unoAddDim( 0, -1 ); + } + + // Array zurueckliefern + USHORT nFlags = pVar->GetFlags(); + pVar->ResetFlag( SBX_FIXED ); + pVar->PutObject( (SbxDimArray*)xArray ); + pVar->SetFlags( nFlags ); + + // #54548, Die Parameter duerfen hier nicht weggehauen werden + //pVar->SetParameters( NULL ); + } + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: break; + + case TypeClass_ANY: + { + // Any rausholen und konvertieren + //Any* pAny = (Any*)aValue.get(); + //if( pAny ) + //unoToSbxValue( pVar, *pAny ); + } + break; + */ + + case TypeClass_BOOLEAN: pVar->PutBool( *(sal_Bool*)aValue.getValue() ); break; + case TypeClass_CHAR: + { + pVar->PutChar( *(sal_Unicode*)aValue.getValue() ); + break; + } + case TypeClass_STRING: { OUString val; aValue >>= val; pVar->PutString( String( val ) ); } break; + case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break; + case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break; + //case TypeClass_OCTET: break; + case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; + //case TypeClass_INT: break; + case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; + case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break; + case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break; + //case TypeClass_UNSIGNED_OCTET:break; + case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break; + case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break; + case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break; + //case TypeClass_UNSIGNED_INT: break; + //case TypeClass_UNSIGNED_BYTE: break; + default: pVar->PutEmpty(); break; + } +} + +// Reflection fuer Sbx-Typen liefern +Type getUnoTypeForSbxBaseType( SbxDataType eType ) +{ + Type aRetType = getCppuVoidType(); + switch( eType ) + { + //case SbxEMPTY: eRet = TypeClass_VOID; break; + case SbxNULL: aRetType = ::getCppuType( (const Reference< XInterface > *)0 ); break; + case SbxINTEGER: aRetType = ::getCppuType( (sal_Int16*)0 ); break; + case SbxLONG: aRetType = ::getCppuType( (sal_Int32*)0 ); break; + case SbxSINGLE: aRetType = ::getCppuType( (float*)0 ); break; + case SbxDOUBLE: aRetType = ::getCppuType( (double*)0 ); break; + case SbxCURRENCY: aRetType = ::getCppuType( (oleautomation::Currency*)0 ); break; + case SbxDECIMAL: aRetType = ::getCppuType( (oleautomation::Decimal*)0 ); break; + case SbxDATE: { +/*?*/ // SbiInstance* pInst = pINST; +/*?*/ // if( pInst && pInst->IsCompatibility() ) +/*?*/ // aRetType = ::getCppuType( (double*)0 ); +/*?*/ // else + aRetType = ::getCppuType( (oleautomation::Date*)0 ); + } + break; + // case SbxDATE: aRetType = ::getCppuType( (double*)0 ); break; + case SbxSTRING: aRetType = ::getCppuType( (OUString*)0 ); break; + //case SbxOBJECT: break; + //case SbxERROR: break; + case SbxBOOL: aRetType = ::getCppuType( (sal_Bool*)0 ); break; + case SbxVARIANT: aRetType = ::getCppuType( (Any*)0 ); break; + //case SbxDATAOBJECT: break; + case SbxCHAR: aRetType = ::getCppuType( (sal_Unicode*)0 ); break; + case SbxBYTE: aRetType = ::getCppuType( (sal_Int16*)0 ); break; + case SbxUSHORT: aRetType = ::getCppuType( (sal_uInt16*)0 ); break; + case SbxULONG: aRetType = ::getCppuType( (sal_uInt32*)0 ); break; + //case SbxLONG64: break; + //case SbxULONG64: break; + // Maschinenabhaengige zur Sicherheit auf Hyper abbilden + case SbxINT: aRetType = ::getCppuType( (sal_Int32*)0 ); break; + case SbxUINT: aRetType = ::getCppuType( (sal_uInt32*)0 ); break; + //case SbxVOID: break; + //case SbxHRESULT: break; + //case SbxPOINTER: break; + //case SbxDIMARRAY: break; + //case SbxCARRAY: break; + //case SbxUSERDEF: break; + //case SbxLPSTR: break; + //case SbxLPWSTR: break; + //case SbxCoreSTRING: break; + default: break; + } + return aRetType; +} + +// Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY +Type getUnoTypeForSbxValue( SbxValue* pVal ) +{ + Type aRetType = getCppuVoidType(); + if( !pVal ) + return aRetType; + + // SbxType nach Uno wandeln + SbxDataType eBaseType = pVal->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVal->GetObject(); + if( !xObj ) + { + // #109936 No error any more + // StarBASIC::Error( SbERR_INVALID_OBJECT ); + aRetType = getCppuType( static_cast<Reference<XInterface> *>(0) ); + return aRetType; + } + + if( xObj->ISA(SbxDimArray) ) + { + SbxBase* pObj = (SbxBase*)xObj; + SbxDimArray* pArray = (SbxDimArray*)pObj; + + short nDims = pArray->GetDims(); + Type aElementType = getUnoTypeForSbxBaseType( (SbxDataType)(pArray->GetType() & 0xfff) ); + TypeClass eElementTypeClass = aElementType.getTypeClass(); + + // Normal case: One dimensional array + sal_Int32 nLower, nUpper; + if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) + { + if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) + { + // Wenn alle Elemente des Arrays vom gleichen Typ sind, wird + // der genommen, sonst wird das ganze als Any-Sequence betrachtet + sal_Bool bNeedsInit = sal_True; + + INT32 nSize = nUpper - nLower + 1; + INT32 nIdx = nLower; + for( INT32 i = 0 ; i < nSize ; i++,nIdx++ ) + { + SbxVariableRef xVar = pArray->Get32( &nIdx ); + Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar ); + if( bNeedsInit ) + { + if( aType.getTypeClass() == TypeClass_VOID ) + { + // #88522 + // if only first element is void: different types -> []any + // if all elements are void: []void is not allowed -> []any + aElementType = getCppuType( (Any*)0 ); + break; + } + aElementType = aType; + bNeedsInit = sal_False; + } + else if( aElementType != aType ) + { + // Verschiedene Typen -> AnySequence + aElementType = getCppuType( (Any*)0 ); + break; + } + } + } + + OUString aSeqTypeName( aSeqLevelStr ); + aSeqTypeName += aElementType.getTypeName(); + aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); + } + // #i33795 Map also multi dimensional arrays to corresponding sequences + else if( nDims > 1 ) + { + if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) + { + // For this check the array's dim structure does not matter + UINT32 nFlatArraySize = pArray->Count32(); + + sal_Bool bNeedsInit = sal_True; + for( UINT32 i = 0 ; i < nFlatArraySize ; i++ ) + { + SbxVariableRef xVar = pArray->SbxArray::Get32( i ); + Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar ); + if( bNeedsInit ) + { + if( aType.getTypeClass() == TypeClass_VOID ) + { + // if only first element is void: different types -> []any + // if all elements are void: []void is not allowed -> []any + aElementType = getCppuType( (Any*)0 ); + break; + } + aElementType = aType; + bNeedsInit = sal_False; + } + else if( aElementType != aType ) + { + // Verschiedene Typen -> AnySequence + aElementType = getCppuType( (Any*)0 ); + break; + } + } + } + + OUString aSeqTypeName; + for( short iDim = 0 ; iDim < nDims ; iDim++ ) + aSeqTypeName += aSeqLevelStr; + aSeqTypeName += aElementType.getTypeName(); + aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); + } + } + // Kein Array, sondern... + else if( xObj->ISA(SbUnoObject) ) + { + aRetType = ((SbUnoObject*)(SbxBase*)xObj)->getUnoAny().getValueType(); + } + // SbUnoAnyObject? + else if( xObj->ISA(SbUnoAnyObject) ) + { + aRetType = ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue().getValueType(); + } + // Sonst ist es ein Nicht-Uno-Basic-Objekt -> default==void liefern + } + // Kein Objekt, Basistyp konvertieren + else + { + aRetType = getUnoTypeForSbxBaseType( eBaseType ); + } + return aRetType; +} + +// Deklaration Konvertierung von Sbx nach Uno mit bekannter Zielklasse +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty = NULL ); + +// Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY +Any sbxToUnoValueImpl( SbxVariable* pVar, bool bBlockConversionToSmallestType = false ) +{ + SbxDataType eBaseType = pVar->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj.Is() && xObj->ISA(SbUnoAnyObject) ) + return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue(); + } + + Type aType = getUnoTypeForSbxValue( pVar ); + TypeClass eType = aType.getTypeClass(); + + if( !bBlockConversionToSmallestType ) + { + // #79615 Choose "smallest" represention for int values + // because up cast is allowed, downcast not + switch( eType ) + { + case TypeClass_FLOAT: + case TypeClass_DOUBLE: + { + double d = pVar->GetDouble(); + if( d == floor( d ) ) + { + if( d >= -128 && d <= 127 ) + aType = ::getCppuType( (sal_Int8*)0 ); + else if( d >= SbxMININT && d <= SbxMAXINT ) + aType = ::getCppuType( (sal_Int16*)0 ); + else if( d >= -SbxMAXLNG && d <= SbxMAXLNG ) + aType = ::getCppuType( (sal_Int32*)0 ); + } + break; + } + case TypeClass_SHORT: + { + sal_Int16 n = pVar->GetInteger(); + if( n >= -128 && n <= 127 ) + aType = ::getCppuType( (sal_Int8*)0 ); + break; + } + case TypeClass_LONG: + { + sal_Int32 n = pVar->GetLong(); + if( n >= -128 && n <= 127 ) + aType = ::getCppuType( (sal_Int8*)0 ); + else if( n >= SbxMININT && n <= SbxMAXINT ) + aType = ::getCppuType( (sal_Int16*)0 ); + break; + } + case TypeClass_UNSIGNED_SHORT: + { + sal_uInt16 n = pVar->GetUShort(); + if( n <= 255 ) + aType = ::getCppuType( (sal_uInt8*)0 ); + break; + } + case TypeClass_UNSIGNED_LONG: + { + sal_uInt32 n = pVar->GetLong(); + if( n <= 255 ) + aType = ::getCppuType( (sal_uInt8*)0 ); + else if( n <= SbxMAXUINT ) + aType = ::getCppuType( (sal_uInt16*)0 ); + break; + } + default: break; + } + } + + return sbxToUnoValue( pVar, aType ); +} + + + +// Helper function for StepREDIMP +static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray, + const Type& aElemType, short nMaxDimIndex, short nActualDim, + sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) +{ + sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1; + OUString aSeqTypeName; + sal_Int32 i; + for( i = 0 ; i < nSeqLevel ; i++ ) + aSeqTypeName += aSeqLevelStr; + + aSeqTypeName += aElemType.getTypeName(); + Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName ); + + // Create Sequence instance + Any aRetVal; + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType ); + xIdlTargetClass->createObject( aRetVal ); + + // Alloc sequence according to array bounds + sal_Int32 nUpper = pUpperBounds[nActualDim]; + sal_Int32 nLower = pLowerBounds[nActualDim]; + sal_Int32 nSeqSize = nUpper - nLower + 1; + Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); + xArray->realloc( aRetVal, nSeqSize ); + + sal_Int32& ri = pActualIndices[nActualDim]; + + for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ ) + { + Any aElementVal; + + if( nActualDim < nMaxDimIndex ) + { + aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType, + nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds ); + } + else + { + SbxVariable* pSource = pArray->Get32( pActualIndices ); + aElementVal = sbxToUnoValue( pSource, aElemType ); + } + + try + { + // In die Sequence uebernehmen + xArray->set( aRetVal, i, aElementVal ); + } + catch( IllegalArgumentException& e1 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e1, aIllegalArgumentExceptionName ) ); + } + catch (IndexOutOfBoundsException&) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + } + return aRetVal; +} + +// Konvertierung von Sbx nach Uno mit bekannter Zielklasse +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty ) +{ + Any aRetVal; + + // #94560 No conversion of empty/void for MAYBE_VOID properties + if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID ) + { + if( pVar->IsEmpty() ) + return aRetVal; + } + + SbxDataType eBaseType = pVar->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj.Is() && xObj->ISA(SbUnoAnyObject) ) + { + return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue(); + } + } + + TypeClass eType = rType.getTypeClass(); + switch( eType ) + { + case TypeClass_INTERFACE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); + + // Null-Referenz? + if( pVar->IsNull() && eType == TypeClass_INTERFACE ) + { + Reference< XInterface > xRef; + OUString aClassName = xIdlTargetClass->getName(); + Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() ); + aRetVal.setValue( &xRef, aClassType ); + } + } + break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_ARRAY: break; + */ + + // Array -> Sequence + case TypeClass_ENUM: + { + aRetVal = int2enum( pVar->GetLong(), rType ); + } + break; + + case TypeClass_SEQUENCE: + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj && xObj->ISA(SbxDimArray) ) + { + SbxBase* pObj = (SbxBase*)xObj; + SbxDimArray* pArray = (SbxDimArray*)pObj; + + short nDims = pArray->GetDims(); + + // Normal case: One dimensional array + sal_Int32 nLower, nUpper; + if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) + { + sal_Int32 nSeqSize = nUpper - nLower + 1; + + // Instanz der geforderten Sequence erzeugen + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); + xIdlTargetClass->createObject( aRetVal ); + Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); + xArray->realloc( aRetVal, nSeqSize ); + + // Element-Type + OUString aClassName = xIdlTargetClass->getName(); + typelib_TypeDescription * pSeqTD = 0; + typelib_typedescription_getByName( &pSeqTD, aClassName.pData ); + OSL_ASSERT( pSeqTD ); + Type aElemType( ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + // Reference< XIdlClass > xElementClass = TypeToIdlClass( aElemType ); + + // Alle Array-Member umwandeln und eintragen + sal_Int32 nIdx = nLower; + for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ ) + { + SbxVariableRef xVar = pArray->Get32( &nIdx ); + + // Wert von Sbx nach Uno wandeln + Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType ); + + try + { + // In die Sequence uebernehmen + xArray->set( aRetVal, i, aAnyValue ); + } + catch( IllegalArgumentException& e1 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e1, aIllegalArgumentExceptionName ) ); + } + catch (IndexOutOfBoundsException&) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + } + } + // #i33795 Map also multi dimensional arrays to corresponding sequences + else if( nDims > 1 ) + { + // Element-Type + typelib_TypeDescription * pSeqTD = 0; + Type aCurType( rType ); + sal_Int32 nSeqLevel = 0; + Type aElemType; + do + { + OUString aTypeName = aCurType.getTypeName(); + typelib_typedescription_getByName( &pSeqTD, aTypeName.pData ); + OSL_ASSERT( pSeqTD ); + if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE ) + { + aCurType = Type( ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + nSeqLevel++; + } + else + { + aElemType = aCurType; + break; + } + } + while( true ); + + if( nSeqLevel == nDims ) + { + sal_Int32* pLowerBounds = new sal_Int32[nDims]; + sal_Int32* pUpperBounds = new sal_Int32[nDims]; + sal_Int32* pActualIndices = new sal_Int32[nDims]; + for( short i = 1 ; i <= nDims ; i++ ) + { + sal_Int32 lBound, uBound; + pArray->GetDim32( i, lBound, uBound ); + + short j = i - 1; + pActualIndices[j] = pLowerBounds[j] = lBound; + pUpperBounds[j] = uBound; + } + + aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType, + nDims - 1, 0, pActualIndices, pLowerBounds, pUpperBounds ); + + delete[] pUpperBounds; + delete[] pLowerBounds; + delete[] pActualIndices; + } + } + } + } + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: break; + */ + + // Bei Any die Klassen-unabhaengige Konvertierungs-Routine nutzen + case TypeClass_ANY: + { + aRetVal = sbxToUnoValueImpl( pVar ); + } + break; + + case TypeClass_BOOLEAN: + { + sal_Bool b = pVar->GetBool(); + aRetVal.setValue( &b, getBooleanCppuType() ); + break; + } + case TypeClass_CHAR: + { + sal_Unicode c = pVar->GetChar(); + aRetVal.setValue( &c , getCharCppuType() ); + break; + } + case TypeClass_STRING: aRetVal <<= OUString( pVar->GetString() ); break; + case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break; + case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break; + //case TypeClass_OCTET: break; + + case TypeClass_BYTE: + { + sal_Int16 nVal = pVar->GetInteger(); + sal_Bool bOverflow = sal_False; + if( nVal < -128 ) + { + bOverflow = sal_True; + nVal = -128; + } + else if( nVal > 127 ) + { + bOverflow = sal_True; + nVal = 127; + } + if( bOverflow ) + StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW ); + + sal_Int8 nByteVal = (sal_Int8)nVal; + aRetVal <<= nByteVal; + break; + } + //case TypeClass_INT: break; + case TypeClass_SHORT: aRetVal <<= (sal_Int16)( pVar->GetInteger() ); break; + case TypeClass_LONG: aRetVal <<= (sal_Int32)( pVar->GetLong() ); break; + case TypeClass_HYPER: aRetVal <<= (sal_Int64)( pVar->GetInt64() ); break; + //case TypeClass_UNSIGNED_OCTET:break; + case TypeClass_UNSIGNED_SHORT: aRetVal <<= (sal_uInt16)( pVar->GetUShort() ); break; + case TypeClass_UNSIGNED_LONG: aRetVal <<= (sal_uInt32)( pVar->GetULong() ); break; + case TypeClass_UNSIGNED_HYPER: aRetVal <<= (sal_uInt64)( pVar->GetUInt64() ); break; + //case TypeClass_UNSIGNED_INT: break; + //case TypeClass_UNSIGNED_BYTE: break; + default: break; + } + + return aRetVal; +} + +// Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces +String Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, USHORT nRekLevel ) +{ + Type aIfaceType = ::getCppuType( (const Reference< XInterface > *)0 ); + static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType ); + + String aRetStr; + for( USHORT i = 0 ; i < nRekLevel ; i++ ) + aRetStr.AppendAscii( " " ); + aRetStr += String( xClass->getName() ); + OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + + // Pruefen, ob das Interface wirklich unterstuetzt wird + if( !x->queryInterface( aClassType ).hasValue() ) + { + aRetStr.AppendAscii( " (ERROR: Not really supported!)\n" ); + } + // Gibt es Super-Interfaces + else + { + aRetStr.AppendAscii( "\n" ); + + // Super-Interfaces holen + Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses(); + const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray(); + UINT32 nSuperIfaceCount = aSuperClassSeq.getLength(); + for( UINT32 j = 0 ; j < nSuperIfaceCount ; j++ ) + { + const Reference< XIdlClass >& rxIfaceClass = pClasses[j]; + if( !rxIfaceClass->equals( xIfaceClass ) ) + aRetStr += Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ); + } + } + return aRetStr; +} + +String getDbgObjectNameImpl( SbUnoObject* pUnoObj ) +{ + String aName; + if( pUnoObj ) + { + aName = pUnoObj->GetClassName(); + if( !aName.Len() ) + { + Any aToInspectObj = pUnoObj->getUnoAny(); + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + Reference< XInterface > xObj; + if( eType == TypeClass_INTERFACE ) + xObj = *(Reference< XInterface >*)aToInspectObj.getValue(); + if( xObj.is() ) + { + Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY ); + if( xServiceInfo.is() ) + aName = xServiceInfo->getImplementationName(); + } + } + } + return aName; +} + +String getDbgObjectName( SbUnoObject* pUnoObj ) +{ + String aName = getDbgObjectNameImpl( pUnoObj ); + if( !aName.Len() ) + aName.AppendAscii( "Unknown" ); + + String aRet; + if( aName.Len() > 20 ) + aRet.AppendAscii( "\n" ); + aRet.AppendAscii( "\"" ); + aRet += aName; + aRet.AppendAscii( "\":" ); + return aRet; +} + +// Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces +String Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj ) +{ + Any aToInspectObj = pUnoObj->getUnoAny(); + + // #54898: Nur TypeClass Interface zulasssen + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + String aRet; + if( eType != TypeClass_INTERFACE ) + { + aRet += ID_DBG_SUPPORTEDINTERFACES; + aRet.AppendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" ); + } + else + { + // Interface aus dem Any besorgen + const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue(); + + // XIdlClassProvider-Interface ansprechen + Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY ); + Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY ); + + aRet.AssignAscii( "Supported interfaces by object " ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + aRet.AppendAscii( "\n" ); + if( xTypeProvider.is() ) + { + // Interfaces der Implementation holen + Sequence< Type > aTypeSeq = xTypeProvider->getTypes(); + const Type* pTypeArray = aTypeSeq.getConstArray(); + UINT32 nIfaceCount = aTypeSeq.getLength(); + for( UINT32 j = 0 ; j < nIfaceCount ; j++ ) + { + const Type& rType = pTypeArray[j]; + + Reference<XIdlClass> xClass = TypeToIdlClass( rType ); + if( xClass.is() ) + { + aRet += Impl_GetInterfaceInfo( x, xClass, 1 ); + } + else + { + typelib_TypeDescription * pTD = 0; + rType.getDescription( &pTD ); + String TypeName( OUString( pTD->pTypeName ) ); + + aRet.AppendAscii( "*** ERROR: No IdlClass for type \"" ); + aRet += TypeName; + aRet.AppendAscii( "\"\n*** Please check type library\n" ); + } + } + } + else if( xClassProvider.is() ) + { + + DBG_ERROR( "XClassProvider not supported in UNO3" ); + } + } + return aRet; +} + + + +// Dbg-Hilfsmethode SbxDataType -> String +String Dbg_SbxDataType2String( SbxDataType eType ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Unknown Sbx-Type!") ); + switch( +eType ) + { + case SbxEMPTY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxEMPTY") ); break; + case SbxNULL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxNULL") ); break; + case SbxINTEGER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINTEGER") ); break; + case SbxLONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG") ); break; + case SbxSINGLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSINGLE") ); break; + case SbxDOUBLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDOUBLE") ); break; + case SbxCURRENCY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCURRENCY") ); break; + case SbxDECIMAL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDECIMAL") ); break; + case SbxDATE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATE") ); break; + case SbxSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSTRING") ); break; + case SbxOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxOBJECT") ); break; + case SbxERROR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxERROR") ); break; + case SbxBOOL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBOOL") ); break; + case SbxVARIANT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVARIANT") ); break; + case SbxDATAOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATAOBJECT") ); break; + case SbxCHAR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCHAR") ); break; + case SbxBYTE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBYTE") ); break; + case SbxUSHORT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSHORT") ); break; + case SbxULONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG") ); break; + case SbxLONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG64") ); break; + case SbxULONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG64") ); break; + case SbxSALINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT64") ); break; + case SbxSALUINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT64") ); break; + case SbxINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT") ); break; + case SbxUINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT") ); break; + case SbxVOID: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVOID") ); break; + case SbxHRESULT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxHRESULT") ); break; + case SbxPOINTER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxPOINTER") ); break; + case SbxDIMARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDIMARRAY") ); break; + case SbxCARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCARRAY") ); break; + case SbxUSERDEF: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSERDEF") ); break; + case SbxLPSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPSTR") ); break; + case SbxLPWSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPWSTR") ); break; + case SbxCoreSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCoreSTRING" ) ); break; + case SbxOBJECT | SbxARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxARRAY") ); break; + default: break; + } + return aRet; +} + +// Dbg-Hilfsmethode zum Anzeigen der Properties eines SbUnoObjects +String Impl_DumpProperties( SbUnoObject* pUnoObj ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Properties of object ") ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + + // Uno-Infos auswerten, um Arrays zu erkennen + Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess(); + if( !xAccess.is() ) + { + Reference< XInvocation > xInvok = pUnoObj->getInvocation(); + if( xInvok.is() ) + xAccess = xInvok->getIntrospection(); + } + if( !xAccess.is() ) + { + aRet.AppendAscii( "\nUnknown, no introspection available\n" ); + return aRet; + } + + Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + UINT32 nUnoPropCount = props.getLength(); + const Property* pUnoProps = props.getConstArray(); + + SbxArray* pProps = pUnoObj->GetProperties(); + USHORT nPropCount = pProps->Count(); + USHORT nPropsPerLine = 1 + nPropCount / 30; + for( USHORT i = 0; i < nPropCount; i++ ) + { + SbxVariable* pVar = pProps->Get( i ); + if( pVar ) + { + String aPropStr; + if( (i % nPropsPerLine) == 0 ) + aPropStr.AppendAscii( "\n" ); + + // Typ und Namen ausgeben + // Ist es in Uno eine Sequence? + SbxDataType eType = pVar->GetFullType(); + + BOOL bMaybeVoid = FALSE; + if( i < nUnoPropCount ) + { + const Property& rProp = pUnoProps[ i ]; + + // #63133: Bei MAYBEVOID Typ aus Uno neu konvertieren, + // damit nicht immer nur SbxEMPTY ausgegben wird. + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + { + eType = unoToSbxType( rProp.Type.getTypeClass() ); + bMaybeVoid = TRUE; + } + if( eType == SbxOBJECT ) + { + Type aType = rProp.Type; + if( aType.getTypeClass() == TypeClass_SEQUENCE ) + eType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + } + } + aPropStr += Dbg_SbxDataType2String( eType ); + if( bMaybeVoid ) + aPropStr.AppendAscii( "/void" ); + aPropStr.AppendAscii( " " ); + aPropStr += pVar->GetName(); + + if( i == nPropCount - 1 ) + aPropStr.AppendAscii( "\n" ); + else + aPropStr.AppendAscii( "; " ); + + aRet += aPropStr; + } + } + return aRet; +} + +// Dbg-Hilfsmethode zum Anzeigen der Methoden eines SbUnoObjects +String Impl_DumpMethods( SbUnoObject* pUnoObj ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Methods of object ") ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + + // XIntrospectionAccess, um die Typen der Parameter auch ausgeben zu koennen + Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess(); + if( !xAccess.is() ) + { + Reference< XInvocation > xInvok = pUnoObj->getInvocation(); + if( xInvok.is() ) + xAccess = xInvok->getIntrospection(); + } + if( !xAccess.is() ) + { + aRet.AppendAscii( "\nUnknown, no introspection available\n" ); + return aRet; + } + Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods + ( MethodConcept::ALL - MethodConcept::DANGEROUS ); + const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray(); + + SbxArray* pMethods = pUnoObj->GetMethods(); + USHORT nMethodCount = pMethods->Count(); + if( !nMethodCount ) + { + aRet.AppendAscii( "\nNo methods found\n" ); + return aRet; + } + USHORT nPropsPerLine = 1 + nMethodCount / 30; + for( USHORT i = 0; i < nMethodCount; i++ ) + { + SbxVariable* pVar = pMethods->Get( i ); + if( pVar ) + { + String aPropStr; + if( (i % nPropsPerLine) == 0 ) + aPropStr.AppendAscii( "\n" ); + + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = pUnoMethods[i]; + + // Ist es in Uno eine Sequence? + SbxDataType eType = pVar->GetFullType(); + if( eType == SbxOBJECT ) + { + Reference< XIdlClass > xClass = rxMethod->getReturnType(); + if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE ) + eType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + } + // Name und Typ ausgeben + aPropStr += Dbg_SbxDataType2String( eType ); + aPropStr.AppendAscii( " " ); + aPropStr += pVar->GetName(); + aPropStr.AppendAscii( " ( " ); + + // get-Methode darf keinen Parameter haben + Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes(); + UINT32 nParamCount = aParamsSeq.getLength(); + const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray(); + + if( nParamCount > 0 ) + { + for( USHORT j = 0; j < nParamCount; j++ ) + { + String aTypeStr = Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ); + aPropStr += aTypeStr; + + if( j < nParamCount - 1 ) + aPropStr.AppendAscii( ", " ); + } + } + else + aPropStr.AppendAscii( "void" ); + + aPropStr.AppendAscii( " ) " ); + + if( i == nMethodCount - 1 ) + aPropStr.AppendAscii( "\n" ); + else + aPropStr.AppendAscii( "; " ); + + aRet += aPropStr; + } + } + return aRet; +} + +TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray) + +// Implementation SbUnoObject +void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + if( bNeedIntrospection ) + doIntrospection(); + + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pParams = pVar->GetParameters(); + SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar); + SbUnoMethod* pMeth = PTR_CAST(SbUnoMethod,pVar); + if( pProp ) + { + bool bInvocation = pProp->isInvocationBased(); + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Test-Properties + INT32 nId = pProp->nId; + if( nId < 0 ) + { + // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen + if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" + { + String aRetStr = Impl_GetSupportedInterfaces( this ); + pVar->PutString( aRetStr ); + } + // Id == -2: Properties ausgeben + else if( nId == -2 ) // Property ID_DBG_PROPERTIES + { + // Jetzt muessen alle Properties angelegt werden + implCreateAll(); + String aRetStr = Impl_DumpProperties( this ); + pVar->PutString( aRetStr ); + } + // Id == -3: Methoden ausgeben + else if( nId == -3 ) // Property ID_DBG_METHODS + { + // Jetzt muessen alle Properties angelegt werden + implCreateAll(); + String aRetStr = Impl_DumpMethods( this ); + pVar->PutString( aRetStr ); + } + return; + } + + if( !bInvocation && mxUnoAccess.is() ) + { + try + { + // Wert holen + Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() ); + // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist + // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an + // Ansonsten kann auch FastPropertySet genutzt werden + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + } + catch( BasicErrorException& e0 ) + { + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + implHandleWrappedTargetException( e1 ); + } + catch( RuntimeException& e2 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e2 ) ); + } + catch( Exception& e3 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e3 ) ); + } + } + else if( bInvocation && mxInvocation.is() ) + { + try + { + // Wert holen + Any aRetAny = mxInvocation->getValue( pProp->GetName() ); + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + } + catch( BasicErrorException& e0 ) + { + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + implHandleWrappedTargetException( e1 ); + } + catch( RuntimeException& e2 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e2 ) ); + } + catch( Exception& e3 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e3 ) ); + } + } + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + if( !bInvocation && mxUnoAccess.is() ) + { + if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY ) + { + StarBASIC::Error( SbERR_PROP_READONLY ); + return; + } + + // Wert von Uno nach Sbx uebernehmen + Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); + try + { + // Wert setzen + Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + xPropSet->setPropertyValue( pProp->GetName(), aAnyValue ); + // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist + // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an + // Ansonsten kann auch FastPropertySet genutzt werden + } + catch( BasicErrorException& e0 ) + { + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + implHandleWrappedTargetException( e1 ); + } + catch( IllegalArgumentException& e2 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e2, aIllegalArgumentExceptionName ) ); + } + catch( RuntimeException& e3 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e3 ) ); + } + catch( Exception& e4 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e4 ) ); + } + } + else if( bInvocation && mxInvocation.is() ) + { + // Wert von Uno nach Sbx uebernehmen + Any aAnyValue = sbxToUnoValueImpl( pVar ); + try + { + // Wert setzen + mxInvocation->setValue( pProp->GetName(), aAnyValue ); + } + catch( BasicErrorException& e0 ) + { + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + implHandleWrappedTargetException( e1 ); + } + catch( RuntimeException& e2 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e2 ) ); + } + catch( Exception& e3 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e3 ) ); + } + } + } + } + else if( pMeth ) + { + bool bInvocation = pMeth->isInvocationBased(); + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Anzahl Parameter -1 wegen Param0 == this + UINT32 nParamCount = pParams ? ((UINT32)pParams->Count() - 1) : 0; + Sequence<Any> args; + BOOL bOutParams = FALSE; + UINT32 i; + + if( !bInvocation && mxUnoAccess.is() ) + { + // Infos holen + const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); + const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); + UINT32 nUnoParamCount = rInfoSeq.getLength(); + UINT32 nAllocParamCount = nParamCount; + + // Ueberschuessige Parameter ignorieren, Alternative: Error schmeissen + if( nParamCount > nUnoParamCount ) + { + nParamCount = nUnoParamCount; + nAllocParamCount = nParamCount; + } + else if( nParamCount < nUnoParamCount ) + { +/*?*/ // SbiInstance* pInst = pINST; +/*?*/ // if( pInst && pInst->IsCompatibility() ) +/*?*/ // { +/*?*/ // // Check types +/*?*/ // bool bError = false; +/*?*/ // for( i = nParamCount ; i < nUnoParamCount ; i++ ) +/*?*/ // { +/*?*/ // const ParamInfo& rInfo = pParamInfos[i]; +/*?*/ // const Reference< XIdlClass >& rxClass = rInfo.aType; +/*?*/ // if( rxClass->getTypeClass() != TypeClass_ANY ) +/*?*/ // { +/*?*/ // bError = true; +/*?*/ // StarBASIC::Error( SbERR_NOT_OPTIONAL ); +/*?*/ // } +/*?*/ // } +/*?*/ // if( !bError ) +/*?*/ // nAllocParamCount = nUnoParamCount; +/*?*/ // } + } + + if( nAllocParamCount > 0 ) + { + args.realloc( nAllocParamCount ); + Any* pAnyArgs = args.getArray(); + for( i = 0 ; i < nParamCount ; i++ ) + { + const ParamInfo& rInfo = pParamInfos[i]; + const Reference< XIdlClass >& rxClass = rInfo.aType; + //const XIdlClassRef& rxClass = pUnoParams[i]; + + com::sun::star::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() ); + + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + pAnyArgs[i] = sbxToUnoValue( pParams->Get( (USHORT)(i+1) ), aType ); + + // Wenn es nicht schon feststeht pruefen, ob Out-Parameter vorliegen + if( !bOutParams ) + { + ParamMode aParamMode = rInfo.aMode; + if( aParamMode != ParamMode_IN ) + bOutParams = TRUE; + } + } + } + } + else if( bInvocation && pParams && mxInvocation.is() ) + { + bool bOLEAutomation = true; + // TODO: bOLEAutomation = xOLEAutomation.is() + + AutomationNamedArgsSbxArray* pArgNamesArray = NULL; + if( bOLEAutomation ) + pArgNamesArray = PTR_CAST(AutomationNamedArgsSbxArray,pParams); + + args.realloc( nParamCount ); + Any* pAnyArgs = args.getArray(); + bool bBlockConversionToSmallestType( false ); +/*?*/ // bool bBlockConversionToSmallestType = pINST->IsCompatibility(); + if( pArgNamesArray ) + { + Sequence< OUString >& rNameSeq = pArgNamesArray->getNames(); + OUString* pNames = rNameSeq.getArray(); + + Any aValAny; + for( i = 0 ; i < nParamCount ; i++ ) + { + USHORT iSbx = (USHORT)(i+1); + + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ), + bBlockConversionToSmallestType ); + + OUString aParamName = pNames[iSbx]; + if( aParamName.getLength() ) + { + oleautomation::NamedArgument aNamedArgument; + aNamedArgument.Name = aParamName; + aNamedArgument.Value = aValAny; + pAnyArgs[i] <<= aNamedArgument; + } + else + { + pAnyArgs[i] = aValAny; + } + } + } + else + { + for( i = 0 ; i < nParamCount ; i++ ) + { + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (USHORT)(i+1) ), + bBlockConversionToSmallestType ); + } + } + } + + // Methode callen + GetSbData()->bBlockCompilerError = TRUE; // #106433 Block compiler errors for API calls + try + { + if( !bInvocation && mxUnoAccess.is() ) + { + Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args ); + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + + // Muessen wir Out-Parameter zurueckkopieren? + if( bOutParams ) + { + const Any* pAnyArgs = args.getConstArray(); + + // Infos holen + const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); + const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); + + UINT32 j; + for( j = 0 ; j < nParamCount ; j++ ) + { + const ParamInfo& rInfo = pParamInfos[j]; + ParamMode aParamMode = rInfo.aMode; + if( aParamMode != ParamMode_IN ) + unoToSbxValue( (SbxVariable*)pParams->Get( (USHORT)(j+1) ), pAnyArgs[ j ] ); + } + } + } + else if( bInvocation && mxInvocation.is() ) + { + Sequence< INT16 > OutParamIndex; + Sequence< Any > OutParam; + Any aRetAny = mxInvocation->invoke( pMeth->GetName(), args, OutParamIndex, OutParam ); + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + + const INT16* pIndices = OutParamIndex.getConstArray(); + UINT32 nLen = OutParamIndex.getLength(); + if( nLen ) + { + const Any* pNewValues = OutParam.getConstArray(); + for( UINT32 j = 0 ; j < nLen ; j++ ) + { + INT16 iTarget = pIndices[ j ]; + if( iTarget >= (INT16)nParamCount ) + break; + unoToSbxValue( (SbxVariable*)pParams->Get( (USHORT)(j+1) ), pNewValues[ j ] ); + } + } + } + + // #55460, Parameter hier weghauen, da das in unoToSbxValue() + // bei Arrays wegen #54548 nicht mehr gemacht wird + if( pParams ) + pVar->SetParameters( NULL ); + } + catch( BasicErrorException& e0 ) + { + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + implHandleWrappedTargetException( e1 ); + } + catch( RuntimeException& e2 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e2 ) ); + } + catch( IllegalArgumentException& e3) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e3, aIllegalArgumentExceptionName ) ); + } + catch( Exception& e4 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e4 ) ); + } + /* + catch( NullPointerException& e1 ) + { + } + catch( InvocationTargetException& e2 ) + { + } + */ + GetSbData()->bBlockCompilerError = FALSE; // #106433 Unblock compiler errors + } + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + + +#ifdef INVOCATION_ONLY +// Aus USR +Reference< XInvocation > createDynamicInvocationFor( const Any& aAny ); +#endif + +SbUnoObject::SbUnoObject( const String& aName_, const Any& aUnoObj_ ) + : SbxObject( aName_ ) +{ + static Reference< XIntrospection > xIntrospection; + + // Default-Properties von Sbx wieder rauspruegeln + Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE ); + Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE ); + + // Typ des Objekts pruefen + TypeClass eType = aUnoObj_.getValueType().getTypeClass(); + Reference< XInterface > x; + if( eType == TypeClass_INTERFACE ) + { + // Interface aus dem Any besorgen + x = *(Reference< XInterface >*)aUnoObj_.getValue(); + if( !x.is() ) + return; + } + + Reference< XTypeProvider > xTypeProvider; +#ifdef INVOCATION_ONLY + // Invocation besorgen + mxInvocation = createDynamicInvocationFor( aUnoObj_ ); +#else + // Hat das Object selbst eine Invocation? + mxInvocation = Reference< XInvocation >( x, UNO_QUERY ); + + xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY ); +#endif + + if( mxInvocation.is() ) + { + // #94670: This is WRONG because then the MaterialHolder doesn't refer + // to the object implementing XInvocation but to the object passed to + // the invocation service!!! + // mxMaterialHolder = Reference< XMaterialHolder >::query( mxInvocation ); + + // ExactName holen + mxExactNameInvocation = Reference< XExactName >::query( mxInvocation ); + + // Rest bezieht sich nur auf Introspection + if( !xTypeProvider.is() ) + { + bNeedIntrospection = FALSE; + return; + } + } + + // Introspection-Flag + bNeedIntrospection = TRUE; + maTmpUnoObj = aUnoObj_; + + + //*** Namen bestimmen *** + BOOL bFatalError = TRUE; + + // Ist es ein Interface oder eine struct? + BOOL bSetClassName = FALSE; + String aClassName_; + if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION ) + { + // Struct ist Ok + bFatalError = FALSE; + + // #67173 Echten Klassen-Namen eintragen + if( aName_.Len() == 0 ) + { + aClassName_ = String( aUnoObj_.getValueType().getTypeName() ); + bSetClassName = TRUE; + } + } + else if( eType == TypeClass_INTERFACE ) + { + // #70197 Interface geht immer durch Typ im Any + bFatalError = FALSE; + + // Nach XIdlClassProvider-Interface fragen + Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY ); + if( xClassProvider.is() ) + { + // #67173 Echten Klassen-Namen eintragen + if( aName_.Len() == 0 ) + { + Sequence< Reference< XIdlClass > > szClasses = xClassProvider->getIdlClasses(); + UINT32 nLen = szClasses.getLength(); + if( nLen ) + { + const Reference< XIdlClass > xImplClass = szClasses.getConstArray()[ 0 ]; + if( xImplClass.is() ) + { + aClassName_ = String( xImplClass->getName() ); + bSetClassName = TRUE; + } + } + } + } + } + if( bSetClassName ) + SetClassName( aClassName_ ); + + // Weder Interface noch Struct -> FatalError + if( bFatalError ) + { + StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION ); + return; + } + + // #67781 Introspection erst on demand durchfuehren +} + +SbUnoObject::~SbUnoObject() +{ +} + + +// #76470 Introspection on Demand durchfuehren +void SbUnoObject::doIntrospection( void ) +{ + static Reference< XIntrospection > xIntrospection; + + if( !bNeedIntrospection ) + return; + bNeedIntrospection = FALSE; + + if( !xIntrospection.is() ) + { + // Introspection-Service holen + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + if ( xFactory.is() ) + { + Reference< XInterface > xI = xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection") ); + if (xI.is()) + xIntrospection = Reference< XIntrospection >::query( xI ); + //xI->queryInterface( ::getCppuType( (const Reference< XIntrospection > *)0 ), xIntrospection ); + } + } + if( !xIntrospection.is() ) + { + StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION ); + return; + } + + // Introspection durchfuehren + try + { + mxUnoAccess = xIntrospection->inspect( maTmpUnoObj ); + } + catch( RuntimeException& e ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + + if( !mxUnoAccess.is() ) + { + // #51475 Ungueltiges Objekt kennzeichnen (kein mxMaterialHolder) + return; + } + + // MaterialHolder vom Access holen + mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess ); + + // ExactName vom Access holen + mxExactName = Reference< XExactName >::query( mxUnoAccess ); +} + + + + +// #67781 Start einer Liste aller SbUnoMethod-Instanzen +static SbUnoMethod* pFirst = NULL; + +SbUnoMethod::SbUnoMethod +( + const String& aName_, + SbxDataType eSbxType, + Reference< XIdlMethod > xUnoMethod_, + bool bInvocation +) + : SbxMethod( aName_, eSbxType ) + , mbInvocation( bInvocation ) +{ + m_xUnoMethod = xUnoMethod_; + pParamInfoSeq = NULL; + + // #67781 Methode in Liste eintragen + pNext = pFirst; + pPrev = NULL; + pFirst = this; + if( pNext ) + pNext->pPrev = this; +} + +SbUnoMethod::~SbUnoMethod() +{ + delete pParamInfoSeq; + + if( this == pFirst ) + pFirst = pNext; + else if( pPrev ) + pPrev->pNext = pNext; + if( pNext ) + pNext->pPrev = pPrev; +} + +SbxInfo* SbUnoMethod::GetInfo() +{ +/*?*/ // if( !pInfo && m_xUnoMethod.is() ) +/*?*/ // { +/*?*/ // SbiInstance* pInst = pINST; +/*?*/ // if( pInst && pInst->IsCompatibility() ) +/*?*/ // { +/*?*/ // pInfo = new SbxInfo(); +/*?*/ // +/*?*/ // const Sequence<ParamInfo>& rInfoSeq = getParamInfos(); +/*?*/ // const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); +/*?*/ // UINT32 nParamCount = rInfoSeq.getLength(); +/*?*/ // +/*?*/ // for( UINT32 i = 0 ; i < nParamCount ; i++ ) +/*?*/ // { +/*?*/ // const ParamInfo& rInfo = pParamInfos[i]; +/*?*/ // OUString aParamName = rInfo.aName; +/*?*/ // +/*?*/ // // const Reference< XIdlClass >& rxClass = rInfo.aType; +/*?*/ // SbxDataType t = SbxVARIANT; +/*?*/ // USHORT nFlags_ = SBX_READ; +/*?*/ // pInfo->AddParam( aParamName, t, nFlags_ ); +/*?*/ // } +/*?*/ // } +/*?*/ // } + return pInfo; +} + +const Sequence<ParamInfo>& SbUnoMethod::getParamInfos( void ) +{ + if( !pParamInfoSeq && m_xUnoMethod.is() ) + { + Sequence<ParamInfo> aTmp = m_xUnoMethod->getParameterInfos() ; + pParamInfoSeq = new Sequence<ParamInfo>( aTmp ); + } + return *pParamInfoSeq; +} + +SbUnoProperty::SbUnoProperty +( + const String& aName_, + SbxDataType eSbxType, + const Property& aUnoProp_, + INT32 nId_, + bool bInvocation +) + : SbxProperty( aName_, eSbxType ) + , aUnoProp( aUnoProp_ ) + , nId( nId_ ) + , mbInvocation( bInvocation ) +{ + // #54548, bei bedarf Dummy-Array einsetzen, damit SbiRuntime::CheckArray() geht + static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT ); + if( eSbxType & SbxARRAY ) + PutObject( xDummyArray ); +} + +SbUnoProperty::~SbUnoProperty() +{} + + +/*?*/ // // #72732 Spezielle SbxVariable, die beim put/get prueft, +/*?*/ // // ob der Kontext fuer eine UnoClass sinnvoll ist. Sonst +/*?*/ // // liegt eventuell ein Schreibfehler im Basic-Source vor. +/*?*/ // BOOL UnoClassMemberVariable::Get( SbxValues& rRes ) const +/*?*/ // { +/*?*/ // // Zugriff auf den Member einer UnoClass mit Parametern ist unsinnig +/*?*/ // if( GetParameters() ) +/*?*/ // { +/*?*/ // if( mpRuntime ) +/*?*/ // mpRuntime->Error( SbERR_NO_METHOD ); +/*?*/ // } +/*?*/ // return SbxVariable::Get( rRes ); +/*?*/ // } +/*?*/ // +/*?*/ // BOOL UnoClassMemberVariable::Put( const SbxValues& rRes ) +/*?*/ // { +/*?*/ // if( bInternalUse ) +/*?*/ // { +/*?*/ // return SbxVariable::Put( rRes ); +/*?*/ // } +/*?*/ // // Schreibzugriff auf den Member einer UnoClass ist immer falsch +/*?*/ // mpRuntime->Error( SbERR_NO_METHOD ); +/*?*/ // return FALSE; +/*?*/ // } +/*?*/ // +/*?*/ // TYPEINIT1(UnoClassMemberVariable,SbxVariable) + +SbxVariable* SbUnoObject::Find( const XubString& rName, SbxClassType t ) +{ + static Reference< XIdlMethod > xDummyMethod; + static Property aDummyProp; + + SbxVariable* pRes = SbxObject::Find( rName, t ); + + if( bNeedIntrospection ) + doIntrospection(); + + // Neu 4.3.1999: Properties on Demand anlegen, daher jetzt perIntrospectionAccess + // suchen, ob doch eine Property oder Methode des geforderten Namens existiert + if( !pRes ) + { + OUString aUName( rName ); + if( mxUnoAccess.is() ) + { + if( mxExactName.is() ) + { + OUString aUExactName = mxExactName->getExactName( aUName ); + if( aUExactName.getLength() ) + aUName = aUExactName; + } + if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) ) + { + const Property& rProp = mxUnoAccess-> + getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + + // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden + SbxDataType eSbxType; + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + eSbxType = SbxVARIANT; + else + eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); + + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, 0, false ); + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + else if( mxUnoAccess->hasMethod( aUName, + MethodConcept::ALL - MethodConcept::DANGEROUS ) ) + { + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = mxUnoAccess-> + getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS ); + + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(), + unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + + // Wenn immer noch nichts gefunden wurde, muss geprueft werden, ob NameAccess vorliegt + if( !pRes ) + { + try + { + Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + OUString aUName2( rName ); + + if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) ) + { + Any aAny = xNameAccess->getByName( aUName2 ); + + // ACHTUNG: Die hier erzeugte Variable darf wegen bei XNameAccess + // nicht als feste Property in das Object aufgenommen werden und + // wird daher nirgendwo gehalten. + // Wenn das Probleme gibt, muss das kuenstlich gemacht werden oder + // es muss eine Klasse SbUnoNameAccessProperty geschaffen werden, + // bei der die Existenz staendig neu ueberprueft und die ggf. weg- + // geworfen wird, wenn der Name nicht mehr gefunden wird. + pRes = new SbxVariable( SbxVARIANT ); + unoToSbxValue( pRes, aAny ); + } + } + catch( NoSuchElementException& e ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + catch( BasicErrorException& e0 ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + implHandleWrappedTargetException( e1 ); + } + catch( RuntimeException& e2 ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e2 ) ); + } + } + } + if( !pRes && mxInvocation.is() ) + { + if( mxExactNameInvocation.is() ) + { + OUString aUExactName = mxExactNameInvocation->getExactName( aUName ); + if( aUExactName.getLength() ) + aUName = aUExactName; + } + + try + { + if( mxInvocation->hasProperty( aUName ) ) + { + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, aDummyProp, 0, true ); + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + else if( mxInvocation->hasMethod( aUName ) ) + { + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + } + catch( RuntimeException& e ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + } + } + + // Ganz am Schluss noch pruefen, ob die Dbg_-Properties gemeint sind + + if( !pRes ) + { + if( rName.EqualsIgnoreCaseAscii( ID_DBG_SUPPORTEDINTERFACES ) || + rName.EqualsIgnoreCaseAscii( ID_DBG_PROPERTIES ) || + rName.EqualsIgnoreCaseAscii( ID_DBG_METHODS ) ) + { + // Anlegen + implCreateDbgProperties(); + + // Jetzt muessen sie regulaer gefunden werden + pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE ); + } + } + return pRes; +} + + +// Hilfs-Methode zum Anlegen der dbg_-Properties +void SbUnoObject::implCreateDbgProperties( void ) +{ + Property aProp; + + // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen + SbxVariableRef xVarRef = new SbUnoProperty( ID_DBG_SUPPORTEDINTERFACES, SbxSTRING, aProp, -1, false ); + QuickInsert( (SbxVariable*)xVarRef ); + + // Id == -2: Properties ausgeben + xVarRef = new SbUnoProperty( ID_DBG_PROPERTIES, SbxSTRING, aProp, -2, false ); + QuickInsert( (SbxVariable*)xVarRef ); + + // Id == -3: Methoden ausgeben + xVarRef = new SbUnoProperty( ID_DBG_METHODS, SbxSTRING, aProp, -3, false ); + QuickInsert( (SbxVariable*)xVarRef ); +} + +void SbUnoObject::implCreateAll( void ) +{ + // Bestehende Methoden und Properties alle wieder wegwerfen + pMethods = new SbxArray; + pProps = new SbxArray; + + if( bNeedIntrospection ) doIntrospection(); + + // Instrospection besorgen + Reference< XIntrospectionAccess > xAccess = mxUnoAccess; + if( !xAccess.is() ) + { + if( mxInvocation.is() ) + xAccess = mxInvocation->getIntrospection(); + } + if( !xAccess.is() ) + return; + + // Properties anlegen + Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + UINT32 nPropCount = props.getLength(); + const Property* pProps_ = props.getConstArray(); + + UINT32 i; + for( i = 0 ; i < nPropCount ; i++ ) + { + const Property& rProp = pProps_[ i ]; + + // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden + SbxDataType eSbxType; + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + eSbxType = SbxVARIANT; + else + eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); + + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, i, false ); + QuickInsert( (SbxVariable*)xVarRef ); + } + + // Dbg_-Properties anlegen + implCreateDbgProperties(); + + // Methoden anlegen + Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods + ( MethodConcept::ALL - MethodConcept::DANGEROUS ); + UINT32 nMethCount = aMethodSeq.getLength(); + const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray(); + for( i = 0 ; i < nMethCount ; i++ ) + { + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = pMethods_[i]; + + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod + ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); + QuickInsert( (SbxVariable*)xMethRef ); + } +} + + +// Wert rausgeben +Any SbUnoObject::getUnoAny( void ) +{ + Any aRetAny; + if( bNeedIntrospection ) doIntrospection(); + if( mxMaterialHolder.is() ) + aRetAny = mxMaterialHolder->getMaterial(); + else if( mxInvocation.is() ) + aRetAny <<= mxInvocation; + return aRetAny; +} + +// Hilfsmethode zum Anlegen einer Uno-Struct per CoreReflection +SbUnoObject* Impl_CreateUnoStruct( const String& aClassName ) +{ + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( !xCoreReflection.is() ) + return NULL; + + // Klasse suchen + Reference< XIdlClass > xClass; + Reference< XHierarchicalNameAccess > xHarryName = + getCoreReflection_HierarchicalNameAccess_Impl(); + if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) ) + xClass = xCoreReflection->forName( aClassName ); + if( !xClass.is() ) + return NULL; + + // Ist es ueberhaupt ein struct? + TypeClass eType = xClass->getTypeClass(); + if( eType != TypeClass_STRUCT ) + return NULL; + + // Instanz erzeugen + Any aNewAny; + xClass->createObject( aNewAny ); + + // SbUnoObject daraus basteln + SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny ); + return pUnoObj; +} + + +// Factory-Klasse fuer das Anlegen von Uno-Structs per DIM AS NEW +SbxBase* SbUnoFactory::Create( UINT16, UINT32 ) +{ + // Ueber SbxId laeuft in Uno nix + return NULL; +} + +SbxObject* SbUnoFactory::CreateObject( const String& rClassName ) +{ + return Impl_CreateUnoStruct( rClassName ); +} + +// Funktion, um einen globalen Bezeichner im +// UnoScope zu suchen und fuer Sbx zu wrappen +SbxVariable* findUnoClass( const String& rName ) +{ + // #105550 Check if module exists + SbUnoClass* pUnoClass = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + Reference< XTypeDescription > xTypeDesc; + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS ) + pUnoClass = new SbUnoClass( rName ); + } + } + return pUnoClass; +} + +SbxVariable* SbUnoClass::Find( const XubString& rName, SbxClassType t ) +{ + (void)t; + + SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE ); + + // Wenn nichts gefunden wird, ist das Sub-Modul noch nicht bekannt + if( !pRes ) + { + // Wenn es schon eine Klasse ist, nach einen Feld fragen + if( m_xClass.is() ) + { + // Ist es ein Field + OUString aUStr( rName ); + Reference< XIdlField > xField = m_xClass->getField( aUStr ); + Reference< XIdlClass > xClass; + if( xField.is() ) + { + try + { + Any aAny; + aAny = xField->get( aAny ); + + // Nach Sbx wandeln + pRes = new SbxVariable( SbxVARIANT ); + pRes->SetName( rName ); + unoToSbxValue( pRes, aAny ); + } + catch( BasicErrorException& e0 ) + { + implHandleBasicErrorException( e0 ); + } + catch( WrappedTargetException& e1 ) + { + implHandleWrappedTargetException( e1 ); + } + catch( RuntimeException& e2 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e2 ) ); + } + catch( IllegalArgumentException& e3 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e3, aIllegalArgumentExceptionName ) ); + } + } + } + else + { + // Vollqualifizierten Namen erweitern + String aNewName = GetName(); + aNewName.AppendAscii( "." ); + aNewName += rName; + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( xCoreReflection.is() ) + { + // Ist es eine Konstante? + Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY ); + if( xHarryName.is() ) + { + try + { + Any aValue = xHarryName->getByHierarchicalName( aNewName ); + TypeClass eType = aValue.getValueType().getTypeClass(); + + // Interface gefunden? Dann ist es eine Klasse + if( eType == TypeClass_INTERFACE ) + { + Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue(); + Reference< XIdlClass > xClass( xIface, UNO_QUERY ); + if( xClass.is() ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass ); + pRes->PutObject( xWrapper ); + + } + } + else + { + pRes = new SbxVariable( SbxVARIANT ); + unoToSbxValue( pRes, aValue ); + } + } + catch( NoSuchElementException& e1 ) + { + String aMsg = implGetExceptionMsg( e1 ); + } + } + + // Sonst wieder als Klasse annehmen + if( !pRes ) + { + SbxVariable* pNewClass = findUnoClass( aNewName ); + if( pNewClass ) + { + Reference< XIdlClass > xClass; + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pNewClass; + pRes->PutObject( xWrapper ); + } + } + } + } + + if( pRes ) + { + pRes->SetName( rName ); + + // Variable einfuegen, damit sie spaeter im Find gefunden wird + QuickInsert( pRes ); + + // Uns selbst gleich wieder als Listener rausnehmen, + // die Werte sind alle konstant + if( pRes->IsBroadcaster() ) + EndListening( pRes->GetBroadcaster(), TRUE ); + } + } + return pRes; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/classes/sbxmod.cxx b/binfilter/bf_basic/source/classes/sbxmod.cxx new file mode 100644 index 000000000000..4f954d25de5e --- /dev/null +++ b/binfilter/bf_basic/source/classes/sbxmod.cxx @@ -0,0 +1,1447 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <list> + +#include <vcl/svapp.hxx> + +#include <tools/stream.hxx> +#include <bf_svtools/brdcst.hxx> +#include <sbx.hxx> +#include "sb.hxx" +#include <sbjsmeth.hxx> +#include "sbjsmod.hxx" +#include "sbintern.hxx" +#include "image.hxx" +#include "token.hxx" +#include "sbunoobj.hxx" +#include "basrdll.hxx" + +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> + +// for the bsearch +#ifdef WNT +#define CDECL _cdecl +#endif +#if defined(UNX) +#define CDECL +#endif +#ifdef UNX +#include <sys/resource.h> +#endif + +#include <stdio.h> + + +namespace binfilter { + +using ::rtl::OUString; + +TYPEINIT1(SbModule,SbxObject) +TYPEINIT1(SbMethod,SbxMethod) +TYPEINIT1(SbProperty,SbxProperty) +TYPEINIT1(SbProcedureProperty,SbxProperty) +TYPEINIT1(SbJScriptModule,SbModule) +TYPEINIT1(SbJScriptMethod,SbMethod) + +///////////////////////////////////////////////////////////////////////////// + +// Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen +// Elemente von anderen Modulen aus gefunden werden koennen. + +SbModule::SbModule( const String& rName ) + : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASICModule") ) ), + pImage( NULL ), pClassData( NULL ) +{ + SetName( rName ); + SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH ); +} + +SbModule::~SbModule() +{ + if( pImage ) + delete pImage; + if( pClassData ) + delete pClassData; +} + +BOOL SbModule::IsCompiled() const +{ + return BOOL( pImage != 0 ); +} + +const SbxObject* SbModule::FindType( String aTypeName ) const +{ + return pImage ? pImage->FindType( aTypeName ) : NULL; +} + + +// Aus dem Codegenerator: Loeschen des Images und Invalidieren der Entries + +void SbModule::StartDefinitions() +{ + delete pImage; pImage = NULL; + if( pClassData ) + pClassData->clear(); + + // Methoden und Properties bleiben erhalten, sind jedoch ungueltig + // schliesslich sind ja u.U. die Infos belegt + USHORT i; + for( i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) ); + if( p ) + p->bInvalid = TRUE; + } + for( i = 0; i < pProps->Count(); ) + { + SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) ); + if( p ) + pProps->Remove( i ); + else + i++; + } +} + +// Methode anfordern/anlegen + +SbMethod* SbModule::GetMethod( const String& rName, SbxDataType t ) +{ + SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD ); + SbMethod* pMeth = p ? PTR_CAST(SbMethod,p) : NULL; + if( p && !pMeth ) + pMethods->Remove( p ); + if( !pMeth ) + { + pMeth = new SbMethod( rName, t, this ); + pMeth->SetParent( this ); + pMeth->SetFlags( SBX_READ ); + pMethods->Put( pMeth, pMethods->Count() ); + StartListening( pMeth->GetBroadcaster(), TRUE ); + } + // Per Default ist die Methode GUELTIG, da sie auch vom Compiler + // (Codegenerator) erzeugt werden kann + pMeth->bInvalid = FALSE; + pMeth->ResetFlag( SBX_FIXED ); + pMeth->SetFlag( SBX_WRITE ); + pMeth->SetType( t ); + pMeth->ResetFlag( SBX_WRITE ); + if( t != SbxVARIANT ) + pMeth->SetFlag( SBX_FIXED ); + return pMeth; +} + +// Property anfordern/anlegen + +SbIfaceMapperMethod::~SbIfaceMapperMethod() +{ +} + +TYPEINIT1(SbIfaceMapperMethod,SbMethod) + + +// Aus dem Codegenerator: Ungueltige Eintraege entfernen + +void SbModule::EndDefinitions( BOOL bNewState ) +{ + for( USHORT i = 0; i < pMethods->Count(); ) + { + SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) ); + if( p ) + { + if( p->bInvalid ) + pMethods->Remove( p ); + else + { + p->bInvalid = bNewState; + i++; + } + } + else + i++; + } + SetModified( TRUE ); +} + +void SbModule::Clear() +{ + delete pImage; pImage = NULL; + if( pClassData ) + pClassData->clear(); + SbxObject::Clear(); +} + + +SbxVariable* SbModule::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pRes = SbxObject::Find( rName, t ); +/*?*/ // if( !pRes && pImage ) +/*?*/ // { +/*?*/ // SbiInstance* pInst = pINST; +/*?*/ // if( pInst && pInst->IsCompatibility() ) +/*?*/ // { +/*?*/ // // Put enum types as objects into module, +/*?*/ // // allows MyEnum.First notation +/*?*/ // SbxArrayRef xArray = pImage->GetEnums(); +/*?*/ // if( xArray.Is() ) +/*?*/ // { +/*?*/ // SbxVariable* pEnumVar = xArray->Find( rName, SbxCLASS_DONTCARE ); +/*?*/ // SbxObject* pEnumObject = PTR_CAST( SbxObject, pEnumVar ); +/*?*/ // if( pEnumObject ) +/*?*/ // { +/*?*/ // bool bPrivate = pEnumObject->IsSet( SBX_PRIVATE ); +/*?*/ // String aEnumName = pEnumObject->GetName(); +/*?*/ // +/*?*/ // pRes = new SbxVariable( SbxOBJECT ); +/*?*/ // pRes->SetName( aEnumName ); +/*?*/ // pRes->SetParent( this ); +/*?*/ // pRes->SetFlag( SBX_READ ); +/*?*/ // if( bPrivate ) +/*?*/ // pRes->SetFlag( SBX_PRIVATE ); +/*?*/ // pRes->PutObject( pEnumObject ); +/*?*/ // } +/*?*/ // } +/*?*/ // } +/*?*/ // } + return pRes; +} + +const ::rtl::OUString& SbModule::GetSource32() const +{ + return aOUSource; +} + +const String& SbModule::GetSource() const +{ + static String aRetStr; + aRetStr = aOUSource; + return aRetStr; +} + +// Parent und BASIC sind eins! + +void SbModule::SetParent( SbxObject* p ) +{ + // #118083: Assertion is not valid any more + // DBG_ASSERT( !p || p->IsA( TYPE(StarBASIC) ), "SbModules nur in BASIC eintragen" ); + pParent = p; +} + +void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbProperty* pProp = PTR_CAST(SbProperty,pVar); + SbMethod* pMeth = PTR_CAST(SbMethod,pVar); + if( pProp ) + { + if( pProp->GetModule() != this ) + SetError( SbxERR_BAD_ACTION ); + } + else if( pMeth ) + { + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + if( pMeth->bInvalid && !Compile() ) + // Auto-Compile hat nicht geklappt! + StarBASIC::Error( SbERR_BAD_PROP_VALUE ); + else + { + // Aufruf eines Unterprogramms + SbModule* pOld = pMOD; + pMOD = this; + Run( (SbMethod*) pVar ); + pMOD = pOld; + } + } + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + +// Das Setzen der Source macht das Image ungueltig +// und scant die Methoden-Definitionen neu ein + +void SbModule::SetSource( const String& r ) +{ + SetSource32( r ); +} + +void SbModule::SetSource32( const ::rtl::OUString& r ) +{ + aOUSource = r; + StartDefinitions(); + SbiTokenizer aTok( r ); + while( !aTok.IsEof() ) + { + SbiToken eEndTok = NIL; + + // Suchen nach SUB oder FUNCTION + SbiToken eLastTok = NIL; + while( !aTok.IsEof() ) + { + // #32385: Nicht bei declare + SbiToken eCurTok = aTok.Next(); + if( eLastTok != DECLARE ) + { + if( eCurTok == SUB ) + { + eEndTok = ENDSUB; break; + } + if( eCurTok == FUNCTION ) + { + eEndTok = ENDFUNC; break; + } + if( eCurTok == PROPERTY ) + { + eEndTok = ENDPROPERTY; break; + } + if( eCurTok == OPTION ) + { + eCurTok = aTok.Next(); + if( eCurTok == COMPATIBLE ) + aTok.SetCompatible( true ); + } + } + eLastTok = eCurTok; + } + // Definition der Methode + SbMethod* pMeth = NULL; + if( eEndTok != NIL ) + { + USHORT nLine1 = aTok.GetLine(); + if( aTok.Next() == SYMBOL ) + { + String aName_( aTok.GetSym() ); + SbxDataType t = aTok.GetType(); + if( t == SbxVARIANT && eEndTok == ENDSUB ) + t = SbxVOID; + pMeth = GetMethod( aName_, t ); + pMeth->nLine1 = pMeth->nLine2 = nLine1; + // Die Methode ist erst mal GUELTIG + pMeth->bInvalid = FALSE; + } + else + eEndTok = NIL; + } + // Skip bis END SUB/END FUNCTION + if( eEndTok != NIL ) + { + while( !aTok.IsEof() ) + { + if( aTok.Next() == eEndTok ) + { + pMeth->nLine2 = aTok.GetLine(); + break; + } + } + if( aTok.IsEof() ) + pMeth->nLine2 = aTok.GetLine(); + } + } + EndDefinitions( TRUE ); +} + +SbMethod* SbModule::GetFunctionForLine( USHORT nLine ) +{ + for( USHORT i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* p = (SbMethod*) pMethods->Get( i ); + if( p->GetSbxId() == SBXID_BASICMETHOD ) + { + if( nLine >= p->nLine1 && nLine <= p->nLine2 ) + return p; + } + } + return NULL; +} + +// Ausstrahlen eines Hints an alle Basics + +static void _SendHint( SbxObject* pObj, ULONG nId, SbMethod* p ) +{ + // Selbst ein BASIC? + if( pObj->IsA( TYPE(StarBASIC) ) && pObj->IsBroadcaster() ) + pObj->GetBroadcaster().Broadcast( SbxHint( nId, p ) ); + // Dann die Unterobjekte fragen + SbxArray* pObjs = pObj->GetObjects(); + for( USHORT i = 0; i < pObjs->Count(); i++ ) + { + SbxVariable* pVar = pObjs->Get( i ); + if( pVar->IsA( TYPE(SbxObject) ) ) + _SendHint( PTR_CAST(SbxObject,pVar), nId, p ); + } +} + +/*?*/ // static void SendHint( SbxObject* pObj, ULONG nId, SbMethod* p ) +/*?*/ // { +/*?*/ // while( pObj->GetParent() ) +/*?*/ // pObj = pObj->GetParent(); +/*?*/ // _SendHint( pObj, nId, p ); +/*?*/ // } + +// #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, +// beim Programm-Ende freigeben, damit nichts gehalten wird. +void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC* pBasic ) +{ + // return-Wert von CreateUnoService loeschen + static String aName( RTL_CONSTASCII_USTRINGPARAM("CreateUnoService") ); + SbxVariable* pVar = pBasic->GetRtl()->Find( aName, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // return-Wert von CreateUnoDialog loeschen + static String aName2( RTL_CONSTASCII_USTRINGPARAM("CreateUnoDialog") ); + pVar = pBasic->GetRtl()->Find( aName2, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // return-Wert von CDec loeschen + static String aName3( RTL_CONSTASCII_USTRINGPARAM("CDec") ); + pVar = pBasic->GetRtl()->Find( aName3, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // return-Wert von CreateObject loeschen + static String aName4( RTL_CONSTASCII_USTRINGPARAM("CreateObject") ); + pVar = pBasic->GetRtl()->Find( aName4, SbxCLASS_METHOD ); + if( pVar ) + pVar->SbxValue::Clear(); + + // Ueber alle Sub-Basics gehen + SbxArray* pObjs = pBasic->GetObjects(); + USHORT nCount = pObjs->Count(); + for( USHORT i = 0 ; i < nCount ; i++ ) + { + SbxVariable* pObjVar = pObjs->Get( i ); + StarBASIC* pSubBasic = PTR_CAST( StarBASIC, pObjVar ); + if( pSubBasic ) + ClearUnoObjectsInRTL_Impl_Rek( pSubBasic ); + } +} + +// Ausfuehren eines BASIC-Unterprogramms +USHORT SbModule::Run( SbMethod* /*pMeth*/ ) +{ + DBG_ERROR( "SbModule::Run: dead code!" ); + return 0; +} + +// Suche nach dem naechsten STMNT-Befehl im Code. Wird vom STMNT- +// Opcode verwendet, um die Endspalte zu setzen. + +const BYTE* SbModule::FindNextStmnt( const BYTE* p, USHORT& nLine, USHORT& nCol ) const +{ + return FindNextStmnt( p, nLine, nCol, FALSE ); +} + +const BYTE* SbModule::FindNextStmnt( const BYTE* /*p*/, USHORT& /*nLine*/, USHORT& /*nCol*/, + BOOL /*bFollowJumps*/, const SbiImage* /*pImg*/ ) const +{ + DBG_ERROR( "SbModule::FindNextStmnt: dead code!" ); +/*?*/ // UINT32 nPC = (UINT32) ( p - (const BYTE*) pImage->GetCode() ); +/*?*/ // while( nPC < pImage->GetCodeSize() ) +/*?*/ // { +/*?*/ // SbiOpcode eOp = (SbiOpcode ) ( *p++ ); +/*?*/ // nPC++; +/*?*/ // if( bFollowJumps && eOp == _JUMP && pImg ) +/*?*/ // { +/*?*/ // DBG_ASSERT( pImg, "FindNextStmnt: pImg==NULL with FollowJumps option" ); +/*?*/ // UINT32 nOp1 = *p++; nOp1 |= *p++ << 8; +/*?*/ // nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; +/*?*/ // p = (const BYTE*) pImg->GetCode() + nOp1; +/*?*/ // } +/*?*/ // else if( eOp >= SbOP1_START && eOp <= SbOP1_END ) +/*?*/ // p += 4, nPC += 4; +/*?*/ // else if( eOp == _STMNT ) +/*?*/ // { +/*?*/ // UINT32 nl, nc; +/*?*/ // nl = *p++; nl |= *p++ << 8; +/*?*/ // nl |= *p++ << 16 ; nl |= *p++ << 24; +/*?*/ // nc = *p++; nc |= *p++ << 8; +/*?*/ // nc |= *p++ << 16 ; nc |= *p++ << 24; +/*?*/ // nLine = (USHORT)nl; nCol = (USHORT)nc; +/*?*/ // return p; +/*?*/ // } +/*?*/ // else if( eOp >= SbOP2_START && eOp <= SbOP2_END ) +/*?*/ // p += 8, nPC += 8; +/*?*/ // else if( !( eOp >= SbOP0_START && eOp <= SbOP0_END ) ) +/*?*/ // { +/*?*/ // StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); +/*?*/ // break; +/*?*/ // } +/*?*/ // } + return NULL; +} + +// Testen, ob eine Zeile STMNT-Opcodes enthaelt + +BOOL SbModule::IsBreakable( USHORT nLine ) const +{ + if( !pImage ) + return FALSE; + const BYTE* p = (const BYTE* ) pImage->GetCode(); + USHORT nl, nc; + while( ( p = FindNextStmnt( p, nl, nc ) ) != NULL ) + if( nl == nLine ) + return TRUE; + return FALSE; +} + +USHORT SbModule::GetBPCount() const +{ + return 0; +} + +USHORT SbModule::GetBP( USHORT ) const +{ + return 0; +} + +BOOL SbModule::IsBP( USHORT ) const +{ + return FALSE; +} + +BOOL SbModule::SetBP( USHORT /*nLine*/ ) +{ + DBG_ERROR( "SbModule::SetBP: dead code!" ); + return FALSE; +} + +BOOL SbModule::ClearBP( USHORT ) +{ + return FALSE; +} + +void SbModule::ClearAllBP() +{ +} + +void +SbModule::fixUpMethodStart( bool bCvtToLegacy, SbiImage* pImg ) const +{ + if ( !pImg ) + pImg = pImage; + for( UINT32 i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* pMeth = PTR_CAST(SbMethod,pMethods->Get( (USHORT)i ) ); + if( pMeth ) + { + //fixup method start positions + if ( bCvtToLegacy ) + pMeth->nStart = pImg->CalcLegacyOffset( pMeth->nStart ); + else + pMeth->nStart = pImg->CalcNewOffset( (USHORT)pMeth->nStart ); + } + } + +} + +BOOL SbModule::LoadData( SvStream& rStrm, USHORT nVer ) +{ + Clear(); + if( !SbxObject::LoadData( rStrm, 1 ) ) + return FALSE; + // Sicherheitshalber... + SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH ); + BYTE bImage; + rStrm >> bImage; + if( bImage ) + { + SbiImage* p = new SbiImage; + UINT32 nImgVer = 0; + + if( !p->Load( rStrm, nImgVer ) ) + { + delete p; + return FALSE; + } + // If the image is in old format, we fix up the method start offsets + if ( nImgVer < B_EXT_IMG_VERSION ) + { + fixUpMethodStart( false, p ); + p->ReleaseLegacyBuffer(); + } + aComment = p->aComment; + SetName( p->aName ); + if( p->GetCodeSize() ) + { + aOUSource = p->aOUSource; + // Alte Version: Image weg + if( nVer == 1 ) + { + SetSource32( p->aOUSource ); + delete p; + } + else + pImage = p; + } + else + { + SetSource32( p->aOUSource ); + delete p; + } + } + return TRUE; +} + +BOOL SbModule::StoreData( SvStream& rStrm ) const +{ + BOOL bFixup = ( pImage && !pImage->ExceedsLegacyLimits() ); + if ( bFixup ) + fixUpMethodStart( true ); + BOOL bRet = SbxObject::StoreData( rStrm ); + if ( !bRet ) + return FALSE; + + if( pImage ) + { + pImage->aOUSource = aOUSource; + pImage->aComment = aComment; + pImage->aName = GetName(); + rStrm << (BYTE) 1; + // # PCode is saved only for legacy formats only + // It should be noted that it probably isn't necessary + // It would be better not to store the image ( more flexible with + // formats ) + bool bRes = pImage->Save( rStrm, B_LEGACYVERSION ); + if ( bFixup ) + fixUpMethodStart( false ); // restore method starts + return bRes; + + } + else + { + SbiImage aImg; + aImg.aOUSource = aOUSource; + aImg.aComment = aComment; + aImg.aName = GetName(); + rStrm << (BYTE) 1; + return aImg.Save( rStrm ); + } +} + +// Called for >= OO 1.0 passwd protected libraries only +// + +BOOL SbModule::LoadCompleted() +{ + SbxArray* p = GetMethods(); + USHORT i; + for( i = 0; i < p->Count(); i++ ) + { + SbMethod* q = PTR_CAST(SbMethod,p->Get( i ) ); + if( q ) + q->pMod = this; + } + p = GetProperties(); + for( i = 0; i < p->Count(); i++ ) + { + SbProperty* q = PTR_CAST(SbProperty,p->Get( i ) ); + if( q ) + q->pMod = this; + } + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////// +// Hilfsklasse zur Untersuchung von JavaScript-Modulen, zunaechst zum +// Heraussuchen der Funktionen, spaeter auch zum Syntax-Highlighting verwenden + +// Flags fuer Zeichen-Eigenschaften +#define CHAR_START_IDENTIFIER 0x0001 +#define CHAR_IN_IDENTIFIER 0x0002 +#define CHAR_START_NUMBER 0x0004 +#define CHAR_IN_NUMBER 0x0008 +#define CHAR_IN_HEX_NUMBER 0x0010 +#define CHAR_IN_OCT_NUMBER 0x0020 +#define CHAR_START_STRING 0x0040 +#define CHAR_OPERATOR 0x0080 +#define CHAR_SPACE 0x0100 +#define CHAR_EOL 0x0200 + +#define CHAR_EOF 0x00 + + +/*?*/ // class SimpleTokenizer_Impl +/*?*/ // { +/*?*/ // // Zeichen-Info-Tabelle +/*?*/ // USHORT aCharTypeTab[256]; +/*?*/ // +/*?*/ // const sal_Unicode* mpStringBegin; +/*?*/ // const sal_Unicode* mpActualPos; +/*?*/ // +/*?*/ // // Zeile und Spalte +/*?*/ // UINT32 nLine; +/*?*/ // UINT32 nCol; +/*?*/ // +/*?*/ // sal_Unicode peekChar( void ) { return *mpActualPos; } +/*?*/ // sal_Unicode getChar( void ) { nCol++; return *mpActualPos++; } +/*?*/ // +/*?*/ // // Hilfsfunktion: Zeichen-Flag Testen +/*?*/ // BOOL testCharFlags( sal_Unicode c, USHORT nTestFlags ); +/*?*/ // +/*?*/ // // Neues Token holen, Leerstring == nix mehr da +/*?*/ // BOOL getNextToken( /*out*/TokenTypes& reType, +/*?*/ // /*out*/const sal_Unicode*& rpStartPos, /*out*/const sal_Unicode*& rpEndPos ); +/*?*/ // +/*?*/ // String getTokStr( /*out*/const sal_Unicode* pStartPos, /*out*/const sal_Unicode* pEndPos ); +/*?*/ // +/*?*/ // #ifdef DBG_UTIL +/*?*/ // // TEST: Token ausgeben +/*?*/ // String getFullTokenStr( /*out*/TokenTypes eType, +/*?*/ // /*out*/const sal_Unicode* pStartPos, /*out*/const sal_Unicode* pEndPos ); +/*?*/ // #endif +/*?*/ // +/*?*/ // const char** ppListKeyWords; +/*?*/ // UINT16 nKeyWordCount; +/*?*/ // +/*?*/ // public: +/*?*/ // SimpleTokenizer_Impl( void ); +/*?*/ // ~SimpleTokenizer_Impl( void ); +/*?*/ // +/*?*/ // UINT16 parseLine( UINT32 nLine, const String* aSource ); +/*?*/ // void getHighlightPortions( UINT32 nParseLine, const String& rLine, +/*?*/ // /*out*/HighlightPortions& portions ); +/*?*/ // void setKeyWords( const char** ppKeyWords, UINT16 nCount ); +/*?*/ // }; + +/*?*/ // // Hilfsfunktion: Zeichen-Flag Testen +/*?*/ // BOOL SimpleTokenizer_Impl::testCharFlags( sal_Unicode c, USHORT nTestFlags ) +/*?*/ // { +/*?*/ // bool bRet = false; +/*?*/ // if( c != 0 && c <= 255 ) +/*?*/ // { +/*?*/ // bRet = ( (aCharTypeTab[c] & nTestFlags) != 0 ); +/*?*/ // } +/*?*/ // else if( c > 255 ) +/*?*/ // { +/*?*/ // bRet = (( CHAR_START_IDENTIFIER | CHAR_IN_IDENTIFIER ) & nTestFlags) != 0 +/*?*/ // ? BasicSimpleCharClass::isAlpha( c, true ) : false; +/*?*/ // } +/*?*/ // return bRet; +/*?*/ // } +/*?*/ // +/*?*/ // void SimpleTokenizer_Impl::setKeyWords( const char** ppKeyWords, UINT16 nCount ) +/*?*/ // { +/*?*/ // ppListKeyWords = ppKeyWords; +/*?*/ // nKeyWordCount = nCount; +/*?*/ // } +/*?*/ // +/*?*/ // // Neues Token holen +/*?*/ // BOOL SimpleTokenizer_Impl::getNextToken( /*out*/TokenTypes& reType, +/*?*/ // /*out*/const sal_Unicode*& rpStartPos, /*out*/const sal_Unicode*& rpEndPos ) +/*?*/ // { +/*?*/ // reType = TT_UNKNOWN; +/*?*/ // +/*?*/ // // Position merken +/*?*/ // rpStartPos = mpActualPos; +/*?*/ // +/*?*/ // // Zeichen untersuchen +/*?*/ // sal_Unicode c = peekChar(); +/*?*/ // if( c == CHAR_EOF ) +/*?*/ // return FALSE; +/*?*/ // +/*?*/ // // Zeichen lesen +/*?*/ // getChar(); +/*?*/ // +/*?*/ // //*** Alle Moeglichkeiten durchgehen *** +/*?*/ // // Space? +/*?*/ // if ( (testCharFlags( c, CHAR_SPACE ) == TRUE) ) +/*?*/ // { +/*?*/ // while( testCharFlags( peekChar(), CHAR_SPACE ) == TRUE ) +/*?*/ // getChar(); +/*?*/ // +/*?*/ // reType = TT_WHITESPACE; +/*?*/ // } +/*?*/ // +/*?*/ // // Identifier? +/*?*/ // else if ( (testCharFlags( c, CHAR_START_IDENTIFIER ) == TRUE) ) +/*?*/ // { +/*?*/ // BOOL bIdentifierChar; +/*?*/ // do +/*?*/ // { +/*?*/ // // Naechstes Zeichen holen +/*?*/ // c = peekChar(); +/*?*/ // bIdentifierChar = testCharFlags( c, CHAR_IN_IDENTIFIER ); +/*?*/ // if( bIdentifierChar ) +/*?*/ // getChar(); +/*?*/ // } +/*?*/ // while( bIdentifierChar ); +/*?*/ // +/*?*/ // reType = TT_IDENTIFIER; +/*?*/ // +/*?*/ // // Schluesselwort-Tabelle +/*?*/ // if (ppListKeyWords != NULL) +/*?*/ // { +/*?*/ // int nCount = mpActualPos - rpStartPos; +/*?*/ // +/*?*/ // // No keyword if string contains char > 255 +/*?*/ // bool bCanBeKeyword = true; +/*?*/ // for( int i = 0 ; i < nCount ; i++ ) +/*?*/ // { +/*?*/ // if( rpStartPos[i] > 255 ) +/*?*/ // { +/*?*/ // bCanBeKeyword = false; +/*?*/ // break; +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // if( bCanBeKeyword ) +/*?*/ // { +/*?*/ // String aKWString( +/*?*/ // rpStartPos, sal::static_int_cast< xub_StrLen >(nCount) ); +/*?*/ // ByteString aByteStr( aKWString, RTL_TEXTENCODING_ASCII_US ); +/*?*/ // aByteStr.ToLowerAscii(); +/*?*/ // if ( bsearch( aByteStr.GetBuffer(), ppListKeyWords, nKeyWordCount, sizeof( char* ), +/*?*/ // compare_strings ) ) +/*?*/ // { +/*?*/ // reType = TT_KEYWORD; +/*?*/ // +/*?*/ // if ( aByteStr.Equals( "rem" ) ) +/*?*/ // { +/*?*/ // // Alle Zeichen bis Zeilen-Ende oder EOF entfernen +/*?*/ // sal_Unicode cPeek = peekChar(); +/*?*/ // while( cPeek != CHAR_EOF && testCharFlags( cPeek, CHAR_EOL ) == FALSE ) +/*?*/ // { +/*?*/ // c = getChar(); +/*?*/ // cPeek = peekChar(); +/*?*/ // } +/*?*/ // +/*?*/ // reType = TT_COMMENT; +/*?*/ // } +/*?*/ // } +/*?*/ // } +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // // Operator? +/*?*/ // else if ( testCharFlags( c, CHAR_OPERATOR ) == TRUE || c == '\'' ) +/*?*/ // { +/*?*/ // // Kommentar ? +/*?*/ // if ( c == '\'' ) +/*?*/ // { +/*?*/ // c = getChar(); // '/' entfernen +/*?*/ // +/*?*/ // // Alle Zeichen bis Zeilen-Ende oder EOF entfernen +/*?*/ // sal_Unicode cPeek = peekChar(); +/*?*/ // while( cPeek != CHAR_EOF && testCharFlags( cPeek, CHAR_EOL ) == FALSE ) +/*?*/ // { +/*?*/ // getChar(); +/*?*/ // cPeek = peekChar(); +/*?*/ // } +/*?*/ // +/*?*/ // reType = TT_COMMENT; +/*?*/ // } +/*?*/ // +/*?*/ // // Echter Operator, kann hier einfach behandelt werden, +/*?*/ // // da nicht der wirkliche Operator, wie z.B. += interessiert, +/*?*/ // // sondern nur die Tatsache, dass es sich um einen handelt. +/*?*/ // if( reType != TT_COMMENT ) +/*?*/ // { +/*?*/ // reType = TT_OPERATOR; +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // // Objekt-Trenner? Muss vor Number abgehandelt werden +/*?*/ // else if( c == '.' && ( peekChar() < '0' || peekChar() > '9' ) ) +/*?*/ // { +/*?*/ // reType = TT_OPERATOR; +/*?*/ // } +/*?*/ // +/*?*/ // // Zahl? +/*?*/ // else if( testCharFlags( c, CHAR_START_NUMBER ) == TRUE ) +/*?*/ // { +/*?*/ // reType = TT_NUMBER; +/*?*/ // +/*?*/ // // Zahlensystem, 10 = normal, wird bei Oct/Hex geaendert +/*?*/ // int nRadix = 10; +/*?*/ // +/*?*/ // // Ist es eine Hex- oder Oct-Zahl? +/*?*/ // if( c == '&' ) +/*?*/ // { +/*?*/ // // Octal? +/*?*/ // if( peekChar() == 'o' || peekChar() == 'O' ) +/*?*/ // { +/*?*/ // // o entfernen +/*?*/ // getChar(); +/*?*/ // nRadix = 8; // Octal-Basis +/*?*/ // +/*?*/ // // Alle Ziffern einlesen +/*?*/ // while( testCharFlags( peekChar(), CHAR_IN_OCT_NUMBER ) ) +/*?*/ // c = getChar(); +/*?*/ // } +/*?*/ // // Hex? +/*?*/ // else if( peekChar() == 'h' || peekChar() == 'H' ) +/*?*/ // { +/*?*/ // // x entfernen +/*?*/ // getChar(); +/*?*/ // nRadix = 16; // Hex-Basis +/*?*/ // +/*?*/ // // Alle Ziffern einlesen und puffern +/*?*/ // while( testCharFlags( peekChar(), CHAR_IN_HEX_NUMBER ) ) +/*?*/ // c = getChar(); +/*?*/ // } +/*?*/ // else +/*?*/ // { +/*?*/ // reType = TT_OPERATOR; +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // // Wenn nicht Oct oder Hex als double ansehen +/*?*/ // if( reType == TT_NUMBER && nRadix == 10 ) +/*?*/ // { +/*?*/ // // Flag, ob das letzte Zeichen ein Exponent war +/*?*/ // BOOL bAfterExpChar = FALSE; +/*?*/ // +/*?*/ // // Alle Ziffern einlesen +/*?*/ // while( testCharFlags( peekChar(), CHAR_IN_NUMBER ) || +/*?*/ // (bAfterExpChar && peekChar() == '+' ) || +/*?*/ // (bAfterExpChar && peekChar() == '-' ) ) +/*?*/ // // Nach Exponent auch +/- OK +/*?*/ // { +/*?*/ // c = getChar(); // Zeichen lesen +/*?*/ // bAfterExpChar = ( c == 'e' || c == 'E' ); +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // // reType = TT_NUMBER; +/*?*/ // } +/*?*/ // +/*?*/ // // String? +/*?*/ // else if( testCharFlags( c, CHAR_START_STRING ) == TRUE ) +/*?*/ // { +/*?*/ // // Merken, welches Zeichen den String eroeffnet hat +/*?*/ // sal_Unicode cEndString = c; +/*?*/ // if( c == '[' ) +/*?*/ // cEndString = ']'; +/*?*/ // +/*?*/ // // Alle Ziffern einlesen und puffern +/*?*/ // while( peekChar() != cEndString ) +/*?*/ // { +/*?*/ // // #58846 EOF vor getChar() abfangen, damit EOF micht verloren geht +/*?*/ // if( peekChar() == CHAR_EOF ) +/*?*/ // { +/*?*/ // // ERROR: unterminated string literal +/*?*/ // reType = TT_ERROR; +/*?*/ // break; +/*?*/ // } +/*?*/ // c = getChar(); +/*?*/ // if( testCharFlags( c, CHAR_EOL ) == TRUE ) +/*?*/ // { +/*?*/ // // ERROR: unterminated string literal +/*?*/ // reType = TT_ERROR; +/*?*/ // break; +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // // Zeichen lesen +/*?*/ // if( reType != TT_ERROR ) +/*?*/ // { +/*?*/ // getChar(); +/*?*/ // if( cEndString == ']' ) +/*?*/ // reType = TT_IDENTIFIER; +/*?*/ // else +/*?*/ // reType = TT_STRING; +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // // Zeilenende? +/*?*/ // else if( testCharFlags( c, CHAR_EOL ) == TRUE ) +/*?*/ // { +/*?*/ // // Falls ein weiteres anderes EOL-Char folgt, weg damit +/*?*/ // sal_Unicode cNext = peekChar(); +/*?*/ // if( cNext != c && testCharFlags( cNext, CHAR_EOL ) == TRUE ) +/*?*/ // getChar(); +/*?*/ // +/*?*/ // // Positions-Daten auf Zeilen-Beginn setzen +/*?*/ // nCol = 0; +/*?*/ // nLine++; +/*?*/ // +/*?*/ // reType = TT_EOL; +/*?*/ // } +/*?*/ // +/*?*/ // // Alles andere bleibt TT_UNKNOWN +/*?*/ // +/*?*/ // +/*?*/ // // End-Position eintragen +/*?*/ // rpEndPos = mpActualPos; +/*?*/ // return TRUE; +/*?*/ // } +/*?*/ // +/*?*/ // String SimpleTokenizer_Impl::getTokStr +/*?*/ // ( /*out*/const sal_Unicode* pStartPos, /*out*/const sal_Unicode* pEndPos ) +/*?*/ // { +/*?*/ // return String( pStartPos, (USHORT)( pEndPos - pStartPos ) ); +/*?*/ // } +/*?*/ // +/*?*/ // #ifdef DBG_UTIL +/*?*/ // // TEST: Token ausgeben +/*?*/ // String SimpleTokenizer_Impl::getFullTokenStr( /*out*/TokenTypes eType, +/*?*/ // /*out*/const sal_Unicode* pStartPos, /*out*/const sal_Unicode* pEndPos ) +/*?*/ // { +/*?*/ // String aOut; +/*?*/ // switch( eType ) +/*?*/ // { +/*?*/ // case TT_UNKNOWN: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_UNKNOWN:") ); break; +/*?*/ // case TT_IDENTIFIER: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_IDENTIFIER:") ); break; +/*?*/ // case TT_WHITESPACE: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_WHITESPACE:") ); break; +/*?*/ // case TT_NUMBER: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_NUMBER:") ); break; +/*?*/ // case TT_STRING: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_STRING:") ); break; +/*?*/ // case TT_EOL: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_EOL:") ); break; +/*?*/ // case TT_COMMENT: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_COMMENT:") ); break; +/*?*/ // case TT_ERROR: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_ERROR:") ); break; +/*?*/ // case TT_OPERATOR: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_OPERATOR:") ); break; +/*?*/ // case TT_KEYWORD: aOut = String( RTL_CONSTASCII_USTRINGPARAM("TT_KEYWORD:") ); break; +/*?*/ // } +/*?*/ // if( eType != TT_EOL ) +/*?*/ // { +/*?*/ // aOut += String( pStartPos, (USHORT)( pEndPos - pStartPos ) ); +/*?*/ // } +/*?*/ // aOut += String( RTL_CONSTASCII_USTRINGPARAM("\n") ); +/*?*/ // return aOut; +/*?*/ // } +/*?*/ // #endif +/*?*/ // +/*?*/ // SimpleTokenizer_Impl::SimpleTokenizer_Impl( void ) +/*?*/ // { +/*?*/ // memset( aCharTypeTab, 0, sizeof( aCharTypeTab ) ); +/*?*/ // +/*?*/ // // Zeichen-Tabelle fuellen +/*?*/ // USHORT i; +/*?*/ // +/*?*/ // // Zulaessige Zeichen fuer Identifier +/*?*/ // USHORT nHelpMask = (USHORT)( CHAR_START_IDENTIFIER | CHAR_IN_IDENTIFIER ); +/*?*/ // for( i = 'a' ; i <= 'z' ; i++ ) +/*?*/ // aCharTypeTab[i] |= nHelpMask; +/*?*/ // for( i = 'A' ; i <= 'Z' ; i++ ) +/*?*/ // aCharTypeTab[i] |= nHelpMask; +/*?*/ // // '_' extra eintragen +/*?*/ // aCharTypeTab[(int)'_'] |= nHelpMask; +/*?*/ // // AB 23.6.97: '$' ist auch erlaubt +/*?*/ // aCharTypeTab[(int)'$'] |= nHelpMask; +/*?*/ // +/*?*/ // // Ziffern (Identifier und Number ist moeglich) +/*?*/ // nHelpMask = (USHORT)( CHAR_IN_IDENTIFIER | CHAR_START_NUMBER | +/*?*/ // CHAR_IN_NUMBER | CHAR_IN_HEX_NUMBER ); +/*?*/ // for( i = '0' ; i <= '9' ; i++ ) +/*?*/ // aCharTypeTab[i] |= nHelpMask; +/*?*/ // +/*?*/ // // e und E sowie . von Hand ergaenzen +/*?*/ // aCharTypeTab[(int)'e'] |= CHAR_IN_NUMBER; +/*?*/ // aCharTypeTab[(int)'E'] |= CHAR_IN_NUMBER; +/*?*/ // aCharTypeTab[(int)'.'] |= (USHORT)( CHAR_IN_NUMBER | CHAR_START_NUMBER ); +/*?*/ // aCharTypeTab[(int)'&'] |= CHAR_START_NUMBER; +/*?*/ // +/*?*/ // // Hex-Ziffern +/*?*/ // for( i = 'a' ; i <= 'f' ; i++ ) +/*?*/ // aCharTypeTab[i] |= CHAR_IN_HEX_NUMBER; +/*?*/ // for( i = 'A' ; i <= 'F' ; i++ ) +/*?*/ // aCharTypeTab[i] |= CHAR_IN_HEX_NUMBER; +/*?*/ // +/*?*/ // // Oct-Ziffern +/*?*/ // for( i = '0' ; i <= '7' ; i++ ) +/*?*/ // aCharTypeTab[i] |= CHAR_IN_OCT_NUMBER; +/*?*/ // +/*?*/ // // String-Beginn/End-Zeichen +/*?*/ // aCharTypeTab[(int)'\''] |= CHAR_START_STRING; +/*?*/ // aCharTypeTab[(int)'\"'] |= CHAR_START_STRING; +/*?*/ // aCharTypeTab[(int)'['] |= CHAR_START_STRING; +/*?*/ // +/*?*/ // // Operator-Zeichen +/*?*/ // aCharTypeTab[(int)'!'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'%'] |= CHAR_OPERATOR; +/*?*/ // // aCharTypeTab[(int)'&'] |= CHAR_OPERATOR; Removed because of #i14140 +/*?*/ // aCharTypeTab[(int)'('] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)')'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'*'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'+'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)','] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'-'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'/'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)':'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'<'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'='] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'>'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'?'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'^'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'|'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'~'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'{'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)'}'] |= CHAR_OPERATOR; +/*?*/ // // aCharTypeTab[(int)'['] |= CHAR_OPERATOR; Removed because of #i17826 +/*?*/ // aCharTypeTab[(int)']'] |= CHAR_OPERATOR; +/*?*/ // aCharTypeTab[(int)';'] |= CHAR_OPERATOR; +/*?*/ // +/*?*/ // // Space +/*?*/ // aCharTypeTab[(int)' ' ] |= CHAR_SPACE; +/*?*/ // aCharTypeTab[(int)'\t'] |= CHAR_SPACE; +/*?*/ // +/*?*/ // // Zeilen-Ende-Zeichen +/*?*/ // aCharTypeTab[(int)'\r'] |= CHAR_EOL; +/*?*/ // aCharTypeTab[(int)'\n'] |= CHAR_EOL; +/*?*/ // +/*?*/ // ppListKeyWords = NULL; +/*?*/ // } +/*?*/ // +/*?*/ // SimpleTokenizer_Impl::~SimpleTokenizer_Impl( void ) +/*?*/ // { +/*?*/ // } +/*?*/ // +/*?*/ // SimpleTokenizer_Impl* getSimpleTokenizer( void ) +/*?*/ // { +/*?*/ // static SimpleTokenizer_Impl* pSimpleTokenizer = NULL; +/*?*/ // if( !pSimpleTokenizer ) +/*?*/ // pSimpleTokenizer = new SimpleTokenizer_Impl(); +/*?*/ // return pSimpleTokenizer; +/*?*/ // } +/*?*/ // +/*?*/ // // Heraussuchen der jeweils naechsten Funktion aus einem JavaScript-Modul +/*?*/ // UINT16 SimpleTokenizer_Impl::parseLine( UINT32 nParseLine, const String* aSource ) +/*?*/ // { +/*?*/ // // Position auf den Anfang des Source-Strings setzen +/*?*/ // mpStringBegin = mpActualPos = aSource->GetBuffer(); +/*?*/ // +/*?*/ // // Zeile und Spalte initialisieren +/*?*/ // nLine = nParseLine; +/*?*/ // nCol = 0L; +/*?*/ // +/*?*/ // // Variablen fuer die Out-Parameter +/*?*/ // TokenTypes eType; +/*?*/ // const sal_Unicode* pStartPos; +/*?*/ // const sal_Unicode* pEndPos; +/*?*/ // +/*?*/ // // Schleife ueber alle Tokens +/*?*/ // UINT16 nTokenCount = 0; +/*?*/ // while( getNextToken( eType, pStartPos, pEndPos ) ) +/*?*/ // nTokenCount++; +/*?*/ // +/*?*/ // return nTokenCount; +/*?*/ // } +/*?*/ // +/*?*/ // void SimpleTokenizer_Impl::getHighlightPortions( UINT32 nParseLine, const String& rLine, +/*?*/ // /*out*/HighlightPortions& portions ) +/*?*/ // { +/*?*/ // // Position auf den Anfang des Source-Strings setzen +/*?*/ // mpStringBegin = mpActualPos = rLine.GetBuffer(); +/*?*/ // +/*?*/ // // Zeile und Spalte initialisieren +/*?*/ // nLine = nParseLine; +/*?*/ // nCol = 0L; +/*?*/ // +/*?*/ // // Variablen fuer die Out-Parameter +/*?*/ // TokenTypes eType; +/*?*/ // const sal_Unicode* pStartPos; +/*?*/ // const sal_Unicode* pEndPos; +/*?*/ // +/*?*/ // // Schleife ueber alle Tokens +/*?*/ // while( getNextToken( eType, pStartPos, pEndPos ) ) +/*?*/ // { +/*?*/ // HighlightPortion portion; +/*?*/ // +/*?*/ // portion.nBegin = (UINT16)(pStartPos - mpStringBegin); +/*?*/ // portion.nEnd = (UINT16)(pEndPos - mpStringBegin); +/*?*/ // portion.tokenType = eType; +/*?*/ // +/*?*/ // portions.Insert(portion, portions.Count()); +/*?*/ // } +/*?*/ // } + + +/*?*/ // ////////////////////////////////////////////////////////////////////////// +/*?*/ // // Implementierung des SyntaxHighlighter +/*?*/ // +/*?*/ // SyntaxHighlighter::SyntaxHighlighter() +/*?*/ // { +/*?*/ // m_pSimpleTokenizer = new SimpleTokenizer_Impl(); +/*?*/ // m_pKeyWords = NULL; +/*?*/ // m_nKeyWordCount = 0; +/*?*/ // } +/*?*/ // +/*?*/ // SyntaxHighlighter::~SyntaxHighlighter() +/*?*/ // { +/*?*/ // delete(m_pSimpleTokenizer); +/*?*/ // delete(m_pKeyWords); +/*?*/ // } +/*?*/ // +/*?*/ // void SyntaxHighlighter::initialize( HighlighterLanguage eLanguage_ ) +/*?*/ // { +/*?*/ // eLanguage = eLanguage_; +/*?*/ // delete(m_pSimpleTokenizer); +/*?*/ // m_pSimpleTokenizer = new SimpleTokenizer_Impl(); +/*?*/ // +/*?*/ // if (eLanguage == HIGHLIGHT_BASIC) +/*?*/ // { +/*?*/ // m_pSimpleTokenizer->setKeyWords( strListBasicKeyWords, +/*?*/ // sizeof( strListBasicKeyWords ) / sizeof( char* )); +/*?*/ // } +/*?*/ // else +/*?*/ // { +/*?*/ // m_pSimpleTokenizer->setKeyWords( NULL, 0 ); +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // const Range SyntaxHighlighter::notifyChange( UINT32 nLine, INT32 nLineCountDifference, +/*?*/ // const String* pChangedLines, UINT32 nArrayLength) +/*?*/ // { +/*?*/ // (void)nLineCountDifference; +/*?*/ // +/*?*/ // for( UINT32 i=0 ; i < nArrayLength ; i++ ) +/*?*/ // m_pSimpleTokenizer->parseLine(nLine+i, &pChangedLines[i]); +/*?*/ // +/*?*/ // return Range( nLine, nLine + nArrayLength-1 ); +/*?*/ // } +/*?*/ // +/*?*/ // void SyntaxHighlighter::getHighlightPortions( UINT32 nLine, const String& rLine, +/*?*/ // /*out*/HighlightPortions& portions ) +/*?*/ // { +/*?*/ // m_pSimpleTokenizer->getHighlightPortions( nLine, rLine, portions ); +/*?*/ // } + + +///////////////////////////////////////////////////////////////////////// +// Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen) +SbJScriptModule::SbJScriptModule( const String& rName ) + :SbModule( rName ) +{ +} + +BOOL SbJScriptModule::LoadData( SvStream& rStrm, USHORT nVer ) +{ + (void)nVer; + + Clear(); + if( !SbxObject::LoadData( rStrm, 1 ) ) + return FALSE; + + // Source-String holen + String aTmp; + rStrm.ReadByteString( aTmp, gsl_getSystemTextEncoding() ); + aOUSource = aTmp; + //rStrm >> aSource; + return TRUE; +} + +BOOL SbJScriptModule::StoreData( SvStream& rStrm ) const +{ + if( !SbxObject::StoreData( rStrm ) ) + return FALSE; + + // Source-String schreiben + String aTmp = aOUSource; + rStrm.WriteByteString( aTmp, gsl_getSystemTextEncoding() ); + //rStrm << aSource; + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////// + +SbMethod::SbMethod( const String& r, SbxDataType t, SbModule* p ) + : SbxMethod( r, t ), pMod( p ) +{ + bInvalid = TRUE; + nStart = + nDebugFlags = + nLine1 = + nLine2 = 0; + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + SetFlag( SBX_NO_MODIFY ); +} + +SbMethod::SbMethod( const SbMethod& r ) + : SvRefBase( r ), SbxMethod( r ) +{ + pMod = r.pMod; + bInvalid = r.bInvalid; + nStart = r.nStart; + nDebugFlags = r.nDebugFlags; + nLine1 = r.nLine1; + nLine2 = r.nLine2; + SetFlag( SBX_NO_MODIFY ); +} + +SbMethod::~SbMethod() +{ +} + +BOOL SbMethod::LoadData( SvStream& rStrm, USHORT nVer ) +{ + if( !SbxMethod::LoadData( rStrm, 1 ) ) + return FALSE; + INT16 n; + rStrm >> n; + INT16 nTempStart = (INT16)nStart; + // nDebugFlags = n; // AB 16.1.96: Nicht mehr uebernehmen + if( nVer == 2 ) + rStrm >> nLine1 >> nLine2 >> nTempStart >> bInvalid; + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + SetFlag( SBX_NO_MODIFY ); + nStart = nTempStart; + return TRUE; +} + +BOOL SbMethod::StoreData( SvStream& rStrm ) const +{ + if( !SbxMethod::StoreData( rStrm ) ) + return FALSE; + rStrm << (INT16) nDebugFlags + << (INT16) nLine1 + << (INT16) nLine2 + << (INT16) nStart + << (BYTE) bInvalid; + return TRUE; +} + +// Kann spaeter mal weg + +SbxInfo* SbMethod::GetInfo() +{ + return pInfo; +} + +// Schnittstelle zum Ausfuehren einer Methode aus den Applikationen +// #34191# Mit speziellem RefCounting, damit das Basic nicht durch CloseDocument() +// abgeschossen werden kann. Rueckgabewert wird als String geliefert. +ErrCode SbMethod::Call( SbxValue* /*pRet*/ ) +{ + DBG_ERROR( "SbMethod::Call: dead code!" ); +/*?*/ // // RefCount vom Modul hochzaehlen +/*?*/ // SbModule* pMod_ = (SbModule*)GetParent(); +/*?*/ // pMod_->AddRef(); +/*?*/ // +/*?*/ // // RefCount vom Basic hochzaehlen +/*?*/ // StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent(); +/*?*/ // pBasic->AddRef(); +/*?*/ // +/*?*/ // // Values anlegen, um Return-Wert zu erhalten +/*?*/ // SbxValues aVals; +/*?*/ // aVals.eType = SbxVARIANT; +/*?*/ // +/*?*/ // // #104083: Compile BEFORE get +/*?*/ // if( bInvalid && !pMod_->Compile() ) +/*?*/ // StarBASIC::Error( SbERR_BAD_PROP_VALUE ); +/*?*/ // +/*?*/ // Get( aVals ); +/*?*/ // if ( pRet ) +/*?*/ // pRet->Put( aVals ); +/*?*/ // +/*?*/ // // Gab es einen Error +/*?*/ // ErrCode nErr = SbxBase::GetError(); +/*?*/ // SbxBase::ResetError(); +/*?*/ // +/*?*/ // // Objekte freigeben +/*?*/ // pMod_->ReleaseRef(); +/*?*/ // pBasic->ReleaseRef(); +/*?*/ // +/*?*/ // return nErr; + return SbERR_NO_METHOD; +} + + +// #100883 Own Broadcast for SbMethod +void SbMethod::Broadcast( ULONG nHintId ) +{ + if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() ) + { + // Da die Methode von aussen aufrufbar ist, hier noch einmal + // die Berechtigung testen + if( nHintId & SBX_HINT_DATAWANTED ) + if( !CanRead() ) + return; + if( nHintId & SBX_HINT_DATACHANGED ) + if( !CanWrite() ) + return; + + if( pMod && !pMod->IsCompiled() ) + pMod->Compile(); + + // Block broadcasts while creating new method + SfxBroadcaster* pSave = pCst; + pCst = NULL; + SbMethod* pThisCopy = new SbMethod( *this ); + SbMethodRef xHolder = pThisCopy; + if( mpPar.Is() ) + { + // this, als Element 0 eintragen, aber den Parent nicht umsetzen! + mpPar->PutDirect( pThisCopy, 0 ); + SetParameters( NULL ); + } + + pCst = pSave; + pSave->Broadcast( SbxHint( nHintId, pThisCopy ) ); + + USHORT nSaveFlags = GetFlags(); + SetFlag( SBX_READWRITE ); + pCst = NULL; + Put( pThisCopy->GetValues_Impl() ); + pCst = pSave; + SetFlags( nSaveFlags ); + } +} + +///////////////////////////////////////////////////////////////////////// + +// Implementation SbJScriptMethod (Method-Klasse als Wrapper fuer JavaScript-Funktionen) + +SbJScriptMethod::SbJScriptMethod( const String& r, SbxDataType t, SbModule* p ) + : SbMethod( r, t, p ) +{ +} + +SbJScriptMethod::~SbJScriptMethod() +{} + + +///////////////////////////////////////////////////////////////////////// + +SbProperty::SbProperty( const String& r, SbxDataType t, SbModule* p ) + : SbxProperty( r, t ), pMod( p ) +{ + bInvalid = FALSE; +} + +SbProperty::~SbProperty() +{} + +///////////////////////////////////////////////////////////////////////// + +SbProcedureProperty::~SbProcedureProperty() +{} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/comp/buffer.cxx b/binfilter/bf_basic/source/comp/buffer.cxx new file mode 100644 index 000000000000..7a2a65c845fb --- /dev/null +++ b/binfilter/bf_basic/source/comp/buffer.cxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "buffer.hxx" +#include <string.h> + +namespace binfilter { + +const static UINT32 UP_LIMIT=0xFFFFFF00L; + +// Der SbiBuffer wird in Inkrements von mindestens 16 Bytes erweitert. +// Dies ist notwendig, da viele Klassen von einer Pufferlaenge +// von x*16 Bytes ausgehen. + +SbiBuffer::SbiBuffer( SbiParser* p, short n ) +{ + pParser = p; + n = ( (n + 15 ) / 16 ) * 16; + if( !n ) n = 16; + pBuf = NULL; + pCur = NULL; + nInc = n; + nSize = + nOff = 0; +} + +SbiBuffer::~SbiBuffer() +{ + delete[] pBuf; +} + +// Rausreichen des Puffers +// Dies fuehrt zur Loeschung des Puffers! + +char* SbiBuffer::GetBuffer() +{ + char* p = pBuf; + pBuf = NULL; + pCur = NULL; + return p; +} + +// Test, ob der Puffer n Bytes aufnehmen kann. +// Im Zweifelsfall wird er vergroessert + +BOOL SbiBuffer::Check( USHORT n ) +{ + if( !n ) return TRUE; + if( ( static_cast<UINT32>( nOff )+ n ) > static_cast<UINT32>( nSize ) ) + { + if( nInc == 0 ) + return FALSE; + USHORT nn = 0; + while( nn < n ) nn = nn + nInc; + char* p; + if( ( static_cast<UINT32>( nSize ) + nn ) > UP_LIMIT ) p = NULL; + else p = new char [nSize + nn]; + if( !p ) + { +/*?*/ // pParser->Error( SbERR_PROG_TOO_LARGE ); + nInc = 0; + delete[] pBuf; pBuf = NULL; + return FALSE; + } + else + { + if( nSize ) memcpy( p, pBuf, nSize ); + delete[] pBuf; + pBuf = p; + pCur = pBuf + nOff; + nSize = nSize + nn; + } + } + return TRUE; +} + +BOOL SbiBuffer::operator +=( INT8 n ) +{ + if( Check( 1 ) ) + { + *pCur++ = (char) n; nOff++; return TRUE; + } else return FALSE; +} + +BOOL SbiBuffer::operator +=( UINT8 n ) +{ + if( Check( 1 ) ) + { + *pCur++ = (char) n; nOff++; return TRUE; + } else return FALSE; +} + +BOOL SbiBuffer::operator +=( INT16 n ) +{ + if( Check( 2 ) ) + { + *pCur++ = (char) ( n & 0xFF ); + *pCur++ = (char) ( n >> 8 ); + nOff += 2; return TRUE; + } else return FALSE; +} + +BOOL SbiBuffer::operator +=( UINT16 n ) +{ + if( Check( 2 ) ) + { + *pCur++ = (char) ( n & 0xFF ); + *pCur++ = (char) ( n >> 8 ); + nOff += 2; return TRUE; + } else return FALSE; +} + +BOOL SbiBuffer::operator +=( UINT32 n ) +{ + if( Check( 4 ) ) + { + UINT16 n1 = static_cast<UINT16>( n & 0xFFFF ); + UINT16 n2 = static_cast<UINT16>( n >> 16 ); + if ( operator +=( n1 ) && operator +=( n2 ) ) + return TRUE; + return TRUE; + } + return FALSE; +} + +BOOL SbiBuffer::operator +=( INT32 n ) +{ + return operator +=( (UINT32) n ); +} + + +BOOL SbiBuffer::operator +=( const String& n ) +{ + USHORT l = n.Len() + 1; + if( Check( l ) ) + { + ByteString aByteStr( n, gsl_getSystemTextEncoding() ); + memcpy( pCur, aByteStr.GetBuffer(), l ); + pCur += l; + nOff = nOff + l; + return TRUE; + } + else return FALSE; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/comp/codegen.cxx b/binfilter/bf_basic/source/comp/codegen.cxx new file mode 100644 index 000000000000..7016206b345a --- /dev/null +++ b/binfilter/bf_basic/source/comp/codegen.cxx @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sbx.hxx" +#include "image.hxx" +#include "buffer.hxx" +#include "opcodes.hxx" +#include "codegen.hxx" +#include <limits> + +namespace binfilter { + +template < class T > +class PCodeVisitor +{ +public: + virtual ~PCodeVisitor(); + + virtual void start( BYTE* pStart ) = 0; + virtual void processOpCode0( SbiOpcode eOp ) = 0; + virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) = 0; + virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) = 0; + virtual bool processParams() = 0; + virtual void end() = 0; +}; + +template <class T> PCodeVisitor< T >::~PCodeVisitor() +{} + +template <class T> +class PCodeBufferWalker +{ +private: + T m_nBytes; + BYTE* m_pCode; + T readParam( BYTE*& pCode ) + { + short nBytes = sizeof( T ); + T nOp1=0; + for ( int i=0; i<nBytes; ++i ) + nOp1 |= *pCode++ << ( i * 8); + return nOp1; + } +public: + PCodeBufferWalker( BYTE* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode ) + { + } + void visitBuffer( PCodeVisitor< T >& visitor ) + { + BYTE* pCode = m_pCode; + if ( !pCode ) + return; + BYTE* pEnd = pCode + m_nBytes; + visitor.start( m_pCode ); + T nOp1 = 0, nOp2 = 0; + for( ; pCode < pEnd; ) + { + SbiOpcode eOp = (SbiOpcode)(*pCode++); + + if ( eOp <= SbOP0_END ) + visitor.processOpCode0( eOp ); + else if( eOp >= SbOP1_START && eOp <= SbOP1_END ) + { + if ( visitor.processParams() ) + nOp1 = readParam( pCode ); + else + pCode += sizeof( T ); + visitor.processOpCode1( eOp, nOp1 ); + } + else if( eOp >= SbOP2_START && eOp <= SbOP2_END ) + { + if ( visitor.processParams() ) + { + nOp1 = readParam( pCode ); + nOp2 = readParam( pCode ); + } + else + pCode += ( sizeof( T ) * 2 ); + visitor.processOpCode2( eOp, nOp1, nOp2 ); + } + } + visitor.end(); + } +}; + +template < class T, class S > +class OffSetAccumulator : public PCodeVisitor< T > +{ + T m_nNumOp0; + T m_nNumSingleParams; + T m_nNumDoubleParams; +public: + + OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){} + virtual void start( BYTE* /*pStart*/ ){} + virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; } + virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){ ++m_nNumSingleParams; } + virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; } + virtual void end(){} + S offset() + { + T result = 0 ; + static const S max = std::numeric_limits< S >::max(); + result = m_nNumOp0 + ( ( sizeof(S) + 1 ) * m_nNumSingleParams ) + ( (( sizeof(S) * 2 )+ 1 ) * m_nNumDoubleParams ); + if ( result > max ) + return max; + + return static_cast<S>(result); + } + virtual bool processParams(){ return false; } +}; + +template < class T, class S > +class BufferTransformer : public PCodeVisitor< T > +{ + BYTE* m_pStart; + SbiBuffer m_ConvertedBuf; +public: + BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {} + virtual void start( BYTE* pStart ){ m_pStart = pStart; } + virtual void processOpCode0( SbiOpcode eOp ) + { + m_ConvertedBuf += (UINT8)eOp; + } + virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) + { + m_ConvertedBuf += (UINT8)eOp; + switch( eOp ) + { + case _JUMP: + case _JUMPT: + case _JUMPF: + case _GOSUB: + case _CASEIS: + case _RETURN: + case _ERRHDL: + case _TESTFOR: + nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) ); + break; + case _RESUME: + if ( nOp1 > 1 ) + nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) ); + break; + default: + break; // + + } + m_ConvertedBuf += (S)nOp1; + } + virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) + { + m_ConvertedBuf += (UINT8)eOp; + if ( eOp == _CASEIS ) + if ( nOp1 ) + nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) ); + m_ConvertedBuf += (S)nOp1; + m_ConvertedBuf += (S)nOp2; + + } + virtual bool processParams(){ return true; } + virtual void end() {} + // yeuch, careful here, you can only call + // GetBuffer on the returned SbiBuffer once, also + // you (as the caller) get to own the memory + SbiBuffer& buffer() + { + return m_ConvertedBuf; + } + static S convertBufferOffSet( BYTE* pStart, T nOp1 ) + { + PCodeBufferWalker< T > aBuff( pStart, nOp1); + OffSetAccumulator< T, S > aVisitor; + aBuff.visitBuffer( aVisitor ); + return aVisitor.offset(); + } +}; + +UINT32 +SbiCodeGen::calcNewOffSet( BYTE* pCode, UINT16 nOffset ) +{ + return BufferTransformer< UINT16, UINT32 >::convertBufferOffSet( pCode, nOffset ); +} + +UINT16 +SbiCodeGen::calcLegacyOffSet( BYTE* pCode, UINT32 nOffset ) +{ + return BufferTransformer< UINT32, UINT16 >::convertBufferOffSet( pCode, nOffset ); +} + +template <class T, class S> +void +PCodeBuffConvertor<T,S>::convert() +{ + PCodeBufferWalker< T > aBuf( m_pStart, m_nSize ); + BufferTransformer< T, S > aTrnsfrmer; + aBuf.visitBuffer( aTrnsfrmer ); + m_pCnvtdBuf = (BYTE*)aTrnsfrmer.buffer().GetBuffer(); + m_nCnvtdSize = static_cast<S>( aTrnsfrmer.buffer().GetSize() ); +} + +// instantiate for types needed in SbiImage::Load and SbiImage::Save +template class PCodeBuffConvertor<UINT16, UINT32 >; +template class PCodeBuffConvertor<UINT32, UINT16>; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/comp/makefile.mk b/binfilter/bf_basic/source/comp/makefile.mk new file mode 100644 index 000000000000..3e7377cdd8f4 --- /dev/null +++ b/binfilter/bf_basic/source/comp/makefile.mk @@ -0,0 +1,64 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=binfilter +TARGET=basic_comp + +NO_HIDS=TRUE + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +INC+= -I$(PRJ)$/inc$/bf_basic + +# --- Allgemein ----------------------------------------------------------- + +EXCEPTIONSFILES= +#EXCEPTIONSFILES=$(SLO)$/parser.obj + +SLOFILES= \ + $(EXCEPTIONSFILES) \ + $(SLO)$/codegen.obj \ + $(SLO)$/token.obj \ + $(SLO)$/scanner.obj \ + $(SLO)$/buffer.obj \ + $(SLO)$/sbcomp.obj \ + +# $(SLO)$/dim.obj \ + $(SLO)$/exprtree.obj \ + $(SLO)$/exprnode.obj \ + $(SLO)$/exprgen.obj \ + $(SLO)$/io.obj \ + $(SLO)$/loops.obj \ + $(SLO)$/symtbl.obj \ + +# --- Targets -------------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/binfilter/bf_basic/source/comp/parser.cxx b/binfilter/bf_basic/source/comp/parser.cxx new file mode 100644 index 000000000000..e68ad6467b3a --- /dev/null +++ b/binfilter/bf_basic/source/comp/parser.cxx @@ -0,0 +1,872 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <sbx.hxx> +#include "sbcomp.hxx" + +struct SbiParseStack { // "Stack" fuer Statement-Blocks + SbiParseStack* pNext; // Chain + SbiExprNode* pWithVar; // Variable fuer WITH + SbiToken eExitTok; // Exit-Token + UINT32 nChain; // JUMP-Chain +}; + +struct SbiStatement { + SbiToken eTok; + void( SbiParser::*Func )(); // Verarbeitungsroutine + BOOL bMain; // TRUE: ausserhalb SUBs OK + BOOL bSubr; // TRUE: in SUBs OK +}; + +#define Y TRUE +#define N FALSE + +static SbiStatement StmntTable [] = { +{ CALL, &SbiParser::Call, N, Y, }, // CALL +{ CLOSE, &SbiParser::Close, N, Y, }, // CLOSE +{ _CONST_, &SbiParser::Dim, Y, Y, }, // CONST +{ DECLARE, &SbiParser::Declare, Y, N, }, // DECLARE +{ DEFBOOL, &SbiParser::DefXXX, Y, N, }, // DEFBOOL +{ DEFCUR, &SbiParser::DefXXX, Y, N, }, // DEFCUR +{ DEFDATE, &SbiParser::DefXXX, Y, N, }, // DEFDATE +{ DEFDBL, &SbiParser::DefXXX, Y, N, }, // DEFDBL +{ DEFERR, &SbiParser::DefXXX, Y, N, }, // DEFERR +{ DEFINT, &SbiParser::DefXXX, Y, N, }, // DEFINT +{ DEFLNG, &SbiParser::DefXXX, Y, N, }, // DEFLNG +{ DEFOBJ, &SbiParser::DefXXX, Y, N, }, // DEFOBJ +{ DEFSNG, &SbiParser::DefXXX, Y, N, }, // DEFSNG +{ DEFSTR, &SbiParser::DefXXX, Y, N, }, // DEFSTR +{ DEFVAR, &SbiParser::DefXXX, Y, N, }, // DEFVAR +{ DIM, &SbiParser::Dim, Y, Y, }, // DIM +{ DO, &SbiParser::DoLoop, N, Y, }, // DO +{ ELSE, &SbiParser::NoIf, N, Y, }, // ELSE +{ ELSEIF, &SbiParser::NoIf, N, Y, }, // ELSEIF +{ ENDIF, &SbiParser::NoIf, N, Y, }, // ENDIF +{ END, &SbiParser::Stop, N, Y, }, // END +{ ENUM, &SbiParser::Enum, Y, N, }, // TYPE +{ ERASE, &SbiParser::Erase, N, Y, }, // ERASE +{ _ERROR_, &SbiParser::ErrorStmnt, N, Y, }, // ERROR +{ EXIT, &SbiParser::Exit, N, Y, }, // EXIT +{ FOR, &SbiParser::For, N, Y, }, // FOR +{ FUNCTION, &SbiParser::SubFunc, Y, N, }, // FUNCTION +{ GOSUB, &SbiParser::Goto, N, Y, }, // GOSUB +{ GLOBAL, &SbiParser::Dim, Y, N, }, // GLOBAL +{ GOTO, &SbiParser::Goto, N, Y, }, // GOTO +{ IF, &SbiParser::If, N, Y, }, // IF +{ IMPLEMENTS, &SbiParser::Implements, Y, N, }, // IMPLEMENTS +{ INPUT, &SbiParser::Input, N, Y, }, // INPUT +{ LET, &SbiParser::Assign, N, Y, }, // LET +{ LINEINPUT,&SbiParser::LineInput, N, Y, }, // LINE INPUT +{ LOOP, &SbiParser::BadBlock, N, Y, }, // LOOP +{ LSET, &SbiParser::LSet, N, Y, }, // LSET +{ NAME, &SbiParser::Name, N, Y, }, // NAME +{ NEXT, &SbiParser::BadBlock, N, Y, }, // NEXT +{ ON, &SbiParser::On, N, Y, }, // ON +{ OPEN, &SbiParser::Open, N, Y, }, // OPEN +{ OPTION, &SbiParser::Option, Y, N, }, // OPTION +{ PRINT, &SbiParser::Print, N, Y, }, // PRINT +{ PRIVATE, &SbiParser::Dim, Y, N, }, // PRIVATE +{ PROPERTY, &SbiParser::SubFunc, Y, N, }, // FUNCTION +{ PUBLIC, &SbiParser::Dim, Y, N, }, // PUBLIC +{ REDIM, &SbiParser::ReDim, N, Y, }, // DIM +{ RESUME, &SbiParser::Resume, N, Y, }, // RESUME +{ RETURN, &SbiParser::Return, N, Y, }, // RETURN +{ RSET, &SbiParser::RSet, N, Y, }, // RSET +{ SELECT, &SbiParser::Select, N, Y, }, // SELECT +{ SET, &SbiParser::Set, N, Y, }, // SET +{ STATIC, &SbiParser::Static, Y, Y, }, // STATIC +{ STOP, &SbiParser::Stop, N, Y, }, // STOP +{ SUB, &SbiParser::SubFunc, Y, N, }, // SUB +{ TYPE, &SbiParser::Type, Y, N, }, // TYPE +{ UNTIL, &SbiParser::BadBlock, N, Y, }, // UNTIL +{ WHILE, &SbiParser::While, N, Y, }, // WHILE +{ WEND, &SbiParser::BadBlock, N, Y, }, // WEND +{ WITH, &SbiParser::With, N, Y, }, // WITH +{ WRITE, &SbiParser::Write, N, Y, }, // WRITE + +{ NIL, NULL, N, N } +}; + + +#ifdef MSC +// 'this' : used in base member initializer list +#pragma warning( disable: 4355 ) +#endif + +SbiParser::SbiParser( StarBASIC* pb, SbModule* pm ) + : SbiTokenizer( pm->GetSource32(), pb ), + aGblStrings( this ), + aLclStrings( this ), + aGlobals( aGblStrings, SbGLOBAL ), + aPublics( aGblStrings, SbPUBLIC ), + aRtlSyms( aGblStrings, SbRTL ), + aGen( *pm, this, 1024 ) +{ + pBasic = pb; + eCurExpr = SbSYMBOL; + eEndTok = NIL; + pProc = NULL; + pStack = NULL; + pWithVar = NULL; + nBase = 0; + bText = + bGblDefs = + bNewGblDefs = + bSingleLineIf = + bExplicit = FALSE; + bClassModule = FALSE; + bVBASupportOn = FALSE; + pPool = &aPublics; + for( short i = 0; i < 26; i++ ) + eDefTypes[ i ] = SbxVARIANT; // Kein expliziter Defaulttyp + + aPublics.SetParent( &aGlobals ); + aGlobals.SetParent( &aRtlSyms ); + + // Die globale Chainkette faengt bei Adresse 0 an: + nGblChain = aGen.Gen( _JUMP, 0 ); + + rTypeArray = new SbxArray; // Array fuer Benutzerdefinierte Typen + rEnumArray = new SbxArray; // Array for Enum types +} + + +// Ist Teil der Runtime-Library? +SbiSymDef* SbiParser::CheckRTLForSym( const String& rSym, SbxDataType eType ) +{ + SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE ); + SbiSymDef* pDef = NULL; + if( pVar ) + { + if( pVar->IsA( TYPE(SbxMethod) ) ) + { + SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym ); + pProc_->SetType( pVar->GetType() ); + pDef = pProc_; + } + else + { + pDef = aRtlSyms.AddSym( rSym ); + pDef->SetType( eType ); + } + } + return pDef; +} + +// Globale Chainkette schliessen + +BOOL SbiParser::HasGlobalCode() +{ + if( bGblDefs && nGblChain ) + { + aGen.BackChain( nGblChain ); + aGen.Gen( _LEAVE ); + // aGen.Gen( _STOP ); + nGblChain = 0; + } + return bGblDefs; +} + +void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar ) +{ + SbiParseStack* p = new SbiParseStack; + p->eExitTok = eTok; + p->nChain = 0; + p->pWithVar = pWithVar; + p->pNext = pStack; + pStack = p; + pWithVar = pVar; + + // #29955 for-Schleifen-Ebene pflegen + if( eTok == FOR ) + aGen.IncForLevel(); +} + +void SbiParser::CloseBlock() +{ + if( pStack ) + { + SbiParseStack* p = pStack; + + // #29955 for-Schleifen-Ebene pflegen + if( p->eExitTok == FOR ) + aGen.DecForLevel(); + + aGen.BackChain( p->nChain ); + pStack = p->pNext; + pWithVar = p->pWithVar; + delete p; + } +} + +// EXIT ... + +void SbiParser::Exit() +{ + SbiToken eTok = Next(); + for( SbiParseStack* p = pStack; p; p = p->pNext ) + { + if( eTok == p->eExitTok ) + { + p->nChain = aGen.Gen( _JUMP, p->nChain ); + return; + } + } + if( pStack ) + Error( SbERR_EXPECTED, pStack->eExitTok ); + else + Error( SbERR_BAD_EXIT ); +} + +BOOL SbiParser::TestSymbol( BOOL bKwdOk ) +{ + Peek(); + if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) ) + { + Next(); return TRUE; + } + Error( SbERR_SYMBOL_EXPECTED ); + return FALSE; +} + +// Testen auf ein bestimmtes Token + +BOOL SbiParser::TestToken( SbiToken t ) +{ + if( Peek() == t ) + { + Next(); return TRUE; + } + else + { + Error( SbERR_EXPECTED, t ); + return FALSE; + } +} + +// Testen auf Komma oder EOLN + +BOOL SbiParser::TestComma() +{ + SbiToken eTok = Peek(); + if( IsEoln( eTok ) ) + { + Next(); + return FALSE; + } + else if( eTok != COMMA ) + { + Error( SbERR_EXPECTED, COMMA ); + return FALSE; + } + Next(); + return TRUE; +} + +// Testen, ob EOLN vorliegt + +void SbiParser::TestEoln() +{ + if( !IsEoln( Next() ) ) + { + Error( SbERR_EXPECTED, EOLN ); + while( !IsEoln( Next() ) ) {} + } +} + +// Parsing eines Statement-Blocks +// Das Parsing laeuft bis zum Ende-Token. + +void SbiParser::StmntBlock( SbiToken eEnd ) +{ + SbiToken xe = eEndTok; + eEndTok = eEnd; + while( !bAbort && Parse() ) {} + eEndTok = xe; + if( IsEof() ) + { + Error( SbERR_BAD_BLOCK, eEnd ); + bAbort = TRUE; + } +} + +// Die Hauptroutine. Durch wiederholten Aufrufs dieser Routine wird +// die Quelle geparst. Returnwert FALSE bei Ende/Fehlern. + +BOOL SbiParser::Parse() +{ + if( bAbort ) return FALSE; + + EnableErrors(); + + bErrorIsSymbol = false; + Peek(); + bErrorIsSymbol = true; + // Dateiende? + if( IsEof() ) + { + // AB #33133: Falls keine Sub angelegt wurde, muss hier + // der globale Chain abgeschlossen werden! + // AB #40689: Durch die neue static-Behandlung kann noch + // ein nGblChain vorhanden sein, daher vorher abfragen + if( bNewGblDefs && nGblChain == 0 ) + nGblChain = aGen.Gen( _JUMP, 0 ); + return FALSE; + } + + // Leerstatement? + if( IsEoln( eCurTok ) ) + { + Next(); return TRUE; + } + + if( !bSingleLineIf && MayBeLabel( TRUE ) ) + { + // Ist ein Label + if( !pProc ) + Error( SbERR_NOT_IN_MAIN, aSym ); + else + pProc->GetLabels().Define( aSym ); + Next(); Peek(); + // Leerstatement? + if( IsEoln( eCurTok ) ) + { + Next(); return TRUE; + } + } + + // Ende des Parsings? + if( eCurTok == eEndTok ) + { + Next(); + if( eCurTok != NIL ) + aGen.Statement(); + return FALSE; + } + + // Kommentar? + if( eCurTok == REM ) + { + Next(); return TRUE; + } + + // Kommt ein Symbol, ist es entweder eine Variable( LET ) + // oder eine SUB-Prozedur( CALL ohne Klammern ) + // DOT fuer Zuweisungen im WITH-Block: .A=5 + if( eCurTok == SYMBOL || eCurTok == DOT ) + { + if( !pProc ) + Error( SbERR_EXPECTED, SUB ); + else + { + // Damit Zeile & Spalte stimmen... + Next(); + Push( eCurTok ); + aGen.Statement(); + Symbol(); + } + } + else + { + Next(); + + // Hier folgen nun die Statement-Parser. + + SbiStatement* p; + for( p = StmntTable; p->eTok != NIL; p++ ) + if( p->eTok == eCurTok ) + break; + if( p->eTok != NIL ) + { + if( !pProc && !p->bMain ) + Error( SbERR_NOT_IN_MAIN, eCurTok ); + else if( pProc && !p->bSubr ) + Error( SbERR_NOT_IN_SUBR, eCurTok ); + else + { + // globalen Chain pflegen + // AB #41606/#40689: Durch die neue static-Behandlung kann noch + // ein nGblChain vorhanden sein, daher vorher abfragen + if( bNewGblDefs && nGblChain == 0 && + ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) ) + { + nGblChain = aGen.Gen( _JUMP, 0 ); + bNewGblDefs = FALSE; + } + // Statement-Opcode bitte auch am Anfang einer Sub + if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) || + eCurTok == SUB || eCurTok == FUNCTION ) + aGen.Statement(); + (this->*( p->Func ) )(); + SbxError nSbxErr = SbxBase::GetError(); + if( nSbxErr ) + SbxBase::ResetError(), Error( (SbError)nSbxErr ); + } + } + else + Error( SbERR_UNEXPECTED, eCurTok ); + } + + // Test auf Ende des Statements: + // Kann auch ein ELSE sein, da vor dem ELSE kein : stehen muss! + + if( !IsEos() ) + { + Peek(); + if( !IsEos() && eCurTok != ELSE ) + { + // falls das Parsing abgebrochen wurde, bis zum ":" vorgehen: + Error( SbERR_UNEXPECTED, eCurTok ); + while( !IsEos() ) Next(); + } + } + // Der Parser bricht am Ende ab, das naechste Token ist noch nicht + // geholt! + return TRUE; +} + +// Innerste With-Variable liefern +SbiExprNode* SbiParser::GetWithVar() +{ + if( pWithVar ) + return pWithVar; + + // Sonst im Stack suchen + SbiParseStack* p = pStack; + while( p ) + { + // LoopVar kann zur Zeit nur fuer with sein + if( p->pWithVar ) + return p->pWithVar; + p = p->pNext; + } + return NULL; +} + + +// Zuweisung oder Subroutine Call + +void SbiParser::Symbol() +{ + SbiExpression aVar( this, SbSYMBOL ); + + bool bEQ = ( Peek() == EQ ); + RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL ); + bool bSpecialMidHandling = false; + SbiSymDef* pDef = aVar.GetRealVar(); + if( bEQ && pDef && pDef->GetScope() == SbRTL ) + { + String aRtlName = pDef->GetName(); + if( aRtlName.EqualsIgnoreCaseAscii("Mid") ) + { + SbiExprNode* pExprNode = aVar.GetExprNode(); + // SbiNodeType eNodeType; + if( pExprNode && pExprNode->GetNodeType() == SbxVARVAL ) + { + SbiExprList* pPar = pExprNode->GetParameters(); + short nParCount = pPar ? pPar->GetSize() : 0; + if( nParCount == 2 || nParCount == 3 ) + { + if( nParCount == 2 ) + pPar->addExpression( new SbiExpression( this, -1, SbxLONG ) ); + + TestToken( EQ ); + pPar->addExpression( new SbiExpression( this ) ); + + bSpecialMidHandling = true; + } + } + } + } + aVar.Gen( eRecMode ); + if( !bSpecialMidHandling ) + { + if( !bEQ ) + { + aGen.Gen( _GET ); + } + else + { + // Dann muss es eine Zuweisung sein. Was anderes gibts nicht! + if( !aVar.IsLvalue() ) + Error( SbERR_LVALUE_EXPECTED ); + TestToken( EQ ); + SbiExpression aExpr( this ); + aExpr.Gen(); + SbiOpcode eOp = _PUT; + // SbiSymDef* pDef = aVar.GetRealVar(); + if( pDef ) + { + if( pDef->GetConstDef() ) + Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); + if( pDef->GetType() == SbxOBJECT ) + { + eOp = _SET; + if( pDef->GetTypeId() ) + { + aGen.Gen( _SETCLASS, pDef->GetTypeId() ); + return; + } + } + } + aGen.Gen( eOp ); + } + } +} + +// Zuweisungen + +void SbiParser::Assign() +{ + SbiExpression aLvalue( this, SbLVALUE ); + TestToken( EQ ); + SbiExpression aExpr( this ); + aLvalue.Gen(); + aExpr.Gen(); + USHORT nLen = 0; + SbiSymDef* pDef = aLvalue.GetRealVar(); + { + if( pDef->GetConstDef() ) + Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); + nLen = aLvalue.GetRealVar()->GetLen(); + } + if( nLen ) + aGen.Gen( _PAD, nLen ); + aGen.Gen( _PUT ); +} + +// Zuweisungen einer Objektvariablen + +void SbiParser::Set() +{ + SbiExpression aLvalue( this, SbLVALUE ); + SbxDataType eType = aLvalue.GetType(); + if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT ) + Error( SbERR_INVALID_OBJECT ); + TestToken( EQ ); + SbiSymDef* pDef = aLvalue.GetRealVar(); + if( pDef && pDef->GetConstDef() ) + Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); + + SbiToken eTok = Peek(); + if( eTok == NEW ) + { + Next(); + String aStr; + SbiSymDef* pTypeDef = new SbiSymDef( aStr ); + TypeDecl( *pTypeDef, TRUE ); + + aLvalue.Gen(); + // aGen.Gen( _CLASS, pDef->GetTypeId() | 0x8000 ); + aGen.Gen( _CREATE, pDef->GetId(), pTypeDef->GetTypeId() ); + aGen.Gen( _SETCLASS, pDef->GetTypeId() ); + } + else + { + SbiExpression aExpr( this ); + aLvalue.Gen(); + aExpr.Gen(); + // Its a good idea to distinguish between + // set someting = another & + // someting = another + // ( its necessary for vba objects where set is object + // specific and also doesn't involve processing default params ) + if( pDef->GetTypeId() ) + aGen.Gen( _SETCLASS, pDef->GetTypeId() ); + else + { + if ( bVBASupportOn ) + aGen.Gen( _VBASET ); + else + aGen.Gen( _SET ); + } + } + // aGen.Gen( _SET ); +} + +// JSM 07.10.95 +void SbiParser::LSet() +{ + SbiExpression aLvalue( this, SbLVALUE ); + if( aLvalue.GetType() != SbxSTRING ) + Error( SbERR_INVALID_OBJECT ); + TestToken( EQ ); + SbiSymDef* pDef = aLvalue.GetRealVar(); + if( pDef && pDef->GetConstDef() ) + Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); + SbiExpression aExpr( this ); + aLvalue.Gen(); + aExpr.Gen(); + aGen.Gen( _LSET ); +} + +// JSM 07.10.95 +void SbiParser::RSet() +{ + SbiExpression aLvalue( this, SbLVALUE ); + if( aLvalue.GetType() != SbxSTRING ) + Error( SbERR_INVALID_OBJECT ); + TestToken( EQ ); + SbiSymDef* pDef = aLvalue.GetRealVar(); + if( pDef && pDef->GetConstDef() ) + Error( SbERR_DUPLICATE_DEF, pDef->GetName() ); + SbiExpression aExpr( this ); + aLvalue.Gen(); + aExpr.Gen(); + aGen.Gen( _RSET ); +} + +// DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR und so weiter + +void SbiParser::DefXXX() +{ + sal_Unicode ch1, ch2; + SbxDataType t = SbxDataType( eCurTok - DEFINT + SbxINTEGER ); + + while( !bAbort ) + { + if( Next() != SYMBOL ) break; + ch1 = aSym.ToUpperAscii().GetBuffer()[0]; + ch2 = 0; + if( Peek() == MINUS ) + { + Next(); + if( Next() != SYMBOL ) Error( SbERR_SYMBOL_EXPECTED ); + else + { + ch2 = aSym.ToUpperAscii().GetBuffer()[0]; + //ch2 = aSym.Upper(); + if( ch2 < ch1 ) Error( SbERR_SYNTAX ), ch2 = 0; + } + } + if (!ch2) ch2 = ch1; + ch1 -= 'A'; ch2 -= 'A'; + for (; ch1 <= ch2; ch1++) eDefTypes[ ch1 ] = t; + if( !TestComma() ) break; + } +} + +// STOP/SYSTEM + +void SbiParser::Stop() +{ + aGen.Gen( _STOP ); + Peek(); // #35694: Nur Peek(), damit EOL in Single-Line-If erkannt wird +} + +// IMPLEMENTS + +void SbiParser::Implements() +{ + if( !bClassModule ) + { + Error( SbERR_UNEXPECTED, IMPLEMENTS ); + return; + } + + if( TestSymbol() ) + { + String aImplementedIface = GetSym(); + aIfaceVector.push_back( aImplementedIface ); + } +} + +void SbiParser::EnableCompatibility() +{ + if( !bCompatible ) + AddConstants(); + bCompatible = TRUE; +} + +// OPTION + +void SbiParser::Option() +{ + switch( Next() ) + { + case EXPLICIT: + bExplicit = TRUE; break; + case BASE: + if( Next() == NUMBER ) + { + if( nVal == 0 || nVal == 1 ) + { + nBase = (short) nVal; + break; + } + } + Error( SbERR_EXPECTED, "0/1" ); + break; + case PRIVATE: + { + String aString = SbiTokenizer::Symbol(Next()); + if( !aString.EqualsIgnoreCaseAscii("Module") ) + Error( SbERR_EXPECTED, "Module" ); + break; + } + case COMPARE: + switch( Next() ) + { + case TEXT: bText = TRUE; return; + case BINARY: bText = FALSE; return; + default:; + } // Fall thru! + case COMPATIBLE: + EnableCompatibility(); + break; + + case CLASSMODULE: + bClassModule = TRUE; + break; + case VBASUPPORT: + if( Next() == NUMBER ) + { + if ( nVal == 1 || nVal == 0 ) + { + bVBASupportOn = ( nVal == 1 ); + if ( bVBASupportOn ) + EnableCompatibility(); + break; + } + } + Error( SbERR_EXPECTED, "0/1" ); + break; + default: + Error( SbERR_BAD_OPTION, eCurTok ); + } +} + +void addStringConst( SbiSymPool& rPool, const char* pSym, const String& rStr ) +{ + SbiConstDef* pConst = new SbiConstDef( String::CreateFromAscii( pSym ) ); + pConst->SetType( SbxSTRING ); + pConst->Set( rStr ); + rPool.Add( pConst ); +} + +inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr ) +{ + addStringConst( rPool, pSym, String::CreateFromAscii( pStr ) ); +} + +void SbiParser::AddConstants( void ) +{ + // #113063 Create constant RTL symbols + addStringConst( aPublics, "vbCr", "\x0D" ); + addStringConst( aPublics, "vbCrLf", "\x0D\x0A" ); + addStringConst( aPublics, "vbFormFeed", "\x0C" ); + addStringConst( aPublics, "vbLf", "\x0A" ); +#if defined(UNX) + addStringConst( aPublics, "vbNewLine", "\x0A" ); +#else + addStringConst( aPublics, "vbNewLine", "\x0D\x0A" ); +#endif + addStringConst( aPublics, "vbNullString", "" ); + addStringConst( aPublics, "vbTab", "\x09" ); + addStringConst( aPublics, "vbVerticalTab", "\x0B" ); + + // Force length 1 and make char 0 afterwards + String aNullCharStr( String::CreateFromAscii( " " ) ); + aNullCharStr.SetChar( 0, 0 ); + addStringConst( aPublics, "vbNullChar", aNullCharStr ); +} + +// ERROR n + +void SbiParser::ErrorStmnt() +{ + SbiExpression aPar( this ); + aPar.Gen(); + aGen.Gen( _ERROR ); +} + + +// AB 22.5.1996 +// JavaScript-Parsing zunaechst provisorisch hier implementiert +void SbiParser::OpenJavaBlock( SbiToken, SbiExprNode* ) +{ +} + +void SbiParser::CloseJavaBlock() +{ +} + +void SbiParser::JavaStmntBlock( SbiToken ) +{ +} + +void SbiParser::JavaBreak() +{ +} + +void SbiParser::JavaContinue() +{ +} + +void SbiParser::JavaFor() +{ +} + +void SbiParser::JavaFunction() +{ +} + +void SbiParser::JavaIf() +{ +} + +void SbiParser::JavaNew() +{ +} + +void SbiParser::JavaReturn() +{ +} + +void SbiParser::JavaThis() +{ +} + +void SbiParser::JavaVar() +{ +} + +void SbiParser::JavaWhile() +{ +} + +void SbiParser::JavaWith() +{ +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/comp/sbcomp.cxx b/binfilter/bf_basic/source/comp/sbcomp.cxx new file mode 100644 index 000000000000..1d703baceac7 --- /dev/null +++ b/binfilter/bf_basic/source/comp/sbcomp.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sbx.hxx" +#include "image.hxx" + + +// For debugging only +// #define DBG_SAVE_DISASSEMBLY + +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess3.hpp> +#include <com/sun/star/io/XTextOutputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> + +namespace binfilter { + +/*?*/ // #ifdef DBG_SAVE_DISASSEMBLY +/*?*/ // static bool dbg_bDisassemble = true; +/*?*/ // +/*?*/ // using namespace comphelper; +/*?*/ // using namespace rtl; +/*?*/ // using namespace com::sun::star::uno; +/*?*/ // using namespace com::sun::star::lang; +/*?*/ // using namespace com::sun::star::ucb; +/*?*/ // using namespace com::sun::star::io; +/*?*/ // +/*?*/ // void dbg_SaveDisassembly( SbModule* pModule ) +/*?*/ // { +/*?*/ // bool bDisassemble = dbg_bDisassemble; +/*?*/ // if( bDisassemble ) +/*?*/ // { +/*?*/ // Reference< XSimpleFileAccess3 > xSFI; +/*?*/ // Reference< XTextOutputStream > xTextOut; +/*?*/ // Reference< XOutputStream > xOut; +/*?*/ // Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); +/*?*/ // if( xSMgr.is() ) +/*?*/ // { +/*?*/ // Reference< XSimpleFileAccess3 > xSFI = Reference< XSimpleFileAccess3 >( xSMgr->createInstance +/*?*/ // ( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); +/*?*/ // if( xSFI.is() ) +/*?*/ // { +/*?*/ // String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///d:/BasicAsm_") ); +/*?*/ // StarBASIC* pBasic = (StarBASIC*)pModule->GetParent(); +/*?*/ // if( pBasic ) +/*?*/ // { +/*?*/ // aFile += pBasic->GetName(); +/*?*/ // aFile.AppendAscii( "_" ); +/*?*/ // } +/*?*/ // aFile += pModule->GetName(); +/*?*/ // aFile.AppendAscii( ".txt" ); +/*?*/ // +/*?*/ // // String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///d:/BasicAsm.txt") ); +/*?*/ // if( xSFI->exists( aFile ) ) +/*?*/ // xSFI->kill( aFile ); +/*?*/ // xOut = xSFI->openFileWrite( aFile ); +/*?*/ // Reference< XInterface > x = xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ) ); +/*?*/ // Reference< XActiveDataSource > xADS( x, UNO_QUERY ); +/*?*/ // xADS->setOutputStream( xOut ); +/*?*/ // xTextOut = Reference< XTextOutputStream >( x, UNO_QUERY ); +/*?*/ // } +/*?*/ // } +/*?*/ // +/*?*/ // if( xTextOut.is() ) +/*?*/ // { +/*?*/ // String aDisassemblyStr; +/*?*/ // pModule->Disassemble( aDisassemblyStr ); +/*?*/ // xTextOut->writeString( aDisassemblyStr ); +/*?*/ // } +/*?*/ // xOut->closeOutput(); +/*?*/ // } +/*?*/ // } +/*?*/ // #endif + +// Diese Routine ist hier definiert, damit der Compiler als eigenes Segment +// geladen werden kann. + +BOOL SbModule::Compile() +{ + DBG_ERROR( "SbModule::Compile: dead code!" ); + return FALSE; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/comp/scanner.cxx b/binfilter/bf_basic/source/comp/scanner.cxx new file mode 100644 index 000000000000..069c22b703ed --- /dev/null +++ b/binfilter/bf_basic/source/comp/scanner.cxx @@ -0,0 +1,559 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "scanner.hxx" +#include "sbintern.hxx" +#include "token.hxx" +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#if defined UNX +#include <stdlib.h> +#else +#include <math.h> // atof() +#endif +#include <rtl/math.hxx> +#include <vcl/svapp.hxx> +#include <unotools/charclass.hxx> + +namespace binfilter { + +SbiScanner::SbiScanner( const ::rtl::OUString& rBuf, StarBASIC* p ) : aBuf( rBuf ) +{ + pBasic = p; + pLine = NULL; + nVal = 0; + eScanType = SbxVARIANT; + nErrors = 0; + nBufPos = 0; + nCurCol1 = 0; + nSavedCol1 = 0; + nColLock = 0; + nLine = 0; + nCol1 = 0; + nCol2 = 0; + nCol = 0; + bError = + bAbort = + bSpaces = + bNumber = + bSymbol = + bUsedForHilite = + bCompatible = + bPrevLineExtentsComment = FALSE; + bHash = + bErrors = TRUE; +} + +SbiScanner::~SbiScanner() +{} + +/*?*/ // void SbiScanner::LockColumn() +/*?*/ // { +/*?*/ // if( !nColLock++ ) +/*?*/ // nSavedCol1 = nCol1; +/*?*/ // } +/*?*/ // +/*?*/ // void SbiScanner::UnlockColumn() +/*?*/ // { +/*?*/ // if( nColLock ) +/*?*/ // nColLock--; +/*?*/ // } +/*?*/ // +void SbiScanner::GenError( SbError code ) +{ + if( GetSbData()->bBlockCompilerError ) + { + bAbort = TRUE; + return; + } + if( !bError && bErrors ) + { + BOOL bRes = TRUE; + // Nur einen Fehler pro Statement reporten + bError = TRUE; + if( pBasic ) + { + // Falls EXPECTED oder UNEXPECTED kommen sollte, bezieht es sich + // immer auf das letzte Token, also die Col1 uebernehmen + USHORT nc = nColLock ? nSavedCol1 : nCol1; + switch( code ) + { + case SbERR_EXPECTED: + case SbERR_UNEXPECTED: + case SbERR_SYMBOL_EXPECTED: + case SbERR_LABEL_EXPECTED: + nc = nCol1; + if( nc > nCol2 ) nCol2 = nc; + break; + } + bRes = pBasic->CError( code, aError, nLine, nc, nCol2 ); + } + bAbort |= !bRes | + ( code == SbERR_NO_MEMORY || code == SbERR_PROG_TOO_LARGE ); + } + if( bErrors ) + nErrors++; +} + +// Testen auf ein legales Suffix + +static SbxDataType GetSuffixType( sal_Unicode c ) +{ + static String aSuffixesStr = String::CreateFromAscii( "%&!#@ $" ); + if( c ) + { + sal_uInt32 n = aSuffixesStr.Search( c ); + if( STRING_NOTFOUND != n && c != ' ' ) + return SbxDataType( (USHORT) n + SbxINTEGER ); + } + return SbxVARIANT; +} + +// Einlesen des naechsten Symbols in die Variablen aSym, nVal und eType +// Returnwert ist FALSE bei EOF oder Fehlern +#define BUF_SIZE 80 + +BOOL SbiScanner::NextSym() +{ + // Fuer den EOLN-Fall merken + USHORT nOldLine = nLine; + USHORT nOldCol1 = nCol1; + USHORT nOldCol2 = nCol2; + sal_Unicode buf[ BUF_SIZE ], *p = buf; + bHash = FALSE; + + eScanType = SbxVARIANT; + aSym.Erase(); + bSymbol = + bNumber = bSpaces = FALSE; + + // Zeile einlesen? + if( !pLine ) + { + INT32 n = nBufPos; + INT32 nLen = aBuf.getLength(); + if( nBufPos >= nLen ) + return FALSE; + const sal_Unicode* p2 = aBuf.getStr(); + p2 += n; + while( ( n < nLen ) && ( *p2 != '\n' ) && ( *p2 != '\r' ) ) + p2++, n++; + aLine = aBuf.copy( nBufPos, n - nBufPos ); + if( n < nLen ) + { + if( *p2 == '\r' && *( p2+1 ) == '\n' ) + n += 2; + else + n++; + } + nBufPos = n; + pLine = aLine.getStr(); + nOldLine = ++nLine; + nCol = nCol1 = nCol2 = nOldCol1 = nOldCol2 = 0; + nColLock = 0; + } + + // Leerstellen weg: + while( *pLine && (( *pLine == ' ' ) || ( *pLine == '\t' ) || ( *pLine == '\f' )) ) + pLine++, nCol++, bSpaces = TRUE; + + nCol1 = nCol; + + // nur Leerzeile? + if( !*pLine ) + goto eoln; + + if( bPrevLineExtentsComment ) + goto PrevLineCommentLbl; + + if( *pLine == '#' ) + { + pLine++; + nCol++; + bHash = TRUE; + } + + // Symbol? Dann Zeichen kopieren. + if( BasicSimpleCharClass::isAlpha( *pLine, bCompatible ) || *pLine == '_' ) + { + // Wenn nach '_' nichts kommt, ist es ein Zeilenabschluss! + if( *pLine == '_' && !*(pLine+1) ) + { pLine++; + goto eoln; } + bSymbol = TRUE; + short n = nCol; + for ( ; (BasicSimpleCharClass::isAlphaNumeric( *pLine, bCompatible ) || ( *pLine == '_' ) ); pLine++ ) + nCol++; + aSym = aLine.copy( n, nCol - n ); + // Abschliessendes '_' durch Space ersetzen, wenn Zeilenende folgt + // (sonst falsche Zeilenfortsetzung) + if( !bUsedForHilite && !*pLine && *(pLine-1) == '_' ) + { + aSym.GetBufferAccess(); // #109693 force copy if necessary + *((sal_Unicode*)(pLine-1)) = ' '; // cast wegen const + } + // Typkennung? + // Das Ausrufezeichen bitte nicht testen, wenn + // danach noch ein Symbol anschliesst + else if( *pLine != '!' || !BasicSimpleCharClass::isAlpha( pLine[ 1 ], bCompatible ) ) + { + SbxDataType t = GetSuffixType( *pLine ); + if( t != SbxVARIANT ) + { + eScanType = t; + pLine++; + nCol++; + } + } + } + + // Zahl? Dann einlesen und konvertieren. + else if( BasicSimpleCharClass::isDigit( *pLine & 0xFF ) + || ( *pLine == '.' && BasicSimpleCharClass::isDigit( *(pLine+1) & 0xFF ) ) ) + { + short exp = 0; + short comma = 0; + short ndig = 0; + short ncdig = 0; + eScanType = SbxDOUBLE; + BOOL bBufOverflow = FALSE; + while( strchr( "0123456789.DEde", *pLine ) && *pLine ) + { + // AB 4.1.1996: Buffer voll? -> leer weiter scannen + if( (p-buf) == (BUF_SIZE-1) ) + { + bBufOverflow = TRUE; + pLine++, nCol++; + continue; + } + // Komma oder Exponent? + if( *pLine == '.' ) + { + if( ++comma > 1 ) + { + pLine++; nCol++; continue; + } + else *p++ = *pLine++, nCol++; + } + else if( strchr( "DdEe", *pLine ) ) + { + if (++exp > 1) + { + pLine++; nCol++; continue; + } +// if( toupper( *pLine ) == 'D' ) +// eScanType = SbxDOUBLE; + *p++ = 'E'; pLine++; nCol++; + // Vorzeichen hinter Exponent? + if( *pLine == '+' ) + pLine++, nCol++; + else + if( *pLine == '-' ) + *p++ = *pLine++, nCol++; + } + else + { + *p++ = *pLine++, nCol++; + if( comma && !exp ) ncdig++; + } + if (!exp) ndig++; + } + *p = 0; + aSym = p; bNumber = TRUE; + // Komma, Exponent mehrfach vorhanden? + if( comma > 1 || exp > 1 ) + { aError = '.'; + GenError( SbERR_BAD_CHAR_IN_NUMBER ); } + + // #57844 Lokalisierte Funktion benutzen + nVal = rtl_math_uStringToDouble( buf, buf+(p-buf), '.', ',', NULL, NULL ); + // ALT: nVal = atof( buf ); + + ndig = ndig - comma; + if( !comma && !exp ) + { + if( nVal >= SbxMININT && nVal <= SbxMAXINT ) + eScanType = SbxINTEGER; + else + if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG ) + eScanType = SbxLONG; + } + if( bBufOverflow ) + GenError( SbERR_MATH_OVERFLOW ); + // zu viele Zahlen fuer SINGLE? +// if (ndig > 15 || ncdig > 6) +// eScanType = SbxDOUBLE; +// else +// if( nVal > SbxMAXSNG || nVal < SbxMINSNG ) +// eScanType = SbxDOUBLE; + + // Typkennung? + SbxDataType t = GetSuffixType( *pLine ); + if( t != SbxVARIANT ) + { + eScanType = t; + pLine++; + nCol++; + } + } + + // Hex/Oktalzahl? Einlesen und konvertieren: + else if( *pLine == '&' ) + { + pLine++; nCol++; + sal_Unicode cmp1[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', 0 }; + sal_Unicode cmp2[] = { '0', '1', '2', '3', '4', '5', '6', '7', 0 }; + sal_Unicode *cmp = cmp1; + //char *cmp = "0123456789ABCDEF"; + sal_Unicode base = 16; + sal_Unicode ndig = 8; + sal_Unicode xch = *pLine++ & 0xFF; nCol++; + switch( toupper( xch ) ) + { + case 'O': + cmp = cmp2; base = 8; ndig = 11; break; + //cmp = "01234567"; base = 8; ndig = 11; break; + case 'H': + break; + default : + // Wird als Operator angesehen + pLine--; nCol--; nCol1 = nCol-1; aSym = '&'; return SYMBOL; + } + bNumber = TRUE; + long l = 0; + int i; + BOOL bBufOverflow = FALSE; + while( BasicSimpleCharClass::isAlphaNumeric( *pLine & 0xFF, bCompatible ) ) + { + sal_Unicode ch = sal::static_int_cast< sal_Unicode >( + toupper( *pLine & 0xFF ) ); + pLine++; nCol++; + // AB 4.1.1996: Buffer voll, leer weiter scannen + if( (p-buf) == (BUF_SIZE-1) ) + bBufOverflow = TRUE; + else if( String( cmp ).Search( ch ) != STRING_NOTFOUND ) + //else if( strchr( cmp, ch ) ) + *p++ = ch; + else + { + aError = ch; + GenError( SbERR_BAD_CHAR_IN_NUMBER ); + } + } + *p = 0; + for( p = buf; *p; p++ ) + { + i = (*p & 0xFF) - '0'; + if( i > 9 ) i -= 7; + l = ( l * base ) + i; + if( !ndig-- ) + { + GenError( SbERR_MATH_OVERFLOW ); break; + } + } + if( *pLine == '&' ) pLine++, nCol++; + nVal = (double) l; + eScanType = ( l >= SbxMININT && l <= SbxMAXINT ) ? SbxINTEGER : SbxLONG; + if( bBufOverflow ) + GenError( SbERR_MATH_OVERFLOW ); + } + + // Strings: + else if( *pLine == '"' || *pLine == '[' ) + { + sal_Unicode cSep = *pLine; + if( cSep == '[' ) + bSymbol = TRUE, cSep = ']'; + short n = nCol+1; + while( *pLine ) + { + do pLine++, nCol++; + while( *pLine && ( *pLine != cSep ) ); + if( *pLine == cSep ) + { + pLine++; nCol++; + if( *pLine != cSep || cSep == ']' ) break; + } else aError = cSep, GenError( SbERR_EXPECTED ); + } + aSym = aLine.copy( n, nCol - n - 1 ); + // Doppelte Stringbegrenzer raus + String s( cSep ); + s += cSep; + USHORT nIdx = 0; + do + { + nIdx = aSym.Search( s, nIdx ); + if( nIdx == STRING_NOTFOUND ) + break; + aSym.Erase( nIdx, 1 ); + nIdx++; + } + while( true ); + if( cSep != ']' ) + eScanType = ( cSep == '#' ) ? SbxDATE : SbxSTRING; + } + // ungueltige Zeichen: + else if( ( *pLine & 0xFF ) >= 0x7F ) + { + GenError( SbERR_SYNTAX ); pLine++; nCol++; + } + // andere Gruppen: + else + { + short n = 1; + switch( *pLine++ ) + { + case '<': if( *pLine == '>' || *pLine == '=' ) n = 2; break; + case '>': if( *pLine == '=' ) n = 2; break; + case ':': if( *pLine == '=' ) n = 2; break; + } + aSym = aLine.copy( nCol, n ); + pLine += n-1; nCol = nCol + n; + } + + nCol2 = nCol-1; + +PrevLineCommentLbl: + // Kommentar? + if( bPrevLineExtentsComment || (eScanType != SbxSTRING && + ( aSym.GetBuffer()[0] == '\'' || aSym.EqualsIgnoreCaseAscii( "REM" ) ) ) ) + { + bPrevLineExtentsComment = FALSE; + aSym = String::CreateFromAscii( "REM" ); + USHORT nLen = String( pLine ).Len(); + if( bCompatible && pLine[ nLen - 1 ] == '_' && pLine[ nLen - 2 ] == ' ' ) + bPrevLineExtentsComment = TRUE; + nCol2 = nCol2 + nLen; + pLine = NULL; + } + return TRUE; + + // Sonst Zeilen-Ende: aber bitte auf '_' testen, ob die + // Zeile nicht weitergeht! +eoln: + if( nCol && *--pLine == '_' ) + { + pLine = NULL; return NextSym(); + } + else + { + pLine = NULL; + nLine = nOldLine; + nCol1 = nOldCol1; + nCol2 = nOldCol2; + aSym = '\n'; + nColLock = 0; + return TRUE; + } +} + +LetterTable BasicSimpleCharClass::aLetterTable; + +LetterTable::LetterTable( void ) +{ + for( int i = 0 ; i < 256 ; ++i ) + IsLetterTab[i] = false; + + IsLetterTab[0xC0] = true; // À , CAPITAL LETTER A WITH GRAVE ACCENT + IsLetterTab[0xC1] = true; // Á , CAPITAL LETTER A WITH ACUTE ACCENT + IsLetterTab[0xC2] = true; // Â , CAPITAL LETTER A WITH CIRCUMFLEX ACCENT + IsLetterTab[0xC3] = true; // Ã , CAPITAL LETTER A WITH TILDE + IsLetterTab[0xC4] = true; // Ä , CAPITAL LETTER A WITH DIAERESIS + IsLetterTab[0xC5] = true; // Å , CAPITAL LETTER A WITH RING ABOVE + IsLetterTab[0xC6] = true; // Æ , CAPITAL LIGATURE AE + IsLetterTab[0xC7] = true; // Ç , CAPITAL LETTER C WITH CEDILLA + IsLetterTab[0xC8] = true; // È , CAPITAL LETTER E WITH GRAVE ACCENT + IsLetterTab[0xC9] = true; // É , CAPITAL LETTER E WITH ACUTE ACCENT + IsLetterTab[0xCA] = true; // Ê , CAPITAL LETTER E WITH CIRCUMFLEX ACCENT + IsLetterTab[0xCB] = true; // Ë , CAPITAL LETTER E WITH DIAERESIS + IsLetterTab[0xCC] = true; // Ì , CAPITAL LETTER I WITH GRAVE ACCENT + IsLetterTab[0xCD] = true; // Í , CAPITAL LETTER I WITH ACUTE ACCENT + IsLetterTab[0xCE] = true; // Î , CAPITAL LETTER I WITH CIRCUMFLEX ACCENT + IsLetterTab[0xCF] = true; // Ï , CAPITAL LETTER I WITH DIAERESIS + IsLetterTab[0xD0] = true; // Ð , CAPITAL LETTER ETH + IsLetterTab[0xD1] = true; // Ñ , CAPITAL LETTER N WITH TILDE + IsLetterTab[0xD2] = true; // Ò , CAPITAL LETTER O WITH GRAVE ACCENT + IsLetterTab[0xD3] = true; // Ó , CAPITAL LETTER O WITH ACUTE ACCENT + IsLetterTab[0xD4] = true; // Ô , CAPITAL LETTER O WITH CIRCUMFLEX ACCENT + IsLetterTab[0xD5] = true; // Õ , CAPITAL LETTER O WITH TILDE + IsLetterTab[0xD6] = true; // Ö , CAPITAL LETTER O WITH DIAERESIS + IsLetterTab[0xD8] = true; // Ø , CAPITAL LETTER O WITH STROKE + IsLetterTab[0xD9] = true; // Ù , CAPITAL LETTER U WITH GRAVE ACCENT + IsLetterTab[0xDA] = true; // Ú , CAPITAL LETTER U WITH ACUTE ACCENT + IsLetterTab[0xDB] = true; // Û , CAPITAL LETTER U WITH CIRCUMFLEX ACCENT + IsLetterTab[0xDC] = true; // Ü , CAPITAL LETTER U WITH DIAERESIS + IsLetterTab[0xDD] = true; // Ý , CAPITAL LETTER Y WITH ACUTE ACCENT + IsLetterTab[0xDE] = true; // Þ , CAPITAL LETTER THORN + IsLetterTab[0xDF] = true; // ß , SMALL LETTER SHARP S + IsLetterTab[0xE0] = true; // à , SMALL LETTER A WITH GRAVE ACCENT + IsLetterTab[0xE1] = true; // á , SMALL LETTER A WITH ACUTE ACCENT + IsLetterTab[0xE2] = true; // â , SMALL LETTER A WITH CIRCUMFLEX ACCENT + IsLetterTab[0xE3] = true; // ã , SMALL LETTER A WITH TILDE + IsLetterTab[0xE4] = true; // ä , SMALL LETTER A WITH DIAERESIS + IsLetterTab[0xE5] = true; // å , SMALL LETTER A WITH RING ABOVE + IsLetterTab[0xE6] = true; // æ , SMALL LIGATURE AE + IsLetterTab[0xE7] = true; // ç , SMALL LETTER C WITH CEDILLA + IsLetterTab[0xE8] = true; // è , SMALL LETTER E WITH GRAVE ACCENT + IsLetterTab[0xE9] = true; // é , SMALL LETTER E WITH ACUTE ACCENT + IsLetterTab[0xEA] = true; // ê , SMALL LETTER E WITH CIRCUMFLEX ACCENT + IsLetterTab[0xEB] = true; // ë , SMALL LETTER E WITH DIAERESIS + IsLetterTab[0xEC] = true; // ì , SMALL LETTER I WITH GRAVE ACCENT + IsLetterTab[0xED] = true; // í , SMALL LETTER I WITH ACUTE ACCENT + IsLetterTab[0xEE] = true; // î , SMALL LETTER I WITH CIRCUMFLEX ACCENT + IsLetterTab[0xEF] = true; // ï , SMALL LETTER I WITH DIAERESIS + IsLetterTab[0xF0] = true; // ð , SMALL LETTER ETH + IsLetterTab[0xF1] = true; // ñ , SMALL LETTER N WITH TILDE + IsLetterTab[0xF2] = true; // ò , SMALL LETTER O WITH GRAVE ACCENT + IsLetterTab[0xF3] = true; // ó , SMALL LETTER O WITH ACUTE ACCENT + IsLetterTab[0xF4] = true; // ô , SMALL LETTER O WITH CIRCUMFLEX ACCENT + IsLetterTab[0xF5] = true; // õ , SMALL LETTER O WITH TILDE + IsLetterTab[0xF6] = true; // ö , SMALL LETTER O WITH DIAERESIS + IsLetterTab[0xF8] = true; // ø , SMALL LETTER O WITH OBLIQUE BAR + IsLetterTab[0xF9] = true; // ù , SMALL LETTER U WITH GRAVE ACCENT + IsLetterTab[0xFA] = true; // ú , SMALL LETTER U WITH ACUTE ACCENT + IsLetterTab[0xFB] = true; // û , SMALL LETTER U WITH CIRCUMFLEX ACCENT + IsLetterTab[0xFC] = true; // ü , SMALL LETTER U WITH DIAERESIS + IsLetterTab[0xFD] = true; // ý , SMALL LETTER Y WITH ACUTE ACCENT + IsLetterTab[0xFE] = true; // þ , SMALL LETTER THORN + IsLetterTab[0xFF] = true; // ÿ , SMALL LETTER Y WITH DIAERESIS +} + +bool LetterTable::isLetterUnicode( sal_Unicode c ) +{ + static CharClass* pCharClass = NULL; + if( pCharClass == NULL ) + pCharClass = new CharClass( Application::GetSettings().GetLocale() ); + String aStr( c ); + bool bRet = pCharClass->isLetter( aStr, 0 ); + return bRet; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/comp/token.cxx b/binfilter/bf_basic/source/comp/token.cxx new file mode 100644 index 000000000000..f26f2b750d5c --- /dev/null +++ b/binfilter/bf_basic/source/comp/token.cxx @@ -0,0 +1,575 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <ctype.h> +#include "token.hxx" + +namespace binfilter { + +struct TokenTable { SbiToken t; const char *s; }; + +static short nToken; // Anzahl der Tokens + +static TokenTable* pTokTable; + +static TokenTable aTokTable_Basic [] = { // Token-Tabelle: + + { CAT, "&" }, + { MUL, "*" }, + { PLUS, "+" }, + { MINUS, "-" }, + { DIV, "/" }, + { EOS, ":" }, + { ASSIGN, ":=" }, + { LT, "<" }, + { LE, "<=" }, + { NE, "<>" }, + { EQ, "=" }, + { GT, ">" }, + { GE, ">=" }, + { ACCESS, "Access" }, + { ALIAS, "Alias" }, + { AND, "And" }, + { ANY, "Any" }, + { APPEND, "Append" }, + { AS, "As" }, + { BASE, "Base" }, + { BINARY, "Binary" }, + { TBOOLEAN, "Boolean" }, + { BYREF, "ByRef", }, + { TBYTE, "Byte", }, + { BYVAL, "ByVal", }, + { CALL, "Call" }, + { CASE, "Case" }, + { _CDECL_, "Cdecl" }, + { CLASSMODULE, "ClassModule" }, + { CLOSE, "Close" }, + { COMPARE, "Compare" }, + { COMPATIBLE,"Compatible" }, + { _CONST_, "Const" }, + { TCURRENCY,"Currency" }, + { TDATE, "Date" }, + { DECLARE, "Declare" }, + { DEFBOOL, "DefBool" }, + { DEFCUR, "DefCur" }, + { DEFDATE, "DefDate" }, + { DEFDBL, "DefDbl" }, + { DEFERR, "DefErr" }, + { DEFINT, "DefInt" }, + { DEFLNG, "DefLng" }, + { DEFOBJ, "DefObj" }, + { DEFSNG, "DefSng" }, + { DEFSTR, "DefStr" }, + { DEFVAR, "DefVar" }, + { DIM, "Dim" }, + { DO, "Do" }, + { TDOUBLE, "Double" }, + { EACH, "Each" }, + { ELSE, "Else" }, + { ELSEIF, "ElseIf" }, + { END, "End" }, + { ENDENUM, "End Enum" }, + { ENDFUNC, "End Function" }, + { ENDIF, "End If" }, + { ENDPROPERTY, "End Property" }, + { ENDSELECT,"End Select" }, + { ENDSUB, "End Sub" }, + { ENDTYPE, "End Type" }, + { ENDIF, "EndIf" }, + { ENUM, "Enum" }, + { EQV, "Eqv" }, + { ERASE, "Erase" }, + { _ERROR_, "Error" }, + { EXIT, "Exit" }, + { EXPLICIT, "Explicit" }, + { FOR, "For" }, + { FUNCTION, "Function" }, + { GET, "Get" }, + { GLOBAL, "Global" }, + { GOSUB, "GoSub" }, + { GOTO, "GoTo" }, + { IF, "If" }, + { IMP, "Imp" }, + { IMPLEMENTS, "Implements" }, + { _IN_, "In" }, + { INPUT, "Input" }, // auch INPUT # + { TINTEGER, "Integer" }, + { IS, "Is" }, + { LET, "Let" }, + { LIB, "Lib" }, + { LINE, "Line" }, + { LINEINPUT,"Line Input" }, + { LOCAL, "Local" }, + { LOCK, "Lock" }, + { TLONG, "Long" }, + { LOOP, "Loop" }, + { LPRINT, "LPrint" }, + { LSET, "LSet" }, // JSM + { MOD, "Mod" }, + { NAME, "Name" }, + { NEW, "New" }, + { NEXT, "Next" }, + { NOT, "Not" }, + { TOBJECT, "Object" }, + { ON, "On" }, + { OPEN, "Open" }, + { OPTION, "Option" }, + { _OPTIONAL_, "Optional" }, + { OR, "Or" }, + { OUTPUT, "Output" }, + { PARAMARRAY, "ParamArray" }, + { PRESERVE, "Preserve" }, + { PRINT, "Print" }, + { PRIVATE, "Private" }, + { PROPERTY, "Property" }, + { PUBLIC, "Public" }, + { RANDOM, "Random" }, + { READ, "Read" }, + { REDIM, "ReDim" }, + { REM, "Rem" }, + { RESUME, "Resume" }, + { RETURN, "Return" }, + { RSET, "RSet" }, // JSM + { SELECT, "Select" }, + { SET, "Set" }, +#ifdef SHARED +#undef SHARED +#define tmpSHARED +#endif + { SHARED, "Shared" }, +#ifdef tmpSHARED +#define SHARED +#undef tmpSHARED +#endif + { TSINGLE, "Single" }, + { STATIC, "Static" }, + { STEP, "Step" }, + { STOP, "Stop" }, + { TSTRING, "String" }, + { SUB, "Sub" }, + { STOP, "System" }, + { TEXT, "Text" }, + { THEN, "Then" }, + { TO, "To", }, + { TYPE, "Type" }, + { TYPEOF, "TypeOf" }, + { UNTIL, "Until" }, + { TVARIANT, "Variant" }, + { VBASUPPORT, "VbaSupport" }, + { WEND, "Wend" }, + { WHILE, "While" }, + { WITH, "With" }, + { WRITE, "Write" }, // auch WRITE # + { XOR, "Xor" }, + { NIL, "" } +}; + +/* +TokenTable aTokTable_Java [] = { // Token-Tabelle: + + { JS_LOG_NOT, "!" }, + { JS_NE, "!=" }, + { JS_MOD, "%" }, + { JS_ASS_MOD, "%=" }, + { JS_BIT_AND, "&" }, + { JS_LOG_AND, "&&" }, + { JS_ASS_AND, "&=" }, + { JS_LPAREN, "(" }, + { JS_RPAREN, ")" }, + { JS_MUL, "*" }, + { JS_ASS_MUL, "*=" }, + { JS_PLUS, "+" }, + { JS_INC, "++" }, + { JS_ASS_PLUS, "+=" }, + { JS_COMMA, "," }, + { JS_MINUS, "-" }, + { JS_DEC, "--" }, + { JS_ASS_MINUS, "-=" }, + { JS_DIV, "/" }, + { JS_ASS_DIV, "/=" }, + { JS_COND_SEL, ":" }, + { JS_LT, "<" }, + { JS_LSHIFT, "<<" }, + { JS_ASS_LSHIFT,"<<=" }, + { JS_LE, "<=" }, + { JS_NE, "<>" }, + { JS_ASSIGNMENT,"=" }, + { JS_EQ, "==" }, + { JS_GT, ">" }, + { JS_RSHIFT, ">>" }, + { JS_ASS_RSHIFT,">>=" }, + { JS_RSHIFT_Z, ">>>" }, + { JS_ASS_RSHIFT_Z,">>>=" }, + { JS_GE, ">=" }, + { JS_COND_QUEST,"?" }, + { ACCESS, "Access" }, + { ALIAS, "Alias" }, + { AND, "And" }, + { ANY, "Any" }, + { APPEND, "Append" }, + { AS, "As" }, + { BASE, "Base" }, + { BINARY, "Binary" }, + { TBOOLEAN, "Boolean" }, + { BYVAL, "ByVal", }, + { CALL, "Call" }, + { CASE, "Case" }, + { _CDECL_, "Cdecl" }, + { CLOSE, "Close" }, + { COMPARE, "Compare" }, + { _CONST_, "Const" }, + { TCURRENCY,"Currency" }, + { TDATE, "Date" }, + { DECLARE, "Declare" }, + { DEFBOOL, "DefBool" }, + { DEFCUR, "DefCur" }, + { DEFDATE, "DefDate" }, + { DEFDBL, "DefDbl" }, + { DEFERR, "DefErr" }, + { DEFINT, "DefInt" }, + { DEFLNG, "DefLng" }, + { DEFOBJ, "DefObj" }, + { DEFSNG, "DefSng" }, + { DEFSTR, "DefStr" }, + { DEFVAR, "DefVar" }, + { DIM, "Dim" }, + { DO, "Do" }, + { TDOUBLE, "Double" }, + { EACH, "Each" }, + { ELSE, "Else" }, + { ELSEIF, "ElseIf" }, + { END, "End" }, + { ENDFUNC, "End Function" }, + { ENDIF, "End If" }, + { ENDSELECT,"End Select" }, + { ENDSUB, "End Sub" }, + { ENDTYPE, "End Type" }, + { ENDIF, "EndIf" }, + { EQV, "Eqv" }, + { ERASE, "Erase" }, + { _ERROR_, "Error" }, + { EXIT, "Exit" }, + { EXPLICIT, "Explicit" }, + { FOR, "For" }, + { FUNCTION, "Function" }, + { GLOBAL, "Global" }, + { GOSUB, "GoSub" }, + { GOTO, "GoTo" }, + { IF, "If" }, + { IMP, "Imp" }, + { _IN_, "In" }, + { INPUT, "Input" }, // auch INPUT # + { TINTEGER, "Integer" }, + { IS, "Is" }, + { LET, "Let" }, + { LIB, "Lib" }, + { LINE, "Line" }, + { LINEINPUT,"Line Input" }, + { LOCAL, "Local" }, + { LOCK, "Lock" }, + { TLONG, "Long" }, + { LOOP, "Loop" }, + { LPRINT, "LPrint" }, + { LSET, "LSet" }, // JSM + { MOD, "Mod" }, + { NAME, "Name" }, + { NEW, "New" }, + { NEXT, "Next" }, + { NOT, "Not" }, + { TOBJECT, "Object" }, + { ON, "On" }, + { OPEN, "Open" }, + { OPTION, "Option" }, + { _OPTIONAL_, "Optional" }, + { OR, "Or" }, + { OUTPUT, "Output" }, + { PRESERVE, "Preserve" }, + { PRINT, "Print" }, + { PRIVATE, "Private" }, + { PUBLIC, "Public" }, + { RANDOM, "Random" }, + { READ, "Read" }, + { REDIM, "ReDim" }, + { REM, "Rem" }, + { RESUME, "Resume" }, + { RETURN, "Return" }, + { RSET, "RSet" }, // JSM + { SELECT, "Select" }, + { SET, "Set" }, + { SHARED, "Shared" }, + { TSINGLE, "Single" }, + { STATIC, "Static" }, + { STEP, "Step" }, + { STOP, "Stop" }, + { TSTRING, "String" }, + { SUB, "Sub" }, + { STOP, "System" }, + { TEXT, "Text" }, + { THEN, "Then" }, + { TO, "To", }, + { TYPE, "Type" }, + { UNTIL, "Until" }, + { TVARIANT, "Variant" }, + { WEND, "Wend" }, + { WHILE, "While" }, + { WITH, "With" }, + { WRITE, "Write" }, // auch WRITE # + { XOR, "Xor" }, + { JS_LINDEX, "[" }, + { JS_RINDEX, "]" }, + { JS_BIT_XOR, "^" }, + { JS_ASS_XOR, "^=" }, + { JS_BIT_OR, "|" }, + { JS_ASS_OR, "|=" }, + { JS_LOG_OR, "||" }, + { JS_BIT_NOT, "~" }, + { NIL } +}; +*/ + +// Der Konstruktor ermittelt die Laenge der Token-Tabelle. + +SbiTokenizer::SbiTokenizer( const ::rtl::OUString& rSrc, StarBASIC* pb ) + : SbiScanner( rSrc, pb ) +{ + pTokTable = aTokTable_Basic; + //if( StarBASIC::GetGlobalLanguageMode() == SB_LANG_JAVASCRIPT ) + // pTokTable = aTokTable_Java; + TokenTable *tp; + bEof = bAs = FALSE; + eCurTok = NIL; + ePush = NIL; + bEos = bKeywords = bErrorIsSymbol = TRUE; + if( !nToken ) + for( nToken = 0, tp = pTokTable; tp->t; nToken++, tp++ ) {} +} + +SbiTokenizer::~SbiTokenizer() +{} + +// Einlesen des naechsten Tokens, ohne dass das Token geschluckt wird + +SbiToken SbiTokenizer::Peek() +{ + if( ePush == NIL ) + { + USHORT nOldLine = nLine; + USHORT nOldCol1 = nCol1; + USHORT nOldCol2 = nCol2; + ePush = Next(); + nPLine = nLine; nLine = nOldLine; + nPCol1 = nCol1; nCol1 = nOldCol1; + nPCol2 = nCol2; nCol2 = nOldCol2; + } + return eCurTok = ePush; +} + +// Einlesen des naechsten Tokens und Ablage desselben +// Tokens, die nicht in der Token-Tabelle vorkommen, werden +// direkt als Zeichen zurueckgeliefert. +// Einige Worte werden gesondert behandelt. + +SbiToken SbiTokenizer::Next() +{ + if (bEof) return EOLN; + // Schon eines eingelesen? + if( ePush != NIL ) + { + eCurTok = ePush; + ePush = NIL; + nLine = nPLine; + nCol1 = nPCol1; + nCol2 = nPCol2; + bEos = IsEoln( eCurTok ); + return eCurTok; + } + TokenTable *tp; + + // Sonst einlesen: + if( !NextSym() ) + { + bEof = bEos = TRUE; + return eCurTok = EOLN; + } + // Zeilenende? + if( aSym.GetBuffer()[0] == '\n' ) + { + bEos = TRUE; return eCurTok = EOLN; + } + bEos = FALSE; + + // Zahl? + if( bNumber ) + return eCurTok = NUMBER; + + // String? + else if( ( eScanType == SbxDATE || eScanType == SbxSTRING ) && !bSymbol ) + return eCurTok = FIXSTRING; + // Sonderfaelle von Zeichen, die zwischen "Z" und "a" liegen. ICompare() + // wertet die Position dieser Zeichen unterschiedlich aus. + else if( aSym.GetBuffer()[0] == '^' ) + return eCurTok = EXPON; + else if( aSym.GetBuffer()[0] == '\\' ) + return eCurTok = IDIV; + else + { + // Mit Typkennung oder ein Symbol und keine Keyword-Erkennung? + // Dann kein Token-Test + if( eScanType != SbxVARIANT + || ( !bKeywords && bSymbol ) ) + return eCurTok = SYMBOL; + // Gueltiges Token? + short lb = 0; + short ub = nToken-1; + short delta; + do + { + delta = (ub - lb) >> 1; + tp = &pTokTable[ lb + delta ]; + StringCompare res = aSym.CompareIgnoreCaseToAscii( tp->s ); + // Gefunden? + if( res == COMPARE_EQUAL ) goto special; + // Groesser? Dann untere Haelfte + if( res == COMPARE_LESS ) + { + if ((ub - lb) == 2) ub = lb; + else ub = ub - delta; + } + // Kleiner? Dann obere Haelfte + else + { + if ((ub -lb) == 2) lb = ub; + else lb = lb + delta; + } + } while( delta ); + // Symbol? Wenn nicht >= Token + sal_Unicode ch = aSym.GetBuffer()[0]; + if( !BasicSimpleCharClass::isAlpha( ch, bCompatible ) && !bSymbol ) + return eCurTok = (SbiToken) (ch & 0x00FF); + return eCurTok = SYMBOL; + } +special: + // LINE INPUT + if( tp->t == LINE ) + { + short nC1 = nCol1; + String aOldSym = aSym; + eCurTok = Peek(); + if( eCurTok == INPUT ) + { + Next(); + nCol1 = nC1; + return eCurTok = LINEINPUT; + } + else + { + aSym = aOldSym; + return eCurTok = LINE; + } + } + // END IF, CASE, SUB, DEF, FUNCTION, TYPE, CLASS, WITH + if( tp->t == END ) + { + // AB, 15.3.96, Spezialbehandlung fuer END, beim Peek() geht die + // aktuelle Zeile verloren, daher alles merken und danach restaurieren + USHORT nOldLine = nLine; + USHORT nOldCol = nCol; + USHORT nOldCol1 = nCol1; + USHORT nOldCol2 = nCol2; + String aOldSym = aSym; + SaveLine(); // pLine im Scanner sichern + + eCurTok = Peek(); + switch( eCurTok ) + { + case IF: Next(); eCurTok = ENDIF; break; + case SELECT: Next(); eCurTok = ENDSELECT; break; + case SUB: Next(); eCurTok = ENDSUB; break; + case FUNCTION: Next(); eCurTok = ENDFUNC; break; + case PROPERTY: Next(); eCurTok = ENDPROPERTY; break; + case TYPE: Next(); eCurTok = ENDTYPE; break; + case ENUM: Next(); eCurTok = ENDENUM; break; + case WITH: Next(); eCurTok = ENDWITH; break; + default : eCurTok = END; + } + nCol1 = nOldCol1; + if( eCurTok == END ) + { + // Alles zuruecksetzen, damit Token nach END ganz neu gelesen wird + ePush = NIL; + nLine = nOldLine; + nCol = nOldCol; + nCol2 = nOldCol2; + aSym = aOldSym; + RestoreLine(); // pLine im Scanner restaurieren + } + return eCurTok; + } + // Sind Datentypen Keywords? + // Nur nach AS, sonst sind es Symbole! + // Es gibt ja ERROR(), DATA(), STRING() etc. + eCurTok = tp->t; + // AS: Datentypen sind Keywords + if( tp->t == AS ) + bAs = TRUE; + else + { + if( bAs ) + bAs = FALSE; + else if( eCurTok >= DATATYPE1 && eCurTok <= DATATYPE2 && (bErrorIsSymbol || eCurTok != _ERROR_) ) + eCurTok = SYMBOL; + } + + // CLASSMODULE, PROPERTY, GET, ENUM token only visible in compatible mode + SbiToken eTok = tp->t; + if( bCompatible ) + { + // #129904 Suppress system + if( eTok == STOP && aSym.CompareIgnoreCaseToAscii( "system" ) == COMPARE_EQUAL ) + eCurTok = SYMBOL; + } + else + { + if( eTok == CLASSMODULE || + eTok == IMPLEMENTS || + eTok == PARAMARRAY || + eTok == ENUM || + eTok == PROPERTY || + eTok == GET || + eTok == TYPEOF ) + { + eCurTok = SYMBOL; + } + } + + bEos = IsEoln( eCurTok ); + return eCurTok; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/buffer.hxx b/binfilter/bf_basic/source/inc/buffer.hxx new file mode 100644 index 000000000000..bd232febdc3c --- /dev/null +++ b/binfilter/bf_basic/source/inc/buffer.hxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BUFFER_HXX +#define _BUFFER_HXX + +#include <tools/solar.h> +#include <tools/string.hxx> + +namespace binfilter { + +class SbiParser; + +class SbiBuffer { // Code/Konstanten-Puffer: + SbiParser* pParser; // fuer Fehlermeldungen + char* pBuf; // Puffer-Pointer + char* pCur; // aktueller Puffer-Pointer + UINT32 nOff; // aktuelles Offset + UINT32 nSize; // aktuelle Groesse + short nInc; // Inkrement + BOOL Check( USHORT ); // Buffergroesse testen +public: + SbiBuffer( SbiParser*, short ); // Inkrement + ~SbiBuffer(); + BOOL operator += (const String&);// Basic-String speichern + BOOL operator += (INT8); // Zeichen speichern + BOOL operator += (INT16); // Integer speichern + BOOL operator += (UINT8); // Zeichen speichern + BOOL operator += (UINT16); // Integer speichern + BOOL operator += (UINT32); // Integer speichern + BOOL operator += (INT32); // Integer speichern + char* GetBuffer(); // Puffer rausgeben (selbst loeschen!) + char* GetBufferPtr(){ return pBuf; } + UINT32 GetSize() { return nOff; } +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/codegen.hxx b/binfilter/bf_basic/source/inc/codegen.hxx new file mode 100644 index 000000000000..290c5a999f6c --- /dev/null +++ b/binfilter/bf_basic/source/inc/codegen.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CODEGEN_HXX +#define _CODEGEN_HXX + +namespace binfilter { + +class SbiImage; +class SbiParser; +class SbModule; + +class SbiCodeGen { // Code-Erzeugung: +/*?*/ // SbiParser* pParser; // fuer Fehlermeldungen, Line, Column etc. +/*?*/ // SbModule& rMod; // aktuelles Modul +/*?*/ // SbiBuffer aCode; // Code-Puffer +/*?*/ // short nLine, nCol; // Zeile, Spalte fuer Stmnt-Befehl +/*?*/ // short nForLevel; // #29955 for-Schleifen-Ebene +/*?*/ // BOOL bStmnt; // TRUE: Statement-Opcode liegt an +public: +/*?*/ // SbiCodeGen( SbModule&, SbiParser*, short ); +/*?*/ // SbiParser* GetParser() { return pParser; } +/*?*/ // UINT32 Gen( SbiOpcode ); +/*?*/ // UINT32 Gen( SbiOpcode, UINT32 ); +/*?*/ // UINT32 Gen( SbiOpcode, UINT32, UINT32 ); +/*?*/ // void Patch( UINT32 o, UINT32 v ){ aCode.Patch( o, v ); } +/*?*/ // void BackChain( UINT32 off ) { aCode.Chain( off ); } +/*?*/ // void Statement(); +/*?*/ // void GenStmnt(); // evtl. Statement-Opcode erzeugen +/*?*/ // UINT32 GetPC(); +/*?*/ // UINT32 GetOffset() { return GetPC() + 1; } +/*?*/ // void Save(); +/*?*/ // +/*?*/ // // #29955 for-Schleifen-Ebene pflegen +/*?*/ // void IncForLevel( void ) { nForLevel++; } +/*?*/ // void DecForLevel( void ) { nForLevel--; } +/*?*/ // + static UINT32 calcNewOffSet( BYTE* pCode, UINT16 nOffset ); + static UINT16 calcLegacyOffSet( BYTE* pCode, UINT32 nOffset ); +/*?*/ // +}; + +template < class T, class S > +class PCodeBuffConvertor +{ + T m_nSize; // + BYTE* m_pStart; + BYTE* m_pCnvtdBuf; + S m_nCnvtdSize; // + + // Disable usual copying symantics and bodgy default ctor + PCodeBuffConvertor(); + PCodeBuffConvertor(const PCodeBuffConvertor& ); + PCodeBuffConvertor& operator = ( const PCodeBuffConvertor& ); +public: + PCodeBuffConvertor( BYTE* pCode, T nSize ): m_nSize( nSize ), m_pStart( pCode ), m_pCnvtdBuf( NULL ), m_nCnvtdSize( 0 ){ convert(); } + S GetSize(){ return m_nCnvtdSize; } + void convert(); + // Caller owns the buffer returned + BYTE* GetBuffer() { return m_pCnvtdBuf; } +}; + +// #111897 PARAM_INFO flags start at 0x00010000 to not +// conflict with DefaultId in SbxParamInfo::nUserData +#define PARAM_INFO_PARAMARRAY 0x0010000 + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/filefmt.hxx b/binfilter/bf_basic/source/inc/filefmt.hxx new file mode 100644 index 000000000000..8805d0253a01 --- /dev/null +++ b/binfilter/bf_basic/source/inc/filefmt.hxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SB_FILEFMT_HXX +#define _SB_FILEFMT_HXX + +#include <tools/solar.h> + +class SvStream; + +namespace binfilter { + +// Version 2: Datentyp des Returnwerts fuer Publics +// Version 3: neue Opcodes +// Version 4: neue Opcodes +// Version 5: Bug (Ansprung von STATIC-Variablen im Init-Code) +// Version 6: Neue Opcodes und Bug (Globals anlegen, ohne BASIC zu beenden) +// Version 7: Korrektur im WITH-Parsing +// Version 8: Korrektur im IF-Parsing +// Version 9: Init-Code auch mit LEAVE beenden, wenn keine SUB/FUNCTION folgt +// Version A: #36374 Bei DIM AS NEW... auch Variablen anlegen +// Version B: #40689 Static umgestellt +// Version C: #41606 Bug bei Static +// Version D: #42678 Bug bei RTL-Function spc +// Version E: #56204 DCREATE, um auch bei DIM AS NEW Arrays anzulegen +// Version F: #57844 Einfuehrung von SvNumberformat::StringToDouble +// Version 10: #29955 For-Schleifen-Level in Statement-PCodes generieren +// Version 11: #29955 Wegen Build-Inkonsistenzen Neu-Compilieren erzwingen + +#define B_LEGACYVERSION 0x00000011L +#define B_CURVERSION 0x00000012L +#define B_EXT_IMG_VERSION 0x00000012L + +// Eine Datei enthaelt entweder einen Modul- oder einen Library-Record. +// Diese Records enthalten wiederum weitere Records. Jeder Record hat +// den folgenden Header: + +// UINT16 Kennung +// UINT32 Laenge des Records ohne Header +// UINT16 Anzahl Unterelemente + +// Alle Datei-Offsets in Records sind relativ zum Start des Moduls! + +#define B_LIBRARY 0x4C42 // BL Library Record +#define B_MODULE 0x4D42 // BM Module Record +#define B_NAME 0x4E4D // MN module name +#define B_COMMENT 0x434D // MC comment +#define B_SOURCE 0x4353 // SC source code +#define B_PCODE 0x4350 // PC p-code +#define B_OLDPUBLICS 0x7550 // Pu publics +#define B_PUBLICS 0x5550 // PU publics +#define B_POOLDIR 0x4450 // PD symbol pool directory +#define B_SYMPOOL 0x5953 // SY symbol pool +#define B_STRINGPOOL 0x5453 // ST symbol pool +#define B_LINERANGES 0x524C // LR line ranges for publics +#define B_MODEND 0x454D // ME module end +#define B_SBXOBJECTS 0x5853 // SX SBX objects + +#define EXTENDED_BINARY_MODULES +#ifdef EXTENDED_BINARY_MODULES +#define B_EXTSOURCE 0x5345 // ES extended source +#endif + +// Ein Library Record enthaelt nur Module Records +// UINT16 Kennung BL +// UINT32 Laenge des Records +// UINT16 Anzahl Module + +// Ein Modul-Record enthaelt alle anderen Recordtypen +// UINT16 Kennung BM +// UINT32 Laenge des Records +// UINT16 1 +// Daten: +// UINT32 Versionsnummer +// UINT32 Zeichensatz +// UINT32 Startadresse Initialisierungscode +// UINT32 Startadresse Sub Main +// UINT32 Reserviert +// UINT32 Reserviert + +// Modulname, Kommentar und Quellcode: +// UINT16 Kennung MN, MC oder SC +// UINT32 Laenge des Records +// UINT16 1 +// Daten: +// String-Instanz + +// P-Code: +// UINT16 Kennung PC +// UINT32 Laenge des Records +// UINT16 1 +// Daten: +// Der P-Code als Bytesack + +// Alle Symbole und Strings werden in einem String-Pool gehalten. +// Verweise auf diese Strings sind in Form eines Indexes in diesen Pool. + +// Liste aller Publics: +// UINT16 Kennung PU oder Pu +// UINT32 Laenge des Records +// UINT16 Anzahl der Publics +// Daten fuer jeden Public-Eintrag: +// UINT16 String-Index +// UINT32 Startadresse im P-Code-Image (UINT16 fuer alte Publics) +// UINT16 Datentyp des Returnwertes (ab Version 2) + +// Verzeichnis der Symbol-Tabellen: +// UINT16 Kennung SP +// UINT32 Laenge des Records +// UINT16 Anzahl der Symboltabellen +// Daten fuer jede Symboltabelle: +// UINT16 Stringindex des Namens +// UINT16 Anzahl Symbole +// UINT16 Scope-Kennung + +// Symboltabelle: +// UINT16 Kennung SY +// UINT32 Laenge des Records +// UINT16 Anzahl der Symbole +// Daten: +// UINT16 Stringindex des Namens +// UINT16 Anzahl Symbole +// Daten fuer jedes Symbol: +// UINT16 Stringindex des Namens +// UINT16 Datentyp +// UINT16 Laenge bei STRING*n-Symbolen (0x8000: STATIC-Variable) + +// Stringpool: +// UINT16 Kennung ST +// UINT32 Laenge des Records +// UINT16 Anzahl der Strings +// Daten fuer jeden String: +// UINT32 Offset in den Block aller Strings +// Danach folgt der Block aller Strings, die dort als ASCIIZ-Strings liegen. + +// Line Ranges: +// UINT16 Kennung LR +// UINT32 Laenge des Records +// UINT16 Anzahl der Strings +// Daten fuer jedes Public: +// UINT16 1. Zeile (Sub XXX) +// UINT16 2. Zeile (End Sub) + +// SBX-Objekte: +// UINT16 Anzahl Objekte +// .... Objektdaten + +//////////////////////////////////////////////////////////////////////////// + +// Service-Routinen (in IMAGE.CXX) + +BOOL SbGood( SvStream& r ); +ULONG SbOpenRecord( SvStream&, UINT16 nSignature, UINT16 nElem ); +void SbCloseRecord( SvStream&, ULONG ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/image.hxx b/binfilter/bf_basic/source/inc/image.hxx new file mode 100644 index 000000000000..cc317931978d --- /dev/null +++ b/binfilter/bf_basic/source/inc/image.hxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBIMAGE_HXX +#define _SBIMAGE_HXX + +#include "sbintern.hxx" +#include <rtl/ustring.hxx> +#include "filefmt.hxx" + +// Diese Klasse liest das vom Compiler erzeugte Image ein und verwaltet +// den Zugriff auf die einzelnen Elemente. + +namespace binfilter { + +struct SbPublicEntry; + +class SbiImage { + friend class SbiCodeGen; // Compiler-Klassen, die die private- + + SbxArrayRef rTypes; // User defined types + SbxArrayRef rEnums; // Enum types + UINT32* pStringOff; // StringId-Offsets + sal_Unicode* pStrings; // StringPool + char* pCode; // Code-Image + char* pLegacyPCode; // Code-Image + BOOL bError; // TRUE: Fehler + USHORT nFlags; // Flags (s.u.) + short nStrings; // Anzahl Strings + UINT32 nStringSize; // Groesse des String-Puffers + UINT32 nCodeSize; // Groesse des Code-Blocks + UINT16 nLegacyCodeSize; // Groesse des Code-Blocks + UINT16 nDimBase; // OPTION BASE-Wert + rtl_TextEncoding eCharSet; // Zeichensatz fuer Strings + // temporaere Verwaltungs-Variable: + short nStringIdx; // aktueller String-Index + UINT32 nStringOff; // aktuelle Pos im Stringpuffer + // Routinen fuer Compiler: + void MakeStrings( short ); // StringPool einrichten + +public: + String aName; // Makroname + ::rtl::OUString aOUSource; // Quellcode + String aComment; // Kommentar + BOOL bInit; // TRUE: Init-Code ist gelaufen + BOOL bFirstInit; // TRUE, wenn das Image das erste mal nach + // dem Compilieren initialisiert wird. + SbiImage(); + ~SbiImage(); + void Clear(); // Inhalt loeschen + BOOL Load( SvStream&, UINT32& nVer ); // Loads image from stream + // nVer is set to version + // of image + BOOL Save( SvStream&, UINT32 = B_CURVERSION ); + BOOL IsError() { return bError; } + + const char* GetCode() const { return pCode; } + UINT32 GetCodeSize() const { return nCodeSize; } + ::rtl::OUString& GetSource32() { return aOUSource; } + USHORT GetBase() const { return nDimBase; } + const SbxObject* FindType (String aTypeName) const; + + SbxArrayRef GetEnums() { return rEnums; } + + void SetFlag( USHORT n ) { nFlags |= n; } + USHORT GetFlag( USHORT n ) const { return nFlags & n; } + UINT16 CalcLegacyOffset( INT32 nOffset ); + UINT32 CalcNewOffset( INT16 nOffset ); + void ReleaseLegacyBuffer(); + BOOL ExceedsLegacyLimits(); + +}; + +#define SBIMG_EXPLICIT 0x0001 // OPTION EXPLICIT ist aktiv +#define SBIMG_COMPARETEXT 0x0002 // OPTION COMPARE TEXT ist aktiv +#define SBIMG_INITCODE 0x0004 // Init-Code vorhanden +#define SBIMG_CLASSMODULE 0x0008 // OPTION ClassModule is active +#define SBIMG_VBASUPPORT 0x0020 // OPTION VBASupport is 1 + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/opcodes.hxx b/binfilter/bf_basic/source/inc/opcodes.hxx new file mode 100644 index 000000000000..a670ed029639 --- /dev/null +++ b/binfilter/bf_basic/source/inc/opcodes.hxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _OPCODES_HXX +#define _OPCODES_HXX + +#include "sbintern.hxx" + +#ifdef MTW +#undef _NUMBER +#endif + +// Ein Opcode ist entweder 1, 3 oder 5 Bytes lang, je nach numerischen +// Wert des Opcodes (s.u.). + +enum SbiOpcode { + // Alle Opcodes ohne Operanden + _NOP = 0, + + SbOP0_START = _NOP, + + // Operatoren + // die folgenden Operatoren sind genauso angeordnet + // wie der enum SbxVarOp + _EXP, _MUL, _DIV, _MOD, _PLUS, _MINUS, _NEG, + _EQ, _NE, _LT, _GT, _LE, _GE, + _IDIV, _AND, _OR, _XOR, _EQV, _IMP, _NOT, + _CAT, + // Ende enum SbxVarOp + _LIKE, _IS, + // Laden/speichern + _ARGC, // neuen Argv einrichten + _ARGV, // TOS ==> aktueller Argv + _INPUT, // Input ==> TOS + _LINPUT, // Line Input ==> TOS + _GET, // TOS anfassen + _SET, // Speichern Objekt TOS ==> TOS-1 + _PUT, // TOS ==> TOS-1 + _PUTC, // TOS ==> TOS-1, dann ReadOnly + _DIM, // DIM + _REDIM, // REDIM + _REDIMP, // REDIM PRESERVE + _ERASE, // TOS loeschen + // Verzweigen + _STOP, // Programmende + _INITFOR, // FOR-Variable initialisieren + _NEXT, // FOR-Variable inkrementieren + _CASE, // Anfang CASE + _ENDCASE, // Ende CASE + _STDERROR, // Standard-Fehlerbehandlung + _NOERROR, // keine Fehlerbehandlung + _LEAVE, // UP verlassen + // E/A + _CHANNEL, // TOS = Kanalnummer + _BPRINT, // print TOS + _PRINTF, // print TOS in field + _BWRITE, // write TOS + _RENAME, // Rename Tos+1 to Tos + _PROMPT, // TOS = Prompt for Input + _RESTART, // Restartpunkt definieren + _CHAN0, // I/O-Kanal 0 + // Sonstiges + _EMPTY, // Leeren Ausdruck auf Stack + _ERROR, // TOS = Fehlercode + _LSET, // Speichern Objekt TOS ==> TOS-1 + _RSET, // Speichern Objekt TOS ==> TOS-1 + _REDIMP_ERASE, // Copies array to be later used by REDIM PRESERVE before erasing it + _INITFOREACH, + _VBASET, // VBA-like Set + SbOP0_END, + + // Alle Opcodes mit einem Operanden + + _NUMBER = 0x40, // Laden einer numerischen Konstanten (+ID) + + SbOP1_START = _NUMBER, + + _SCONST, // Laden einer Stringkonstanten (+ID) + _CONST, // Immediate Load (+Wert) + _ARGN, // Speichern eines named Args in Argv (+StringID) + _PAD, // String auf feste Laenge bringen (+Laenge) + // Verzweigungen + _JUMP, // Sprung (+Target) + _JUMPT, // TOS auswerten, bedingter Sprung (+Target) + _JUMPF, // TOS auswerten, bedingter Sprung (+Target) + _ONJUMP, // TOS auswerten, Sprung in JUMP-Tabelle (+MaxVal) + _GOSUB, // UP-Aufruf (+Target) + _RETURN, // UP-Return (+0 oder Target) + _TESTFOR, // FOR-Variable testen, inkrementieren (+Endlabel) + _CASETO, // Tos+1 <= Case <= Tos, 2xremove (+Target) + _ERRHDL, // Fehler-Handler (+Offset) + _RESUME, // Resume nach Fehlern (+0 or 1 or Label) + // E/A + _CLOSE, // (+Kanal/0) + _PRCHAR, // (+char) + // Verwaltung + _SETCLASS, // Set + Klassennamen testen (+StringId) + _TESTCLASS, // Check TOS class (+StringId) + _LIB, // Libnamen fuer Declare-Procs setzen (+StringId) + _BASED, // TOS wird um BASE erhoeht, BASE davor gepusht (+base) + // Typanpassung im Argv + _ARGTYP, // Letzten Parameter in Argv konvertieren (+Typ) + SbOP1_END, + + // Alle Opcodes mit zwei Operanden + + _RTL = 0x80, // Laden aus RTL (+StringID+Typ) + + SbOP2_START = _RTL, + + _FIND, // Laden (+StringID+Typ) + _ELEM, // Laden Element (+StringID+Typ) + _PARAM, // Parameter (+Offset+Typ) + // Verzweigen + _CALL, // DECLARE-Methode rufen (+StringID+Typ) + _CALLC, // Cdecl-DECLARE-Methode rufen (+StringID+Typ) + _CASEIS, // Case-Test (+Test-Opcode+True-Target) + // Verwaltung + _STMNT, // Beginn eines Statements (+Line+Col) + // E/A + _OPEN, // (+SvStreamFlags+Flags) + // Objekte + _LOCAL, // Lokale Variable definieren (+StringID+Typ) + _PUBLIC, // Modulglobale Variable (+StringID+Typ) + _GLOBAL, // Globale Variable definieren, public-Anweisung (+StringID+Typ) + _CREATE, // Objekt kreieren (+StringId+StringID) + _STATIC, // Statische Variabl (+StringID+Typ) JSM + _TCREATE, // User Defined Objekt kreieren + _DCREATE, // Objekt-Array kreieren (+StringId+StringID) + _GLOBAL_P, // Globale Variable definieren, die beim Neustart von Basic + // nicht ueberschrieben wird, P=PERSIST (+StringID+Typ) + _FIND_G, // Sucht globale Variable mit Spezialbehandlung wegen _GLOBAL_P + _DCREATE_REDIMP, // Objekt-Array redimensionieren (+StringId+StringID) + _FIND_CM, // Search inside a class module (CM) to enable global search in time + SbOP2_END + +}; + + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/sbintern.hxx b/binfilter/bf_basic/source/inc/sbintern.hxx new file mode 100644 index 000000000000..01ec2fea482d --- /dev/null +++ b/binfilter/bf_basic/source/inc/sbintern.hxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SB_INTERN_HXX +#define _SB_INTERN_HXX + +#include <sbxfac.hxx> +#include <unotools/transliterationwrapper.hxx> +#include "sb.hxx" + +namespace +{ + class TransliterationWrapper; +} + +namespace binfilter { + +class SbUnoFactory; +class SbTypeFactory; +class SbOLEFactory; +class SbiInstance; +class SbModule; + +class SbiFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +struct SbClassData +{ + SbxArrayRef mxIfaces; + + ~SbClassData( void ) + { clear(); } + void clear( void ); +}; + +// #115824: Factory class to create class objects (type command) +// Implementation: sb.cxx +class SbClassFactory : public SbxFactory +{ + SbxObjectRef xClassModules; + +public: + SbClassFactory( void ); + virtual ~SbClassFactory(); + + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +// Stack fuer die im Fehlerfall abgebaute SbiRuntime Kette +class SbErrorStackEntry +{ +public: + SbErrorStackEntry(SbMethodRef aM, xub_StrLen nL, xub_StrLen nC1, xub_StrLen nC2) + : aMethod(aM), nLine(nL), nCol1(nC1), nCol2(nC2) {} + SbMethodRef aMethod; + xub_StrLen nLine; + xub_StrLen nCol1, nCol2; +}; + +SV_DECL_PTRARR_DEL(SbErrorStack, SbErrorStackEntry*, 1, 1) + + + +struct SbiGlobals +{ + SbiInstance* pInst; // alle aktiven Runtime-Instanzen + SbiFactory* pSbFac; // StarBASIC-Factory + SbUnoFactory* pUnoFac; // Factory fuer Uno-Structs bei DIM AS NEW + SbTypeFactory* pTypeFac; // Factory for user defined types + SbClassFactory* pClassFac; // Factory for user defined classes (based on class modules) + SbOLEFactory* pOLEFac; // Factory for OLE types + SbModule* pMod; // aktuell aktives Modul + SbModule* pCompMod; // aktuell compiliertes Modul + short nInst; // Anzahl BASICs + Link aErrHdl; // globaler Error-Handler + Link aBreakHdl; // globaler Break-Handler + SbError nCode; // aktueller Fehlercode + xub_StrLen nLine; // aktuelle Zeile + xub_StrLen nCol1,nCol2; // aktuelle Spalten (von,bis) + BOOL bCompiler; // Flag fuer Compiler-Error + BOOL bGlobalInitErr; // Beim GlobalInit trat ein Compiler-Fehler auf + BOOL bRunInit; // TRUE, wenn RunInit vom Basic aktiv ist + String aErrMsg; // Puffer fuer GetErrorText() + SbLanguageMode eLanguageMode; // Flag fuer Visual-Basic-Script-Modus + SbErrorStack* pErrStack; // Stack fuer die im Fehlerfall abgebaute SbiRuntime Kette + ::utl::TransliterationWrapper* pTransliterationWrapper; // For StrComp + BOOL bBlockCompilerError; + BasicManager* pAppBasMgr; + + SbiGlobals(); + ~SbiGlobals(); +}; + +// Utility-Makros und -Routinen + +SbiGlobals* GetSbData(); + +#define pINST GetSbData()->pInst +#define pMOD GetSbData()->pMod +#define pCMOD GetSbData()->pCompMod +#define pSBFAC GetSbData()->pSbFac +#define pUNOFAC GetSbData()->pUnoFac +#define pTYPEFAC GetSbData()->pTypeFac +#define pCLASSFAC GetSbData()->pClassFac +#define pOLEFAC GetSbData()->pOLEFac + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/sbjsmeth.hxx b/binfilter/bf_basic/source/inc/sbjsmeth.hxx new file mode 100644 index 000000000000..dfd9c85c5a88 --- /dev/null +++ b/binfilter/bf_basic/source/inc/sbjsmeth.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _SB_SBJSMETH_HXX +#define _SB_SBJSMETH_HXX + +#include "sbmeth.hxx" + +namespace binfilter { + +// Basic-Modul fuer JavaScript-Sourcen. +// Alle Basic-spezifischen Methoden muessen virtuell ueberladen und deaktiviert +// werden. Die Unterscheidung von normalen Modulen erfolgt uebr RTTI. + +class SbJScriptMethod : public SbMethod +{ +public: + SbJScriptMethod( const String&, SbxDataType, SbModule* ); + virtual ~SbJScriptMethod(); + + SBX_DECL_PERSIST_NODATA(SBXCR_SBX,SBXID_JSCRIPTMETH,2); + TYPEINFO(); +}; + +#ifndef __SB_SBJSCRIPTMETHODREF_HXX +#define __SB_SBJSCRIPTMETHODREF_HXX +SV_DECL_IMPL_REF(SbJScriptMethod) +#endif + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/sbjsmod.hxx b/binfilter/bf_basic/source/inc/sbjsmod.hxx new file mode 100644 index 000000000000..835f23a72fb0 --- /dev/null +++ b/binfilter/bf_basic/source/inc/sbjsmod.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SB_SBJSMOD_HXX +#define _SB_SBJSMOD_HXX + +#include "sbmod.hxx" + +namespace binfilter { + +// Basic-Modul fuer JavaScript-Sourcen. +// Alle Basic-spezifischen Methoden muessen virtuell ueberladen und deaktiviert +// werden. Die Unterscheidung von normalen Modulen erfolgt uebr RTTI. + +class SbJScriptModule : public SbModule +{ + virtual BOOL LoadData( SvStream&, USHORT ); + virtual BOOL StoreData( SvStream& ) const; +public: + SBX_DECL_PERSIST_NODATA(SBXCR_SBX,SBXID_JSCRIPTMOD,1); + TYPEINFO(); + SbJScriptModule( const String& ); // DURCHREICHEN +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/sbunoobj.hxx b/binfilter/bf_basic/source/inc/sbunoobj.hxx new file mode 100644 index 000000000000..47e93dab804a --- /dev/null +++ b/binfilter/bf_basic/source/inc/sbunoobj.hxx @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef SB_UNO_OBJ +#define SB_UNO_OBJ + +#include "sbxobj.hxx" +#include "sbxmeth.hxx" +#include "sbxprop.hxx" +#include "sbxfac.hxx" +#include "sbx.hxx" + +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <com/sun/star/beans/XExactName.hpp> +#include <com/sun/star/beans/XIntrospectionAccess.hpp> +#include <com/sun/star/beans/XIntrospection.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/reflection/XIdlClass.hpp> +#ifndef _RTL_USTRING_ +#include <rtl/ustring.hxx> +#endif + +namespace binfilter { + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::script; +using namespace com::sun::star::reflection; + +class SbUnoObject: public SbxObject +{ + Reference< XIntrospectionAccess > mxUnoAccess; + Reference< XMaterialHolder > mxMaterialHolder; + Reference< XInvocation > mxInvocation; + Reference< XExactName > mxExactName; + Reference< XExactName > mxExactNameInvocation; + BOOL bNeedIntrospection; + Any maTmpUnoObj; // Only to save obj for doIntrospection! + + // Hilfs-Methode zum Anlegen der dbg_-Properties + void implCreateDbgProperties( void ); + + // Hilfs-Methode zum Anlegen aller Properties und Methoden + // (Beim on-demand-Mechanismus erforderlich fuer die dbg_-Properties) + void implCreateAll( void ); + +public: + TYPEINFO(); + SbUnoObject( const String& aName_, const Any& aUnoObj_ ); + ~SbUnoObject(); + + // #76470 Introspection on Demand durchfuehren + void doIntrospection( void ); + + // Find ueberladen, um z.B. NameAccess zu unterstuetzen + virtual SbxVariable* Find( const String&, SbxClassType ); + + // Force creation of all properties for debugging + void createAllProperties( void ) + { implCreateAll(); } + + // Wert rausgeben + Any getUnoAny( void ); + Reference< XIntrospectionAccess > getIntrospectionAccess( void ) { return mxUnoAccess; } + Reference< XInvocation > getInvocation( void ) { return mxInvocation; } + + void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); +}; +SV_DECL_IMPL_REF(SbUnoObject); + + +class SbUnoMethod : public SbxMethod +{ + friend class SbUnoObject; + + Reference< XIdlMethod > m_xUnoMethod; + Sequence<ParamInfo>* pParamInfoSeq; + + // #67781 Verweis auf vorige und naechste Methode in der Methoden-Liste + SbUnoMethod* pPrev; + SbUnoMethod* pNext; + + bool mbInvocation; // Method is based on invocation + +public: + TYPEINFO(); + + SbUnoMethod( const String& aName_, SbxDataType eSbxType, Reference< XIdlMethod > xUnoMethod_, + bool bInvocation ); + virtual ~SbUnoMethod(); + virtual SbxInfo* GetInfo(); + + const Sequence<ParamInfo>& getParamInfos( void ); + + bool isInvocationBased( void ) + { return mbInvocation; } +}; + + +class SbUnoProperty : public SbxProperty +{ + friend class SbUnoObject; + + // Daten der Uno-Property + Property aUnoProp; + INT32 nId; + + bool mbInvocation; // Property is based on invocation + + virtual ~SbUnoProperty(); +public: + TYPEINFO(); + SbUnoProperty( const String& aName_, SbxDataType eSbxType, + const Property& aUnoProp_, INT32 nId_, bool bInvocation ); + + bool isInvocationBased( void ) + { return mbInvocation; } +}; + +// Factory-Klasse fuer das Anlegen von Uno-Structs per DIM AS NEW +class SbUnoFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); +}; + +// Wrapper fuer eine Uno-Klasse +class SbUnoClass: public SbxObject +{ + const Reference< XIdlClass > m_xClass; + +public: + TYPEINFO(); + SbUnoClass( const String& aName_ ) + : SbxObject( aName_ ) + {} + SbUnoClass( const String& aName_, const Reference< XIdlClass >& xClass_ ) + : SbxObject( aName_ ) + , m_xClass( xClass_ ) + {} + //~SbUnoClass(); + + // Find ueberladen, um Elemente on Demand anzulegen + virtual SbxVariable* Find( const String&, SbxClassType ); + + // Wert rausgeben + const Reference< XIdlClass >& getUnoClass( void ) { return m_xClass; } + + //void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); +}; +SV_DECL_IMPL_REF(SbUnoClass); + + +// Funktion, um einen globalen Bezeichner im +// UnoScope zu suchen und fuer Sbx zu wrappen +SbxVariable* findUnoClass( const String& rName ); + + +// #105565 Special Object to wrap a strongly typed Uno Any +class SbUnoAnyObject: public SbxObject +{ + Any mVal; + +public: + SbUnoAnyObject( const Any& rVal ) + : SbxObject( String() ) + , mVal( rVal ) + {} + + const Any& getValue( void ) + { return mVal; } + + TYPEINFO(); +}; + + +// #112509 Special SbxArray to transport named parameters for calls +// to OLEAutomation objects through the UNO OLE automation bridge + +class AutomationNamedArgsSbxArray : public SbxArray +{ + Sequence< ::rtl::OUString > maNameSeq; +public: + TYPEINFO(); + AutomationNamedArgsSbxArray( sal_Int32 nSeqSize ) + : maNameSeq( nSeqSize ) + {} + + Sequence< ::rtl::OUString >& getNames( void ) + { return maNameSeq; } +}; + + +class StarBASIC; + +//======================================================================== +// #118116 Collection object + +class BasicCollection : public SbxObject +{ + friend class SbiRuntime; + SbxArrayRef xItemArray; + + void Initialize(); + virtual ~BasicCollection(); + virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ); + INT32 implGetIndex( SbxVariable* pIndexVar ); + INT32 implGetIndexForName( const String& rName ); + void CollAdd( SbxArray* pPar_ ); + void CollItem( SbxArray* pPar_ ); + void CollRemove( SbxArray* pPar_ ); + +public: + TYPEINFO(); + BasicCollection( const String& rClassname ); + virtual SbxVariable* Find( const String&, SbxClassType ); + virtual void Clear(); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/scanner.hxx b/binfilter/bf_basic/source/inc/scanner.hxx new file mode 100644 index 000000000000..068cb627bbb7 --- /dev/null +++ b/binfilter/bf_basic/source/inc/scanner.hxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SCANNER_HXX +#define _SCANNER_HXX + +#include <tools/string.hxx> +#include "sberrors.hxx" + +namespace binfilter { + +// Der Scanner ist stand-alone, d.h. er kann von ueberallher verwendet +// werden. Eine BASIC-Instanz ist fuer Fehlermeldungen notwendig. Ohne +// BASIC werden die Fehler nur gezaehlt. Auch ist Basic notwendig, wenn +// eine erweiterte SBX-Variable zur Erkennung von Datentypen etc. verwendet +// werden soll. + +class StarBASIC; + +class SbiScanner +{ + ::rtl::OUString aBuf; // Input-Puffer + ::rtl::OUString aLine; // aktuelle Zeile + const sal_Unicode* pLine; // Pointer + const sal_Unicode* pSaveLine; // Merker fuer Line +protected: + String aSym; // Symbolpuffer + String aError; // Fehler-String + SbxDataType eScanType; // evtl. Datentyp + StarBASIC* pBasic; // Instanz fuer Fehler-Callbacks + double nVal; // numerischer Wert + short nCurCol1; // aktuelle Spalte 1 + short nSavedCol1; // gerettete Spalte 1 + short nCol; // aktuelle Spaltennummer + short nErrors; // Anzahl Fehler + short nColLock; // Lock-Zaehler fuer Col1 + INT32 nBufPos; // aktuelle Buffer-Pos + USHORT nLine; // aktuelle Zeile + USHORT nCol1, nCol2; // aktuelle 1. und 2. Spalte + BOOL bSymbol; // TRUE: Symbol gescannt + BOOL bNumber; // TRUE: Zahl gescannt + BOOL bSpaces; // TRUE: Whitespace vor Token + BOOL bErrors; // TRUE: Fehler generieren + BOOL bAbort; // TRUE: abbrechen + BOOL bHash; // TRUE: # eingelesen + BOOL bError; // TRUE: Fehler generieren + BOOL bUsedForHilite; // TRUE: Nutzung fuer Highlighting + BOOL bCompatible; // TRUE: OPTION Compatible + BOOL bPrevLineExtentsComment; // TRUE: Previous line is comment and ends on "... _" + + void GenError( SbError ); +public: + SbiScanner( const ::rtl::OUString&, StarBASIC* = NULL ); + ~SbiScanner(); + + void EnableErrors() { bError = FALSE; } + BOOL IsHash() { return bHash; } + BOOL IsCompatible() { return bCompatible; } + void SetCompatible( bool b ) { bCompatible = b; } // #118206 + BOOL WhiteSpace() { return bSpaces; } + short GetErrors() { return nErrors; } + short GetLine() { return nLine; } + short GetCol1() { return nCol1; } + short GetCol2() { return nCol2; } + void SetCol1( short n ) { nCol1 = n; } + StarBASIC* GetBasic() { return pBasic; } + void SaveLine(void) { pSaveLine = pLine; } + void RestoreLine(void) { pLine = pSaveLine; } + void LockColumn(); + void UnlockColumn(); + + BOOL NextSym(); // naechstes Symbol lesen + const String& GetSym() { return aSym; } + SbxDataType GetType() { return eScanType; } + double GetDbl() { return nVal; } +}; + +class LetterTable +{ + bool IsLetterTab[256]; + +public: + LetterTable( void ); + + inline bool isLetter( sal_Unicode c ) + { + bool bRet = (c < 256) ? IsLetterTab[c] : isLetterUnicode( c ); + return bRet; + } + bool isLetterUnicode( sal_Unicode c ); +}; + +class BasicSimpleCharClass +{ + static LetterTable aLetterTable; + +public: + static BOOL isAlpha( sal_Unicode c, bool bCompatible ) + { + BOOL bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || (bCompatible && aLetterTable.isLetter( c )); + return bRet; + } + + static BOOL isDigit( sal_Unicode c ) + { + BOOL bRet = (c >= '0' && c <= '9'); + return bRet; + } + + static BOOL isAlphaNumeric( sal_Unicode c, bool bCompatible ) + { + BOOL bRet = isDigit( c ) || isAlpha( c, bCompatible ); + return bRet; + } +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/inc/token.hxx b/binfilter/bf_basic/source/inc/token.hxx new file mode 100644 index 000000000000..6b6196741a74 --- /dev/null +++ b/binfilter/bf_basic/source/inc/token.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _TOKEN_HXX +#define _TOKEN_HXX + +#include "scanner.hxx" +#include "sbdef.hxx" + +#if defined( SHARED ) +#define SbiTokenSHAREDTMPUNDEF +#undef SHARED +#endif + +namespace binfilter { + +// Der Tokenizer ist stand-alone, d.h. er kann von ueberallher verwendet +// werden. Eine BASIC-Instanz ist fuer Fehlermeldungen notwendig. Ohne +// BASIC werden die Fehler nur gezaehlt. Auch ist Basic notwendig, wenn +// eine erweiterte SBX-Variable zur Erkennung von Datentypen etc. verwendet +// werden soll. + +enum SbiToken { + NIL = 0, + // Token zwischen 0x20 und 0x3F sind Literale: + LPAREN = '(', RPAREN = ')', COMMA = ',', DOT = '.', EXCLAM = '!', + HASH = '#', SEMICOLON = ';', + + // Anweisungen: + FIRSTKWD = 0x40, + AS = FIRSTKWD, ALIAS, ASSIGN, + CALL, CASE, CLOSE, COMPARE, _CONST_, + DECLARE, DIM, DO, + + // in der Reihenfolge der Datentyp-Enums! + DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFCUR, DEFDATE, DEFSTR, DEFOBJ, + DEFERR, DEFBOOL, DEFVAR, + // in der Reihenfolge der Datentyp-Enums! + DATATYPE1, + TINTEGER = DATATYPE1, + TLONG, TSINGLE, TDOUBLE, TCURRENCY, TDATE, TSTRING, TOBJECT, + _ERROR_, TBOOLEAN, TVARIANT, TBYTE, + DATATYPE2 = TBYTE, + + EACH, ELSE, ELSEIF, END, ERASE, EXIT, + FOR, FUNCTION, + GET, GLOBAL, GOSUB, GOTO, + IF, _IN_, INPUT, + LET, LINE, LINEINPUT, LOCAL, LOOP, LPRINT, LSET, + NAME, NEW, NEXT, + ON, OPEN, OPTION, IMPLEMENTS, + PRINT, PRIVATE, PROPERTY, PUBLIC, + REDIM, REM, RESUME, RETURN, RSET, + SELECT, SET, SHARED, STATIC, STEP, STOP, SUB, + TEXT, THEN, TO, TYPE, ENUM, + UNTIL, + WEND, WHILE, WITH, WRITE, + ENDENUM, ENDIF, ENDFUNC, ENDPROPERTY, ENDSUB, ENDTYPE, ENDSELECT, ENDWITH, + // Ende aller Keywords + LASTKWD = ENDWITH, + // Statement-Ende + EOS, EOLN, + // Operatoren: + EXPON, NEG, MUL, + DIV, IDIV, MOD, PLUS, MINUS, + EQ, NE, LT, GT, LE, GE, + NOT, AND, OR, XOR, EQV, + IMP, CAT, LIKE, IS, TYPEOF, + // Sonstiges: + FIRSTEXTRA, + NUMBER=FIRSTEXTRA, FIXSTRING, SYMBOL, _CDECL_, BYVAL, BYREF, + OUTPUT, RANDOM, APPEND, BINARY, ACCESS, + LOCK, READ, PRESERVE, BASE, ANY, LIB, _OPTIONAL_, + EXPLICIT, COMPATIBLE, CLASSMODULE, PARAMARRAY, + + // Ab hier kommen JavaScript-Tokens (gleiches enum, damit gleicher Typ) + FIRSTJAVA, + JS_BREAK=FIRSTJAVA, JS_CONTINUE, JS_FOR, JS_FUNCTION, JS_IF, JS_NEW, + JS_RETURN, JS_THIS, JS_VAR, JS_WHILE, JS_WITH, + + // JavaScript-Operatoren + // _ASS_ = Assignment + JS_COMMA, JS_ASSIGNMENT, JS_ASS_PLUS, JS_ASS_MINUS, JS_ASS_MUL, + JS_ASS_DIV, JS_ASS_MOD, JS_ASS_LSHIFT, JS_ASS_RSHIFT, JS_ASS_RSHIFT_Z, + JS_ASS_AND, JS_ASS_XOR, JS_ASS_OR, + JS_COND_QUEST, JS_COND_SEL, JS_LOG_OR, JS_LOG_AND, JS_BIT_OR, + JS_BIT_XOR, JS_BIT_AND, JS_EQ, JS_NE, JS_LT, JS_LE, + JS_GT, JS_GE, JS_LSHIFT, JS_RSHIFT, JS_RSHIFT_Z, + JS_PLUS, JS_MINUS, JS_MUL, JS_DIV, JS_MOD, JS_LOG_NOT, JS_BIT_NOT, + JS_INC, JS_DEC, JS_LPAREN, JS_RPAREN, JS_LINDEX, JS_RINDEX + , VBASUPPORT +}; + +#ifdef SbiTokenSHAREDTMPUNDEF +#define SHARED +#undef SbiTokenSHAREDTMPUNDEF +#endif + +class SbiTokenizer : public SbiScanner { +protected: + SbiToken eCurTok; // aktuelles Token + SbiToken ePush; // Pushback-Token + USHORT nPLine, nPCol1, nPCol2; // Pushback-Location + BOOL bEof; // TRUE bei Dateiende + BOOL bEos; // TRUE bei Statement-Ende + BOOL bKeywords; // TRUE, falls Keywords geparst werden + BOOL bAs; // letztes Keyword war AS + BOOL bErrorIsSymbol; // Handle Error token as Symbol, not keyword +public: + SbiTokenizer( const ::rtl::OUString&, StarBASIC* = NULL ); + ~SbiTokenizer(); + + inline BOOL IsEof() { return bEof; } + inline BOOL IsEos() { return bEos; } + + SbiToken Peek(); // das naechste Token lesen + SbiToken Next(); // Ein Token lesen + void Error( SbError c ) { GenError( c ); } + + void Keywords( BOOL b ) { bKeywords = b; } + + static BOOL IsEoln( SbiToken t ) + { return BOOL( t == EOS || t == EOLN || t == REM ); } + static BOOL IsKwd( SbiToken t ) + { return BOOL( t >= FIRSTKWD && t <= LASTKWD ); } + static BOOL IsExtra( SbiToken t ) + { return BOOL( t >= FIRSTEXTRA ); } +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/runtime/basrdll.cxx b/binfilter/bf_basic/source/runtime/basrdll.cxx new file mode 100644 index 000000000000..a2efc14d8b5f --- /dev/null +++ b/binfilter/bf_basic/source/runtime/basrdll.cxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "basrdll.hxx" + +namespace binfilter { + +/*?*/ // BasicResId::BasicResId( USHORT nId ): +/*?*/ // ResId( nId, (*(BasicDLL**)GetAppData(SHL_BASIC))->GetResMgr() ) +/*?*/ // { +/*?*/ // } + +BasicDLL::BasicDLL() +{ +/*?*/ // *(BasicDLL**)GetAppData(SHL_BASIC) = this; +/*?*/ // ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); +/*?*/ // pResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(ofa), aLocale ); + bDebugMode = FALSE; + bBreakEnabled = TRUE; +} + +BasicDLL::~BasicDLL() +{ +/*?*/ // delete pResMgr; +} + +/*?*/ // 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( BasicResId( IDS_SBERR_TERMINATED ) ); +/*?*/ // InfoBox( 0, aMessageStr ).Execute(); +/*?*/ // bJustStopping = FALSE; +/*?*/ // } +/*?*/ // } +/*?*/ // } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/runtime/makefile.mk b/binfilter/bf_basic/source/runtime/makefile.mk new file mode 100644 index 000000000000..f2553b1e47ca --- /dev/null +++ b/binfilter/bf_basic/source/runtime/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=binfilter +TARGET=basic_runtime + +NO_HIDS=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +INC+= -I$(PRJ)$/inc$/bf_basic + +# --- 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)$(CPU)" == "WNTI" +#SLOFILES+= $(SLO)$/wnt.obj +.ENDIF + +.IF "$(GUI)$(CPU)" == "OS2I" +#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 + diff --git a/binfilter/bf_basic/source/sbx/makefile.mk b/binfilter/bf_basic/source/sbx/makefile.mk new file mode 100644 index 000000000000..33335d8eb054 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=binfilter +TARGET=basic_sbx + +NO_HIDS=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +INC+= -I$(PRJ)$/inc$/bf_basic + +# --- Allgemein ----------------------------------------------------------- + +EXCEPTIONSFILES=$(SLO)$/sbxarray.obj + +SLOFILES= \ + $(EXCEPTIONSFILES) \ + $(SLO)$/sbxbase.obj \ + $(SLO)$/sbxvar.obj \ + $(SLO)$/sbxvalue.obj \ + $(SLO)$/sbxdec.obj \ + $(SLO)$/sbxint.obj \ + $(SLO)$/sbxcurr.obj \ + $(SLO)$/sbxstr.obj \ + $(SLO)$/sbxbool.obj \ + $(SLO)$/sbxdbl.obj \ + $(SLO)$/sbxdate.obj \ + $(SLO)$/sbxsng.obj \ + $(SLO)$/sbxlng.obj \ + $(SLO)$/sbxobj.obj \ + $(SLO)$/sbxscan.obj \ + $(SLO)$/sbxbyte.obj \ + $(SLO)$/sbxchar.obj \ + $(SLO)$/sbxulng.obj \ + $(SLO)$/sbxuint.obj \ + $(SLO)$/sbxcoll.obj \ + $(SLO)$/sbxres.obj \ + $(SLO)$/sbxexec.obj \ + +# $(SLO)$/sbxvals.obj \ + $(SLO)$/sbxmstrm.obj \ + + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + + diff --git a/binfilter/bf_basic/source/sbx/sbxarray.cxx b/binfilter/bf_basic/source/sbx/sbxarray.cxx new file mode 100644 index 000000000000..74301330e258 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxarray.cxx @@ -0,0 +1,784 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/stream.hxx> +#include "sbx.hxx" +#include <vector> +using namespace std; + +namespace binfilter { + +struct SbxDim { // eine Array-Dimension: + SbxDim* pNext; // Link + INT32 nLbound, nUbound; // Begrenzungen + INT32 nSize; // Anzahl Elemente +}; + +class SbxVarEntry : public SbxVariableRef { +public: + XubString* pAlias; + SbxVarEntry() : SbxVariableRef(), pAlias( NULL ) {} + ~SbxVarEntry() { delete pAlias; } +}; + +typedef SbxVarEntry* SbxVarEntryPtr; +typedef vector< SbxVarEntryPtr > SbxVarEntryPtrVector; +class SbxVarRefs : public SbxVarEntryPtrVector +{ +public: + SbxVarRefs( void ) {} +}; + + +TYPEINIT1(SbxArray,SbxBase) +TYPEINIT1(SbxDimArray,SbxArray) + +////////////////////////////////////////////////////////////////////////// +// +// SbxArray +// +////////////////////////////////////////////////////////////////////////// + +SbxArray::SbxArray( SbxDataType t ) : SbxBase() +{ + pData = new SbxVarRefs; + eType = t; + if( t != SbxVARIANT ) + SetFlag( SBX_FIXED ); +} + +SbxArray::SbxArray( const SbxArray& rArray ) : + SvRefBase( rArray ), SbxBase() +{ + pData = new SbxVarRefs; + if( rArray.eType != SbxVARIANT ) + SetFlag( SBX_FIXED ); + *this = rArray; +} + +SbxArray& SbxArray::operator=( const SbxArray& rArray ) +{ + if( &rArray != this ) + { + eType = rArray.eType; + Clear(); + SbxVarRefs* pSrc = rArray.pData; + for( UINT32 i = 0; i < pSrc->size(); i++ ) + { + SbxVarEntryPtr pSrcRef = (*pSrc)[i]; + SbxVarEntryPtr pDstRef = new SbxVarEntry; + *((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef); + if( pSrcRef->pAlias ) + pDstRef->pAlias = new XubString( *pSrcRef->pAlias ); + const SbxVariable* pSrc_ = *pSrcRef; + if( pSrc_ ) + { + if( eType != SbxVARIANT ) + // Keine Objekte konvertieren + if( eType != SbxOBJECT || pSrc_->GetClass() != SbxCLASS_OBJECT ) + ((SbxVariable*) pSrc_)->Convert( eType ); + pData->push_back( pDstRef ); + } + } + } + return *this; +} + +SbxArray::~SbxArray() +{ + Clear(); + delete pData; +} + +SbxDataType SbxArray::GetType() const +{ + return (SbxDataType) ( eType | SbxARRAY ); +} + +SbxClassType SbxArray::GetClass() const +{ + return SbxCLASS_ARRAY; +} + +void SbxArray::Clear() +{ + UINT32 nSize = pData->size(); + for( UINT32 i = 0 ; i < nSize ; i++ ) + { + SbxVarEntry* pEntry = (*pData)[i]; + delete pEntry; + } + pData->clear(); +} + +UINT32 SbxArray::Count32() const +{ + return pData->size(); +} + +USHORT SbxArray::Count() const +{ + UINT32 nCount = pData->size(); + DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" ); + return (USHORT)nCount; +} + +SbxVariableRef& SbxArray::GetRef32( UINT32 nIdx ) +{ + // Array ggf. vergroessern + DBG_ASSERT( nIdx <= SBX_MAXINDEX32, "SBX: Array-Index > SBX_MAXINDEX32" ); + // Very Hot Fix + if( nIdx > SBX_MAXINDEX32 ) + { + SetError( SbxERR_BOUNDS ); + nIdx = 0; + } + while( pData->size() <= nIdx ) + { + const SbxVarEntryPtr p = new SbxVarEntry; + pData->push_back( p ); + } + return *((*pData)[nIdx]); +} + +SbxVariableRef& SbxArray::GetRef( USHORT nIdx ) +{ + // Array ggf. vergroessern + DBG_ASSERT( nIdx <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" ); + // Very Hot Fix + if( nIdx > SBX_MAXINDEX ) + { + SetError( SbxERR_BOUNDS ); + nIdx = 0; + } + while( pData->size() <= nIdx ) + { + const SbxVarEntryPtr p = new SbxVarEntry; + pData->push_back( p ); + } + return *((*pData)[nIdx]); +} + +SbxVariable* SbxArray::Get32( UINT32 nIdx ) +{ + if( !CanRead() ) + { + SetError( SbxERR_PROP_WRITEONLY ); + return NULL; + } + SbxVariableRef& rRef = GetRef32( nIdx ); + + if ( !rRef.Is() ) + rRef = new SbxVariable( eType ); + + return rRef; +} + +SbxVariable* SbxArray::Get( USHORT nIdx ) +{ + if( !CanRead() ) + { + SetError( SbxERR_PROP_WRITEONLY ); + return NULL; + } + SbxVariableRef& rRef = GetRef( nIdx ); + + if ( !rRef.Is() ) + rRef = new SbxVariable( eType ); + + return rRef; +} + +void SbxArray::Put32( SbxVariable* pVar, UINT32 nIdx ) +{ + if( !CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else + { + if( pVar ) + if( eType != SbxVARIANT ) + // Keine Objekte konvertieren + if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT ) + pVar->Convert( eType ); + SbxVariableRef& rRef = GetRef32( nIdx ); + if( (SbxVariable*) rRef != pVar ) + { + rRef = pVar; + SetFlag( SBX_MODIFIED ); + } + } +} + +void SbxArray::Put( SbxVariable* pVar, USHORT nIdx ) +{ + if( !CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else + { + if( pVar ) + if( eType != SbxVARIANT ) + // Keine Objekte konvertieren + if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT ) + pVar->Convert( eType ); + SbxVariableRef& rRef = GetRef( nIdx ); + if( (SbxVariable*) rRef != pVar ) + { + rRef = pVar; + SetFlag( SBX_MODIFIED ); + } + } +} + +void SbxArray::Insert32( SbxVariable* pVar, UINT32 nIdx ) +{ + DBG_ASSERT( pData->size() <= SBX_MAXINDEX32, "SBX: Array wird zu gross" ); + if( pData->size() > SBX_MAXINDEX32 ) + return; + SbxVarEntryPtr p = new SbxVarEntry; + *((SbxVariableRef*) p) = pVar; + SbxVarEntryPtrVector::size_type nSize = pData->size(); + if( nIdx > nSize ) + nIdx = nSize; + if( eType != SbxVARIANT && pVar ) + (*p)->Convert( eType ); + if( nIdx == nSize ) + { + pData->push_back( p ); + } + else + { + pData->insert( pData->begin() + nIdx, p ); + } + SetFlag( SBX_MODIFIED ); +} + +void SbxArray::Insert( SbxVariable* pVar, USHORT nIdx ) +{ + DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array wird zu gross" ); + if( pData->size() > 0x3FF0 ) + return; + Insert32( pVar, nIdx ); +} + +void SbxArray::Remove32( UINT32 nIdx ) +{ + if( nIdx < pData->size() ) + { + SbxVariableRef* pRef = (*pData)[nIdx]; + pData->erase( pData->begin() + nIdx ); + delete pRef; + SetFlag( SBX_MODIFIED ); + } +} + +void SbxArray::Remove( USHORT nIdx ) +{ + if( nIdx < pData->size() ) + { + SbxVariableRef* pRef = (*pData)[nIdx]; + pData->erase( pData->begin() + nIdx ); + delete pRef; + SetFlag( SBX_MODIFIED ); + } +} + +void SbxArray::Remove( SbxVariable* pVar ) +{ + if( pVar ) + { + for( UINT32 i = 0; i < pData->size(); i++ ) + { + SbxVariableRef* pRef = (*pData)[i]; + // SbxVariableRef* pRef = pData->GetObject( i ); + if( *pRef == pVar ) + { + Remove32( i ); break; + } + } + } +} + +// Uebernahme der Daten aus dem uebergebenen Array, wobei +// gleichnamige Variable ueberschrieben werden. + +void SbxArray::Merge( SbxArray* p ) +{ + if( p ) + { + UINT32 nSize = p->Count(); + for( UINT32 i = 0; i < nSize; i++ ) + { + SbxVarEntryPtr pRef1 = (*(p->pData))[i]; + // Ist das Element by name schon drin? + // Dann ueberschreiben! + SbxVariable* pVar = *pRef1; + if( pVar ) + { + XubString aName = pVar->GetName(); + USHORT nHash = pVar->GetHashCode(); + for( UINT32 j = 0; j < pData->size(); j++ ) + { + SbxVariableRef* pRef2 = (*pData)[j]; + if( (*pRef2)->GetHashCode() == nHash + && (*pRef2)->GetName().EqualsIgnoreCaseAscii( aName ) ) + { + *pRef2 = pVar; pRef1 = NULL; + break; + } + } + if( pRef1 ) + { + SbxVarEntryPtr pRef = new SbxVarEntry; + const SbxVarEntryPtr pTemp = pRef; + pData->push_back( pTemp ); + *((SbxVariableRef*) pRef) = *((SbxVariableRef*) pRef1); + if( pRef1->pAlias ) + pRef->pAlias = new XubString( *pRef1->pAlias ); + } + } + } + } +} + +// Suchen eines Elements ueber die Userdaten. Falls ein Element +// ein Objekt ist, wird dieses ebenfalls durchsucht. + +SbxVariable* SbxArray::FindUserData( UINT32 nData ) +{ + SbxVariable* p = NULL; + for( UINT32 i = 0; i < pData->size(); i++ ) + { + SbxVariableRef* pRef = (*pData)[i]; + SbxVariable* pVar = *pRef; + if( pVar ) + { + if( pVar->IsVisible() && pVar->GetUserData() == nData ) + { + p = pVar; + p->ResetFlag( SBX_EXTFOUND ); + break; // JSM 06.10.95 + } + // Haben wir ein Array/Objekt mit Extended Search? + else if( pVar->IsSet( SBX_EXTSEARCH ) ) + { + switch( pVar->GetClass() ) + { + case SbxCLASS_OBJECT: + { + // Objekte duerfen ihren Parent nicht durchsuchen + USHORT nOld = pVar->GetFlags(); + pVar->ResetFlag( SBX_GBLSEARCH ); + p = ((SbxObject*) pVar)->FindUserData( nData ); + pVar->SetFlags( nOld ); + break; + } + case SbxCLASS_ARRAY: + p = ((SbxArray*) pVar)->FindUserData( nData ); + break; + default: break; + } + if( p ) + { + p->SetFlag( SBX_EXTFOUND ); + break; + } + } + } + } + return p; +} + +// Suchen eines Elements ueber den Namen und den Typ. Falls ein Element +// ein Objekt ist, wird dieses ebenfalls durchsucht. + +SbxVariable* SbxArray::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* p = NULL; + UINT32 nCount = pData->size(); + if( !nCount ) + return NULL; + BOOL bExtSearch = IsSet( SBX_EXTSEARCH ); + USHORT nHash = SbxVariable::MakeHashCode( rName ); + for( UINT32 i = 0; i < nCount; i++ ) + { + SbxVariableRef* pRef = (*pData)[i]; + SbxVariable* pVar = *pRef; + if( pVar && pVar->IsVisible() ) + { + // Die ganz sichere Suche klappt auch, wenn es + // keinen Hascode gibt! + USHORT nVarHash = pVar->GetHashCode(); + if( ( !nVarHash || nVarHash == nHash ) + && ( t == SbxCLASS_DONTCARE || pVar->GetClass() == t ) + && ( pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) ) + { + p = pVar; + p->ResetFlag( SBX_EXTFOUND ); + break; + } + // Haben wir ein Array/Objekt mit Extended Search? + else if( bExtSearch && pVar->IsSet( SBX_EXTSEARCH ) ) + { + switch( pVar->GetClass() ) + { + case SbxCLASS_OBJECT: + { + // Objekte duerfen ihren Parent nicht durchsuchen + USHORT nOld = pVar->GetFlags(); + pVar->ResetFlag( SBX_GBLSEARCH ); + p = ((SbxObject*) pVar)->Find( rName, t ); + pVar->SetFlags( nOld ); + break; + } + case SbxCLASS_ARRAY: + p = ((SbxArray*) pVar)->Find( rName, t ); + break; + default: break; + } + if( p ) + { + p->SetFlag( SBX_EXTFOUND ); + break; + } + } + } + } + return p; +} + +BOOL SbxArray::LoadData( SvStream& rStrm, USHORT nVer ) +{ + UINT16 nElem; + Clear(); + BOOL bRes = TRUE; + USHORT f = nFlags; + nFlags |= SBX_WRITE; + rStrm >> nElem; + nElem &= 0x7FFF; + for( UINT32 n = 0; n < nElem; n++ ) + { + UINT16 nIdx; + rStrm >> nIdx; + SbxVariable* pVar = (SbxVariable*) Load( rStrm ); + if( pVar ) + { + SbxVariableRef& rRef = GetRef( nIdx ); + rRef = pVar; + } + else + { + bRes = FALSE; break; + } + } + if( bRes ) + bRes = LoadPrivateData( rStrm, nVer ); + nFlags = f; + return bRes; +} + +BOOL SbxArray::StoreData( SvStream& rStrm ) const +{ + UINT32 nElem = 0; + UINT32 n; + // Welche Elemente sind ueberhaupt definiert? + for( n = 0; n < pData->size(); n++ ) + { + SbxVariableRef* pRef = (*pData)[n]; + SbxVariable* p = *pRef; + if( p && !( p->GetFlags() & SBX_DONTSTORE ) ) + nElem++; + } + rStrm << (UINT16) nElem; + for( n = 0; n < pData->size(); n++ ) + { + SbxVariableRef* pRef = (*pData)[n]; + SbxVariable* p = *pRef; + if( p && !( p->GetFlags() & SBX_DONTSTORE ) ) + { + rStrm << (UINT16) n; + if( !p->Store( rStrm ) ) + return FALSE; + } + } + return StorePrivateData( rStrm ); +} + +// #100883 Method to set method directly to parameter array +void SbxArray::PutDirect( SbxVariable* pVar, UINT32 nIdx ) +{ + SbxVariableRef& rRef = GetRef32( nIdx ); + rRef = pVar; +} + + +////////////////////////////////////////////////////////////////////////// +// +// SbxArray +// +////////////////////////////////////////////////////////////////////////// + +SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ) +{ + pFirst = pLast = NULL; + nDim = 0; +} + +SbxDimArray::SbxDimArray( const SbxDimArray& rArray ) + : SvRefBase( rArray ), SbxArray( rArray.eType ) +{ + pFirst = pLast = NULL; + nDim = 0; + *this = rArray; +} + +SbxDimArray& SbxDimArray::operator=( const SbxDimArray& rArray ) +{ + if( &rArray != this ) + { + SbxArray::operator=( (const SbxArray&) rArray ); + SbxDim* p = rArray.pFirst; + while( p ) + { + AddDim32( p->nLbound, p->nUbound ); + p = p->pNext; + } + } + return *this; +} + +SbxDimArray::~SbxDimArray() +{ + Clear(); +} + +void SbxDimArray::Clear() +{ + SbxDim* p = pFirst; + while( p ) + { + SbxDim* q = p->pNext; + delete p; + p = q; + } + pFirst = pLast = NULL; + nDim = 0; +} + +// Dimension hinzufuegen + +void SbxDimArray::AddDimImpl32( INT32 lb, INT32 ub, BOOL bAllowSize0 ) +{ + SbxError eRes = SbxERR_OK; + if( ub < lb && !bAllowSize0 ) + { + eRes = SbxERR_BOUNDS; + ub = lb; + } + SbxDim* p = new SbxDim; + p->nLbound = lb; + p->nUbound = ub; + p->nSize = ub - lb + 1; + p->pNext = NULL; + if( !pFirst ) + pFirst = pLast = p; + else + pLast->pNext = p, pLast = p; + nDim++; + if( eRes ) + SetError( eRes ); +} + +void SbxDimArray::AddDim( short lb, short ub ) +{ + AddDimImpl32( lb, ub, FALSE ); +} + +void SbxDimArray::unoAddDim( short lb, short ub ) +{ + AddDimImpl32( lb, ub, TRUE ); +} + +void SbxDimArray::AddDim32( INT32 lb, INT32 ub ) +{ + AddDimImpl32( lb, ub, FALSE ); +} + +void SbxDimArray::unoAddDim32( INT32 lb, INT32 ub ) +{ + AddDimImpl32( lb, ub, TRUE ); +} + + +// Dimensionsdaten auslesen + +BOOL SbxDimArray::GetDim32( INT32 n, INT32& rlb, INT32& rub ) const +{ + if( n < 1 || n > nDim ) + { + SetError( SbxERR_BOUNDS ); rub = rlb = 0; return FALSE; + } + SbxDim* p = pFirst; + while( --n ) + p = p->pNext; + rub = p->nUbound; + rlb = p->nLbound; + return TRUE; +} + +BOOL SbxDimArray::GetDim( short n, short& rlb, short& rub ) const +{ + INT32 rlb32, rub32; + BOOL bRet = GetDim32( n, rlb32, rub32 ); + if( bRet ) + { + if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX ) + { + SetError( SbxERR_BOUNDS ); + return FALSE; + } + rub = (short)rub32; + rlb = (short)rlb32; + } + return bRet; +} + +// Element-Ptr anhand einer Index-Liste + +UINT32 SbxDimArray::Offset32( const INT32* pIdx ) +{ + UINT32 nPos = 0; + for( SbxDim* p = pFirst; p; p = p->pNext ) + { + INT32 nIdx = *pIdx++; + if( nIdx < p->nLbound || nIdx > p->nUbound ) + { + nPos = (UINT32)SBX_MAXINDEX32 + 1; break; + } + nPos = nPos * p->nSize + nIdx - p->nLbound; + } + if( nDim == 0 || nPos > SBX_MAXINDEX32 ) + { + SetError( SbxERR_BOUNDS ); nPos = 0; + } + return nPos; +} + +USHORT SbxDimArray::Offset( const short* pIdx ) +{ + long nPos = 0; + for( SbxDim* p = pFirst; p; p = p->pNext ) + { + short nIdx = *pIdx++; + if( nIdx < p->nLbound || nIdx > p->nUbound ) + { + nPos = SBX_MAXINDEX + 1; break; + } + nPos = nPos * p->nSize + nIdx - p->nLbound; + } + if( nDim == 0 || nPos > SBX_MAXINDEX ) + { + SetError( SbxERR_BOUNDS ); nPos = 0; + } + return (USHORT) nPos; +} + +SbxVariable* SbxDimArray::Get( const short* pIdx ) +{ + return SbxArray::Get( Offset( pIdx ) ); +} + +SbxVariable* SbxDimArray::Get32( const INT32* pIdx ) +{ + return SbxArray::Get32( Offset32( pIdx ) ); +} + +void SbxDimArray::Put32( SbxVariable* p, const INT32* pIdx ) +{ + SbxArray::Put32( p, Offset32( pIdx ) ); +} + + +// Element-Nr anhand eines Parameter-Arrays + +UINT32 SbxDimArray::Offset32( SbxArray* pPar ) +{ + if( nDim == 0 || !pPar ) + { + SetError( SbxERR_BOUNDS ); return 0; + } + UINT32 nPos = 0; + USHORT nOff = 1; // Nicht Element 0! + for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext ) + { + INT32 nIdx = pPar->Get( nOff++ )->GetLong(); + if( nIdx < p->nLbound || nIdx > p->nUbound ) + { + nPos = (UINT32) SBX_MAXINDEX32+1; break; + } + nPos = nPos * p->nSize + nIdx - p->nLbound; + } + if( nPos > (UINT32) SBX_MAXINDEX32 ) + { + SetError( SbxERR_BOUNDS ); nPos = 0; + } + return nPos; +} + +SbxVariable* SbxDimArray::Get( SbxArray* pPar ) +{ + return SbxArray::Get32( Offset32( pPar ) ); +} + +BOOL SbxDimArray::LoadData( SvStream& rStrm, USHORT nVer ) +{ + short nDimension; + rStrm >> nDimension; + for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ ) + { + INT16 lb, ub; + rStrm >> lb >> ub; + AddDim( lb, ub ); + } + return SbxArray::LoadData( rStrm, nVer ); +} + +BOOL SbxDimArray::StoreData( SvStream& rStrm ) const +{ + rStrm << (INT16) nDim; + for( short i = 0; i < nDim; i++ ) + { + short lb, ub; + GetDim( i, lb, ub ); + rStrm << (INT16) lb << (INT16) ub; + } + return SbxArray::StoreData( rStrm ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxbase.cxx b/binfilter/bf_basic/source/sbx/sbxbase.cxx new file mode 100644 index 000000000000..3a367fef54b7 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxbase.cxx @@ -0,0 +1,426 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/stream.hxx> + +#include "sbx.hxx" +#include "sbxfac.hxx" +#include "sbxbase.hxx" + +namespace binfilter { + +// AppData-Struktur fuer SBX: + +SV_IMPL_PTRARR(SbxParams,SbxParamInfo*); +SV_IMPL_PTRARR(SbxFacs,SbxFactory*); + +TYPEINIT0(SbxBase) + +// SBX-Daten anfordern oder ggf. anlegen +// wir legen den Bereich einfach an und verzichten auf die Freigabe! + +SbxAppData* GetSbxData_Impl() +{ + DBG_TESTSOLARMUTEX(); + static SbxAppData* pAppData = new SbxAppData; + return pAppData; +} + +//////////////////////////////// SbxBase ///////////////////////////////// + +DBG_NAME(SbxBase); + +SbxBase::SbxBase() +{ + DBG_CTOR( SbxBase, 0 ); + nFlags = SBX_READWRITE; +} + +SbxBase::SbxBase( const SbxBase& r ) + : SvRefBase( r ) +{ + DBG_CTOR( SbxBase, 0 ); + nFlags = r.nFlags; +} + +SbxBase::~SbxBase() +{ + DBG_DTOR(SbxBase,0); +} + +SbxBase& SbxBase::operator=( const SbxBase& r ) +{ + DBG_CHKTHIS( SbxBase, 0 ); + nFlags = r.nFlags; + return *this; +} + +SbxDataType SbxBase::GetType() const +{ + DBG_CHKTHIS( SbxBase, 0 ); + return SbxEMPTY; +} + +SbxClassType SbxBase::GetClass() const +{ + DBG_CHKTHIS( SbxBase, 0 ); + return SbxCLASS_DONTCARE; +} + +void SbxBase::Clear() +{ + DBG_CHKTHIS( SbxBase, 0 ); +} + +BOOL SbxBase::IsFixed() const +{ + DBG_CHKTHIS( SbxBase, 0 ); + return IsSet( SBX_FIXED ); +} + +void SbxBase::SetModified( BOOL b ) +{ + DBG_CHKTHIS( SbxBase, 0 ); + if( IsSet( SBX_NO_MODIFY ) ) + return; + if( b ) + SetFlag( SBX_MODIFIED ); + else + ResetFlag( SBX_MODIFIED ); +} + +SbxError SbxBase::GetError() +{ + return GetSbxData_Impl()->eSbxError; +} + +void SbxBase::SetError( SbxError e ) +{ + SbxAppData* p = GetSbxData_Impl(); + if( e && p->eSbxError == SbxERR_OK ) + p->eSbxError = e; +} + +BOOL SbxBase::IsError() +{ + return BOOL( GetSbxData_Impl()->eSbxError != SbxERR_OK ); +} + +void SbxBase::ResetError() +{ + GetSbxData_Impl()->eSbxError = SbxERR_OK; +} + +void SbxBase::AddFactory( SbxFactory* pFac ) +{ + SbxAppData* p = GetSbxData_Impl(); + const SbxFactory* pTemp = pFac; + + // AB, 6.3.96: HandleLast-Flag beruecksichtigen + USHORT nPos = p->aFacs.Count(); // Einfuege-Position + if( !pFac->IsHandleLast() ) // Nur, wenn nicht selbst HandleLast + { + // Neue Factory vor Factories mit HandleLast einordnen + while( nPos > 0 && + (static_cast<SbxFactory*>(p->aFacs.GetObject( nPos-1 )))->IsHandleLast() ) + nPos--; + } + p->aFacs.Insert( pTemp, nPos ); +} + +void SbxBase::RemoveFactory( SbxFactory* pFac ) +{ + SbxAppData* p = GetSbxData_Impl(); + for( USHORT i = 0; i < p->aFacs.Count(); i++ ) + { + if( p->aFacs.GetObject( i ) == pFac ) + { + p->aFacs.Remove( i, 1 ); break; + } + } +} + + +SbxBase* SbxBase::Create( UINT16 nSbxId, UINT32 nCreator ) +{ + // #91626: Hack to skip old Basic dialogs + // Problem: There does not exist a factory any more, + // so we have to create a dummy SbxVariable instead + if( nSbxId == 0x65 ) // Dialog Id + return new SbxVariable; + + XubString aEmptyStr; + if( nCreator == SBXCR_SBX ) + switch( nSbxId ) + { + case SBXID_VALUE: return new SbxValue; + case SBXID_VARIABLE: return new SbxVariable; + case SBXID_ARRAY: return new SbxArray; + case SBXID_DIMARRAY: return new SbxDimArray; + case SBXID_OBJECT: return new SbxObject( aEmptyStr ); + case SBXID_COLLECTION: return new SbxCollection( aEmptyStr ); + case SBXID_FIXCOLLECTION: + return new SbxStdCollection( aEmptyStr, aEmptyStr ); + case SBXID_METHOD: return new SbxMethod( aEmptyStr, SbxEMPTY ); + case SBXID_PROPERTY: return new SbxProperty( aEmptyStr, SbxEMPTY ); + } + // Unbekanter Typ: ber die Factories gehen! + SbxAppData* p = GetSbxData_Impl(); + SbxBase* pNew = NULL; + for( USHORT i = 0; i < p->aFacs.Count(); i++ ) + { + SbxFactory* pFac = p->aFacs.GetObject( i ); + pNew = pFac->Create( nSbxId, nCreator ); + if( pNew ) + break; + } +#ifdef DBG_UTIL + if( !pNew ) + { + ByteString aMsg( "SBX: Keine Factory fuer SBX-ID " ); + aMsg += ByteString::CreateFromInt32(nSbxId); + DbgError( aMsg.GetBuffer() ); + } +#endif + return pNew; +} + +SbxObject* SbxBase::CreateObject( const XubString& rClass ) +{ + SbxAppData* p = GetSbxData_Impl(); + SbxObject* pNew = NULL; + for( USHORT i = 0; i < p->aFacs.Count(); i++ ) + { + pNew = p->aFacs.GetObject( i )->CreateObject( rClass ); + if( pNew ) + break; + } +#ifdef DBG_UTIL + if( !pNew ) + { + ByteString aMsg( "SBX: Keine Factory fuer Objektklasse " ); + ByteString aClassStr( (const UniString&)rClass, RTL_TEXTENCODING_ASCII_US ); + aMsg += aClassStr; + DbgError( (const char*)aMsg.GetBuffer() ); + } +#endif + return pNew; +} + +static BOOL bStaticEnableBroadcasting = TRUE; + +// Sbx-Loesung als Ersatz fuer SfxBroadcaster::Enable() +BOOL SbxBase::StaticIsEnabledBroadcasting( void ) +{ + return bStaticEnableBroadcasting; +} + +SbxBase* SbxBase::Load( SvStream& rStrm ) +{ + UINT16 nSbxId, nFlags, nVer; + UINT32 nCreator, nSize; + rStrm >> nCreator >> nSbxId >> nFlags >> nVer; + + // Eine Dummheit meinerseits korrigieren: + if( nFlags & SBX_RESERVED ) + nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH; + + ULONG nOldPos = rStrm.Tell(); + rStrm >> nSize; + SbxBase* p = Create( nSbxId, nCreator ); + if( p ) + { + p->nFlags = nFlags; + if( p->LoadData( rStrm, nVer ) ) + { + ULONG nNewPos = rStrm.Tell(); + nOldPos += nSize; + DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" ); + if( nOldPos != nNewPos ) + rStrm.Seek( nOldPos ); + if( !p->LoadCompleted() ) + { + // Loeschen des Objekts + SbxBaseRef aRef( p ); + p = NULL; + } + } + else + { + rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR ); + // Loeschen des Objekts + SbxBaseRef aRef( p ); + p = NULL; + } + } + else + rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR ); + return p; +} + +// Sbx-Objekt im Stream ueberspringen +void SbxBase::Skip( SvStream& rStrm ) +{ + UINT16 nSbxId, nFlags, nVer; + UINT32 nCreator, nSize; + rStrm >> nCreator >> nSbxId >> nFlags >> nVer; + + ULONG nStartPos = rStrm.Tell(); + rStrm >> nSize; + + rStrm.Seek( nStartPos + nSize ); +} + +BOOL SbxBase::Store( SvStream& rStrm ) +{ + DBG_CHKTHIS( SbxBase, 0 ); + if( !( nFlags & SBX_DONTSTORE ) ) + { + rStrm << (UINT32) GetCreator() + << (UINT16) GetSbxId() + << (UINT16) GetFlags() + << (UINT16) GetVersion(); + ULONG nOldPos = rStrm.Tell(); + rStrm << (UINT32) 0L; + BOOL bRes = StoreData( rStrm ); + ULONG nNewPos = rStrm.Tell(); + rStrm.Seek( nOldPos ); + rStrm << (UINT32) ( nNewPos - nOldPos ); + rStrm.Seek( nNewPos ); + if( rStrm.GetError() != SVSTREAM_OK ) + bRes = FALSE; + if( bRes ) + bRes = StoreCompleted(); + return bRes; + } + else + return TRUE; +} + +BOOL SbxBase::LoadData( SvStream&, USHORT ) +{ + DBG_CHKTHIS( SbxBase, 0 ); + return FALSE; +} + +BOOL SbxBase::StoreData( SvStream& ) const +{ + DBG_CHKTHIS( SbxBase, 0 ); + return FALSE; +} + +BOOL SbxBase::LoadPrivateData( SvStream&, USHORT ) +{ + DBG_CHKTHIS( SbxBase, 0 ); + return TRUE; +} + +BOOL SbxBase::StorePrivateData( SvStream& ) const +{ + DBG_CHKTHIS( SbxBase, 0 ); + return TRUE; +} + +BOOL SbxBase::LoadCompleted() +{ + DBG_CHKTHIS( SbxBase, 0 ); + return TRUE; +} + +BOOL SbxBase::StoreCompleted() +{ + DBG_CHKTHIS( SbxBase, 0 ); + return TRUE; +} + +//////////////////////////////// SbxFactory //////////////////////////////// + +SbxBase* SbxFactory::Create( UINT16, UINT32 ) +{ + return NULL; +} + +SbxObject* SbxFactory::CreateObject( const XubString& ) +{ + return NULL; +} + +///////////////////////////////// SbxInfo ////////////////////////////////// + +SbxInfo::~SbxInfo() +{} + +void SbxInfo::AddParam + ( const XubString& rName, SbxDataType eType, USHORT nFlags ) +{ + const SbxParamInfo* p = new SbxParamInfo( rName, eType, nFlags ); + aParams.Insert( p, aParams.Count() ); +} + +BOOL SbxInfo::LoadData( SvStream& rStrm, USHORT nVer ) +{ + aParams.Remove( 0, aParams.Count() ); + UINT16 nParam; + rStrm.ReadByteString( aComment, RTL_TEXTENCODING_ASCII_US ); + rStrm.ReadByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US ); + rStrm >> nHelpId >> nParam; + while( nParam-- ) + { + XubString aName; + UINT16 nType, nFlags; + UINT32 nUserData = 0; + rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US ); + rStrm >> nType >> nFlags; + if( nVer > 1 ) + rStrm >> nUserData; + AddParam( aName, (SbxDataType) nType, nFlags ); + SbxParamInfo* p = aParams.GetObject( aParams.Count() - 1 ); + p->nUserData = nUserData; + } + return TRUE; +} + +BOOL SbxInfo::StoreData( SvStream& rStrm ) const +{ + rStrm.WriteByteString( aComment, RTL_TEXTENCODING_ASCII_US ); + rStrm.WriteByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US ); + rStrm << nHelpId << aParams.Count(); + for( USHORT i = 0; i < aParams.Count(); i++ ) + { + SbxParamInfo* p = aParams.GetObject( i ); + rStrm.WriteByteString( p->aName, RTL_TEXTENCODING_ASCII_US ); + rStrm << (UINT16) p->eType + << (UINT16) p->nFlags + << (UINT32) p->nUserData; + } + return TRUE; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxbool.cxx b/binfilter/bf_basic/source/sbx/sbxbool.cxx new file mode 100644 index 000000000000..6fabf540c7f5 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxbool.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" +#include "sbxres.hxx" + +namespace binfilter { + +enum SbxBOOL ImpGetBool( const SbxValues* p ) +{ + enum SbxBOOL nRes; + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = SbxFALSE; break; + case SbxCHAR: + nRes = p->nChar ? SbxTRUE : SbxFALSE; break; + case SbxBYTE: + nRes = p->nByte ? SbxTRUE : SbxFALSE; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger ? SbxTRUE : SbxFALSE; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort ? SbxTRUE : SbxFALSE; break; + case SbxLONG: + nRes = p->nLong ? SbxTRUE : SbxFALSE; break; + case SbxULONG: + nRes = p->nULong ? SbxTRUE : SbxFALSE; break; + case SbxSINGLE: + nRes = p->nSingle ? SbxTRUE : SbxFALSE; break; + case SbxDATE: + case SbxDOUBLE: + nRes = p->nDouble ? SbxTRUE : SbxFALSE; break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + nRes = dVal ? SbxTRUE : SbxFALSE; + } + break; + case SbxSALINT64: + nRes = p->nInt64 ? SbxTRUE : SbxFALSE; break; + case SbxSALUINT64: + nRes = p->uInt64 ? SbxTRUE : SbxFALSE; break; + case SbxULONG64: + nRes = !!p->nULong64 ? SbxTRUE : SbxFALSE; break; + case SbxLONG64: + case SbxCURRENCY: + nRes = !!p->nLong64 ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + nRes = SbxFALSE; + if( p->pString ) + { + if( p->pString->EqualsIgnoreCaseAscii( SbxRes( STRING_TRUE ) ) ) + nRes = SbxTRUE; + else if( !p->pString->EqualsIgnoreCaseAscii( SbxRes( STRING_FALSE ) ) ) + { + // Jetzt kann es noch in eine Zahl konvertierbar sein + BOOL bError = TRUE; + double n; + SbxDataType t; + USHORT nLen = 0; + String s( *p->pString ); + if( ImpScan( s, n, t, &nLen ) == SbxERR_OK ) + { + if( nLen == s.Len() ) + { + bError = FALSE; + if( n != 0.0 ) + nRes = SbxTRUE; + } + } + if( bError ) + SbxBase::SetError( SbxERR_CONVERSION ); + } + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetBool() ? SbxTRUE : SbxFALSE; + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = SbxFALSE; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxLONG: + nRes = *p->pLong ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxULONG: + nRes = *p->pULong ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = *p->pUShort ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxSINGLE: + nRes = ( *p->pSingle != 0 ) ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + nRes = ( *p->pDouble != 0 ) ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxSALINT64: + nRes = ( *p->pnInt64 ) ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxSALUINT64: + nRes = ( *p->puInt64 ) ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxULONG64: + nRes = !!*p->pULong64 ? SbxTRUE : SbxFALSE; break; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + nRes = !!*p->pLong64 ? SbxTRUE : SbxFALSE; break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = SbxFALSE; + } + return nRes; +} + +void ImpPutBool( SbxValues* p, INT16 n ) +{ + if( n ) + n = SbxTRUE; + switch( +p->eType ) + { + case SbxCHAR: + p->nChar = (xub_Unicode) n; break; + case SbxUINT: + p->nByte = (BYTE) n; break; + case SbxINTEGER: + case SbxBOOL: + p->nInteger = n; break; + case SbxLONG: + p->nLong = n; break; + case SbxULONG: + p->nULong = (UINT32) n; break; + case SbxERROR: + case SbxUSHORT: + p->nUShort = (UINT16) n; break; + case SbxSINGLE: + p->nSingle = n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxSALUINT64: + p->uInt64 = n; break; + case SbxULONG64: + p->nULong64.Set( (UINT32)n ); break; + case SbxLONG64: + case SbxCURRENCY: + p->nLong64.Set( (INT32)n ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setInt( (INT16)n ); + break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + *p->pString = SbxRes( n ? STRING_TRUE : STRING_FALSE ); + break; + + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutBool( BOOL( n != 0 ) ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + *p->pLong = n; break; + case SbxBYREF | SbxULONG: + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = n; break; + case SbxBYREF | SbxULONG64: + p->pULong64->Set( (UINT32)n ); break; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + p->pLong64->Set( (INT32)n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxbyte.cxx b/binfilter/bf_basic/source/sbx/sbxbyte.cxx new file mode 100644 index 000000000000..6f19626042b0 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxbyte.cxx @@ -0,0 +1,333 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +BYTE ImpGetByte( const SbxValues* p ) +{ + SbxValues aTmp; + BYTE nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + if( p->nChar > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) p->nChar; + break; + case SbxBYTE: + nRes = (BYTE) p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + if( p->nInteger > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else if( p->nInteger < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) p->nInteger; + break; + case SbxERROR: + case SbxUSHORT: + if( p->nUShort > (USHORT) SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else + nRes = (BYTE) p->nUShort; + break; + case SbxLONG: + if( p->nLong > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else if( p->nLong < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) p->nLong; + break; + case SbxULONG: + if( p->nULong > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else + nRes = (BYTE) p->nULong; + break; + case SbxSALINT64: + if( p->nInt64 > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else if( p->nInt64 < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) p->nInt64; + break; + case SbxSALUINT64: + if( p->uInt64 > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else + nRes = (BYTE) p->uInt64; + break; + case SbxSINGLE: + if( p->nSingle > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else if( p->nSingle < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) ImpRound( p->nSingle ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else if( p->eType == SbxDECIMAL ) + { + dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + } + else + dVal = p->nDouble; + + if( dVal > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else if( dVal < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) ImpRound( dVal ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE; + } + else if( d < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (BYTE) ( d + 0.5 ); + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetByte(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxBYTE: + nRes = p->nByte; break; + + // ab hier wird getestet + case SbxBYREF | SbxCHAR: + aTmp.nChar = *p->pChar; goto ref; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + aTmp.nInteger = *p->pInteger; goto ref; + case SbxBYREF | SbxLONG: + aTmp.nLong = *p->pLong; goto ref; + case SbxBYREF | SbxULONG: + aTmp.nULong = *p->pULong; goto ref; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + aTmp.nUShort = *p->pUShort; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutByte( SbxValues* p, BYTE n ) +{ + switch( +p->eType ) + { + case SbxBYTE: + p->nByte = n; break; + case SbxINTEGER: + case SbxBOOL: + p->nInteger = n; break; + case SbxERROR: + case SbxUSHORT: + p->nUShort = n; break; + case SbxLONG: + p->nLong = n; break; + case SbxULONG: + p->nULong = n; break; + case SbxSINGLE: + p->nSingle = n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxSALUINT64: + p->uInt64 = n; break; + case SbxULONG64: + p->nULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxLONG64: + p->nLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxCURRENCY: + p->nLong64 = ImpDoubleToCurrency( (double)n ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setByte( n ); + break; + + case SbxCHAR: + p->nChar = (xub_Unicode) n; break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 0, *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutByte( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + *p->pByte = n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + *p->pInteger = n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + *p->pUShort = n; break; + case SbxBYREF | SbxLONG: + *p->pLong = n; break; + case SbxBYREF | SbxULONG: + *p->pULong = n; break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = n; break; + case SbxBYREF | SbxULONG64: + *p->pULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxBYREF | SbxLONG64: + *p->pLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = n; break; + case SbxBYREF | SbxCURRENCY: + *p->pLong64 = ImpDoubleToCurrency( (double)n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxchar.cxx b/binfilter/bf_basic/source/sbx/sbxchar.cxx new file mode 100644 index 000000000000..a34549217cd8 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxchar.cxx @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +xub_Unicode ImpGetChar( const SbxValues* p ) +{ + SbxValues aTmp; + xub_Unicode nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = (xub_Unicode) p->nByte; + break; + case SbxINTEGER: + case SbxBOOL: + if( p->nInteger < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR; + } + else + nRes = (xub_Unicode) p->nInteger; + break; + case SbxERROR: + case SbxUSHORT: + nRes = (xub_Unicode) p->nUShort; + break; + case SbxLONG: + if( p->nLong > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else if( p->nLong < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR; + } + else + nRes = (xub_Unicode) p->nLong; + break; + case SbxULONG: + if( p->nULong > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else + nRes = (xub_Unicode) p->nULong; + break; + case SbxSALINT64: + if( p->nInt64 > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else if( p->nInt64 < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR; + } + else + nRes = (xub_Unicode) p->nInt64; + break; + case SbxSALUINT64: + if( p->uInt64 > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else + nRes = (xub_Unicode) p->uInt64; + break; + case SbxSINGLE: + if( p->nSingle > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else if( p->nSingle < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR; + } + else + nRes = (xub_Unicode) ImpRound( p->nSingle ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else if( p->eType == SbxDECIMAL ) + { + dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + } + else + dVal = p->nDouble; + + if( dVal > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else if( dVal < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR; + } + else + nRes = (BYTE) ImpRound( dVal ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR; + } + else if( d < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR; + } + else + nRes = (xub_Unicode) ImpRound( d ); + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetChar(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + // ab hier wird getestet + case SbxBYREF | SbxBYTE: + aTmp.nByte = *p->pByte; goto ref; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + aTmp.nInteger = *p->pInteger; goto ref; + case SbxBYREF | SbxLONG: + aTmp.nLong = *p->pLong; goto ref; + case SbxBYREF | SbxULONG: + aTmp.nULong = *p->pULong; goto ref; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + aTmp.nUShort = *p->pUShort; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutChar( SbxValues* p, xub_Unicode n ) +{ + SbxValues aTmp; +start: + switch( +p->eType ) + { + case SbxCHAR: + p->nChar = n; break; + case SbxINTEGER: + case SbxBOOL: + p->nInteger = n; break; + case SbxLONG: + p->nLong = n; break; + case SbxSINGLE: + p->nSingle = n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxSALUINT64: + p->uInt64 = n; break; + case SbxULONG64: + p->nULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxLONG64: + p->nLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxCURRENCY: + p->nLong64 = ImpDoubleToCurrency( (double)n ); break; + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setChar( n ); + break; + + // ab hier wird getestet + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + *p->pString = n; + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutChar( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + *p->pChar = n; break; + case SbxBYREF | SbxBYTE: + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + *p->pInteger = n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = (float) n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = n; break; + case SbxBYREF | SbxULONG64: + *p->pULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxBYREF | SbxLONG64: + *p->pLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxBYREF | SbxCURRENCY: + *p->pLong64 = ImpDoubleToCurrency( (double)n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxcoll.cxx b/binfilter/bf_basic/source/sbx/sbxcoll.cxx new file mode 100644 index 000000000000..23c42ae7fd23 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxcoll.cxx @@ -0,0 +1,303 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/stream.hxx> + +#include "sbx.hxx" +#include "sbxres.hxx" + +namespace binfilter { + +TYPEINIT1(SbxCollection,SbxObject) +TYPEINIT1(SbxStdCollection,SbxCollection) + +static const char* pCount; +static const char* pAdd; +static const char* pItem; +static const char* pRemove; +static USHORT nCountHash = 0, nAddHash, nItemHash, nRemoveHash; + +///////////////////////////////////////////////////////////////////////// + +SbxCollection::SbxCollection( const XubString& rClass ) + : SbxObject( rClass ) +{ + if( !nCountHash ) + { + pCount = GetSbxRes( STRING_COUNTPROP ); + pAdd = GetSbxRes( STRING_ADDMETH ); + pItem = GetSbxRes( STRING_ITEMMETH ); + pRemove = GetSbxRes( STRING_REMOVEMETH ); + nCountHash = MakeHashCode( String::CreateFromAscii( pCount ) ); + nAddHash = MakeHashCode( String::CreateFromAscii( pAdd ) ); + nItemHash = MakeHashCode( String::CreateFromAscii( pItem ) ); + nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemove ) ); + } + Initialize(); + // Fuer Zugriffe auf sich selbst + StartListening( GetBroadcaster(), TRUE ); +} + +SbxCollection::SbxCollection( const SbxCollection& rColl ) + : SvRefBase( rColl ), SbxObject( rColl ) +{} + +SbxCollection& SbxCollection::operator=( const SbxCollection& r ) +{ + if( &r != this ) + SbxObject::operator=( r ); + return *this; +} + +SbxCollection::~SbxCollection() +{} + +void SbxCollection::Clear() +{ + SbxObject::Clear(); + Initialize(); +} + +void SbxCollection::Initialize() +{ + SetType( SbxOBJECT ); + SetFlag( SBX_FIXED ); + ResetFlag( SBX_WRITE ); + SbxVariable* p; + p = Make( String::CreateFromAscii( pCount ), SbxCLASS_PROPERTY, SbxINTEGER ); + p->ResetFlag( SBX_WRITE ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pAdd ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pItem ), SbxCLASS_METHOD, SbxOBJECT ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pRemove ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); +} + +SbxVariable* SbxCollection::FindUserData( UINT32 nData ) +{ + if( GetParameters() ) + { + SbxObject* pObj = (SbxObject*) GetObject(); + return pObj ? pObj->FindUserData( nData ) : NULL; + } + else + return SbxObject::FindUserData( nData ); +} + +SbxVariable* SbxCollection::Find( const XubString& rName, SbxClassType t ) +{ + if( GetParameters() ) + { + SbxObject* pObj = (SbxObject*) GetObject(); + return pObj ? pObj->Find( rName, t ) : NULL; + } + else + return SbxObject::Find( rName, t ); +} + +void SbxCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1, + const SfxHint& rHint, const TypeId& rId2 ) +{ + const SbxHint* p = PTR_CAST(SbxHint,&rHint); + if( p ) + { + ULONG nId = p->GetId(); + BOOL bRead = BOOL( nId == SBX_HINT_DATAWANTED ); + BOOL bWrite = BOOL( nId == SBX_HINT_DATACHANGED ); + SbxVariable* pVar = p->GetVar(); + SbxArray* pArg = pVar->GetParameters(); + if( bRead || bWrite ) + { + XubString aVarName( pVar->GetName() ); + if( pVar == this ) + CollItem( pArg ); + else if( pVar->GetHashCode() == nCountHash + && aVarName.EqualsIgnoreCaseAscii( pCount ) ) + pVar->PutLong( pObjs->Count() ); + else if( pVar->GetHashCode() == nAddHash + && aVarName.EqualsIgnoreCaseAscii( pAdd ) ) + CollAdd( pArg ); + else if( pVar->GetHashCode() == nItemHash + && aVarName.EqualsIgnoreCaseAscii( pItem ) ) + CollItem( pArg ); + else if( pVar->GetHashCode() == nRemoveHash + && aVarName.EqualsIgnoreCaseAscii( pRemove ) ) + CollRemove( pArg ); + else + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); + return; + } + } + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); +} + +// Default: Argument ist Objekt + +void SbxCollection::CollAdd( SbxArray* pPar_ ) +{ + if( pPar_->Count() != 2 ) + SetError( SbxERR_WRONG_ARGS ); + else + { + SbxBase* pObj = pPar_->Get( 1 )->GetObject(); + if( !pObj || !( pObj->ISA(SbxObject) ) ) + SetError( SbxERR_NOTIMP ); + else + Insert( (SbxObject*) pObj ); + } +} + +// Default: Index ab 1 oder der Objektname + +void SbxCollection::CollItem( SbxArray* pPar_ ) +{ + if( pPar_->Count() != 2 ) + SetError( SbxERR_WRONG_ARGS ); + else + { + SbxVariable* pRes = NULL; + SbxVariable* p = pPar_->Get( 1 ); + if( p->GetType() == SbxSTRING ) + pRes = Find( p->GetString(), SbxCLASS_OBJECT ); + else + { + short n = p->GetInteger(); + if( n >= 1 && n <= (short) pObjs->Count() ) + pRes = pObjs->Get( (USHORT) n - 1 ); + } + if( !pRes ) + SetError( SbxERR_BAD_INDEX ); + pPar_->Get( 0 )->PutObject( pRes ); + } +} + +// Default: Index ab 1 + +void SbxCollection::CollRemove( SbxArray* pPar_ ) +{ + if( pPar_->Count() != 2 ) + SetError( SbxERR_WRONG_ARGS ); + else + { + short n = pPar_->Get( 1 )->GetInteger(); + if( n < 1 || n > (short) pObjs->Count() ) + SetError( SbxERR_BAD_INDEX ); + else + Remove( pObjs->Get( (USHORT) n - 1 ) ); + } +} + +BOOL SbxCollection::LoadData( SvStream& rStrm, USHORT nVer ) +{ + BOOL bRes = SbxObject::LoadData( rStrm, nVer ); + Initialize(); + return bRes; +} + +///////////////////////////////////////////////////////////////////////// + +SbxStdCollection::SbxStdCollection + ( const XubString& rClass, const XubString& rElem, BOOL b ) + : SbxCollection( rClass ), aElemClass( rElem ), + bAddRemoveOk( b ) +{} + +SbxStdCollection::SbxStdCollection( const SbxStdCollection& r ) + : SvRefBase( r ), SbxCollection( r ), + aElemClass( r.aElemClass ), bAddRemoveOk( r.bAddRemoveOk ) +{} + +SbxStdCollection& SbxStdCollection::operator=( const SbxStdCollection& r ) +{ + if( &r != this ) + { + if( !r.aElemClass.EqualsIgnoreCaseAscii( aElemClass ) ) + SetError( SbxERR_CONVERSION ); + else + SbxCollection::operator=( r ); + } + return *this; +} + +SbxStdCollection::~SbxStdCollection() +{} + +// Default: Fehler, wenn falsches Objekt + +void SbxStdCollection::Insert( SbxVariable* p ) +{ + SbxObject* pObj = PTR_CAST(SbxObject,p); + if( pObj && !pObj->IsClass( aElemClass ) ) + SetError( SbxERR_BAD_ACTION ); + else + SbxCollection::Insert( p ); +} + +void SbxStdCollection::CollAdd( SbxArray* pPar_ ) +{ + if( !bAddRemoveOk ) + SetError( SbxERR_BAD_ACTION ); + else + SbxCollection::CollAdd( pPar_ ); +} + +void SbxStdCollection::CollRemove( SbxArray* pPar_ ) +{ + if( !bAddRemoveOk ) + SetError( SbxERR_BAD_ACTION ); + else + SbxCollection::CollRemove( pPar_ ); +} + +BOOL SbxStdCollection::LoadData( SvStream& rStrm, USHORT nVer ) +{ + BOOL bRes = SbxCollection::LoadData( rStrm, nVer ); + if( bRes ) + { + rStrm.ReadByteString( aElemClass, RTL_TEXTENCODING_ASCII_US ); + rStrm >> bAddRemoveOk; + } + return bRes; +} + +BOOL SbxStdCollection::StoreData( SvStream& rStrm ) const +{ + BOOL bRes = SbxCollection::StoreData( rStrm ); + if( bRes ) + { + rStrm.WriteByteString( aElemClass, RTL_TEXTENCODING_ASCII_US ); + rStrm << bAddRemoveOk; + } + return bRes; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxconv.hxx b/binfilter/bf_basic/source/sbx/sbxconv.hxx new file mode 100644 index 000000000000..03a523cf5832 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxconv.hxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBXCONV_HXX +#define _SBXCONV_HXX + +#include "sbxdec.hxx" + +namespace binfilter { + +class SbxINT64Converter +{ +public: + static BigInt SbxINT64_2_BigInt( const SbxINT64 &r ); + static BOOL BigInt_2_SbxINT64( const BigInt& b, SbxINT64 *p ); + static BigInt SbxUINT64_2_BigInt( const SbxUINT64 &r ); + static BOOL BigInt_2_SbxUINT64( const BigInt& b, SbxUINT64 *p ); +}; + +// SBXSCAN.CXX +extern void ImpCvtNum( double nNum, short nPrec, String& rRes, BOOL bCoreString=FALSE ); +extern SbxError ImpScan + ( const String& rSrc, double& nVal, SbxDataType& rType, USHORT* pLen, + BOOL bAllowIntntl=FALSE, BOOL bOnlyIntntl=FALSE ); + +// SBXINT.CXX + +double ImpRound( double ); +INT16 ImpGetInteger( const SbxValues* ); +void ImpPutInteger( SbxValues*, INT16 ); +sal_Int64 ImpGetInt64( const SbxValues* ); +void ImpPutInt64( SbxValues*, sal_Int64 ); +sal_uInt64 ImpGetUInt64( const SbxValues* ); +void ImpPutUInt64( SbxValues*, sal_uInt64 ); + +sal_Int64 ImpDoubleToSalInt64( double d ); +sal_uInt64 ImpDoubleToSalUInt64( double d ); +double ImpSalUInt64ToDouble( sal_uInt64 n ); + +// SBXLNG.CXX + +INT32 ImpGetLong( const SbxValues* ); +void ImpPutLong( SbxValues*, INT32 ); + +// SBXSNG.CXX + +float ImpGetSingle( const SbxValues* ); +void ImpPutSingle( SbxValues*, float ); + +// SBXDBL.CXX + +double ImpGetDouble( const SbxValues* ); +void ImpPutDouble( SbxValues*, double, BOOL bCoreString=FALSE ); + +#if FALSE +// SBX64.CXX + +SbxINT64 ImpGetINT64( const SbxValues* ); +void ImpPutINT64( SbxValues*, const SbxINT64& ); +SbxUINT64 ImpGetUINT64( const SbxValues* ); +void ImpPutUINT64( SbxValues*, const SbxUINT64& ); +#endif + +// SBXCURR.CXX + +SbxUINT64 ImpDoubleToUINT64( double ); +double ImpUINT64ToDouble( const SbxUINT64& ); +SbxINT64 ImpDoubleToINT64( double ); +double ImpINT64ToDouble( const SbxINT64& ); + +#if TRUE +INT32 ImpGetCurrLong( const SbxValues* ); +void ImpPutCurrLong( SbxValues*, INT32 ); +INT32 ImpDoubleToCurrLong( double ); +double ImpCurrLongToDouble( INT32 ); +#endif + +SbxINT64 ImpGetCurrency( const SbxValues* ); +void ImpPutCurrency( SbxValues*, const SbxINT64& ); +inline +SbxINT64 ImpDoubleToCurrency( double d ) + { return ImpDoubleToINT64( d * CURRENCY_FACTOR ); } +inline +double ImpCurrencyToDouble( const SbxINT64 &r ) + { return ImpINT64ToDouble( r ) / CURRENCY_FACTOR; } + + +// SBXDEC.CXX + +SbxDecimal* ImpCreateDecimal( SbxValues* p ); +SbxDecimal* ImpGetDecimal( const SbxValues* p ); +void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec ); + +// SBXDATE.CXX + +double ImpGetDate( const SbxValues* ); +void ImpPutDate( SbxValues*, double ); + +// SBXSTR.CXX + +String ImpGetString( const SbxValues* ); +String ImpGetCoreString( const SbxValues* ); +void ImpPutString( SbxValues*, const String* ); + +// SBXCHAR.CXX + +sal_Unicode ImpGetChar( const SbxValues* ); +void ImpPutChar( SbxValues*, sal_Unicode ); + +// SBXBYTE.CXX +BYTE ImpGetByte( const SbxValues* ); +void ImpPutByte( SbxValues*, BYTE ); + +// SBXUINT.CXX + +UINT16 ImpGetUShort( const SbxValues* ); +void ImpPutUShort( SbxValues*, UINT16 ); + +// SBXULNG.CXX + +UINT32 ImpGetULong( const SbxValues* ); +void ImpPutULong( SbxValues*, UINT32 ); + +// SBXBOOL.CXX + +enum SbxBOOL ImpGetBool( const SbxValues* ); +void ImpPutBool( SbxValues*, INT16 ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxcurr.cxx b/binfilter/bf_basic/source/sbx/sbxcurr.cxx new file mode 100644 index 000000000000..5e273496bd83 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxcurr.cxx @@ -0,0 +1,399 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sbx.hxx" + +#include <tools/errcode.hxx> + +#define _TLBIGINT_INT64 +#include <tools/bigint.hxx> + +#include "sbxvar.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +static String ImpCurrencyToString( const SbxINT64& ); +static SbxINT64 ImpStringToCurrency( const String& ); + +SbxINT64 ImpGetCurrency( const SbxValues* p ) +{ + SbxValues aTmp; + SbxINT64 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes.SetNull(); break; + case SbxCHAR: + nRes = ImpDoubleToCurrency( (double)p->nChar ); break; + case SbxBYTE: + nRes = ImpDoubleToCurrency( (double)p->nByte ); break; + case SbxINTEGER: + case SbxBOOL: + nRes = ImpDoubleToCurrency( (double)p->nInteger ); break; + case SbxERROR: + case SbxUSHORT: + nRes = ImpDoubleToCurrency( (double)p->nUShort ); break; + case SbxCURRENCY: + nRes = p->nLong64; break; + case SbxLONG: + nRes = ImpDoubleToCurrency( (double)p->nLong ); + break; + case SbxULONG: + nRes = ImpDoubleToCurrency( (double)p->nULong ); + break; + case SbxSALINT64: + nRes = ImpDoubleToCurrency( (double)p->nInt64 ); + break; + case SbxSALUINT64: + nRes = ImpDoubleToCurrency( ImpSalUInt64ToDouble( p->uInt64 ) ); + break; + case SbxSINGLE: + if( p->nSingle > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax(); + } + else if( p->nSingle < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin(); + } + else + nRes = ImpDoubleToCurrency( (double)p->nSingle ); + break; + case SbxDATE: + case SbxDOUBLE: + if( p->nDouble > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax(); + } + else if( p->nDouble < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin(); + } + else + nRes = ImpDoubleToCurrency( p->nDouble ); + break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double d = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( d ); + if( d > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax(); + } + else if( d < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin(); + } + else + nRes = ImpDoubleToCurrency( d ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes.SetNull(); + else + nRes = ImpStringToCurrency( *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetCurrency(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes.SetNull(); + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = ImpDoubleToCurrency( (double)*p->pChar ); break; + case SbxBYREF | SbxBYTE: + nRes = ImpDoubleToCurrency( (double)*p->pByte ); break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = ImpDoubleToCurrency( (double)*p->pInteger ); break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = ImpDoubleToCurrency( (double)*p->pUShort ); break; + case SbxBYREF | SbxCURRENCY: + nRes = *p->pLong64; break; + + // ab hier muss getestet werden + case SbxBYREF | SbxLONG: + aTmp.nLong = *p->pLong; goto ref; + case SbxBYREF | SbxULONG: + aTmp.nULong = *p->pULong; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes.SetNull(); + } + return nRes; +} + +void ImpPutCurrency( SbxValues* p, const SbxINT64 &r ) +{ + double dVal = ImpCurrencyToDouble( r ); + SbxValues aTmp; +start: + switch( +p->eType ) + { + // Hier sind Tests notwendig + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxLONG: + aTmp.pLong = &p->nLong; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // ab hier nicht mehr + case SbxSINGLE: + p->nSingle = (float)dVal; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = dVal; break; + case SbxSALINT64: + p->nInt64 = ImpDoubleToSalInt64( dVal ); break; + case SbxSALUINT64: + p->uInt64 = ImpDoubleToSalUInt64( dVal ); break; + case SbxCURRENCY: + p->nLong64 = r; break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + SbxDecimal* pDec = ImpCreateDecimal( p ); + if( !pDec->setDouble( dVal ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + + *p->pString = ImpCurrencyToString( r ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutCurrency( r ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( dVal > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXCHAR; + } + else if( dVal < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINCHAR; + } + *p->pChar = (xub_Unicode) dVal; break; + case SbxBYREF | SbxBYTE: + if( dVal > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXBYTE; + } + else if( dVal < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0; + } + *p->pByte = (BYTE) dVal; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( dVal > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXINT; + } + else if( dVal < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMININT; + } + *p->pInteger = (INT16) dVal; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( dVal > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXUINT; + } + else if( dVal < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0; + } + *p->pUShort = (UINT16) dVal; break; + case SbxBYREF | SbxLONG: + if( dVal > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXLNG; + } + else if( dVal < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINLNG; + } + *p->pLong = (INT32) dVal; break; + case SbxBYREF | SbxULONG: + if( dVal > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXULNG; + } + else if( dVal < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0; + } + *p->pULong = (UINT32) dVal; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = ImpDoubleToSalInt64( dVal ); break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = ImpDoubleToSalUInt64( dVal ); break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = (float) dVal; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) dVal; break; + case SbxBYREF | SbxCURRENCY: + *p->pLong64 = r; break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +// Hilfs-Funktionen zur Wandlung + +static String ImpCurrencyToString( const SbxINT64 &r ) +{ + BigInt a10000 = 10000; + + //return GetpApp()->GetAppInternational().GetCurr( BigInt( r ), 4 ); + BigInt aInt( SbxINT64Converter::SbxINT64_2_BigInt( r ) ); + aInt.Abs(); + BigInt aFrac = aInt; + aInt /= a10000; + aFrac %= a10000; + aFrac += a10000; + + String aString; + if( r.nHigh < 0 ) + aString = '-'; + aString += aInt.GetString(); + aString += '.'; + aString += aFrac.GetString().GetBuffer()+1; + return aString; +} + +static SbxINT64 ImpStringToCurrency( const String &r ) +{ + int nDec = 4; + String aStr; + const sal_Unicode* p = r.GetBuffer(); + + if( *p == '-' ) + aStr += *p++; + + while( *p >= '0' && *p <= '9' ) { + aStr += *p++; + if( *p == ',' ) + p++; + } + + if( *p == '.' ) { + p++; + while( nDec && *p >= '0' && *p <= '9' ) { + aStr += *p++; + nDec--; + } + } + while( nDec ) { + aStr += '0'; + nDec--; + } + + BigInt aBig( aStr ); + SbxINT64 nRes; + SbxINT64Converter::BigInt_2_SbxINT64( aBig, &nRes ); + return nRes; +} + +double ImpINT64ToDouble( const SbxINT64 &r ) +{ return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; } + +SbxINT64 ImpDoubleToINT64( double d ) +{ + SbxINT64 nRes; + nRes.Set( d ); + return nRes; +} + +double ImpUINT64ToDouble( const SbxUINT64 &r ) +{ return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; } + +SbxUINT64 ImpDoubleToUINT64( double d ) +{ + SbxUINT64 nRes; + nRes.Set( d ); + return nRes; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxdate.cxx b/binfilter/bf_basic/source/sbx/sbxdate.cxx new file mode 100644 index 000000000000..d936c719333b --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxdate.cxx @@ -0,0 +1,416 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <vcl/svapp.hxx> +#include <bf_svtools/zforlist.hxx> +#include <tools/errcode.hxx> +#include <tools/color.hxx> +#include <i18npool/lang.h> +#include "sbx.hxx" +#include "sbxconv.hxx" +#include "math.h" + +#include <comphelper/processfactory.hxx> + +namespace binfilter { + +double ImpGetDate( const SbxValues* p ) +{ + double nRes; + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; break; + case SbxLONG: + nRes = (double) p->nLong; break; + case SbxULONG: + nRes = (double) p->nULong; break; + case SbxSINGLE: + nRes = p->nSingle; break; + case SbxDATE: + case SbxDOUBLE: + nRes = p->nDouble; break; + case SbxULONG64: + nRes = ImpUINT64ToDouble( p->nULong64 ); break; + case SbxLONG64: + nRes = ImpINT64ToDouble( p->nLong64 ); break; + case SbxCURRENCY: + nRes = ImpCurrencyToDouble( p->nLong64 ); break; + case SbxSALINT64: + nRes = static_cast< double >(p->nInt64); break; + case SbxSALUINT64: + nRes = ImpSalUInt64ToDouble( p->uInt64 ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + if( p->pDecimal ) + p->pDecimal->getDouble( nRes ); + else + nRes = 0.0; + break; + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { +#ifndef DOS + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + + SvNumberFormatter* pFormatter; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + xFactory = comphelper::getProcessServiceFactory(); + pFormatter = new SvNumberFormatter( xFactory, eLangType ); + + sal_uInt32 nIndex; + xub_StrLen nCheckPos = 0; + short nType = 127; + + // 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 basic\source\runtime\runtime.cxx + + SvtSysLocale aSysLocale; + DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat(); + String aDateStr; + switch( eDate ) + { + case MDY: aDateStr.AssignAscii( "MM.TT.JJJJ" ); break; + case DMY: aDateStr.AssignAscii( "TT.MM.JJJJ" ); break; + case YMD: aDateStr.AssignAscii( "JJJJ.MM.TT" ); break; + default: aDateStr.AssignAscii( "MM.TT.JJJJ" ); + } + + String aStr( aDateStr ); + aStr.AppendAscii( " HH:MM:SS" ); + + pFormatter->PutandConvertEntry( aStr, nCheckPos, nType, + nIndex, LANGUAGE_GERMAN, eLangType ); + BOOL bSuccess = pFormatter->IsNumberFormat( *p->pString, nIndex, nRes ); + if ( bSuccess ) + { + short nType_ = pFormatter->GetType( nIndex ); + if(!(nType_ & ( NUMBERFORMAT_DATETIME | NUMBERFORMAT_DATE | + NUMBERFORMAT_TIME | NUMBERFORMAT_DEFINED ))) + bSuccess = FALSE; + } + + if ( !bSuccess ) + { + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + + delete pFormatter; +#else + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; +#endif + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetDate(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + case SbxBYREF | SbxLONG: + nRes = *p->pLong; break; + case SbxBYREF | SbxULONG: + nRes = *p->pULong; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = *p->pUShort; break; + case SbxBYREF | SbxSINGLE: + nRes = *p->pSingle; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + nRes = *p->pDouble; break; + case SbxBYREF | SbxULONG64: + nRes = ImpUINT64ToDouble( *p->pULong64 ); break; + case SbxBYREF | SbxLONG64: + nRes = ImpINT64ToDouble( *p->pLong64 ); break; + case SbxBYREF | SbxCURRENCY: + nRes = ImpCurrencyToDouble( *p->pLong64 ); break; + case SbxBYREF | SbxSALINT64: + nRes = static_cast< double >(*p->pnInt64); break; + case SbxBYREF | SbxSALUINT64: + nRes = ImpSalUInt64ToDouble( *p->puInt64 ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutDate( SbxValues* p, double n ) +{ + SbxValues aTmp; + +start: + switch( +p->eType ) + { + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + + // ab hier wird getestet + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxLONG: + aTmp.pLong = &p->nLong; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxSINGLE: + aTmp.pSingle = &p->nSingle; goto direct; + case SbxULONG64: + aTmp.pULong64 = &p->nULong64; goto direct; + case SbxLONG64: + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + case SbxSALINT64: + aTmp.pnInt64 = &p->nInt64; goto direct; + case SbxSALUINT64: + aTmp.puInt64 = &p->uInt64; goto direct; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + SbxDecimal* pDec = ImpCreateDecimal( p ); + if( !pDec->setDouble( n ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + break; + } + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: +#ifndef DOS + { + if( !p->pString ) + p->pString = new XubString; + Color* pColor; + + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + SvNumberFormatter* pFormatter; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + xFactory = comphelper::getProcessServiceFactory(); + pFormatter = new SvNumberFormatter( xFactory, eLangType ); + + sal_uInt32 nIndex; + xub_StrLen nCheckPos = 0; + short nType; + + SvtSysLocale aSysLocale; + DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat(); + String aStr; + // ist der ganzzahlige Teil 0, wollen wir kein Jahr! + if( n <= -1.0 || n >= 1.0 ) + { + // Time only if != 00:00:00 + if( floor( n ) == n ) + { + switch( eDate ) + { + case MDY: aStr.AssignAscii( "MM.TT.JJJJ" ); break; + case DMY: aStr.AssignAscii( "TT.MM.JJJJ" ); break; + case YMD: aStr.AssignAscii( "JJJJ.MM.TT" ); break; + default: aStr.AssignAscii( "MM.TT.JJJJ" ); + } + } + else + { + switch( eDate ) + { + case MDY: aStr.AssignAscii( "MM.TT.JJJJ HH:MM:SS" ); break; + case DMY: aStr.AssignAscii( "TT.MM.JJJJ HH:MM:SS" ); break; + case YMD: aStr.AssignAscii( "JJJJ.MM.TT HH:MM:SS" ); break; + default: aStr.AssignAscii( "MM.TT.JJJJ HH:MM:SS" ); + } + } + } + else + aStr.AppendAscii( "HH:MM:SS" ); + + pFormatter->PutandConvertEntry( aStr, + nCheckPos, + nType, + nIndex, + LANGUAGE_GERMAN, + eLangType ); + pFormatter->GetOutputString( n, nIndex, *p->pString, &pColor ); + delete pFormatter; +#endif + break; +#ifndef DOS + } +#endif + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutDate( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + else if( n < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + else if( n < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + if( n > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG; + } + else if( n < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG; + } + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + if( n > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSINGLE: + if( n > SbxMAXSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG; + } + else if( n < SbxMINSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG; + } + *p->pSingle = (float) n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = ImpDoubleToSalInt64( n ); break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = ImpDoubleToSalUInt64( n ); break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxCURRENCY: + if( n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCURR; + } + else if( n < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCURR; + } + *p->pLong64 = ImpDoubleToCurrency( n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxdbl.cxx b/binfilter/bf_basic/source/sbx/sbxdbl.cxx new file mode 100644 index 000000000000..25815cee7482 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxdbl.cxx @@ -0,0 +1,301 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +double ImpGetDouble( const SbxValues* p ) +{ + double nRes; + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; break; + case SbxLONG: + nRes = p->nLong; break; + case SbxULONG: + nRes = p->nULong; break; + case SbxSINGLE: + nRes = p->nSingle; break; + case SbxDATE: + case SbxDOUBLE: + nRes = p->nDouble; break; + case SbxCURRENCY: + nRes = ImpCurrencyToDouble( p->nLong64 ); break; + case SbxSALINT64: + nRes = static_cast< double >(p->nInt64); break; + case SbxSALUINT64: + nRes = ImpSalUInt64ToDouble( p->uInt64 ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + if( p->pDecimal ) + p->pDecimal->getDouble( nRes ); + else + nRes = 0.0; + break; + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else + nRes = d; + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetDouble(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + case SbxBYREF | SbxLONG: + nRes = *p->pLong; break; + case SbxBYREF | SbxULONG: + nRes = *p->pULong; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = *p->pUShort; break; + case SbxBYREF | SbxSINGLE: + nRes = *p->pSingle; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + nRes = *p->pDouble; break; + case SbxBYREF | SbxCURRENCY: + nRes = ImpCurrencyToDouble( *p->pLong64 ); break; + case SbxBYREF | SbxSALINT64: + nRes = static_cast< double >(*p->pnInt64); break; + case SbxBYREF | SbxSALUINT64: + nRes = ImpSalUInt64ToDouble( *p->puInt64 ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutDouble( SbxValues* p, double n, BOOL bCoreString ) +{ + SbxValues aTmp; +start: + switch( +p->eType ) + { + // Hier sind Tests notwendig + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxLONG: + case SbxCURRENCY: + aTmp.pLong = &p->nLong; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxSINGLE: + aTmp.pSingle = &p->nSingle; goto direct; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + SbxDecimal* pDec = ImpCreateDecimal( p ); + if( !pDec->setDouble( n ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + break; + } + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // ab hier nicht mehr + case SbxSALINT64: + p->nInt64 = ImpDoubleToSalInt64( n ); break; + case SbxSALUINT64: + p->uInt64 = ImpDoubleToSalUInt64( n ); break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 14, *p->pString, bCoreString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutDouble( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + else if( n < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + else if( n < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + if( n > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG; + } + else if( n < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG; + } + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + if( n > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSINGLE: + if( n > SbxMAXSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG; + } + else if( n < SbxMINSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG; + } + else if( n > 0 && n < SbxMAXSNG2 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG2; + } + else if( n < 0 && n > SbxMINSNG2 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG2; + } + *p->pSingle = (float) n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = ImpDoubleToSalInt64( n ); break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = ImpDoubleToSalUInt64( n ); break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxCURRENCY: + if( n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCURR; + } + else if( n < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCURR; + } + *p->pLong64 = ImpDoubleToCurrency( n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxdec.cxx b/binfilter/bf_basic/source/sbx/sbxdec.cxx new file mode 100644 index 000000000000..ff74d6664d92 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxdec.cxx @@ -0,0 +1,742 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> + +#include "sbx.hxx" +#include "sbxconv.hxx" + +#include <com/sun/star/bridge/oleautomation/Decimal.hpp> + +namespace binfilter { + +#ifdef WIN32 +// int GnDecCounter = 0; +SbxDecimal::SbxDecimal( void ) +{ + setInt( 0 ); + mnRefCount = 0; + // GnDecCounter++; +} +#endif + +SbxDecimal::SbxDecimal( const SbxDecimal& rDec ) +{ +#ifdef WIN32 + maDec = rDec.maDec; +#else + (void)rDec; +#endif + mnRefCount = 0; + // GnDecCounter++; +} + +SbxDecimal::~SbxDecimal() +{ + // GnDecCounter--; +} + +void releaseDecimalPtr( SbxDecimal*& rpDecimal ) +{ + if( rpDecimal ) + { + rpDecimal->mnRefCount--; + if( rpDecimal->mnRefCount == 0 ) + { + delete rpDecimal; + rpDecimal = NULL; + } + } +} + +#ifdef WIN32 + +bool SbxDecimal::operator -= ( const SbxDecimal &r ) +{ + HRESULT hResult = VarDecSub( &maDec, (LPDECIMAL)&r.maDec, &maDec ); + bool bRet = ( hResult == S_OK ); + return bRet; +} + +bool SbxDecimal::operator += ( const SbxDecimal &r ) +{ + HRESULT hResult = VarDecAdd( &maDec, (LPDECIMAL)&r.maDec, &maDec ); + bool bRet = ( hResult == S_OK ); + return bRet; +} + +bool SbxDecimal::operator /= ( const SbxDecimal &r ) +{ + HRESULT hResult = VarDecDiv( &maDec, (LPDECIMAL)&r.maDec, &maDec ); + bool bRet = ( hResult == S_OK ); + return bRet; +} + +bool SbxDecimal::operator *= ( const SbxDecimal &r ) +{ + HRESULT hResult = VarDecMul( &maDec, (LPDECIMAL)&r.maDec, &maDec ); + bool bRet = ( hResult == S_OK ); + return bRet; +} + +bool SbxDecimal::neg( void ) +{ + HRESULT hResult = VarDecNeg( &maDec, &maDec ); + bool bRet = ( hResult == S_OK ); + return bRet; +} + +bool SbxDecimal::isZero( void ) +{ + SbxDecimal aZeroDec; + aZeroDec.setLong( 0 ); + bool bZero = ( EQ == compare( *this, aZeroDec ) ); + return bZero; +} + +SbxDecimal::CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight ) +{ + HRESULT hResult = VarDecCmp( (LPDECIMAL)&rLeft.maDec, (LPDECIMAL)&rRight.maDec ); + SbxDecimal::CmpResult eRes = (SbxDecimal::CmpResult)hResult; + return eRes; +} + +void SbxDecimal::setChar( sal_Unicode val ) +{ + VarDecFromUI2( (USHORT)val, &maDec ); +} + +void SbxDecimal::setByte( BYTE val ) +{ + VarDecFromUI1( (BYTE)val, &maDec ); +} + +void SbxDecimal::setShort( INT16 val ) +{ + VarDecFromI2( (short)val, &maDec ); +} + +void SbxDecimal::setLong( INT32 val ) +{ + VarDecFromI4( (long)val, &maDec ); +} + +void SbxDecimal::setUShort( UINT16 val ) +{ + VarDecFromUI2( (USHORT)val, &maDec ); +} + +void SbxDecimal::setULong( UINT32 val ) +{ + VarDecFromUI4( (ULONG)val, &maDec ); +} + +bool SbxDecimal::setSingle( float val ) +{ + bool bRet = ( VarDecFromR4( val, &maDec ) == S_OK ); + return bRet; +} + +bool SbxDecimal::setDouble( double val ) +{ + bool bRet = ( VarDecFromR8( val, &maDec ) == S_OK ); + return bRet; +} + +void SbxDecimal::setInt( int val ) +{ + setLong( (INT32)val ); +} + +void SbxDecimal::setUInt( unsigned int val ) +{ + setULong( (UINT32)val ); +} + +// sbxscan.cxx +void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep ); + +bool SbxDecimal::setString( String* pString ) +{ + static LCID nLANGID = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); + + // Convert delimiter + sal_Unicode cDecimalSep; + sal_Unicode cThousandSep; + ImpGetIntntlSep( cDecimalSep, cThousandSep ); + + bool bRet = false; + HRESULT hResult; + if( cDecimalSep != '.' || cThousandSep != ',' ) + { + int nLen = pString->Len(); + sal_Unicode* pBuffer = new sal_Unicode[nLen + 1]; + pBuffer[nLen] = 0; + + const sal_Unicode* pSrc = pString->GetBuffer(); + int i; + for( i = 0 ; i < nLen ; ++i ) + pBuffer[i] = pSrc[i]; + + sal_Unicode c; + i = 0; + while( (c = pBuffer[i]) != 0 ) + { + if( c == cDecimalSep ) + pBuffer[i] = '.'; + else if( c == cThousandSep ) + pBuffer[i] = ','; + i++; + } + hResult = VarDecFromStr( (OLECHAR*)pBuffer, nLANGID, 0, &maDec ); + delete pBuffer; + } + else + { + hResult = VarDecFromStr( (OLECHAR*)pString->GetBuffer(), nLANGID, 0, &maDec ); + } + bRet = ( hResult == S_OK ); + return bRet; +} + + +bool SbxDecimal::getChar( sal_Unicode& rVal ) +{ + bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getShort( INT16& rVal ) +{ + bool bRet = ( VarI2FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getLong( INT32& rVal ) +{ + bool bRet = ( VarI4FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getUShort( UINT16& rVal ) +{ + bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getULong( UINT32& rVal ) +{ + bool bRet = ( VarUI4FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getSingle( float& rVal ) +{ + bool bRet = ( VarR4FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getDouble( double& rVal ) +{ + bool bRet = ( VarR8FromDec( &maDec, &rVal ) == S_OK ); + return bRet; +} + +bool SbxDecimal::getUInt( unsigned int& rVal ) +{ + UINT32 TmpVal; + bool bRet = getULong( TmpVal ); + rVal = TmpVal; + return bRet; +} + +#else +// !WIN32 + +bool SbxDecimal::operator -= ( const SbxDecimal &r ) +{ + (void)r; + return false; +} + +bool SbxDecimal::operator += ( const SbxDecimal &r ) +{ + (void)r; + return false; +} + +bool SbxDecimal::operator /= ( const SbxDecimal &r ) +{ + (void)r; + return false; +} + +bool SbxDecimal::operator *= ( const SbxDecimal &r ) +{ + (void)r; + return false; +} + +bool SbxDecimal::neg( void ) +{ + return false; +} + +bool SbxDecimal::isZero( void ) +{ + return false; +} + +SbxDecimal::CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight ) +{ + (void)rLeft; + (void)rRight; + return (SbxDecimal::CmpResult)0; +} + +void SbxDecimal::setChar( sal_Unicode val ) { (void)val; } +void SbxDecimal::setByte( BYTE val ) { (void)val; } +void SbxDecimal::setLong( INT32 val ) { (void)val; } +void SbxDecimal::setULong( UINT32 val ) { (void)val; } +bool SbxDecimal::setSingle( float val ) { (void)val; return false; } +bool SbxDecimal::setDouble( double val ) { (void)val; return false; } +void SbxDecimal::setInt( int val ) { (void)val; } +void SbxDecimal::setUInt( unsigned int val ) { (void)val; } + +bool SbxDecimal::getSingle( float& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getDouble( double& rVal ) { (void)rVal; return false; } + +#endif + +#ifdef WIN32 +bool SbxDecimal::getString( String& rString ) +{ + static LCID nLANGID = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); + + bool bRet = false; + + OLECHAR sz[100]; + BSTR aBStr = SysAllocString( sz ); + if( aBStr != NULL ) + { + HRESULT hResult = VarBstrFromDec( &maDec, nLANGID, 0, &aBStr ); + bRet = ( hResult == S_OK ); + if( bRet ) + { + // Convert delimiter + sal_Unicode cDecimalSep; + sal_Unicode cThousandSep; + ImpGetIntntlSep( cDecimalSep, cThousandSep ); + + if( cDecimalSep != '.' || cThousandSep != ',' ) + { + sal_Unicode c; + int i = 0; + while( (c = aBStr[i]) != 0 ) + { + if( c == '.' ) + aBStr[i] = cDecimalSep; + else if( c == ',' ) + aBStr[i] = cThousandSep; + i++; + } + } + rString = reinterpret_cast<const sal_Unicode*>(aBStr); + } + + SysFreeString( aBStr ); + } + return bRet; +} +#endif + +SbxDecimal* ImpCreateDecimal( SbxValues* p ) +{ +#ifdef WIN32 + if( !p ) + return NULL; + + SbxDecimal*& rpDecimal = p->pDecimal; + if( rpDecimal == NULL ) + { + rpDecimal = new SbxDecimal(); + rpDecimal->addRef(); + } + return rpDecimal; +#else + (void)p; + return NULL; +#endif +} + +SbxDecimal* ImpGetDecimal( const SbxValues* p ) +{ +#ifdef WIN32 + SbxValues aTmp; + SbxDecimal* pnDecRes; + + SbxDataType eType = p->eType; + if( eType == SbxDECIMAL && p->pDecimal ) + { + pnDecRes = new SbxDecimal( *p->pDecimal ); + pnDecRes->addRef(); + return pnDecRes; + } + pnDecRes = new SbxDecimal(); + pnDecRes->addRef(); + +start: + switch( +eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + pnDecRes->setShort( 0 ); break; + case SbxCHAR: + pnDecRes->setChar( p->nChar ); break; + case SbxBYTE: + pnDecRes->setByte( p->nByte ); break; + case SbxINTEGER: + case SbxBOOL: + pnDecRes->setInt( p->nInteger ); break; + case SbxERROR: + case SbxUSHORT: + pnDecRes->setUShort( p->nUShort ); break; + case SbxLONG: + pnDecRes->setLong( p->nLong ); break; + case SbxULONG: + pnDecRes->setULong( p->nULong ); break; + case SbxSINGLE: + if( !pnDecRes->setSingle( p->nSingle ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + break; + case SbxSALINT64: + { + double d = (double)p->nInt64; + pnDecRes->setDouble( d ); + break; + } + case SbxSALUINT64: + { + double d = ImpSalUInt64ToDouble( p->uInt64 ); + pnDecRes->setDouble( d ); + break; + } + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else + dVal = p->nDouble; + + if( !pnDecRes->setDouble( dVal ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + break; + } + case SbxLPSTR: + case SbxSTRING: + case SbxBYREF | SbxSTRING: + pnDecRes->setString( p->pString ); break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pnDecRes->setDecimal( pVal->GetDecimal() ); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); + pnDecRes->setShort( 0 ); + } + break; + } + + case SbxBYREF | SbxCHAR: + pnDecRes->setChar( *p->pChar ); break; + case SbxBYREF | SbxBYTE: + pnDecRes->setByte( *p->pByte ); break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + pnDecRes->setInt( *p->pInteger ); break; + case SbxBYREF | SbxLONG: + pnDecRes->setLong( *p->pLong ); break; + case SbxBYREF | SbxULONG: + pnDecRes->setULong( *p->pULong ); break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + pnDecRes->setUShort( *p->pUShort ); break; + + // ab hier muss getestet werden + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); pnDecRes->setShort( 0 ); + } + return pnDecRes; +#else + (void)p; + return NULL; +#endif +} + + +void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec ) +{ +#ifdef WIN32 + if( !pDec ) + return; + + SbxValues aTmp; +start: + switch( +p->eType ) + { + // hier muss getestet werden + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxSALUINT64: + aTmp.puInt64 = &p->uInt64; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxLONG: + aTmp.pLong = &p->nLong; goto direct; + case SbxSALINT64: + aTmp.pnInt64 = &p->nInt64; goto direct; + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // ab hier nicht mehr + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + if( pDec != p->pDecimal ) + { + releaseDecimalPtr( p->pDecimal ); + // if( p->pDecimal ) + // p->pDecimal->ReleaseRef(); + p->pDecimal = pDec; + if( pDec ) + pDec->addRef(); + } + break; + } + case SbxSINGLE: + { + float f; + pDec->getSingle( f ); + p->nSingle = f; + break; + } + case SbxDATE: + case SbxDOUBLE: + { + double d; + pDec->getDouble( d ); + p->nDouble = d; + break; + } + case SbxULONG64: + { + double d; + pDec->getDouble( d ); + p->nULong64 = ImpDoubleToUINT64( d ); + break; + } + case SbxLONG64: + { + double d; + pDec->getDouble( d ); + p->nLong64 = ImpDoubleToINT64( d ); + break; + } + + case SbxLPSTR: + case SbxSTRING: + case SbxBYREF | SbxSTRING: + if( !p->pString ) + p->pString = new XubString; + // ImpCvtNum( (double) n, 0, *p->pString ); + pDec->getString( *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutDecimal( pDec ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + + case SbxBYREF | SbxCHAR: + if( !pDec->getChar( *p->pChar ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pChar = 0; + } + break; + case SbxBYREF | SbxBYTE: + if( !pDec->getChar( *p->pChar ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pByte = 0; + } + break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( !pDec->getShort( *p->pInteger ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pInteger = 0; + } + break; + // *p->pInteger = n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( !pDec->getUShort( *p->pUShort ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pUShort = 0; + } + break; + case SbxBYREF | SbxLONG: + if( !pDec->getLong( *p->pLong ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pLong = 0; + } + break; + case SbxBYREF | SbxULONG: + if( !pDec->getULong( *p->pULong ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pULong = 0; + } + break; + case SbxBYREF | SbxSALINT64: + { + double d; + if( !pDec->getDouble( d ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + else + *p->pnInt64 = ImpDoubleToSalInt64( d ); + break; + } + case SbxBYREF | SbxSALUINT64: + { + double d; + if( !pDec->getDouble( d ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + else + *p->puInt64 = ImpDoubleToSalUInt64( d ); + break; + } + case SbxBYREF | SbxSINGLE: + if( !pDec->getSingle( *p->pSingle ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pSingle = 0; + } + break; + // *p->pSingle = (float) n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + if( !pDec->getDouble( *p->pDouble ) ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + *p->pDouble = 0; + } + break; + case SbxBYREF | SbxULONG64: + { + double d; + pDec->getDouble( d ); + *p->pULong64 = ImpDoubleToUINT64( d ); + break; + } + case SbxBYREF | SbxLONG64: + { + double d; + pDec->getDouble( d ); + *p->pLong64 = ImpDoubleToINT64( d ); + break; + } + case SbxBYREF | SbxCURRENCY: + { + double d; + pDec->getDouble( d ); + *p->pLong64 = ImpDoubleToCurrency( d ); + break; + } + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +#else + (void)p; + (void)pDec; +#endif +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxdec.hxx b/binfilter/bf_basic/source/sbx/sbxdec.hxx new file mode 100644 index 000000000000..3fd5019c934f --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxdec.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef __SBX_SBX_DEC_HXX +#define __SBX_SBX_DEC_HXX + +#ifdef WIN32 + +#include <tools/prewin.h> +} // close extern "C" { + +#ifndef __MINGW32__ +#include <comutil.h> +#endif +#include <oleauto.h> + +extern "C" { // reopen extern "C" { +#include <tools/postwin.h> + +#endif +#endif + +#include "sbx.hxx" + +#include <com/sun/star/bridge/oleautomation/Decimal.hpp> + +namespace binfilter { + +// Decimal support +// Implementation only for windows + +class SbxDecimal +{ + friend void releaseDecimalPtr( SbxDecimal*& rpDecimal ); + +#ifdef WIN32 + DECIMAL maDec; +#endif + INT32 mnRefCount; + +public: +#ifdef WIN32 + SbxDecimal(); +#endif + SbxDecimal( const SbxDecimal& rDec ); + + ~SbxDecimal(); + + void addRef( void ) + { mnRefCount++; } + + void setChar( sal_Unicode val ); + void setByte( BYTE val ); +#ifdef WIN32 + void setShort( INT16 val ); + bool setString( String* pString ); + void setUShort( UINT16 val ); +#endif + void setLong( INT32 val ); + void setULong( UINT32 val ); + bool setSingle( float val ); + bool setDouble( double val ); + void setInt( int val ); + void setUInt( unsigned int val ); + void setDecimal( SbxDecimal* pDecimal ) + { +#ifdef WIN32 + if( pDecimal ) + maDec = pDecimal->maDec; +#else + (void)pDecimal; +#endif + } + +#ifdef WIN32 + bool getShort( INT16& rVal ); + bool getChar( sal_Unicode& rVal ); + bool getLong( INT32& rVal ); + bool getString( String& rString ); + bool getUInt( unsigned int& rVal ); + bool getULong( UINT32& rVal ); + bool getUShort( UINT16& rVal ); +#endif + bool getSingle( float& rVal ); + bool getDouble( double& rVal ); + + bool operator -= ( const SbxDecimal &r ); + bool operator += ( const SbxDecimal &r ); + bool operator /= ( const SbxDecimal &r ); + bool operator *= ( const SbxDecimal &r ); + bool neg( void ); + + bool isZero( void ); + + enum CmpResult { LT, EQ, GT }; + friend CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight ); +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxexec.cxx b/binfilter/bf_basic/source/sbx/sbxexec.cxx new file mode 100644 index 000000000000..679495e228be --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxexec.cxx @@ -0,0 +1,402 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include <vcl/svapp.hxx> +#include "sbx.hxx" + +namespace binfilter { + +class SbxSimpleCharClass +{ +public: + BOOL isAlpha( sal_Unicode c ) const + { + BOOL bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + return bRet; + } + + BOOL isDigit( sal_Unicode c ) const + { + BOOL bRet = (c >= '0' && c <= '9'); + return bRet; + } + + BOOL isAlphaNumeric( sal_Unicode c ) const + { + BOOL bRet = isDigit( c ) || isAlpha( c ); + return bRet; + } +}; + + +static SbxVariable* Element + ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, + SbxClassType, const SbxSimpleCharClass& rCharClass ); + +static const xub_Unicode* SkipWhitespace( const xub_Unicode* p ) +{ + while( *p && ( *p == ' ' || *p == '\t' ) ) + p++; + return p; +} + +// Scannen eines Symbol. Das Symbol wird in rSym eingetragen, der Returnwert +// ist die neue Scanposition. Bei Fehlern ist das Symbol leer. + +static const xub_Unicode* Symbol( const xub_Unicode* p, XubString& rSym, const SbxSimpleCharClass& rCharClass ) +{ + USHORT nLen = 0; + // Haben wir ein Sondersymbol? + if( *p == '[' ) + { + rSym = ++p; + while( *p && *p != ']' ) + p++, nLen++; + p++; + } + else + { + // Ein Symbol muss mit einem Buchstaben oder einem Underline beginnen + if( !rCharClass.isAlpha( *p ) && *p != '_' ) + SbxBase::SetError( SbxERR_SYNTAX ); + else + { + rSym = p; + // Dann darf es Buchstaben, Zahlen oder Underlines enthalten + while( *p && (rCharClass.isAlphaNumeric( *p ) || *p == '_') ) + p++, nLen++; + // BASIC-Standard-Suffixe werden ignoriert + if( *p && (*p == '%' || *p == '&' || *p == '!' || *p == '#' || *p == '$' ) ) + p++; + } + } + rSym.Erase( nLen ); + return p; +} + +// Qualifizierter Name. Element.Element.... + +static SbxVariable* QualifiedName + ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, SbxClassType t ) +{ + static SbxSimpleCharClass aCharClass; + + SbxVariableRef refVar; + const xub_Unicode* p = SkipWhitespace( *ppBuf ); + if( aCharClass.isAlpha( *p ) || *p == '_' || *p == '[' ) + { + // Element einlesen + refVar = Element( pObj, pGbl, &p, t, aCharClass ); + while( refVar.Is() && (*p == '.' || *p == '!') ) + { + // Es folgt noch ein Objektelement. Das aktuelle Element + // muss also ein SBX-Objekt sein oder liefern! + pObj = PTR_CAST(SbxObject,(SbxVariable*) refVar); + if( !pObj ) + // Dann muss es ein Objekt liefern + pObj = PTR_CAST(SbxObject,refVar->GetObject()); + refVar.Clear(); + if( !pObj ) + break; + p++; + // Und das naechste Element bitte + refVar = Element( pObj, pGbl, &p, t, aCharClass ); + } + } + else + SbxBase::SetError( SbxERR_SYNTAX ); + *ppBuf = p; + if( refVar.Is() ) + refVar->AddRef(); + return refVar; +} + +// Einlesen eines Operanden. Dies kann eine Zahl, ein String oder +// eine Funktion (mit optionalen Parametern) sein. + +static SbxVariable* Operand + ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, BOOL bVar ) +{ + static SbxSimpleCharClass aCharClass; + + SbxVariableRef refVar( new SbxVariable ); + const xub_Unicode* p = SkipWhitespace( *ppBuf ); + if( !bVar && ( aCharClass.isDigit( *p ) + || ( *p == '.' && aCharClass.isDigit( *( p+1 ) ) ) + || *p == '-' + || *p == '&' ) ) + { + // Eine Zahl kann direkt eingescant werden! + USHORT nLen; + if( !refVar->Scan( XubString( p ), &nLen ) ) + refVar.Clear(); + else + p += nLen; + } + else if( !bVar && *p == '"' ) + { + // Ein String + XubString aString; + p++; + for( ;; ) + { + // Das ist wohl ein Fehler + if( !*p ) + return NULL; + // Doppelte Quotes sind OK + if( *p == '"' ) + if( *++p != '"' ) + break; + aString += *p++; + } + refVar->PutString( aString ); + } + else + refVar = QualifiedName( pObj, pGbl, &p, SbxCLASS_DONTCARE ); + *ppBuf = p; + if( refVar.Is() ) + refVar->AddRef(); + return refVar; +} + +// Einlesen einer einfachen Term. Die Operatoren +, -, * und / +// werden unterstuetzt. + +static SbxVariable* MulDiv( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) +{ + const xub_Unicode* p = *ppBuf; + SbxVariableRef refVar( Operand( pObj, pGbl, &p, FALSE ) ); + p = SkipWhitespace( p ); + while( refVar.Is() && ( *p == '*' || *p == '/' ) ) + { + xub_Unicode cOp = *p++; + SbxVariableRef refVar2( Operand( pObj, pGbl, &p, FALSE ) ); + if( refVar2.Is() ) + { + // temporaere Variable! + SbxVariable* pVar = refVar; + pVar = new SbxVariable( *pVar ); + refVar = pVar; + if( cOp == '*' ) + *refVar *= *refVar2; + else + *refVar /= *refVar2; + } + else + { + refVar.Clear(); + break; + } + } + *ppBuf = p; + if( refVar.Is() ) + refVar->AddRef(); + return refVar; +} + +static SbxVariable* PlusMinus( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) +{ + const xub_Unicode* p = *ppBuf; + SbxVariableRef refVar( MulDiv( pObj, pGbl, &p ) ); + p = SkipWhitespace( p ); + while( refVar.Is() && ( *p == '+' || *p == '-' ) ) + { + xub_Unicode cOp = *p++; + SbxVariableRef refVar2( MulDiv( pObj, pGbl, &p ) ); + if( refVar2.Is() ) + { + // temporaere Variable! + SbxVariable* pVar = refVar; + pVar = new SbxVariable( *pVar ); + refVar = pVar; + if( cOp == '+' ) + *refVar += *refVar2; + else + *refVar -= *refVar2; + } + else + { + refVar.Clear(); + break; + } + } + *ppBuf = p; + if( refVar.Is() ) + refVar->AddRef(); + return refVar; +} + +/*?*/ // static SbxVariable* Assign( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) +/*?*/ // { +/*?*/ // const xub_Unicode* p = *ppBuf; +/*?*/ // SbxVariableRef refVar( Operand( pObj, pGbl, &p, TRUE ) ); +/*?*/ // p = SkipWhitespace( p ); +/*?*/ // if( refVar.Is() ) +/*?*/ // { +/*?*/ // if( *p == '=' ) +/*?*/ // { +/*?*/ // // Nur auf Props zuweisen! +/*?*/ // if( refVar->GetClass() != SbxCLASS_PROPERTY ) +/*?*/ // { +/*?*/ // SbxBase::SetError( SbxERR_BAD_ACTION ); +/*?*/ // refVar.Clear(); +/*?*/ // } +/*?*/ // else +/*?*/ // { +/*?*/ // p++; +/*?*/ // SbxVariableRef refVar2( PlusMinus( pObj, pGbl, &p ) ); +/*?*/ // if( refVar2.Is() ) +/*?*/ // { +/*?*/ // SbxVariable* pVar = refVar; +/*?*/ // SbxVariable* pVar2 = refVar2; +/*?*/ // *pVar = *pVar2; +/*?*/ // pVar->SetParameters( NULL ); +/*?*/ // } +/*?*/ // } +/*?*/ // } +/*?*/ // else +/*?*/ // // Einfacher Aufruf: einmal aktivieren +/*?*/ // refVar->Broadcast( SBX_HINT_DATAWANTED ); +/*?*/ // } +/*?*/ // *ppBuf = p; +/*?*/ // if( refVar.Is() ) +/*?*/ // refVar->AddRef(); +/*?*/ // return refVar; +/*?*/ // } +/*?*/ // +/*?*/ // // Einlesen eines Elements. Dies ist ein Symbol, optional gefolgt +/*?*/ // // von einer Parameterliste. Das Symbol wird im angegebenen Objekt +/*?*/ // // gesucht und die Parameterliste wird ggf. angefuegt. + +static SbxVariable* Element + ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, + SbxClassType t, const SbxSimpleCharClass& rCharClass ) +{ + XubString aSym; + const xub_Unicode* p = Symbol( *ppBuf, aSym, rCharClass ); + SbxVariableRef refVar; + if( aSym.Len() ) + { + USHORT nOld = pObj->GetFlags(); + if( pObj == pGbl ) + pObj->SetFlag( SBX_GBLSEARCH ); + refVar = pObj->Find( aSym, t ); + pObj->SetFlags( nOld ); + if( refVar.Is() ) + { + refVar->SetParameters( NULL ); + // folgen noch Parameter? + p = SkipWhitespace( p ); + if( *p == '(' ) + { + p++; + SbxArrayRef refPar = new SbxArray; + USHORT nArg = 0; + // Wird sind mal relaxed und akzeptieren auch + // das Zeilen- oder Komandoende als Begrenzer + // Parameter immer global suchen! + while( *p && *p != ')' && *p != ']' ) + { + SbxVariableRef refArg = PlusMinus( pGbl, pGbl, &p ); + if( !refArg ) + { + // Fehler beim Parsing + refVar.Clear(); break; + } + else + { + // Man kopiere den Parameter, damit + // man den aktuellen Zustand hat (loest auch + // den Aufruf per Zugriff aus) + SbxVariable* pArg = refArg; + refPar->Put( new SbxVariable( *pArg ), ++nArg ); + } + p = SkipWhitespace( p ); + if( *p == ',' ) + p++; + } + if( *p == ')' ) + p++; + if( refVar.Is() ) + refVar->SetParameters( refPar ); + } + } + else + SbxBase::SetError( SbxERR_NO_METHOD ); + } + *ppBuf = p; + if( refVar.Is() ) + refVar->AddRef(); + return refVar; +} + +/*?*/ // // Hauptroutine +/*?*/ // +/*?*/ // SbxVariable* SbxObject::Execute( const XubString& rTxt ) +/*?*/ // { +/*?*/ // SbxVariable* pVar = NULL; +/*?*/ // const xub_Unicode* p = rTxt.GetBuffer(); +/*?*/ // for( ;; ) +/*?*/ // { +/*?*/ // p = SkipWhitespace( p ); +/*?*/ // if( !*p ) +/*?*/ // break; +/*?*/ // if( *p++ != '[' ) +/*?*/ // { +/*?*/ // SetError( SbxERR_SYNTAX ); break; +/*?*/ // } +/*?*/ // pVar = Assign( this, this, &p ); +/*?*/ // if( !pVar ) +/*?*/ // break; +/*?*/ // p = SkipWhitespace( p ); +/*?*/ // if( *p++ != ']' ) +/*?*/ // { +/*?*/ // SetError( SbxERR_SYNTAX ); break; +/*?*/ // } +/*?*/ // } +/*?*/ // return pVar; +/*?*/ // } +/*?*/ // +SbxVariable* SbxObject::FindQualified( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pVar = NULL; + const xub_Unicode* p = rName.GetBuffer(); + p = SkipWhitespace( p ); + if( !*p ) + return NULL;; + pVar = QualifiedName( this, this, &p, t ); + p = SkipWhitespace( p ); + if( *p ) + SetError( SbxERR_SYNTAX ); + return pVar; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxint.cxx b/binfilter/bf_basic/source/sbx/sbxint.cxx new file mode 100644 index 000000000000..f358bd4b0f2b --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxint.cxx @@ -0,0 +1,970 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +double ImpRound( double d ) +{ + return d + ( d < 0 ? -0.5 : 0.5 ); +} + +INT16 ImpGetInteger( const SbxValues* p ) +{ + SbxValues aTmp; + INT16 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + if( p->nUShort > (USHORT) SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else + nRes = (INT16) p->nUShort; + break; + case SbxLONG: + if( p->nLong > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else if( p->nLong < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT; + } + else + nRes = (INT16) p->nLong; + break; + case SbxULONG: + if( p->nULong > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else + nRes = (INT16) p->nULong; + break; + case SbxSINGLE: + if( p->nSingle > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else if( p->nSingle < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT; + } + else + nRes = (INT16) ImpRound( p->nSingle ); + break; + case SbxSALINT64: + if( p->nInt64 > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else if( p->nInt64 < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT; + } + else + nRes = (INT16) p->nInt64; + break; + case SbxSALUINT64: + if( p->uInt64 > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else + nRes = (INT16) p->uInt64; + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else if( p->eType == SbxDECIMAL ) + { + dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + } + else + dVal = p->nDouble; + + if( dVal > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else if( dVal < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT; + } + else + nRes = (INT16) ImpRound( dVal ); + break; + } + case SbxLPSTR: + case SbxSTRING: + case SbxBYREF | SbxSTRING: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT; + } + else if( d < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT; + } + else + nRes = (INT16) ImpRound( d ); + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetInteger(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + + // ab hier muss getestet werden + case SbxBYREF | SbxLONG: + aTmp.nLong = *p->pLong; goto ref; + case SbxBYREF | SbxULONG: + aTmp.nULong = *p->pULong; goto ref; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + aTmp.nUShort = *p->pUShort; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutInteger( SbxValues* p, INT16 n ) +{ + SbxValues aTmp; +start: + switch( +p->eType ) + { + // hier muss getestet werden + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxSALUINT64: + aTmp.puInt64 = &p->uInt64; goto direct; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // ab hier nicht mehr + case SbxINTEGER: + case SbxBOOL: + p->nInteger = n; break; + case SbxLONG: + p->nLong = n; break; + case SbxSINGLE: + p->nSingle = n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxULONG64: + p->nULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxLONG64: + p->nLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxCURRENCY: + p->nLong64 = ImpDoubleToCurrency( (double)n ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setInt( n ); + break; + + case SbxLPSTR: + case SbxSTRING: + case SbxBYREF | SbxSTRING: + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 0, *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutInteger( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR; + } + *p->pChar = (char) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + *p->pInteger = n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); *p->puInt64 = 0; + } + else + *p->puInt64 = n; + break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = (float) n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxULONG64: + *p->pULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxBYREF | SbxLONG64: + *p->pLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxBYREF | SbxCURRENCY: + *p->pLong64 = ImpDoubleToCurrency( (double)n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + + +// sal_Int64 / hyper + +sal_Int64 ImpDoubleToSalInt64( double d ) +{ + sal_Int64 nRes; + if( d > SbxMAXSALINT64 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALINT64; + } + else if( d < SbxMINSALINT64 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINSALINT64; + } + else + nRes = (sal_Int64) ImpRound( d ); + return nRes; +} + +sal_uInt64 ImpDoubleToSalUInt64( double d ) +{ + sal_uInt64 nRes; + if( d > SbxMAXSALUINT64 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALUINT64; + } + else if( d < 0.0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (sal_uInt64) ImpRound( d ); + return nRes; +} + +double ImpSalUInt64ToDouble( sal_uInt64 n ) +{ + double d = 0.0; + if( n > SbxMAXSALINT64 ) + SbxBase::SetError( SbxERR_CONVERSION ); + else + d = (double)(sal_Int64) n; + return d; +} + + +sal_Int64 ImpGetInt64( const SbxValues* p ) +{ + SbxValues aTmp; + sal_Int64 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; break; + case SbxLONG: + nRes = p->nLong; break; + case SbxULONG: + nRes = (sal_Int64) p->nULong; break; + case SbxSINGLE: + nRes = ImpDoubleToSalInt64( (double)p->nSingle ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else + dVal = p->nDouble; + + nRes = ImpDoubleToSalInt64( dVal ); + break; + } + case SbxSALINT64: + nRes = p->nInt64; break; + case SbxSALUINT64: + if( p->uInt64 > SbxMAXSALINT64 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALINT64; + } + else + nRes = (sal_Int64) p->uInt64; + break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + ::rtl::OUString aOUStr( *p->pString ); + ::rtl::OString aOStr = ::rtl::OUStringToOString + ( aOUStr, RTL_TEXTENCODING_ASCII_US ); + nRes = aOStr.toInt64(); + if( nRes == 0 ) + { + // Check if really 0 or invalid conversion + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else + nRes = ImpDoubleToSalInt64( d ); + } + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetInt64(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + case SbxBYREF | SbxLONG: + nRes = *p->pLong; break; + case SbxBYREF | SbxULONG: + nRes = *p->pULong; break; + case SbxBYREF | SbxSALINT64: + nRes = *p->pnInt64; break; + + // from here the values has to be checked + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + aTmp.nUShort = *p->pUShort; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutInt64( SbxValues* p, sal_Int64 n ) +{ + SbxValues aTmp; + +start: + switch( +p->eType ) + { + // Check neccessary + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxULONG64: + aTmp.pULong64 = &p->nULong64; goto direct; + case SbxLONG64: + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxLONG: + aTmp.pnInt64 = &p->nInt64; goto direct; + case SbxSALUINT64: + aTmp.puInt64 = &p->uInt64; goto direct; + + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // Check not neccessary + case SbxSALINT64: + p->nInt64 = n; break; + case SbxSINGLE: + p->nSingle = (float) n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = (double) n; break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + { + if( !p->pString ) + p->pString = new XubString; + + ::rtl::OString aOStr = ::rtl::OString::valueOf( n ); + ::rtl::OUString aOUStr = ::rtl::OStringToOUString + ( aOStr, RTL_TEXTENCODING_ASCII_US ); + (*p->pString) = aOUStr; + break; + } + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutInt64( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + else if( n < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + else if( n < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + if( n > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG; + } + else if( n < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG; + } + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + if( n > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = (float) n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxCURRENCY: + if( n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = (sal_Int64) SbxMAXCURR; + } + else if( n < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = (sal_Int64) SbxMINCURR; + } + *p->pLong64 = ImpDoubleToCurrency( (double)n ); break; + + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->puInt64 = (sal_Int64) n; break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +sal_uInt64 ImpGetUInt64( const SbxValues* p ) +{ + SbxValues aTmp; + sal_uInt64 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; break; + case SbxLONG: + nRes = p->nLong; break; + case SbxULONG: + nRes = (sal_uInt64) p->nULong; break; + case SbxSINGLE: + nRes = ImpDoubleToSalUInt64( (double)p->nSingle ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else + dVal = p->nDouble; + + nRes = ImpDoubleToSalUInt64( dVal ); + break; + } + case SbxSALINT64: + if( p->nInt64 < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (sal_uInt64) p->nInt64; + case SbxSALUINT64: + nRes = p->uInt64; break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + ::rtl::OUString aOUStr( *p->pString ); + ::rtl::OString aOStr = ::rtl::OUStringToOString + ( aOUStr, RTL_TEXTENCODING_ASCII_US ); + sal_Int64 n64 = aOStr.toInt64(); + if( n64 == 0 ) + { + // Check if really 0 or invalid conversion + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXSALUINT64 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALUINT64; + } + else if( d < 0.0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (sal_uInt64) ImpRound( d ); + } + else if( n64 < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + { + nRes = n64; + } + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetUInt64(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + case SbxBYREF | SbxLONG: + nRes = *p->pLong; break; + case SbxBYREF | SbxULONG: + nRes = *p->pULong; break; + case SbxBYREF | SbxSALUINT64: + nRes = *p->puInt64; break; + + // from here the values has to be checked + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + aTmp.nUShort = *p->pUShort; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutUInt64( SbxValues* p, sal_uInt64 n ) +{ + SbxValues aTmp; + +start: + switch( +p->eType ) + { + // Check neccessary + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxULONG64: + aTmp.pULong64 = &p->nULong64; goto direct; + case SbxLONG64: + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxLONG: + aTmp.pnInt64 = &p->nInt64; goto direct; + case SbxSALINT64: + aTmp.pnInt64 = &p->nInt64; goto direct; + case SbxSINGLE: + aTmp.pSingle = &p->nSingle; goto direct; + case SbxDATE: + case SbxDOUBLE: + aTmp.pDouble = &p->nDouble; goto direct; + + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // Check not neccessary + case SbxSALUINT64: + p->uInt64 = n; break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + if( n > SbxMAXSALINT64 ) + SbxBase::SetError( SbxERR_CONVERSION ); + else + { + ::rtl::OString aOStr = ::rtl::OString::valueOf( (sal_Int64)n ); + ::rtl::OUString aOUStr = ::rtl::OStringToOUString + ( aOStr, RTL_TEXTENCODING_ASCII_US ); + (*p->pString) = aOUStr; + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutUInt64( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + if( n > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG; + } + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + if( n > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG; + } + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSINGLE: + *p->pDouble = (float)ImpSalUInt64ToDouble( n ); break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = ImpSalUInt64ToDouble( n ); break; + case SbxBYREF | SbxCURRENCY: + if( n > SbxMAXSALINT64 || (sal_Int64)n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = (sal_Int64) SbxMAXCURR; + } + *p->pLong64 = ImpDoubleToCurrency( (double)(sal_Int64) n ); break; + + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = n; break; + case SbxBYREF | SbxSALINT64: + if( n > SbxMAXSALINT64 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pnInt64 = (sal_Int64) n; break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxlng.cxx b/binfilter/bf_basic/source/sbx/sbxlng.cxx new file mode 100644 index 000000000000..566eb1e68e70 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxlng.cxx @@ -0,0 +1,345 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +INT32 ImpGetLong( const SbxValues* p ) +{ + SbxValues aTmp; + INT32 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; break; + case SbxLONG: + nRes = p->nLong; break; + case SbxULONG: + if( p->nULong > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG; + } + else + nRes = (INT32) p->nULong; + break; + case SbxSINGLE: + if( p->nSingle > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG; + } + else if( p->nSingle < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINLNG; + } + else + nRes = (INT32) ImpRound( p->nSingle ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxSALINT64: + case SbxSALUINT64: + case SbxCURRENCY: + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else if( p->eType == SbxSALINT64 ) + dVal = static_cast< double >(p->nInt64); + else if( p->eType == SbxSALUINT64 ) + dVal = ImpSalUInt64ToDouble( p->uInt64 ); + else if( p->eType == SbxDECIMAL ) + { + dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + } + else + dVal = p->nDouble; + + if( dVal > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG; + } + else if( dVal < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINLNG; + } + else + nRes = (INT32) ImpRound( dVal ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG; + } + else if( d < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINLNG; + } + else + nRes = (INT32) ImpRound( d ); + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetLong(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + case SbxBYREF | SbxLONG: + nRes = *p->pLong; break; + + // ab hier muss getestet werden + case SbxBYREF | SbxULONG: + aTmp.nULong = *p->pULong; goto ref; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + aTmp.nUShort = *p->pUShort; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutLong( SbxValues* p, INT32 n ) +{ + SbxValues aTmp; + +start: + switch( +p->eType ) + { + // Ab hier muss getestet werden + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxULONG64: + aTmp.pULong64 = &p->nULong64; goto direct; + case SbxLONG64: + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxSALUINT64: + aTmp.puInt64 = &p->uInt64; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // ab hier nicht mehr + case SbxLONG: + p->nLong = n; break; + case SbxSINGLE: + p->nSingle = (float) n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setLong( n ); + break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 0, *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutLong( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + else if( n < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + else if( n < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + *p->pLong = n; break; + case SbxBYREF | SbxULONG: + if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pULong = (UINT32) n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); *p->puInt64 = 0; + } + else + *p->puInt64 = n; + break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = (float) n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxCURRENCY: + double d; + if( n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMAXCURR; + } + else if( n < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMINCURR; + } + else + { + d = n; + } + *p->pLong64 = ImpDoubleToCurrency( d ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxobj.cxx b/binfilter/bf_basic/source/sbx/sbxobj.cxx new file mode 100644 index 000000000000..45e6e34417d1 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxobj.cxx @@ -0,0 +1,926 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/stream.hxx> +#include <vcl/sound.hxx> +#include "sbx.hxx" +#include "sbxbase.hxx" +#include "sbxres.hxx" + +#include <bf_svtools/brdcst.hxx> + +namespace binfilter { + +TYPEINIT1(SbxMethod,SbxVariable) +TYPEINIT1(SbxProperty,SbxVariable) +TYPEINIT2(SbxObject,SbxVariable,SfxListener) + +static const char* pNameProp; // Name-Property +static const char* pParentProp; // Parent-Property + +static USHORT nNameHash = 0, nParentHash = 0; + +///////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////// + +SbxObject::SbxObject( const XubString& rClass ) + : SbxVariable( SbxOBJECT ), aClassName( rClass ) +{ + aData.pObj = this; + if( !nNameHash ) + { + pNameProp = GetSbxRes( STRING_NAMEPROP ); + pParentProp = GetSbxRes( STRING_PARENTPROP ); + nNameHash = MakeHashCode( String::CreateFromAscii( pNameProp ) ); + nParentHash = MakeHashCode( String::CreateFromAscii( pParentProp ) ); + } + SbxObject::Clear(); + SbxObject::SetName( rClass ); +} + +SbxObject::SbxObject( const SbxObject& rObj ) + : SvRefBase( rObj ), SbxVariable( rObj.GetType() ), + SfxListener( rObj ) +{ + *this = rObj; +} + +SbxObject& SbxObject::operator=( const SbxObject& r ) +{ + if( &r != this ) + { + SbxVariable::operator=( r ); + aClassName = r.aClassName; + pMethods = new SbxArray; + pProps = new SbxArray; + pObjs = new SbxArray( SbxOBJECT ); + // Die Arrays werden kopiert, die Inhalte uebernommen + *pMethods = *r.pMethods; + *pProps = *r.pProps; + *pObjs = *r.pObjs; + // Da die Variablen uebernommen wurden, ist dies OK + pDfltProp = r.pDfltProp; + SetName( r.GetName() ); + SetFlags( r.GetFlags() ); + SetModified( TRUE ); + } + return *this; +} + +static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p ) +{ + for( USHORT i = 0; i < p->Count(); i++ ) + { + SbxVariableRef& rRef = p->GetRef( i ); + if( rRef->IsBroadcaster() ) + pObj->EndListening( rRef->GetBroadcaster(), TRUE ); + // Hat das Element mehr als eine Referenz und noch einen Listener? + if( rRef->GetRefCount() > 1 ) + { + rRef->SetParent( NULL ); + DBG_ASSERT( !rRef->IsBroadcaster() || rRef->GetBroadcaster().GetListenerCount(), "Object element with dangling parent" ); + } + } +} + +SbxObject::~SbxObject() +{ + CheckParentsOnDelete( this, pProps ); + CheckParentsOnDelete( this, pMethods ); + CheckParentsOnDelete( this, pObjs ); +} + +SbxDataType SbxObject::GetType() const +{ + return SbxOBJECT; +} + +SbxClassType SbxObject::GetClass() const +{ + return SbxCLASS_OBJECT; +} + +void SbxObject::Clear() +{ + pMethods = new SbxArray; + pProps = new SbxArray; + pObjs = new SbxArray( SbxOBJECT ); + SbxVariable* p; + p = Make( String::CreateFromAscii( pNameProp ), SbxCLASS_PROPERTY, SbxSTRING ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pParentProp ), SbxCLASS_PROPERTY, SbxOBJECT ); + p->ResetFlag( SBX_WRITE ); + p->SetFlag( SBX_DONTSTORE ); + pDfltProp = NULL; + SetModified( FALSE ); +} + +void SbxObject::SFX_NOTIFY( SfxBroadcaster&, const TypeId&, + const SfxHint& rHint, const TypeId& ) +{ + const SbxHint* p = PTR_CAST(SbxHint,&rHint); + if( p ) + { + ULONG nId = p->GetId(); + BOOL bRead = BOOL( nId == SBX_HINT_DATAWANTED ); + BOOL bWrite = BOOL( nId == SBX_HINT_DATACHANGED ); + SbxVariable* pVar = p->GetVar(); + if( bRead || bWrite ) + { + XubString aVarName( pVar->GetName() ); + USHORT nHash_ = MakeHashCode( aVarName ); + if( nHash_ == nNameHash + && aVarName.EqualsIgnoreCaseAscii( pNameProp ) ) + { + if( bRead ) + pVar->PutString( GetName() ); + else + SetName( pVar->GetString() ); + } + else if( nHash_ == nParentHash + && aVarName.EqualsIgnoreCaseAscii( pParentProp ) ) + { + SbxObject* p_ = GetParent(); + if( !p_ ) + p_ = this; + pVar->PutObject( p_ ); + } + } + } +} + +BOOL SbxObject::IsClass( const XubString& rName ) const +{ + return BOOL( aClassName.EqualsIgnoreCaseAscii( rName ) ); +} + +SbxVariable* SbxObject::FindUserData( UINT32 nData ) +{ + if( !GetAll( SbxCLASS_DONTCARE ) ) + return NULL; + + SbxVariable* pRes = pMethods->FindUserData( nData ); + if( !pRes ) + pRes = pProps->FindUserData( nData ); + if( !pRes ) + pRes = pObjs->FindUserData( nData ); + // Search in den Parents? + if( !pRes && IsSet( SBX_GBLSEARCH ) ) + { + SbxObject* pCur = this; + while( !pRes && pCur->pParent ) + { + // Ich selbst bin schon durchsucht worden! + USHORT nOwn = pCur->GetFlags(); + pCur->ResetFlag( SBX_EXTSEARCH ); + // Ich suche bereits global! + USHORT nPar = pCur->pParent->GetFlags(); + pCur->pParent->ResetFlag( SBX_GBLSEARCH ); + pRes = pCur->pParent->FindUserData( nData ); + pCur->SetFlags( nOwn ); + pCur->pParent->SetFlags( nPar ); + pCur = pCur->pParent; + } + } + return pRes; +} + +SbxVariable* SbxObject::Find( const XubString& rName, SbxClassType t ) +{ +#ifdef DBG_UTIL + static USHORT nLvl = 0; + static const char* pCls[] = + { "DontCare","Array","Value","Variable","Method","Property","Object" }; + ByteString aNameStr1( (const UniString&)rName, RTL_TEXTENCODING_ASCII_US ); + ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US ); + DbgOutf( "SBX: Search %.*s %s %s in %s", + nLvl++, " ", + ( t >= SbxCLASS_DONTCARE && t <= SbxCLASS_OBJECT ) + ? pCls[ t-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() ); +#endif + + if( !GetAll( t ) ) + return NULL; + SbxVariable* pRes = NULL; + pObjs->SetFlag( SBX_EXTSEARCH ); + if( t == SbxCLASS_DONTCARE ) + { + pRes = pMethods->Find( rName, SbxCLASS_METHOD ); + if( !pRes ) + pRes = pProps->Find( rName, SbxCLASS_PROPERTY ); + if( !pRes ) + pRes = pObjs->Find( rName, t ); + } + else + { + SbxArray* pArray = NULL; + switch( t ) + { + case SbxCLASS_VARIABLE: + case SbxCLASS_PROPERTY: pArray = pProps; break; + case SbxCLASS_METHOD: pArray = pMethods; break; + case SbxCLASS_OBJECT: pArray = pObjs; break; + default: + DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); + } + if( pArray ) + pRes = pArray->Find( rName, t ); + } + // Extended Search im Objekt-Array? + // Fuer Objekte und DontCare ist das Objektarray bereits + // durchsucht worden + if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) ) + pRes = pObjs->Find( rName, t ); + // Search in den Parents? + if( !pRes && IsSet( SBX_GBLSEARCH ) ) + { + SbxObject* pCur = this; + while( !pRes && pCur->pParent ) + { + // Ich selbst bin schon durchsucht worden! + USHORT nOwn = pCur->GetFlags(); + pCur->ResetFlag( SBX_EXTSEARCH ); + // Ich suche bereits global! + USHORT nPar = pCur->pParent->GetFlags(); + pCur->pParent->ResetFlag( SBX_GBLSEARCH ); + pRes = pCur->pParent->Find( rName, t ); + pCur->SetFlags( nOwn ); + pCur->pParent->SetFlags( nPar ); + pCur = pCur->pParent; + } + } +#ifdef DBG_UTIL + nLvl--; + if( pRes ) + { + ByteString aNameStr3( (const UniString&)rName, RTL_TEXTENCODING_ASCII_US ); + ByteString aNameStr4( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US ); + DbgOutf( "SBX: Found %.*s %s in %s", + nLvl, " ", aNameStr3.GetBuffer(), aNameStr4.GetBuffer() ); + } +#endif + return pRes; +} + +// Kurzform: Die Parent-Kette wird durchsucht +// Das ganze rekursiv, da Call() ueberladen sein kann +// Qualified Names sind zugelassen + +BOOL SbxObject::Call( const XubString& rName, SbxArray* pParam ) +{ + SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE); + if( pMeth && pMeth->ISA(SbxMethod) ) + { + // FindQualified() koennte schon zugeschlagen haben! + if( pParam ) + pMeth->SetParameters( pParam ); + pMeth->Broadcast( SBX_HINT_DATAWANTED ); + pMeth->SetParameters( NULL ); + return TRUE; + } + SetError( SbxERR_NO_METHOD ); + return FALSE; +} + +SbxProperty* SbxObject::GetDfltProperty() +{ + if ( !pDfltProp && aDfltPropName.Len() ) + { + pDfltProp = (SbxProperty*) Find( aDfltPropName, SbxCLASS_PROPERTY ); + if( !pDfltProp ) + pDfltProp = (SbxProperty*) Make( aDfltPropName, SbxCLASS_PROPERTY, SbxVARIANT ); + } + return pDfltProp; +} + +// Suchen einer bereits vorhandenen Variablen. Falls sie gefunden wurde, +// wird der Index gesetzt, sonst wird der Count des Arrays geliefert. +// In jedem Fall wird das korrekte Array geliefert. + +SbxArray* SbxObject::FindVar( SbxVariable* pVar, USHORT& nArrayIdx ) +{ + SbxArray* pArray = NULL; + if( pVar ) switch( pVar->GetClass() ) + { + case SbxCLASS_VARIABLE: + case SbxCLASS_PROPERTY: pArray = pProps; break; + case SbxCLASS_METHOD: pArray = pMethods; break; + case SbxCLASS_OBJECT: pArray = pObjs; break; + default: + DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); + } + if( pArray ) + { + nArrayIdx = pArray->Count(); + // ist die Variable per Name vorhanden? + pArray->ResetFlag( SBX_EXTSEARCH ); + SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() ); + if( pOld ) + for( USHORT i = 0; i < pArray->Count(); i++ ) + { + SbxVariableRef& rRef = pArray->GetRef( i ); + if( (SbxVariable*) rRef == pOld ) + { + nArrayIdx = i; break; + } + } + } + return pArray; +} + +// Falls ein neues Objekt eingerichtet wird, wird es, falls es bereits +// eines mit diesem Namen gibt, indiziert. + +SbxVariable* SbxObject::Make( const XubString& rName, SbxClassType ct, SbxDataType dt ) +{ + // Ist das Objekt bereits vorhanden? + SbxArray* pArray = NULL; + switch( ct ) + { + case SbxCLASS_VARIABLE: + case SbxCLASS_PROPERTY: pArray = pProps; break; + case SbxCLASS_METHOD: pArray = pMethods; break; + case SbxCLASS_OBJECT: pArray = pObjs; break; + default: + DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); + } + if( !pArray ) + return NULL; + // Collections duerfen gleichnamige Objekte enthalten + if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) ) + { + SbxVariable* pRes = pArray->Find( rName, ct ); + if( pRes ) + { +/* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus +#ifdef DBG_UTIL + if( pRes->GetHashCode() != nNameHash + && pRes->GetHashCode() != nParentHash ) + { + XubString aMsg( "SBX-Element \"" ); + aMsg += pRes->GetName(); + aMsg += "\"\n in Objekt \""; + aMsg += GetName(); + aMsg += "\" bereits vorhanden"; + DbgError( (const char*)aMsg.GetStr() ); + } +#endif +*/ + return pRes; + } + } + SbxVariable* pVar = NULL; + switch( ct ) + { + case SbxCLASS_VARIABLE: + case SbxCLASS_PROPERTY: + pVar = new SbxProperty( rName, dt ); + break; + case SbxCLASS_METHOD: + pVar = new SbxMethod( rName, dt ); + break; + case SbxCLASS_OBJECT: + pVar = CreateObject( rName ); + break; + default: break; + } + pVar->SetParent( this ); + pArray->Put( pVar, pArray->Count() ); + SetModified( TRUE ); + // Das Objekt lauscht immer + StartListening( pVar->GetBroadcaster(), TRUE ); + Broadcast( SBX_HINT_OBJECTCHANGED ); + return pVar; +} + +SbxObject* SbxObject::MakeObject( const XubString& rName, const XubString& rClass ) +{ + // Ist das Objekt bereits vorhanden? + if( !ISA(SbxCollection) ) + { + SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT ); + if( pRes ) + { +/* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus +#ifdef DBG_UTIL + if( pRes->GetHashCode() != nNameHash + && pRes->GetHashCode() != nParentHash ) + { + XubString aMsg( "SBX-Objekt \"" ); + aMsg += pRes->GetName(); + aMsg += "\"\n in Objekt \""; + aMsg += GetName(); + aMsg += "\" bereits vorhanden"; + DbgError( (const char*)aMsg.GetStr() ); + } +#endif +*/ + return PTR_CAST(SbxObject,pRes); + } + } + SbxObject* pVar = CreateObject( rClass ); + if( pVar ) + { + pVar->SetName( rName ); + pVar->SetParent( this ); + pObjs->Put( pVar, pObjs->Count() ); + SetModified( TRUE ); + // Das Objekt lauscht immer + StartListening( pVar->GetBroadcaster(), TRUE ); + Broadcast( SBX_HINT_OBJECTCHANGED ); + } + return pVar; +} + +void SbxObject::Insert( SbxVariable* pVar ) +{ + USHORT nIdx; + SbxArray* pArray = FindVar( pVar, nIdx ); + if( pArray ) + { + // Hinein damit. Man sollte allerdings auf die Pointer aufpassen! + if( nIdx < pArray->Count() ) + { + // dann gibt es dieses Element bereits + // Bei Collections duerfen gleichnamige Objekte hinein + if( pArray == pObjs && ISA(SbxCollection) ) + nIdx = pArray->Count(); + else + { + SbxVariable* pOld = pArray->Get( nIdx ); + // schon drin: ueberschreiben + if( pOld == pVar ) + return; + +/* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus +#ifdef DBG_UTIL + if( pOld->GetHashCode() != nNameHash + && pOld->GetHashCode() != nParentHash ) + { + XubString aMsg( "SBX-Element \"" ); + aMsg += pVar->GetName(); + aMsg += "\"\n in Objekt \""; + aMsg += GetName(); + aMsg += "\" bereits vorhanden"; + DbgError( (const char*)aMsg.GetStr() ); + } +#endif +*/ + EndListening( pOld->GetBroadcaster(), TRUE ); + if( pVar->GetClass() == SbxCLASS_PROPERTY ) + { + if( pOld == pDfltProp ) + pDfltProp = (SbxProperty*) pVar; + } + } + } + StartListening( pVar->GetBroadcaster(), TRUE ); + pArray->Put( pVar, nIdx ); + if( pVar->GetParent() != this ) + pVar->SetParent( this ); + SetModified( TRUE ); + Broadcast( SBX_HINT_OBJECTCHANGED ); +#ifdef DBG_UTIL + static const char* pCls[] = + { "DontCare","Array","Value","Variable","Method","Property","Object" }; + XubString aVarName( pVar->GetName() ); + if ( !aVarName.Len() && pVar->ISA(SbxObject) ) + aVarName = PTR_CAST(SbxObject,pVar)->GetClassName(); + ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US ); + ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US ); + DbgOutf( "SBX: Insert %s %s in %s", + ( pVar->GetClass() >= SbxCLASS_DONTCARE && + pVar->GetClass() <= SbxCLASS_OBJECT ) + ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() ); +#endif + } +} + +// AB 23.4.1997, Optimierung, Einfuegen ohne Ueberpruefung auf doppelte +// Eintraege und ohne Broadcasts, wird nur in SO2/auto.cxx genutzt +void SbxObject::QuickInsert( SbxVariable* pVar ) +{ + SbxArray* pArray = NULL; + if( pVar ) + { + switch( pVar->GetClass() ) + { + case SbxCLASS_VARIABLE: + case SbxCLASS_PROPERTY: pArray = pProps; break; + case SbxCLASS_METHOD: pArray = pMethods; break; + case SbxCLASS_OBJECT: pArray = pObjs; break; + default: + DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); + } + } + if( pArray ) + { + StartListening( pVar->GetBroadcaster(), TRUE ); + pArray->Put( pVar, pArray->Count() ); + if( pVar->GetParent() != this ) + pVar->SetParent( this ); + SetModified( TRUE ); +#ifdef DBG_UTIL + static const char* pCls[] = + { "DontCare","Array","Value","Variable","Method","Property","Object" }; + XubString aVarName( pVar->GetName() ); + if ( !aVarName.Len() && pVar->ISA(SbxObject) ) + aVarName = PTR_CAST(SbxObject,pVar)->GetClassName(); + ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US ); + ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US ); + DbgOutf( "SBX: Insert %s %s in %s", + ( pVar->GetClass() >= SbxCLASS_DONTCARE && + pVar->GetClass() <= SbxCLASS_OBJECT ) + ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() ); +#endif + } +} + +void SbxObject::Remove( const XubString& rName, SbxClassType t ) +{ + Remove( SbxObject::Find( rName, t ) ); +} + +void SbxObject::Remove( SbxVariable* pVar ) +{ + USHORT nIdx; + SbxArray* pArray = FindVar( pVar, nIdx ); + if( pArray && nIdx < pArray->Count() ) + { +#ifdef DBG_UTIL + XubString aVarName( pVar->GetName() ); + if ( !aVarName.Len() && pVar->ISA(SbxObject) ) + aVarName = PTR_CAST(SbxObject,pVar)->GetClassName(); + ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US ); + ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US ); +#endif + SbxVariableRef pVar_ = pArray->Get( nIdx ); + if( pVar_->IsBroadcaster() ) + EndListening( pVar_->GetBroadcaster(), TRUE ); + if( (SbxVariable*) pVar_ == pDfltProp ) + pDfltProp = NULL; + pArray->Remove( nIdx ); + if( pVar_->GetParent() == this ) + pVar_->SetParent( NULL ); + SetModified( TRUE ); + Broadcast( SBX_HINT_OBJECTCHANGED ); + } +} + +static BOOL LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray ) +{ + SbxArrayRef p = (SbxArray*) SbxBase::Load( rStrm ); + if( !p.Is() ) + return FALSE; + for( USHORT i = 0; i < p->Count(); i++ ) + { + SbxVariableRef& r = p->GetRef( i ); + SbxVariable* pVar = r; + if( pVar ) + { + pVar->SetParent( pThis ); + pThis->StartListening( pVar->GetBroadcaster(), TRUE ); + } + } + pArray->Merge( p ); + return TRUE; +} + +// Der Load eines Objekts ist additiv! + +BOOL SbxObject::LoadData( SvStream& rStrm, USHORT nVer ) +{ + // Hilfe fuer das Einlesen alter Objekte: einfach TRUE zurueck, + // LoadPrivateData() muss Default-Zustand herstellen + if( !nVer ) + return TRUE; + + pDfltProp = NULL; + if( !SbxVariable::LoadData( rStrm, nVer ) ) + return FALSE; + // Wenn kein fremdes Objekt enthalten ist, uns selbst eintragen + if( aData.eType == SbxOBJECT && !aData.pObj ) + aData.pObj = this; + sal_uInt32 nSize; + XubString aDfltProp; + rStrm.ReadByteString( aClassName, RTL_TEXTENCODING_ASCII_US ); + rStrm.ReadByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US ); + ULONG nPos = rStrm.Tell(); + rStrm >> nSize; + if( !LoadPrivateData( rStrm, nVer ) ) + return FALSE; + ULONG nNewPos = rStrm.Tell(); + nPos += nSize; + DBG_ASSERT( nPos >= nNewPos, "SBX: Zu viele Daten eingelesen" ); + if( nPos != nNewPos ) + rStrm.Seek( nPos ); + if( !LoadArray( rStrm, this, pMethods ) + || !LoadArray( rStrm, this, pProps ) + || !LoadArray( rStrm, this, pObjs ) ) + return FALSE; + // Properties setzen + if( aDfltProp.Len() ) + pDfltProp = (SbxProperty*) pProps->Find( aDfltProp, SbxCLASS_PROPERTY ); + SetModified( FALSE ); + return TRUE; +} + +BOOL SbxObject::StoreData( SvStream& rStrm ) const +{ + if( !SbxVariable::StoreData( rStrm ) ) + return FALSE; + XubString aDfltProp; + if( pDfltProp ) + aDfltProp = pDfltProp->GetName(); + rStrm.WriteByteString( aClassName, RTL_TEXTENCODING_ASCII_US ); + rStrm.WriteByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US ); + ULONG nPos = rStrm.Tell(); + rStrm << (UINT32) 0L; + if( !StorePrivateData( rStrm ) ) + return FALSE; + ULONG nNew = rStrm.Tell(); + rStrm.Seek( nPos ); + rStrm << (UINT32) ( nNew - nPos ); + rStrm.Seek( nNew ); + if( !pMethods->Store( rStrm ) ) + return FALSE; + if( !pProps->Store( rStrm ) ) + return FALSE; + if( !pObjs->Store( rStrm ) ) + return FALSE; + ((SbxObject*) this)->SetModified( FALSE ); + return TRUE; +} + +XubString SbxObject::GenerateSource( const XubString &rLinePrefix, + const SbxObject* ) +{ + // Properties in einem String einsammeln + XubString aSource; + SbxArrayRef xProps( GetProperties() ); + FASTBOOL bLineFeed = FALSE; + for ( USHORT nProp = 0; nProp < xProps->Count(); ++nProp ) + { + SbxPropertyRef xProp = (SbxProperty*) xProps->Get(nProp); + XubString aPropName( xProp->GetName() ); + if ( xProp->CanWrite() + && !( xProp->GetHashCode() == nNameHash + && aPropName.EqualsIgnoreCaseAscii( pNameProp ) ) ) + { + // ausser vor dem ersten Property immer einen Umbruch einfuegen + if ( bLineFeed ) + aSource.AppendAscii( "\n" ); + else + bLineFeed = TRUE; + + aSource += rLinePrefix; + aSource += '.'; + aSource += aPropName; + aSource.AppendAscii( " = " ); + + // den Property-Wert textuell darstellen + switch ( xProp->GetType() ) + { + case SbxEMPTY: + case SbxNULL: + // kein Wert + break; + + case SbxSTRING: + { + // Strings in Anf"uhrungszeichen + aSource.AppendAscii( "\"" ); + aSource += xProp->GetString(); + aSource.AppendAscii( "\"" ); + break; + } + + default: + { + // sonstiges wie z.B. Zahlen direkt + aSource += xProp->GetString(); + break; + } + } + } + } + return aSource; +} + +static BOOL CollectAttrs( const SbxBase* p, XubString& rRes ) +{ + XubString aAttrs; + if( p->IsHidden() ) + aAttrs.AssignAscii( "Hidden" ); + if( p->IsSet( SBX_EXTSEARCH ) ) + { + if( aAttrs.Len() ) + aAttrs += ','; + aAttrs.AppendAscii( "ExtSearch" ); + } + if( !p->IsVisible() ) + { + if( aAttrs.Len() ) + aAttrs += ','; + aAttrs.AppendAscii( "Invisible" ); + } + if( p->IsSet( SBX_DONTSTORE ) ) + { + if( aAttrs.Len() ) + aAttrs += ','; + aAttrs.AppendAscii( "DontStore" ); + } + if( aAttrs.Len() ) + { + rRes.AssignAscii( " (" ); + rRes += aAttrs; + rRes += ')'; + return TRUE; + } + else + { + rRes.Erase(); + return FALSE; + } +} + +void SbxObject::Dump( SvStream& rStrm, BOOL bFill ) +{ + // Einr"uckung + static USHORT nLevel = 0; + if ( nLevel > 10 ) + { + rStrm << "<too deep>" << endl; + return; + } + ++nLevel; + String aIndent; + for ( USHORT n = 1; n < nLevel; ++n ) + aIndent.AppendAscii( " " ); + + // ggf. Objekt vervollst"andigen + if ( bFill ) + GetAll( SbxCLASS_DONTCARE ); + + // Daten des Objekts selbst ausgeben + ByteString aNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US ); + ByteString aClassNameStr( (const UniString&)aClassName, RTL_TEXTENCODING_ASCII_US ); + rStrm << "Object( " + << ByteString::CreateFromInt64( (ULONG) this ).GetBuffer() << "=='" + << ( aNameStr.Len() ? aNameStr.GetBuffer() : "<unnamed>" ) << "', " + << "of class '" << aClassNameStr.GetBuffer() << "', " + << "counts " + << ByteString::CreateFromInt64( GetRefCount() ).GetBuffer() + << " refs, "; + if ( GetParent() ) + { + ByteString aParentNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US ); + rStrm << "in parent " + << ByteString::CreateFromInt64( (ULONG) GetParent() ).GetBuffer() + << "=='" << ( aParentNameStr.Len() ? aParentNameStr.GetBuffer() : "<unnamed>" ) << "'"; + } + else + rStrm << "no parent "; + rStrm << " )" << endl; + ByteString aIndentNameStr( (const UniString&)aIndent, RTL_TEXTENCODING_ASCII_US ); + rStrm << aIndentNameStr.GetBuffer() << "{" << endl; + + // Flags + XubString aAttrs; + if( CollectAttrs( this, aAttrs ) ) + { + ByteString aAttrStr( (const UniString&)aAttrs, RTL_TEXTENCODING_ASCII_US ); + rStrm << aIndentNameStr.GetBuffer() << "- Flags: " << aAttrStr.GetBuffer() << endl; + } + + // Methods + rStrm << aIndentNameStr.GetBuffer() << "- Methods:" << endl; + for( USHORT i = 0; i < pMethods->Count(); i++ ) + { + SbxVariableRef& r = pMethods->GetRef( i ); + SbxVariable* pVar = r; + if( pVar ) + { + XubString aLine( aIndent ); + aLine.AppendAscii( " - " ); + aLine += pVar->GetName( SbxNAME_SHORT_TYPES ); + XubString aAttrs2; + if( CollectAttrs( pVar, aAttrs2 ) ) + aLine += aAttrs2; + if( !pVar->IsA( TYPE(SbxMethod) ) ) + aLine.AppendAscii( " !! Not a Method !!" ); + rStrm.WriteByteString( aLine, RTL_TEXTENCODING_ASCII_US ); + + // bei Object-Methods auch das Object ausgeben + if ( pVar->GetValues_Impl().eType == SbxOBJECT && + pVar->GetValues_Impl().pObj && + pVar->GetValues_Impl().pObj != this && + pVar->GetValues_Impl().pObj != GetParent() ) + { + rStrm << " contains "; + ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill ); + } + else + rStrm << endl; + } + } + + // Properties + rStrm << aIndentNameStr.GetBuffer() << "- Properties:" << endl; + { + for( USHORT i = 0; i < pProps->Count(); i++ ) + { + SbxVariableRef& r = pProps->GetRef( i ); + SbxVariable* pVar = r; + if( pVar ) + { + XubString aLine( aIndent ); + aLine.AppendAscii( " - " ); + aLine += pVar->GetName( SbxNAME_SHORT_TYPES ); + XubString aAttrs3; + if( CollectAttrs( pVar, aAttrs3 ) ) + aLine += aAttrs3; + if( !pVar->IsA( TYPE(SbxProperty) ) ) + aLine.AppendAscii( " !! Not a Property !!" ); + rStrm.WriteByteString( aLine, RTL_TEXTENCODING_ASCII_US ); + + // bei Object-Properties auch das Object ausgeben + if ( pVar->GetValues_Impl().eType == SbxOBJECT && + pVar->GetValues_Impl().pObj && + pVar->GetValues_Impl().pObj != this && + pVar->GetValues_Impl().pObj != GetParent() ) + { + rStrm << " contains "; + ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill ); + } + else + rStrm << endl; + } + } + } + + // Objects + rStrm << aIndentNameStr.GetBuffer() << "- Objects:" << endl; + { + for( USHORT i = 0; i < pObjs->Count(); i++ ) + { + SbxVariableRef& r = pObjs->GetRef( i ); + SbxVariable* pVar = r; + if ( pVar ) + { + rStrm << aIndentNameStr.GetBuffer() << " - Sub"; + if ( pVar->ISA(SbxObject) ) + ((SbxObject*) pVar)->Dump( rStrm, bFill ); + else if ( pVar->ISA(SbxVariable) ) + ((SbxVariable*) pVar)->Dump( rStrm, bFill ); + } + } + } + + rStrm << aIndentNameStr.GetBuffer() << "}" << endl << endl; + --nLevel; +} + +SvDispatch* SbxObject::GetSvDispatch() +{ + return NULL; +} + +SbxClassType SbxMethod::GetClass() const +{ + return SbxCLASS_METHOD; +} + +SbxClassType SbxProperty::GetClass() const +{ + return SbxCLASS_PROPERTY; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxres.cxx b/binfilter/bf_basic/source/sbx/sbxres.cxx new file mode 100644 index 000000000000..d6c7ec33da7a --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxres.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sbxres.hxx" + +namespace binfilter { + +static const char* pSbxRes[] = { + "Empty", + "Null", + "Integer", + "Long", + "Single", + "Double", + "Currency", + "Date", + "String", + "Object", + "Error", + "Boolean", + "Variant", + "Any", + "Type14", + "Type15", + "Char", + "Byte", + "UShort", + "ULong", + "Long64", + "ULong64", + "Int", + "UInt", + "Void", + "HResult", + "Pointer", + "DimArray", + "CArray", + "Any", + "LpStr", + "LpWStr", + " As ", + "Optional ", + "Byref ", + + "Name", + "Parent", + "Application", + "Count", + "Add", + "Item", + "Remove", + + "Error ", // mit Blank! + "False", + "True" +}; + +const char* GetSbxRes( USHORT nId ) +{ + return ( ( nId > SBXRES_MAX ) ? "???" : pSbxRes[ nId ] ); +} + +SbxRes::SbxRes( USHORT nId ) + : XubString( String::CreateFromAscii( GetSbxRes( nId ) ) ) +{} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxres.hxx b/binfilter/bf_basic/source/sbx/sbxres.hxx new file mode 100644 index 000000000000..9f03fab4b8bc --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxres.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBXRES_HXX +#define _SBXRES_HXX + +#include <tools/string.hxx> + +// Zur Zeit sind Ressources im SVTOOLS-Projekt nicht vorgesehen. +// Da es sich um unkritische Ressourcen handelt (BASIC-Keywords), +// koennen wir mit Dummies arbeiten. + +#define STRING_TYPES 0 +#define STRING_EMPTY 0 +#define STRING_NULL 1 +#define STRING_INTEGER 2 +#define STRING_LONG 3 +#define STRING_SINGLE 4 +#define STRING_DOUBLE 5 +#define STRING_CURRENCY 6 +#define STRING_DATE 7 +#define STRING_STRING 8 +#define STRING_OBJECT 9 +#define STRING_ERROR 10 +#define STRING_BOOL 11 +#define STRING_VARIANT 12 +#define STRING_ANY 13 +#define STRING_CHAR 16 +#define STRING_BYTE 17 +#define STRING_USHORT 18 +#define STRING_ULONG 19 +#define STRING_INT 22 +#define STRING_UINT 23 +#define STRING_LPSTR 30 +#define STRING_LPWSTR 31 +#define STRING_AS 32 +#define STRING_OPTIONAL 33 +#define STRING_BYREF 34 + +#define STRING_NAMEPROP 35 +#define STRING_PARENTPROP 36 +#define STRING_APPLPROP 37 +#define STRING_COUNTPROP 38 +#define STRING_ADDMETH 39 +#define STRING_ITEMMETH 40 +#define STRING_REMOVEMETH 41 + +#define STRING_ERRORMSG 42 +#define STRING_FALSE 43 +#define STRING_TRUE 44 + +#define SBXRES_MAX 44 + +namespace binfilter { + +class SbxRes : public String +{ +public: + SbxRes( USHORT ); +}; + +const char* GetSbxRes( USHORT ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxscan.cxx b/binfilter/bf_basic/source/sbx/sbxscan.cxx new file mode 100644 index 000000000000..a5d4417afae1 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxscan.cxx @@ -0,0 +1,517 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +#include "bf_svtools/syslocale.hxx" + +#if defined ( UNX ) +#include <stdlib.h> +#endif + +#include <vcl/svapp.hxx> +#include <math.h> +#include <string.h> +#include <ctype.h> + +#include "sbxres.hxx" +#include "sbxbase.hxx" +#include <bf_svtools/svtools.hrc> + +namespace binfilter { + +void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep ) +{ + SvtSysLocale aSysLocale; + const LocaleDataWrapper& rData = aSysLocale.GetLocaleData(); + rcDecimalSep = rData.getNumDecimalSep().GetBuffer()[0]; + rcThousandSep = rData.getNumThousandSep().GetBuffer()[0]; +} + +// Scannen eines Strings nach BASIC-Konventionen +// Dies entspricht den ueblichen Konventionen, nur dass der Exponent +// auch ein D sein darf, was den Datentyp auf SbxDOUBLE festlegt. +// Die Routine versucht, den Datentyp so klein wie moeglich zu gestalten. +// Das ganze gibt auch noch einen Konversionsfehler, wenn der Datentyp +// Fixed ist und das ganze nicht hineinpasst! + +SbxError ImpScan( const XubString& rWSrc, double& nVal, SbxDataType& rType, + USHORT* pLen, BOOL bAllowIntntl, BOOL bOnlyIntntl ) +{ + ByteString aBStr( rWSrc, RTL_TEXTENCODING_ASCII_US ); + + // Bei International Komma besorgen + char cIntntlComma, cIntntl1000; + char cNonIntntlComma = '.'; + + sal_Unicode cDecimalSep, cThousandSep = 0; + if( bAllowIntntl || bOnlyIntntl ) + { + ImpGetIntntlSep( cDecimalSep, cThousandSep ); + cIntntlComma = (char)cDecimalSep; + cIntntl1000 = (char)cThousandSep; + } + // Sonst einfach auch auf . setzen + else + { + cIntntlComma = cNonIntntlComma; + cIntntl1000 = cNonIntntlComma; // Unschaedlich machen + } + // Nur International -> IntnlComma uebernehmen + if( bOnlyIntntl ) + { + cNonIntntlComma = cIntntlComma; + cIntntl1000 = (char)cThousandSep; + } + + const char* pStart = aBStr.GetBuffer(); + const char* p = pStart; + char buf[ 80 ], *q = buf; + BOOL bRes = TRUE; + BOOL bMinus = FALSE; + nVal = 0; + SbxDataType eScanType = SbxSINGLE; + // Whitespace wech + while( *p &&( *p == ' ' || *p == '\t' ) ) p++; + // Zahl? Dann einlesen und konvertieren. + if( *p == '-' ) + p++, bMinus = TRUE; + if( isdigit( *p ) ||( (*p == cNonIntntlComma || *p == cIntntlComma || + *p == cIntntl1000) && isdigit( *(p+1 ) ) ) ) + { + short exp = 0; // >0: Exponentteil + short comma = 0; // >0: Nachkomma + short ndig = 0; // Anzahl Ziffern + short ncdig = 0; // Anzahl Ziffern nach Komma + ByteString aSearchStr( "0123456789DEde" ); + // Kommas ergaenzen + aSearchStr += cNonIntntlComma; + if( cIntntlComma != cNonIntntlComma ) + aSearchStr += cIntntlComma; + if( bOnlyIntntl ) + aSearchStr += cIntntl1000; + const char* pSearchStr = aSearchStr.GetBuffer(); + while( strchr( pSearchStr, *p ) && *p ) + { + // 1000er-Trenner ueberlesen + if( bOnlyIntntl && *p == cIntntl1000 ) + { + p++; + continue; + } + + // Komma oder Exponent? + if( *p == cNonIntntlComma || *p == cIntntlComma ) + { + // Immer '.' einfuegen, damit atof funktioniert + p++; + if( ++comma > 1 ) + continue; + else + *q++ = '.'; + } + else if( strchr( "DdEe", *p ) ) + { + if( ++exp > 1 ) + { + p++; continue; + } + if( toupper( *p ) == 'D' ) + eScanType = SbxDOUBLE; + *q++ = 'E'; p++; + // Vorzeichen hinter Exponent? + if( *p == '+' ) + p++; + else + if( *p == '-' ) + *q++ = *p++; + } + else + { + *q++ = *p++; + if( comma && !exp ) ncdig++; + } + if( !exp ) ndig++; + } + *q = 0; + // Komma, Exponent mehrfach vorhanden? + if( comma > 1 || exp > 1 ) + bRes = FALSE; + // Kann auf Integer gefaltet werden? + if( !comma && !exp ) + { + if( nVal >= SbxMININT && nVal <= SbxMAXINT ) + eScanType = SbxINTEGER; + else if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG ) + eScanType = SbxLONG; + } + + nVal = atof( buf ); + ndig = ndig - comma; + // zu viele Zahlen fuer SINGLE? + if( ndig > 15 || ncdig > 6 ) + eScanType = SbxDOUBLE; + + // Typkennung? + if( strchr( "%!&#", *p ) && *p ) p++; + } + // Hex/Oktalzahl? Einlesen und konvertieren: + else if( *p == '&' ) + { + p++; + eScanType = SbxLONG; + const char *cmp = "0123456789ABCDEF"; + char base = 16; + char ndig = 8; + char xch = *p++; + switch( toupper( xch ) ) + { + case 'O': cmp = "01234567"; base = 8; ndig = 11; break; + case 'H': break; + default : bRes = FALSE; + } + long l = 0; + int i; + while( isalnum( *p ) ) + { + char ch = sal::static_int_cast< char >( toupper( *p ) ); + p++; + if( strchr( cmp, ch ) ) *q++ = ch; + else bRes = FALSE; + } + *q = 0; + for( q = buf; *q; q++ ) + { + i =( *q & 0xFF ) - '0'; + if( i > 9 ) i -= 7; + l =( l * base ) + i; + if( !ndig-- ) + bRes = FALSE; + } + if( *p == '&' ) p++; + nVal = (double) l; + if( l >= SbxMININT && l <= SbxMAXINT ) + eScanType = SbxINTEGER; + } + if( pLen ) + *pLen = (USHORT) ( p - pStart ); + if( !bRes ) + return SbxERR_CONVERSION; + if( bMinus ) + nVal = -nVal; + rType = eScanType; + return SbxERR_OK; +} + +//////////////////////////////////////////////////////////////////////////// + +static double roundArray[] = { + 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6, 0.5e-7, + 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,0.5e-15 }; + +/*************************************************************************** +|* +|* void myftoa( double, char *, short, short, BOOL, BOOL ) +|* +|* Beschreibung: Konversion double --> ASCII +|* Parameter: double die Zahl. +|* char * der Zielpuffer +|* short Anzahl Nachkommastellen +|* short Weite des Exponenten( 0=kein E ) +|* BOOL TRUE: mit 1000er Punkten +|* BOOL TRUE: formatfreie Ausgabe +|* +***************************************************************************/ + +static void myftoa( double nNum, char * pBuf, short nPrec, short nExpWidth, + BOOL bPt, BOOL bFix, sal_Unicode cForceThousandSep = 0 ) +{ + + short nExp = 0; // Exponent + short nDig = nPrec + 1; // Anzahl Digits in Zahl + short nDec; // Anzahl Vorkommastellen + register int i, digit; + + // Komma besorgen + sal_Unicode cDecimalSep, cThousandSep; + ImpGetIntntlSep( cDecimalSep, cThousandSep ); + if( cForceThousandSep ) + cThousandSep = cForceThousandSep; + + // Exponentberechnung: + nExp = 0; + if( nNum > 0.0 ) + { + while( nNum < 1.0 ) nNum *= 10.0, nExp--; + while( nNum >= 10.0 ) nNum /= 10.0, nExp++; + } + if( !bFix && !nExpWidth ) + nDig = nDig + nExp; + else if( bFix && !nPrec ) + nDig = nExp + 1; + + // Zahl runden: + if( (nNum += roundArray [( nDig > 16 ) ? 16 : nDig] ) >= 10.0 ) + { + nNum = 1.0; + ++nExp; + if( !nExpWidth ) ++nDig; + } + + // Bestimmung der Vorkommastellen: + if( !nExpWidth ) + { + if( nExp < 0 ) + { + // #41691: Auch bei bFix eine 0 spendieren + *pBuf++ = '0'; + if( nPrec ) *pBuf++ = (char)cDecimalSep; + i = -nExp - 1; + if( nDig <= 0 ) i = nPrec; + while( i-- ) *pBuf++ = '0'; + nDec = 0; + } + else + nDec = nExp+1; + } + else + nDec = 1; + + // Zahl ausgeben: + if( nDig > 0 ) + { + for( i = 0 ; ; ++i ) + { + if( i < 16 ) + { + digit = (int) nNum; + *pBuf++ = sal::static_int_cast< char >(digit + '0'); + nNum =( nNum - digit ) * 10.0; + } else + *pBuf++ = '0'; + if( --nDig == 0 ) break; + if( nDec ) + { + nDec--; + if( !nDec ) + *pBuf++ = (char)cDecimalSep; + else if( !(nDec % 3 ) && bPt ) + *pBuf++ = (char)cThousandSep; + } + } + } + + // Exponent ausgeben: + if( nExpWidth ) + { + if( nExpWidth < 3 ) nExpWidth = 3; + nExpWidth -= 2; + *pBuf++ = 'E'; + *pBuf++ =( nExp < 0 ) ?( (nExp = -nExp ), '-' ) : '+'; + while( nExpWidth > 3 ) *pBuf++ = '0', nExpWidth--; + if( nExp >= 100 || nExpWidth == 3 ) + { + *pBuf++ = sal::static_int_cast< char >(nExp/100 + '0'); + nExp %= 100; + } + if( nExp/10 || nExpWidth >= 2 ) + *pBuf++ = sal::static_int_cast< char >(nExp/10 + '0'); + *pBuf++ = sal::static_int_cast< char >(nExp%10 + '0'); + } + *pBuf = 0; +} + +// Die Zahl wird unformatiert mit der angegebenen Anzahl NK-Stellen +// aufbereitet. Evtl. wird ein Minus vorangestellt. +// Diese Routine ist public, weil sie auch von den Put-Funktionen +// der Klasse SbxImpSTRING verwendet wird. + +#ifdef _MSC_VER +#pragma optimize( "", off ) +#pragma warning(disable: 4748) // "... because optimizations are disabled ..." +#endif + +void ImpCvtNum( double nNum, short nPrec, XubString& rRes, BOOL bCoreString ) +{ + char *q; + char cBuf[ 40 ], *p = cBuf; + + sal_Unicode cDecimalSep, cThousandSep; + ImpGetIntntlSep( cDecimalSep, cThousandSep ); + if( bCoreString ) + cDecimalSep = '.'; + + if( nNum < 0.0 ) { + nNum = -nNum; + *p++ = '-'; + } + double dMaxNumWithoutExp = (nPrec == 6) ? 1E6 : 1E14; + myftoa( nNum, p, nPrec,( nNum &&( nNum < 1E-1 || nNum > dMaxNumWithoutExp ) ) ? 4:0, + FALSE, TRUE, cDecimalSep ); + // Trailing Zeroes weg: + for( p = cBuf; *p &&( *p != 'E' ); p++ ) {} + q = p; p--; + while( nPrec && *p == '0' ) nPrec--, p--; + if( *p == cDecimalSep ) p--; + while( *q ) *++p = *q++; + *++p = 0; + rRes = String::CreateFromAscii( cBuf ); +} + +#ifdef _MSC_VER +#pragma optimize( "", on ) +#endif + +// Formatierte Zahlenausgabe +// Der Returnwert ist die Anzahl Zeichen, die aus dem +// Format verwendt wurden. + +#ifdef _old_format_code_ +// lasse diesen Code vorl"aufig drin, zum 'abgucken' +// der bisherigen Implementation + +static USHORT printfmtnum( double nNum, XubString& rRes, const XubString& rWFmt ) +{ + const String& rFmt = rWFmt; + char cFill = ' '; // Fuellzeichen + char cPre = 0; // Startzeichen( evtl. "$" ) + short nExpDig= 0; // Anzahl Exponentstellen + short nPrec = 0; // Anzahl Nachkommastellen + short nWidth = 0; // Zahlenweite gesamnt + short nLen; // Laenge konvertierte Zahl + BOOL bPoint = FALSE; // TRUE: mit 1000er Kommas + BOOL bTrail = FALSE; // TRUE, wenn folgendes Minus + BOOL bSign = FALSE; // TRUE: immer mit Vorzeichen + BOOL bNeg = FALSE; // TRUE: Zahl ist negativ + char cBuf [1024]; // Zahlenpuffer + char * p; + const char* pFmt = rFmt; + rRes.Erase(); + // $$ und ** abfangen. Einfach wird als Zeichen ausgegeben. + if( *pFmt == '$' ) + if( *++pFmt != '$' ) rRes += '$'; + if( *pFmt == '*' ) + if( *++pFmt != '*' ) rRes += '*'; + + switch( *pFmt++ ) + { + case 0: + break; + case '+': + bSign = TRUE; nWidth++; break; + case '*': + nWidth++; cFill = '*'; + if( *pFmt == '$' ) nWidth++, pFmt++, cPre = '$'; + break; + case '$': + nWidth++; cPre = '$'; break; + case '#': + case '.': + case ',': + pFmt--; break; + } + // Vorkomma: + for( ;; ) + { + while( *pFmt == '#' ) pFmt++, nWidth++; + // 1000er Kommas? + if( *pFmt == ',' ) + { + nWidth++; pFmt++; bPoint = TRUE; + } else break; + } + // Nachkomma: + if( *pFmt == '.' ) + { + while( *++pFmt == '#' ) nPrec++; + nWidth += nPrec + 1; + } + // Exponent: + while( *pFmt == '^' ) + pFmt++, nExpDig++, nWidth++; + // Folgendes Minus: + if( !bSign && *pFmt == '-' ) + pFmt++, bTrail = TRUE; + + // Zahl konvertieren: + if( nPrec > 15 ) nPrec = 15; + if( nNum < 0.0 ) nNum = -nNum, bNeg = TRUE; + p = cBuf; + if( bSign ) *p++ = bNeg ? '-' : '+'; + myftoa( nNum, p, nPrec, nExpDig, bPoint, FALSE ); + nLen = strlen( cBuf ); + + // Ueberlauf? + if( cPre ) nLen++; + if( nLen > nWidth ) rRes += '%'; + else { + nWidth -= nLen; + while( nWidth-- ) rRes += (xub_Unicode)cFill; + if( cPre ) rRes += (xub_Unicode)cPre; + } + rRes += (xub_Unicode*)&(cBuf[0]); + if( bTrail ) + rRes += bNeg ? '-' : ' '; + + return (USHORT) ( pFmt - (const char*) rFmt ); +} + +#endif //_old_format_code_ + +///////////////////////////////////////////////////////////////////////// + +BOOL SbxValue::Scan( const XubString& rSrc, USHORT* pLen ) +{ + SbxError eRes = SbxERR_OK; + if( !CanWrite() ) + eRes = SbxERR_PROP_READONLY; + else + { + double n; + SbxDataType t; + eRes = ImpScan( rSrc, n, t, pLen ); + if( eRes == SbxERR_OK ) + { + if( !IsFixed() ) + SetType( t ); + PutDouble( n ); + } + } + if( eRes ) + { + SetError( eRes ); return FALSE; + } + else + return TRUE; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxsng.cxx b/binfilter/bf_basic/source/sbx/sbxsng.cxx new file mode 100644 index 000000000000..7e5732d0f258 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxsng.cxx @@ -0,0 +1,363 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +float ImpGetSingle( const SbxValues* p ) +{ + SbxValues aTmp; + float nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + nRes = p->nInteger; break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; break; + case SbxLONG: + nRes = (float) p->nLong; break; + case SbxULONG: + nRes = (float) p->nULong; break; + case SbxSINGLE: + nRes = p->nSingle; break; + case SbxSALINT64: + nRes = (float) p->nInt64; break; + case SbxSALUINT64: + nRes = (float) ImpSalUInt64ToDouble( p->uInt64 ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + if( p->pDecimal ) + p->pDecimal->getSingle( nRes ); + else + nRes = 0.0; + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else + dVal = p->nDouble; + + if( dVal > SbxMAXSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + nRes = static_cast< float >(SbxMAXSNG); + } + else if( dVal < SbxMINSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + nRes = static_cast< float >(SbxMINSNG); + } + else if( dVal > 0 && dVal < SbxMAXSNG2 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + nRes = static_cast< float >(SbxMAXSNG2); + } + else if( dVal < 0 && dVal > SbxMINSNG2 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + nRes = static_cast< float >(SbxMINSNG2); + } + else + nRes = (float) dVal; + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + nRes = static_cast< float >(SbxMAXSNG); + } + else if( d < SbxMINSNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); + nRes = static_cast< float >(SbxMINSNG); + } + else + nRes = (float) d; + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetSingle(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxCHAR: + nRes = *p->pChar; break; + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + nRes = *p->pInteger; break; + case SbxBYREF | SbxLONG: + nRes = (float) *p->pLong; break; + case SbxBYREF | SbxULONG: + nRes = (float) *p->pULong; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = *p->pUShort; break; + case SbxBYREF | SbxSINGLE: + nRes = *p->pSingle; break; + // ab hier muss getestet werden + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxSALINT64: + nRes = (float) *p->pnInt64; break; + case SbxBYREF | SbxSALUINT64: + nRes = (float) ImpSalUInt64ToDouble( *p->puInt64 ); break; + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutSingle( SbxValues* p, float n ) +{ + SbxValues aTmp; +start: + switch( +p->eType ) + { + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxLONG: + aTmp.pLong = &p->nLong; goto direct; + case SbxULONG: + aTmp.pULong = &p->nULong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxULONG64: + aTmp.pULong64 = &p->nULong64; goto direct; + case SbxLONG64: + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + case SbxSALINT64: + aTmp.pnInt64 = &p->nInt64; goto direct; + case SbxSALUINT64: + aTmp.puInt64 = &p->uInt64; goto direct; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + SbxDecimal* pDec = ImpCreateDecimal( p ); + if( !pDec->setSingle( n ) ) + SbxBase::SetError( SbxERR_OVERFLOW ); + break; + } + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + // keine Tests ab hier + case SbxSINGLE: + p->nSingle = n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + { + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 6, *p->pString ); + break; + } + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutSingle( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + else if( n < SbxMINCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + else if( n < SbxMININT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = 0; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + { + INT32 i; + if( n > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); i = SbxMAXLNG; + } + else if( n < SbxMINLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); i = SbxMINLNG; + } + else + { + i = sal::static_int_cast< INT32 >(n); + } + *p->pLong = i; break; + } + case SbxBYREF | SbxULONG: + { + UINT32 i; + if( n > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); i = SbxMAXULNG; + } + else if( n < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); i = 0; + } + else + { + i = sal::static_int_cast< UINT32 >(n); + } + *p->pULong = i; break; + } + case SbxBYREF | SbxSINGLE: + *p->pSingle = n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = (double) n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = ImpDoubleToSalInt64( (double) n ); break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = ImpDoubleToSalUInt64( (double) n ); break; + case SbxBYREF | SbxCURRENCY: + double d; + if( n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMAXCURR; + } + else if( n < SbxMINCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMINCURR; + } + else + { + d = n; + } + *p->pLong64 = ImpDoubleToCurrency( n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxstr.cxx b/binfilter/bf_basic/source/sbx/sbxstr.cxx new file mode 100644 index 000000000000..193d9a99bc11 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxstr.cxx @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" +#include "sbxres.hxx" + +namespace binfilter { + +// Die Konversion eines Items auf String wird ueber die Put-Methoden +// der einzelnen Datentypen abgewickelt, um doppelten Code zu vermeiden. + +XubString ImpGetString( const SbxValues* p ) +{ + SbxValues aTmp; + XubString aRes; + aTmp.eType = SbxSTRING; + aTmp.pString = &aRes; + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + break; + case SbxCHAR: + ImpPutChar( &aTmp, p->nChar ); break; + case SbxBYTE: + ImpPutByte( &aTmp, p->nByte ); break; + case SbxINTEGER: + ImpPutInteger( &aTmp, p->nInteger ); break; + case SbxBOOL: + ImpPutBool( &aTmp, p->nUShort ); break; + case SbxUSHORT: + ImpPutUShort( &aTmp, p->nUShort ); break; + case SbxLONG: + ImpPutLong( &aTmp, p->nLong ); break; + case SbxULONG: + ImpPutULong( &aTmp, p->nULong ); break; + case SbxSINGLE: + ImpPutSingle( &aTmp, p->nSingle ); break; + case SbxDOUBLE: + ImpPutDouble( &aTmp, p->nDouble ); break; + case SbxCURRENCY: + ImpPutCurrency( &aTmp, p->nLong64 ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpPutDecimal( &aTmp, p->pDecimal ); break; + case SbxSALINT64: + ImpPutInt64( &aTmp, p->nInt64 ); break; + case SbxSALUINT64: + ImpPutUInt64( &aTmp, p->uInt64 ); break; + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( p->pString ) + aRes = *p->pString; + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + aRes = pVal->GetString(); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxERROR: + // Hier wird der String "Error n" erzeugt + aRes = SbxRes( STRING_ERRORMSG ); + aRes += p->nUShort; break; + case SbxDATE: + ImpPutDate( &aTmp, p->nDouble ); break; + + case SbxBYREF | SbxCHAR: + ImpPutChar( &aTmp, *p->pChar ); break; + case SbxBYREF | SbxBYTE: + ImpPutByte( &aTmp, *p->pByte ); break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + ImpPutInteger( &aTmp, *p->pInteger ); break; + case SbxBYREF | SbxLONG: + ImpPutLong( &aTmp, *p->pLong ); break; + case SbxBYREF | SbxULONG: + ImpPutULong( &aTmp, *p->pULong ); break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + ImpPutUShort( &aTmp, *p->pUShort ); break; + case SbxBYREF | SbxSINGLE: + ImpPutSingle( &aTmp, *p->pSingle ); break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + ImpPutDouble( &aTmp, *p->pDouble ); break; + case SbxBYREF | SbxCURRENCY: + ImpPutCurrency( &aTmp, *p->pLong64 ); break; + case SbxBYREF | SbxSALINT64: + ImpPutInt64( &aTmp, *p->pnInt64 ); break; + case SbxBYREF | SbxSALUINT64: + ImpPutUInt64( &aTmp, *p->puInt64 ); break; + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } + return aRes; +} + +// AB 10.4.97, neue Funktion fuer SbxValue::GetCoreString() +XubString ImpGetCoreString( const SbxValues* p ) +{ + // Vorerst nur fuer double + if( ( p->eType & (~SbxBYREF) ) == SbxDOUBLE ) + { + SbxValues aTmp; + XubString aRes; + aTmp.eType = SbxSTRING; + aTmp.pString = &aRes; + if( p->eType == SbxDOUBLE ) + ImpPutDouble( &aTmp, p->nDouble, /*bCoreString=*/TRUE ); + else + ImpPutDouble( &aTmp, *p->pDouble, /*bCoreString=*/TRUE ); + return aRes; + } + else + return ImpGetString( p ); +} + +void ImpPutString( SbxValues* p, const XubString* n ) +{ + SbxValues aTmp; + aTmp.eType = SbxSTRING; + XubString* pTmp = NULL; + // Sicherheitshalber, falls ein NULL-Ptr kommt + if( !n ) + n = pTmp = new XubString; + aTmp.pString = (XubString*) n; + switch( +p->eType ) + { + case SbxCHAR: + p->nChar = ImpGetChar( &aTmp ); break; + case SbxBYTE: + p->nByte = ImpGetByte( &aTmp ); break; + case SbxINTEGER: + case SbxBOOL: + p->nInteger = ImpGetInteger( &aTmp ); break; + case SbxLONG: + p->nLong = ImpGetLong( &aTmp ); break; + case SbxULONG: + p->nULong = ImpGetULong( &aTmp ); break; + case SbxERROR: + case SbxUSHORT: + p->nUShort = ImpGetUShort( &aTmp ); break; + case SbxSINGLE: + p->nSingle = ImpGetSingle( &aTmp ); break; + case SbxDATE: + p->nDouble = ImpGetDate( &aTmp ); break; + case SbxDOUBLE: + p->nDouble = ImpGetDouble( &aTmp ); break; + case SbxULONG64: + p->nLong64 = ImpGetCurrency( &aTmp ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + releaseDecimalPtr( p->pDecimal ); + p->pDecimal = ImpGetDecimal( &aTmp ); break; + case SbxSALINT64: + p->nInt64 = ImpGetInt64( &aTmp ); break; + case SbxSALUINT64: + p->uInt64 = ImpGetUInt64( &aTmp ); break; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( n->Len() ) + { + if( !p->pString ) + p->pString = new XubString; + *p->pString = *n; + } + else + delete p->pString, p->pString = NULL; + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutString( *n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + *p->pChar = ImpGetChar( p ); break; + case SbxBYREF | SbxBYTE: + *p->pByte = ImpGetByte( p ); break; + case SbxBYREF | SbxINTEGER: + *p->pInteger = ImpGetInteger( p ); break; + case SbxBYREF | SbxBOOL: + *p->pUShort = sal::static_int_cast< UINT16 >( ImpGetBool( p ) ); + break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + *p->pUShort = ImpGetUShort( p ); break; + case SbxBYREF | SbxLONG: + *p->pLong = ImpGetLong( p ); break; + case SbxBYREF | SbxULONG: + *p->pULong = ImpGetULong( p ); break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = ImpGetSingle( p ); break; + case SbxBYREF | SbxDATE: + *p->pDouble = ImpGetDate( p ); break; + case SbxBYREF | SbxDOUBLE: + *p->pDouble = ImpGetDouble( p ); break; + case SbxBYREF | SbxCURRENCY: + *p->pLong64 = ImpGetCurrency( p ); break; + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } + delete pTmp; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxuint.cxx b/binfilter/bf_basic/source/sbx/sbxuint.cxx new file mode 100644 index 000000000000..9eb3d0cbf2fb --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxuint.cxx @@ -0,0 +1,335 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +UINT16 ImpGetUShort( const SbxValues* p ) +{ + SbxValues aTmp; + UINT16 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; + break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + if( p->nInteger < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = p->nInteger; + break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; + break; + case SbxLONG: + if( p->nLong > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else if( p->nLong < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT16) p->nLong; + break; + case SbxULONG: + if( p->nULong > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else + nRes = (UINT16) p->nULong; + break; + case SbxSALINT64: + if( p->nInt64 > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else if( p->nInt64 < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT16) p->nInt64; + break; + case SbxSALUINT64: + if( p->uInt64 > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else + nRes = (UINT16) p->uInt64; + break; + case SbxSINGLE: + if( p->nSingle > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else if( p->nSingle < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT16) ( p->nSingle + 0.5 ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxCURRENCY: + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else if( p->eType == SbxDECIMAL ) + { + dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + } + else + dVal = p->nDouble; + + if( dVal > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else if( dVal < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT16) ( dVal + 0.5 ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT; + } + else if( d < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT16) ( d + 0.5 ); + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetUShort(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = *p->pUShort; break; + + // ab hier wird getestet + case SbxBYREF | SbxCHAR: + aTmp.nChar = *p->pChar; goto ref; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + aTmp.nInteger = *p->pInteger; goto ref; + case SbxBYREF | SbxLONG: + aTmp.nLong = *p->pLong; goto ref; + case SbxBYREF | SbxULONG: + aTmp.nULong = *p->pULong; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutUShort( SbxValues* p, UINT16 n ) +{ + SbxValues aTmp; + +start: + switch( +p->eType ) + { + case SbxERROR: + case SbxUSHORT: + p->nUShort = n; break; + case SbxLONG: + p->nLong = n; break; + case SbxULONG: + p->nULong = n; break; + case SbxSINGLE: + p->nSingle = n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxSALUINT64: + p->uInt64 = n; break; + case SbxULONG64: + p->nULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxLONG64: + p->nLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxCURRENCY: + p->nLong64 = ImpDoubleToCurrency( (double)n ); break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setUInt( n ); + break; + + // Tests ab hier + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxBYTE: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 0, *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutUShort( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + + case SbxBYREF | SbxCHAR: + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + *p->pUShort = n; break; + case SbxBYREF | SbxLONG: + *p->pLong = n; break; + case SbxBYREF | SbxULONG: + *p->pULong = n; break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = n; break; + case SbxBYREF | SbxULONG64: + *p->pULong64 = ImpDoubleToUINT64( (double)n ); break; + case SbxBYREF | SbxLONG64: + *p->pLong64 = ImpDoubleToINT64( (double)n ); break; + case SbxBYREF | SbxCURRENCY: + *p->pLong64 = ImpDoubleToCurrency( (double)n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxulng.cxx b/binfilter/bf_basic/source/sbx/sbxulng.cxx new file mode 100644 index 000000000000..da49619667a1 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxulng.cxx @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/errcode.hxx> +#include "sbx.hxx" +#include "sbxconv.hxx" + +namespace binfilter { + +UINT32 ImpGetULong( const SbxValues* p ) +{ + SbxValues aTmp; + UINT32 nRes; +start: + switch( +p->eType ) + { + case SbxNULL: + SbxBase::SetError( SbxERR_CONVERSION ); + case SbxEMPTY: + nRes = 0; break; + case SbxCHAR: + nRes = p->nChar; + break; + case SbxBYTE: + nRes = p->nByte; break; + case SbxINTEGER: + case SbxBOOL: + if( p->nInteger < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = p->nInteger; + break; + case SbxERROR: + case SbxUSHORT: + nRes = p->nUShort; + break; + case SbxLONG: + if( p->nLong < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = p->nLong; + break; + case SbxULONG: + nRes = p->nULong; break; + case SbxSINGLE: + if( p->nSingle > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXULNG; + } + else if( p->nSingle < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT32) ( p->nSingle + 0.5 ); + break; + case SbxDATE: + case SbxDOUBLE: + case SbxLONG64: + case SbxULONG64: + case SbxSALINT64: + case SbxSALUINT64: + case SbxCURRENCY: + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + { + double dVal; + if( p->eType == SbxCURRENCY ) + dVal = ImpCurrencyToDouble( p->nLong64 ); + else if( p->eType == SbxLONG64 ) + dVal = ImpINT64ToDouble( p->nLong64 ); + else if( p->eType == SbxULONG64 ) + dVal = ImpUINT64ToDouble( p->nULong64 ); + else if( p->eType == SbxSALINT64 ) + dVal = static_cast< double >(p->nInt64); + else if( p->eType == SbxSALUINT64 ) + dVal = ImpSalUInt64ToDouble( p->uInt64 ); + else if( p->eType == SbxDECIMAL ) + { + dVal = 0.0; + if( p->pDecimal ) + p->pDecimal->getDouble( dVal ); + } + else + dVal = p->nDouble; + + if( dVal > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXULNG; + } + else if( dVal < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT32) ( dVal + 0.5 ); + break; + } + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + nRes = 0; + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + nRes = 0; + else if( d > SbxMAXULNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXULNG; + } + else if( d < 0 ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0; + } + else + nRes = (UINT32) ( d + 0.5 ); + } + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + nRes = pVal->GetULong(); + else + { + SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0; + } + break; + } + + case SbxBYREF | SbxBYTE: + nRes = *p->pByte; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + nRes = *p->pUShort; break; + case SbxBYREF | SbxULONG: + nRes = *p->pULong; break; + + // Tests ab hier + case SbxBYREF | SbxCHAR: + aTmp.nChar = *p->pChar; goto ref; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + aTmp.nInteger = *p->pInteger; goto ref; + case SbxBYREF | SbxLONG: + aTmp.nLong = *p->pLong; goto ref; + case SbxBYREF | SbxSINGLE: + aTmp.nSingle = *p->pSingle; goto ref; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + aTmp.nDouble = *p->pDouble; goto ref; + case SbxBYREF | SbxSALINT64: + aTmp.nInt64 = *p->pnInt64; goto ref; + case SbxBYREF | SbxSALUINT64: + aTmp.uInt64 = *p->puInt64; goto ref; + case SbxBYREF | SbxULONG64: + aTmp.nULong64 = *p->pULong64; goto ref; + case SbxBYREF | SbxLONG64: + case SbxBYREF | SbxCURRENCY: + aTmp.nLong64 = *p->pLong64; goto ref; + ref: + aTmp.eType = SbxDataType( p->eType & 0x0FFF ); + p = &aTmp; goto start; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0; + } + return nRes; +} + +void ImpPutULong( SbxValues* p, UINT32 n ) +{ + SbxValues aTmp; +start: + switch( +p->eType ) + { + case SbxULONG: + p->nULong = n; break; + case SbxSINGLE: + p->nSingle = (float) n; break; + case SbxDATE: + case SbxDOUBLE: + p->nDouble = n; break; + case SbxSALINT64: + p->nInt64 = n; break; + case SbxSALUINT64: + p->uInt64 = n; break; + case SbxDECIMAL: + case SbxBYREF | SbxDECIMAL: + ImpCreateDecimal( p )->setULong( n ); + break; + + // Tests ab hier + case SbxCHAR: + aTmp.pChar = &p->nChar; goto direct; + case SbxUINT: + aTmp.pByte = &p->nByte; goto direct; + case SbxINTEGER: + case SbxBOOL: + aTmp.pInteger = &p->nInteger; goto direct; + case SbxLONG: + aTmp.pLong = &p->nLong; goto direct; + case SbxERROR: + case SbxUSHORT: + aTmp.pUShort = &p->nUShort; goto direct; + case SbxULONG64: + aTmp.pULong64 = &p->nULong64; goto direct; + case SbxLONG64: + case SbxCURRENCY: + aTmp.pLong64 = &p->nLong64; goto direct; + direct: + aTmp.eType = SbxDataType( p->eType | SbxBYREF ); + p = &aTmp; goto start; + + case SbxBYREF | SbxSTRING: + case SbxSTRING: + case SbxLPSTR: + if( !p->pString ) + p->pString = new XubString; + ImpCvtNum( (double) n, 0, *p->pString ); + break; + case SbxOBJECT: + { + SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); + if( pVal ) + pVal->PutULong( n ); + else + SbxBase::SetError( SbxERR_NO_OBJECT ); + break; + } + case SbxBYREF | SbxCHAR: + if( n > SbxMAXCHAR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR; + } + *p->pChar = (xub_Unicode) n; break; + case SbxBYREF | SbxBYTE: + if( n > SbxMAXBYTE ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE; + } + *p->pByte = (BYTE) n; break; + case SbxBYREF | SbxINTEGER: + case SbxBYREF | SbxBOOL: + if( n > SbxMAXINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT; + } + *p->pInteger = (INT16) n; break; + case SbxBYREF | SbxERROR: + case SbxBYREF | SbxUSHORT: + if( n > SbxMAXUINT ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT; + } + *p->pUShort = (UINT16) n; break; + case SbxBYREF | SbxLONG: + if( n > SbxMAXLNG ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG; + } + *p->pLong = (INT32) n; break; + case SbxBYREF | SbxULONG: + *p->pULong = n; break; + case SbxBYREF | SbxSINGLE: + *p->pSingle = (float) n; break; + case SbxBYREF | SbxDATE: + case SbxBYREF | SbxDOUBLE: + *p->pDouble = n; break; + case SbxBYREF | SbxSALINT64: + *p->pnInt64 = n; break; + case SbxBYREF | SbxSALUINT64: + *p->puInt64 = n; break; + case SbxBYREF | SbxCURRENCY: + double d; + if( n > SbxMAXCURR ) + { + SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMAXCURR; + } + else + { + d = n; + } + *p->pLong64 = ImpDoubleToCurrency( n ); break; + + default: + SbxBase::SetError( SbxERR_CONVERSION ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxvalue.cxx b/binfilter/bf_basic/source/sbx/sbxvalue.cxx new file mode 100644 index 000000000000..5c88a1218706 --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxvalue.cxx @@ -0,0 +1,1710 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define _TLBIGINT_INT64 +#include <tools/bigint.hxx> +#include <tools/stream.hxx> + +#include "sbx.hxx" +#include "sbxconv.hxx" +#include <math.h> + +namespace binfilter { + +TYPEINIT1(SbxValue,SbxBase) + +BigInt SbxINT64Converter::SbxINT64_2_BigInt( const SbxINT64 &r ) +{ + BigInt a10000 = 0x10000; + + BigInt aReturn( r.nHigh ); + if( r.nHigh ) + aReturn *= a10000; + aReturn += (USHORT)(r.nLow >> 16); + aReturn *= a10000; + aReturn += (USHORT)r.nLow; + return aReturn; +} + +BOOL SbxINT64Converter::BigInt_2_SbxINT64( const BigInt& b, SbxINT64 *p ) +{ + if( !b.IsLong() ) { + if( b.nLen > 4 || (b.nNum[3] & 0x8000) ) + return FALSE; + + p->nLow = ((UINT32)b.nNum[1] << 16) | (UINT32)b.nNum[0]; + p->nHigh = ((UINT32)b.nNum[3] << 16) | (UINT32)b.nNum[2]; + if( b.bIsNeg ) + p->CHS(); + } + else + p->Set( (INT32)b.nVal ); + + return TRUE; +} + +BigInt SbxINT64Converter::SbxUINT64_2_BigInt( const SbxUINT64 &r ) +{ + BigInt a10000 = 0x10000; + + BigInt aReturn(r.nHigh); + if( r.nHigh ) + aReturn *= a10000; + aReturn += (USHORT)(r.nLow >> 16); + aReturn *= a10000; + aReturn += (USHORT)r.nLow; + return aReturn; +} + +BOOL SbxINT64Converter::BigInt_2_SbxUINT64( const BigInt& b, SbxUINT64 *p ) +{ + if( b.bIsBig ) { + if( b.bIsNeg || b.nLen > 4 ) + return FALSE; + + p->nLow = ((UINT32)b.nNum[1] << 16) | (UINT32)b.nNum[0]; + p->nHigh = ((UINT32)b.nNum[3] << 16) | (UINT32)b.nNum[2]; + } + else { + if( b.nVal < 0 ) + return FALSE; + + p->Set( (UINT32)b.nVal ); + } + + return TRUE; +} + +/////////////////////////// SbxINT64 ///////////////////////////////////// +SbxINT64 &SbxINT64::operator -= ( const SbxINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxINT64_2_BigInt( *this ) ); + b -= SbxINT64Converter::SbxINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxINT64( b, this ); + return *this; +} +SbxINT64 &SbxINT64::operator += ( const SbxINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxINT64_2_BigInt( *this ) ); + b += SbxINT64Converter::SbxINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxINT64( b, this ); + return *this; +} +SbxINT64 &SbxINT64::operator *= ( const SbxINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxINT64_2_BigInt( *this ) ); + b *= SbxINT64Converter::SbxINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxINT64( b, this ); + return *this; +} +SbxINT64 &SbxINT64::operator %= ( const SbxINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxINT64_2_BigInt( *this ) ); + b %= SbxINT64Converter::SbxINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxINT64( b, this ); + return *this; +} +SbxINT64 &SbxINT64::operator /= ( const SbxINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxINT64_2_BigInt( *this ) ); + b /= SbxINT64Converter::SbxINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxINT64( b, this ); + return *this; +} +SbxINT64 &SbxINT64::operator &= ( const SbxINT64 &r ) +{ + nHigh &= r.nHigh; + nLow &= r.nLow; + return *this; +} +SbxINT64 &SbxINT64::operator |= ( const SbxINT64 &r ) +{ + nHigh |= r.nHigh; + nLow |= r.nLow; + return *this; +} +SbxINT64 &SbxINT64::operator ^= ( const SbxINT64 &r ) +{ + nHigh ^= r.nHigh; + nLow ^= r.nLow; + return *this; +} + +SbxINT64 operator - ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a(l); + a -= r; + return a; +} +SbxINT64 operator + ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a(l); + a += r; + return a; +} +SbxINT64 operator / ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a(l); + a /= r; + return a; +} +SbxINT64 operator % ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a(l); + a %= r; + return a; +} +SbxINT64 operator * ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a(l); + a *= r; + return a; +} +SbxINT64 operator & ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a; + a.nHigh = r.nHigh & l.nHigh; + a.nLow = r.nLow & l.nLow; + return a; +} +SbxINT64 operator | ( const SbxINT64 &l, const SbxINT64 &r ) +{ + SbxINT64 a; + a.nHigh = r.nHigh | l.nHigh; + a.nLow = r.nLow | l.nLow; + return a; +} +SbxINT64 operator ^ ( const SbxINT64 &r, const SbxINT64 &l ) +{ + SbxINT64 a; + a.nHigh = r.nHigh ^ l.nHigh; + a.nLow = r.nLow ^ l.nLow; + return a; +} + +SbxINT64 operator - ( const SbxINT64 &r ) +{ + SbxINT64 a( r ); + a.CHS(); + return a; +} +SbxINT64 operator ~ ( const SbxINT64 &r ) +{ + SbxINT64 a; + a.nHigh = ~r.nHigh; + a.nLow = ~r.nLow; + return a; +} + +SbxUINT64 &SbxUINT64::operator %= ( const SbxUINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxUINT64_2_BigInt( *this ) ); + b %= SbxINT64Converter::SbxUINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxUINT64( b, this ); + return *this; +} +SbxUINT64 &SbxUINT64::operator /= ( const SbxUINT64 &r ) +{ + BigInt b( SbxINT64Converter::SbxUINT64_2_BigInt( *this ) ); + b /= SbxINT64Converter::SbxUINT64_2_BigInt( r ); + SbxINT64Converter::BigInt_2_SbxUINT64( b, this ); + return *this; +} +/////////////////////////// Fehlerbehandlung ///////////////////////////// + +#ifdef _USED +// NOCH NACHZUBAUEN! + +// Das Default-Handling setzt nur den Fehlercode. + +#ifndef WNT +#if defined ( UNX ) +int matherr( struct exception* p ) +#else +int matherr( struct _exception* p ) +#endif +{ + switch( p->type ) + { +#if defined ( UNX ) + case OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break; +#else + case _OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break; +#endif + default: SbxBase::SetError( SbxERR_NOTIMP ); break; + } + return TRUE; +} +#endif + +#endif // _USED + + +///////////////////////////// Konstruktoren ////////////////////////////// + +SbxValue::SbxValue() : SbxBase() +{ + aData.eType = SbxEMPTY; +} + +SbxValue::SbxValue( SbxDataType t, void* p ) : SbxBase() +{ + int n = t & 0x0FFF; + if( p ) + n |= SbxBYREF; + if( n == SbxVARIANT ) + n = SbxEMPTY; + else + SetFlag( SBX_FIXED ); + if( p ) + switch( t & 0x0FFF ) + { + case SbxINTEGER: n |= SbxBYREF; aData.pInteger = (INT16*) p; break; + case SbxULONG64: n |= SbxBYREF; aData.pULong64 = (SbxUINT64*) p; break; + case SbxLONG64: + case SbxCURRENCY: n |= SbxBYREF; aData.pLong64 = (SbxINT64*) p; break; + case SbxLONG: n |= SbxBYREF; aData.pLong = (INT32*) p; break; + case SbxSINGLE: n |= SbxBYREF; aData.pSingle = (float*) p; break; + case SbxDATE: + case SbxDOUBLE: n |= SbxBYREF; aData.pDouble = (double*) p; break; + case SbxSTRING: n |= SbxBYREF; aData.pString = (XubString*) p; break; + case SbxERROR: + case SbxUSHORT: + case SbxBOOL: n |= SbxBYREF; aData.pUShort = (UINT16*) p; break; + case SbxULONG: n |= SbxBYREF; aData.pULong = (UINT32*) p; break; + case SbxCHAR: n |= SbxBYREF; aData.pChar = (xub_Unicode*) p; break; + case SbxBYTE: n |= SbxBYREF; aData.pByte = (BYTE*) p; break; + case SbxINT: n |= SbxBYREF; aData.pInt = (int*) p; break; + case SbxOBJECT: + aData.pObj = (SbxBase*) p; + if( p ) + aData.pObj->AddRef(); + break; + case SbxDECIMAL: + aData.pDecimal = (SbxDecimal*) p; + if( p ) + aData.pDecimal->addRef(); + break; + default: + DBG_ASSERT( !this, "Angabe eines Pointers unzulaessig" ); + n = SbxNULL; + } + else + memset( &aData, 0, sizeof( SbxValues ) ); + aData.eType = SbxDataType( n ); +} + +SbxValue::SbxValue( const SbxValue& r ) + : SvRefBase( r ), SbxBase( r ) +{ + if( !r.CanRead() ) + { + SetError( SbxERR_PROP_WRITEONLY ); + if( !IsFixed() ) + aData.eType = SbxNULL; + } + else + { + ((SbxValue*) &r)->Broadcast( SBX_HINT_DATAWANTED ); + aData = r.aData; + // Pointer kopieren, Referenzen inkrementieren + switch( aData.eType ) + { + case SbxSTRING: + if( aData.pString ) + aData.pString = new XubString( *aData.pString ); + break; + case SbxOBJECT: + if( aData.pObj ) + aData.pObj->AddRef(); + break; + case SbxDECIMAL: + if( aData.pDecimal ) + aData.pDecimal->addRef(); + break; + default: break; + } + } +} + +SbxValue& SbxValue::operator=( const SbxValue& r ) +{ + if( &r != this ) + { + if( !CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else + { + // Den Inhalt der Variablen auslesen + SbxValues aNew; + if( IsFixed() ) + // fest: dann muss der Typ stimmen + aNew.eType = aData.eType; + else if( r.IsFixed() ) + // Quelle fest: Typ uebernehmen + aNew.eType = SbxDataType( r.aData.eType & 0x0FFF ); + else + // beides Variant: dann isses egal + aNew.eType = SbxVARIANT; + if( r.Get( aNew ) ) + Put( aNew ); + } + } + return *this; +} + +SbxValue::~SbxValue() +{ +#ifndef C50 + Broadcast( SBX_HINT_DYING ); + SetFlag( SBX_WRITE ); + SbxValue::Clear(); +#else + // Provisorischer Fix fuer Solaris 5.0 Compiler Bug + // bei Nutzung virtueller Vererbung. Virtuelle Calls + // im Destruktor vermeiden. Statt Clear() zu rufen + // moegliche Objekt-Referenzen direkt freigeben. + if( aData.eType == SbxOBJECT ) + { + if( aData.pObj && aData.pObj != this ) + { + HACK(nicht bei Parent-Prop - sonst CyclicRef) + SbxVariable *pThisVar = PTR_CAST(SbxVariable, this); + BOOL bParentProp = pThisVar && 5345 == + ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) ); + if ( !bParentProp ) + aData.pObj->ReleaseRef(); + } + } + else if( aData.eType == SbxDECIMAL ) + { + releaseDecimalPtr( aData.pDecimal ); + } +#endif +} + +void SbxValue::Clear() +{ + switch( aData.eType ) + { + case SbxNULL: + case SbxEMPTY: + case SbxVOID: + break; + case SbxSTRING: + delete aData.pString; aData.pString = NULL; + break; + case SbxOBJECT: + if( aData.pObj ) + { + if( aData.pObj != this ) + { + HACK(nicht bei Parent-Prop - sonst CyclicRef) + SbxVariable *pThisVar = PTR_CAST(SbxVariable, this); + BOOL bParentProp = pThisVar && 5345 == + ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) ); + if ( !bParentProp ) + aData.pObj->ReleaseRef(); + } + aData.pObj = NULL; + } + break; + case SbxDECIMAL: + if( aData.eType == SbxDECIMAL ) + releaseDecimalPtr( aData.pDecimal ); + break; + case SbxDATAOBJECT: + aData.pData = NULL; break; + default: + { + SbxValues aEmpty; + memset( &aEmpty, 0, sizeof( SbxValues ) ); + aEmpty.eType = GetType(); + Put( aEmpty ); + } + } +} + +// Dummy + +void SbxValue::Broadcast( ULONG ) +{} + +//////////////////////////// Daten auslesen ////////////////////////////// + +// Ermitteln der "richtigen" Variablen. Falls es ein Objekt ist, wird +// entweder das Objekt selbst oder dessen Default-Property angesprochen. +// Falls die Variable eine Variable oder ein Objekt enthaelt, wird +// dieses angesprochen. + +SbxValue* SbxValue::TheRealValue() const +{ + return TheRealValue( TRUE ); +} + +// #55226 Zusaetzliche Info transportieren +SbxValue* SbxValue::TheRealValue( BOOL bObjInObjError ) const +{ + SbxValue* p = (SbxValue*) this; + for( ;; ) + { + SbxDataType t = SbxDataType( p->aData.eType & 0x0FFF ); + if( t == SbxOBJECT ) + { + // Der Block enthaelt ein Objekt oder eine Variable + SbxObject* pObj = PTR_CAST(SbxObject,p->aData.pObj); + if( pObj ) + { + // Hat das Objekt eine Default-Property? + SbxVariable* pDflt = pObj->GetDfltProperty(); + + // Falls dies ein Objekt ist und sich selbst enthaelt, + // koennen wir nicht darauf zugreifen + // #55226# Die alte Bedingung, um einen Fehler zu setzen, + // ist nicht richtig, da z.B. eine ganz normale Variant- + // Variable mit Objekt davon betroffen sein kann, wenn ein + // anderer Wert zugewiesen werden soll. Daher mit Flag. + if( bObjInObjError && !pDflt && + ((SbxValue*) pObj)->aData.eType == SbxOBJECT && + ((SbxValue*) pObj)->aData.pObj == pObj ) + { + SetError( SbxERR_BAD_PROP_VALUE ); + p = NULL; + } + else if( pDflt ) + p = pDflt; + /* ALT: + else + p = pDflt ? pDflt : (SbxVariable*) pObj; + */ + break; + } + // Haben wir ein Array? + SbxArray* pArray = PTR_CAST(SbxArray,p->aData.pObj); + if( pArray ) + { + // Ggf. Parameter holen + SbxArray* pPar = NULL; + SbxVariable* pVar = PTR_CAST(SbxVariable,p); + if( pVar ) + pPar = pVar->GetParameters(); + if( pPar ) + { + // Haben wir ein dimensioniertes Array? + SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,p->aData.pObj); + if( pDimArray ) + p = pDimArray->Get( pPar ); + else + p = pArray->Get( pPar->Get( 1 )->GetInteger() ); + break; + } + } + // Sonst einen SbxValue annehmen + SbxValue* pVal = PTR_CAST(SbxValue,p->aData.pObj); + if( pVal ) + p = pVal; + else + break; + } + else + break; + } + return p; +} + +BOOL SbxValue::Get( SbxValues& rRes ) const +{ + BOOL bRes = FALSE; + SbxError eOld = GetError(); + if( eOld != SbxERR_OK ) + ResetError(); + if( !CanRead() ) + { + SetError( SbxERR_PROP_WRITEONLY ); + rRes.pObj = NULL; + } + else + { + // Falls nach einem Objekt oder einem VARIANT gefragt wird, nicht + // die wahren Werte suchen + SbxValue* p = (SbxValue*) this; + if( rRes.eType != SbxOBJECT && rRes.eType != SbxVARIANT ) + p = TheRealValue(); + if( p ) + { + p->Broadcast( SBX_HINT_DATAWANTED ); + switch( rRes.eType ) + { + case SbxEMPTY: + case SbxVOID: + case SbxNULL: break; + case SbxVARIANT: rRes = p->aData; break; + case SbxINTEGER: rRes.nInteger = ImpGetInteger( &p->aData ); break; + case SbxLONG: rRes.nLong = ImpGetLong( &p->aData ); break; + case SbxSALINT64: rRes.nInt64 = ImpGetInt64( &p->aData ); break; + case SbxSALUINT64: rRes.uInt64 = ImpGetUInt64( &p->aData ); break; + case SbxSINGLE: rRes.nSingle = ImpGetSingle( &p->aData ); break; + case SbxDOUBLE: rRes.nDouble = ImpGetDouble( &p->aData ); break; + case SbxCURRENCY:rRes.nLong64 = ImpGetCurrency( &p->aData ); break; + case SbxDECIMAL: rRes.pDecimal = ImpGetDecimal( &p->aData ); break; + case SbxDATE: rRes.nDouble = ImpGetDate( &p->aData ); break; + case SbxBOOL: + rRes.nUShort = sal::static_int_cast< UINT16 >( + ImpGetBool( &p->aData ) ); + break; + case SbxCHAR: rRes.nChar = ImpGetChar( &p->aData ); break; + case SbxBYTE: rRes.nByte = ImpGetByte( &p->aData ); break; + case SbxUSHORT: rRes.nUShort = ImpGetUShort( &p->aData ); break; + case SbxULONG: rRes.nULong = ImpGetULong( &p->aData ); break; + case SbxLPSTR: + case SbxSTRING: p->aPic = ImpGetString( &p->aData ); + rRes.pString = &p->aPic; break; + case SbxCoreSTRING: p->aPic = ImpGetCoreString( &p->aData ); + rRes.pString = &p->aPic; break; + case SbxINT: +#if SAL_TYPES_SIZEOFINT == 2 + rRes.nInt = (int) ImpGetInteger( &p->aData ); +#else + rRes.nInt = (int) ImpGetLong( &p->aData ); +#endif + break; + case SbxUINT: +#if SAL_TYPES_SIZEOFINT == 2 + rRes.nUInt = (int) ImpGetUShort( &p->aData ); +#else + rRes.nUInt = (int) ImpGetULong( &p->aData ); +#endif + break; + case SbxOBJECT: + if( p->aData.eType == SbxOBJECT ) + rRes.pObj = p->aData.pObj; + else + { + SetError( SbxERR_NO_OBJECT ); + rRes.pObj = NULL; + } + break; + default: + if( p->aData.eType == rRes.eType ) + rRes = p->aData; + else + { + SetError( SbxERR_CONVERSION ); + rRes.pObj = NULL; + } + } + } + else + { + // Objekt enthielt sich selbst + SbxDataType eTemp = rRes.eType; + memset( &rRes, 0, sizeof( SbxValues ) ); + rRes.eType = eTemp; + } + } + if( !IsError() ) + { + bRes = TRUE; + if( eOld != SbxERR_OK ) + SetError( eOld ); + } + return bRes; +} + +const XubString& SbxValue::GetString() const +{ + SbxValues aRes; + aRes.eType = SbxSTRING; + if( Get( aRes ) ) + // Geht in Ordnung, da Ptr eine Kopie ist + return *aRes.pString; + else + { + ((SbxValue*) this)->aPic.Erase(); + return aPic; + } +} + +const XubString& SbxValue::GetCoreString() const +{ + SbxValues aRes; + aRes.eType = SbxCoreSTRING; + if( Get( aRes ) ) + // Geht in Ordnung, da Ptr eine Kopie ist + return *aRes.pString; + else + { + ((SbxValue*) this)->aPic.Erase(); + return aPic; + } +} + +BOOL SbxValue::GetBool() const +{ + SbxValues aRes; + aRes.eType = SbxBOOL; + Get( aRes ); + return BOOL( aRes.nUShort != 0 ); +} + +#define GET( g, e, t, m ) \ +t SbxValue::g() const { SbxValues aRes(e); Get( aRes ); return aRes.m; } + +GET( GetByte, SbxBYTE, BYTE, nByte ) +GET( GetChar, SbxCHAR, xub_Unicode, nChar ) +GET( GetCurrency, SbxCURRENCY, SbxINT64, nLong64 ) +GET( GetDate, SbxDATE, double, nDouble ) +GET( GetDouble, SbxDOUBLE, double, nDouble ) +GET( GetInteger, SbxINTEGER, INT16, nInteger ) +GET( GetLong, SbxLONG, INT32, nLong ) +GET( GetObject, SbxOBJECT, SbxBase*, pObj ) +GET( GetSingle, SbxSINGLE, float, nSingle ) +GET( GetULong, SbxULONG, UINT32, nULong ) +GET( GetUShort, SbxUSHORT, UINT16, nUShort ) +GET( GetInt64, SbxSALINT64, sal_Int64, nInt64 ) +GET( GetUInt64, SbxSALUINT64, sal_uInt64, uInt64 ) +#ifdef WNT +GET( GetDecimal, SbxDECIMAL, SbxDecimal*, pDecimal ) +#endif + +//////////////////////////// Daten schreiben ///////////////////////////// + +BOOL SbxValue::Put( const SbxValues& rVal ) +{ + BOOL bRes = FALSE; + SbxError eOld = GetError(); + if( eOld != SbxERR_OK ) + ResetError(); + if( !CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else if( rVal.eType & 0xF000 ) + SetError( SbxERR_NOTIMP ); + else + { + // Falls nach einem Objekt gefragt wird, nicht + // die wahren Werte suchen + SbxValue* p = this; + if( rVal.eType != SbxOBJECT ) + p = TheRealValue( FALSE ); // #55226 Hier keinen Fehler erlauben + if( p ) + { + if( !p->CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else if( p->IsFixed() || p->SetType( (SbxDataType) ( rVal.eType & 0x0FFF ) ) ) + switch( rVal.eType & 0x0FFF ) + { + case SbxEMPTY: + case SbxVOID: + case SbxNULL: break; + case SbxINTEGER: ImpPutInteger( &p->aData, rVal.nInteger ); break; + case SbxLONG: ImpPutLong( &p->aData, rVal.nLong ); break; + case SbxSALINT64: ImpPutInt64( &p->aData, rVal.nInt64 ); break; + case SbxSALUINT64: ImpPutUInt64( &p->aData, rVal.uInt64 ); break; + case SbxSINGLE: ImpPutSingle( &p->aData, rVal.nSingle ); break; + case SbxDOUBLE: ImpPutDouble( &p->aData, rVal.nDouble ); break; + case SbxCURRENCY: ImpPutCurrency( &p->aData, rVal.nLong64 ); break; + case SbxDECIMAL: ImpPutDecimal( &p->aData, rVal.pDecimal ); break; + case SbxDATE: ImpPutDate( &p->aData, rVal.nDouble ); break; + case SbxBOOL: ImpPutBool( &p->aData, rVal.nInteger ); break; + case SbxCHAR: ImpPutChar( &p->aData, rVal.nChar ); break; + case SbxBYTE: ImpPutByte( &p->aData, rVal.nByte ); break; + case SbxUSHORT: ImpPutUShort( &p->aData, rVal.nUShort ); break; + case SbxULONG: ImpPutULong( &p->aData, rVal.nULong ); break; + case SbxLPSTR: + case SbxSTRING: ImpPutString( &p->aData, rVal.pString ); break; + case SbxINT: +#if SAL_TYPES_SIZEOFINT == 2 + ImpPutInteger( &p->aData, (INT16) rVal.nInt ); +#else + ImpPutLong( &p->aData, (INT32) rVal.nInt ); +#endif + break; + case SbxUINT: +#if SAL_TYPES_SIZEOFINT == 2 + ImpPutUShort( &p->aData, (UINT16) rVal.nUInt ); +#else + ImpPutULong( &p->aData, (UINT32) rVal.nUInt ); +#endif + break; + case SbxOBJECT: + if( !p->IsFixed() || p->aData.eType == SbxOBJECT ) + { + // ist schon drin + if( p->aData.eType == SbxOBJECT && p->aData.pObj == rVal.pObj ) + break; + + // Nur den Werteteil loeschen! + p->SbxValue::Clear(); + + // eingentliche Zuweisung + p->aData.pObj = rVal.pObj; + + // ggf. Ref-Count mitzaehlen + if( p->aData.pObj && p->aData.pObj != p ) + { + if ( p != this ) + { + DBG_ERROR( "TheRealValue" ); + } + HACK(nicht bei Parent-Prop - sonst CyclicRef) + SbxVariable *pThisVar = PTR_CAST(SbxVariable, this); + BOOL bParentProp = pThisVar && 5345 == + ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) ); + if ( !bParentProp ) + p->aData.pObj->AddRef(); + } + } + else + SetError( SbxERR_CONVERSION ); + break; + default: + if( p->aData.eType == rVal.eType ) + p->aData = rVal; + else + { + SetError( SbxERR_CONVERSION ); + if( !p->IsFixed() ) + p->aData.eType = SbxNULL; + } + } + if( !IsError() ) + { + p->SetModified( TRUE ); + p->Broadcast( SBX_HINT_DATACHANGED ); + if( eOld != SbxERR_OK ) + SetError( eOld ); + bRes = TRUE; + } + } + } + return bRes; +} + +BOOL SbxValue::PutBool( BOOL b ) +{ + SbxValues aRes; + aRes.eType = SbxBOOL; + aRes.nUShort = sal::static_int_cast< UINT16 >(b ? SbxTRUE : SbxFALSE); + Put( aRes ); + return BOOL( !IsError() ); +} + +BOOL SbxValue::PutEmpty() +{ + BOOL bRet = SetType( SbxEMPTY ); + SetModified( TRUE ); + return bRet; +} + +BOOL SbxValue::PutString( const XubString& r ) +{ + SbxValues aRes; + aRes.eType = SbxSTRING; + aRes.pString = (XubString*) &r; + Put( aRes ); + return BOOL( !IsError() ); +} + +#define PUT( p, e, t, m ) \ +BOOL SbxValue::p( t n ) \ +{ SbxValues aRes(e); aRes.m = n; Put( aRes ); return BOOL( !IsError() ); } + +PUT( PutByte, SbxBYTE, BYTE, nByte ) +PUT( PutChar, SbxCHAR, xub_Unicode, nChar ) +PUT( PutCurrency, SbxCURRENCY, const SbxINT64&, nLong64 ) +PUT( PutDate, SbxDATE, double, nDouble ) +PUT( PutDouble, SbxDOUBLE, double, nDouble ) +PUT( PutInteger, SbxINTEGER, INT16, nInteger ) +PUT( PutLong, SbxLONG, INT32, nLong ) +PUT( PutObject, SbxOBJECT, SbxBase*, pObj ) +PUT( PutSingle, SbxSINGLE, float, nSingle ) +PUT( PutULong, SbxULONG, UINT32, nULong ) +PUT( PutUShort, SbxUSHORT, UINT16, nUShort ) +PUT( PutInt64, SbxSALINT64, sal_Int64, nInt64 ) +PUT( PutUInt64, SbxSALUINT64, sal_uInt64, uInt64 ) +#ifdef WNT +PUT( PutDecimal, SbxDECIMAL, SbxDecimal*, pDecimal ) +#endif + +////////////////////////// Setzen des Datentyps /////////////////////////// + +BOOL SbxValue::IsFixed() const +{ + return ( (GetFlags() & SBX_FIXED) | (aData.eType & SbxBYREF) ) != 0; +} + +// Eine Variable ist numerisch, wenn sie EMPTY oder wirklich numerisch ist +// oder einen vollstaendig konvertierbaren String enthaelt + +// #41692, fuer RTL und Basic-Core getrennt implementieren +BOOL SbxValue::IsNumeric() const +{ + return ImpIsNumeric( /*bOnlyIntntl*/FALSE ); +} + +BOOL SbxValue::ImpIsNumeric( BOOL bOnlyIntntl ) const +{ + + if( !CanRead() ) + { + SetError( SbxERR_PROP_WRITEONLY ); return FALSE; + } + // Downcast pruefen!!! + if( this->ISA(SbxVariable) ) + ((SbxVariable*)this)->Broadcast( SBX_HINT_DATAWANTED ); + SbxDataType t = GetType(); + if( t == SbxSTRING ) + { + if( aData.pString ) + { + XubString s( *aData.pString ); + double n; + SbxDataType t2; + USHORT nLen = 0; + if( ImpScan( s, n, t2, &nLen, /*bAllowIntntl*/FALSE, bOnlyIntntl ) == SbxERR_OK ) + return BOOL( nLen == s.Len() ); + } + return FALSE; + } + else + return BOOL( t == SbxEMPTY + || ( t >= SbxINTEGER && t <= SbxCURRENCY ) + || ( t >= SbxCHAR && t <= SbxUINT ) ); +} + +SbxClassType SbxValue::GetClass() const +{ + return SbxCLASS_VALUE; +} + +SbxDataType SbxValue::GetType() const +{ + return SbxDataType( aData.eType & 0x0FFF ); +} + +SbxDataType SbxValue::GetFullType() const +{ + return aData.eType; +} + +BOOL SbxValue::SetType( SbxDataType t ) +{ + DBG_ASSERT( !( t & 0xF000 ), "Setzen von BYREF|ARRAY verboten!" ); + if( ( t == SbxEMPTY && aData.eType == SbxVOID ) + || ( aData.eType == SbxEMPTY && t == SbxVOID ) ) + return TRUE; + if( ( t & 0x0FFF ) == SbxVARIANT ) + { + // Versuch, den Datentyp auf Variant zu setzen + ResetFlag( SBX_FIXED ); + if( IsFixed() ) + { + SetError( SbxERR_CONVERSION ); return FALSE; + } + t = SbxEMPTY; + } + if( ( t & 0x0FFF ) != ( aData.eType & 0x0FFF ) ) + { + if( !CanWrite() || IsFixed() ) + { + SetError( SbxERR_CONVERSION ); return FALSE; + } + else + { + // Eventuelle Objekte freigeben + switch( aData.eType ) + { + case SbxSTRING: + delete aData.pString; + break; + case SbxOBJECT: + if( aData.pObj && aData.pObj != this ) + { + HACK(nicht bei Parent-Prop - sonst CyclicRef) + SbxVariable *pThisVar = PTR_CAST(SbxVariable, this); + UINT16 nSlotId = pThisVar + ? ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) ) + : 0; + DBG_ASSERT( nSlotId != 5345 || pThisVar->GetName() == UniString::CreateFromAscii( "Parent" ), + "SID_PARENTOBJECT heisst nicht 'Parent'" ); + BOOL bParentProp = 5345 == nSlotId; + if ( !bParentProp ) + aData.pObj->ReleaseRef(); + } + break; + default: break; + } + // Das klappt immer, da auch die Float-Repraesentationen 0 sind. + memset( &aData, 0, sizeof( SbxValues ) ); + aData.eType = t; + } + } + return TRUE; +} + +BOOL SbxValue::Convert( SbxDataType eTo ) +{ + eTo = SbxDataType( eTo & 0x0FFF ); + if( ( aData.eType & 0x0FFF ) == eTo ) + return TRUE; + if( !CanWrite() ) + return FALSE; + if( eTo == SbxVARIANT ) + { + // Versuch, den Datentyp auf Variant zu setzen + ResetFlag( SBX_FIXED ); + if( IsFixed() ) + { + SetError( SbxERR_CONVERSION ); return FALSE; + } + else + return TRUE; + } + // Convert from Null geht niemals. Einmal Null, immer Null! + if( aData.eType == SbxNULL ) + { + SetError( SbxERR_CONVERSION ); return FALSE; + } + + // Konversion der Daten: + SbxValues aNew; + aNew.eType = eTo; + if( Get( aNew ) ) + { + // Der Datentyp konnte konvertiert werden. Bei Fixed-Elementen + // ist hier Ende, da die Daten nicht uebernommen zu werden brauchen + if( !IsFixed() ) + { + SetType( eTo ); + Put( aNew ); + SetModified( TRUE ); + } + Broadcast( SBX_HINT_CONVERTED ); + return TRUE; + } + else + return FALSE; +} +////////////////////////////////// Rechnen ///////////////////////////////// + +BOOL SbxValue::Compute( SbxOperator eOp, const SbxValue& rOp ) +{ + SbxDataType eThisType = GetType(); + SbxDataType eOpType = rOp.GetType(); + SbxError eOld = GetError(); + if( eOld != SbxERR_OK ) + ResetError(); + if( !CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else if( !rOp.CanRead() ) + SetError( SbxERR_PROP_WRITEONLY ); + // Sonderregel 1: Ist ein Operand Null, ist das Ergebnis Null + else if( eThisType == SbxNULL || eOpType == SbxNULL ) + SetType( SbxNULL ); + // Sonderregel 2: Ist ein Operand Empty, ist das Ergebnis der 2. Operand + else if( eThisType == SbxEMPTY ) + *this = rOp; + // 13.2.96: Nicht schon vor Get auf SbxEMPTY pruefen + else + { + SbxValues aL, aR; + bool bDecimal = false; + if( eThisType == SbxSTRING || eOp == SbxCAT ) + { + if( eOp == SbxCAT || eOp == SbxPLUS ) + { + // AB 5.11.1999, OUString beruecksichtigen + aL.eType = aR.eType = SbxSTRING; + rOp.Get( aR ); + // AB 8.12.1999, #70399: Hier wieder GetType() rufen, Get() kann Typ aendern! + if( rOp.GetType() == SbxEMPTY ) + goto Lbl_OpIsEmpty; + Get( aL ); + + // #30576: Erstmal testen, ob Wandlung geklappt hat + if( aL.pString != NULL && aR.pString != NULL ) + { + *aL.pString += *aR.pString; + } + // Nicht einmal Left OK? + else if( aL.pString == NULL ) + { + aL.pString = new String(); + } + Put( aL ); + } + else + SetError( SbxERR_CONVERSION ); + } + else if( eOpType == SbxSTRING && rOp.IsFixed() ) + { // Numerisch: rechts darf kein String stehen + SetError( SbxERR_CONVERSION ); + } + else if( ( eOp >= SbxIDIV && eOp <= SbxNOT ) || eOp == SbxMOD ) + { + if( GetType() == eOpType ) + { + if( GetType() == SbxULONG64 + || GetType() == SbxLONG64 + || GetType() == SbxCURRENCY + || GetType() == SbxULONG ) + aL.eType = aR.eType = GetType(); +// else if( GetType() == SbxDouble || GetType() == SbxSingle ) +// aL.eType = aR.eType = SbxLONG64; + else + aL.eType = aR.eType = SbxLONG; + } + else if( GetType() == SbxCURRENCY || eOpType == SbxCURRENCY + || GetType() == SbxULONG64 || eOpType == SbxULONG64 + || GetType() == SbxLONG64 || eOpType == SbxLONG64 ) + aL.eType = aR.eType = SbxLONG64; +// else if( GetType() == SbxDouble || rOP.GetType() == SbxDouble +// || GetType() == SbxSingle || rOP.GetType() == SbxSingle ) +// aL.eType = aR.eType = SbxLONG64; + else + aL.eType = aR.eType = SbxLONG; + + if( rOp.Get( aR ) ) + { + if( rOp.GetType() == SbxEMPTY ) + goto Lbl_OpIsEmpty; + if( Get( aL ) ) switch( eOp ) + { + case SbxIDIV: + if( aL.eType == SbxCURRENCY ) + aL.eType = SbxLONG64; + if( aL.eType == SbxLONG64 ) + if( !aR.nLong64 ) SetError( SbxERR_ZERODIV ); + else aL.nLong64 /= aR.nLong64; + else if( aL.eType == SbxULONG64 ) + if( !aR.nULong64 ) SetError( SbxERR_ZERODIV ); + else aL.nULong64 /= aR.nULong64; + else if( aL.eType == SbxLONG ) + if( !aR.nLong ) SetError( SbxERR_ZERODIV ); + else aL.nLong /= aR.nLong; + else + if( !aR.nULong ) SetError( SbxERR_ZERODIV ); + else aL.nULong /= aR.nULong; + break; + case SbxMOD: + if( aL.eType == SbxCURRENCY ) + aL.eType = SbxLONG64; + if( aL.eType == SbxLONG64 ) + if( !aR.nLong64 ) SetError( SbxERR_ZERODIV ); + else aL.nLong64 %= aR.nLong64; + else if( aL.eType == SbxULONG64 ) + if( !aR.nULong64 ) SetError( SbxERR_ZERODIV ); + else aL.nULong64 %= aR.nULong64; + else if( aL.eType == SbxLONG ) + if( !aR.nLong ) SetError( SbxERR_ZERODIV ); + else aL.nLong %= aR.nLong; + else + if( !aR.nULong ) SetError( SbxERR_ZERODIV ); + else aL.nULong %= aR.nULong; + break; + case SbxAND: + if( aL.eType != SbxLONG && aL.eType != SbxULONG ) + aL.nLong64 &= aR.nLong64; + else + aL.nLong &= aR.nLong; + break; + case SbxOR: + if( aL.eType != SbxLONG && aL.eType != SbxULONG ) + aL.nLong64 |= aR.nLong64; + else + aL.nLong |= aR.nLong; + break; + case SbxXOR: + if( aL.eType != SbxLONG && aL.eType != SbxULONG ) + aL.nLong64 ^= aR.nLong64; + else + aL.nLong ^= aR.nLong; + break; + case SbxEQV: + if( aL.eType != SbxLONG && aL.eType != SbxULONG ) + aL.nLong64 = (aL.nLong64 & aR.nLong64) | (~aL.nLong64 & ~aR.nLong64); + else + aL.nLong = (aL.nLong & aR.nLong) | (~aL.nLong & ~aR.nLong); + break; + case SbxIMP: + if( aL.eType != SbxLONG && aL.eType != SbxULONG ) + aL.nLong64 = ~aL.nLong64 | aR.nLong64; + else + aL.nLong = ~aL.nLong | aR.nLong; + break; + case SbxNOT: + if( aL.eType != SbxLONG && aL.eType != SbxULONG ) + aL.nLong64 = ~aL.nLong64; + else + aL.nLong = ~aL.nLong; + break; + default: break; + } + } + } + else if( ( GetType() == SbxDECIMAL || rOp.GetType() == SbxDECIMAL ) && + ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS || eOp == SbxNEG ) ) + { + aL.eType = aR.eType = SbxDECIMAL; + bDecimal = true; + if( rOp.Get( aR ) ) + { + if( rOp.GetType() == SbxEMPTY ) + { + releaseDecimalPtr( aL.pDecimal ); + goto Lbl_OpIsEmpty; + } + if( Get( aL ) ) + { + if( aL.pDecimal && aR.pDecimal ) + { + bool bOk = true; + switch( eOp ) + { + case SbxMUL: + bOk = ( *(aL.pDecimal) *= *(aR.pDecimal) ); + break; + case SbxDIV: + if( aR.pDecimal->isZero() ) + SetError( SbxERR_ZERODIV ); + else + bOk = ( *(aL.pDecimal) /= *(aR.pDecimal) ); + break; + case SbxPLUS: + bOk = ( *(aL.pDecimal) += *(aR.pDecimal) ); + break; + case SbxMINUS: + bOk = ( *(aL.pDecimal) -= *(aR.pDecimal) ); + break; + case SbxNEG: + bOk = ( aL.pDecimal->neg() ); + break; + default: + SetError( SbxERR_NOTIMP ); + } + if( !bOk ) + SetError( SbxERR_OVERFLOW ); + } + else + { + SetError( SbxERR_CONVERSION ); + } + } + } + } + else if( GetType() == SbxCURRENCY || rOp.GetType() == SbxCURRENCY ) + { + aL.eType = SbxCURRENCY; + aR.eType = SbxCURRENCY; + + if( rOp.Get( aR ) ) + { + static BigInt n10K( 10000 ); + + if( rOp.GetType() == SbxEMPTY ) + goto Lbl_OpIsEmpty; + + if( Get( aL ) ) switch( eOp ) + { + case SbxMUL: + { + // #i20704 Implement directly + BigInt b1( SbxINT64Converter::SbxINT64_2_BigInt( aL.nLong64 ) ); + BigInt b2( SbxINT64Converter::SbxINT64_2_BigInt( aR.nLong64 ) ); + b1 *= b2; + b1 /= n10K; + double d = double( b1 ) / 10000.0; + if( d > SbxMAXCURR || d < SbxMINCURR ) + SetError( SbxERR_OVERFLOW ); + else + SbxINT64Converter::BigInt_2_SbxINT64( b1, &aL.nLong64 ); + break; + } + case SbxDIV: + if( !aR.nLong64 ) + { + SetError( SbxERR_ZERODIV ); + } + else + { + // #i20704 Implement directly + BigInt b1( SbxINT64Converter::SbxINT64_2_BigInt( aL.nLong64 ) ); + BigInt b2( SbxINT64Converter::SbxINT64_2_BigInt( aR.nLong64 ) ); + b1 *= n10K; + b1 /= b2; + double d = double( b1 ) / 10000.0; + if( d > SbxMAXCURR || d < SbxMINCURR ) + SetError( SbxERR_OVERFLOW ); + else + SbxINT64Converter::BigInt_2_SbxINT64( b1, &aL.nLong64 ); + } + break; + case SbxPLUS: + aL.nLong64 += aR.nLong64; break; + case SbxMINUS: + aL.nLong64 -= aR.nLong64; break; + case SbxNEG: + aL.nLong64 = -aL.nLong64; break; + default: + SetError( SbxERR_NOTIMP ); + } + } + } + else + { // Andere Operatoren + aL.eType = aR.eType = SbxDOUBLE; + if( rOp.Get( aR ) ) + { + if( rOp.GetType() == SbxEMPTY ) + goto Lbl_OpIsEmpty; + if( Get( aL ) ) + { + switch( eOp ) + { + case SbxEXP: + aL.nDouble = pow( aL.nDouble, aR.nDouble ); + break; + case SbxMUL: + aL.nDouble *= aR.nDouble; break; + case SbxDIV: + if( !aR.nDouble ) SetError( SbxERR_ZERODIV ); + else aL.nDouble /= aR.nDouble; break; + case SbxPLUS: + aL.nDouble += aR.nDouble; break; + case SbxMINUS: + aL.nDouble -= aR.nDouble; break; + case SbxNEG: + aL.nDouble = -aL.nDouble; break; + default: + SetError( SbxERR_NOTIMP ); + } + + // #45465 Date braucht bei + eine Spezial-Behandlung + if( eOp == SbxPLUS && (GetType() == SbxDATE || rOp.GetType() == SbxDATE ) ) + aL.eType = SbxDATE; + } + } + + } + if( !IsError() ) + Put( aL ); + if( bDecimal ) + { + releaseDecimalPtr( aL.pDecimal ); + releaseDecimalPtr( aR.pDecimal ); + } + } +Lbl_OpIsEmpty: + + BOOL bRes = BOOL( !IsError() ); + if( bRes && eOld != SbxERR_OK ) + SetError( eOld ); + return bRes; +} + +// Die Vergleichs-Routine liefert TRUE oder FALSE. + +BOOL SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const +{ + BOOL bRes = FALSE; + SbxError eOld = GetError(); + if( eOld != SbxERR_OK ) + ResetError(); + if( !CanRead() || !rOp.CanRead() ) + SetError( SbxERR_PROP_WRITEONLY ); + else if( GetType() == SbxNULL && rOp.GetType() == SbxNULL ) + bRes = TRUE; + else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY ) + bRes = TRUE; + // Sonderregel 1: Ist ein Operand Null, ist das Ergebnis FALSE + else if( GetType() == SbxNULL || rOp.GetType() == SbxNULL ) + bRes = FALSE; + // Sonderregel 2: Wenn beide Variant sind und einer ist numerisch, + // und der andere ein String, ist num < str + else if( !IsFixed() && !rOp.IsFixed() + && ( rOp.GetType() == SbxSTRING && GetType() != SbxSTRING && IsNumeric() ) ) + bRes = BOOL( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE ); + else if( !IsFixed() && !rOp.IsFixed() + && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() ) ) + bRes = BOOL( eOp == SbxGT || eOp == SbxGE || eOp == SbxNE ); + else + { + SbxValues aL, aR; + // Wenn einer der Operanden ein String ist, + // findet ein Stringvergleich statt + if( GetType() == SbxSTRING || rOp.GetType() == SbxSTRING ) + { + aL.eType = aR.eType = SbxSTRING; + if( Get( aL ) && rOp.Get( aR ) ) switch( eOp ) + { + case SbxEQ: + bRes = BOOL( *aL.pString == *aR.pString ); break; + case SbxNE: + bRes = BOOL( *aL.pString != *aR.pString ); break; + case SbxLT: + bRes = BOOL( *aL.pString < *aR.pString ); break; + case SbxGT: + bRes = BOOL( *aL.pString > *aR.pString ); break; + case SbxLE: + bRes = BOOL( *aL.pString <= *aR.pString ); break; + case SbxGE: + bRes = BOOL( *aL.pString >= *aR.pString ); break; + default: + SetError( SbxERR_NOTIMP ); + } + } + // AB 19.12.95: Wenn SbxSINGLE beteiligt, auf SINGLE konvertieren, + // sonst gibt es numerische Fehler + else if( GetType() == SbxSINGLE || rOp.GetType() == SbxSINGLE ) + { + aL.eType = aR.eType = SbxSINGLE; + if( Get( aL ) && rOp.Get( aR ) ) + switch( eOp ) + { + case SbxEQ: + bRes = BOOL( aL.nSingle == aR.nSingle ); break; + case SbxNE: + bRes = BOOL( aL.nSingle != aR.nSingle ); break; + case SbxLT: + bRes = BOOL( aL.nSingle < aR.nSingle ); break; + case SbxGT: + bRes = BOOL( aL.nSingle > aR.nSingle ); break; + case SbxLE: + bRes = BOOL( aL.nSingle <= aR.nSingle ); break; + case SbxGE: + bRes = BOOL( aL.nSingle >= aR.nSingle ); break; + default: + SetError( SbxERR_NOTIMP ); + } + } + else if( GetType() == SbxDECIMAL && rOp.GetType() == SbxDECIMAL ) + { + aL.eType = aR.eType = SbxDECIMAL; + Get( aL ); + rOp.Get( aR ); + if( aL.pDecimal && aR.pDecimal ) + { + SbxDecimal::CmpResult eRes = compare( *aL.pDecimal, *aR.pDecimal ); + switch( eOp ) + { + case SbxEQ: + bRes = BOOL( eRes == SbxDecimal::EQ ); break; + case SbxNE: + bRes = BOOL( eRes != SbxDecimal::EQ ); break; + case SbxLT: + bRes = BOOL( eRes == SbxDecimal::LT ); break; + case SbxGT: + bRes = BOOL( eRes == SbxDecimal::GT ); break; + case SbxLE: + bRes = BOOL( eRes != SbxDecimal::GT ); break; + case SbxGE: + bRes = BOOL( eRes != SbxDecimal::LT ); break; + default: + SetError( SbxERR_NOTIMP ); + } + } + else + { + SetError( SbxERR_CONVERSION ); + } + releaseDecimalPtr( aL.pDecimal ); + releaseDecimalPtr( aR.pDecimal ); + } + // Alles andere auf SbxDOUBLE-Basis vergleichen + else + { + aL.eType = aR.eType = SbxDOUBLE; + if( Get( aL ) && rOp.Get( aR ) ) + switch( eOp ) + { + case SbxEQ: + bRes = BOOL( aL.nDouble == aR.nDouble ); break; + case SbxNE: + bRes = BOOL( aL.nDouble != aR.nDouble ); break; + case SbxLT: + bRes = BOOL( aL.nDouble < aR.nDouble ); break; + case SbxGT: + bRes = BOOL( aL.nDouble > aR.nDouble ); break; + case SbxLE: + bRes = BOOL( aL.nDouble <= aR.nDouble ); break; + case SbxGE: + bRes = BOOL( aL.nDouble >= aR.nDouble ); break; + default: + SetError( SbxERR_NOTIMP ); + } + } + } + if( eOld != SbxERR_OK ) + SetError( eOld ); + return bRes; +} + +///////////////////////////// Lesen/Schreiben //////////////////////////// + +BOOL SbxValue::LoadData( SvStream& r, USHORT ) +{ + SbxValue::Clear(); + UINT16 nType; + r >> nType; + aData.eType = SbxDataType( nType ); + switch( nType ) + { + case SbxBOOL: + case SbxINTEGER: + r >> aData.nInteger; break; + case SbxLONG: + r >> aData.nLong; break; + case SbxSINGLE: + { + // Floats als ASCII + XubString aVal; + r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US ); + double d; + SbxDataType t; + if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE ) + { + aData.nSingle = 0.0F; + return FALSE; + } + aData.nSingle = (float) d; + break; + } + case SbxDATE: + case SbxDOUBLE: + { + // Floats als ASCII + XubString aVal; + r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US ); + SbxDataType t; + if( ImpScan( aVal, aData.nDouble, t, NULL ) != SbxERR_OK ) + { + aData.nDouble = 0.0; + return FALSE; + } + break; + } + case SbxULONG64: + { + r >> aData.nULong64.nHigh >> aData.nULong64.nLow; + break; + } + case SbxLONG64: + case SbxCURRENCY: + { + r >> aData.nLong64.nHigh >> aData.nLong64.nLow; + break; + } + case SbxSTRING: + { + XubString aVal; + r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US ); + if( aVal.Len() ) + aData.pString = new XubString( aVal ); + else + aData.pString = NULL; // JSM 22.09.1995 + break; + } + case SbxERROR: + case SbxUSHORT: + r >> aData.nUShort; break; + case SbxOBJECT: + { + BYTE nMode; + r >> nMode; + switch( nMode ) + { + case 0: + aData.pObj = NULL; + break; + case 1: + aData.pObj = SbxBase::Load( r ); + return BOOL( aData.pObj != NULL ); + case 2: + aData.pObj = this; + break; + } + break; + } + case SbxCHAR: + { + char c; + r >> c; + aData.nChar = c; + break; + } + case SbxBYTE: + r >> aData.nByte; break; + case SbxULONG: + r >> aData.nULong; break; + case SbxINT: + { + BYTE n; + r >> n; + // Passt der Int auf diesem System? + if( n > SAL_TYPES_SIZEOFINT ) + r >> aData.nLong, aData.eType = SbxLONG; + else + r >> aData.nInt; + break; + } + case SbxUINT: + { + BYTE n; + r >> n; + // Passt der UInt auf diesem System? + if( n > SAL_TYPES_SIZEOFINT ) + r >> aData.nULong, aData.eType = SbxULONG; + else + r >> (sal_uInt32&)aData.nUInt; + break; + } + case SbxEMPTY: + case SbxNULL: + case SbxVOID: + break; + case SbxDATAOBJECT: + r >> aData.nLong; + break; + // #78919 For backwards compatibility + case SbxWSTRING: + case SbxWCHAR: + break; + default: + memset (&aData,0,sizeof(aData)); + ResetFlag(SBX_FIXED); + aData.eType = SbxNULL; + DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" ); + return FALSE; + } + return TRUE; +} + +BOOL SbxValue::StoreData( SvStream& r ) const +{ + UINT16 nType = sal::static_int_cast< UINT16 >(aData.eType); + r << nType; + switch( nType & 0x0FFF ) + { + case SbxBOOL: + case SbxINTEGER: + r << aData.nInteger; break; + case SbxLONG: + r << aData.nLong; break; + case SbxDATE: + // #49935: Als double speichern, sonst Fehler beim Einlesen + ((SbxValue*)this)->aData.eType = (SbxDataType)( ( nType & 0xF000 ) | SbxDOUBLE ); + r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US ); + ((SbxValue*)this)->aData.eType = (SbxDataType)nType; + break; + case SbxSINGLE: + case SbxDOUBLE: + r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US ); + break; + case SbxULONG64: + { + r << aData.nULong64.nHigh << aData.nULong64.nLow; + break; + } + case SbxLONG64: + case SbxCURRENCY: + { + r << aData.nLong64.nHigh << aData.nLong64.nLow; + break; + } + case SbxSTRING: + if( aData.pString ) + { + r.WriteByteString( *aData.pString, RTL_TEXTENCODING_ASCII_US ); + } + else + { + String aEmpty; + r.WriteByteString( aEmpty, RTL_TEXTENCODING_ASCII_US ); + } + break; + case SbxERROR: + case SbxUSHORT: + r << aData.nUShort; break; + case SbxOBJECT: + // sich selbst als Objektptr speichern geht nicht! + if( aData.pObj ) + { + if( PTR_CAST(SbxValue,aData.pObj) != this ) + { + r << (BYTE) 1; + return aData.pObj->Store( r ); + } + else + r << (BYTE) 2; + } + else + r << (BYTE) 0; + break; + case SbxCHAR: + { + char c = sal::static_int_cast< char >(aData.nChar); + r << c; + break; + } + case SbxBYTE: + r << aData.nByte; break; + case SbxULONG: + r << aData.nULong; break; + case SbxINT: + { + BYTE n = SAL_TYPES_SIZEOFINT; + r << n << (sal_Int32)aData.nInt; + break; + } + case SbxUINT: + { + BYTE n = SAL_TYPES_SIZEOFINT; + r << n << (sal_uInt32)aData.nUInt; + break; + } + case SbxEMPTY: + case SbxNULL: + case SbxVOID: + break; + case SbxDATAOBJECT: + r << aData.nLong; + break; + // #78919 For backwards compatibility + case SbxWSTRING: + case SbxWCHAR: + break; + default: + DBG_ASSERT( !this, "Speichern eines nicht unterstuetzten Datentyps" ); + return FALSE; + } + return TRUE; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/source/sbx/sbxvar.cxx b/binfilter/bf_basic/source/sbx/sbxvar.cxx new file mode 100644 index 000000000000..43c431ba847d --- /dev/null +++ b/binfilter/bf_basic/source/sbx/sbxvar.cxx @@ -0,0 +1,565 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include <tools/stream.hxx> +#include "bf_svtools/brdcst.hxx" + +#include "sbx.hxx" +#include "sbxbase.hxx" +#include "sbxres.hxx" +#include "sbxconv.hxx" +#include <math.h> +#include <ctype.h> + +namespace binfilter { + +///////////////////////////// SbxVariable ////////////////////////////// + +TYPEINIT1(SbxVariable,SbxValue) +TYPEINIT1(SbxHint,SfxSimpleHint) + +extern UINT32 nVarCreator; // in SBXBASE.CXX, fuer LoadData() +#ifdef DBG_UTIL +static ULONG nVar = 0; +#endif + +///////////////////////////// Konstruktoren ////////////////////////////// + +SbxVariable::SbxVariable() : SbxValue() +{ + pCst = NULL; + pParent = NULL; + nUserData = 0; + nHash = 0; +#ifdef DBG_UTIL + DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar ); + GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND ); +#endif +} + +SbxVariable::SbxVariable( const SbxVariable& r ) + : SvRefBase( r ), SbxValue( r ), mpPar( r.mpPar ), pInfo( r.pInfo ) +{ + pCst = NULL; + if( r.CanRead() ) + { + pParent = r.pParent; + nUserData = r.nUserData; + maName = r.maName; + nHash = r.nHash; + } + else + { + pParent = NULL; + nUserData = 0; + nHash = 0; + } +#ifdef DBG_UTIL + static sal_Char const aCellsStr[] = "Cells"; + if ( maName.EqualsAscii( aCellsStr ) ) + maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 ); + DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar ); + GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND ); +#endif +} + +SbxVariable::SbxVariable( SbxDataType t, void* p ) : SbxValue( t, p ) +{ + pCst = NULL; + pParent = NULL; + nUserData = 0; + nHash = 0; +#ifdef DBG_UTIL + DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar ); + GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND ); +#endif +} + +SbxVariable::~SbxVariable() +{ +#ifdef DBG_UTIL + ByteString aBStr( (const UniString&)maName, RTL_TEXTENCODING_ASCII_US ); + DbgOutf( "SbxVariable::Dtor %lx (%s)", (void*)this, aBStr.GetBuffer() ); + static sal_Char const aCellsStr[] = "Cells"; + if ( maName.EqualsAscii( aCellsStr ) ) + maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 ); + GetSbxData_Impl()->aVars.Remove( this ); +#endif + delete pCst; +} + +////////////////////////////// Broadcasting ////////////////////////////// + +SfxBroadcaster& SbxVariable::GetBroadcaster() +{ + if( !pCst ) + pCst = new SfxBroadcaster; + return *pCst; +} + +// Eines Tages kann man vielleicht den Parameter 0 schleifen, +// dann entfaellt die Kopiererei... + +void SbxVariable::Broadcast( ULONG nHintId ) +{ + if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() ) + { + // Da die Methode von aussen aufrufbar ist, hier noch einmal + // die Berechtigung testen + if( nHintId & SBX_HINT_DATAWANTED ) + if( !CanRead() ) + return; + if( nHintId & SBX_HINT_DATACHANGED ) + if( !CanWrite() ) + return; + // Weitere Broadcasts verhindern + SfxBroadcaster* pSave = pCst; + pCst = NULL; + USHORT nSaveFlags = GetFlags(); + SetFlag( SBX_READWRITE ); + if( mpPar.Is() ) + // this, als Element 0 eintragen, aber den Parent nicht umsetzen! + mpPar->GetRef( 0 ) = this; + pSave->Broadcast( SbxHint( nHintId, this ) ); + delete pCst; // wer weiss schon, auf welche Gedanken mancher kommt? + pCst = pSave; + SetFlags( nSaveFlags ); + } +} + +SbxInfo* SbxVariable::GetInfo() +{ + if( !pInfo ) + { + Broadcast( SBX_HINT_INFOWANTED ); + if( pInfo.Is() ) + SetModified( TRUE ); + } + return pInfo; +} + +void SbxVariable::SetParameters( SbxArray* p ) +{ + mpPar = p; +} + + +/////////////////////////// Name der Variablen /////////////////////////// + +void SbxVariable::SetName( const XubString& rName ) +{ + maName = rName; + nHash = MakeHashCode( rName ); +} + +const XubString& SbxVariable::GetName( SbxNameType t ) const +{ + static char cSuffixes[] = " %&!#@ $"; + if( t == SbxNAME_NONE ) + return maName; + // Parameter-Infos anfordern (nicht fuer Objekte) + ((SbxVariable*)this)->GetInfo(); + // Nix anfuegen, wenn einfache Property (keine leeren Klammern) + if( !pInfo + || ( !pInfo->aParams.Count() && GetClass() == SbxCLASS_PROPERTY ) ) + return maName; + xub_Unicode cType = ' '; + XubString aTmp( maName ); + // Kurzer Typ? Dann holen, evtl. ist dieser 0. + SbxDataType et = GetType(); + if( t == SbxNAME_SHORT_TYPES ) + { + if( et <= SbxSTRING ) + cType = cSuffixes[ et ]; + if( cType != ' ' ) + aTmp += cType; + } + aTmp += '('; + for( USHORT i = 0; i < pInfo->aParams.Count(); i++ ) + { + const SbxParamInfo* q = pInfo->aParams.GetObject( i ); + int nt = q->eType & 0x0FFF; + if( i ) + aTmp += ','; + if( q->nFlags & SBX_OPTIONAL ) + aTmp += SbxRes( STRING_OPTIONAL ); + if( q->eType & SbxBYREF ) + aTmp += SbxRes( STRING_BYREF ); + aTmp += q->aName; + cType = ' '; + // Kurzer Typ? Dann holen, evtl. ist dieser 0. + if( t == SbxNAME_SHORT_TYPES ) + { + if( nt <= SbxSTRING ) + cType = cSuffixes[ nt ]; + } + if( cType != ' ' ) + { + aTmp += cType; + if( q->eType & SbxARRAY ) + aTmp.AppendAscii( "()" ); + } + else + { + if( q->eType & SbxARRAY ) + aTmp.AppendAscii( "()" ); + // langer Typ? + if( t != SbxNAME_SHORT ) + { + aTmp += SbxRes( STRING_AS ); + if( nt < 32 ) + aTmp += SbxRes( + sal::static_int_cast< USHORT >( STRING_TYPES + nt ) ); + else + aTmp += SbxRes( STRING_ANY ); + } + } + } + aTmp += ')'; + // Langer Typ? Dann holen + if( t == SbxNAME_LONG_TYPES && et != SbxEMPTY ) + { + aTmp += SbxRes( STRING_AS ); + if( et < 32 ) + aTmp += SbxRes( + sal::static_int_cast< USHORT >( STRING_TYPES + et ) ); + else + aTmp += SbxRes( STRING_ANY ); + } + ((SbxVariable*) this)->aPic = aTmp; + return aPic; +} + +// Einen simplen Hashcode erzeugen: Es werden die ersten 6 Zeichen gewertet. + +USHORT SbxVariable::MakeHashCode( const XubString& rName ) +{ + USHORT n = 0; + USHORT nLen = rName.Len(); + if( nLen > 6 ) + nLen = 6; + const xub_Unicode* p = rName.GetBuffer(); + while( nLen-- ) + { + BYTE c = (BYTE)*p; + p++; + // Falls wir ein Schweinezeichen haben, abbrechen!! + if( c >= 0x80 ) + return 0; + n = sal::static_int_cast< USHORT >( ( n << 3 ) + toupper( c ) ); + } + return n; +} + +////////////////////////////// Operatoren //////////////////////////////// + +SbxVariable& SbxVariable::operator=( const SbxVariable& r ) +{ + SbxValue::operator=( r ); + return *this; +} + +//////////////////////////////// Konversion //////////////////////////////// + +SbxDataType SbxVariable::GetType() const +{ + if( aData.eType == SbxOBJECT ) + return aData.pObj ? aData.pObj->GetType() : SbxOBJECT; + else if( aData.eType == SbxVARIANT ) + return aData.pObj ? aData.pObj->GetType() : SbxVARIANT; + else + return aData.eType; +} + +SbxClassType SbxVariable::GetClass() const +{ + return SbxCLASS_VARIABLE; +} + +void SbxVariable::SetModified( BOOL b ) +{ + if( IsSet( SBX_NO_MODIFY ) ) + return; + SbxBase::SetModified( b ); + if( pParent && pParent != this ) //??? HotFix: Rekursion raus MM + pParent->SetModified( b ); +} + +void SbxVariable::SetParent( SbxObject* p ) +{ +#ifdef DBG_UTIL + // wird der Parent eines SbxObjects gesetzt? + if ( p && ISA(SbxObject) ) + { + // dann mu\s dieses auch Child vom neuen Parent sein + BOOL bFound = FALSE; + SbxArray *pChilds = p->GetObjects(); + if ( pChilds ) + { + for ( USHORT nIdx = 0; !bFound && nIdx < pChilds->Count(); ++nIdx ) + bFound = ( this == pChilds->Get(nIdx) ); + } + if ( !bFound ) + { + String aMsg = String::CreateFromAscii( "dangling: [" ); + aMsg += GetName(); + aMsg.AppendAscii( "].SetParent([" ); + aMsg += p->GetName(); + aMsg.AppendAscii( "])" ); + ByteString aBStr( (const UniString&)aMsg, RTL_TEXTENCODING_ASCII_US ); + DbgOut( aBStr.GetBuffer(), DBG_OUT_WARNING, __FILE__, __LINE__); + } + } +#endif + + pParent = p; +} + +////////////////////////////// Laden/Speichern ///////////////////////////// + +BOOL SbxVariable::LoadData( SvStream& rStrm, USHORT nVer ) +{ + UINT16 nType; + BYTE cMark; + rStrm >> cMark; + if( cMark == 0xFF ) + { + if( !SbxValue::LoadData( rStrm, nVer ) ) + return FALSE; + rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US ); + rStrm >> nUserData; + } + else + { + rStrm.SeekRel( -1L ); + rStrm >> nType; + rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US ); + rStrm >> nUserData; + // Korrektur: Alte Methoden haben statt SbxNULL jetzt SbxEMPTY + if( nType == SbxNULL && GetClass() == SbxCLASS_METHOD ) + nType = SbxEMPTY; + SbxValues aTmp; + XubString aVal; + aTmp.eType = aData.eType = (SbxDataType) nType; + aTmp.pString = &aVal; + switch( nType ) + { + case SbxBOOL: + case SbxERROR: + case SbxINTEGER: + rStrm >> aTmp.nInteger; break; + case SbxLONG: + rStrm >> aTmp.nLong; break; + case SbxSINGLE: + { + // Floats als ASCII + rStrm.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US ); + double d; + SbxDataType t; + if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE ) + { + aTmp.nSingle = 0; + return FALSE; + } + aTmp.nSingle = (float) d; + break; + } + case SbxDATE: + case SbxDOUBLE: + { + // Floats als ASCII + rStrm.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US ); + SbxDataType t; + if( ImpScan( aVal, aTmp.nDouble, t, NULL ) != SbxERR_OK ) + { + aTmp.nDouble = 0; + return FALSE; + } + break; + } + case SbxSTRING: + rStrm.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US ); + break; + case SbxEMPTY: + case SbxNULL: + break; + default: + aData.eType = SbxNULL; + DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" ); + return FALSE; + } + // Wert putten + if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) ) + return FALSE; + } + rStrm >> cMark; + // cMark ist auch eine Versionsnummer! + // 1: initial version + // 2: mit nUserData + if( cMark ) + { + if( cMark > 2 ) + return FALSE; + pInfo = new SbxInfo; + pInfo->LoadData( rStrm, (USHORT) cMark ); + } + // Privatdaten nur laden, wenn es eine SbxVariable ist + if( GetClass() == SbxCLASS_VARIABLE && !LoadPrivateData( rStrm, nVer ) ) + return FALSE; + ((SbxVariable*) this)->Broadcast( SBX_HINT_DATACHANGED ); + nHash = MakeHashCode( maName ); + SetModified( TRUE ); + return TRUE; +} + +BOOL SbxVariable::StoreData( SvStream& rStrm ) const +{ + rStrm << (BYTE) 0xFF; // Marker + BOOL bValStore; + if( this->IsA( TYPE(SbxMethod) ) ) + { + // #50200 Verhindern, dass Objekte, die zur Laufzeit als Return-Wert + // in der Methode als Value gespeichert sind, mit gespeichert werden + SbxVariable* pThis = (SbxVariable*)this; + USHORT nSaveFlags = GetFlags(); + pThis->SetFlag( SBX_WRITE ); + pThis->SbxValue::Clear(); + pThis->SetFlags( nSaveFlags ); + + // Damit die Methode in keinem Fall ausgefuehrt wird! + // CAST, um const zu umgehen! + pThis->SetFlag( SBX_NO_BROADCAST ); + bValStore = SbxValue::StoreData( rStrm ); + pThis->ResetFlag( SBX_NO_BROADCAST ); + } + else + bValStore = SbxValue::StoreData( rStrm ); + if( !bValStore ) + return FALSE; + // if( !SbxValue::StoreData( rStrm ) ) + // return FALSE; + rStrm.WriteByteString( maName, RTL_TEXTENCODING_ASCII_US ); + rStrm << nUserData; + if( pInfo.Is() ) + { + rStrm << (BYTE) 2; // Version 2: mit UserData! + pInfo->StoreData( rStrm ); + } + else + rStrm << (BYTE) 0; + // Privatdaten nur speichern, wenn es eine SbxVariable ist + if( GetClass() == SbxCLASS_VARIABLE ) + return StorePrivateData( rStrm ); + else + return TRUE; +} + +////////////////////////////// SbxInfo /////////////////////////////////// + +SbxInfo::SbxInfo() : aHelpFile(), nHelpId( 0 ), aParams() +{} + +////////////////////////////// SbxAlias ////////////////////////////////// + +SbxAlias::SbxAlias( const SbxAlias& r ) + : SvRefBase( r ), SbxVariable( r ), + SfxListener( r ), xAlias( r.xAlias ) +{} + +SbxAlias& SbxAlias::operator=( const SbxAlias& r ) +{ + xAlias = r.xAlias; + return *this; +} + +SbxAlias::~SbxAlias() +{ + if( xAlias.Is() ) + EndListening( xAlias->GetBroadcaster() ); +} + +void SbxAlias::Broadcast( ULONG nHt ) +{ + if( xAlias.Is() && StaticIsEnabledBroadcasting() ) + { + xAlias->SetParameters( GetParameters() ); + if( nHt == SBX_HINT_DATAWANTED ) + SbxVariable::operator=( *xAlias ); + else if( nHt == SBX_HINT_DATACHANGED || nHt == SBX_HINT_CONVERTED ) + *xAlias = *this; + else if( nHt == SBX_HINT_INFOWANTED ) + { + xAlias->Broadcast( nHt ); + pInfo = xAlias->GetInfo(); + } + } +} + +void SbxAlias::SFX_NOTIFY( SfxBroadcaster&, const TypeId&, + const SfxHint& rHint, const TypeId& ) +{ + const SbxHint* p = PTR_CAST(SbxHint,&rHint); + if( p && p->GetId() == SBX_HINT_DYING ) + { + xAlias.Clear(); + // Alias loeschen? + if( pParent ) + pParent->Remove( this ); + } +} + +void SbxVariable::Dump( SvStream& rStrm, BOOL bFill ) +{ + ByteString aBNameStr( (const UniString&)GetName( SbxNAME_SHORT_TYPES ), RTL_TEXTENCODING_ASCII_US ); + rStrm << "Variable( " + << ByteString::CreateFromInt64( (ULONG) this ).GetBuffer() << "==" + << aBNameStr.GetBuffer(); + ByteString aBParentNameStr( (const UniString&)GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US ); + if ( GetParent() ) + rStrm << " in parent '" << aBParentNameStr.GetBuffer() << "'"; + else + rStrm << " no parent"; + rStrm << " ) "; + + // bei Object-Vars auch das Object ausgeben + if ( GetValues_Impl().eType == SbxOBJECT && + GetValues_Impl().pObj && + GetValues_Impl().pObj != this && + GetValues_Impl().pObj != GetParent() ) + { + rStrm << " contains "; + ((SbxObject*) GetValues_Impl().pObj)->Dump( rStrm, bFill ); + } + else + rStrm << endl; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/binfilter/bf_basic/util/makefile.mk b/binfilter/bf_basic/util/makefile.mk new file mode 100644 index 000000000000..5c20d63dcd27 --- /dev/null +++ b/binfilter/bf_basic/util/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +BFPRJ=.. +PRJ=..$/.. + +PRJNAME=binfilter +TARGET=bf_sb + +# --- Settings --------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Allgemein --------------------------------------------------- + +LIB1TARGET=$(SLB)$/$(TARGET).lib +LIB1FILES= \ + $(SLB)$/basic_basicmgr.lib \ + $(SLB)$/basic_sbx.lib \ + $(SLB)$/basic_classes.lib \ + $(SLB)$/basic_comp.lib \ + $(SLB)$/basic_runtime.lib + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB=$(TARGET) + +SHL1STDLIBS= \ + $(TOOLSLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(BFSVTOOLLIB) \ + $(SALLIB) \ + $(COMPHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(SOTLIB) \ + $(VCLLIB) + +.IF "$(GUI)"=="WNT" +SHL1STDLIBS+= \ + $(UWINAPILIB) \ + $(OLEAUT32LIB) +.ENDIF # WNT + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1LIBS= $(SLB)$/$(TARGET).lib + +DEF1NAME =$(SHL1TARGET) +DEF1DEPN = \ + $(MISC)$/$(SHL1TARGET).flt + +DEFLIB1NAME =$(TARGET) + +# --- Targets ----------------------------------------------------------- + +.INCLUDE : target.mk + +# --- Basic-Filter-Datei --- + +$(MISC)$/$(SHL1TARGET).flt: makefile.mk + @echo ------------------------------ + @echo Making: $@ + @echo __CT >> $@ + + |