diff options
Diffstat (limited to 'basic/source')
157 files changed, 75054 insertions, 0 deletions
diff --git a/basic/source/app/app.cxx b/basic/source/app/app.cxx new file mode 100644 index 000000000000..4743b8c0ddca --- /dev/null +++ b/basic/source/app/app.cxx @@ -0,0 +1,1995 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: app.cxx,v $ + * $Revision: 1.79.14.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <tools/fsys.hxx> +#ifndef _SV_FILEDLG_HXX //autogen +#include <svtools/filedlg.hxx> +#endif +#include <tools/config.hxx> + +#include <vcl/font.hxx> + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif +#include <basic/sbx.hxx> +#include <svtools/filedlg.hxx> + +#include <osl/module.h> + +#include "basic.hrc" +#include "app.hxx" +#include "printer.hxx" +#include "status.hxx" +#include "appedit.hxx" +#include "appbased.hxx" +#include "apperror.hxx" +#include <basic/mybasic.hxx> +#include "ttbasic.hxx" +#include "dialogs.hxx" +#include <basic/basrdll.hxx> +#include "basrid.hxx" + +#ifndef _RUNTIME_HXX +#include "runtime.hxx" +#endif +#include "sbintern.hxx" + +#ifdef _USE_UNO +#include <ucbhelper/contentbroker.hxx> +#include <ucbhelper/configurationkeys.hxx> +#include <comphelper/regpathhelper.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> + +#include <ucbhelper/content.hxx> +#include <svtools/syslocale.hxx> + +using namespace comphelper; +using namespace cppu; +using namespace rtl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::beans; + +#endif /* _USE_UNO */ + +IMPL_GEN_RES_STR; + +#ifdef DBG_UTIL +// filter Messages generated due to missing configuration Bug:#83887# +void TestToolDebugMessageFilter( const sal_Char *pString, BOOL bIsOsl ) +{ + static BOOL static_bInsideFilter = FALSE; + + // Ignore messages during filtering to avoid endless recursions + if ( static_bInsideFilter ) + return; + + static_bInsideFilter = TRUE; + + ByteString aMessage( pString ); + + BOOL bIgnore = FALSE; + + if ( bIsOsl ) + { + // OSL + if ( aMessage.Search( CByteString("Cannot open Configuration: Connector: unknown delegatee com.sun.star.connection.Connector.portal") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + } + else + { + // DBG +#if ! (OSL_DEBUG_LEVEL > 1) + if ( aMessage.Search( CByteString("SelectAppIconPixmap") ) != STRING_NOTFOUND ) + bIgnore = TRUE; +#endif + if ( aMessage.Search( CByteString("PropertySetRegistry::") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + if ( aMessage.Search( CByteString("property value missing") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + if ( aMessage.Search( CByteString("getDateFormatsImpl") ) != STRING_NOTFOUND + && aMessage.Search( CByteString("no date formats") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + if ( aMessage.Search( CByteString("ucb::configureUcb(): Bad arguments") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + if ( aMessage.Search( CByteString("CreateInstance with arguments exception") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + if ( aMessage.Search( CByteString("AcquireTree failed") ) != STRING_NOTFOUND ) + bIgnore = TRUE; + } + + + if ( bIgnore ) + { + static_bInsideFilter = FALSE; + return; + } + + if ( bIsOsl ) + { + // due to issue #i36895 only print on console + // unfortunately the osl assertions deadlock by design :-( on recursive calls of assertions + printf("%s\n", pString ); + } + else + { + try + { + aBasicApp.DbgPrintMsgBox( pString ); + } + catch ( ... ) + + { + printf("DbgPrintMsgBox failed: %s\n", pString ); + } + } +/* DBG_INSTOUTERROR( DBG_OUT_MSGBOX ) + DBG_ERROR( pString ); + DBG_INSTOUTERROR( DBG_OUT_TESTTOOL )*/ + static_bInsideFilter = FALSE; +} +void SAL_CALL DBG_TestToolDebugMessageFilter( const sal_Char *pString ) +{ + TestToolDebugMessageFilter( pString, FALSE ); +} +extern "C" void SAL_CALL osl_TestToolDebugMessageFilter( const sal_Char *pString ) +{ + if ( !getenv( "DISABLE_SAL_DBGBOX" ) ) + TestToolDebugMessageFilter( pString, TRUE ); +} +#endif + +// #94145# Due to a tab in TT_SIGNATURE_FOR_UNICODE_TEXTFILES which is changed to blanks by some editors +// this routine became necessary +BOOL IsTTSignatureForUnicodeTextfile( String aLine ) +{ + aLine.SearchAndReplace( '\t', ' ' ); + String ThreeBlanks = CUniString(" "); + String TwoBlanks = CUniString(" "); + while ( aLine.SearchAndReplace( ThreeBlanks, TwoBlanks ) != STRING_NOTFOUND ) + {} + return aLine.EqualsAscii( TT_SIGNATURE_FOR_UNICODE_TEXTFILES ); +} + +BasicApp aBasicApp; // Application instance + +static const char * const components[] = +{ + SAL_MODULENAME( "ucb1" ) // KSO, ABI + , SAL_MODULENAME( "ucpfile1" ) + , "configmgr2.uno" SAL_DLLEXTENSION + , "sax.uno" SAL_DLLEXTENSION + , "stocservices.uno" SAL_DLLEXTENSION + , SAL_MODULENAME( "fileacc" ) + , SAL_MODULENAME( "mcnttype" ) // Clipboard Ask Oliver Braun + , "i18npool.uno" SAL_DLLEXTENSION + // Reading of files in specific encodings like UTF-8 using + // createUnoService( "com.sun.star.io.TextInputStream" ) and such + , "textinstream.uno" SAL_DLLEXTENSION + , "textoutstream.uno" SAL_DLLEXTENSION + , "introspection.uno" SAL_DLLEXTENSION + , "reflection.uno" SAL_DLLEXTENSION + // RemoteUno + , "connector.uno" SAL_DLLEXTENSION + , "bridgefac.uno" SAL_DLLEXTENSION + , "remotebridge.uno" SAL_DLLEXTENSION +#ifdef SAL_UNX +#ifdef QUARTZ + , SVLIBRARY( "dtransaqua" ) // Mac OS X Aqua uses a dedicated libdtransaqua +#else + , SVLIBRARY( "dtransX11" ) // OBR +#endif +#endif +#ifdef SAL_W32 + , SAL_MODULENAME( "sysdtrans" ) + , SAL_MODULENAME( "ftransl" ) + , SAL_MODULENAME( "dnd" ) +#endif + , 0 +}; + +uno::Reference< XContentProviderManager > InitializeUCB( void ) +{ + uno::Reference< XMultiServiceFactory > xSMgr; + try + { + xSMgr = uno::Reference< XMultiServiceFactory >( + defaultBootstrap_InitialComponentContext()->getServiceManager(), + UNO_QUERY_THROW); + } + catch( com::sun::star::uno::Exception & exc ) + { + fprintf( stderr, "Couldn't bootstrap uno servicemanager for reason : %s\n" , + OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + InfoBox( NULL, String( exc.Message ) ).Execute(); + throw ; + } + + + ////////////////////////////////////////////////////////////////////// + // set global factory + setProcessServiceFactory( xSMgr ); + +/* // Create simple ConfigManager + Sequence< Any > aConfArgs(3); + aConfArgs[0] <<= PropertyValue( OUString::createFromAscii("servertype"), 0, makeAny( OUString::createFromAscii("local") ), ::com::sun::star::beans::PropertyState_DIRECT_VALUE ); + aConfArgs[1] <<= PropertyValue( OUString::createFromAscii("sourcepath"), 0, makeAny( OUString::createFromAscii("g:\\") ), ::com::sun::star::beans::PropertyState_DIRECT_VALUE ); + aConfArgs[2] <<= PropertyValue( OUString::createFromAscii("updatepath"), 0, makeAny( OUString::createFromAscii("g:\\") ), ::com::sun::star::beans::PropertyState_DIRECT_VALUE ); + + uno::Reference< XContentProvider > xConfProvider + ( xSMgr->createInstanceWithArguments( OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ), aConfArgs), UNO_QUERY ); +*/ + + +// Create unconfigured Ucb: +/* Sequence< Any > aArgs(1); + aArgs[1] = makeAny ( xConfProvider );*/ + Sequence< Any > aArgs; + ::ucbhelper::ContentBroker::initialize( xSMgr, aArgs ); + uno::Reference< XContentProviderManager > xUcb = + ::ucbhelper::ContentBroker::get()->getContentProviderManagerInterface(); + + uno::Reference< XContentProvider > xFileProvider + ( xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ) ), UNO_QUERY ); + xUcb->registerContentProvider( xFileProvider, OUString::createFromAscii( "file" ), sal_True ); + + +/* uno::Reference< XContentProvider > xPackageProvider + ( xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.ucb.PackageContentProvider" ) ), UNO_QUERY ); + xUcb->registerContentProvider( xPackageProvider, OUString::createFromAscii( "vnd.sun.star.pkg" ), sal_True ); + */ + + return xUcb; +} + +static void ReplaceStringHookProc( UniString& rStr ) +{ + static String aTestToolName( RTL_CONSTASCII_USTRINGPARAM( "VCLTestTool" ) ); // HACK, should be read from ressources + + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + { + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", aTestToolName ); + /* + rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion ); + rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATNAME", rXMLFileFormatName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATVERSION", rXMLFileFormatVersion ); + */ + } +} + +void BasicApp::Main( ) +{ +#ifdef DBG_UTIL +// Install filter for OSLAsserts + DbgPrintMsgBox = DbgGetPrintMsgBox(); + DbgSetPrintTestTool( DBG_TestToolDebugMessageFilter ); + DBG_INSTOUTERROR( DBG_OUT_TESTTOOL ); + + if ( osl_setDebugMessageFunc( osl_TestToolDebugMessageFilter ) ) + DBG_ERROR("osl_setDebugMessageFunc returns non NULL pointer"); +#endif + + ResMgr::SetReadStringHook( ReplaceStringHookProc ); + + try + { +#ifdef _USE_UNO + uno::Reference< XContentProviderManager > xUcb = InitializeUCB(); +#endif + + { + DirEntry aIniPath( Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") ) ); + if ( !aIniPath.Exists() ) + { // look for it besides the executable + DirEntry aAppFileName( GetAppFileName() ); + String aAppDir ( aAppFileName.GetPath().GetFull() ); + +// DirEntry aDefIniPath( Config::GetConfigName( aAppDir, CUniString("testtool") ) ); +// Do not use Config::GetConfigName here because is uses a hidden file for UNIX + + DirEntry aDefIniPath( aAppDir ); + ByteString aFileName; +#ifdef UNX + aFileName = "testtoolrc"; +#else + aFileName = "testtool.ini"; +#endif + aDefIniPath += DirEntry( aFileName ); + + if ( aDefIniPath.Exists() ) + { + aDefIniPath.CopyTo( aIniPath, FSYS_ACTION_COPYFILE ); + FileStat::SetReadOnlyFlag( aIniPath, FALSE ); + } + } + } + + { + LanguageType aRequestedLanguage; + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + + // 1033 = LANGUAGE_ENGLISH_US + // 1031 = LANGUAGE_GERMAN + aConf.SetGroup("Misc"); + ByteString aLang = aConf.ReadKey( "Language", ByteString::CreateFromInt32( LANGUAGE_SYSTEM ) ); + aRequestedLanguage = LanguageType( aLang.ToInt32() ); + + AllSettings aSettings = GetSettings(); + aSettings.SetUILanguage( aRequestedLanguage ); + aSettings.SetLanguage( aRequestedLanguage ); +// International aInternational; +// aInternational = GetSettings().GetInternational(); +// aInternational = International( aRequestedLanguage ); +// aSettings.SetInternational( aInternational ); + SetSettings( aSettings ); +// aInternational = GetSettings().GetInternational(); + } + +// ResMgr::CreateResMgr( CREATEVERSIONRESMGR( stt ), ) +//const char* ResMgr::GetLang( LanguageType& nType, USHORT nPrio ) + +// ResMgr::CreateResMgr( CREATEVERSIONRESMGR( stt ) +// ResMgr *pRes = new ResMgr( "testtool.res" ); +// Resource::SetResManager( pRes ); + + BasicDLL aBasicDLL; + nWait = 0; + + // Hilfe: +// pHelp = new Help; +// SetHelp( pHelp ); +// Help::EnableContextHelp(); +// Help::EnableExtHelp(); +// DeactivateExtHelp(); + + // Acceleratoren + Accelerator aAccel( SttResId( MAIN_ACCEL ) ); + InsertAccel( &aAccel ); + pMainAccel = &aAccel; + + // Frame Window: + pFrame = new BasicFrame; + aAccel.SetSelectHdl( LINK( pFrame, BasicFrame, Accel ) ); + + pFrame->Show(); + + SetSystemWindowMode( SYSTEMWINDOW_MODE_NOAUTOMODE ); + SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG ); + + // Instantiate a SvtSysLocale to avoid permant instatiation + // and deletion of SvtSysLocale_Impl in SvtSysLocale Ctor/Dtor + // because in the testtool szenario Basic is the only instance + // instatiating SvtSysLocale (#107417). + SvtSysLocale aSysLocale; + + PostUserEvent( LINK( this, BasicApp, LateInit ) ); + Execute(); + +// delete pHelp; + delete pFrame; + + RemoveAccel( pMainAccel ); + + } + catch( class Exception & rEx) + { + printf( "Exception not caught: %s\n", ByteString( String(rEx.Message), RTL_TEXTENCODING_ASCII_US ).GetBuffer() ); + String aMsg( String::CreateFromAscii( "Exception not caught: " ) ); + aMsg.Append( String( rEx.Message ) ); + InfoBox( NULL, aMsg ).Execute(); + throw; + } + catch( ... ) + { + printf( "unknown Exception not caught\n" ); + InfoBox( NULL, String::CreateFromAscii( "unknown Exception not caught" ) ).Execute(); + throw; + } +} + +void BasicApp::LoadIniFile() +{ + pFrame->LoadIniFile(); +} + +void BasicApp::SetFocus() +{ + if( pFrame->pWork && pFrame->pWork->ISA(AppEdit) ) + ((AppEdit*)pFrame->pWork)->pDataEdit->GrabFocus(); +} + +IMPL_LINK( BasicApp, LateInit, void *, pDummy ) +{ + (void) pDummy; /* avoid warning about unused parameter */ + USHORT i; + for ( i = 0 ; i < Application::GetCommandLineParamCount() ; i++ ) + { + if ( Application::GetCommandLineParam( i ).Copy(0,4).CompareIgnoreCaseToAscii("-run") == COMPARE_EQUAL +#ifndef UNX + || Application::GetCommandLineParam( i ).Copy(0,4).CompareIgnoreCaseToAscii("/run") == COMPARE_EQUAL +#endif + ) + pFrame->SetAutoRun( TRUE ); + else if ( Application::GetCommandLineParam( i ).Copy(0,7).CompareIgnoreCaseToAscii("-result") == COMPARE_EQUAL +#ifndef UNX + || Application::GetCommandLineParam( i ).Copy(0,7).CompareIgnoreCaseToAscii("/result") == COMPARE_EQUAL +#endif + ) + { + if ( (i+1) < Application::GetCommandLineParamCount() ) + { + if ( ByteString( Application::GetCommandLineParam( i+1 ), osl_getThreadTextEncoding() ).IsNumericAscii() ) + { + MsgEdit::SetMaxLogLen( sal::static_int_cast< USHORT >( Application::GetCommandLineParam( i+1 ).ToInt32() ) ); + } + i++; + } + } + } + + // now load the files after the switches have been set. Espechially -run is of interest sunce it changes the behavior + for ( i = 0 ; i < Application::GetCommandLineParamCount() ; i++ ) + { + if ( Application::GetCommandLineParam( i ).Copy(0,1).CompareToAscii("-") != COMPARE_EQUAL +#ifndef UNX + && Application::GetCommandLineParam( i ).Copy(0,1).CompareToAscii("/") != COMPARE_EQUAL +#endif + ) + { + pFrame->LoadFile( Application::GetCommandLineParam( i ) ); + } + else if ( Application::GetCommandLineParam( i ).Copy(0,7).CompareIgnoreCaseToAscii("-result") == COMPARE_EQUAL +#ifndef UNX + || Application::GetCommandLineParam( i ).Copy(0,7).CompareIgnoreCaseToAscii("/result") == COMPARE_EQUAL +#endif + ) + { // Increment count to skip the parameter. This works even if it is not given + i++; + } + } + + pFrame->pStatus->SetStatusSize( pFrame->pStatus->GetStatusSize()+1 ); + pFrame->pStatus->SetStatusSize( pFrame->pStatus->GetStatusSize()-1 ); + + if ( pFrame->IsAutoRun() ) + { + pFrame->Command( RID_RUNSTART ); + } + + if ( pFrame->IsAutoRun() ) + pFrame->Command( RID_QUIT ); + + return 0; +} + +////////////////////////////////////////////////////////////////////////// + +class FloatingExecutionStatus : public FloatingWindow +{ +public: + FloatingExecutionStatus( Window * pParent ); + void SetStatus( String aW ); + void SetAdditionalInfo( String aF ); + +private: + Timer aAusblend; + DECL_LINK(HideNow, FloatingExecutionStatus* ); + FixedText aStatus; + FixedText aAdditionalInfo; +}; + + +FloatingExecutionStatus::FloatingExecutionStatus( Window * pParent ) + : FloatingWindow( pParent, SttResId(LOAD_CONF) ), + aStatus( this, SttResId( WORK ) ), + aAdditionalInfo( this, SttResId( FILENAME ) ) +{ + FreeResource(); + aAusblend.SetTimeoutHdl( LINK(this, FloatingExecutionStatus, HideNow ) ); + aAusblend.SetTimeout(5000); // in ms + aAusblend.Start(); +} + +void FloatingExecutionStatus::SetStatus( String aW ) +{ + Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE ); + ToTop( TOTOP_NOGRABFOCUS ); + aAusblend.Start(); + aStatus.SetText( aW ); +} + +void FloatingExecutionStatus::SetAdditionalInfo( String aF ) +{ + Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE ); + ToTop( TOTOP_NOGRABFOCUS ); + aAusblend.Start(); + aAdditionalInfo.SetText( aF ); +} + +IMPL_LINK(FloatingExecutionStatus, HideNow, FloatingExecutionStatus*, pFLC ) +{ + (void) pFLC; /* avoid warning about unused parameter */ + Hide(); + return 0; +} + +////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(TTExecutionStatusHint, SfxSimpleHint); + +BasicFrame::BasicFrame() : WorkWindow( NULL, + WinBits( WB_APP | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ) +, bIsAutoRun( FALSE ) +, pDisplayHidDlg( NULL ) +, pEditVar ( 0 ) +, bAutoReload( FALSE ) +, bAutoSave( TRUE ) +, pBasic( NULL ) +, pExecutionStatus( NULL ) +, pStatus( NULL ) +, pList( NULL ) +, pWork( NULL ) +, pPrn( NULL ) +{ + + Application::SetDefDialogParent( this ); + AlwaysEnableInput( TRUE ); + pBasic = TTBasic::CreateMyBasic(); // depending on what was linked to the executable + bInBreak = FALSE; + bDisas = FALSE; + nFlags = 0; +// Icon aAppIcon; + + if ( pBasic->pTestObject ) // Are we the testtool? + { +// aAppIcon = Icon( ResId( RID_APPICON2 ) ); + aAppName = String( SttResId( IDS_APPNAME2 ) ); + } + else + { +// aAppIcon = Icon( ResId( RID_APPICON ) ); + aAppName = String( SttResId( IDS_APPNAME ) ); + } + + // Menu: + MenuBar *pBar = new MenuBar( SttResId( RID_APPMENUBAR ) ); + SetMenuBar( pBar ); + + pBar->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + + + // Menu Handler: + PopupMenu* pFileMenu = pBar->GetPopupMenu( RID_APPFILE ); + pFileMenu->SetSelectHdl( LINK( this, BasicFrame, MenuCommand ) ); + pFileMenu->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + pFileMenu->SetActivateHdl( LINK( this, BasicFrame, InitMenu ) ); + pFileMenu->SetDeactivateHdl( LINK( this, BasicFrame, DeInitMenu ) ); + if (Basic().pTestObject ) // Are we TestTool? + { + pFileMenu->RemoveItem( pFileMenu->GetItemPos( RID_FILELOADLIB ) -1 ); // Separator before + pFileMenu->RemoveItem( pFileMenu->GetItemPos( RID_FILELOADLIB ) ); + pFileMenu->RemoveItem( pFileMenu->GetItemPos( RID_FILESAVELIB ) ); + } + + PopupMenu* pEditMenu = pBar->GetPopupMenu( RID_APPEDIT ); + pEditMenu->SetSelectHdl( LINK( this, BasicFrame, MenuCommand ) ); + pEditMenu->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + pEditMenu->SetActivateHdl( LINK( this, BasicFrame, InitMenu ) ); + pEditMenu->SetDeactivateHdl( LINK( this, BasicFrame, DeInitMenu ) ); + PopupMenu* pRunMenu = pBar->GetPopupMenu( RID_APPRUN ); + pRunMenu->SetSelectHdl( LINK( this, BasicFrame, MenuCommand ) ); + pRunMenu->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + pRunMenu->SetActivateHdl( LINK( this, BasicFrame, InitMenu ) ); + pRunMenu->SetDeactivateHdl( LINK( this, BasicFrame, DeInitMenu ) ); + if (Basic().pTestObject ) // Are we TestTool? + { + pRunMenu->RemoveItem( pRunMenu->GetItemPos( RID_RUNDISAS ) ); + pRunMenu->RemoveItem( pRunMenu->GetItemPos( RID_RUNCOMPILE ) ); + } + + PopupMenu *pExtras; + if (Basic().pTestObject ) // Are we TestTool? + { + pExtras = new PopupMenu( SttResId( RID_TT_EXTRAS ) ); + pBar->InsertItem( RID_TT_EXTRAS, String( SttResId( RID_TT_EXTRAS_NAME ) ), 0, pBar->GetItemPos( RID_APPWINDOW ) ); + pBar->SetPopupMenu( RID_TT_EXTRAS, pExtras ); + + pExtras->SetSelectHdl( LINK( this, BasicFrame, MenuCommand ) ); + pExtras->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + pExtras->SetDeactivateHdl( LINK( this, BasicFrame, DeInitMenu ) ); + } + + PopupMenu* pWinMenu = pBar->GetPopupMenu( RID_APPWINDOW ); + pWinMenu->SetSelectHdl( LINK( this, BasicFrame, MenuCommand ) ); + pWinMenu->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + pWinMenu->SetDeactivateHdl( LINK( this, BasicFrame, DeInitMenu ) ); + PopupMenu* pHelpMenu = pBar->GetPopupMenu( RID_APPHELP ); + pHelpMenu->SetSelectHdl( LINK( this, BasicFrame, MenuCommand ) ); + pHelpMenu->SetHighlightHdl( LINK( this, BasicFrame, HighlightMenu ) ); + pHelpMenu->SetActivateHdl( LINK( this, BasicFrame, InitMenu ) ); + pHelpMenu->SetDeactivateHdl( LINK( this, BasicFrame, DeInitMenu ) ); + +#ifndef UNX + pPrn = new BasicPrinter; +#else + pPrn = NULL; +#endif + pList = new EditList; + pStatus = new StatusLine( this ); + + LoadIniFile(); + + UpdateTitle(); +// SetIcon( aAppIcon ); + + // Size: half width, 0.75 * height - 2 * IconSize + { + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup("WinGeom"); + SetWindowState( aConf.ReadKey("WinParams", "") ); + } + +// pWork = new AppEdit( this, NULL ); +// pWork->Show(); +// pWork->Close(); + + aLineNum.SetTimeoutHdl( LINK( this, BasicFrame, ShowLineNr ) ); + aLineNum.SetTimeout(200); + aLineNum.Start(); + + + aCheckFiles.SetTimeout( 10000 ); + aCheckFiles.SetTimeoutHdl( LINK( this, BasicFrame, CheckAllFiles ) ); + aCheckFiles.Start(); + + GetMenuBar()->SetCloserHdl( LINK( this, BasicFrame, CloseButtonClick ) ); + GetMenuBar()->SetFloatButtonClickHdl( LINK( this, BasicFrame, FloatButtonClick ) ); + GetMenuBar()->SetHideButtonClickHdl( LINK( this, BasicFrame, HideButtonClick ) ); +} + +const ByteString ProfilePrefix("_profile_"); +const USHORT ProfilePrefixLen = ProfilePrefix.Len(); + +void BasicFrame::LoadIniFile() +{ + USHORT i; + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + + for ( i = 0 ; i < aConf.GetGroupCount() ; i++ ) + { + aConf.SetGroup( ByteString( aConf.GetGroupName( i ) ) ); + if ( ( aConf.ReadKey( "Aktuell" ).Len() || aConf.ReadKey( "Alle" ).Len() ) + &&( !aConf.ReadKey( "Current" ).Len() && !aConf.ReadKey( "All" ).Len() ) ) + { + aConf.WriteKey( "Current", aConf.ReadKey( "Aktuell" ) ); + aConf.WriteKey( "All", aConf.ReadKey( "Alle" ) ); + } + } + + aConf.SetGroup("Misc"); + ByteString aTemp; + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Misc" ); + + pStatus->SetProfileName( String( aCurrentProfile.Copy( ProfilePrefixLen ), RTL_TEXTENCODING_UTF8 ) ); + + aConf.SetGroup( aCurrentProfile ); + aTemp = aConf.ReadKey( "AutoReload", "0" ); + bAutoReload = ( aTemp.CompareTo("1") == COMPARE_EQUAL ); + aTemp = aConf.ReadKey( "AutoSave", "0" ); + bAutoSave = ( aTemp.CompareTo("1") == COMPARE_EQUAL ); + + LoadLRU(); + + if ( pBasic ) + pBasic->LoadIniFile(); + + for ( i = 0 ; i < pList->Count() ; i++ ) + pList->GetObject( i )->LoadIniFile(); +} + +BasicFrame::~BasicFrame() +{ + AppWin* p = pList->First(); + DBG_ASSERT( !p, "Still open FileWindows"); + if( p ) + while( (p = pList->Remove() ) != NULL ) + delete p; + + MenuBar *pBar = GetMenuBar(); + SetMenuBar( NULL ); + delete pBar; + + delete pStatus; + delete pPrn; + delete pList; +// delete pExecutionStatus; +// delete pBasic; + pBasic.Clear(); +} + +void BasicFrame::Command( const CommandEvent& rCEvt ) +{ + switch( rCEvt.GetCommand() ) { + case COMMAND_SHOWDIALOG: + { + const CommandDialogData* pData = rCEvt.GetDialogData(); + if ( pData) + { + const int nCommand = pData->GetDialogId(); + + switch (nCommand) + { + case SHOWDIALOG_ID_PREFERENCES : + Command( RID_OPTIONS ); + break; + + case SHOWDIALOG_ID_ABOUT : + Command( RID_HELPABOUT ); + break; + + default : + ; + } + } + } + break; + } +} + +void BasicFrame::UpdateTitle() +{ + String aTitle; + aTitle += aAppName; + if ( aAppMode.Len() ) + { + aTitle.AppendAscii(" ["); + aTitle += aAppMode; + aTitle.AppendAscii("]"); + } + aTitle.AppendAscii(" - "); + aTitle += aAppFile; + SetText( aTitle ); +} + +IMPL_LINK( BasicFrame, CheckAllFiles, Timer*, pTimer ) +{ + if ( pWork ) + { + AppWin* pStartWin = pWork; + Window* pFocusWin = Application::GetFocusWindow(); + for ( int i = pList->Count()-1 ; i >= 0 ; i-- ) + pList->GetObject( i )->CheckReload(); + + if ( pWork != pStartWin ) + { + pWork = pStartWin; + pWork->ToTop(); + } + if ( pFocusWin ) + pFocusWin->GrabFocus(); + } + pTimer->Start(); + return 0; +} + +BOOL BasicFrame::IsAutoRun() +{ + return bIsAutoRun; +} + +void BasicFrame::SetAutoRun( BOOL bAuto ) +{ + bIsAutoRun = bAuto; +} + +void BasicFrame::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( TTExecutionStatusHint ) ) + { + TTExecutionStatusHint *pStatusHint = ( TTExecutionStatusHint* )&rHint; + switch ( pStatusHint->GetType() ) + { + case TT_EXECUTION_ENTERWAIT: + { + EnterWait(); + } + break; + case TT_EXECUTION_LEAVEWAIT: + { + LeaveWait(); + } + break; + case TT_EXECUTION_SHOW_ACTION: + { + String aTotalStatus( pStatusHint->GetExecutionStatus() ); + aTotalStatus.AppendAscii( " " ); + aTotalStatus.Append( pStatusHint->GetAdditionalExecutionStatus() ); + pStatus->Message( aTotalStatus ); +/* if ( !pExecutionStatus ) + pExecutionStatus = new FloatingExecutionStatus( this ); + pExecutionStatus->SetStatus( pStatusHint->GetExecutionStatus() ); + pExecutionStatus->SetAdditionalInfo( pStatusHint->GetAdditionalExecutionStatus() );*/ + } + break; + case TT_EXECUTION_HIDE_ACTION: + { +/* if ( pExecutionStatus ) + { + delete pExecutionStatus; + pExecutionStatus = NULL; + }*/ + } + break; + } + } + + + Broadcast( rHint ); +} + +void BasicFrame::Resize() +{ + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup("WinGeom"); + aConf.WriteKey("WinParams",GetWindowState()); + + // Statusbar + Size aOutSize = GetOutputSizePixel(); + Size aStatusSize = pStatus->GetSizePixel(); + Point aStatusPos( 0, aOutSize.Height() - aStatusSize.Height() ); + aStatusSize.Width() = aOutSize.Width(); + + pStatus->SetPosPixel( aStatusPos ); + pStatus->SetSizePixel( aStatusSize ); + + + // Resize possibly maximized window + ULONG i; + for( i = pList->Count(); i > 0 ; i-- ) + { + if ( pList->GetObject( i-1 )->GetWinState() == TT_WIN_STATE_MAX ) + pList->GetObject( i-1 )->Maximize(); + } +} + +void BasicFrame::Move() +{ + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup("WinGeom"); + aConf.WriteKey("WinParams",GetWindowState()); +} + +void BasicFrame::GetFocus() +{ + if ( pWork ) + pWork->GrabFocus(); +} + +IMPL_LINK( BasicFrame, CloseButtonClick, void*, EMPTYARG ) +{ + AppWin* p; + for ( p = pList->Last() ; p && p->GetWinState() != TT_WIN_STATE_MAX ; p = pList->Prev() ) + {}; + if ( p ) + p->GrabFocus(); + return Command( RID_FILECLOSE, FALSE ); +} + +IMPL_LINK( BasicFrame, FloatButtonClick, void*, EMPTYARG ) +{ + AppWin* p; + for ( p = pList->Last() ; p && p->GetWinState() != TT_WIN_STATE_MAX ; p = pList->Prev() ) + {}; + if ( p ) + p->TitleButtonClick( TITLE_BUTTON_DOCKING ); + return 1; +} + +IMPL_LINK( BasicFrame, HideButtonClick, void*, EMPTYARG ) +{ + AppWin* p; + for ( p = pList->Last() ; p && p->GetWinState() != TT_WIN_STATE_MAX ; p = pList->Prev() ) + {}; + if ( p ) + p->TitleButtonClick( TITLE_BUTTON_HIDE ); + return 1; +} + +void BasicFrame::WinShow_Hide() +{ + if ( !pList->Count() ) + return; + + AppWin* p; + BOOL bWasFullscreen = FALSE; + for ( p = pList->Last() ; p ; p = pList->Prev() ) + { + if ( p->pDataEdit ) + { + if ( p->GetWinState() & TT_WIN_STATE_HIDE // Hidden + || ( bWasFullscreen && ( !p->IsPined() || p->GetWinState() & TT_WIN_STATE_MAX )) + ) + p->Hide( SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE ); + else + p->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE ); + } + bWasFullscreen |= p->GetWinState() == TT_WIN_STATE_MAX; + } +} + +void BasicFrame::WinMax_Restore() +{ + // The application buttons + AppWin* p; + BOOL bHasFullscreenWin = FALSE; + for( p = pList->First(); p && !bHasFullscreenWin ; p = pList->Next() ) + bHasFullscreenWin |= ( p->GetWinState() == TT_WIN_STATE_MAX ); + GetMenuBar()->ShowButtons( bHasFullscreenWin, FALSE, FALSE ); + WinShow_Hide(); +} + +void BasicFrame::RemoveWindow( AppWin *pWin ) +{ +// delete pIcon; + pList->Remove( pWin ); + pWork = pList->Last(); + + WinShow_Hide(); + + if ( pWork ) + pWork->ToTop(); + + WinMax_Restore(); + + Menu* pMenu = GetMenuBar(); + if( pList->Count() == 0 ) { + pMenu->EnableItem( RID_APPEDIT, FALSE ); + pMenu->EnableItem( RID_APPRUN, FALSE ); + pMenu->EnableItem( RID_APPWINDOW, FALSE ); + } + + PopupMenu* pWinMenu = pMenu->GetPopupMenu( RID_APPWINDOW ); + + pWinMenu->RemoveItem( pWinMenu->GetItemPos( pWin->GetWinId() ) ); + + // Remove separator + if ( pWinMenu->GetItemType( pWinMenu->GetItemCount() - 1 ) == MENUITEM_SEPARATOR ) + pWinMenu->RemoveItem( pWinMenu->GetItemCount() - 1 ); + + pStatus->LoadTaskToolBox(); +} + +void BasicFrame::AddWindow( AppWin *pWin ) +{ + pList->Insert( pWin, LIST_APPEND ); + pWork = pWin; + + WinMax_Restore(); + + // Enable main menu + MenuBar* pMenu = GetMenuBar(); + if( pList->Count() > 0 ) { + pMenu->EnableItem( RID_APPEDIT, TRUE ); + pMenu->EnableItem( RID_APPRUN, TRUE ); + pMenu->EnableItem( RID_APPWINDOW, TRUE ); + } + + PopupMenu* pWinMenu = pMenu->GetPopupMenu( RID_APPWINDOW ); + USHORT nLastID = pWinMenu->GetItemId( pWinMenu->GetItemCount() - 1 ); + + // Separator necessary + if ( nLastID < RID_WIN_FILE1 && pWinMenu->GetItemType( pWinMenu->GetItemCount() - 1 ) != MENUITEM_SEPARATOR ) + pWinMenu->InsertSeparator(); + + // Find free ID + USHORT nFreeID = RID_WIN_FILE1; + while ( pWinMenu->GetItemPos( nFreeID ) != MENU_ITEM_NOTFOUND && nFreeID < RID_WIN_FILEn ) + nFreeID++; + + pWin->SetWinId( nFreeID ); + pWinMenu->InsertItem( nFreeID, pWin->GetText() ); +} + +void BasicFrame::WindowRenamed( AppWin *pWin ) +{ + MenuBar* pMenu = GetMenuBar(); + PopupMenu* pWinMenu = pMenu->GetPopupMenu( RID_APPWINDOW ); + + pWinMenu->SetItemText( pWin->GetWinId(), pWin->GetText() ); + + pStatus->LoadTaskToolBox(); + + aAppFile = pWin->GetText(); + UpdateTitle(); +} + +void BasicFrame::FocusWindow( AppWin *pWin ) +{ + pWork = pWin; + pList->Remove( pWin ); + pList->Insert( pWin, LIST_APPEND ); + pWin->Minimize( FALSE ); + + aAppFile = pWin->GetText(); + UpdateTitle(); + + WinShow_Hide(); + pStatus->LoadTaskToolBox(); +} + +BOOL BasicFrame::Close() +{ + if( bInBreak || Basic().IsRunning() ) + if( RET_NO == QueryBox( this, SttResId( IDS_RUNNING ) ).Execute() ) + return FALSE; + + StarBASIC::Stop(); + bInBreak = FALSE; + if( CloseAll() ) + { + aLineNum.Stop(); + + // Close remaining dialogs to avoid assertions + while ( GetWindow( WINDOW_OVERLAP )->GetWindow( WINDOW_FIRSTOVERLAP ) ) + { + delete GetWindow( WINDOW_OVERLAP )->GetWindow( WINDOW_FIRSTOVERLAP )->GetWindow( WINDOW_CLIENT ); + } + + Application::SetDefDialogParent( NULL ); + WorkWindow::Close(); + + return TRUE; + } else return FALSE; +} + +BOOL BasicFrame::CloseAll() +{ + while ( pList->Count() ) + if ( !pList->Last()->Close() ) + return FALSE; + return TRUE; +} + +BOOL BasicFrame::CompileAll() +{ + AppWin* p; + for( p = pList->First(); p; p = pList->Next() ) + if( p->ISA(AppBasEd) && !((AppBasEd*)p)->Compile() ) return FALSE; + return TRUE; +} + +// Setup menu +#define MENU2FILENAME( Name ) Name.Copy( Name.SearchAscii(" ") +1).EraseAllChars( '~' ) +#define LRUNr( nNr ) CByteString("LRU").Append( ByteString::CreateFromInt32( nNr ) ) +String FILENAME2MENU( USHORT nNr, String aName ) +{ + String aRet; + if ( nNr <= 9 ) + aRet = CUniString("~").Append( UniString::CreateFromInt32( nNr ) ); + else if ( nNr == 10 ) + aRet = CUniString("1~0"); + else + aRet = UniString::CreateFromInt32( nNr ); + + return aRet.AppendAscii(" ").Append( aName ); +} + +void BasicFrame::AddToLRU(String const& aFile) +{ + Config aConfig(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + PopupMenu *pPopup = GetMenuBar()->GetPopupMenu(RID_APPFILE); + + aConfig.SetGroup("LRU"); + USHORT nMaxLRU = (USHORT)aConfig.ReadKey("MaxLRU","4").ToInt32(); + DirEntry aFileEntry( aFile ); + USHORT i,nLastMove = nMaxLRU; + + for ( i = 1 ; i<nMaxLRU && nLastMove == nMaxLRU ; i++ ) + { + if ( DirEntry( UniString( aConfig.ReadKey(LRUNr(i),""), RTL_TEXTENCODING_UTF8 ) ) == aFileEntry ) + nLastMove = i; + } + + if ( pPopup->GetItemPos( IDM_FILE_LRU1 ) == MENU_ITEM_NOTFOUND ) + pPopup->InsertSeparator(); + for ( i = nLastMove ; i>1 ; i-- ) + { + if ( aConfig.ReadKey(LRUNr(i-1),"").Len() ) + { + aConfig.WriteKey(LRUNr(i), aConfig.ReadKey(LRUNr(i-1),"")); + if ( pPopup->GetItemPos( IDM_FILE_LRU1 + i-1 ) == MENU_ITEM_NOTFOUND ) + pPopup->InsertItem(IDM_FILE_LRU1 + i-1, FILENAME2MENU( i, MENU2FILENAME( pPopup->GetItemText(IDM_FILE_LRU1 + i-1-1) ) )); + else + pPopup->SetItemText(IDM_FILE_LRU1 + i-1,FILENAME2MENU( i, MENU2FILENAME( pPopup->GetItemText(IDM_FILE_LRU1 + i-1-1) ) )); + } + } + aConfig.WriteKey(LRUNr(1), ByteString( aFile, RTL_TEXTENCODING_UTF8 ) ); + if ( pPopup->GetItemPos( IDM_FILE_LRU1 ) == MENU_ITEM_NOTFOUND ) + pPopup->InsertItem(IDM_FILE_LRU1,FILENAME2MENU( 1, aFile)); + else + pPopup->SetItemText(IDM_FILE_LRU1,FILENAME2MENU( 1, aFile)); +} + +void BasicFrame::LoadLRU() +{ + Config aConfig(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + PopupMenu *pPopup = GetMenuBar()->GetPopupMenu(RID_APPFILE); + BOOL bAddSep = TRUE; + + aConfig.SetGroup("LRU"); + USHORT nMaxLRU = (USHORT)aConfig.ReadKey("MaxLRU","4").ToInt32(); + + if ( pPopup ) + bAddSep = pPopup->GetItemPos( IDM_FILE_LRU1 ) == MENU_ITEM_NOTFOUND; + + USHORT i; + for ( i = 1; i <= nMaxLRU && pPopup != NULL; i++) + { + String aFile = UniString( aConfig.ReadKey(LRUNr(i)), RTL_TEXTENCODING_UTF8 ); + + if (aFile.Len() != 0) + { + if (bAddSep) + { + pPopup->InsertSeparator(); + bAddSep = FALSE; + } + + if ( pPopup->GetItemPos( IDM_FILE_LRU1 + i-1 ) == MENU_ITEM_NOTFOUND ) + pPopup->InsertItem(IDM_FILE_LRU1 + i-1, FILENAME2MENU( i, aFile )); + else + pPopup->SetItemText(IDM_FILE_LRU1 + i-1, FILENAME2MENU( i, aFile )); + } + } + i = nMaxLRU+1; + while ( pPopup->GetItemPos( IDM_FILE_LRU1 + i-1 ) != MENU_ITEM_NOTFOUND ) + { + pPopup->RemoveItem( pPopup->GetItemPos( IDM_FILE_LRU1 + i-1 ) ); + i++; + } +} + +IMPL_LINK( BasicFrame, InitMenu, Menu *, pMenu ) +{ + BOOL bNormal = BOOL( !bInBreak ); + pMenu->EnableItem( RID_RUNCOMPILE, bNormal ); + + BOOL bHasEdit = BOOL( /*bNormal &&*/ pWork != NULL ); + +// pMenu->EnableItem( RID_FILENEW, bNormal ); // always possible +// pMenu->EnableItem( RID_FILEOPEN, bNormal ); + pMenu->EnableItem( RID_FILECLOSE, bHasEdit ); + pMenu->EnableItem( RID_FILESAVE, bHasEdit ); + pMenu->EnableItem( RID_FILESAVEAS, bHasEdit ); + pMenu->EnableItem( RID_FILEPRINT, bHasEdit ); + pMenu->EnableItem( RID_FILESETUP, bHasEdit ); + pMenu->EnableItem( RID_FILELOADLIB, bNormal ); + pMenu->EnableItem( RID_FILESAVELIB, bHasEdit ); + + BOOL bHasErr = BOOL( bNormal && pBasic->GetErrors() != 0 ); + BOOL bNext = bHasErr & bNormal; + BOOL bPrev = bHasErr & bNormal; + if( bHasErr ) + { + ULONG n = pBasic->aErrors.GetCurPos(); + if( n == 0 ) + bPrev = FALSE; + if( USHORT(n+1) == pBasic->GetErrors() ) + bNext = FALSE; + } + pMenu->EnableItem( RID_RUNNEXTERR, bNext ); + pMenu->EnableItem( RID_RUNPREVERR, bPrev ); + pMenu->CheckItem( RID_RUNDISAS, bDisas ); + if( pWork ) + pWork->InitMenu( pMenu ); + + return TRUE; +} + +IMPL_LINK_INLINE_START( BasicFrame, DeInitMenu, Menu *, pMenu ) +{ + (void) pMenu; /* avoid warning about unused parameter */ +/* pMenu->EnableItem( RID_RUNCOMPILE ); + + pMenu->EnableItem( RID_FILECLOSE ); + pMenu->EnableItem( RID_FILESAVE ); + pMenu->EnableItem( RID_FILESAVEAS ); + pMenu->EnableItem( RID_FILEPRINT ); + pMenu->EnableItem( RID_FILESETUP ); + pMenu->EnableItem( RID_FILELOADLIB ); + pMenu->EnableItem( RID_FILESAVELIB ); + + pMenu->EnableItem( RID_RUNNEXTERR ); + pMenu->EnableItem( RID_RUNPREVERR ); + if( pWork ) pWork->DeInitMenu( pMenu ); +*/ + SetAutoRun( FALSE ); + String aString; + pStatus->Message( aString ); + return 0L; +} +IMPL_LINK_INLINE_END( BasicFrame, DeInitMenu, Menu *, pMenu ) + +IMPL_LINK_INLINE_START( BasicFrame, HighlightMenu, Menu *, pMenu ) +{ + String s = pMenu->GetHelpText( pMenu->GetCurItemId() ); + pStatus->Message( s ); + return 0L; +} +IMPL_LINK_INLINE_END( BasicFrame, HighlightMenu, Menu *, pMenu ) + +IMPL_LINK_INLINE_START( BasicFrame, MenuCommand, Menu *, pMenu ) +{ + USHORT nId = pMenu->GetCurItemId(); + BOOL bChecked = pMenu->IsItemChecked( nId ); + return Command( nId, bChecked ); +} +IMPL_LINK_INLINE_END( BasicFrame, MenuCommand, Menu *, pMenu ) + +IMPL_LINK_INLINE_START( BasicFrame, Accel, Accelerator*, pAcc ) +{ + SetAutoRun( FALSE ); + return Command( pAcc->GetCurItemId() ); +} +IMPL_LINK_INLINE_END( BasicFrame, Accel, Accelerator*, pAcc ) + +IMPL_LINK_INLINE_START( BasicFrame, ShowLineNr, AutoTimer *, pTimer ) +{ + (void) pTimer; /* avoid warning about unused parameter */ + String aPos; + if ( pWork && pWork->ISA(AppBasEd)) + { + aPos = String::CreateFromInt32(pWork->GetLineNr()); + } + pStatus->Pos( aPos ); + return 0L; +} +IMPL_LINK_INLINE_END( BasicFrame, ShowLineNr, AutoTimer *, pTimer ) + + +MsgEdit* BasicFrame::GetMsgTree( String aLogFileName ) +{ + if ( FindErrorWin( aLogFileName ) ) + { + return FindErrorWin( aLogFileName )->GetMsgTree(); + } + else + { // create new Window on the fly + AppError *pNewWindow = new AppError( this, aLogFileName ); + pNewWindow->Show(); + pNewWindow->GrabFocus(); + return pNewWindow->GetMsgTree(); + } +} + +IMPL_LINK( BasicFrame, Log, TTLogMsg *, pLogMsg ) +{ + GetMsgTree( pLogMsg->aLogFileName )->AddAnyMsg( pLogMsg ); + return 0L; +} + +IMPL_LINK( BasicFrame, WinInfo, WinInfoRec*, pWinInfo ) +{ + if ( !pDisplayHidDlg ) + pDisplayHidDlg = new DisplayHidDlg( this ); + if ( pDisplayHidDlg ) + { + pDisplayHidDlg->AddData( pWinInfo ); + pDisplayHidDlg->Show(); + } + return 0; +} + +AppBasEd* BasicFrame::CreateModuleWin( SbModule* pMod ) +{ + String aModName = pMod->GetName(); + if ( aModName.Copy(0,2).CompareToAscii("--") == COMPARE_EQUAL ) + aModName.Erase(0,2); + pMod->SetName(aModName); + AppBasEd* p = new AppBasEd( this, pMod ); + p->Show(); + p->GrabFocus(); + p->ToTop(); + return p; +} + +BOOL BasicFrame::LoadFile( String aFilename ) +{ + BOOL bIsResult = DirEntry( aFilename ).GetExtension().CompareIgnoreCaseToAscii("RES") == COMPARE_EQUAL; + BOOL bIsBasic = DirEntry( aFilename ).GetExtension().CompareIgnoreCaseToAscii("BAS") == COMPARE_EQUAL; + bIsBasic |= DirEntry( aFilename ).GetExtension().CompareIgnoreCaseToAscii("INC") == COMPARE_EQUAL; + + AppWin* p; + BOOL bSuccess = TRUE; + if ( bIsResult ) + { + p = new AppError( this, aFilename ); + } + else if ( bIsBasic ) + { + p = new AppBasEd( this, NULL ); + bSuccess = p->Load( aFilename ); + } + else + { + p = new AppEdit( this ); + bSuccess = p->Load( aFilename ); + } + if ( bSuccess ) + { + p->Show(); + p->GrabFocus(); + } + else + delete p; + + return bSuccess; +} + +// Execute command +long BasicFrame::Command( short nID, BOOL bChecked ) +{ + BasicError* pErr; + + switch( nID ) { + case RID_FILENEW: { + AppBasEd* p = new AppBasEd( this, NULL ); + p->Show(); + p->GrabFocus(); + // InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); + } break; + case RID_FILEOPEN: + { + String s; + if( QueryFileName( s, FT_BASIC_SOURCE | FT_RESULT_FILE, FALSE ) ) { + AddToLRU( s ); + LoadFile( s ); +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); + } + } break; + case RID_FILELOADLIB: + LoadLibrary(); + break; + case RID_FILESAVELIB: + SaveLibrary(); + break; + case RID_FILECLOSE: + if( pWork && pWork->Close() ){}; +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); + break; + case RID_FILEPRINT: +#ifndef UNX + if( pWork ) + pPrn->Print( pWork->GetText(), pWork->pDataEdit->GetText(), this ); +#else + InfoBox( this, SttResId( IDS_NOPRINTERERROR ) ).Execute(); +#endif + break; + case RID_FILESETUP: +#ifndef UNX + pPrn->Setup(); +#else + InfoBox( this, SttResId( IDS_NOPRINTERERROR ) ).Execute(); +#endif + break; + case RID_QUIT: + if( Close() ) aBasicApp.Quit(); + break; + + + case RID_RUNSTART: + nFlags = SbDEBUG_BREAK; + goto start; + case RID_RUNSTEPOVER: + nFlags = SbDEBUG_STEPINTO | SbDEBUG_STEPOVER; + goto start; + case RID_RUNSTEPINTO: + nFlags = SbDEBUG_STEPINTO; + goto start; + case RID_RUNTOCURSOR: + if ( pWork && pWork->ISA(AppBasEd) && ((AppBasEd*)pWork)->GetModule()->SetBP(pWork->GetLineNr()) ) + { + SbModule *pModule = ((AppBasEd*)pWork)->GetModule(); +#if OSL_DEBUG_LEVEL > 1 + USHORT x; + x = pWork->GetLineNr(); + x = ((AppBasEd*)pWork)->GetModule()->GetBPCount(); + if ( !x ) + x = pModule->SetBP(pWork->GetLineNr()); + x = pModule->GetBPCount(); +#endif + + for ( USHORT nMethod = 0; nMethod < pModule->GetMethods()->Count(); nMethod++ ) + { + SbMethod* pMethod = (SbMethod*)pModule->GetMethods()->Get( nMethod ); + DBG_ASSERT( pMethod, "Methode nicht gefunden! (NULL)" ); + pMethod->SetDebugFlags( pMethod->GetDebugFlags() | SbDEBUG_BREAK ); + } + } + nFlags = SbDEBUG_BREAK; + goto start; + start: { +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); + if ( !Basic().IsRunning() || bInBreak ) + { + AppBasEd* p = NULL; + if( pWork && pWork->ISA(AppBasEd) ) + { + p = ((AppBasEd*)pWork); + p->ToTop(); + } + else + { + AppWin *w = NULL; + for ( w = pList->Last() ; w ? !w->ISA(AppBasEd) : FALSE ; w = pList->Prev() ) ; + if ( w ) + { + p = ((AppBasEd*)w); + p->ToTop(); + } + else + if ( IsAutoRun() ) + printf( "No file loaded to run.\n" ); + } + + if( bInBreak ) + // Reset the flag + bInBreak = FALSE; + else + { + if( IsAutoSave() && !SaveAll() ) break; + if( !CompileAll() ) break; + String aString; + pStatus->Message( aString ); + if( p ) + { + BasicDLL::SetDebugMode( TRUE ); + Basic().ClearGlobalVars(); + p->Run(); + BasicDLL::SetDebugMode( FALSE ); + // If cancelled during Interactive=FALSE +// BasicDLL::EnableBreak( TRUE ); + } + }} + } +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); // after run + break; + case RID_RUNCOMPILE: + if( pWork && pWork->ISA(AppBasEd) && SaveAll() ) + { + ((AppBasEd*)pWork)->Compile(); + pWork->ToTop(); + pWork->GrabFocus(); + } + break; + case RID_RUNDISAS: + bDisas = BOOL( !bChecked ); + break; + case RID_RUNBREAK: + if ( Basic().IsRunning() && !bInBreak ) + { +// pINST->CalcBreakCallLevel(SbDEBUG_STEPINTO); + pINST->nBreakCallLvl = pINST->nCallLvl; + } + break; + case RID_RUNSTOP: + Basic().Stop(); + bInBreak = FALSE; + break; + case RID_RUNNEXTERR: + pErr = pBasic->aErrors.Next(); + if( pErr ) pErr->Show(); + break; + case RID_RUNPREVERR: + pErr = pBasic->aErrors.Prev(); + if( pErr ) pErr->Show(); + break; + + case RID_OPTIONS: + { + OptionsDialog *pOptions = new OptionsDialog( this, SttResId(IDD_OPTIONS_DLG) ); + pOptions->Show(); + } + break; + case RID_DECLARE_HELPER: + InfoBox( this, SttResId( IDS_NOT_YET_IMPLEMENTED ) ).Execute(); + break; + + case RID_WINTILE: + { + WindowArrange aArange; + for ( ULONG i = 0 ; i < pList->Count() ; i++ ) + { + aArange.AddWindow( pList->GetObject( i ) ); + pList->GetObject( i )->Restore(); + } + + + sal_Int32 nTitleHeight; + { + sal_Int32 nDummy1, nDummy2, nDummy3; + GetBorder( nDummy1, nTitleHeight, nDummy2, nDummy3 ); + } + + Size aSize = GetOutputSizePixel(); + aSize.Height() -= nTitleHeight; + Rectangle aRect( Point( 0, nTitleHeight ), aSize ); + + aArange.Arrange( WINDOWARRANGE_TILE, aRect ); + + } + break; + case RID_WINTILEHORZ: + { + WindowArrange aArange; + for ( ULONG i = 0 ; i < pList->Count() ; i++ ) + { + aArange.AddWindow( pList->GetObject( i ) ); + pList->GetObject( i )->Restore(); + } + + + sal_Int32 nTitleHeight; + { + sal_Int32 nDummy1, nDummy2, nDummy3; + GetBorder( nDummy1, nTitleHeight, nDummy2, nDummy3 ); + } + + Size aSize = GetOutputSizePixel(); + aSize.Height() -= nTitleHeight; + Rectangle aRect( Point( 0, nTitleHeight ), aSize ); + + aArange.Arrange( WINDOWARRANGE_HORZ, aRect ); + + } + break; + case RID_WINTILEVERT: +//#define WINDOWARRANGE_TILE 1 +//#define WINDOWARRANGE_HORZ 2 +//#define WINDOWARRANGE_VERT 3 +//#define WINDOWARRANGE_CASCADE 4 + { + WindowArrange aArange; + for ( ULONG i = 0 ; i < pList->Count() ; i++ ) + { + aArange.AddWindow( pList->GetObject( i ) ); + pList->GetObject( i )->Restore(); + } + + + sal_Int32 nTitleHeight; + { + sal_Int32 nDummy1, nDummy2, nDummy3; + GetBorder( nDummy1, nTitleHeight, nDummy2, nDummy3 ); + } + + Size aSize = GetOutputSizePixel(); + aSize.Height() -= nTitleHeight; + Rectangle aRect( Point( 0, nTitleHeight ), aSize ); + + aArange.Arrange( WINDOWARRANGE_VERT, aRect ); + + } + break; + case RID_WINCASCADE: + { + for ( USHORT i = 0 ; i < pList->Count() ; i++ ) + { + pList->GetObject( i )->Cascade( i ); + } + } + break; + +/* case RID_HELPTOPIC: + if( pWork ) pWork->Help(); + break; + case RID_HELPKEYS: + aBasicApp.pHelp->Start( CUniString( "Keyboard" ) ); + break; + case RID_HELPINDEX: + aBasicApp.pHelp->Start( OOO_HELP_INDEX ); + break; + case RID_HELPINTRO: + aBasicApp.pHelp->Start( OOO_HELP_HELPONHELP ); + break; +*/ case RID_HELPABOUT: + { + SttResId aResId( IDD_ABOUT_DIALOG ); + if ( Basic().pTestObject ) // Are we TestTool? + aResId = SttResId( IDD_TT_ABOUT_DIALOG ); + else + aResId = SttResId( IDD_ABOUT_DIALOG ); + AboutDialog aAbout( this, aResId ); + aAbout.Execute(); + } + break; + case RID_POPUPEDITVAR: + { + new VarEditDialog( this, pEditVar ); + } + break; + default: + if ( nID >= RID_WIN_FILE1 && nID <= RID_WIN_FILEn ) + { + MenuBar* pMenu = GetMenuBar(); + PopupMenu* pWinMenu = pMenu->GetPopupMenu( RID_APPWINDOW ); + String aName = pWinMenu->GetItemText( nID ); + aName.EraseAllChars( L'~' ); + AppWin* pWin = FindWin( aName ); + if ( pWin ) + pWin->ToTop(); + } + else if ( nID >= IDM_FILE_LRU1 && nID <= IDM_FILE_LRUn ) + { + String s = MENU2FILENAME( GetMenuBar()->GetPopupMenu(RID_APPFILE)->GetItemText(nID) ); + + AddToLRU( s ); + LoadFile( s ); +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); + } + else + { +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPEDIT )); // So daß Delete richtig ist + if( pWork ) + pWork->Command( CommandEvent( Point(), nID ) ); +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPEDIT )); // So daß Delete richtig ist + } + } + return TRUE; +} + +BOOL BasicFrame::SaveAll() +{ + AppWin* p, *q = pWork; + for( p = pList->First(); p; p = pList->Next() ) + { + USHORT nRes = p->QuerySave( QUERY_DISK_CHANGED ); + if( (( nRes == SAVE_RES_ERROR ) && QueryBox(this,SttResId(IDS_ASKSAVEERROR)).Execute() == RET_NO ) + || ( nRes == SAVE_RES_CANCEL ) ) + return FALSE; + } + if ( q ) + q->ToTop(); + return TRUE; +} + +IMPL_LINK( BasicFrame, ModuleWinExists, String*, pFilename ) +{ + return FindModuleWin( *pFilename ) != NULL; +} + +AppBasEd* BasicFrame::FindModuleWin( const String& rName ) +{ + AppWin* p; + for( p = pList->First(); p; p = pList->Next() ) + { + if( p->ISA(AppBasEd) && ((AppBasEd*)p)->GetModName() == rName ) + return ((AppBasEd*)p); + } + return NULL; +} + +AppError* BasicFrame::FindErrorWin( const String& rName ) +{ + AppWin* p; + for( p = pList->First(); p; p = pList->Next() ) + { + if( p->ISA(AppError) && ((AppError*)p)->GetText() == rName ) + return ((AppError*)p); + } + return NULL; +} + +AppWin* BasicFrame::FindWin( const String& rName ) +{ + AppWin* p; + for( p = pList->First(); p; p = pList->Next() ) + { + if( p->GetText() == rName ) + return p; + } + return NULL; +} + +AppWin* BasicFrame::FindWin( USHORT nWinId ) +{ + AppWin* p; + for( p = pList->First(); p; p = pList->Next() ) + { + if( p->GetWinId() == nWinId ) + return p; + } + return NULL; +} + +AppWin* BasicFrame::IsWinValid( AppWin* pMaybeWin ) +{ + AppWin* p; + for( p = pList->First(); p; p = pList->Next() ) + { + if( p == pMaybeWin ) + return p; + } + return NULL; +} + +IMPL_LINK( BasicFrame, WriteString, String*, pString ) +{ + if ( pList->Last() ) + { + pList->Last()->pDataEdit->ReplaceSelected( *pString ); + return TRUE; + } + else + return FALSE; +} + +class NewFileDialog : public FileDialog +{ +private: + String aLastPath; +public: + ByteString aFilterType; + NewFileDialog( Window* pParent, WinBits nWinStyle ):FileDialog( pParent, nWinStyle ){}; + virtual short Execute(); + virtual void FilterSelect(); +}; + +void NewFileDialog::FilterSelect() +{ + String aTemp = GetPath(); + if ( aLastPath.Len() == 0 ) + aLastPath = DirEntry( GetPath() ).GetPath().GetFull(); + if ( aLastPath.CompareIgnoreCaseToAscii( DirEntry( GetPath() ).GetPath().GetFull() ) != COMPARE_EQUAL ) + return; // User decides after he has changed the path + + String aCurFilter = GetCurFilter(); + USHORT nFilterNr = 0; + while ( nFilterNr < GetFilterCount() && aCurFilter != GetFilterName( nFilterNr ) ) + { + nFilterNr++; + } + aFilterType = ByteString( GetFilterType( nFilterNr ), RTL_TEXTENCODING_UTF8 ); + + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup( "Misc" ); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + aLastPath = UniString( aConf.ReadKey( aFilterType, aConf.ReadKey( "BaseDir" ) ), RTL_TEXTENCODING_UTF8 ); + SetPath( aLastPath ); +// if ( IsInExecute() ) +// SetPath( "" ); +} + +short NewFileDialog::Execute() +{ + BOOL bRet = (BOOL)FileDialog::Execute(); + if ( bRet ) + { + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup( "Misc" ); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + aConf.WriteKey( aFilterType, ByteString( DirEntry( GetPath() ).GetPath().GetFull(), RTL_TEXTENCODING_UTF8 ) ); + aConf.WriteKey( "LastFilterName", ByteString( GetCurFilter(), RTL_TEXTENCODING_UTF8 ) ); + } + return bRet; +} + +BOOL BasicFrame::QueryFileName + (String& rName, FileType nFileType, BOOL bSave ) +{ + NewFileDialog aDlg( this, bSave ? WinBits( WB_SAVEAS ) : + WinBits( WB_OPEN ) ); + aDlg.SetText( String( SttResId( bSave ? IDS_SAVEDLG : IDS_LOADDLG ) ) ); + + if ( nFileType & FT_RESULT_FILE ) + { + aDlg.SetDefaultExt( String( SttResId( IDS_RESFILE ) ) ); + aDlg.AddFilter( String( SttResId( IDS_RESFILTER ) ), String( SttResId( IDS_RESFILE ) ) ); + aDlg.AddFilter( String( SttResId( IDS_TXTFILTER ) ), String( SttResId( IDS_TXTFILE ) ) ); + aDlg.SetCurFilter( SttResId( IDS_RESFILTER ) ); + } + + if ( nFileType & FT_BASIC_SOURCE ) + { + aDlg.SetDefaultExt( String( SttResId( IDS_NONAMEFILE ) ) ); + aDlg.AddFilter( String( SttResId( IDS_BASFILTER ) ), String( SttResId( IDS_NONAMEFILE ) ) ); + aDlg.AddFilter( String( SttResId( IDS_INCFILTER ) ), String( SttResId( IDS_INCFILE ) ) ); + aDlg.SetCurFilter( SttResId( IDS_BASFILTER ) ); + } + + if ( nFileType & FT_BASIC_LIBRARY ) + { + aDlg.SetDefaultExt( String( SttResId( IDS_LIBFILE ) ) ); + aDlg.AddFilter( String( SttResId( IDS_LIBFILTER ) ), String( SttResId( IDS_LIBFILE ) ) ); + aDlg.SetCurFilter( SttResId( IDS_LIBFILTER ) ); + } + + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup( "Misc" ); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + ByteString aFilter( aConf.ReadKey( "LastFilterName") ); + if ( aFilter.Len() ) + aDlg.SetCurFilter( String( aFilter, RTL_TEXTENCODING_UTF8 ) ); + else + aDlg.SetCurFilter( String( SttResId( IDS_BASFILTER ) ) ); + + aDlg.FilterSelect(); // Selects the last used path +// if ( bSave ) + if ( rName.Len() > 0 ) + aDlg.SetPath( rName ); + + if( aDlg.Execute() ) + { + rName = aDlg.GetPath(); +/* rExtension = aDlg.GetCurrentFilter(); + var i:integer; + for ( i = 0 ; i < aDlg.GetFilterCount() ; i++ ) + if ( rExtension == aDlg.GetFilterName( i ) ) + rExtension = aDlg.GetFilterType( i ); +*/ + return TRUE; + } else return FALSE; +} + +USHORT BasicFrame::BreakHandler() +{ + bInBreak = TRUE; +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); +// MenuBar aBar( ResId( RID_APPMENUBAR ) ); +// aBar.EnableItem( RID_APPEDIT, FALSE ); + SetAppMode( String( SttResId ( IDS_APPMODE_BREAK ) ) ); + while( bInBreak ) + GetpApp()->Yield(); + SetAppMode( String( SttResId ( IDS_APPMODE_RUN ) ) ); +// aBar.EnableItem( RID_APPEDIT, TRUE ); +// InitMenu(GetMenuBar()->GetPopupMenu( RID_APPRUN )); + return nFlags; +} + +void BasicFrame::LoadLibrary() +{ + String s; + if( QueryFileName( s, FT_BASIC_LIBRARY, FALSE ) ) + { + CloseAll(); + SvFileStream aStrm( s, STREAM_STD_READ ); + MyBasic* pNew = (MyBasic*) SbxBase::Load( aStrm ); + if( pNew && pNew->ISA( MyBasic ) ) + { + pBasic = pNew; + // Show all contents if existing + SbxArray* pMods = pBasic->GetModules(); + for( USHORT i = 0; i < pMods->Count(); i++ ) + { + SbModule* pMod = (SbModule*) pMods->Get( i ); + AppWin* p = new AppBasEd( this, pMod ); + p->Show(); + } + } + else + { + delete pNew; + ErrorBox( this, SttResId( IDS_READERROR ) ).Execute(); + } + } +} + +void BasicFrame::SaveLibrary() +{ + String s; + if( QueryFileName( s, FT_BASIC_LIBRARY, TRUE ) ) + { + SvFileStream aStrm( s, STREAM_STD_WRITE ); + if( !Basic().Store( aStrm ) ) + ErrorBox( this, SttResId( IDS_WRITEERROR ) ).Execute(); + } +} + +String BasicFrame::GenRealString( const String &aResString ) +{ + xub_StrLen nStart,nGleich = 0,nEnd = 0,nStartPos = 0; + String aType,aValue,aResult(aResString); + String aString; + xub_StrLen nInsertPos = 0; + BOOL bFound; + bFound = FALSE; + + while ( (nStart = aResult.Search(StartKenn,nStartPos)) != STRING_NOTFOUND && + (nGleich = aResult.SearchAscii("=",nStart+StartKenn.Len())) != STRING_NOTFOUND && + (nEnd = aResult.Search(EndKenn,nGleich+1)) != STRING_NOTFOUND) + { + aType = aResult.Copy(nStart,nGleich-nStart); + aValue = aResult.Copy(nGleich+1,nEnd-nGleich-1); + if ( aType.CompareTo(ResKenn) == COMPARE_EQUAL ) + { + if ( bFound ) + { + // insert results of previous resource + DBG_ASSERT( aString.SearchAscii( "($Arg" ) == STRING_NOTFOUND, "Argument missing in String"); + aResult.Insert( aString, nInsertPos ); + nStart = nStart + aString.Len(); + nEnd = nEnd + aString.Len(); + aString.Erase(); + } +// if ( Resource::GetResManager()->IsAvailable( ResId( aValue ) ) ) + aString = String( SttResId( (USHORT)(aValue.ToInt32()) ) ); +// else + { +// DBG_ERROR( "Could not load resource!" ); +// return aResString; + } + nInsertPos = nStart; + nStartPos = nStart; + aResult.Erase( nStart, nEnd-nStart+1 ); + bFound = TRUE; + } + else if ( aType.Search(BaseArgKenn) == 0 ) // Starts with BaseArgKenn + { + // TODO: What the hell is that for?? + USHORT nArgNr = USHORT( aType.Copy( BaseArgKenn.Len() ).ToInt32() ); + DBG_ASSERT( aString.Search( CUniString("($Arg").Append( String::CreateFromInt32(nArgNr) ).AppendAscii(")") ) != STRING_NOTFOUND, "Extra Argument given in String"); + aString.SearchAndReplace( CUniString("($Arg").Append( String::CreateFromInt32(nArgNr) ).AppendAscii(")"), aValue ); + nStartPos = nStart; + aResult.Erase( nStart, nEnd-nStart+1 ); + } + else + { + DBG_ERROR( CByteString("Unknown replacement in String: ").Append( ByteString( aResult.Copy(nStart,nEnd-nStart), RTL_TEXTENCODING_UTF8 ) ).GetBuffer() ); + nStartPos = nStartPos + StartKenn.Len(); + } + } + if ( bFound ) + { + DBG_ASSERT( aString.SearchAscii( "($Arg" ) == STRING_NOTFOUND, "Argument missing in String"); + aResult.Insert( aString, nInsertPos ); + } + return aResult; +} + + diff --git a/basic/source/app/app.hxx b/basic/source/app/app.hxx new file mode 100644 index 000000000000..4fc9e9cb9c07 --- /dev/null +++ b/basic/source/app/app.hxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: app.hxx,v $ + * $Revision: 1.13 $ + * + * 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 _BASICAPP_HXX +#define _BASICAPP_HXX + +#include <vcl/svapp.hxx> +#ifndef _HELP_HXX //autogen +#include <vcl/help.hxx> +#endif +#ifndef _MENU_HXX //autogen +#include <vcl/menu.hxx> +#endif +#ifndef _WRKWIN_HXX //autogen +#include <vcl/wrkwin.hxx> +#endif +#include <vcl/timer.hxx> +#include <svtools/brdcst.hxx> +#include <svtools/lstner.hxx> + +class BasicFrame; +#include <basic/mybasic.hxx> + +class EditList; +class AppWin; +class AppEdit; +class AppBasEd; +class MsgEdit; +class AppError; +class StatusLine; +class BasicPrinter; +struct TTLogMsg; + +class BasicApp : public Application { + short nWait; // Wait-Zaehler +public: +// Help* pHelp; // Hilfesystem + BasicFrame* pFrame; // Frame Window +// MenuBar* pMainMenu; // Hauptmenue + Accelerator* pMainAccel; // Acceleratoren + + void Main( ); + + void LoadIniFile(); + void SetFocus(); + void Wait( BOOL ); + DECL_LINK( LateInit, void * ); + +#ifdef DBG_UTIL + DbgPrintLine DbgPrintMsgBox; +#endif +}; + + +typedef USHORT FileType; + +#define FT_NO_FILE (FileType)0x00 // An error has occurred ... +#define FT_BASIC_SOURCE (FileType)0x01 +#define FT_BASIC_INCLUDE (FileType)0x02 +#define FT_RESULT_FILE (FileType)0x04 +#define FT_RESULT_FILE_TXT (FileType)0x08 +#define FT_BASIC_LIBRARY (FileType)0x10 + +struct WinInfoRec; +class DisplayHidDlg; + +class FloatingExecutionStatus; + +class BasicFrame : public WorkWindow, public SfxBroadcaster, public SfxListener +{ +using SystemWindow::Notify; +using Window::Command; + +virtual BOOL Close(); + BOOL CloseAll(); // Close all windows + BOOL CompileAll(); // Compile all texts + AutoTimer aLineNum; // Show the line numbers +virtual void Resize(); +virtual void Move(); +virtual void GetFocus(); + void LoadLibrary(); + void SaveLibrary(); + BOOL bIsAutoRun; + DisplayHidDlg* pDisplayHidDlg; + +// BreakPoint *pRunToCursorBP; + + SbxVariable *pEditVar; + + + + Timer aCheckFiles; // Checks the files for changes + BOOL bAutoReload; + BOOL bAutoSave; + DECL_LINK( CheckAllFiles, Timer* ); + + MyBasicRef pBasic; // BASIC-Engine + + String aAppName; // Title bar content + String aAppFile; // AppName AppFile [AppMode] + String aAppMode; + void UpdateTitle(); + DECL_LINK( CloseButtonClick, void* ); + DECL_LINK( FloatButtonClick, void* ); + DECL_LINK( HideButtonClick, void* ); + + FloatingExecutionStatus *pExecutionStatus; + +public: + BOOL IsAutoRun(); + void SetAutoRun( BOOL bAuto ); + BOOL bInBreak; // TRUE if in Break-Handler + StatusLine* pStatus; // Status line + EditList* pList; // List of edit windows + AppWin* pWork; // Current edit window + BasicPrinter* pPrn; // Printer + BOOL bDisas; // TRUE: disassemble + USHORT nFlags; // Debugging-Flags + USHORT nMaximizedWindows; // Number of maximized windows + void FocusWindow( AppWin *pWin ); + void WinMax_Restore(); + void WinShow_Hide(); + void RemoveWindow( AppWin *pWin ); + void AddWindow( AppWin *pWin ); + void WindowRenamed( AppWin *pWin ); + + BasicFrame(); + ~BasicFrame(); + MyBasic& Basic() { return *pBasic; } + void AddToLRU(String const& aFile); + void LoadLRU(); + DECL_LINK( InitMenu, Menu * ); + DECL_LINK( DeInitMenu, Menu * ); + DECL_LINK( HighlightMenu, Menu * ); + DECL_LINK( MenuCommand, Menu * ); + DECL_LINK( Accel, Accelerator * ); + DECL_LINK( ShowLineNr, AutoTimer * ); + MsgEdit* GetMsgTree( String aLogFileName ); + DECL_LINK( Log, TTLogMsg * ); + DECL_LINK( WinInfo, WinInfoRec * ); + BOOL LoadFile( String aFilename ); + long Command( short,BOOL=FALSE ); // Command handler + virtual void Command( const CommandEvent& rCEvt ); // Command handler + BOOL SaveAll(); // Save all windows + BOOL QueryFileName( String& rName, FileType nFileType, BOOL bSave ); // Query for filename + DECL_LINK( ModuleWinExists, String* ); + DECL_LINK( WriteString, String* ); + AppBasEd* CreateModuleWin( SbModule* pMod ); + AppBasEd* FindModuleWin( const String& ); + AppError* FindErrorWin( const String& ); + AppWin* FindWin( const String& ); + AppWin* FindWin( USHORT nWinId ); + AppWin* IsWinValid( AppWin* pMaybeWin ); + USHORT BreakHandler(); // Break-Handler-Callback + + void SetEditVar( SbxVariable *pVar ){ pEditVar = pVar;} + SbxVariable* GetEditVar(){ return pEditVar;} + BOOL IsAutoReload() { return bAutoReload; } + BOOL IsAutoSave() { return bAutoSave; } + void LoadIniFile(); + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + + void SetAppMode( const String &aNewMode ){ aAppMode = aNewMode; UpdateTitle(); } + + String GenRealString( const String &aResString ); + +}; + +extern BasicApp aBasicApp; + +#endif diff --git a/basic/source/app/appbased.cxx b/basic/source/app/appbased.cxx new file mode 100644 index 000000000000..c81ce03c3b54 --- /dev/null +++ b/basic/source/app/appbased.cxx @@ -0,0 +1,302 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: appbased.cxx,v $ + * $Revision: 1.13.20.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <basic/sbx.hxx> +#include <svtools/texteng.hxx> +#include <svtools/textview.hxx> +#include <basic/sbmeth.hxx> +#include <svtools/stringtransfer.hxx> + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +#include "basic.hrc" +#include "status.hxx" +#include "appbased.hxx" +#include "brkpnts.hxx" +#include <basic/testtool.hxx> // defines for Syntaxhighlighting +#include "basrid.hxx" + + +TYPEINIT1(AppBasEd,AppEdit); +AppBasEd::AppBasEd( BasicFrame* pParent, SbModule* p ) +: AppEdit( pParent ) +, pBreakpoints( NULL ) +{ + pBreakpoints = new BreakpointWindow( this ); + pBreakpoints->SetFont( ((TextEdit*)pDataEdit)->GetTextEditImp().pTextEngine->GetFont() ); + + pBreakpoints->Show(); + + + ((TextEdit*)pDataEdit)->GetTextEditImp().pTextView->SetAutoIndentMode( TRUE ); + ((TextEdit*)pDataEdit)->GetTextEditImp().pTextEngine->SetMaxTextLen( STRING_MAXLEN ); +// ((TextEdit*)pDataEdit)->GetTextEditImp().pTextEngine->SetWordDelimiters( CUniString(" ,.;:(){}[]\"'+-*/<>^\\") ); + ((TextEdit*)pDataEdit)->GetTextEditImp().SyntaxHighlight( TRUE ); + ((TextEdit*)pDataEdit)->SaveAsUTF8( TRUE ); + + String aEmpty; + + pMod = p; + if( !pMod ) + { + String aModName = *pNoName; + aModName += String::CreateFromInt32( nCount ); + pMod = pFrame->Basic().MakeModule( aModName, aEmpty ); + } + bCompiled = pMod->IsCompiled(); + + pBreakpoints->SetModule( pMod ); + + // Define icon: +// pIcon = new Icon( ResId( RID_WORKICON ) ); +// if( pIcon ) SetIcon( *pIcon ); + + SetText( pMod->GetName() ); + pDataEdit->SetText( pMod->GetSource() ); + + // If a module was given, load the source from harddisk + if ( p ) + LoadSource(); + + // Dispatch event AFTER loading the sourcecode + ((TextEdit*)pDataEdit)->SetBreakpointWindow( pBreakpoints ); + + // Touch compile flag + pDataEdit->SetModifyHdl( LINK( this, AppBasEd, EditChange ) ); + +} + +AppBasEd::~AppBasEd() +{ + pBreakpoints->SaveBreakpoints( GetText() ); + delete pBreakpoints; + pMod->SetName( CUniString("--").Append( pMod->GetName() ) ); +} + +void AppBasEd::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + const SfxSimpleHint* p = PTR_CAST(SfxSimpleHint,&rHint); + if( p ) + { + ULONG nHintId = p->GetId(); + if( nHintId == SBX_HINT_LANGUAGE_EXTENSION_LOADED ) + { + ((TextEdit*)pDataEdit)->GetTextEditImp().InvalidateSyntaxHighlight(); + } + } +} + +FileType AppBasEd::GetFileType() +{ + return FT_BASIC_SOURCE; +} + +IMPL_LINK_INLINE_START( AppBasEd, EditChange, void *, p ) +{ + (void) p; /* avoid warning about unused parameter */ + bCompiled = FALSE; + return TRUE; +} +IMPL_LINK_INLINE_END( AppBasEd, EditChange, void *, p ) + +// Set up the menu +long AppBasEd::InitMenu( Menu* pMenu ) +{ + AppEdit::InitMenu (pMenu ); + BOOL bRunning = pFrame->Basic().IsRunning(); + pMenu->EnableItem( RID_RUNCOMPILE, !bCompiled && !bRunning ); + return TRUE; +} + +long AppBasEd::DeInitMenu( Menu* pMenu ) +{ + AppEdit::DeInitMenu (pMenu ); + pMenu->EnableItem( RID_RUNCOMPILE ); + return TRUE; +} + +// Menu Handler +void AppBasEd::Command( const CommandEvent& rCEvt ) +{ + switch( rCEvt.GetCommand() ) { + case RID_TOGLEBRKPNT: + ((TextEdit*)pDataEdit)->GetBreakpointWindow()->ToggleBreakpoint( pDataEdit->GetLineNr() ); + break; + default: + AppEdit::Command( rCEvt ); + } +} + +void AppBasEd::Resize() +{ + if( pDataEdit ) + { + AppEdit::Resize(); + + // Insert breakpoint window + Size aEditSize = pDataEdit->GetSizePixel(); + Point aEditPos = pDataEdit->GetPosPixel(); + + pBreakpoints->SetPosPixel( aEditPos ); + + aEditPos.X() += BREAKPOINTSWIDTH; + pDataEdit->SetPosPixel( aEditPos ); + aEditSize.Width() -= BREAKPOINTSWIDTH; + pDataEdit->SetSizePixel( aEditSize ); + + aEditSize.Width() = BREAKPOINTSWIDTH; + pBreakpoints->SetSizePixel( aEditSize ); + } +} + +void AppBasEd::PostLoad() +{ + pMod->SetName( GetText() ); + pMod->Clear(); + pMod->SetSource( pDataEdit->GetText() ); + bCompiled = FALSE; // because the code might have changed in the meantime + AppEdit::PostLoad(); + + pBreakpoints->LoadBreakpoints( GetText() ); +} + +USHORT AppBasEd::ImplSave() +{ + pBreakpoints->SaveBreakpoints( GetText() ); + return AppEdit::ImplSave(); +} + +void AppBasEd::Reload() +{ + TextSelection aSelMemo = pDataEdit->GetSelection(); + LoadSource(); + pDataEdit->SetSelection( aSelMemo ); +} + +// Reload source code file after change +void AppBasEd::LoadSource() +{ + BOOL bErr; + +// if( pDataEdit->GetText().Len() != 0 ) return; + String aName = pMod->GetName(); + bErr = !pDataEdit->Load( aName ); + pBreakpoints->LoadBreakpoints( GetText() ); + if( bErr ) + ErrorBox( this, SttResId( IDS_READERROR ) ).Execute(); + else + UpdateFileInfo( HAS_BEEN_LOADED ); + bCompiled = FALSE; // because the code might have changed in the meantime +} + +// Save as (new name) +void AppBasEd::PostSaveAs() +{ + pMod->SetName( GetText() ); + AppEdit::PostSaveAs(); +} + +// Compile +BOOL AppBasEd::Compile() +{ + if( !pDataEdit->HasText() || bCompiled ) + return TRUE; + pMod->SetSource( pDataEdit->GetText() ); + BOOL bRes = FALSE; + if( pFrame->Basic().Compile( pMod ) ) + { + bRes = TRUE; + if( pFrame->bDisas ) + Disassemble(); + TextSelection aSel( pDataEdit->GetSelection() ); + String aString; + pFrame->pStatus->Message( aString ); + if( aSel.HasRange() ) + aSel.GetStart() = aSel.GetEnd(), pDataEdit->SetSelection( aSel ); + + pBreakpoints->SetBPsInModule(); + } + else + { + BasicError* pErr = pFrame->Basic().aErrors.First(); + if( pErr ) pErr->Show(); + } + return bCompiled = bRes; +} + +void AppBasEd::Disassemble() +{ + String aText; + if( pFrame->Basic().Disassemble( pMod, aText ) ) + ::svt::OStringTransfer::CopyString( aText, this ); +} + +void AppBasEd::Run() +{ + pFrame->Basic().Reset(); + SbxArray* pAllModules = pFrame->Basic().GetModules(); + for (USHORT i = 0; i < pAllModules->Count(); i++) + { + if ( (pAllModules->Get(i)->GetName()).Copy(0,2).CompareToAscii( "--" ) == COMPARE_EQUAL ) + { + // Little hack to get around basic + SbxVariableRef pRMod = pAllModules->Get(i); + pFrame->Basic().Remove(pRMod); + i--; + } + } + + SbMethod* pMain = (SbMethod*) pMod->Find( CUniString("Main"), SbxCLASS_METHOD ); + if( pMain ) + { + pMain->SetDebugFlags( pFrame->nFlags ); + // Triggers a call! + pFrame->SetAppMode( String( SttResId( IDS_APPMODE_RUN ) ) ); + pMain->Run(); + if (aBasicApp.pFrame) + { + BasicError* pErr = aBasicApp.pFrame->Basic().aErrors.First(); + if( pErr ) + pErr->Show(); + aBasicApp.pFrame->SetAppMode( String() ); + } + pMain->SetDebugFlags( 0 ); + } +} + + diff --git a/basic/source/app/appbased.hxx b/basic/source/app/appbased.hxx new file mode 100644 index 000000000000..0977e9bab25e --- /dev/null +++ b/basic/source/app/appbased.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: appbased.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _APPBASED_HXX +#define _APPBASED_HXX + +#include <basic/sbmod.hxx> +#ifndef _SB_APPEDIT_HXX +#include "appedit.hxx" +#endif +#ifndef _SB_TEXTEDIT_HXX +#include "textedit.hxx" +#endif + +class BasicFrame; +class BreakpointWindow; + +class AppBasEd : public AppEdit { // Editor-Window: +using DockingWindow::Notify; + + SbModuleRef pMod; // compile module + BOOL bCompiled; // TRUE if compiled +protected: + DECL_LINK( EditChange, void * ); +#define BREAKPOINTSWIDTH 15 + BreakpointWindow *pBreakpoints; + virtual USHORT ImplSave(); // Save file + +public: + TYPEINFO(); + AppBasEd( BasicFrame*, SbModule* ); + ~AppBasEd(); + FileType GetFileType(); // Returns Filetype + SbModule* GetModule() { return pMod; } + long InitMenu( Menu* ); // Initialision of the menus + virtual long DeInitMenu( Menu* ); // Reset to enable all shortcuts + virtual void Command( const CommandEvent& rCEvt ); // Command handler + virtual void Resize(); // Includes the breakpoint bar + virtual void PostLoad(); // Set source of module + virtual void PostSaveAs(); // Postprocess of module... + void Reload(); + void LoadSource(); // Load source for object + BOOL Compile(); // Compile text + void Run(); // Run image + void Disassemble(); // Disassemble image + const String& GetModName() const { return pMod->GetName(); } + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); +}; + +#endif diff --git a/basic/source/app/appedit.cxx b/basic/source/app/appedit.cxx new file mode 100644 index 000000000000..a9b7b1d03b77 --- /dev/null +++ b/basic/source/app/appedit.cxx @@ -0,0 +1,304 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: appedit.cxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/config.hxx> +#include <svtools/ctrltool.hxx> +#include <svtools/textview.hxx> +#include <svtools/texteng.hxx> +#include <svtools/undo.hxx> + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +#include "basic.hrc" +#include "appedit.hxx" +#include "brkpnts.hxx" + +TYPEINIT1(AppEdit,AppWin); +AppEdit::AppEdit( BasicFrame* pParent ) +: AppWin( pParent ) +, pVScroll( NULL ) +, pHScroll( NULL ) +, nCurTextWidth(5) +{ + String aEmpty; + // perhaps load the Untitled-String: + + pDataEdit = new TextEdit( this, WB_LEFT ); + LoadIniFile(); + // define Icon: +// pIcon = new Icon( ResId( RID_WORKICON ) ); +// if( pIcon ) SetIcon( *pIcon ); + + pDataEdit->SetText( aEmpty ); + + pDataEdit->Show(); + + pVScroll = new ScrollBar( this, WB_VSCROLL|WB_DRAG ); + pVScroll->Show(); + pVScroll->SetScrollHdl( LINK( this, AppEdit, Scroll ) ); + pHScroll = new ScrollBar( this, WB_HSCROLL|WB_DRAG ); + pHScroll->Show(); + pHScroll->SetScrollHdl( LINK( this, AppEdit, Scroll ) ); + + InitScrollBars(); +} + +AppEdit::~AppEdit() +{ + DataEdit *pHold = pDataEdit; + pDataEdit = NULL; + delete pHold; + delete pHScroll; + delete pVScroll; +} + +void AppEdit::LoadIniFile() +{ + TextView *pTextView = ((TextEdit*)pDataEdit)->aEdit.pTextView; + BOOL bWasModified = pTextView->GetTextEngine()->IsModified(); + pTextView->GetTextEngine()->SetModified( FALSE ); + + FontList aFontList( pFrame ); // Just some Window is needed + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup("Misc"); + String aFontName = String( aConf.ReadKey( "ScriptFontName", "Courier" ), RTL_TEXTENCODING_UTF8 ); + String aFontStyle = String( aConf.ReadKey( "ScriptFontStyle", "normal" ), RTL_TEXTENCODING_UTF8 ); + String aFontSize = String( aConf.ReadKey( "ScriptFontSize", "12" ), RTL_TEXTENCODING_UTF8 ); + Font aFont = aFontList.Get( aFontName, aFontStyle ); +// ULONG nFontSize = aFontSize.GetValue( FUNIT_POINT ); + ULONG nFontSize = aFontSize.ToInt32(); +// aFont.SetSize( Size( nFontSize, nFontSize ) ); + aFont.SetHeight( nFontSize ); + +#if OSL_DEBUG_LEVEL > 1 + { + Font aFont2( OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetUILanguage(), 0, pFrame )); + } +#endif + aFont.SetTransparent( FALSE ); +// aFont.SetAlign( ALIGN_BOTTOM ); +// aFont.SetHeight( aFont.GetHeight()+2 ); + pDataEdit->SetFont( aFont ); + + if ( ((TextEdit*)pDataEdit)->GetBreakpointWindow() ) + { + ((TextEdit*)pDataEdit)->GetBreakpointWindow()->SetFont( aFont ); + ((TextEdit*)pDataEdit)->GetBreakpointWindow()->Invalidate(); + } + + pTextView->GetTextEngine()->SetModified( bWasModified ); // Perhaps reset the flag +} + +void AppEdit::Command( const CommandEvent& rCEvt ) +{ + switch( rCEvt.GetCommand() ) { + case COMMAND_WHEEL: + { + HandleScrollCommand( rCEvt, pHScroll, pVScroll ); + } + break; + default: + AppWin::Command( rCEvt ); + } +} + + +IMPL_LINK( AppEdit, Scroll, ScrollBar*, pScroll ) +{ + (void) pScroll; /* avoid warning about unused parameter */ + if ( !pHScroll || !pVScroll ) + return 0; + + TextView *pTextView = ((TextEdit*)pDataEdit)->aEdit.pTextView; + pTextView->SetStartDocPos( Point( pHScroll->GetThumbPos(), pVScroll->GetThumbPos() ) ); + pTextView->Invalidate(); + + if ( ((TextEdit*)pDataEdit)->GetBreakpointWindow() ) + ((TextEdit*)pDataEdit)->GetBreakpointWindow()->Scroll( 0, ((TextEdit*)pDataEdit)->GetBreakpointWindow()->GetCurYOffset() - pTextView->GetStartDocPos().Y() ); + + return 0L; +} + + +void AppEdit::InitScrollBars() +{ + if ( !pHScroll || !pVScroll ) + return; + + TextView *pTextView = ((TextEdit*)pDataEdit)->aEdit.pTextView; + + SetScrollBarRanges(); + + Size aOutSz( pTextView->GetWindow()->GetOutputSizePixel() ); + pVScroll->SetVisibleSize( aOutSz.Height() ); + pVScroll->SetPageSize( aOutSz.Height() * 8 / 10 ); + pVScroll->SetLineSize( GetTextHeight() +2 ); // +2 is empirical. don't know why + pVScroll->SetThumbPos( pTextView->GetStartDocPos().Y() ); + pVScroll->Show(); + + pHScroll->SetVisibleSize( aOutSz.Width() ); + pHScroll->SetPageSize( aOutSz.Width() * 8 / 10 ); + pHScroll->SetLineSize( GetTextWidth( CUniString("x") ) ); + pHScroll->SetThumbPos( pTextView->GetStartDocPos().X() ); + pHScroll->Show(); +} + +void AppEdit::SetScrollBarRanges() +{ + // Extra-Method, not InitScrollBars, but for EditEngine-Events. + + if ( !pHScroll || !pVScroll ) + return; + + pHScroll->SetRange( Range( 0, nCurTextWidth ) ); + pVScroll->SetRange( Range( 0, ((TextEdit*)pDataEdit)->aEdit.pTextEngine->GetTextHeight() ) ); +} + + + +USHORT AppEdit::GetLineNr() +{ + return pDataEdit->GetLineNr(); +} + +FileType AppEdit::GetFileType() +{ + return FT_BASIC_SOURCE; +} + +// Set up the menu +long AppEdit::InitMenu( Menu* pMenu ) +{ + AppWin::InitMenu (pMenu ); + + if( pDataEdit ) + { + USHORT UndoCount = ((TextEdit*)pDataEdit)->aEdit.pTextEngine->GetUndoManager().GetUndoActionCount(); + USHORT RedoCount = ((TextEdit*)pDataEdit)->aEdit.pTextEngine->GetUndoManager().GetRedoActionCount(); + + pMenu->EnableItem( RID_EDITUNDO, UndoCount > 0 ); + pMenu->EnableItem( RID_EDITREDO, RedoCount > 0 ); + } + + return TRUE; +} + +long AppEdit::DeInitMenu( Menu* pMenu ) +{ + AppWin::DeInitMenu (pMenu ); + + pMenu->EnableItem( RID_EDITUNDO ); + pMenu->EnableItem( RID_EDITREDO ); + + return TRUE; +} + +void AppEdit::Resize() +{ + if( !pDataEdit ) + return; + + Point rHStart,rVStart; + Size rHSize,rVSize; + Size rNewSize( GetOutputSizePixel() ); + + if ( pHScroll ) + { + rHSize = pHScroll->GetSizePixel(); + ULONG nHieght = rHSize.Height(); + rNewSize.Height() -= nHieght; + rHStart.Y() = rNewSize.Height(); + } + + if ( pVScroll ) + { + rVSize = pVScroll->GetSizePixel(); + ULONG nWidth = rVSize.Width(); + rNewSize.Width() -= nWidth; + rVStart.X() = rNewSize.Width(); + } + + rHSize.Width() = rNewSize.Width(); + rVSize.Height() = rNewSize.Height(); + + if ( pHScroll ) + { + pHScroll->SetPosPixel( rHStart ); + pHScroll->SetSizePixel( rHSize ); + } + + if ( pVScroll ) + { + pVScroll->SetPosPixel( rVStart ); + pVScroll->SetSizePixel( rVSize ); + } + pDataEdit->SetPosPixel( Point() ); + pDataEdit->SetSizePixel( rNewSize ); + + + TextView *pTextView = ((TextEdit*)pDataEdit)->aEdit.pTextView; + long nVisY = pTextView->GetStartDocPos().Y(); + pTextView->ShowCursor(); + Size aOutSz( pTextView->GetWindow()->GetOutputSizePixel() ); + long nMaxVisAreaStart = pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height(); + if ( nMaxVisAreaStart < 0 ) + nMaxVisAreaStart = 0; + if ( pTextView->GetStartDocPos().Y() > nMaxVisAreaStart ) + { + Point aStartDocPos( pTextView->GetStartDocPos() ); + aStartDocPos.Y() = nMaxVisAreaStart; + pTextView->SetStartDocPos( aStartDocPos ); + pTextView->ShowCursor(); +// pModulWindow->GetBreakPointWindow().GetCurYOffset() = aStartDocPos.Y(); + } + InitScrollBars(); + if ( nVisY != pTextView->GetStartDocPos().Y() ) + pTextView->GetWindow()->Invalidate(); + +} + +void AppEdit::PostLoad() +{ +} + +void AppEdit::PostSaveAs() +{ +} + +void AppEdit::Highlight( USHORT nLine, USHORT nCol1, USHORT nCol2 ) +{ + ((TextEdit*)pDataEdit)->Highlight( nLine, nCol1, nCol2 ); + ToTop(); +} + diff --git a/basic/source/app/appedit.hxx b/basic/source/app/appedit.hxx new file mode 100644 index 000000000000..8940f7c88fc0 --- /dev/null +++ b/basic/source/app/appedit.hxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: appedit.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _APPEDIT_HXX +#define _APPEDIT_HXX + +#ifndef _SCRBAR_HXX //autogen +#include <vcl/scrbar.hxx> +#endif + +#include "appwin.hxx" +#include "textedit.hxx" + +class BasicFrame; + +class AppEdit : public AppWin { // Editor window +using Window::Scroll; + +public: + ScrollBar *pVScroll; + ScrollBar *pHScroll; + void SetScrollBarRanges(); + ULONG nCurTextWidth; +private: + void InitScrollBars(); +protected: + DECL_LINK( Scroll, ScrollBar* ); +public: + TYPEINFO(); + AppEdit( BasicFrame* ); + ~AppEdit(); + USHORT GetLineNr(); // Current line number + FileType GetFileType(); // Returns the file type + virtual long InitMenu( Menu* ); // Inits the menu + virtual long DeInitMenu( Menu* ); // Reset to enable all Shortcuts + virtual void Command( const CommandEvent& rCEvt ); // Command Handler + void Resize(); + void PostLoad(); + void PostSaveAs(); + void Mark( short, short, short ); // Select text + void Highlight( USHORT nLine, USHORT nCol1, USHORT nCol2 ); + virtual BOOL ReloadAllowed(){ return !StarBASIC::IsRunning(); } + virtual void LoadIniFile(); // (re)load ini file after change +}; + +#endif diff --git a/basic/source/app/apperror.cxx b/basic/source/app/apperror.cxx new file mode 100644 index 000000000000..e1a083f3df82 --- /dev/null +++ b/basic/source/app/apperror.cxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: apperror.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/config.hxx> +#include <svtools/ctrltool.hxx> +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif +#include "basic.hrc" +#include "apperror.hxx" + +TYPEINIT1(AppError,AppWin); +AppError::AppError( BasicFrame* pParent, String aFileName ) +: AppWin( pParent ) +{ + SetText( aFileName ); // Call before MsgEdit!! + pDataEdit = new MsgEdit( this, pParent, WB_HSCROLL | WB_VSCROLL | WB_LEFT ); + LoadIniFile(); + bHasFile = pDataEdit->Load( aFileName ); + DirEntry aEntry( aFileName ); + UpdateFileInfo( HAS_BEEN_LOADED ); + // Define icon +// pIcon = new Icon( ResId( RID_WORKICON ) ); +// if( pIcon ) SetIcon( *pIcon ); + + pDataEdit->Show(); + GrabFocus(); +} + +AppError::~AppError() +{ + DataEdit* pTemp = pDataEdit; + pDataEdit = NULL; + delete pTemp; +} + +// Set up the menu +long AppError::InitMenu( Menu* pMenu ) +{ + AppWin::InitMenu (pMenu ); + + pMenu->EnableItem( RID_EDITUNDO, FALSE ); + pMenu->EnableItem( RID_EDITREDO, FALSE ); + + return TRUE; +} + +long AppError::DeInitMenu( Menu* pMenu ) +{ + AppWin::DeInitMenu (pMenu ); + + pMenu->EnableItem( RID_EDITUNDO ); + pMenu->EnableItem( RID_EDITREDO ); + + return TRUE; +} + +USHORT AppError::GetLineNr(){ return pDataEdit->GetLineNr(); } + +FileType AppError::GetFileType() +{ + return FT_RESULT_FILE; +} + +void AppError::LoadIniFile() +{ + Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + aConf.SetGroup("Misc"); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + aBaseDir = DirEntry( aConf.ReadKey("BaseDir") ); + + + FontList aFontList( pFrame ); // Just some Window is needed + aConf.SetGroup("Misc"); + String aFontName = String( aConf.ReadKey( "ScriptFontName", "Courier" ), RTL_TEXTENCODING_UTF8 ); + String aFontStyle = String( aConf.ReadKey( "ScriptFontStyle", "normal" ), RTL_TEXTENCODING_UTF8 ); + String aFontSize = String( aConf.ReadKey( "ScriptFontSize", "12" ), RTL_TEXTENCODING_UTF8 ); + Font aFont = aFontList.Get( aFontName, aFontStyle ); +// ULONG nFontSize = aFontSize.GetValue( FUNIT_POINT ); + ULONG nFontSize = aFontSize.ToInt32(); +// aFont.SetSize( Size( nFontSize, nFontSize ) ); + aFont.SetHeight( nFontSize ); + + aFont.SetTransparent( FALSE ); +// aFont.SetAlign( ALIGN_BOTTOM ); +// aFont.SetHeight( aFont.GetHeight()+2 ); + pDataEdit->SetFont( aFont ); +} diff --git a/basic/source/app/apperror.hxx b/basic/source/app/apperror.hxx new file mode 100644 index 000000000000..ca50aac4ec6d --- /dev/null +++ b/basic/source/app/apperror.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: apperror.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <appwin.hxx> +#include <msgedit.hxx> + +class AppError : public AppWin +{ +protected: + DECL_LINK( EditChange, MsgEdit * ); +public: + TYPEINFO(); + AppError( BasicFrame*, String ); + ~AppError(); +// long Command( short nID ); + virtual long InitMenu( Menu* ); + virtual long DeInitMenu( Menu* ); + USHORT GetLineNr(); + FileType GetFileType(); + MsgEdit* GetMsgTree() { return ((MsgEdit*)pDataEdit); } + virtual BOOL ReloadAllowed(){ return !StarBASIC::IsRunning(); } + virtual void LoadIniFile(); // (re)load ini file after change + DirEntry aBaseDir; +}; + diff --git a/basic/source/app/appwin.cxx b/basic/source/app/appwin.cxx new file mode 100644 index 000000000000..099dcda03e37 --- /dev/null +++ b/basic/source/app/appwin.cxx @@ -0,0 +1,660 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: appwin.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdio.h> +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <tools/fsys.hxx> +#include <svtools/stringtransfer.hxx> + +#include "basic.hrc" +#include "app.hxx" +#include <basic/mybasic.hxx> +#include "status.hxx" +#include "appwin.hxx" +#include "dataedit.hxx" +#include "dialogs.hxx" +#include "basrid.hxx" + +String *AppWin::pNoName = NULL; // contains the "Untitled"-String +short AppWin::nNumber = 0; // consecutive number +short AppWin::nCount = 0; // number of edit windows + +TYPEINIT0(AppWin); +AppWin::AppWin( BasicFrame* pParent ) +: DockingWindow( pParent, WB_SIZEMOVE | WB_CLOSEABLE | WB_PINABLE ) +, nSkipReload(0) +, bHasFile( FALSE ) +, bReloadAborted( FALSE ) +, pFrame( pParent ) +, bFind( TRUE ) +, pDataEdit(NULL) +{ + // Load the Untitled string if not yet loaded + if( !pNoName ) + pNoName = new String( SttResId( IDS_NONAME ) ); + nCount++; + + // Get maximized state from current window + USHORT nInitialWinState; + if ( pFrame->pWork ) + { + nInitialWinState = pFrame->pWork->GetWinState(); + nInitialWinState &= TT_WIN_STATE_MAX | TT_WIN_STATE_FLOAT; + } + else + nInitialWinState = TT_WIN_STATE_MAX; + + StartListening( *pFrame ); + pFrame->AddWindow( this ); + + ShowTitleButton( TITLE_BUTTON_DOCKING ); + ShowTitleButton( TITLE_BUTTON_HIDE ); + SetActivateMode( ACTIVATE_MODE_GRABFOCUS ); + + Cascade( nCount ); + if ( TT_WIN_STATE_MAX == nInitialWinState ) + Maximize(); +} + +AppWin::~AppWin() +{ + nCount--; + pFrame->RemoveWindow( this ); + pFrame = NULL; // Set to stop setting window text after BasicRun +} + +void AppWin::SetText( const XubString& rStr ) +{ + DockingWindow::SetText( rStr ); + pFrame->WindowRenamed( this ); +} + +void AppWin::TitleButtonClick( USHORT nButton ) +{ + if ( TITLE_BUTTON_DOCKING == nButton ) + if ( TT_WIN_STATE_MAX != nWinState ) + Maximize(); + else + Restore(); + else // if ( TITLE_BUTTON_HIDE == nButton ) + Minimize( TRUE ); +} + +void AppWin::Maximize() +{ + if ( TT_WIN_STATE_MAX != nWinState ) + { + nNormalPos = GetPosPixel(); + nNormalSize = GetSizePixel(); + + SetFloatingMode( FALSE ); + + pFrame->nMaximizedWindows++; + nWinState = TT_WIN_STATE_MAX; + } + sal_Int32 nTitleHeight; + { + sal_Int32 nDummy1, nDummy2, nDummy3; + pFrame->GetBorder( nDummy1, nTitleHeight, nDummy2, nDummy3 ); + } + + Size aSize = pFrame->GetOutputSizePixel(); + aSize.Height() -= nTitleHeight; + aSize.Height() -= 2; + aSize.Width() -= 2; + SetSizePixel( aSize ); + SetPosPixel( Point( 1,1 ) ); + pFrame->WinMax_Restore(); +} + +void AppWin::Restore() +{ + SetFloatingMode( TRUE ); + SetPosSizePixel( nNormalPos, nNormalSize ); + + if ( TT_WIN_STATE_MAX == nWinState ) + pFrame->nMaximizedWindows--; + + nWinState = TT_WIN_STATE_FLOAT; + pFrame->WinMax_Restore(); +} + +void AppWin::Minimize( BOOL bMinimize ) +{ + if ( bMinimize ) + nWinState |= TT_WIN_STATE_HIDE; + else + nWinState &= ~TT_WIN_STATE_HIDE; + pFrame->WinMax_Restore(); +} + +void AppWin::Cascade( USHORT nNr ) +{ + Restore(); + + nNr--; + nNr %= 10; + nNr++; + + sal_Int32 nTitleHeight; + { + sal_Int32 nDummy1, nDummy2, nDummy3; + pFrame->GetBorder( nDummy1, nTitleHeight, nDummy2, nDummy3 ); + } + + Size aWinSize = pFrame->GetOutputSizePixel(); + aWinSize.Width() -= aWinSize.Width() / 5; // reduce to 80 % + aWinSize.Height() -= nTitleHeight * nNr; // snip height to appropriate value + aWinSize.Height() -= 2; + + Point nPos( nTitleHeight * nNr, nTitleHeight * nNr ); + + SetPosSizePixel( nPos, aWinSize ); +} + +void AppWin::RequestHelp( const HelpEvent& ) +{ + Help(); +} + +void AppWin::Help() +{ + String s = pDataEdit->GetSelected(); + if( s.Len() > 0 ) + { + // Trim leading whitespaces + while( s.GetChar(0) == ' ' ) + s.Erase( 0, 1 ); +// aBasicApp.pHelp->Start( s ); + } + else + { +// aBasicApp.pHelp->Start( OOO_HELP_INDEX ); + } +} + +void AppWin::Resize() +{ + if( pDataEdit ) + { + pDataEdit->SetPosPixel( Point( 0, 0 ) ); + pDataEdit->SetSizePixel( GetOutputSizePixel() ); + } +} + +void AppWin::GetFocus() +{ + pFrame->FocusWindow( this ); + if( pDataEdit ) // GetFocus is called by the destructor, so this check + { + pDataEdit->GrabFocus(); +// InitMenu(GetpApp()->GetAppMenu()->GetPopupMenu( RID_APPEDIT )); + } +} + +long AppWin::PreNotify( NotifyEvent& rNEvt ) +{ + + if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) + Activate(); + if ( rNEvt.GetType() == EVENT_GETFOCUS ) + if ( pFrame->pList->Last() != this ) + Activate(); + return FALSE; // Der event soll weiter verarbeitet werden +} + +void AppWin::Activate() +{ + GrabFocus(); +} + +// Set up the menu +long AppWin::InitMenu( Menu* pMenu ) +{ + + ::rtl::OUString aTemp; + BOOL bMarked; + if( pDataEdit ) + { + TextSelection r = pDataEdit->GetSelection(); + bMarked = r.HasRange(); + } + else + bMarked = FALSE; + pMenu->EnableItem( RID_EDITREPEAT, (aFind.Len() != 0 ) ); + pMenu->EnableItem( RID_EDITCUT, bMarked ); + pMenu->EnableItem( RID_EDITCOPY, bMarked ); + pMenu->EnableItem( RID_EDITPASTE, ( ::svt::OStringTransfer::PasteString( aTemp, this ) ) ); + pMenu->EnableItem( RID_EDITDEL, bMarked ); +// pMenu->EnableItem( RID_HELPTOPIC, bMarked ); + + BOOL bHasText; + if( pDataEdit ) + bHasText = pDataEdit->HasText(); + else + bHasText = FALSE; + BOOL bRunning = pFrame->Basic().IsRunning(); + BOOL bCanExecute = BOOL( (!bRunning && bHasText) || pFrame->bInBreak ); + pMenu->EnableItem( RID_RUNSTART, bCanExecute ); + pMenu->EnableItem( RID_RUNBREAK, bRunning && !pFrame->bInBreak); + pMenu->EnableItem( RID_RUNSTOP, bRunning ); + pMenu->EnableItem( RID_RUNTOCURSOR, bCanExecute ); + pMenu->EnableItem( RID_RUNSTEPINTO, bCanExecute ); + pMenu->EnableItem( RID_RUNSTEPOVER, bCanExecute ); + return TRUE; +} + +long AppWin::DeInitMenu( Menu* pMenu ) +{ + pMenu->EnableItem( RID_EDITREPEAT ); + pMenu->EnableItem( RID_EDITCUT ); + pMenu->EnableItem( RID_EDITCOPY ); + pMenu->EnableItem( RID_EDITPASTE ); + pMenu->EnableItem( RID_EDITDEL ); + + pMenu->EnableItem( RID_RUNSTART ); + pMenu->EnableItem( RID_RUNBREAK ); + pMenu->EnableItem( RID_RUNSTOP ); + pMenu->EnableItem( RID_RUNTOCURSOR ); + pMenu->EnableItem( RID_RUNSTEPINTO ); + pMenu->EnableItem( RID_RUNSTEPOVER ); + return TRUE; +} + +// Menu Handler + +void AppWin::Command( const CommandEvent& rCEvt ) +{ + TextSelection r = pDataEdit->GetSelection(); + BOOL bHasMark = r.HasRange(); + switch( rCEvt.GetCommand() ) { + case RID_FILESAVE: + QuerySave( QUERY_DISK_CHANGED | SAVE_NOT_DIRTY ); break; + case RID_FILESAVEAS: + SaveAs(); break; + case RID_EDITSEARCH: + Find(); break; + case RID_EDITREPLACE: + Replace(); break; + case RID_EDITREPEAT: + Repeat(); break; + case RID_EDITCUT: + if( bHasMark ) + pDataEdit->Cut(); + break; + case RID_EDITCOPY: + if( bHasMark ) + pDataEdit->Copy(); + break; + case RID_EDITPASTE: + { + ::rtl::OUString aTemp; + if( ::svt::OStringTransfer::PasteString( aTemp, this ) ) + pDataEdit->Paste(); + } + break; + case RID_EDITDEL: + /*if( bHasMark ) */pDataEdit->Delete(); + break; + case RID_EDITUNDO: + pDataEdit->Undo(); + break; + case RID_EDITREDO: + pDataEdit->Redo(); + break; + case COMMAND_CONTEXTMENU: + { + PopupMenu *pKontext = NULL; + pDataEdit->BuildKontextMenu( pKontext ); + if ( pKontext ) + { + USHORT nRes = pKontext->Execute( this, GetPointerPosPixel() ); + if ( nRes ) + pFrame->Command( nRes ); + delete pKontext; + } + } + break; + } +} + + +BOOL AppWin::IsSkipReload() +{ + return nSkipReload != 0; +} + +void AppWin::SkipReload( BOOL bSkip ) +{ + DBG_ASSERT( bSkip || nSkipReload, "SkipReload aufgehoben ohne es zu aktivieren"); + if ( bSkip ) + nSkipReload++; + else + nSkipReload--; +} + +BOOL AppWin::DiskFileChanged( USHORT nWhat ) +{ + if ( !bHasFile ) + return FALSE; + + switch ( nWhat ) + { + case SINCE_LAST_LOAD: + { + if ( bReloadAborted ) + return TRUE; + else + return DiskFileChanged( SINCE_LAST_ASK_RELOAD ); + } +// uncomment to avoid compiler warning +// break; + case SINCE_LAST_ASK_RELOAD: + { + String aFilename( GetText() ); + + DirEntry aFile( aFilename ); + FileStat aStat( aFile ); + + return ( !aLastAccess.GetError() != !aStat.GetError() ) + || aLastAccess.IsYounger( aStat ) || aStat.IsYounger( aLastAccess ); + } +// uncomment to avoid compiler warning +// break; + default: + DBG_ERROR("Not Implemented in AppWin::DiskFileChanged"); + } + return TRUE; +} + +void AppWin::UpdateFileInfo( USHORT nWhat ) +{ + switch ( nWhat ) + { + case HAS_BEEN_LOADED: + { + bReloadAborted = FALSE; + UpdateFileInfo( ASKED_RELOAD ); + + } + break; + case ASKED_RELOAD: + { + String aFilename( GetText() ); + + DirEntry aFile( aFilename ); + aLastAccess.Update( aFile ); + } + break; + default: + DBG_ERROR("Not Implemented in AppWin::UpdateFileInfo"); + } +} + +void AppWin::CheckReload() +{ + if ( IsSkipReload() || !bHasFile ) + return; + + String aFilename( GetText() ); + DirEntry aFile( aFilename ); + if ( !aFilename.Len() ) + return; + + if ( !aFile.Exists() ) + return; + +// FileStat aStat( aFile ); + + if ( DiskFileChanged( SINCE_LAST_ASK_RELOAD ) && ReloadAllowed() ) + { + UpdateFileInfo( ASKED_RELOAD ); + ToTop(); + Update(); + if ( (IsModified() && QueryBox( this, SttResId( IDS_ASKDIRTYRELOAD ) ).Execute() == RET_YES ) + || ( !IsModified() && ( pFrame->IsAutoReload() || QueryBox( this, SttResId( IDS_ASKRELOAD ) ).Execute() == RET_YES ) ) ) + { + Reload(); + } + else + { + bReloadAborted = TRUE; + } + } +} + +void AppWin::Reload() +{ + SkipReload(); + TextSelection aSelMemo = pDataEdit->GetSelection(); + Load( GetText() ); + pDataEdit->SetSelection( aSelMemo ); + SkipReload( FALSE ); +} + +// Load file +BOOL AppWin::Load( const String& aName ) +{ + SkipReload(); + BOOL bErr; + +// if( !QuerySave() ) +// return; + bErr = !pDataEdit->Load( aName ); + if( bErr ) + { + ErrorBox aBox( this, SttResId( IDS_READERROR ) ); + String aMsg = aBox.GetMessText(); + aMsg.AppendAscii("\n\""); + aMsg.Append( aName ); + aMsg.AppendAscii("\""); + if ( pFrame->IsAutoRun() ) + { + printf( "%s\n", ByteString( aMsg, osl_getThreadTextEncoding() ).GetBuffer() ); + } + else + { + aBox.SetMessText( aMsg ); + aBox.Execute(); + } + } + else + { + DirEntry aEntry( aName ); + String aModName = aEntry.GetFull(); + SetText( aModName ); + UpdateFileInfo( HAS_BEEN_LOADED ); + PostLoad(); + bHasFile = TRUE; + } + SkipReload( FALSE ); + return !bErr; +} + +// Save file +USHORT AppWin::ImplSave() +{ + SkipReload(); + USHORT nResult = SAVE_RES_NOT_SAVED; + String s1 = *pNoName; + String s2 = GetText().Copy( 0, s1.Len() ); + if( s1 == s2 ) + nResult = SaveAs(); + else { + String aName = GetText(); + if ( pDataEdit->Save( aName ) ) + { + nResult = SAVE_RES_SAVED; + bHasFile = TRUE; + } + else + { + nResult = SAVE_RES_ERROR; + ErrorBox( this, SttResId( IDS_WRITEERROR ) ).Execute(); + } + UpdateFileInfo( HAS_BEEN_LOADED ); + } + SkipReload( FALSE ); + return nResult; +} + +// Save to new file name +USHORT AppWin::SaveAs() +{ + SkipReload(); + String s1 = *pNoName; + String s2 = GetText().Copy( 0, s1.Len() ); + if( s1 == s2 ) s2.Erase(); + else s2 = GetText(); + if( pFrame->QueryFileName( s2, GetFileType(), TRUE ) ) + { + SetText( s2 ); + PostSaveAs(); + SkipReload( FALSE ); + return ImplSave(); + } + else + { + SkipReload( FALSE ); + return SAVE_RES_CANCEL; + } +} + +// Should we save the file? +USHORT AppWin::QuerySave( QueryBits nBits ) +{ + BOOL bQueryDirty = ( nBits & QUERY_DIRTY ) != 0; + BOOL bQueryDiskChanged = ( nBits & QUERY_DISK_CHANGED ) != 0; + BOOL bSaveNotDirty = ( nBits & SAVE_NOT_DIRTY ) != 0; + + SkipReload(); + short nResult; + if ( IsModified() || bSaveNotDirty ) + nResult = RET_YES; + else + nResult = RET_NO; + + BOOL bAlwaysEnableInput = pFrame->IsAlwaysEnableInput(); + pFrame->AlwaysEnableInput( FALSE ); + if( ( ( IsModified() || bSaveNotDirty ) && bQueryDirty ) || ( DiskFileChanged( SINCE_LAST_LOAD ) && bQueryDiskChanged ) ) + { + ToTop(); + if ( ( ( IsModified() && bQueryDirty ) && DiskFileChanged( SINCE_LAST_LOAD ) ) + || ( IsModified() && ( DiskFileChanged( SINCE_LAST_LOAD ) && bQueryDiskChanged ) ) ) + nResult = QueryBox( this, SttResId( IDS_ASK_DIRTY_AND_DISKCHANGE_SAVE ) ).Execute(); + else if ( ( IsModified() && bQueryDirty ) ) + nResult = QueryBox( this, SttResId( IDS_ASK_DIRTY_SAVE ) ).Execute(); + else + nResult = QueryBox( this, SttResId( IDS_ASK_DISKCHANGE_SAVE ) ).Execute(); + } + pFrame->AlwaysEnableInput( bAlwaysEnableInput ); + + USHORT nReturn; + switch( nResult ) + { + case RET_YES: + nReturn = ImplSave(); + break; + case RET_NO: + nReturn = SAVE_RES_NOT_SAVED; + break; + case RET_CANCEL: + nReturn = SAVE_RES_CANCEL; + break; + default: + DBG_ERROR("switch default where no default should be: Internal error"); + nReturn = SAVE_RES_CANCEL; + } + SkipReload( FALSE ); + return nReturn; +} + +BOOL AppWin::Close() +{ + switch ( QuerySave( QUERY_DIRTY ) ) + { + case SAVE_RES_NOT_SAVED: + case SAVE_RES_SAVED: + { + DockingWindow::Close(); + delete this; + return TRUE; + } +// uncomment to avoid compiler warning +// break; + case SAVE_RES_ERROR: + return FALSE; +// uncomment to avoid compiler warning +// break; + case SAVE_RES_CANCEL: + return FALSE; +// uncomment to avoid compiler warning +// break; + default: + DBG_ERROR("Not Implemented in AppWin::Close"); + return FALSE; + } +} + +// Search and find text +void AppWin::Find() +{ + SttResId aResId( IDD_FIND_DIALOG ); + FindDialog aDlg( this, aResId, aFind ); + if( aDlg.Execute() ) { + bFind = TRUE; + Repeat(); + } +} + +// Replace text +void AppWin::Replace() +{ + SttResId aResId( IDD_REPLACE_DIALOG ); + ReplaceDialog* pDlg = new ReplaceDialog + (this, aResId, aFind, aReplace ); + if( pDlg->Execute() ) { + bFind = FALSE; + Repeat(); + } +} + +// Repeat search/replace operation +void AppWin::Repeat() +{ + if( (aFind.Len() != 0 ) && ( pDataEdit->Find( aFind ) || (ErrorBox(this,SttResId(IDS_PATTERNNOTFOUND)).Execute() && FALSE) ) && !bFind ) + pDataEdit->ReplaceSelected( aReplace ); +} + diff --git a/basic/source/app/appwin.hxx b/basic/source/app/appwin.hxx new file mode 100644 index 000000000000..14ca4e6eb448 --- /dev/null +++ b/basic/source/app/appwin.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: appwin.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _APPWIN_HXX +#define _APPWIN_HXX + +//#include <sb.hxx> +#include <vcl/dockwin.hxx> +#include <tools/fsys.hxx> + +#include "app.hxx" +#include "dataedit.hxx" + +typedef USHORT QueryBits; +#define QUERY_NONE ( QueryBits ( 0x00 ) ) +#define QUERY_DIRTY ( QueryBits ( 0x01 ) ) +#define QUERY_DISK_CHANGED ( QueryBits ( 0x02 ) ) +#define QUERY_ALL ( QUERY_DIRTY | QUERY_DISK_CHANGED ) +#define SAVE_NOT_DIRTY ( QueryBits ( 0x04 ) ) + +#define SAVE_RES_SAVED TRUE +#define SAVE_RES_NOT_SAVED FALSE +#define SAVE_RES_ERROR 3 +#define SAVE_RES_CANCEL 4 + + +#define SINCE_LAST_LOAD 1 +#define SINCE_LAST_ASK_RELOAD 2 + +#define HAS_BEEN_LOADED 1 // includes ASKED_RELOAD +#define ASKED_RELOAD 2 + + +#define TT_WIN_STATE_MAX 0x01 +#define TT_WIN_STATE_FLOAT 0x02 +#define TT_WIN_STATE_HIDE 0x04 + +class BasicFrame; + +class AppWin : public DockingWindow, public SfxListener // Document window +{ + friend class MsgEdit; +protected: + static short nNumber; // serial number + static short nCount; // number of edit windows + static String *pNoName; // "Untitled" + FileStat aLastAccess; // Last access time of loaded file + USHORT nSkipReload; // Sometimes there must not be a reload + BOOL bHasFile; // Otherwise reload does not make sense + BOOL bReloadAborted; // Is set if reload was cancelled so that we can ask again wehn closing + + short nId; // ID-Nummer( "Unnamed n" ) + BasicFrame* pFrame; // Parent-Window +// Icon* pIcon; // Document icon + String aFind; // Search string + String aReplace; // Replace string + BOOL bFind; // TRUE if search not replace + void RequestHelp( const HelpEvent& ); // Help handler + void GetFocus(); // activate + virtual USHORT ImplSave(); // Save file + USHORT nWinState; // Maximized, Iconized or Normal + Point nNormalPos; // Position if normal + Size nNormalSize; // Size if Normal + virtual long PreNotify( NotifyEvent& rNEvt ); + USHORT nWinId; + +public: + TYPEINFO(); + AppWin( BasicFrame* ); + ~AppWin(); + DataEdit* pDataEdit; // Data area + virtual USHORT GetLineNr()=0; // Current line number + virtual long InitMenu( Menu* ); // Init of the menu + virtual long DeInitMenu( Menu* ); // reset to enable all shortcuts + virtual void Command( const CommandEvent& rCEvt ); // Command handler + virtual void Resize(); + virtual void Help(); + virtual BOOL Load( const String& ); // Load file + virtual void PostLoad(){} // Set source at module + virtual USHORT SaveAs(); // Save file as + virtual void PostSaveAs(){} + virtual void Find(); // find text + virtual void Replace(); // replace text + virtual void Repeat(); // repeat find/replace + virtual BOOL Close(); // close window + virtual void Activate(); // window was activated + virtual FileType GetFileType()=0; // returns the filetype + virtual BOOL ReloadAllowed(){ return TRUE; } + virtual void Reload(); // Reload after change on disk + virtual void LoadIniFile(){;} // (re)load ini file after change + void CheckReload(); // Checks and asks if reload should performed + BOOL DiskFileChanged( USHORT nWhat ); // Checks file for changes + void UpdateFileInfo( USHORT nWhat ); // Remembers last file state + BOOL IsSkipReload(); // Should we test reload? + void SkipReload( BOOL bSkip = TRUE ); + USHORT GetWinState(){ return nWinState; } + void Maximize(); + void Restore(); + void Minimize( BOOL bMinimize ); + void Cascade( USHORT nNr ); + + USHORT QuerySave( QueryBits nBits = QUERY_ALL ); + BOOL IsModified() { return pDataEdit->IsModified(); } + BasicFrame* GetBasicFrame() { return pFrame; } + virtual void TitleButtonClick( USHORT nButton ); + virtual void SetText( const XubString& rStr ); + + USHORT GetWinId() { return nWinId; } + void SetWinId( USHORT nWId ) { nWinId = nWId; } +}; + +DECLARE_LIST( EditList, AppWin* ) + +#endif diff --git a/basic/source/app/basic.hrc b/basic/source/app/basic.hrc new file mode 100644 index 000000000000..5a030cb36ac2 --- /dev/null +++ b/basic/source/app/basic.hrc @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basic.hrc,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#define RID_OPTLIST 101 +#define RID_OPTLINES 102 +#define RID_OPTPACKS 103 +#define RID_OPTPACKD 104 +#define RID_OPTWARN1 105 +#define RID_OPTWARN2 106 +#define RID_OPTVIRT 107 +#define RID_PARAMS 108 +#define RID_RETTYPE 109 +#define RID_RETVAL 110 +//#define RID_APPICON 500 +//#define RID_APPICON2 501 +//#define RID_WORKICON 502 +//#define RID_LOADICON 503 +//#define RID_SAVEICON 504 +#define RID_APPMENUBAR 1000 +#define RID_APPFILE 1001 +#define RID_APPEDIT 1002 +#define RID_APPRUN 1003 +#define RID_APPWINDOW 1004 +#define RID_APPHELP 1005 +#define RID_FILE 1100 +#define RID_FILENEW 1101 +#define RID_FILEOPEN 1102 +#define RID_FILECLOSE 1103 +#define RID_FILESAVE 1104 +#define RID_FILESAVEAS 1105 +#define RID_FILELOADLIB 1106 +#define RID_FILESAVELIB 1107 +#define RID_FILEPRINT 1109 +#define RID_FILESETUP 1110 +#define RID_QUIT 1111 +#define IDM_FILE_LRU1 1112 +#define IDM_FILE_LRUn 1199 +#define RID_EDIT 1200 +#define RID_EDITUNDO 1201 +#define RID_EDITREDO 1202 +#define RID_EDITCUT 1203 +#define RID_EDITCOPY 1204 +#define RID_EDITPASTE 1205 +#define RID_EDITDEL 1206 +#define RID_EDITSEARCH 1207 +#define RID_EDITREPLACE 1208 +#define RID_EDITREPEAT 1209 +#define RID_RUN 1300 +#define RID_RUNCOMPILE 1301 +#define RID_RUNSTART 1302 +#define RID_RUNBREAK 1304 +#define RID_RUNSTOP 1303 +#define RID_RUNNEXTERR 1307 +#define RID_RUNPREVERR 1308 +#define RID_RUNDISAS 1310 +#define RID_RUNSTEPINTO 1311 +#define RID_RUNSTEPOVER 1312 +#define RID_RUNTOCURSOR 1313 +#define RID_TOGLEBRKPNT 1314 +#define RID_TT_EXTRAS_NAME 1400 +#define RID_TT_EXTRAS 1401 +#define RID_OPTIONS 1402 +#define RID_DECLARE_HELPER 1403 +#define RID_WINDOW 1501 +#define RID_WINTILE 1502 +#define RID_WINTILEHORZ 1503 +#define RID_WINTILEVERT 1504 +#define RID_WINCASCADE 1505 +#define RID_WIN_FILE1 1520 +#define RID_WIN_FILEn 1599 + +#define RID_HELP 1601 +//#define RID_HELPINDEX 1602 +//#define RID_HELPKEYS 1603 +//#define RID_HELPINTRO 1604 +//#define RID_HELPTOPIC 1605 +#define RID_HELPABOUT 1606 +#define RID_POPUP 1700 +#define RID_POPUPEDITVAR 1701 + + + +#define IDS_APPNAME 2000 +#define IDS_APPNAME2 2001 +#define IDS_APPMODE_BREAK 2002 +#define IDS_APPMODE_RUN 2003 +#define IDS_NONAME 2100 +#define IDS_NONAMEFILE 2101 +#define IDS_INCFILE 2102 +#define IDS_LIBFILE 2103 +#define IDS_RESFILE 2104 +#define IDS_TXTFILE 2105 +#define IDS_READERROR 2103 +#define IDS_WRITEERROR 2104 +#define IDS_COMPERROR 2105 +#define IDS_CONTINUE 2106 +#define IDS_CANCEL 2107 +#define IDS_NOPRINTERERROR 2108 +#define IDS_PATTERNNOTFOUND 2109 +#define IDS_INVALID_VALUE 2110 +#define IDS_ASK_DIRTY_SAVE 2200 +#define IDS_ASK_DISKCHANGE_SAVE 2201 +#define IDS_ASK_DIRTY_AND_DISKCHANGE_SAVE 2202 +#define IDS_ASKSAVEERROR 2203 +#define IDS_ASKRELOAD 2204 +#define IDS_ASKDIRTYRELOAD 2205 +#define IDS_LOADDLG 2300 +#define IDS_SAVEDLG 2301 +#define IDS_BASFILTER 2304 +#define IDS_LIBFILTER 2305 +#define IDS_INCFILTER 2306 +#define IDS_RESFILTER 2307 +#define IDS_TXTFILTER 2308 +#define IDS_PAGE 2401 +#define IDS_PRINTMSG 2402 +#define IDS_CANTLOAD 2501 +#define IDS_CANTSAVE 2502 +#define IDS_ERROR1 2601 +#define IDS_ERROR2 2602 +#define IDS_WARNING1 2603 +#define IDS_NO_LONGNAME 2604 +#define IDS_WARNING_PREFIX 2605 +#define IDS_OBJECT 2606 +#define IDS_EDIT_VAR 2607 + +#define IDS_NOMAINPGM 2701 +#define IDS_DISASWIN 2702 +#define IDS_RUNNING 2703 +#define IDS_NOT_YET_IMPLEMENTED 2704 +#define IDS_LOSS_OF_INFORMATION 2705 + +#define RID_ACCEL 3000 + +#define IDD_LOADSAVE_DIALOG 4001 +#define IDD_ABOUT_DIALOG 4002 +#define IDD_TT_ABOUT_DIALOG 4003 +#define IDD_FIND_DIALOG 4004 +#define IDD_REPLACE_DIALOG 4005 +#define IDD_PRINT_DIALOG 4006 +#define IDD_OPTIONS_DLG 4007 +#define RID_TP_PROFILE 4008 +#define RID_TP_CRASH 4009 +#define RID_TP_MISC 4010 +#define RID_TP_FONT 4011 +#define RID_TP_GENERIC 4012 +#define IDD_DISPLAY_HID 4013 +#define IDD_EDIT_VAR 4014 + + +//#define RID_APPFONT 5000 +//#define RID_APPEDITFONT 5001 +//#define RID_DLGBRUSH 5002 +#define RID_CALLDLG 6001 +#define MBP_PLUS 8001 +#define MBP_MINUS 8002 +#define RID_IMGLST_LAYOUT 8005 +#define MAIN_ACCEL 9001 + +#define LOAD_CONF 10001 +#define WORK 10002 +#define FILENAME 10003 diff --git a/basic/source/app/basic.src b/basic/source/app/basic.src new file mode 100644 index 000000000000..1eb8d1b4c880 --- /dev/null +++ b/basic/source/app/basic.src @@ -0,0 +1,1475 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basic.src,v $ + * $Revision: 1.67 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "basic.hrc" +#include "resids.hrc" + +ModalDialog RID_CALLDLG { + PosSize = MAP_SYSFONT (18,18,142,142); + SVLook = TRUE; + MOVEABLE = TRUE; + CLOSEABLE = TRUE; +// WinChilds = { +// FixedText { +// Text = "Aktuelle Parameter"; +// PosSize = MAP_SYSFONT (10,10,120,8); +// }; +// }; + FixedText RID_RETTYPE { + PosSize = MAP_SYSFONT (10,70,120,8); + }; + Edit RID_RETVAL { + PosSize = MAP_SYSFONT (10,85,120,12); + Border = TRUE; + TabStop = TRUE; + }; + ListBox RID_PARAMS { + PosSize = MAP_SYSFONT (10,25,120,40); + TabStop = TRUE; + Border = TRUE; + }; + OKButton RID_OK { + PosSize = MAP_SYSFONT (50,105,40,14); + TabStop = TRUE; + DefButton = TRUE; + }; + Text[ en-US ] = "Dynamic Link No. "; +}; + +ModalDialog IDD_ABOUT_DIALOG { + Pos = MAP_APPFONT( 58, 17 ); + Size = MAP_APPFONT( 155, 106 ); + SVLook = TRUE; +/* + WINCHILDS = { + FixedText { + Pos = MAP_APPFONT( 40, 5 ); + Size = MAP_APPFONT( 110, 10 ); + TEXT = "Testtool"; + CENTER = TRUE; + }; + FixedText { + Pos = MAP_APPFONT( 40, 20 ); + Size = MAP_APPFONT( 110, 20 ); + TEXT = "Ojektorientiertes BASIC-Entwicklungssystem"; + CENTER = TRUE; + }; + FixedText { + Pos = MAP_APPFONT( 40, 45 ); + Size = MAP_APPFONT( 110, 10 ); + TEXT = "Version 2.0 May 2002"; + CENTER = TRUE; + }; + FixedText { + Pos = MAP_APPFONT( 40, 60 ); + Size = MAP_APPFONT( 110, 10 ); + TEXT = "®1995 Sun Microsystems, Inc."; + CENTER = TRUE; + }; + }; +*/ +// FixedIcon RID_ICON { +// Pos = MAP_APPFONT( 20, 26 ); +// Size = MAP_APPFONT( 20, 20 ); +// FIXED = Icon { +// FILE = "basic.ico"; +// }; +// }; + OKButton RID_OK { + Pos = MAP_APPFONT( 55, 80 ); + Size = MAP_APPFONT( 40, 14 ); + DefButton = TRUE; + }; +}; + +ModalDialog IDD_TT_ABOUT_DIALOG { + Pos = MAP_APPFONT( 58, 17 ); + Size = MAP_APPFONT( 120, 81 ); + SVLook = TRUE; + MOVEABLE = TRUE; + FixedText 1 { + Pos = MAP_APPFONT( 5, 10 ); + Size = MAP_APPFONT( 110, 10 ); + CENTER = TRUE; + TEXT[ en-US ] = "VCLTestTool"; + }; + FixedText RID_VERSIONSTRING { + Pos = MAP_APPFONT( 5, 25 ); + Size = MAP_APPFONT( 110, 10 ); + Text = UPDVER; + CENTER = TRUE; + }; + FixedText 4 { + Pos = MAP_APPFONT( 5, 40 ); + Size = MAP_APPFONT( 110, 10 ); + CENTER = TRUE; + TEXT[ en-US ] = "©1995-2005 Sun Microsystems, Inc."; + }; + OKButton RID_OK { + Pos = MAP_APPFONT( 40, 60 ); + Size = MAP_APPFONT( 40, 14 ); + DefButton = TRUE; + }; + TEXT[ en-US ] = "About VCLTestTool"; +}; + +ModalDialog IDD_FIND_DIALOG { + Pos = MAP_APPFONT( 69, 30 ); + Size = MAP_APPFONT( 185, 70 ); + SVLook = TRUE; + MOVEABLE = TRUE; + // CLOSEABLE = TRUE; // Hat cancelbutton + + FixedText RID_FIXEDTEXT1 { + Pos = MAP_APPFONT( 5, 10 ); + Size = MAP_APPFONT( 30, 10 ); + TEXT[ en-US ] = "~Text"; + }; + Edit RID_FIND { + BORDER = TRUE; + Pos = MAP_APPFONT( 40, 8 ); + Size = MAP_APPFONT( 135, 12 ); + TABSTOP = TRUE; + }; + OKButton RID_OK { + Pos = MAP_APPFONT( 30, 30 ); + Size = MAP_APPFONT( 50, 14 ); + TABSTOP = TRUE; + DefButton = TRUE; + TEXT[ en-US ] = "~Find"; + }; + CancelButton RID_CANCEL { + Pos = MAP_APPFONT( 105, 30 ); + Size = MAP_APPFONT( 50, 14 ); + TABSTOP = TRUE; + TEXT[ en-US ] = "~Cancel"; + }; + TEXT[ en-US ] = "Testtool: Find Text"; +}; + +ModalDialog IDD_REPLACE_DIALOG { + Pos = MAP_APPFONT( 69, 30 ); + Size = MAP_APPFONT( 185, 88 ); + SVLook = TRUE; + MOVEABLE = TRUE; + // CLOSEABLE = TRUE; // Hat cancelbutton + FixedText RID_FIXEDTEXT1 { + Pos = MAP_APPFONT( 5, 10 ); + Size = MAP_APPFONT( 55, 10 ); + TEXT[ en-US ] = "~Search for"; + }; + FixedText RID_FIXEDTEXT2 { + Pos = MAP_APPFONT( 5, 30 ); + Size = MAP_APPFONT( 55, 10 ); + TEXT[ en-US ] = "~Replace by"; + }; + Edit RID_FIND { + BORDER = TRUE; + Pos = MAP_APPFONT( 65, 8 ); + Size = MAP_APPFONT( 110, 12 ); + TABSTOP = TRUE; + }; + Edit RID_REPLACE { + BORDER = TRUE; + Pos = MAP_APPFONT( 65, 28 ); + Size = MAP_APPFONT( 110, 12 ); + TABSTOP = TRUE; + }; + OKButton RID_OK { + Pos = MAP_APPFONT( 30, 50 ); + Size = MAP_APPFONT( 50, 14 ); + TABSTOP = TRUE; + DefButton = TRUE; + TEXT[ en-US ] = "~Replace"; + }; + CancelButton RID_CANCEL { + Pos = MAP_APPFONT( 105, 50 ); + Size = MAP_APPFONT( 50, 14 ); + TABSTOP = TRUE; + TEXT[ en-US ] = "~Cancel"; + }; + TEXT[ en-US ] = "Testtool: Replace Text"; +}; + +InfoBox IDS_NOPRINTERERROR { + MESSAGE[ en-US ] = "The print function is not available!"; +}; +ErrorBox IDS_CANTLOAD { + MESSAGE[ en-US ] = "Library cannot be loaded!"; + Title[ en-US ] = "Testtool Error"; +}; +ErrorBox IDS_CANTSAVE { + MESSAGE[ en-US ] = "Library cannot be saved!"; + Title[ en-US ] = "Testtool Error"; +}; +ErrorBox IDS_NOMAINPGM { + MESSAGE[ en-US ] = "This window does not contain a main program!"; + Title[ en-US ] = "Testtool Error"; +}; +ErrorBox IDS_READERROR { + MESSAGE[ en-US ] = "File cannot be read!"; + Title[ en-US ] = "Testtool Error"; +}; +ErrorBox IDS_WRITEERROR { + MESSAGE[ en-US ] = "File cannot be saved!"; + Title[ en-US ] = "Testtool Error"; +}; +ErrorBox IDS_PATTERNNOTFOUND { + MESSAGE[ en-US ] = "Search key not found!"; + Title[ en-US ] = "Testtool Error"; +}; +ErrorBox IDS_INVALID_VALUE { + MESSAGE[ en-US ] = "The value is invalid and cannot be set."; + Title[ en-US ] = "Testtool Error"; +}; + +QueryBox IDS_ASKSAVEERROR { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO; + MESSAGE[ en-US ] = "Error saving files! Run anyway?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_ASK_DIRTY_SAVE { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO_CANCEL; + MESSAGE[ en-US ] = "File has been changed. Save?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_ASK_DIRTY_AND_DISKCHANGE_SAVE { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO_CANCEL; + MESSAGE[ en-US ] = "File has been changed on data medium\nand in the Editor. Save?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_ASK_DISKCHANGE_SAVE { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO_CANCEL; + MESSAGE[ en-US ] = "File has been changed on data medium.\nOverwrite?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_ASKRELOAD { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO; + MESSAGE[ en-US ] = "File has been changed on data medium. Reload?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_ASKDIRTYRELOAD { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO; + MESSAGE[ en-US ] = "File has been changed on data medium\nand in the Editor. Reload?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_RUNNING { + TITLE = "Testtool"; + BUTTONS = WB_YES_NO; + MESSAGE[ en-US ] = "BASIC is still running! Exit anyway?"; + Title[ en-US ] = "Testtool"; +}; +QueryBox IDS_LOSS_OF_INFORMATION { + TITLE = "Testtool"; + BUTTONS = WB_OK_CANCEL; + MESSAGE[ en-US ] = "Saving in an external format causes information loss."; + Title[ en-US ] = "Testtool"; +}; + +InfoBox IDS_NOT_YET_IMPLEMENTED +{ + MESSAGE[ en-US ] = "Not yet implemented"; +}; + + +String IDS_WARNING1 { + TEXT[ en-US ] = "Warning "; +}; +String IDS_ERROR1 { + TEXT[ en-US ] = "Error "; +}; +String IDS_ERROR2 { + TEXT[ en-US ] = " in line "; +}; +String IDS_NO_LONGNAME { + TEXT[ en-US ] = "No entries in Hid.Lst"; +}; +String IDS_WARNING_PREFIX +{ + Text[ en-US ] = "Warning: "; +}; +String IDS_OBJECT +{ + Text[ en-US ] = "Object"; +}; +String IDS_EDIT_VAR +{ + Text[ en-US ] = "Edit ($Arg1)"; +}; + +String IDS_APPNAME { + TEXT[ en-US ] = "Testtool"; +}; +String IDS_APPNAME2 { + TEXT[ en-US ] = "VCLTestTool"; +}; +String IDS_APPMODE_BREAK { + text[ en-US ] = "Break"; +}; +String IDS_APPMODE_RUN { + text[ en-US ] = "Run"; +}; +String IDS_NONAME { + TEXT[ en-US ] = "Unnamed"; +}; + +String IDS_NONAMEFILE { +#if defined ( UNX ) +TEXT = "*.bas"; +#else +TEXT = "*.BAS"; +#endif +}; +String IDS_INCFILE { +#if defined ( UNX ) +TEXT = "*.inc"; +#else +TEXT = "*.INC"; +#endif +}; +String IDS_LIBFILE { +#if defined ( UNX ) +TEXT = "*.sb"; +#else +TEXT = "*.SB"; +#endif +}; +String IDS_RESFILE { +#if defined ( UNX ) +TEXT = "*.res"; +#else +TEXT = "*.RES"; +#endif +}; +String IDS_TXTFILE { +#if defined ( UNX ) +TEXT = "*.txt"; +#else +TEXT = "*.TXT"; +#endif +}; + +String IDS_LOADDLG { + TEXT[ en-US ] = "Testtool: Load File"; +}; +String IDS_SAVEDLG { + TEXT[ en-US ] = "Testtool: Save File"; +}; +String IDS_BASFILTER { + TEXT[ en-US ] = "Source files (*.BAS)"; +}; +String IDS_INCFILTER { + TEXT[ en-US ] = "Include files (*.INC)"; +}; +String IDS_LIBFILTER { + TEXT[ en-US ] = "Libraries (*.SB)"; +}; +String IDS_RESFILTER { + TEXT[ en-US ] = "Result files (*.RES)"; +}; +String IDS_TXTFILTER { + TEXT[ en-US ] = "Results as text file (*.TXT)"; +}; +String IDS_PAGE { + TEXT[ en-US ] = "Page "; +}; +String IDS_PRINTMSG { + TEXT[ en-US ] = "Printout of "; +}; +String IDS_CONTINUE { + TEXT[ en-US ] = "Continue"; +}; +String IDS_CANCEL { + TEXT[ en-US ] = "Cancel"; +}; +String IDS_DISASWIN { + TEXT[ en-US ] = "Disassembly"; +}; +//Icon RID_APPICON { +// FILE = "basic.ico"; +//}; +//Icon RID_APPICON2 { +// FILE = "testtool.ico"; +//}; +//Icon RID_WORKICON { +// FILE = "work.ico"; +//}; + +Bitmap MBP_PLUS { + File = "plus.bmp"; +}; +Bitmap MBP_MINUS { + File = "minus.bmp"; +}; + +Menu RID_APPMENUBAR { + ItemList = { + MenuItem { + Identifier = RID_APPFILE; + SUBMENU = Menu ,RID_FILE; + TEXT[ en-US ] = "~File"; + }; + MenuItem { + Identifier = RID_APPEDIT; + SUBMENU = Menu ,RID_EDIT; + TEXT[ en-US ] = "~Edit"; + }; + MenuItem { + Identifier = RID_APPRUN; + SUBMENU = Menu ,RID_RUN; + TEXT[ en-US ] = "~Program"; + }; + MenuItem { + Identifier = RID_APPWINDOW; + SUBMENU = Menu ,RID_WINDOW; + TEXT[ en-US ] = "~Window"; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + HELP = TRUE; + Identifier = RID_APPHELP; + SUBMENU = Menu ,RID_HELP; + TEXT[ en-US ] = "~Help"; + }; + }; +}; +Menu RID_FILE { + ITEMLIST = { + MenuItem { + Identifier = RID_FILENEW; + TEXT[ en-US ] = "~New"; + AccelKey = KeyCode { Function = KEYFUNC_NEW; }; + }; + MenuItem { + Identifier = RID_FILEOPEN; + TEXT[ en-US ] = "~Open..."; + AccelKey = KeyCode { Function = KEYFUNC_OPEN; }; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_FILECLOSE; + TEXT[ en-US ] = "~Close"; + AccelKey = KeyCode { Function = KEYFUNC_CLOSE; }; + }; + MenuItem { + Identifier = RID_FILESAVE; + TEXT[ en-US ] = "~Save"; + AccelKey = KeyCode { Function = KEYFUNC_SAVE; }; + }; + MenuItem { + Identifier = RID_FILESAVEAS; + TEXT[ en-US ] = "Save~ As..."; + AccelKey = KeyCode { Function = KEYFUNC_SAVEAS; }; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_FILELOADLIB; + TEXT[ en-US ] = "~Load Library..."; + }; + MenuItem { + Identifier = RID_FILESAVELIB; + TEXT[ en-US ] = "Save Li~brary..."; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_FILEPRINT; + TEXT[ en-US ] = "~Print"; + }; + MenuItem { + Identifier = RID_FILESETUP; + TEXT[ en-US ] = "P~rinter Setting..."; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_QUIT; + TEXT[ en-US ] = "~Exit"; + AccelKey = KeyCode { Function = KEYFUNC_QUIT; }; + }; + }; +}; +Menu RID_EDIT { + ITEMLIST = { + MenuItem { + Identifier = RID_EDITUNDO; + TEXT[ en-US ] = "~Undo"; +// AccelKey = KeyCode { Function = KEYFUNC_CUT; }; + }; + MenuItem { + Identifier = RID_EDITREDO; + TEXT[ en-US ] = "~Redo"; +// AccelKey = KeyCode { Function = KEYFUNC_CUT; }; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_EDITCUT; + TEXT[ en-US ] = "~Cut"; + AccelKey = KeyCode { Function = KEYFUNC_CUT; }; + }; + MenuItem { + Identifier = RID_EDITCOPY; + TEXT[ en-US ] = "~Copy"; + AccelKey = KeyCode { Function = KEYFUNC_COPY; }; + }; + MenuItem { + Identifier = RID_EDITPASTE; + TEXT[ en-US ] = "~Paste"; + AccelKey = KeyCode { Function = KEYFUNC_PASTE; }; + }; + MenuItem { + Identifier = RID_EDITDEL; + TEXT[ en-US ] = "~Delete"; + AccelKey = KeyCode { Function = KEYFUNC_DELETE; }; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_EDITSEARCH; + TEXT[ en-US ] = "~Find..."; + AccelKey = KeyCode { Function = KEYFUNC_FIND; }; + }; + MenuItem { + Identifier = RID_EDITREPLACE; + TEXT[ en-US ] = "~Replace..."; + }; + MenuItem { + Identifier = RID_EDITREPEAT; + TEXT[ en-US ] = "Repeat S~earch"; + AccelKey = KeyCode { Code = KEY_F3; }; +// AccelKey = KeyCode { Function = KEYFUNC_REPEAT; }; + }; + }; +}; +Menu RID_RUN { + ITEMLIST = { + MenuItem { + Identifier = RID_RUNCOMPILE; + TEXT[ en-US ] = "~Compile"; + }; + MenuItem { + Identifier = RID_RUNDISAS; + TEXT[ en-US ] = "~Disassemble"; + }; + MenuItem { + Identifier = RID_RUNSTART; + TEXT[ en-US ] = "~Start"; + AccelKey = KeyCode { Code = KEY_F5; }; + }; + MenuItem { + Identifier = RID_RUNSTEPINTO; + TEXT[ en-US ] = "~Single Step"; + AccelKey = KeyCode { Code = KEY_F8; }; + }; + MenuItem { + Identifier = RID_RUNSTEPOVER; + TEXT[ en-US ] = "Si~ngle Step over Procedure"; + AccelKey = KeyCode { Code = KEY_F10; }; + }; +// MenuItem { +// Identifier = RID_RUNTOCURSOR; +// TEXT = "Run to cursor"; +// AccelKey = KeyCode { Code = KEY_F7; }; +// }; + MenuItem { + Identifier = RID_TOGLEBRKPNT; + TEXT[ en-US ] = "Set / Delete Break Point"; + AccelKey = KeyCode { Code = KEY_F9; }; + }; + MenuItem { + Identifier = RID_RUNBREAK; + TEXT[ en-US ] = "~Break"; + AccelKey = KeyCode { Code = KEY_F5; Modifier1 = TRUE; }; + }; + MenuItem { + Identifier = RID_RUNSTOP; + TEXT[ en-US ] = "~Stop"; + AccelKey = KeyCode { Code = KEY_F5; Shift = TRUE; }; + }; + MenuItem { + Identifier = RID_RUNNEXTERR; + TEXT[ en-US ] = "~Next Error"; + AccelKey = KeyCode { Code = KEY_F8; Shift = TRUE; }; + }; + MenuItem { + Identifier = RID_RUNPREVERR; + TEXT[ en-US ] = "~Previous Error"; + AccelKey = KeyCode { Code = KEY_F7; Shift = TRUE; }; + }; + MenuItem { + SEPARATOR = TRUE; + }; + }; +}; +// Wird nur beim Test Tool eingef³gt + +// unter Folgendem Name +String RID_TT_EXTRAS_NAME +{ + Text[ en-US ] = "E~xtra"; +}; + +Menu RID_TT_EXTRAS { + ITEMLIST = { + MenuItem { + Identifier = RID_OPTIONS; + TEXT[ en-US ] = "~Settings"; + }; +/* comment out till it gets functionality #i26908 + MenuItem { + Identifier = RID_DECLARE_HELPER; + Text [ en-US ] = "~Record Dialogs"; + };*/ + }; +}; +Menu RID_WINDOW { + ITEMLIST = { +/* MenuItem { + Identifier = RID_WINCASCADE; + TEXT[ en-US ] = "~Cascade"; + }; + MenuItem { + Identifier = RID_WINTILE; + TEXT[ en-US ] = "~Tile"; + }; + MenuItem { + Identifier = RID_WINTILEHORZ; + TEXT[ en-US ] = "~Arrange Horizontally"; + }; + MenuItem { + Identifier = RID_WINTILEVERT; + TEXT[ en-US ] = "~Arrange Vertically"; + };*/ + }; +}; +Menu RID_HELP { + ITEMLIST = { +/* MenuItem { + Identifier = RID_HELPINDEX; + TEXT = "~Index"; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_HELPKEYS; + TEXT = "~Tastaturbelegung"; + }; + MenuItem { + Identifier = RID_HELPINTRO; + TEXT = "~Anleitung"; + }; + MenuItem { + SEPARATOR = TRUE; + }; + MenuItem { + Identifier = RID_HELPTOPIC; + TEXT = "~Markierter Text"; + }; + MenuItem { + SEPARATOR = TRUE; + }; +*/ MenuItem { + ABOUT = TRUE; + Identifier = RID_HELPABOUT; + TEXT[ en-US ] = "~About..."; + }; + }; +}; +ModelessDialog IDD_PRINT_DIALOG { + Pos = MAP_APPFONT( 83, 42 ); + Size = MAP_APPFONT( 171, 94 ); + MOVEABLE = TRUE; + SVLook = TRUE; + FixedText RID_TEXT { + Pos = MAP_APPFONT( 11, 9 ); + Size = MAP_APPFONT( 146, 28 ); + CENTER = TRUE; + TEXT[ en-US ] = "Print "; + }; + CancelButton RID_CANCEL { + Pos = MAP_APPFONT( 56, 46 ); + Size = MAP_APPFONT( 47, 19 ); + TEXT[ en-US ] = "Cancel"; + }; + TEXT[ en-US ] = "Testtool: Print File"; +}; + + +TabDialog IDD_OPTIONS_DLG +{ + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 248, 140 ); + Text[ en-US ] = "Settings"; + Moveable = TRUE ; + Closeable = TRUE ; + TabControl RES_TC_OPTIONS + { + OutputSize = TRUE ; + Pos = MAP_APPFONT( 4, 4 ); + Size = MAP_APPFONT( 240, 116 ); + Hide = FALSE ; + PageList = + { + PageItem + { + Identifier = RID_TP_GEN ; + Text[ en-US ] = "Generic"; + }; + PageItem + { + Identifier = RID_TP_PRO ; + Text[ en-US ] = "Profile"; + }; + PageItem + { + Identifier = RID_TP_CRA ; + Text[ en-US ] = "Crashreport"; + }; + PageItem + { + Identifier = RID_TP_MIS ; + Text[ en-US ] = "Misc"; + }; + PageItem + { + Identifier = RID_TP_FON ; + Text[ en-US ] = "Font"; + }; + }; + }; +}; + + +TabPage RID_TP_GENERIC { + Hide = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 244, 100 ); + FixedLine RID_FL_AREA { + Pos = MAP_APPFONT( 4, 2 ); + Size = MAP_APPFONT( 228, 8 ); + Text[ en-US ] = "Area"; + }; + ComboBox RID_CB_AREA { + HScroll = TRUE; + VScroll = TRUE; + AutoHScroll = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( 8, 12 ); + Size = MAP_APPFONT( 132, 88 ); + TabStop = TRUE; + DropDown = TRUE; + }; + PushButton RID_PB_NEW_AREA { + Pos = MAP_APPFONT( 144, 12 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "New"; + }; + PushButton RID_PD_DEL_AREA { + Pos = MAP_APPFONT( 188, 12 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Delete"; + }; + FixedLine RID_FL_VALUE { + Pos = MAP_APPFONT( 4, 32 ); + Size = MAP_APPFONT( 228, 8 ); + Text[ en-US ] = "Setting"; + }; + ComboBox RID_CB_VALUE { + HScroll = TRUE; + VScroll = TRUE; + AutoHScroll = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( 8, 48 ); + Size = MAP_APPFONT( 176, 44 ); + TabStop = TRUE; + }; + PushButton RID_PB_SELECT_FILE { + Pos = MAP_APPFONT( 188, 48 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Path ..."; + Disable = TRUE; + Hide = TRUE; + }; + PushButton RID_PB_NEW_VALUE { + Pos = MAP_APPFONT( 188, 48 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "New"; + }; + PushButton RID_PB_DEL_VALUE { + Pos = MAP_APPFONT( 188, 64 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Delete"; + }; +}; + + +TabPage RID_TP_PROFILE { + Hide = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 244, 100 ); + FixedLine RID_FL_PROFILE { + Pos = MAP_APPFONT( 4, 4 ); + Size = MAP_APPFONT( 22, 8 ); + Text[ en-US ] = "Profile"; + }; + ComboBox RID_CB_PROFILE { + HScroll = TRUE; + VScroll = TRUE; + AutoHScroll = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( 30, 2 ); + Size = MAP_APPFONT( 110, 88 ); + TabStop = TRUE; + DropDown = TRUE; + }; + PushButton RID_PB_NEW_PROFILE { + Pos = MAP_APPFONT( 144, 2 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "New"; + }; + PushButton RID_PD_DEL_PROFILE { + Pos = MAP_APPFONT( 188, 2 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Delete"; + }; + FixedLine FL_DIRECTORIES { + Pos = MAP_APPFONT( 4, 16 ); + Size = MAP_APPFONT( 230, 8 ); + Text[ en-US ] = "Profile settings"; + }; + FixedText LOG_TEXT { + Pos = MAP_APPFONT( 7, 26 ); + Size = MAP_APPFONT( 86, 12 ); + Text[ en-US ] = "Log base directory"; + }; + FixedText BASIS_TEXT { + Pos = MAP_APPFONT( 7, 42 ); + Size = MAP_APPFONT( 86, 12 ); + Text[ en-US ] = "Base directory"; + }; + CheckBox HID_CHECK { + Pos = MAP_APPFONT( 7, 58 ); + Size = MAP_APPFONT( 86, 12 ); + Text[ en-US ] = "Default HID directory"; + TabStop = TRUE; + Hide = FALSE; + }; + Edit LOG_NAME { + Border = TRUE; + Pos = MAP_APPFONT( 97, 26 ); + Size = MAP_APPFONT( 116, 12 ); + TabStop = TRUE; + }; + Edit BASIS_NAME { + Border = TRUE; + Pos = MAP_APPFONT( 97, 42 ); + Size = MAP_APPFONT( 116, 12 ); + TabStop = TRUE; + }; + Edit HID_NAME { + Border = TRUE; + Pos = MAP_APPFONT( 97, 58 ); + Size = MAP_APPFONT( 116, 12 ); + TabStop = TRUE; + }; + PushButton LOG_SET { + Pos = MAP_APPFONT( 217, 26 ); + Size = MAP_APPFONT( 12, 12 ); + TabStop = TRUE; + Text[ en-US ] = "..."; + }; + PushButton BASIS_SET { + Pos = MAP_APPFONT( 217, 42 ); + Size = MAP_APPFONT( 12, 12 ); + TabStop = TRUE; + Text[ en-US ] = "..."; + }; + PushButton HID_SET { + Pos = MAP_APPFONT( 217, 58 ); + Size = MAP_APPFONT( 12, 12 ); + TabStop = TRUE; + Text[ en-US ] = "..."; + }; + CheckBox CB_AUTORELOAD { + Pos = MAP_APPFONT( 7, 74 ); + Size = MAP_APPFONT( 115, 12 ); + Text[ en-US ] = "AutoReload"; + }; + CheckBox CB_AUTOSAVE { + Pos = MAP_APPFONT( 7, 87 ); + Size = MAP_APPFONT( 115, 12 ); + Text[ en-US ] = "Save before execute"; + }; + CheckBox CB_STOPONSYNTAXERRORS { + Pos = MAP_APPFONT( 132, 74 ); + Size = MAP_APPFONT( 115, 12 ); + Text[ en-US ] = "Stop on Syntax Errors"; + }; +}; + +TabPage RID_TP_CRASH { + Hide = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 244, 100 ); + FixedLine FL_CRASHREPORT { + Pos = MAP_APPFONT( 4, 2 ); + Size = MAP_APPFONT( 230, 8 ); + Text[ en-US ] = "Crashreport"; + }; + CheckBox CB_USEPROXY { + Pos = MAP_APPFONT( 8, 12 ); + Size = MAP_APPFONT( 120, 12 ); + Text[ en-US ] = "Use Proxy"; + }; + FixedText FT_CRHOST { + Pos = MAP_APPFONT( 8+12, 12+13 ); + Size = MAP_APPFONT( 30, 12 ); + Text[ en-US ] = "Host"; + }; + Edit ED_CRHOST { + Border = TRUE; + Pos = MAP_APPFONT( 43+12, 12+13 ); + Size = MAP_APPFONT( 80, 12 ); + TabStop = TRUE; + }; + FixedText FT_CRPORT { + Pos = MAP_APPFONT( 8+12, 12+13+16 ); + Size = MAP_APPFONT( 30, 12 ); + Text[ en-US ] = "Port"; + }; + NumericField NF_CRPORT { + Border = TRUE; + Pos = MAP_APPFONT( 43+12, 12+13+16 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Right = TRUE; + Repeat = TRUE; + Spin = TRUE; + Minimum = 1024; + Maximum = 0xffff; + First = 1024; + Last = 0xffff; + }; + CheckBox CB_ALLOWCONTACT { + Pos = MAP_APPFONT( 8, 12+13+16+16 ); + Size = MAP_APPFONT( 120, 12 ); + Text[ en-US ] = "Allow Contact"; + }; + FixedText FT_EMAIL { + Pos = MAP_APPFONT( 8+12, 12+13+16+16+13 ); + Size = MAP_APPFONT( 30, 12 ); + Text[ en-US ] = "EMail"; + }; + Edit ED_EMAIL { + Border = TRUE; + Pos = MAP_APPFONT( 43+12, 12+13+16+16+13 ); + Size = MAP_APPFONT( 80, 12 ); + TabStop = TRUE; + }; +}; + + +TabPage RID_TP_MISC { + Hide = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 244, 100 ); + FixedLine FL_COMMUNICATION { + Pos = MAP_APPFONT( 4, 2 ); + Size = MAP_APPFONT( 230, 8 ); + Text[ en-US ] = "Communication"; + }; + FixedText FT_HOST { + Pos = MAP_APPFONT( 8, 12 ); + Size = MAP_APPFONT( 30, 12 ); + Text[ en-US ] = "Host"; + }; + Edit ED_HOST { + Border = TRUE; + Pos = MAP_APPFONT( 43, 12); + Size = MAP_APPFONT( 80, 12 ); + TabStop = TRUE; + }; + FixedText FT_TTPORT { + Pos = MAP_APPFONT( 132, 12 ); + Size = MAP_APPFONT( 70, 12 ); + Text[ en-US ] = "Testtool Port"; + }; + NumericField NF_TTPORT { + Border = TRUE; + Pos = MAP_APPFONT( 191, 12); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Right = TRUE; + Repeat = TRUE; + Spin = TRUE; + Minimum = 1024; + Maximum = 0xffff; + First = 1024; + Last = 0xffff; + }; + FixedText FT_UNOPORT { + Pos = MAP_APPFONT( 132, 12+15 ); + Size = MAP_APPFONT( 70, 12 ); + Text[ en-US ] = "Remote UNO Port"; + }; + NumericField NF_UNOPORT { + Border = TRUE; + Pos = MAP_APPFONT( 191, 12+15); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Right = TRUE; + Repeat = TRUE; + Spin = TRUE; + Minimum = 1024; + Maximum = 0xffff; + First = 1024; + Last = 0xffff; + }; + + FixedLine FL_OTHER { + Pos = MAP_APPFONT( 4, 27 +13 ); + Size = MAP_APPFONT( 230, 8 ); + Text[ en-US ] = "Other settings"; + }; + FixedText TIMEOUT_TEXT { + Pos = MAP_APPFONT( 8, 50 ); + Size = MAP_APPFONT( 70, 12 ); + Text[ en-US ] = "Server Timeout"; + }; + TimeField SERVER_TIMEOUT { + Border = TRUE; + Pos = MAP_APPFONT( 83, 50 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Repeat = TRUE; + Spin = TRUE; + Format = TIMEF_SEC; + Duration = TRUE; + }; + FixedText FT_LRU { + Pos = MAP_APPFONT( 132, 50 ); + Size = MAP_APPFONT( 70, 12 ); + Text[ en-US ] = "Max LRU Files"; + }; + NumericField TF_MAX_LRU { + Border = TRUE; + Pos = MAP_APPFONT( 191, 50); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Right = TRUE; + Repeat = TRUE; + Spin = TRUE; + Minimum = 0; + Maximum = IDM_FILE_LRUn - IDM_FILE_LRU1 +1; + }; + FixedText FT_PROGDIR { + Pos = MAP_APPFONT( 8, 50+15 ); + Size = MAP_APPFONT( 76, 12 ); + Text[ en-US ] = "OOo Program Dir"; + }; + Edit ED_PROGDIR { + Border = TRUE; + Pos = MAP_APPFONT( 83, 50+15 ); + Size = MAP_APPFONT( 219-83-4, 12 ); + TabStop = TRUE; + }; + PushButton PB_PROGDIR { + Pos = MAP_APPFONT( 219, 50+15 ); + Size = MAP_APPFONT( 12, 12 ); + TabStop = TRUE; + Text[ en-US ] = "..."; + }; +}; + + +TabPage RID_TP_FONT { + Hide = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 244, 100 ); + FixedText FT_FONTNAME { + Pos = MAP_APPFONT( 4, 2 ); + Size = MAP_APPFONT( 123, 8 ); + Text[ en-US ] = "Type"; + }; + ComboBox CB_FONTNAME { + Pos = MAP_APPFONT( 4, 12 ); + Size = MAP_APPFONT( 123, 12*4 ); + Sort = TRUE; + AutoHScroll = TRUE; + }; + FixedText FT_FONTSTYLE { + Pos = MAP_APPFONT( 131, 2 ); + Size = MAP_APPFONT( 65, 8 ); + Text[ en-US ] = "Typeface"; + }; + ComboBox CB_FONTSTYLE { + Pos = MAP_APPFONT( 131, 12 ); + Size = MAP_APPFONT( 65, 12*4 ); + AutoHScroll = TRUE; + }; + FixedText FT_FONTSIZE { + Pos = MAP_APPFONT( 200, 2 ); + Size = MAP_APPFONT( 29, 8 ); + Text[ en-US ] = "Size"; + }; + MetricBox MB_FONTSIZE { + Pos = MAP_APPFONT( 200, 12 ); + Size = MAP_APPFONT( 29, 12*4 ); + AutoHScroll = TRUE; + }; + FixedText FT_PREVIEW { + Pos = MAP_APPFONT( 4, 12*5+5 ); + Size = MAP_APPFONT( 229, 30 ); + Center = TRUE; + Border = TRUE; + }; + // 229 is max +}; + + +FloatingWindow IDD_DISPLAY_HID { + OutputSize = TRUE; + SVLook = TRUE; + Size = MAP_APPFONT( 261, 160 ); + Moveable = TRUE; + Closeable = TRUE; + Sizeable = TRUE; + Zoomable = TRUE; + Hide = TRUE; + ClipChildren = TRUE; + ToolBox RID_TB_CONF { + Border = TRUE; + Pos = MAP_APPFONT( 0, 0 ); + Size = MAP_APPFONT( 260, 14 ); +/* ItemList = { + ToolBoxItem { + Text = "erster der Toolbox"; + }; + };*/ +// Hide = TRUE; + }; + FixedText RID_FT_CONTROLS { + Pos = MAP_APPFONT( 4, 16 ); + Size = MAP_APPFONT( 128, 10 ); + Text[ en-US ] = "Controls"; + }; + MultiListBox RID_MLB_CONTROLS { + Border = TRUE; + AutoHScroll = TRUE; + Pos = MAP_APPFONT( 4, 28 ); + Size = MAP_APPFONT( 208, 88 ); + TabStop = TRUE; + }; + FixedText RID_FT_SLOTS { + Pos = MAP_APPFONT( 4, 120 ); + Size = MAP_APPFONT( 128, 10 ); + Text[ en-US ] = "Slots"; + }; + MultiListBox RID_MLB_SLOTS { + Border = TRUE; + AutoHScroll = TRUE; + Pos = MAP_APPFONT( 4, 132 ); + Size = MAP_APPFONT( 208, 24 ); + TabStop = TRUE; + }; + PushButton RID_PB_KOPIEREN { + Pos = MAP_APPFONT( 216, 28 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Copy"; + }; + PushButton RID_PB_BENENNEN { + Pos = MAP_APPFONT( 216, 44 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Hide = TRUE; + Text[ en-US ] = "Name"; + }; + PushButton RID_PB_SELECTALL { + Pos = MAP_APPFONT( 216, 44 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Select all"; + }; + OKButton RID_OK_CLOSE { + Pos = MAP_APPFONT( 216, 144 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Close"; + }; + Text[ en-US ] = "Display HId"; +}; + + + +Accelerator MAIN_ACCEL { + ItemList = { + AcceleratorItem { + Identifier = RID_FILENEW; + Key = KeyCode { Function = KEYFUNC_NEW; }; + }; + AcceleratorItem { + Identifier = RID_FILEOPEN; + Key = KeyCode { Function = KEYFUNC_OPEN; }; + }; + AcceleratorItem { + Identifier = RID_FILECLOSE; + Key = KeyCode { Function = KEYFUNC_CLOSE; }; + }; + AcceleratorItem { + Identifier = RID_FILESAVE; + Key = KeyCode { Function = KEYFUNC_SAVE; }; + }; + AcceleratorItem { + Identifier = RID_FILESAVEAS; + Key = KeyCode { Function = KEYFUNC_SAVEAS; }; + }; + AcceleratorItem { + Identifier = RID_QUIT; + Key = KeyCode { Function = KEYFUNC_QUIT; }; + }; +// AcceleratorItem { +// Identifier = RID_EDITCUT; +// Key = KeyCode { Function = KEYFUNC_CUT; }; +// }; +// AcceleratorItem { +// Identifier = RID_EDITCOPY; +// Key = KeyCode { Function = KEYFUNC_COPY; }; +// }; +// AcceleratorItem { +// Identifier = RID_EDITPASTE; +// Key = KeyCode { Function = KEYFUNC_PASTE; }; +// }; +// AcceleratorItem { +// Identifier = RID_EDITDEL; +// Key = KeyCode { Function = KEYFUNC_DELETE; }; +// }; + AcceleratorItem { + Identifier = RID_EDITSEARCH; + Key = KeyCode { Function = KEYFUNC_FIND; }; + }; + AcceleratorItem { + Identifier = RID_EDITREPEAT; + Key = KeyCode { Code = KEY_F3; }; +// Key = KeyCode { Function = KEYFUNC_REPEAT; }; + }; + AcceleratorItem { + Identifier = RID_RUNSTART; + Key = KeyCode { Code = KEY_F5; }; + }; + AcceleratorItem { + Identifier = RID_RUNSTEPINTO; + Key = KeyCode { Code = KEY_F8; }; + }; + AcceleratorItem { + Identifier = RID_TOGLEBRKPNT; + Key = KeyCode { Code = KEY_F9; }; + }; + AcceleratorItem { + Identifier = RID_RUNSTEPOVER; + Key = KeyCode { Code = KEY_F10; }; + }; + AcceleratorItem { + Identifier = RID_RUNTOCURSOR; + Key = KeyCode { Code = KEY_F7; }; + }; + AcceleratorItem { + Identifier = RID_RUNBREAK; + Key = KeyCode { Code = KEY_F5; Modifier1 = TRUE; }; + }; + AcceleratorItem { + Identifier = RID_RUNSTOP; + Key = KeyCode { Code = KEY_F5; Shift = TRUE; }; + }; + AcceleratorItem { + Identifier = RID_RUNNEXTERR; + Key = KeyCode { Code = KEY_F8; Shift = TRUE; }; + }; + AcceleratorItem { + Identifier = RID_RUNPREVERR; + Key = KeyCode { Code = KEY_F7; Shift = TRUE; }; + }; + }; +}; + +ImageList RID_IMGLST_LAYOUT +{ + Prefix = "im"; + MaskColor = Color { Red = 0xFFFF ; Green = 0xFFFF ; Blue = 0xFFFF ; }; + IdList = + { + IMGID_BRKENABLED ; + IMGID_BRKDISABLED ; + IMGID_STEPMARKER ; + IMGID_ERRORMARKER ; + }; +}; + +ModelessDialog IDD_EDIT_VAR { + Pos = MAP_APPFONT( 0, 0 ); + Size = MAP_APPFONT( 171, 87 ); + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_FT_NAME { + Pos = MAP_APPFONT( 8, 8 ); + Size = MAP_APPFONT( 40, 10 ); + Text[ en-US ] = "Name"; + }; + FixedText RID_FT_CONTENT { + Pos = MAP_APPFONT( 8, 21 ); + Size = MAP_APPFONT( 40, 10 ); + Text[ en-US ] = "Content"; + }; + FixedText RID_FT_NEW_CONTENT { + Pos = MAP_APPFONT( 8, 38 ); + Size = MAP_APPFONT( 40, 10 ); + Text[ en-US ] = "New content"; + }; + FixedText RID_FT_NAME_VALUE { + Pos = MAP_APPFONT( 53, 8 ); + Size = MAP_APPFONT( 111, 10 ); + Text[ en-US ] = "Name of variable"; + }; + FixedText RID_FT_CONTENT_VALUE { + Pos = MAP_APPFONT( 53, 21 ); + Size = MAP_APPFONT( 111, 10 ); + Text[ en-US ] = "Previous contents"; + }; + RadioButton RID_RB_NEW_BOOL_T { + Hide = TRUE; + Pos = MAP_APPFONT( 53, 37 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "True"; + }; + RadioButton RID_RB_NEW_BOOL_F { + Hide = TRUE; + Pos = MAP_APPFONT( 98, 37 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + Text[ en-US ] = "False"; + }; + NumericField RID_NF_NEW_INTEGER { + Border = TRUE; + Hide = TRUE; + Pos = MAP_APPFONT( 53, 37 ); + Size = MAP_APPFONT( 111, 12 ); + TabStop = TRUE; + Repeat = TRUE; + Spin = TRUE; + Minimum = -32768; + Maximum = 32767; + First = -32768; + Last = 32767; + SpinSize = 10; + }; + NumericField RID_NF_NEW_LONG { + Border = TRUE; + Hide = TRUE; + Pos = MAP_APPFONT( 53, 37 ); + Size = MAP_APPFONT( 111, 12 ); + TabStop = TRUE; + Repeat = TRUE; + Spin = TRUE; + Minimum = -2147483648; + Maximum = 2147483647; + First = -2147483648; + Last = 2147483647; + SpinSize = 10; + }; + Edit RID_ED_NEW_STRING { + Hide = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( 53, 37 ); + Size = MAP_APPFONT( 111, 12 ); + TabStop = TRUE; + Text[ en-US ] = "Edit"; + }; + OKButton RID_OK { + Pos = MAP_APPFONT( 33, 58 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + }; + CancelButton RID_CANCEL { + Pos = MAP_APPFONT( 93, 58 ); + Size = MAP_APPFONT( 40, 12 ); + TabStop = TRUE; + }; + Text[ en-US ] = "Edit variable"; +}; + +FloatingWindow LOAD_CONF { + SVLook = TRUE; + Pos = MAP_APPFONT( 66, 23 ); + Size = MAP_APPFONT( 156, 51 ); + Moveable = TRUE; + FixedText WORK { + SVLook = TRUE; + Pos = MAP_APPFONT( 0, 8 ); + Size = MAP_APPFONT( 155, 10 ); + Center = TRUE; + Text[ en-US ] = "Slot IDs"; + }; + FixedText FILENAME { + SVLook = TRUE; + Pos = MAP_APPFONT( 0, 21 ); + Size = MAP_APPFONT( 155, 10 ); + Center = TRUE; + Text[ en-US ] = "File.win"; + }; + Text[ en-US ] = "Reading Configuration Files"; +}; + diff --git a/basic/source/app/basicrt.cxx b/basic/source/app/basicrt.cxx new file mode 100644 index 000000000000..cd975b76de07 --- /dev/null +++ b/basic/source/app/basicrt.cxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basicrt.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include "sbintern.hxx" +#include "runtime.hxx" +#include <basic/basicrt.hxx> + +const String BasicRuntime::GetSourceRevision() +{ + return pRun->GetModule()->GetComment(); +} + +const String BasicRuntime::GetModuleName( SbxNameType nType ) +{ + return pRun->GetModule()->GetName( nType ); +} + +const String BasicRuntime::GetMethodName( SbxNameType nType ) +{ + return pRun->GetMethod()->GetName( nType ); +} + +xub_StrLen BasicRuntime::GetLine() +{ + return pRun->nLine; +} + +xub_StrLen BasicRuntime::GetCol1() +{ + return pRun->nCol1; +} + +xub_StrLen BasicRuntime::GetCol2() +{ + return pRun->nCol2; +} + +BOOL BasicRuntime::IsRun() +{ + return pRun->IsRun(); +} + +BasicRuntime BasicRuntime::GetNextRuntime() +{ + return BasicRuntime ( pRun->pNext ); +} + + + +const String BasicErrorStackEntry::GetSourceRevision() +{ + return pEntry->aMethod->GetModule()->GetComment(); +} + +const String BasicErrorStackEntry::GetModuleName( SbxNameType nType ) +{ + return pEntry->aMethod->GetModule()->GetName( nType ); +} + +const String BasicErrorStackEntry::GetMethodName( SbxNameType nType ) +{ + return pEntry->aMethod->GetName( nType ); +} + +xub_StrLen BasicErrorStackEntry::GetLine() +{ + return pEntry->nLine; +} + +xub_StrLen BasicErrorStackEntry::GetCol1() +{ + return pEntry->nCol1; +} + +xub_StrLen BasicErrorStackEntry::GetCol2() +{ + return pEntry->nCol2; +} + + + +BasicRuntime BasicRuntimeAccess::GetRuntime() +{ + return BasicRuntime( pINST->pRun ); +} + +bool BasicRuntimeAccess::HasRuntime() +{ + return pINST && pINST->pRun != NULL; +} + +USHORT BasicRuntimeAccess::GetStackEntryCount() +{ + return GetSbData()->pErrStack->Count(); +} + +BasicErrorStackEntry BasicRuntimeAccess::GetStackEntry( USHORT nIndex ) +{ + return BasicErrorStackEntry( GetSbData()->pErrStack->GetObject( nIndex ) ); +} + +BOOL BasicRuntimeAccess::HasStack() +{ + return GetSbData()->pErrStack != NULL; +} + +void BasicRuntimeAccess::DeleteStack() +{ + delete GetSbData()->pErrStack; + GetSbData()->pErrStack = NULL; +} + +BOOL BasicRuntimeAccess::IsRunInit() +{ + return GetSbData()->bRunInit; +} diff --git a/basic/source/app/basmsg.hrc b/basic/source/app/basmsg.hrc new file mode 100644 index 000000000000..73c458059d3d --- /dev/null +++ b/basic/source/app/basmsg.hrc @@ -0,0 +1,48 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basmsg.hrc,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include "basic/ttglobal.hrc" + + +// Hier sind die Messages aus dem Verzeichnis /basic/source/app enhalten + + +/////////////////////////////// +// Fehlermeldungen, die in das Resultfile gelangen. +// ********************* +// *** !!ACHTUNG!! *** +// ********************* +// Die Nummern dürfen sich NIE! ändern, +// da sie in den Resultfiles gespeichert sind, und bei erneutem Anzeigen +// statdessen die entsprechenden neuen oder garkeine Strings angzeigt werden. +/////////////////////////////// + +#define S_PROG_START ( BAS_START + 0 ) +#define S_ERROR_OUTSIDE_TESTCASE ( BAS_START + 1 ) +#define S_WARNING_PREFIX ( BAS_START + 2 ) diff --git a/basic/source/app/basmsg.src b/basic/source/app/basmsg.src new file mode 100644 index 000000000000..6a44ad78d1ff --- /dev/null +++ b/basic/source/app/basmsg.src @@ -0,0 +1,57 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basmsg.src,v $ + * $Revision: 1.26 $ + * + * 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 "basmsg.hrc" + + +// Hier sind die Messages aus dem Verzeichnis /basic/source/app enhalten + + +/////////////////////////////// +// Fehlermeldungen, die in das Resultfile gelangen. +// ********************* +// *** !!ACHTUNG!! *** +// ********************* +// Die Nummern dürfen sich NIE! ändern, +// da sie in den Resultfiles gespeichert sind, und bei erneutem Anzeigen +// statdessen die entsprechenden neuen oder garkeine Strings angzeigt werden. +/////////////////////////////// +String S_PROG_START +{ + Text[ en-US ] = "Program start: ($Arg1); ($Arg2)"; +}; +String S_ERROR_OUTSIDE_TESTCASE +{ + Text[ en-US ] = "Error outside of test case"; +}; +String S_WARNING_PREFIX +{ + Text[ en-US ] = "Warning: "; +}; + diff --git a/basic/source/app/brkpnts.cxx b/basic/source/app/brkpnts.cxx new file mode 100644 index 000000000000..115233439f5c --- /dev/null +++ b/basic/source/app/brkpnts.cxx @@ -0,0 +1,389 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: brkpnts.cxx,v $ + * $Revision: 1.13 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/list.hxx> +#include <basic/sbx.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <vcl/image.hxx> +#include <svtools/textdata.hxx> +#include <tools/config.hxx> +#include <vcl/gradient.hxx> + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +#include "brkpnts.hxx" +#include "basic.hrc" +#include "resids.hrc" +#include "basrid.hxx" + +struct Breakpoint +{ + USHORT nLine; + + Breakpoint( USHORT nL ) { nLine = nL; } +}; + + +ImageList* BreakpointWindow::pImages = NULL; + + +BreakpointWindow::BreakpointWindow( Window *pParent ) +: Window( pParent ) +, nCurYOffset( 0 ) +, nMarkerPos( MARKER_NOMARKER ) +, pModule( NULL ) +, bErrorMarker( FALSE ) +{ + if ( !pImages ) + pImages = new ImageList( SttResId( RID_IMGLST_LAYOUT ) ); + + Gradient aGradient( GRADIENT_AXIAL, Color( 185, 182, 215 ), Color( 250, 245, 255 ) ); + aGradient.SetAngle(900); + SetBackground( aGradient ); + Show(); +} + + +void BreakpointWindow::Reset() +{ + Breakpoint* pBrk = First(); + while ( pBrk ) + { + delete pBrk; + pBrk = Next(); + } + Clear(); + + pModule->ClearAllBP(); +} + +void BreakpointWindow::SetModule( SbModule *pMod ) +{ + pModule = pMod; + USHORT i; + for ( i=0 ; i < pModule->GetBPCount() ; i++ ) + { + InsertBreakpoint( pModule->GetBP( i ) ); + } + SetBPsInModule(); +} + + +void BreakpointWindow::SetBPsInModule() +{ + pModule->ClearAllBP(); + + Breakpoint* pBrk = First(); + while ( pBrk ) + { + pModule->SetBP( (USHORT)pBrk->nLine ); +#if OSL_DEBUG_LEVEL > 1 + DBG_ASSERT( !pModule->IsCompiled() || pModule->IsBP( (USHORT)pBrk->nLine ), "Brechpunkt wurde nicht gesetzt" ); +#endif + pBrk = Next(); + } + for ( USHORT nMethod = 0; nMethod < pModule->GetMethods()->Count(); nMethod++ ) + { + SbMethod* pMethod = (SbMethod*)pModule->GetMethods()->Get( nMethod ); + DBG_ASSERT( pMethod, "Methode nicht gefunden! (NULL)" ); + pMethod->SetDebugFlags( pMethod->GetDebugFlags() | SbDEBUG_BREAK ); + } +} + + +void BreakpointWindow::InsertBreakpoint( USHORT nLine ) +{ + Breakpoint* pNewBrk = new Breakpoint( nLine ); + Breakpoint* pBrk = First(); + while ( pBrk ) + { + if ( nLine <= pBrk->nLine ) + { + if ( pBrk->nLine != nLine ) + Insert( pNewBrk ); + else + delete pNewBrk; + pNewBrk = NULL; + pBrk = NULL; + } + else + pBrk = Next(); + } + // No insert position found => LIST_APPEND + if ( pNewBrk ) + Insert( pNewBrk, LIST_APPEND ); + + Invalidate(); + + if ( pModule->SetBP( nLine ) ) + { +#if OSL_DEBUG_LEVEL > 1 + DBG_ASSERT( !pModule->IsCompiled() || pModule->IsBP( nLine ), "Brechpunkt wurde nicht gesetzt" ); +#endif + if ( StarBASIC::IsRunning() ) + { + for ( USHORT nMethod = 0; nMethod < pModule->GetMethods()->Count(); nMethod++ ) + { + SbMethod* pMethod = (SbMethod*)pModule->GetMethods()->Get( nMethod ); + DBG_ASSERT( pMethod, "Methode nicht gefunden! (NULL)" ); + pMethod->SetDebugFlags( pMethod->GetDebugFlags() | SbDEBUG_BREAK ); + } + } + } +#if OSL_DEBUG_LEVEL > 1 + DBG_ASSERT( !pModule->IsCompiled() || pModule->IsBP( nLine ), "Brechpunkt wurde nicht gesetzt" ); +#endif +} + + +Breakpoint* BreakpointWindow::FindBreakpoint( ULONG nLine ) +{ + Breakpoint* pBrk = First(); + while ( pBrk ) + { + if ( pBrk->nLine == nLine ) + return pBrk; + + pBrk = Next(); + } + + return (Breakpoint*)0; +} + + +void BreakpointWindow::AdjustBreakpoints( ULONG nLine, BOOL bInserted ) +{ + if ( nLine == 0 ) //TODO: nLine == TEXT_PARA_ALL+1 + return; + Breakpoint* pBrk = First(); + while ( pBrk ) + { + BOOL bDelBrk = FALSE; + if ( pBrk->nLine == nLine ) + { + if ( bInserted ) + pBrk->nLine++; + else + bDelBrk = TRUE; + } + else if ( pBrk->nLine > nLine ) + { + if ( bInserted ) + pBrk->nLine++; + else + pBrk->nLine--; + } + + if ( bDelBrk ) + { + ULONG n = GetCurPos(); + delete Remove( pBrk ); + pBrk = Seek( n ); + } + else + { + pBrk = Next(); + } + } + Invalidate(); +} + + +void BreakpointWindow::LoadBreakpoints( String aFilename ) +{ + Config aConfig(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + + aConfig.SetGroup("Breakpoints"); + + ByteString aBreakpoints; + aBreakpoints = aConfig.ReadKey( ByteString( aFilename, RTL_TEXTENCODING_UTF8 ) ); + + xub_StrLen i; + + for ( i = 0 ; i < aBreakpoints.GetTokenCount( ';' ) ; i++ ) + { + InsertBreakpoint( (USHORT)aBreakpoints.GetToken( i, ';' ).ToInt32() ); + } +} + + +void BreakpointWindow::SaveBreakpoints( String aFilename ) +{ + ByteString aBreakpoints; + + Breakpoint* pBrk = First(); + while ( pBrk ) + { + if ( aBreakpoints.Len() ) + aBreakpoints += ';'; + + aBreakpoints += ByteString::CreateFromInt32( pBrk->nLine ); + pBrk = Next(); + } + + Config aConfig(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") )); + + aConfig.SetGroup("Breakpoints"); + + if ( aBreakpoints.Len() ) + aConfig.WriteKey( ByteString( aFilename, RTL_TEXTENCODING_UTF8 ), aBreakpoints ); + else + aConfig.DeleteKey( ByteString( aFilename, RTL_TEXTENCODING_UTF8 ) ); +} + + +void BreakpointWindow::Paint( const Rectangle& ) +{ + Size aOutSz( GetOutputSize() ); + long nLineHeight = GetTextHeight(); + + Image aBrk( pImages->GetImage( IMGID_BRKENABLED ) ); + Size aBmpSz( aBrk.GetSizePixel() ); + aBmpSz = PixelToLogic( aBmpSz ); + Point aBmpOff( 0, 0 ); + aBmpOff.X() = ( aOutSz.Width() - aBmpSz.Width() ) / 2; + aBmpOff.Y() = ( nLineHeight - aBmpSz.Height() ) / 2; + + Breakpoint* pBrk = First(); + while ( pBrk ) + { +#if OSL_DEBUG_LEVEL > 1 + DBG_ASSERT( !pModule->IsCompiled() || pModule->IsBP( pBrk->nLine ), "Brechpunkt wurde nicht gesetzt" ); +#endif + ULONG nLine = pBrk->nLine-1; + ULONG nY = nLine*nLineHeight - nCurYOffset; + DrawImage( Point( 0, nY ) + aBmpOff, aBrk ); + pBrk = Next(); + } + ShowMarker( TRUE ); +} + + +Breakpoint* BreakpointWindow::FindBreakpoint( const Point& rMousePos ) +{ + long nLineHeight = GetTextHeight(); + long nYPos = rMousePos.Y() + nCurYOffset; + + Breakpoint* pBrk = First(); + while ( pBrk ) + { + ULONG nLine = pBrk->nLine-1; + long nY = nLine*nLineHeight; + if ( ( nYPos > nY ) && ( nYPos < ( nY + nLineHeight ) ) ) + return pBrk; + pBrk = Next(); + } + return 0; +} + + +void BreakpointWindow::ToggleBreakpoint( USHORT nLine ) +{ + Breakpoint* pBrk = FindBreakpoint( nLine ); + if ( pBrk ) // remove + { + pModule->ClearBP( nLine ); + delete Remove( pBrk ); + } + else // create one + { + InsertBreakpoint( nLine ); + } + + Invalidate(); +} + +void BreakpointWindow::ShowMarker( BOOL bShow ) +{ + if ( nMarkerPos == MARKER_NOMARKER ) + return; + + Size aOutSz( GetOutputSize() ); + long nLineHeight = GetTextHeight(); + + Image aMarker; + if ( bErrorMarker ) + aMarker = pImages->GetImage( IMGID_ERRORMARKER ); + else + aMarker = pImages->GetImage( IMGID_STEPMARKER ); + + Size aMarkerSz( aMarker.GetSizePixel() ); + aMarkerSz = PixelToLogic( aMarkerSz ); + Point aMarkerOff( 0, 0 ); + aMarkerOff.X() = ( aOutSz.Width() - aMarkerSz.Width() ) / 2; + aMarkerOff.Y() = ( nLineHeight - aMarkerSz.Height() ) / 2; + + ULONG nY = nMarkerPos*nLineHeight - nCurYOffset; + Point aPos( 0, nY ); + aPos += aMarkerOff; + if ( bShow ) + DrawImage( aPos, aMarker ); + else + Invalidate( Rectangle( aPos, aMarkerSz ) ); +} + + +void BreakpointWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.GetClicks() == 2 ) + { + Point aMousePos( PixelToLogic( rMEvt.GetPosPixel() ) ); + long nLineHeight = GetTextHeight(); + long nYPos = aMousePos.Y() + nCurYOffset; + long nLine = nYPos / nLineHeight + 1; + ToggleBreakpoint( sal::static_int_cast< USHORT >(nLine) ); + Invalidate(); + } +} + + +void BreakpointWindow::SetMarkerPos( USHORT nLine, BOOL bError ) +{ + ShowMarker( FALSE ); // Remove old one + nMarkerPos = nLine; + bErrorMarker = bError; + ShowMarker( TRUE ); // Draw new one + Update(); +} + + +void BreakpointWindow::Scroll( long nHorzScroll, long nVertScroll, USHORT nFlags ) +{ + (void) nFlags; /* avoid warning about unused parameter */ + nCurYOffset -= nVertScroll; + Window::Scroll( nHorzScroll, nVertScroll ); +} + diff --git a/basic/source/app/brkpnts.hxx b/basic/source/app/brkpnts.hxx new file mode 100644 index 000000000000..4a9d5868f738 --- /dev/null +++ b/basic/source/app/brkpnts.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: brkpnts.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <vcl/window.hxx> + +#define MARKER_NOMARKER 0xFFFF + + +class SbModule; +class BreakpointListe; +struct Breakpoint; +class ImageList; + +DECLARE_LIST( BreakpointList, Breakpoint* ) + +class BreakpointWindow : public Window, public BreakpointList +{ +using Window::Scroll; + +public: + BreakpointWindow( Window *pParent ); +// ~BreakpointWindow(); + + void Reset(); + + void SetModule( SbModule *pMod ); + void SetBPsInModule(); + + void InsertBreakpoint( USHORT nLine ); + void ToggleBreakpoint( USHORT nLine ); + void AdjustBreakpoints( ULONG nLine, BOOL bInserted ); + + void LoadBreakpoints( String aFilename ); + void SaveBreakpoints( String aFilename ); + +protected: + Breakpoint* FindBreakpoint( ULONG nLine ); + +private: + long nCurYOffset; + USHORT nMarkerPos; + SbModule* pModule; + BOOL bErrorMarker; + static ImageList *pImages; + +protected: + virtual void Paint( const Rectangle& ); + Breakpoint* FindBreakpoint( const Point& rMousePos ); + void ShowMarker( BOOL bShow ); + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + +public: + +// void SetModulWindow( ModulWindow* pWin ) +// { pModulWindow = pWin; } + + void SetMarkerPos( USHORT nLine, BOOL bErrorMarker = FALSE ); + + virtual void Scroll( long nHorzScroll, long nVertScroll, + USHORT nFlags = 0 ); + long& GetCurYOffset() { return nCurYOffset; } +}; + + + + + + + + diff --git a/basic/source/app/dataedit.hxx b/basic/source/app/dataedit.hxx new file mode 100644 index 000000000000..dd06d9d8d456 --- /dev/null +++ b/basic/source/app/dataedit.hxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dataedit.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DATAEDIT_HXX +#define DATAEDIT_HXX + +#include <vcl/menu.hxx> +#include <tools/link.hxx> +#include <tools/gen.hxx> +#include <svtools/textdata.hxx> + +class String; +class Font; + +// Find, Load and Save must be implemented, +// the others must exist in MemberType +#define DATA_FUNC_DEF( MemberName, MemberType ) \ +public: \ + MemberType MemberName; \ + BOOL Find( const String& rStr ); \ + BOOL Load( const String& rStr ); \ + BOOL Save( const String& rStr ); \ + \ + void GrabFocus(){ MemberName.GrabFocus(); } \ + void Show(){ MemberName.Show(); } \ + void SetPosPixel( const Point& rNewPos ){ MemberName.SetPosPixel(rNewPos); }\ + void SetSizePixel( const Size& rNewSize ){ MemberName.SetSizePixel(rNewSize); } \ + Size GetSizePixel(){ return MemberName.GetSizePixel(); } \ + Point GetPosPixel(){ return MemberName.GetPosPixel(); } \ + void Update(){ MemberName.Update(); } \ + void SetFont( const Font& rNewFont ){ MemberName.SetFont(rNewFont); } \ + \ + void Delete(); \ + void Cut(); \ + void Copy(); \ + void Paste(); \ + void Undo(); \ + void Redo(); \ + String GetText() const; \ + void SetText( const String& rStr ); \ + BOOL HasText() const; \ + String GetSelected(); \ + TextSelection GetSelection() const; \ + void SetSelection( const TextSelection& rSelection ); \ + USHORT GetLineNr() const; \ + void ReplaceSelected( const String& rStr ); \ + BOOL IsModified(); \ + void SetModifyHdl( Link l ); + + +class DataEdit +{ +public: + virtual ~DataEdit(){} + + virtual void Delete()=0; + virtual void Cut()=0; + virtual void Copy()=0; + virtual void Paste()=0; + + virtual void Undo()=0; + virtual void Redo()=0; + + virtual BOOL Find( const String& )=0; // Find and select text + virtual BOOL Load( const String& )=0; // Load text from file + virtual BOOL Save( const String& )=0; // Save text to file + virtual String GetSelected()=0; + virtual void GrabFocus()=0; + virtual TextSelection GetSelection() const=0; + virtual void SetSelection( const TextSelection& rSelection )=0; + virtual USHORT GetLineNr() const=0; + virtual String GetText() const=0; + virtual void SetText( const String& rStr )=0; + virtual BOOL HasText() const=0; // to avoid GetText.Len() + virtual void ReplaceSelected( const String& rStr )=0; + virtual BOOL IsModified()=0; + virtual void SetModifyHdl( Link )=0; + virtual void Show()=0; + virtual void SetPosPixel( const Point& rNewPos )=0; + virtual void SetSizePixel( const Size& rNewSize )=0; + virtual Size GetSizePixel()=0; + virtual Point GetPosPixel()=0; + virtual void Update()=0; + virtual void SetFont( const Font& rNewFont )=0; + + virtual void BuildKontextMenu( PopupMenu *&pMenu ) + { + (void) pMenu; /* avoid warning about unused parameter */ + } +}; + +#endif diff --git a/basic/source/app/dialogs.cxx b/basic/source/app/dialogs.cxx new file mode 100644 index 000000000000..8c4df4186f41 --- /dev/null +++ b/basic/source/app/dialogs.cxx @@ -0,0 +1,1510 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dialogs.cxx,v $ + * $Revision: 1.37 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/solar.h> + +#include <algorithm> +#include <tools/rc.hxx> +#include <vcl/metric.hxx> +#ifndef _DIALOG_HXX //autogen +#include <vcl/dialog.hxx> +#endif +#ifndef _BUTTON_HXX //autogen +#include <vcl/button.hxx> +#endif +#ifndef _FIXED_HXX //autogen +#include <vcl/fixed.hxx> +#endif +#ifndef _EDIT_HXX //autogen +#include <vcl/edit.hxx> +#endif +#include <tools/config.hxx> +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <tools/debug.hxx> +#ifndef _SV_FILEDLG_HXX //autogen +#include <svtools/filedlg.hxx> +#endif +#include <tools/stream.hxx> +#include <tools/fsys.hxx> +#include <svtools/stringtransfer.hxx> +#include <vcl/splitwin.hxx> +#ifndef _ZFORLIST_HXX //autogen +#include <svtools/zformat.hxx> +#endif +#include <svtools/ctrltool.hxx> + +// Ohne Includeschutz +#include <svtools/svtdata.hxx> +#include <svtools/solar.hrc> + + +#include <basic/dispdefs.hxx> +#include <basic/testtool.hxx> +#include "dialogs.hxx" +#include "resids.hrc" +#include "basic.hrc" + +#include "app.hxx" +#include "basrid.hxx" + +#include "_version.h" + +AboutDialog::AboutDialog( Window* pParent, const ResId& id ) +: ModalDialog( pParent, id ) +, a1( this, ResId( 1, *id.GetResMgr() ) ) +, a4( this, ResId( 4, *id.GetResMgr() ) ) +, aVersionString( this, ResId( RID_VERSIONSTRING, *id.GetResMgr() ) ) +, aOk ( this, ResId( RID_OK, *id.GetResMgr() ) ) +{ + FreeResource(); +} + +//////////////////////////////////////////////////////////////////// + +FindDialog::FindDialog( Window* pParent, const ResId& id, String& Text ) +: ModalDialog( pParent, id ) +, aFT1( this, ResId( RID_FIXEDTEXT1, *id.GetResMgr() ) ) +, aFind( this, ResId( RID_FIND, *id.GetResMgr() ) ) +, aOk( this, ResId( RID_OK, *id.GetResMgr() ) ) +, aCancel( this, ResId( RID_CANCEL, *id.GetResMgr() ) ) +{ + FreeResource(); + pFind = &Text; + // Button-Handler: + aOk.SetClickHdl( LINK( this, FindDialog, ButtonClick ) ); + aCancel.SetClickHdl( LINK( this, FindDialog, ButtonClick ) ); + aFind.SetText( Text ); +} + +IMPL_LINK_INLINE_START( FindDialog, ButtonClick, Button *, pB ) +{ + if( pB == &aOk ) { + *pFind = aFind.GetText(); + EndDialog( TRUE ); + } else EndDialog( FALSE ); + return TRUE; +} +IMPL_LINK_INLINE_END( FindDialog, ButtonClick, Button *, pB ) + +ReplaceDialog::ReplaceDialog(Window* pParent, const ResId& id, String& Old, String& New ) +: ModalDialog( pParent, id ) +, aFT1( this, ResId( RID_FIXEDTEXT1, *id.GetResMgr() ) ) +, aFT2( this, ResId( RID_FIXEDTEXT2, *id.GetResMgr() ) ) +, aFind( this, ResId( RID_FIND, *id.GetResMgr() ) ) +, aReplace(this, ResId( RID_REPLACE, *id.GetResMgr() ) ) +, aOk( this, ResId( RID_OK, *id.GetResMgr() ) ) +, aCancel( this, ResId( RID_CANCEL, *id.GetResMgr() ) ) +{ + FreeResource(); + pFind = &Old; + pReplace = &New; + // Button-Handler: + aOk.SetClickHdl( LINK( this, ReplaceDialog, ButtonClick ) ); + aCancel.SetClickHdl( LINK( this, ReplaceDialog, ButtonClick ) ); + aFind.SetText( Old ); + aReplace.SetText( New ); +} + +IMPL_LINK( ReplaceDialog, ButtonClick, Button *, pB ) +{ + if( pB == &aOk ) { + *pFind = aFind.GetText(); + *pReplace = aReplace.GetText(); + EndDialog( TRUE ); + } else EndDialog( FALSE ); + return TRUE; +} + +//////////////////////////////////////////////////////////////////// + + +void CheckButtons( ComboBox &aCB, Button &aNewB, Button &aDelB ) +{ + aNewB.Enable( aCB.GetEntryPos( aCB.GetText() ) == COMBOBOX_ENTRY_NOTFOUND && aCB.GetText().Len() ); + aDelB.Enable( aCB.GetEntryPos( aCB.GetText() ) != COMBOBOX_ENTRY_NOTFOUND ); +} + + +void ConfEdit::Init( Config &aConf ) +{ + aConf.SetGroup("Misc"); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + + String aTemp = UniString( aConf.ReadKey( aKeyName ), RTL_TEXTENCODING_UTF8 ); + aEdit.SetText( aTemp ); +} + +ConfEdit::ConfEdit( Window* pParent, USHORT nResText, USHORT nResEdit, USHORT nResButton, const ByteString& aKN, Config &aConf ) +: PushButton( pParent, SttResId(nResButton) ) +, aText( pParent, SttResId(nResText) ) +, aEdit( pParent, SttResId(nResEdit) ) +, aKeyName(aKN) +{ + Init( aConf ); +} + +ConfEdit::ConfEdit( Window* pParent, USHORT nResEdit, USHORT nResButton, const ByteString& aKN, Config &aConf ) +: PushButton( pParent, SttResId(nResButton) ) +, aText( pParent ) +, aEdit( pParent, SttResId(nResEdit) ) +, aKeyName(aKN) +{ + Init( aConf ); + aText.Hide(); +} + +void ConfEdit::Save( Config &aConf ) +{ + aConf.SetGroup("Misc"); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + aConf.WriteKey( aKeyName, ByteString( aEdit.GetText(), RTL_TEXTENCODING_UTF8 ) ); +} + +void ConfEdit::Reload( Config &aConf ) +{ + aConf.SetGroup("Misc"); + ByteString aCurrentProfile = aConf.ReadKey( "CurrentProfile", "Path" ); + aConf.SetGroup( aCurrentProfile ); + String aValue = String( aConf.ReadKey( aKeyName ), RTL_TEXTENCODING_UTF8 ); + aEdit.SetText( aValue ); +} + +void ConfEdit::Click() +{ + PathDialog aPD( this ); + aPD.SetPath( aEdit.GetText() ); + if ( aPD.Execute() ) + { + aEdit.SetText( aPD.GetPath() ); + aEdit.Modify(); + } +} + +OptConfEdit::OptConfEdit( Window* pParent, USHORT nResCheck, USHORT nResEdit, USHORT nResButton, const ByteString& aKN, ConfEdit& rBaseEdit, Config& aConf ) +: ConfEdit( pParent, nResEdit, nResButton, aKN, aConf ) +, aCheck( pParent, SttResId( nResCheck ) ) +, rBase( rBaseEdit ) +{ + aCheck.SetToggleHdl( LINK( this, OptConfEdit, ToggleHdl ) ); + rBase.SetModifyHdl( LINK( this, OptConfEdit, BaseModifyHdl ) ); +} + +void OptConfEdit::Reload( Config &aConf ) +{ + ConfEdit::Reload( aConf ); + + DirEntry aCalculatedHIDDir( rBase.GetValue() ); + aCalculatedHIDDir += DirEntry( "global/hid", FSYS_STYLE_FAT ); + + DirEntry aCurrentHIDDir( aEdit.GetText() ); + + aCheck.Check( aCalculatedHIDDir == aCurrentHIDDir || aEdit.GetText().Len() == 0 ); + aEdit.Enable( !aCheck.IsChecked() ); + Enable( !aCheck.IsChecked() ); +} + +IMPL_LINK( OptConfEdit, ToggleHdl, CheckBox*, EMPTYARG ) +{ + BaseModifyHdl( &aEdit ); + aEdit.Enable( !aCheck.IsChecked() ); + Enable( !aCheck.IsChecked() ); + return 0; +} + +IMPL_LINK( OptConfEdit, BaseModifyHdl, Edit*, EMPTYARG ) +{ + if ( aCheck.IsChecked() ) + { + DirEntry aCalculatedHIDDir( rBase.GetValue() ); + aCalculatedHIDDir += DirEntry( "global/hid", FSYS_STYLE_FAT ); + aEdit.SetText( aCalculatedHIDDir.GetFull() ); + } + return 0; +} + + +OptionsDialog::OptionsDialog( Window* pParent, const ResId& aResId ) +: TabDialog( pParent, aResId ) +, aTabCtrl( this, ResId( RES_TC_OPTIONS, *aResId.GetResMgr() ) ) +, aOK( this ) +, aCancel( this ) +, aConfig( Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") ) ) +{ + aConfig.EnablePersistence( FALSE ); + FreeResource(); + aTabCtrl.SetActivatePageHdl( LINK( this, OptionsDialog, ActivatePageHdl ) ); + aTabCtrl.SetCurPageId( RID_TP_PRO ); + ActivatePageHdl( &aTabCtrl ); + + aOK.SetClickHdl( LINK( this, OptionsDialog, OKClick ) ); + + aOK.Show(); + aCancel.Show(); +} + +OptionsDialog::~OptionsDialog() +{ + for ( USHORT i = 0; i < aTabCtrl.GetPageCount(); i++ ) + delete aTabCtrl.GetTabPage( aTabCtrl.GetPageId( i ) ); +}; + +BOOL OptionsDialog::Close() +{ + if ( TabDialog::Close() ) + { + delete this; + return TRUE; + } + else + return FALSE; +} + + +IMPL_LINK( OptionsDialog, ActivatePageHdl, TabControl *, pTabCtrl ) +{ + USHORT nId = pTabCtrl->GetCurPageId(); + // If TabPage was not yet created, do it + if ( !pTabCtrl->GetTabPage( nId ) ) + { + TabPage *pNewTabPage = NULL; + switch ( nId ) + { + case RID_TP_GEN: + pNewTabPage = new GenericOptions( pTabCtrl, aConfig ); + break; + case RID_TP_PRO: + pNewTabPage = new ProfileOptions( pTabCtrl, aConfig ); + break; + case RID_TP_CRA: + pNewTabPage = new CrashreportOptions( pTabCtrl, aConfig ); + break; + case RID_TP_MIS: + pNewTabPage = new MiscOptions( pTabCtrl, aConfig ); + break; + case RID_TP_FON: + pNewTabPage = new FontOptions( pTabCtrl, aConfig ); + break; + default: DBG_ERROR( "PageHdl: Unbekannte ID!" ); + } + DBG_ASSERT( pNewTabPage, "Keine Page!" ); + pTabCtrl->SetTabPage( nId, pNewTabPage ); + } + return 0; +} + + + + +IMPL_LINK( OptionsDialog, OKClick, Button *, pButton ) +{ + (void) pButton; /* avoid warning about unused parameter */ + aConfig.EnablePersistence(); + GenericOptions *pGeneric; + pGeneric = (GenericOptions*)aTabCtrl.GetTabPage( RID_TP_GEN ); + if ( pGeneric ) + pGeneric->Save( aConfig ); + + ProfileOptions *pProfile; + pProfile = (ProfileOptions*)aTabCtrl.GetTabPage( RID_TP_PRO ); + if ( pProfile ) + pProfile->Save( aConfig ); + + CrashreportOptions *pCrash; + pCrash = (CrashreportOptions*)aTabCtrl.GetTabPage( RID_TP_CRA ); + if ( pCrash ) + pCrash->Save( aConfig ); + + MiscOptions *pMisc; + pMisc = (MiscOptions*)aTabCtrl.GetTabPage( RID_TP_MIS ); + if ( pMisc ) + pMisc->Save( aConfig ); + + FontOptions *pFonts; + pFonts = (FontOptions*)aTabCtrl.GetTabPage( RID_TP_FON ); + if ( pFonts ) + pFonts->Save( aConfig ); + + aConfig.Flush(); + + ((BasicApp*)GetpApp())->LoadIniFile(); + Close(); + return 0; +} + +const ByteString ProfilePrefix("_profile_"); +const USHORT ProfilePrefixLen = ProfilePrefix.Len(); + +ProfileOptions::ProfileOptions( Window* pParent, Config &rConfig ) +: TabPage( pParent, SttResId( RID_TP_PROFILE ) ) +, rConf( rConfig ) + +, aFlProfile( this, SttResId( RID_FL_PROFILE ) ) +, aCbProfile( this, SttResId( RID_CB_PROFILE ) ) +, aPbNewProfile( this, SttResId( RID_PB_NEW_PROFILE ) ) +, aPbDelProfile( this, SttResId( RID_PD_DEL_PROFILE ) ) + +, aDirs( this, SttResId(FL_DIRECTORIES) ) +, aLog( this, LOG_TEXT, LOG_NAME, LOG_SET, "LogBaseDir", rConfig ) +, aBasis( this, BASIS_TEXT, BASIS_NAME, BASIS_SET, "BaseDir", rConfig ) +, aHID( this, HID_CHECK, HID_NAME, HID_SET, "HIDDir", aBasis, rConfig ) + +, aAutoReload( this, SttResId(CB_AUTORELOAD) ) +, aAutoSave( this, SttResId(CB_AUTOSAVE) ) +, aStopOnSyntaxError( this, SttResId(CB_STOPONSYNTAXERRORS) ) +{ + FreeResource(); + + aCbProfile.EnableAutocomplete( TRUE ); + + aCbProfile.SetSelectHdl( LINK( this, ProfileOptions, Select ) ); + + aPbNewProfile.SetClickHdl( LINK( this, ProfileOptions, NewProfile ) ); + aPbDelProfile.SetClickHdl( LINK( this, ProfileOptions, DelProfile ) ); + aCbProfile.SetModifyHdl( LINK( this, ProfileOptions, CheckButtonsHdl ) ); + + LoadData(); + ReloadProfile(); +} + +void ProfileOptions::LoadData() +{ + // collect all profiles (all groups starting with the ProfilePrefix) + for ( USHORT i = 0 ; i < rConf.GetGroupCount() ; i++ ) + { + ByteString aProfile = rConf.GetGroupName( i ); + if ( aProfile.Match( ProfilePrefix ) ) + aCbProfile.InsertEntry( String( aProfile.Copy( ProfilePrefixLen ), RTL_TEXTENCODING_UTF8 ) ); + } + // set the current profile + rConf.SetGroup( "Misc" ); + ByteString aCurrentProfile = rConf.ReadKey( "CurrentProfile", "Path" ); + aCbProfile.SetText( String( aCurrentProfile.Copy( ProfilePrefixLen ), RTL_TEXTENCODING_UTF8 ) ); + CheckButtons( aCbProfile, aPbNewProfile, aPbDelProfile ); +} + +IMPL_LINK( ProfileOptions, Select, ComboBox*, EMPTYARG ) +{ + if ( aCbProfile.GetEntryPos( aCbProfile.GetText() ) == LISTBOX_ENTRY_NOTFOUND ) + return 1; + Save(); + ByteString aProfileKey( ByteString( ProfilePrefix ).Append( ByteString( aCbProfile.GetText(), RTL_TEXTENCODING_UTF8 ) ) ); + rConf.SetGroup( "Misc" ); + rConf.WriteKey( "CurrentProfile", aProfileKey ); + ReloadProfile(); + + return 0; +} + +void ProfileOptions::ReloadProfile() +{ + aLog.Reload( rConf ); + aBasis.Reload( rConf ); + aHID.Reload( rConf ); + + ByteString aTemp; + rConf.SetGroup( "Misc" ); + ByteString aCurrentProfile = rConf.ReadKey( "CurrentProfile", "Misc" ); + rConf.SetGroup( aCurrentProfile ); + aTemp = rConf.ReadKey( "AutoReload", "0" ); + aAutoReload.Check( aTemp.Equals("1") ); + aTemp = rConf.ReadKey( "AutoSave", "0" ); + aAutoSave.Check( aTemp.Equals("1") ); + aTemp = rConf.ReadKey( "StopOnSyntaxError", "0" ); + aStopOnSyntaxError.Check( aTemp.Equals("1") ); + + CheckButtons( aCbProfile, aPbNewProfile, aPbDelProfile ); +} + +IMPL_LINK( ProfileOptions, DelProfile, Button*, EMPTYARG ) +{ + String aProfile = aCbProfile.GetText(); + ByteString aProfileKey( ByteString( ProfilePrefix ).Append( ByteString( aProfile, RTL_TEXTENCODING_UTF8 ) ) ); + if ( aCbProfile.GetEntryPos( aProfile ) != COMBOBOX_ENTRY_NOTFOUND ) + { + aCbProfile.RemoveEntry( aProfile ); + rConf.DeleteGroup( aProfileKey ); + } + // Set first remaining profile as current profile + aCbProfile.SetText( aCbProfile.GetEntry( 0 ) ); + aProfile = aCbProfile.GetText(); + aProfileKey = ByteString( ProfilePrefix ).Append( ByteString( aProfile, RTL_TEXTENCODING_UTF8 ) ); + rConf.SetGroup( "Misc" ); + rConf.WriteKey( "CurrentProfile", aProfileKey ); + ReloadProfile(); + CheckButtons( aCbProfile, aPbNewProfile, aPbDelProfile ); + + return 0; +} + +IMPL_LINK( ProfileOptions, NewProfile, Button*, EMPTYARG ) +{ + aCbProfile.InsertEntry( aCbProfile.GetText() ); + ByteString aProfileKey( ByteString( ProfilePrefix ).Append( ByteString( aCbProfile.GetText(), RTL_TEXTENCODING_UTF8 ) ) ); + rConf.SetGroup( "Misc" ); + rConf.WriteKey( "CurrentProfile", aProfileKey ); + // save last profile as new data for new profile + Save(); + CheckButtons( aCbProfile, aPbNewProfile, aPbDelProfile ); + + return 0; +} + +IMPL_LINK( ProfileOptions, CheckButtonsHdl, ComboBox*, pCB ) +{ + (void) pCB; /* avoid warning about unused parameter */ + CheckButtons( aCbProfile, aPbNewProfile, aPbDelProfile ); + return 0; +} + +void ProfileOptions::Save() +{ + Save(rConf); +} + +void ProfileOptions::Save( Config &rConfig ) +{ + // save data to current profile + aLog.Save( rConfig ); + aBasis.Save( rConfig ); + aHID.Save( rConfig ); + + rConfig.SetGroup( "Misc" ); + ByteString aCurrentProfile = rConfig.ReadKey( "CurrentProfile", "Misc" ); + rConfig.SetGroup( aCurrentProfile ); + rConfig.WriteKey( "AutoReload", aAutoReload.IsChecked()?"1":"0" ); + rConfig.WriteKey( "AutoSave", aAutoSave.IsChecked()?"1":"0" ); + rConfig.WriteKey( "StopOnSyntaxError", aStopOnSyntaxError.IsChecked()?"1":"0" ); +} + +CrashreportOptions::CrashreportOptions( Window* pParent, Config &aConfig ) +: TabPage( pParent, SttResId( RID_TP_CRASH ) ) +, aFLCrashreport( this, SttResId( FL_CRASHREPORT ) ) +, aCBUseProxy( this, SttResId( CB_USEPROXY ) ) +, aFTCRHost( this, SttResId( FT_CRHOST ) ) +, aEDCRHost( this, SttResId( ED_CRHOST ) ) +, aFTCRPort( this, SttResId( FT_CRPORT ) ) +, aNFCRPort( this, SttResId( NF_CRPORT ) ) +, aCBAllowContact( this, SttResId( CB_ALLOWCONTACT ) ) +, aFTEMail( this, SttResId( FT_EMAIL ) ) +, aEDEMail( this, SttResId( ED_EMAIL ) ) +{ + FreeResource(); + + aNFCRPort.SetUseThousandSep( FALSE ); + + ByteString aTemp; + + aConfig.SetGroup("Crashreporter"); + + aTemp = aConfig.ReadKey( "UseProxy", "false" ); + if ( aTemp.EqualsIgnoreCaseAscii( "true" ) || aTemp.Equals( "1" ) ) + aCBUseProxy.Check(); + else + aCBUseProxy.Check( FALSE ); + + aCBUseProxy.SetToggleHdl( LINK( this, CrashreportOptions, CheckProxy ) ); + LINK( this, CrashreportOptions, CheckProxy ).Call( NULL ); // call once to initialize + + aTemp = aConfig.ReadKey( "ProxyServer" ); + aEDCRHost.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); + aTemp = aConfig.ReadKey( "ProxyPort", "8080" ); + aNFCRPort.SetValue( aTemp.ToInt32() ); + + + aTemp = aConfig.ReadKey( "AllowContact", "false" ); + if ( aTemp.EqualsIgnoreCaseAscii( "true" ) || aTemp.Equals( "1" ) ) + aCBAllowContact.Check(); + else + aCBAllowContact.Check( FALSE ); + + aCBAllowContact.SetToggleHdl( LINK( this, CrashreportOptions, CheckResponse ) ); + LINK( this, CrashreportOptions, CheckResponse ).Call( NULL ); // call once to initialize + + aTemp = aConfig.ReadKey( "ReturnAddress" ); + aEDEMail.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); +} + + +void CrashreportOptions::Save( Config &aConfig ) +{ + aConfig.SetGroup("Crashreporter"); + + if ( aCBUseProxy.IsChecked() ) + aConfig.WriteKey( "UseProxy", "true" ); + else + aConfig.WriteKey( "UseProxy", "false" ); + + aConfig.WriteKey( "ProxyServer", ByteString( aEDCRHost.GetText(), RTL_TEXTENCODING_UTF8 ) ); + aConfig.WriteKey( "ProxyPort", ByteString::CreateFromInt64( aNFCRPort.GetValue() ) ); + + if ( aCBAllowContact.IsChecked() ) + aConfig.WriteKey( "AllowContact", "true" ); + else + aConfig.WriteKey( "AllowContact", "false" ); + + aConfig.WriteKey( "ReturnAddress", ByteString( aEDEMail.GetText(), RTL_TEXTENCODING_UTF8 ) ); +} + +IMPL_LINK( CrashreportOptions, CheckProxy, void*, EMPTYARG ) +{ + aFTCRHost.Enable( aCBUseProxy.IsChecked() ); + aEDCRHost.Enable( aCBUseProxy.IsChecked() ); + aFTCRPort.Enable( aCBUseProxy.IsChecked() ); + aNFCRPort.Enable( aCBUseProxy.IsChecked() ); + + return 0; +} +IMPL_LINK( CrashreportOptions, CheckResponse, void*, EMPTYARG ) +{ + aFTEMail.Enable( aCBAllowContact.IsChecked() ); + aEDEMail.Enable( aCBAllowContact.IsChecked() ); + return 0; +} + +MiscOptions::MiscOptions( Window* pParent, Config &aConfig ) +: TabPage( pParent, SttResId( RID_TP_MISC ) ) +, aFLCommunication( this, SttResId(FL_COMMUNICATION) ) +, aFTHost( this, SttResId(FT_HOST) ) +, aEDHost( this, SttResId(ED_HOST) ) +, aFTTTPort( this, SttResId(FT_TTPORT) ) +, aNFTTPort( this, SttResId(NF_TTPORT) ) +, aFTUNOPort( this, SttResId(FT_UNOPORT) ) +, aNFUNOPort( this, SttResId(NF_UNOPORT) ) +, aOther( this, SttResId(FL_OTHER) ) +, aTimeoutText( this, SttResId(TIMEOUT_TEXT) ) +, aServerTimeout( this, SttResId(SERVER_TIMEOUT) ) +, aFTLRU( this, SttResId(FT_LRU) ) +, aTFMaxLRU( this, SttResId(TF_MAX_LRU) ) +, aFTProgDir( this, SttResId(FT_PROGDIR) ) +, aEDProgDir( this, SttResId(ED_PROGDIR) ) +, aPBProgDir( this, SttResId(PB_PROGDIR) ) +{ + FreeResource(); + + aNFTTPort.SetUseThousandSep( FALSE ); + aNFUNOPort.SetUseThousandSep( FALSE ); + aTFMaxLRU.SetUseThousandSep( FALSE ); + + ByteString aTemp; + + aConfig.SetGroup("Communication"); + aTemp = aConfig.ReadKey( "Host", DEFAULT_HOST ); + aEDHost.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); + aTemp = aConfig.ReadKey( "TTPort", ByteString::CreateFromInt32( TESTTOOL_DEFAULT_PORT ) ); + aNFTTPort.SetValue( aTemp.ToInt32() ); + aTemp = aConfig.ReadKey( "UnoPort", ByteString::CreateFromInt32( UNO_DEFAULT_PORT ) ); + aNFUNOPort.SetValue( aTemp.ToInt32() ); + + aConfig.SetGroup("Misc"); + aTemp = aConfig.ReadKey( "ServerTimeout", "10000" ); // Default 1 Minute + aServerTimeout.SetTime( Time(aTemp.ToInt32()) ); + + aConfig.SetGroup("LRU"); + aTemp = aConfig.ReadKey( "MaxLRU", "4" ); + aTFMaxLRU.SetValue( aTemp.ToInt32() ); + + aConfig.SetGroup("OOoProgramDir"); + aTemp = aConfig.ReadKey( "Current" ); + aEDProgDir.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); + aPBProgDir.SetClickHdl( LINK( this, MiscOptions, Click ) ); +} + +IMPL_LINK( MiscOptions, Click, void*, EMPTYARG ) +{ + PathDialog aPD( this ); + aPD.SetPath( aEDProgDir.GetText() ); + if ( aPD.Execute() ) + aEDProgDir.SetText( aPD.GetPath() ); + return 0; +} + + +void MiscOptions::Save( Config &aConfig ) +{ + aConfig.SetGroup("Communication"); + aConfig.WriteKey( "Host", ByteString( aEDHost.GetText(), RTL_TEXTENCODING_UTF8 ) ); + aConfig.WriteKey( "TTPort", ByteString::CreateFromInt64( aNFTTPort.GetValue() ) ); + aConfig.WriteKey( "UnoPort", ByteString::CreateFromInt64( aNFUNOPort.GetValue() ) ); + + aConfig.SetGroup("Misc"); + aConfig.WriteKey( "ServerTimeout", ByteString::CreateFromInt32( aServerTimeout.GetTime().GetTime() ) ); + + aConfig.SetGroup("LRU"); + ByteString aTemp = aConfig.ReadKey( "MaxLRU", "4" ); + USHORT nOldMaxLRU = (USHORT)aTemp.ToInt32(); + USHORT n; + for ( n = nOldMaxLRU ; n > aTFMaxLRU.GetValue() ; n-- ) + aConfig.DeleteKey( ByteString("LRU").Append( ByteString::CreateFromInt32( n ) ) ); + aConfig.WriteKey( "MaxLRU", ByteString::CreateFromInt64( aTFMaxLRU.GetValue() ) ); + + aConfig.SetGroup("OOoProgramDir"); + aConfig.WriteKey( C_KEY_AKTUELL, ByteString( aEDProgDir.GetText(), RTL_TEXTENCODING_UTF8 ) ); + aConfig.WriteKey( C_KEY_TYPE, ByteString( "PATH" ) ); +} + + +FontOptions::FontOptions( Window* pParent, Config &aConfig ) +: TabPage( pParent, SttResId( RID_TP_FONT ) ) +, aFTFontName( this, SttResId(FT_FONTNAME) ) +, aFontName( this, SttResId(CB_FONTNAME) ) +, aFTStyle( this, SttResId(FT_FONTSTYLE) ) +, aFontStyle( this, SttResId(CB_FONTSTYLE) ) +, aFTSize( this, SttResId(FT_FONTSIZE) ) +, aFontSize( this, SttResId(MB_FONTSIZE) ) +, aFTPreview( this, SttResId(FT_PREVIEW) ) +, aFontList( this ) +{ + FreeResource(); + + aFontName.Fill( &aFontList ); + aFontName.EnableWYSIWYG(); + aFontName.EnableSymbols(); + +// aFontSize.SetUnit( FUNIT_POINT ); +// MapMode aMode( MAP_POINT ); +// aFTPreview.SetMapMode( aMode ); + + aFontName.SetModifyHdl( LINK( this, FontOptions, FontNameChanged ) ); + aFontStyle.SetModifyHdl( LINK( this, FontOptions, FontStyleChanged ) ); + aFontSize.SetModifyHdl( LINK( this, FontOptions, FontSizeChanged ) ); + + ByteString aTemp; + aConfig.SetGroup("Misc"); + aTemp = aConfig.ReadKey( "ScriptFontName", "Courier" ); + aFontName.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); + aFontName.Modify(); + aTemp = aConfig.ReadKey( "ScriptFontStyle", "normal" ); + aFontStyle.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); + aFontStyle.Modify(); + aTemp = aConfig.ReadKey( "ScriptFontSize", "12" ); + aFontSize.SetText( String( aTemp, RTL_TEXTENCODING_UTF8 ) ); + aFontSize.Modify(); +} + +IMPL_LINK( FontOptions, FontNameChanged, void*, EMPTYARG ) +{ + aFontStyle.Fill( aFontName.GetText(), &aFontList ); + FontStyleChanged( NULL ); + return 0; +} + +IMPL_LINK( FontOptions, FontStyleChanged, void*, EMPTYARG ) +{ + FontInfo aFontInfo( aFontList.Get( aFontName.GetText(), aFontStyle.GetText() ) ); + aFontSize.Fill( &aFontInfo, &aFontList ); + FontSizeChanged( NULL ); + return 0; +} + +IMPL_LINK( FontOptions, FontSizeChanged, void*, EMPTYARG ) +{ + UpdatePreview(); + return 0; +} + +void FontOptions::UpdatePreview() +{ + Font aFont = aFontList.Get( aFontName.GetText(), aFontStyle.GetText() ); +// ULONG nFontSize = aFontSize.GetValue( FUNIT_POINT ); + ULONG nFontSize = static_cast<ULONG>((aFontSize.GetValue() + 5) / 10); + aFont.SetHeight( nFontSize ); + aFTPreview.SetFont( aFont ); + aFTPreview.SetText( aFontName.GetText() ); + aFTPreview.Invalidate(); +} + + +void FontOptions::Save( Config &aConfig ) +{ + aConfig.SetGroup("Misc"); + aConfig.WriteKey( "ScriptFontName", aFontName.GetText(), RTL_TEXTENCODING_UTF8 ); + aConfig.WriteKey( "ScriptFontStyle", aFontStyle.GetText(), RTL_TEXTENCODING_UTF8 ); + aConfig.WriteKey( "ScriptFontSize", aFontSize.GetText(), RTL_TEXTENCODING_UTF8 ); +} + + +GenericOptions::GenericOptions( Window* pParent, Config &aConfig ) +: TabPage( pParent, SttResId( RID_TP_GENERIC ) ) +, aConf( aConfig ) + +, aFlArea( this, SttResId( RID_FL_AREA ) ) +, aCbArea( this, SttResId( RID_CB_AREA ) ) +, aPbNewArea( this, SttResId( RID_PB_NEW_AREA ) ) +, aPbDelArea( this, SttResId( RID_PD_DEL_AREA ) ) + +, aFlValue( this, SttResId( RID_FL_VALUE ) ) +, aCbValue( this, SttResId( RID_CB_VALUE ) ) + +, aPbSelectPath( this, SttResId( RID_PB_SELECT_FILE ) ) +, aPbNewValue( this, SttResId( RID_PB_NEW_VALUE ) ) +, aPbDelValue( this, SttResId( RID_PB_DEL_VALUE ) ) + +, nMoveButtons( 0 ) +, bShowSelectPath( FALSE ) +{ + FreeResource(); + LoadData(); + + aCbArea.EnableAutocomplete( TRUE ); + aCbValue.EnableAutocomplete( TRUE ); + + aCbArea.SetSelectHdl( LINK( this, GenericOptions, LoadGroup ) ); + + aPbNewArea.SetClickHdl( LINK( this, GenericOptions, NewGroup ) ); + aPbDelArea.SetClickHdl( LINK( this, GenericOptions, DelGroup ) ); + + aPbSelectPath.SetClickHdl( LINK( this, GenericOptions, SelectPath ) ); + aPbNewValue.SetClickHdl( LINK( this, GenericOptions, NewValue ) ); + aPbDelValue.SetClickHdl( LINK( this, GenericOptions, DelValue ) ); + + aCbArea.SetModifyHdl( LINK( this, GenericOptions, CheckButtonsHdl ) ); + aCbValue.SetModifyHdl( LINK( this, GenericOptions, CheckButtonsHdl ) ); + aCbValue.SetSelectHdl( LINK( this, GenericOptions, CheckButtonsHdl ) ); + + aMoveTimer.SetTimeout( 60 ); + aMoveTimer.SetTimeoutHdl( LINK( this, GenericOptions, MoveButtons ) ); +} + +GenericOptions::~GenericOptions() +{ +} + +StringList* GenericOptions::GetAllGroups() +{ + StringList* pGroups = new StringList(); + for ( USHORT i = 0 ; i < aConf.GetGroupCount() ; i++ ) + { + String *pGroup = new String( aConf.GetGroupName( i ), RTL_TEXTENCODING_UTF8 ); + pGroups->Insert( pGroup ); + } + return pGroups; +} + +void GenericOptions::LoadData() +{ + StringList* pGroups = GetAllGroups(); + String* pGroup; + while ( (pGroup = pGroups->First()) != NULL ) + { + pGroups->Remove( pGroup ); + aConf.SetGroup( ByteString( *pGroup, RTL_TEXTENCODING_UTF8 ) ); + if ( aConf.ReadKey( C_KEY_AKTUELL ).Len() > 0 ) + { + aCbArea.InsertEntry( *pGroup ); + } + delete pGroup; + } + delete pGroups; + aCbArea.SetText( aCbArea.GetEntry( 0 ) ); + CheckButtons( aCbArea, aPbNewArea, aPbDelArea ); + + // Add load the data + LINK( this, GenericOptions, LoadGroup ).Call( NULL ); +} + +void GenericOptions::ShowSelectPath( const String aType ) +{ + Point aNPos = aPbNewValue.GetPosPixel(); + Point aDPos = aPbDelValue.GetPosPixel(); + long nDelta = aDPos.Y() - aNPos.Y(); + if ( aType.EqualsIgnoreCaseAscii( "PATH" ) && !bShowSelectPath ) + { // Show Path button + nMoveButtons += nDelta; + aMoveTimer.Start(); + bShowSelectPath = TRUE; + aPbSelectPath.Show( TRUE ); + aPbSelectPath.Enable( TRUE ); + } + else if ( !aType.EqualsIgnoreCaseAscii( "PATH" ) && bShowSelectPath ) + { // Hide Path button + nMoveButtons -= nDelta; + aMoveTimer.Start(); + bShowSelectPath = FALSE; + aPbSelectPath.Enable( FALSE ); + } +} + +IMPL_LINK( GenericOptions, MoveButtons, AutoTimer*, aTimer ) +{ + if ( nMoveButtons == 0 ) + { + aTimer->Stop(); + aPbSelectPath.Show( bShowSelectPath ); + return 0; + } + + int nStep = (nMoveButtons > 0) ? 2 : -2; + if ( nMoveButtons <= 1 && nMoveButtons >= -1 ) + nStep = nMoveButtons; + + nMoveButtons -= nStep ; + + Point aPos; + + aPos = aPbNewValue.GetPosPixel(); + aPos.Y() += nStep; + aPbNewValue.SetPosPixel( aPos ); + + aPos = aPbDelValue.GetPosPixel(); + aPos.Y() += nStep; + aPbDelValue.SetPosPixel( aPos ); + return 0; +} + +String GenericOptions::ReadKey( const ByteString &aGroup, const ByteString &aKey ) +{ + aConf.SetGroup( aGroup ); + return UniString( aConf.ReadKey( aKey ), RTL_TEXTENCODING_UTF8 ); +} + +IMPL_LINK( GenericOptions, LoadGroup, ComboBox*, EMPTYARG ) +{ + String aCurrentValue; + String aAllValues; + String aType; + + if ( aLastGroupName.Len() ) + { // Cache values? + aCurrentValue = aCbValue.GetText(); + if ( aCbValue.GetEntryPos( aCurrentValue ) == COMBOBOX_ENTRY_NOTFOUND ) + { // Create a new value + LINK( this, GenericOptions, NewValue ).Call( NULL ); + } + + aConf.SetGroup( aLastGroupName ); + aConf.WriteKey( C_KEY_AKTUELL, ByteString( aCurrentValue, RTL_TEXTENCODING_UTF8 ) ); + USHORT i; + for ( i=0 ; i < aCbValue.GetEntryCount() ; i++ ) + { + if ( i > 0 ) + aAllValues += ';'; + aAllValues += aCbValue.GetEntry( i ); + } + aConf.WriteKey( C_KEY_ALLE, ByteString( aAllValues, RTL_TEXTENCODING_UTF8 ) ); + } + + aCbValue.Clear(); + + ByteString aGroupName = ByteString( aCbArea.GetText(), RTL_TEXTENCODING_UTF8 ); + aCurrentValue = ReadKey( aGroupName, C_KEY_AKTUELL ); + aAllValues = ReadKey( aGroupName, C_KEY_ALLE ); + aType = ReadKey( aGroupName, C_KEY_TYPE ); + + xub_StrLen i; + for ( i=0 ; i < aAllValues.GetTokenCount() ; i++ ) + { + aCbValue.InsertEntry( aAllValues.GetToken( i ) ); + } + aCbValue.SetText( aCurrentValue ); + + aLastGroupName = aGroupName; + CheckButtons( aCbArea, aPbNewArea, aPbDelArea ); + CheckButtons( aCbValue, aPbNewValue, aPbDelValue ); + ShowSelectPath( aType ); + return 0; +} + +IMPL_LINK( GenericOptions, DelGroup, Button*, EMPTYARG ) +{ + String aGroup = aCbArea.GetText(); + if ( aCbArea.GetEntryPos( aGroup ) != COMBOBOX_ENTRY_NOTFOUND ) + { + aCbArea.RemoveEntry( aGroup ); + ByteString aByteGroup( aGroup, RTL_TEXTENCODING_UTF8 ); + aConf.DeleteGroup( aByteGroup ); + } + + aCbArea.SetText( aCbArea.GetEntry( 0 ) ); + LINK( this, GenericOptions, LoadGroup ).Call( NULL ); + + return 0; +} + +IMPL_LINK( GenericOptions, NewGroup, Button*, EMPTYARG ) +{ + aCbArea.InsertEntry( aCbArea.GetText() ); + + LINK( this, GenericOptions, LoadGroup ).Call( NULL ); + + return 0; +} + +IMPL_LINK( GenericOptions, SelectPath, Button*, EMPTYARG ) +{ + PathDialog aPD( this ); + aPD.SetPath( aCbValue.GetText() ); + if ( aPD.Execute() ) + { + aCbValue.SetText( aPD.GetPath() ); + CheckButtons( aCbValue, aPbNewValue, aPbDelValue ); + if ( aPbNewValue.IsEnabled() ) + { + LINK( this, GenericOptions, NewValue ).Call( NULL ); + } + } + return 1; +} + +IMPL_LINK( GenericOptions, DelValue, Button*, EMPTYARG ) +{ + String aValue = aCbValue.GetText(); + if ( aCbValue.GetEntryPos( aValue ) != COMBOBOX_ENTRY_NOTFOUND ) + { + aCbValue.RemoveEntry( aValue ); + } + + aCbValue.SetText( aCbValue.GetEntry( 0 ) ); + CheckButtons( aCbValue, aPbNewValue, aPbDelValue ); + return 0; +} + +IMPL_LINK( GenericOptions, NewValue, Button*, EMPTYARG ) +{ + aCbValue.InsertEntry( aCbValue.GetText() ); + CheckButtons( aCbValue, aPbNewValue, aPbDelValue ); + return 0; +} + +IMPL_LINK( GenericOptions, CheckButtonsHdl, ComboBox*, pCB ) +{ + if ( pCB == &aCbArea ) + CheckButtons( aCbArea, aPbNewArea, aPbDelArea ); + if ( pCB == &aCbValue ) + CheckButtons( aCbValue, aPbNewValue, aPbDelValue ); + return 0; +} + +void GenericOptions::Save( Config &aConfig ) +{ + (void) aConfig; /* avoid warning about unused parameter */ + DBG_ASSERT( &aConfig == &aConf, "Saving to different Configuration" ); + + // Save changes + LINK( this, GenericOptions, LoadGroup ).Call( NULL ); +} + + +class TextAndWin : public DockingWindow +{ + FixedText *pFt; + Window *pWin; + Window* pFtOriginalParent; + Window* pWinOriginalParent; + long nSpace; // default space + BOOL bAlignTop; + +public: + TextAndWin( Window *pParent, FixedText *pFtP, Window *pWinP, long nSpaceP, BOOL bAlignTopP ); + ~TextAndWin(); + + virtual void Resize(); +}; + +TextAndWin::TextAndWin( Window *pParent, FixedText *pFtP, Window *pWinP, long nSpaceP, BOOL bAlignTopP ) +: DockingWindow( pParent ) +, pFt( pFtP ) +, pWin( pWinP ) +, nSpace( nSpaceP ) +, bAlignTop( bAlignTopP ) +{ + pFtOriginalParent = pFt->GetParent(); + pWinOriginalParent = pWin->GetParent(); + pFt->SetParent( this ); + pWin->SetParent( this ); +} + +TextAndWin::~TextAndWin() +{ + pFt->SetParent( pFtOriginalParent ); + pWin->SetParent( pWinOriginalParent ); +} + +void TextAndWin::Resize() +{ + long nTopSpace = bAlignTop ? 0 : nSpace; + long nBottomSpace = bAlignTop ? nSpace : 0; + + long nFixedTextOffset; + if ( GetOutputSizePixel().Height() < 3 * pFt->GetSizePixel().Height() ) + { + pFt->Hide(); + nFixedTextOffset = 0; + } + else + { + pFt->Show(); + nFixedTextOffset = pFt->GetSizePixel().Height() + nSpace; + + // FixedText positioning + pFt->SetPosPixel( Point( 0, nTopSpace ) ); + } + + // Window positioning + long nWinPosY = nFixedTextOffset; + nWinPosY += nTopSpace; + pWin->SetPosPixel( Point( 0, nWinPosY ) ); + + // Set size of window + long nWinHeight = GetOutputSizePixel().Height(); + nWinHeight -= nWinPosY; + nWinHeight -= nBottomSpace; + pWin->SetSizePixel( Size( GetOutputSizePixel().Width(), nWinHeight ) ); +} + +DisplayHidDlg::DisplayHidDlg( Window * pParent ) +: FloatingWindow( pParent, SttResId( IDD_DISPLAY_HID ) ) +, aTbConf( this, SttResId( RID_TB_CONF ) ) +, aFtControls( this, SttResId( RID_FT_CONTROLS ) ) +, aMlbControls( this, SttResId( RID_MLB_CONTROLS ) ) +, aFtSlots( this, SttResId( RID_FT_SLOTS ) ) +, aMlbSlots( this, SttResId( RID_MLB_SLOTS ) ) +, aPbKopieren( this, SttResId( RID_PB_KOPIEREN ) ) +, aPbBenennen( this, SttResId( RID_PB_BENENNEN ) ) +, aPbSelectAll( this, SttResId( RID_PB_SELECTALL ) ) +, aOKClose( this, SttResId( RID_OK_CLOSE ) ) +, nDisplayMode( DH_MODE_KURZNAME | DH_MODE_LANGNAME ) // If we have an old office use this default +{ + FreeResource(); + +/* ResMgr* pRM = CREATERESMGR( svt ); + ToolBox aOrig( this, ResId( 12345, pRM ) ); + delete pRM; + + aTbConf.CopyItem( aOrig, 4 ); + aTbConf.InsertSeparator(); + aTbConf.CopyItem( aOrig, 5 ); + aTbConf.CopyItem( aOrig, 6 ); + aTbConf.CopyItem( aOrig, 7 ); */ + aTbConf.SetOutStyle( TOOLBOX_STYLE_FLAT ); + +#if OSL_DEBUG_LEVEL < 2 + aTbConf.Hide(); +#endif + + pSplit = new SplitWindow( this ); + pControls = new TextAndWin( pSplit, &aFtControls, &aMlbControls, aMlbControls.GetPosPixel().X(), TRUE ); + pSlots = new TextAndWin( pSplit, &aFtSlots, &aMlbSlots, aMlbControls.GetPosPixel().X(), FALSE ); + + pSplit->SetPosPixel( aFtControls.GetPosPixel() ); + pSplit->InsertItem( 1, pControls, 70, SPLITWINDOW_APPEND, 0, SWIB_PERCENTSIZE ); + pSplit->InsertItem( 2, pSlots, 30, SPLITWINDOW_APPEND, 0, SWIB_PERCENTSIZE ); + pSplit->Show(); + + aTbConf.SetBorderStyle( WINDOW_BORDER_NORMAL ); + aPbKopieren.SetClickHdl( LINK( this, DisplayHidDlg, CopyToClipboard ) ); + aPbSelectAll.SetClickHdl( LINK( this, DisplayHidDlg, SelectAll ) ); + + aMlbControls.SetSelectHdl( LINK( this, DisplayHidDlg, Select ) ); + aMlbSlots.SetSelectHdl( LINK( this, DisplayHidDlg, Select ) ); + Select( NULL ); +} + +DisplayHidDlg::~DisplayHidDlg() +{ + delete pControls; + delete pSlots; + delete pSplit; +} + +IMPL_LINK( DisplayHidDlg, CopyToClipboard, void*, EMPTYARG ) +{ + String aSammel; + USHORT i; + + for ( i=0 ; i < aMlbControls.GetSelectEntryCount() ; i++ ) + { + if ( aSammel.Len() ) + aSammel += '\n'; + aSammel += aMlbControls.GetSelectEntry( i ); + } + for ( i=0 ; i < aMlbSlots.GetSelectEntryCount() ; i++ ) + { + if ( aSammel.Len() ) + aSammel += '\n'; + aSammel += aMlbSlots.GetSelectEntry( i ); + } + ::svt::OStringTransfer::CopyString( aSammel, this ); + return 0; +} + +IMPL_LINK( DisplayHidDlg, SelectAll, PushButton*, pButton ) +{ + if ( pButton->GetState() != STATE_CHECK ) + { + USHORT i; + for ( i=0 ; i < aMlbControls.GetEntryCount() ; i++ ) + aMlbControls.SelectEntryPos( i ); + for ( i=0 ; i < aMlbSlots.GetEntryCount() ; i++ ) + aMlbSlots.SelectEntryPos( i ); + } + else + { + aMlbControls.SetNoSelection(); + aMlbControls.Invalidate(); + aMlbSlots.SetNoSelection(); + aMlbSlots.Invalidate(); + } + Select( NULL ); + return 0; +} + +IMPL_LINK( DisplayHidDlg, Select, void*, EMPTYARG ) +{ + if ( !aMlbControls.GetSelectEntryCount() && !aMlbSlots.GetSelectEntryCount() ) + aPbSelectAll.SetState( STATE_NOCHECK ); + else if ( aMlbControls.GetSelectEntryCount() == aMlbControls.GetEntryCount() + && aMlbSlots.GetSelectEntryCount() == aMlbSlots.GetEntryCount() ) + aPbSelectAll.SetState( STATE_CHECK ); + else + aPbSelectAll.SetState( STATE_DONTKNOW ); + return 0; +} + +void DisplayHidDlg::AddData( WinInfoRec* pWinInfo ) +{ + if ( pWinInfo->bIsReset ) + { + aMlbControls.Clear(); + aMlbSlots.Clear(); + + if ( pWinInfo->nRType & DH_MODE_DATA_VALID ) // no old office + nDisplayMode = pWinInfo->nRType; // Is used for mode transmission while reset +// if ( pWinInfo->aUId.GetULONG() & DH_MODE_DATA_VALID ) // kein altes Office +// nDisplayMode = pWinInfo->aUId.GetULONG(); // Wird im Reset zur �bermittlung des Modus verwendet + + return; + } + + String aMsg; + if ( ( nDisplayMode & DH_MODE_KURZNAME ) ) + { + if ( pWinInfo->aKurzname.Len() > 0 ) + aMsg += pWinInfo->aKurzname; + else + { + aMsg.AppendAscii( "--" ); + aMsg += pWinInfo->aUId; + aMsg.AppendAscii( ": " ); + aMsg += pWinInfo->aRName; + } + aMsg.Expand(20); + } + else + { + aMsg += pWinInfo->aUId; + aMsg.Expand(13); + } + aMsg.AppendAscii( " " ); // At least three blanks + + if ( nDisplayMode & DH_MODE_LANGNAME ) + { + if ( pWinInfo->aLangname.Len() > 0 ) + aMsg += pWinInfo->aLangname; + else + aMsg += String( SttResId( IDS_NO_LONGNAME ) ); + } + + aMlbControls.InsertEntry( aMsg ); + + + // Do we have a Slotname? + if ( ( nDisplayMode & DH_MODE_KURZNAME ) && pWinInfo->aSlotname.Len() > 0 ) + { + aMsg = pWinInfo->aSlotname; + aMsg.Expand(20); + aMsg.AppendAscii( " " ); + + if ( nDisplayMode & DH_MODE_LANGNAME ) + { + if ( pWinInfo->aLangname.Len() > 0 ) + aMsg += pWinInfo->aLangname; + else + aMsg += String( SttResId( IDS_NO_LONGNAME ) ); + } + + aMlbSlots.InsertEntry( aMsg ); + } +} + +void DisplayHidDlg::Resize() +{ + + if ( IsRollUp() ) + { + // We want only the toolbox to be seend + SetOutputSizePixel( aTbConf.GetSizePixel() ); + } + else + { +// SetUpdateMode( FALSE ); + + // Minimum size + Size aSize( GetOutputSizePixel() ); + aSize.Width() = std::max( aSize.Width(), (long)(aOKClose.GetSizePixel().Width() * 3 )); + aSize.Height() = std::max( aSize.Height(), (long)(aOKClose.GetSizePixel().Height() * 8 )); + SetOutputSizePixel( aSize ); + + // Default space + long nSpace = pSplit->GetPosPixel().X(); + + // Adapt ToolBox width + aTbConf.SetSizePixel( Size ( GetSizePixel().Width(), aTbConf.CalcWindowSizePixel().Height() ) ); + aTbConf.SetSizePixel( Size() ); // Hide at first + + // SplitWindow positioning + pSplit->SetPosPixel( Point( nSpace, nSpace + aTbConf.GetPosPixel().Y() + aTbConf.GetSizePixel().Height() ) ); + + // Calculate width of SplitWindows + long nSplitWidth = GetSizePixel().Width(); + nSplitWidth -= aPbBenennen.GetSizePixel().Width(); + nSplitWidth -= 3 * nSpace; // Spaces + nSplitWidth -= nSpace / 2; // Little more space at right margin + + // Calculate hight of SplitWindows + long nSplitHeight = GetOutputSizePixel().Height(); + nSplitHeight -= pSplit->GetPosPixel().Y(); + nSplitHeight -= nSpace; // bottom margin + + // Set size of SplitWindows + pSplit->SetSizePixel( Size( nSplitWidth, nSplitHeight ) ); + + Point aPos; + + // Button "Copy" positioning + aPos = pSplit->GetPosPixel(); + aPos.Move( nSplitWidth, 0 ); + aPos.Move( nSpace, 0 ); + aPbKopieren.SetPosPixel( aPos ); + + // Button "Get all" + aPos.Move( 0, aPbKopieren.GetSizePixel().Height() ); + aPos.Move( 0, nSpace ); + aPbSelectAll.SetPosPixel( aPos ); + + // Button "Name" + aPos.Move( 0, aPbSelectAll.GetSizePixel().Height() ); + aPos.Move( 0, nSpace ); + aPbBenennen.SetPosPixel( aPos ); + + // "Close" Button + aPos = pSplit->GetPosPixel(); + aPos.Move( nSpace, -aOKClose.GetSizePixel().Height() ); + aPos.Move( pSplit->GetSizePixel().Width(), pSplit->GetSizePixel().Height() ); + aOKClose.SetPosPixel( aPos ); + +// SetUpdateMode( TRUE ); +// Invalidate(); + } + FloatingWindow::Resize(); +} + + +VarEditDialog::VarEditDialog( Window * pParent, SbxVariable *pPVar ) +: ModelessDialog( pParent, SttResId( IDD_EDIT_VAR ) ) +, aFixedTextRID_FT_NAME( this, SttResId( RID_FT_NAME ) ) +, aFixedTextRID_FT_CONTENT( this, SttResId( RID_FT_CONTENT ) ) +, aFixedTextRID_FT_NEW_CONTENT( this, SttResId( RID_FT_NEW_CONTENT ) ) +, aFixedTextRID_FT_NAME_VALUE( this, SttResId( RID_FT_NAME_VALUE ) ) +, aFixedTextRID_FT_CONTENT_VALUE( this, SttResId( RID_FT_CONTENT_VALUE ) ) + +, aRadioButtonRID_RB_NEW_BOOL_T( this, SttResId( RID_RB_NEW_BOOL_T ) ) +, aRadioButtonRID_RB_NEW_BOOL_F( this, SttResId( RID_RB_NEW_BOOL_F ) ) +, aNumericFieldRID_NF_NEW_INTEGER( this, SttResId( RID_NF_NEW_INTEGER ) ) +, aNumericFieldRID_NF_NEW_LONG( this, SttResId( RID_NF_NEW_LONG ) ) +, aEditRID_ED_NEW_STRING( this, SttResId( RID_ED_NEW_STRING ) ) + +, aOKButtonRID_OK( this, SttResId( RID_OK ) ) +, aCancelButtonRID_CANCEL( this, SttResId( RID_CANCEL ) ) +, pVar( pPVar ) +{ + aFixedTextRID_FT_NAME_VALUE.SetText( pVar->GetName() ); + aFixedTextRID_FT_CONTENT_VALUE.SetText( pVar->GetString() ); + + SbxDataType eType = pVar->GetType(); + if ( ( eType & ( SbxVECTOR | SbxARRAY | SbxBYREF )) == 0 ) + { + switch ( eType ) + { + case SbxBOOL: + aRadioButtonRID_RB_NEW_BOOL_T.Show(); + aRadioButtonRID_RB_NEW_BOOL_F.Show(); + if ( pVar->GetBool() ) + aRadioButtonRID_RB_NEW_BOOL_T.Check(); + else + aRadioButtonRID_RB_NEW_BOOL_F.Check(); + break; +// case SbxCURRENCY: +// case SbxDATE: +// break; + case SbxINTEGER: + aNumericFieldRID_NF_NEW_INTEGER.Show(); + aNumericFieldRID_NF_NEW_INTEGER.SetText( pVar->GetString() ); + aNumericFieldRID_NF_NEW_INTEGER.Reformat(); + break; + case SbxLONG: + aNumericFieldRID_NF_NEW_LONG.Show(); + aNumericFieldRID_NF_NEW_LONG.SetText( pVar->GetString() ); + aNumericFieldRID_NF_NEW_LONG.Reformat(); + // Must be hardcoded otherwise the Rsc Compiler will fail + aNumericFieldRID_NF_NEW_LONG.SetMin( -aNumericFieldRID_NF_NEW_LONG.GetMax()-1 ); + aNumericFieldRID_NF_NEW_LONG.SetFirst( -aNumericFieldRID_NF_NEW_LONG.GetLast()-1 ); + break; +// case SbxOBJECT: // cannot be edited +// break; + case SbxSINGLE: + case SbxDOUBLE: + case SbxSTRING: + case SbxVARIANT: + case SbxEMPTY: + aEditRID_ED_NEW_STRING.Show(); + aEditRID_ED_NEW_STRING.SetText( pVar->GetString() ); + break; + default: // don't know how to edit + ; + } + } + + + aOKButtonRID_OK.SetClickHdl( LINK( this, VarEditDialog, OKClick ) ); +} + + +IMPL_LINK( VarEditDialog, OKClick, Button *, pButton ) +{ + (void) pButton; /* avoid warning about unused parameter */ + BOOL bWasError = SbxBase::IsError(); // Probably an error is thrown + + + SbxDataType eType = pVar->GetType(); +/* +Boolean +Currency +Date +Double +Integer +Long +Object +Single +String +Variant + + +atof + + ecvt + f + gcvt + +SvNumberformat:: + static double StringToDouble( const xub_Unicode* pStr, + const International& rIntl, + int& nErrno, + const xub_Unicode** ppEnd = NULL ); + // Converts just as strtod a decimal string to a double. + // Decimal and thousand separators come from International, + // leading spaces are omitted. + // If ppEnd!=NULL then *ppEnd is set after the parsed data. + // If pStr contains only the String to be parsed, then if success: + // **ppEnd=='\0' and *ppEnd-pStr==strlen(pStr). + // If overflow fVal=+/-HUGE_VAL, if underflow 0, + // nErrno is in this cases set to ERANGE otherwise 0. + // "+/-1.#INF" are recognized as +/-HUGE_VAL. + + */ + + + + String aContent( aEditRID_ED_NEW_STRING.GetText() ); + BOOL bError = FALSE; + switch ( eType ) + { + case SbxBOOL: + pVar->PutBool( aRadioButtonRID_RB_NEW_BOOL_T.IsChecked() ); + break; +// case SbxCURRENCY: +// pVar->PutCurrency( aContent ); +// break; +// case SbxDATE: +// pVar->PutDate( aContent ); +// break; + case SbxINTEGER: + pVar->PutInteger( (INT16)aNumericFieldRID_NF_NEW_INTEGER.GetValue() ); + break; + case SbxLONG: + pVar->PutLong( static_cast<INT32>(aNumericFieldRID_NF_NEW_LONG.GetValue()) ); + break; + case SbxDOUBLE: + case SbxSINGLE: + bError = !pVar->PutStringExt( aContent ); + break; + case SbxSTRING: + pVar->PutString( aContent ); + break; + case SbxVARIANT: + case SbxEMPTY: + bError = !pVar->PutStringExt( aContent ); + break; + default: // don't know how to edit + ; + } + + +// pVar->PutStringExt( aEditRID_ED_NEW_STRING.GetText() ); + if ( !bWasError && SbxBase::IsError() ) + { + bError = TRUE; + SbxBase::ResetError(); + } + + if ( bError ) + { + ErrorBox( this, SttResId( IDS_INVALID_VALUE ) ).Execute(); + return 1; + } + +// if ( aEditRID_ED_NEW_STRING.GetText().Compare( pVar->GetString() ) != COMPARE_EQUAL ) +// { +// aFixedTextRID_FT_CONTENT_VALUE.SetText( pVar->GetString() ); +// aEditRID_ED_NEW_STRING.SetText( pVar->GetString() ); +// return 1; +// } + + Close(); + return 0; +} + + + diff --git a/basic/source/app/dialogs.hxx b/basic/source/app/dialogs.hxx new file mode 100644 index 000000000000..7f31af2ebb47 --- /dev/null +++ b/basic/source/app/dialogs.hxx @@ -0,0 +1,374 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dialogs.hxx,v $ + * $Revision: 1.15 $ + * + * 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 _DIALOGS_HXX +#define _DIALOGS_HXX + +#ifndef _DIALOG_HXX //autogen +#include <vcl/dialog.hxx> +#endif +#ifndef _BUTTON_HXX //autogen +#include <vcl/button.hxx> +#endif +#ifndef _EDIT_HXX //autogen +#include <vcl/edit.hxx> +#endif +#ifndef _FIELD_HXX //autogen +#include <vcl/field.hxx> +#endif +#include <vcl/fixed.hxx> +#include <vcl/tabdlg.hxx> +#include <vcl/tabctrl.hxx> +#include <vcl/tabpage.hxx> +#include <tools/config.hxx> +#ifndef _TOOLS_LIST_HXX +#include <tools/list.hxx> +#endif +#include <vcl/lstbox.hxx> +#include <vcl/floatwin.hxx> +#include <vcl/toolbox.hxx> +#include <svtools/ctrltool.hxx> +#include <svtools/ctrlbox.hxx> + +class SbxVariable; + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +class AboutDialog : public ModalDialog { + FixedText a1,a4,aVersionString; + OKButton aOk; +public: + AboutDialog (Window*, const ResId&); +}; + +class FindDialog : public ModalDialog { + FixedText aFT1; + Edit aFind; + OKButton aOk; + CancelButton aCancel; + String* pFind; + DECL_LINK( ButtonClick, Button * ); +public: + FindDialog (Window*, const ResId&, String&); +}; + +class ReplaceDialog : public ModalDialog { + FixedText aFT1; + FixedText aFT2; + Edit aFind; + Edit aReplace; + OKButton aOk; + CancelButton aCancel; + String* pFind; + String* pReplace; + DECL_LINK( ButtonClick, Button * ); +public: + ReplaceDialog (Window*, const ResId&, String&, String&); +}; + +//////////////////////////////////////////////////////////////////// + +class ConfEdit : public PushButton +{ +protected: + FixedText aText; + Edit aEdit; + ByteString aKeyName; + + void Init( Config &aConf ); + +public: + ConfEdit( Window* pParent, USHORT nResText, USHORT nResEdit, USHORT nResButton, const ByteString& aKN, Config &aConf ); + ConfEdit( Window* pParent, USHORT nResEdit, USHORT nResButton, const ByteString& aKN, Config &aConf ); + void Save( Config &aConf ); + void Reload( Config &aConf ); + void Click(); + String GetValue() { return aEdit.GetText(); }; + void SetModifyHdl( Link aLink ) { aEdit.SetModifyHdl( aLink ); }; +}; + + +class OptConfEdit : public ConfEdit +{ +protected: + CheckBox aCheck; + ConfEdit& rBase; + DECL_LINK( ToggleHdl, CheckBox* ); +public: + OptConfEdit( Window* pParent, USHORT nResCheck, USHORT nResEdit, USHORT nResButton, const ByteString& aKN, ConfEdit& rBaseEdit, Config& aConf ); + void Reload( Config &aConf ); + DECL_LINK( BaseModifyHdl, Edit* ); +}; + + +class OptionsDialog : public TabDialog +{ +private: + TabControl aTabCtrl; + + OKButton aOK; + CancelButton aCancel; + DECL_LINK( OKClick, Button * ); + + Config aConfig; + +public: + OptionsDialog( Window* pParent, const ResId& ); + ~OptionsDialog(); + virtual BOOL Close(); + + + DECL_LINK( ActivatePageHdl, TabControl * ); +}; + +class ProfileOptions : public TabPage +{ + Config &rConf; + + FixedLine aFlProfile; + ComboBox aCbProfile; + PushButton aPbNewProfile; + PushButton aPbDelProfile; + + FixedLine aDirs; + ConfEdit aLog; + ConfEdit aBasis; + OptConfEdit aHID; + + CheckBox aAutoReload; + CheckBox aAutoSave; + CheckBox aStopOnSyntaxError; + + void LoadData(); + + DECL_LINK( Select, ComboBox* ); + DECL_LINK( DelProfile, Button* ); + DECL_LINK( NewProfile, Button* ); + DECL_LINK( CheckButtonsHdl, ComboBox* ); + + void ReloadProfile(); + void Save(); + +public: + ProfileOptions( Window*, Config &rConfig ); + void Save( Config &rConfig ); +}; + + +class CrashreportOptions : public TabPage +{ + FixedLine aFLCrashreport; + CheckBox aCBUseProxy; + FixedText aFTCRHost; + Edit aEDCRHost; + FixedText aFTCRPort; + NumericField aNFCRPort; + + CheckBox aCBAllowContact; + FixedText aFTEMail; + Edit aEDEMail; + + DECL_LINK( CheckProxy, void*); + DECL_LINK( CheckResponse, void*); + +public: + CrashreportOptions( Window*, Config &aConfig ); + void Save( Config &aConfig ); +}; + +class MiscOptions : public TabPage +{ + FixedLine aFLCommunication; + FixedText aFTHost; + Edit aEDHost; + FixedText aFTTTPort; + NumericField aNFTTPort; + FixedText aFTUNOPort; + NumericField aNFUNOPort; + FixedLine aOther; + FixedText aTimeoutText; + TimeField aServerTimeout; + FixedText aFTLRU; + NumericField aTFMaxLRU; + FixedText aFTProgDir; + Edit aEDProgDir; + PushButton aPBProgDir; + + DECL_LINK( Click, void*); + +public: + MiscOptions( Window*, Config &aConfig ); + void Save( Config &aConfig ); +}; + +class FontOptions : public TabPage +{ + FixedText aFTFontName; + FontNameBox aFontName; + FixedText aFTStyle; + FontStyleBox aFontStyle; + FixedText aFTSize; + FontSizeBox aFontSize; + FixedText aFTPreview; + + FontList aFontList; + + DECL_LINK( FontNameChanged, void* ); + DECL_LINK( FontStyleChanged, void* ); + DECL_LINK( FontSizeChanged, void* ); + + void UpdatePreview(); + +public: + FontOptions( Window*, Config &aConfig ); + void Save( Config &aConfig ); +}; + + +DECLARE_LIST( StringList, String * ) +#define C_KEY_ALLE CByteString("All") +#define C_KEY_AKTUELL CByteString("Current") +#define C_KEY_TYPE CByteString("Type") +#define C_KEY_DELETE CByteString("Deleted Groups") + +class GenericOptions : public TabPage +{ + Config &aConf; + + FixedLine aFlArea; + ComboBox aCbArea; + PushButton aPbNewArea; + PushButton aPbDelArea; + + FixedLine aFlValue; + ComboBox aCbValue; + PushButton aPbSelectPath; + PushButton aPbNewValue; + PushButton aPbDelValue; + + int nMoveButtons; + BOOL bShowSelectPath; + AutoTimer aMoveTimer; + DECL_LINK( MoveButtons, AutoTimer* ); + + ByteString aLastGroupName; + + String ReadKey( const ByteString &aGroup, const ByteString &aKey ); + + StringList* GetAllGroups(); + void LoadData(); + + void ShowSelectPath( const String aType ); + + DECL_LINK( LoadGroup, ComboBox* ); + DECL_LINK( DelGroup, Button* ); + DECL_LINK( NewGroup, Button* ); + DECL_LINK( SelectPath, Button* ); + DECL_LINK( DelValue, Button* ); + DECL_LINK( NewValue, Button* ); + DECL_LINK( CheckButtonsHdl, ComboBox* ); + +public: + GenericOptions( Window*, Config &aConfig ); + ~GenericOptions(); + void Save( Config &aConfig ); +}; + + +struct WinInfoRec; +class SplitWindow; + +class DisplayHidDlg : public FloatingWindow +{ +protected: + ToolBox aTbConf; + FixedText aFtControls; + MultiListBox aMlbControls; + FixedText aFtSlots; + MultiListBox aMlbSlots; + PushButton aPbKopieren; + PushButton aPbBenennen; + PushButton aPbSelectAll; + OKButton aOKClose; + + DockingWindow* pControls; + DockingWindow* pSlots; + SplitWindow *pSplit; + + ULONG nDisplayMode; + + DECL_LINK( Select, void* ); + DECL_LINK( SelectAll, PushButton* ); + DECL_LINK( CopyToClipboard, void* ); + +public: + DisplayHidDlg( Window * pParent ); + virtual ~DisplayHidDlg(); + + virtual void Resize(); + + void AddData( WinInfoRec* pWinInfo ); + +}; + + +class VarEditDialog : public ModelessDialog +{ +protected: + FixedText aFixedTextRID_FT_NAME; + FixedText aFixedTextRID_FT_CONTENT; + FixedText aFixedTextRID_FT_NEW_CONTENT; + FixedText aFixedTextRID_FT_NAME_VALUE; + FixedText aFixedTextRID_FT_CONTENT_VALUE; + + RadioButton aRadioButtonRID_RB_NEW_BOOL_T; + RadioButton aRadioButtonRID_RB_NEW_BOOL_F; + NumericField aNumericFieldRID_NF_NEW_INTEGER; + NumericField aNumericFieldRID_NF_NEW_LONG; + Edit aEditRID_ED_NEW_STRING; + + OKButton aOKButtonRID_OK; + CancelButton aCancelButtonRID_CANCEL; + + SbxVariable *pVar; + + DECL_LINK( OKClick, Button * ); + +// BOOL bCompare = FALSE; +// String aCompareString; + +public: + VarEditDialog( Window * pParent, SbxVariable *pPVar ); +}; + + +#endif diff --git a/basic/source/app/makefile.mk b/basic/source/app/makefile.mk new file mode 100644 index 000000000000..13c3b4a8b507 --- /dev/null +++ b/basic/source/app/makefile.mk @@ -0,0 +1,104 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.15 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=app + +LIBTARGET = NO + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +# --- Common ------------------------------------------------------------ + +OBJFILES = \ + $(OBJ)$/ttbasic.obj \ + $(OBJ)$/basicrt.obj \ + $(OBJ)$/processw.obj \ + $(OBJ)$/process.obj \ + $(OBJ)$/brkpnts.obj \ + $(OBJ)$/mybasic.obj \ + $(OBJ)$/status.obj \ + $(OBJ)$/printer.obj \ + $(OBJ)$/appwin.obj \ + $(OBJ)$/appedit.obj \ + $(OBJ)$/appbased.obj \ + $(OBJ)$/apperror.obj \ + $(OBJ)$/textedit.obj \ + $(OBJ)$/msgedit.obj \ + $(OBJ)$/dialogs.obj \ + +EXCEPTIONSFILES = \ + $(OBJ)$/app.obj \ + $(OBJ)$/process.obj + +.IF "$(GUI)" == "WNT" +EXCEPTIONSFILES += \ + $(OBJ)$/process.obj +.ENDIF + +SRS1NAME=$(TARGET) +SRC1FILES = \ + basic.src \ + ttmsg.src \ + basmsg.src \ + svtmsg.src \ + testtool.src + +LIB1TARGET=$(LB)$/app.lib +LIB1ARCHIV=$(LB)$/libapp.a +LIB1OBJFILES = \ + $(OBJ)$/basicrt.obj \ + $(OBJ)$/processw.obj \ + $(OBJ)$/process.obj \ + $(OBJ)$/brkpnts.obj \ + $(OBJ)$/app.obj \ + $(OBJ)$/mybasic.obj \ + $(OBJ)$/status.obj \ + $(OBJ)$/printer.obj \ + $(OBJ)$/appwin.obj \ + $(OBJ)$/appedit.obj \ + $(OBJ)$/appbased.obj \ + $(OBJ)$/apperror.obj \ + $(OBJ)$/textedit.obj \ + $(OBJ)$/msgedit.obj \ + $(OBJ)$/dialogs.obj \ + $(OBJ)$/sbintern.obj + +# --- Targets ------------------------------------------------------------ + +.INCLUDE : target.mk + +$(OBJ)$/dialogs.obj : $(INCCOM)$/_version.h + diff --git a/basic/source/app/msgedit.cxx b/basic/source/app/msgedit.cxx new file mode 100644 index 000000000000..7d0755d39aa6 --- /dev/null +++ b/basic/source/app/msgedit.cxx @@ -0,0 +1,1002 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: msgedit.cxx,v $ + * $Revision: 1.30 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +/************************************************************************* +File Versions so far: +No Version Initial Implementation without Version Information +Version 2 changed order of entries(New Entries at the end) +Version 3 Changed Charset from CHARSET_IBMPC to RTL_TEXTENCODING_UTF8 + +*************************************************************************/ +#include <cstdio> +#include <tools/time.hxx> +#include <tools/stream.hxx> +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#ifndef _SOUND_HXX //autogen +#include <vcl/sound.hxx> +#endif +#include <tools/fsys.hxx> +#include <svtools/stringtransfer.hxx> +#include <svtools/syslocale.hxx> +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif +#include "basic.hrc" +#include "msgedit.hxx" +#include "app.hxx" +#include "apperror.hxx" +#include "appbased.hxx" +#include "basmsg.hrc" +#include "basrid.hxx" + +USHORT MsgEdit::nMaxLogLen = 0; +BOOL MsgEdit::bLimitLogLen = FALSE; +BOOL MsgEdit::bPrintLogToStdout = FALSE; +BOOL MsgEdit::bPrintLogToStdoutSet = FALSE; + +#define WARNING_PREFIX String( SttResId( S_WARNING_PREFIX ) ) +#define VERSION_STRING CUniString("File Format Version: ") +#define THIS_VERSION 2 + +#define LOGTYPE( pEntry ) ((pEntry && pEntry->GetUserData())?((TTDebugData*)pEntry->GetUserData())->aLogType:LOG_ERROR) + +MsgEdit::MsgEdit( AppError* pParent, BasicFrame *pBF, const WinBits& aBits ) +: pBasicFrame(pBF) +, pCurrentRun(NULL) +, pCurrentTestCase(NULL) +, pCurrentAssertion( NULL ) +, pCurrentError(NULL) +, bModified(FALSE) +, bFileLoading(FALSE) +, nVersion(0) +, pAppError( pParent ) +, aEditTree( pParent, pBF, aBits | WB_HASBUTTONS | WB_HASLINES | WB_HASBUTTONSATROOT ) +{ +// SetFont( aEditTree.GetDefaultFont( DEFAULTFONT_FIXED, aEditTree.GetSettings().GetLanguage(), 0, &aEditTree ) ); + aEditTree.SetNodeBitmaps( Bitmap( SttResId (MBP_PLUS) ), Bitmap( SttResId (MBP_MINUS) ) ); + aEditTree.SetSelectionMode( MULTIPLE_SELECTION ); + if ( aEditTree.GetModel()->GetSortMode() != SortNone ) + aEditTree.GetModel()->SetSortMode( SortNone ); + + if ( !bPrintLogToStdoutSet ) + { + bPrintLogToStdoutSet = TRUE; + for ( USHORT i = 0 ; i < Application::GetCommandLineParamCount() ; i++ ) + { + if ( Application::GetCommandLineParam( i ).Copy(0,9).CompareIgnoreCaseToAscii("-printlog") == COMPARE_EQUAL + #ifndef UNX + || Application::GetCommandLineParam( i ).Copy(0,9).CompareIgnoreCaseToAscii("/printlog") == COMPARE_EQUAL + #endif + ) + bPrintLogToStdout = TRUE; + } + } +} + +MsgEdit::~MsgEdit() +{} + +// set the LogType since calling the add method can be from other add methods +#define COPY_TTDEBUGDATA( LOGTYPE ) \ + TTDebugData *pTTDebugData = new TTDebugData; \ + *pTTDebugData = aDebugData; \ + pTTDebugData->aLogType = LOGTYPE; \ + + +void MsgEdit::AddAnyMsg( TTLogMsg *LogMsg ) +{ + if ( LogMsg->aDebugData.aFilename.Copy(0,2).CompareToAscii( "--" ) == COMPARE_EQUAL ) + LogMsg->aDebugData.aFilename.Erase(0,2); + + if ( LogMsg->aDebugData.aFilename.Len() && LogMsg->aDebugData.aFilename.GetChar(0) != '~' ) // do we want to convert + { + DirEntry aConvert( LogMsg->aDebugData.aFilename ); + if ( pAppError->aBaseDir.Contains( aConvert ) ) + { + aConvert.ToRel( pAppError->aBaseDir ); + LogMsg->aDebugData.aFilename = CUniString("~"); // mark as converted + LogMsg->aDebugData.aFilename += aConvert.GetFull( FSYS_STYLE_VFAT ); + } + else if ( !bFileLoading ) + { + LogMsg->aDebugData.aFilename.Insert( CUniString("~-"), 0); // mark as unconvertable + } + } + xub_StrLen nPos; + LogMsg->aDebugData.aMsg.ConvertLineEnd(); + // does the message have several lines -> repeat the call for each line + if ( (nPos = LogMsg->aDebugData.aMsg.Search( CUniString("\n").ConvertLineEnd() )) != STRING_NOTFOUND ) + { + String aOriginalMsg = LogMsg->aDebugData.aMsg; + xub_StrLen nSysLineEndLen = CUniString("\n").ConvertLineEnd().Len(); + String aLastPart = LogMsg->aDebugData.aMsg.Copy( nPos+nSysLineEndLen ); + LogMsg->aDebugData.aMsg.Erase( nPos ); + AddAnyMsg( LogMsg ); + if ( aLastPart.Len() ) + { + LogMsg->aDebugData.aMsg = aLastPart; + AddAnyMsg( LogMsg ); + } + LogMsg->aDebugData.aMsg = aOriginalMsg; + } + else + { + String aUILogMsg( pBasicFrame->GenRealString( LogMsg->aDebugData.aMsg ) ); + switch ( LogMsg->aDebugData.aLogType ) + { + case LOG_RUN: + { + if ( LogMsg->aDebugData.aMsg.Len() == 0 ) + { + SvtSysLocale aLocale; + LogMsg->aDebugData.aMsg = GEN_RES_STR2( S_PROG_START, + aLocale.GetLocaleData().getDate(Date()), + aLocale.GetLocaleData().getTime(Time()) ); + aUILogMsg = pBasicFrame->GenRealString( LogMsg->aDebugData.aMsg ); + } + AddRun( aUILogMsg, LogMsg->aDebugData ); break; + } + case LOG_TEST_CASE: AddTestCase( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_ERROR: AddError( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_CALL_STACK:AddCallStack( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_MESSAGE: AddMessage( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_WARNING: AddWarning( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_ASSERTION: AddAssertion( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_ASSERTION_STACK: AddAssertionStack( aUILogMsg, LogMsg->aDebugData ); break; + case LOG_QA_ERROR: AddQAError( aUILogMsg, LogMsg->aDebugData ); break; + default:DBG_ERROR("Unbekannter Typ in ResultFile. Speichern des ResultFile resultiert in Informationsverlust"); + } + + if ( !bFileLoading ) + { // Comes from Testtool and must be written immediately + BOOL bFileWasChanged = pAppError->DiskFileChanged( SINCE_LAST_LOAD ); + + DBG_ASSERT( aLogFileName == LogMsg->aLogFileName, "Logging to different logfile as before" ); + DirEntry aEntry( LogMsg->aLogFileName ); + BOOL bNewFile = !aEntry.Exists(); + SvFileStream aStrm( LogMsg->aLogFileName, STREAM_STD_WRITE ); + if ( bNewFile ) + { + String aSave = VERSION_STRING.Append( UniString::CreateFromInt32( 3 ) ).AppendAscii("\n"); // Version 3 + aSave.ConvertLineEnd(LINEEND_CRLF); + aStrm << ByteString( aSave, RTL_TEXTENCODING_IBM_850 ).GetBuffer(); + } + + String aLogMsg = Impl_MakeSaveText( LogMsg->aDebugData ).AppendAscii("\n"); + + if( aStrm.IsOpen() ) + { + aLogMsg.ConvertLineEnd(LINEEND_CRLF); + aStrm.Seek(STREAM_SEEK_TO_END); + aStrm << ByteString( aLogMsg, RTL_TEXTENCODING_UTF8 ).GetBuffer(); + aStrm.Close(); + } + if ( !bFileWasChanged ) + pAppError->UpdateFileInfo( HAS_BEEN_LOADED ); + + + // now write to stdout + if ( bPrintLogToStdout ) + { + String aPrintMsg, aOriginalMsg; + + aOriginalMsg = LogMsg->aDebugData.aMsg; + // converting to human readable string for adding errors to list in testobject + LogMsg->aDebugData.aMsg = pBasicFrame->GenRealString( LogMsg->aDebugData.aMsg ); + + aPrintMsg = Impl_MakeSaveText( LogMsg->aDebugData ).AppendAscii("\n"); + + // restore Original Msg + LogMsg->aDebugData.aMsg = aOriginalMsg; + + printf( ByteString( aPrintMsg, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + } + } + // converting to human readable string for adding errors to list in testobject + LogMsg->aDebugData.aMsg = pBasicFrame->GenRealString( LogMsg->aDebugData.aMsg ); +} + +void MsgEdit::AddRun( String aMsg, TTDebugData aDebugData ) +{ + if ( !bFileLoading && bLimitLogLen ) + { + USHORT nSkip = nMaxLogLen; + SvLBoxEntry *pRun = aEditTree.First(); + while ( nSkip-- && pRun ) + pRun = aEditTree.NextSibling( pRun ); + // Remove all Entries thereafter + if ( pRun ) + { + while ( pRun && aEditTree.NextSibling( pRun ) ) + aEditTree.GetModel()->Remove( aEditTree.NextSibling( pRun ) ); + + aEditTree.GetModel()->Remove( pRun ); + bModified = TRUE; + lModify.Call( NULL ); + Save( aLogFileName ); + pAppError->UpdateFileInfo( HAS_BEEN_LOADED ); + } + } + + COPY_TTDEBUGDATA( LOG_RUN ); + if ( !bFileLoading || ( bFileLoading && nVersion >= 2 ) ) + pCurrentRun = aEditTree.InsertEntry( aMsg, NULL, FALSE, 0, pTTDebugData ); + else // First file format + pCurrentRun = aEditTree.InsertEntry( aMsg, NULL, FALSE, LIST_APPEND, pTTDebugData ); // and therefor at the end + + aEditTree.ShowEntry( pCurrentRun ); + pCurrentTestCase = NULL; + pCurrentAssertion = NULL; + pCurrentError = NULL; +} + +void MsgEdit::AddTestCase( String aMsg, TTDebugData aDebugData ) +{ + if ( pCurrentRun ) + { + if ( aMsg.Len() == 0 ) // End of Testcase + { + pCurrentTestCase = NULL; + } + else + { + COPY_TTDEBUGDATA( LOG_TEST_CASE ); + pCurrentTestCase = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pCurrentTestCase ); + } + } + pCurrentAssertion = NULL; + pCurrentError = NULL; +} + +void MsgEdit::AddError( String aMsg, TTDebugData aDebugData ) +{ + if ( !pCurrentTestCase ) + { + TTLogMsg aLogMsg; + aLogMsg.aDebugData = aDebugData; + aLogMsg.aDebugData.aMsg = GEN_RES_STR0( S_ERROR_OUTSIDE_TESTCASE ); + aLogMsg.aDebugData.aLogType = LOG_TEST_CASE; + aLogMsg.aLogFileName = aLogFileName; + AddAnyMsg( &aLogMsg ); + } + if ( pCurrentTestCase ) + { + COPY_TTDEBUGDATA( LOG_ERROR ); + pCurrentError = aEditTree.InsertEntry( aMsg, pCurrentTestCase, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pCurrentError ); + } +} + +void MsgEdit::AddCallStack( String aMsg, TTDebugData aDebugData ) +{ + DBG_ASSERT( pCurrentError, "Callstack ohne CurrentError im Journal" ); + if ( pCurrentError ) + { + COPY_TTDEBUGDATA( LOG_CALL_STACK ); + aEditTree.InsertEntry( aMsg, pCurrentError, FALSE, LIST_APPEND, pTTDebugData ); + } +} + +void MsgEdit::AddMessage( String aMsg, TTDebugData aDebugData ) +{ + SvLBoxEntry *pThisEntry = NULL; + COPY_TTDEBUGDATA( LOG_MESSAGE ); + if ( pCurrentTestCase ) + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentTestCase, FALSE, LIST_APPEND, pTTDebugData ); + else if ( pCurrentRun ) + { + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + else + { + AddRun( aMsg, aDebugData ); + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } +} + +void MsgEdit::AddWarning( String aMsg, TTDebugData aDebugData ) +{ + SvLBoxEntry *pThisEntry = NULL; + String aCompleteMsg; + aCompleteMsg = WARNING_PREFIX.Append( aMsg ); + COPY_TTDEBUGDATA( LOG_WARNING ); + + if ( pCurrentTestCase ) + pThisEntry = aEditTree.InsertEntry( aCompleteMsg, pCurrentTestCase, FALSE, LIST_APPEND, pTTDebugData ); + else if ( pCurrentRun ) + { + pThisEntry = aEditTree.InsertEntry( aCompleteMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + else + { + AddRun( aMsg, aDebugData ); + pThisEntry = aEditTree.InsertEntry( aCompleteMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + + while ( !aEditTree.IsEntryVisible( pThisEntry ) && ( pThisEntry = aEditTree.GetParent( pThisEntry ) ) != NULL ) + aEditTree.InvalidateEntry( pThisEntry ); +} + +void MsgEdit::AddAssertion( String aMsg, TTDebugData aDebugData ) +{ + const String aAssertionStackPrefix( CUniString(ASSERTION_STACK_PREFIX) ); + if ( aMsg.Match( aAssertionStackPrefix ) == aAssertionStackPrefix.Len() ) + { + AddAssertionStack( aMsg, aDebugData ); + return; + } + SvLBoxEntry *pThisEntry = NULL; + COPY_TTDEBUGDATA( LOG_ASSERTION ); + if ( pCurrentTestCase ) + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentTestCase, FALSE, LIST_APPEND, pTTDebugData ); + else if ( pCurrentRun ) + { + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + else + { + AddRun( aMsg, aDebugData ); + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + + pCurrentAssertion = pThisEntry; + + while ( !aEditTree.IsEntryVisible( pThisEntry ) && ( pThisEntry = aEditTree.GetParent( pThisEntry ) ) != NULL ) + aEditTree.InvalidateEntry( pThisEntry ); +} + +void MsgEdit::AddAssertionStack( String aMsg, TTDebugData aDebugData ) +{ + SvLBoxEntry *pThisEntry = NULL; + COPY_TTDEBUGDATA( LOG_ASSERTION_STACK ); + if ( pCurrentAssertion ) + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentAssertion, FALSE, LIST_APPEND, pTTDebugData ); + else if ( pCurrentTestCase ) + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentTestCase, FALSE, LIST_APPEND, pTTDebugData ); + else if ( pCurrentRun ) + { + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + else + { + AddRun( aMsg, aDebugData ); + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + + while ( !aEditTree.IsEntryVisible( pThisEntry ) && ( pThisEntry = aEditTree.GetParent( pThisEntry ) ) != NULL ) + aEditTree.InvalidateEntry( pThisEntry ); +} + +void MsgEdit::AddQAError( String aMsg, TTDebugData aDebugData ) +{ + SvLBoxEntry *pThisEntry = NULL; + COPY_TTDEBUGDATA( LOG_QA_ERROR ); + if ( pCurrentTestCase ) + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentTestCase, FALSE, LIST_APPEND, pTTDebugData ); + else if ( pCurrentRun ) + { + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + else + { + AddRun( aMsg, aDebugData ); + pThisEntry = aEditTree.InsertEntry( aMsg, pCurrentRun, FALSE, LIST_APPEND, pTTDebugData ); + aEditTree.ShowEntry( pThisEntry ); + } + + while ( !aEditTree.IsEntryVisible( pThisEntry ) && ( pThisEntry = aEditTree.GetParent( pThisEntry ) ) != NULL ) + aEditTree.InvalidateEntry( pThisEntry ); +} + +/* + SvLBoxEntry* GetEntry( SvLBoxEntry* pParent, ULONG nPos ) const { return SvLBox::GetEntry(pParent,nPos); } + SvLBoxEntry* GetEntry( ULONG nRootPos ) const { return SvLBox::GetEntry(nRootPos);} + + + + SvLBoxEntry* FirstChild(SvLBoxEntry* pParent ) const { return (SvLBoxEntry*)(pModel->FirstChild(pParent)); } + SvLBoxEntry* NextSibling(SvLBoxEntry* pEntry ) const { return (SvLBoxEntry*)(pModel->NextSibling( pEntry )); } + SvLBoxEntry* PrevSibling(SvLBoxEntry* pEntry ) const { return (SvLBoxEntry*)(pModel->PrevSibling( pEntry )); } + + SvLBoxEntry* FirstSelected() const { return (SvLBoxEntry*)SvListView::FirstSelected(); } + SvLBoxEntry* NextSelected( SvLBoxEntry* pEntry ) const { return (SvLBoxEntry*)(SvListView::NextSelected(pEntry)); } + SvLBoxEntry* PrevSelected( SvLBoxEntry* pEntry ) const { return (SvLBoxEntry*)(SvListView::PrevSelected(pEntry)); } + SvLBoxEntry* LastSelected() const { return (SvLBoxEntry*)(SvListView::LastSelected()); } + + SvLBoxEntry* GetEntry( SvLBoxEntry* pParent, ULONG nPos ) const { return (SvLBoxEntry*)(pModel->GetEntry(pParent,nPos)); } + SvLBoxEntry* GetEntry( ULONG nRootPos ) const { return (SvLBoxEntry*)(pModel->GetEntry(nRootPos)); } + + SvLBoxEntry* GetParent( SvLBoxEntry* pEntry ) const { return (SvLBoxEntry*)(pModel->GetParent(pEntry)); } + SvLBoxEntry* GetRootLevelParent(SvLBoxEntry* pEntry ) const { return (SvLBoxEntry*)(pModel->GetRootLevelParent( pEntry ));} + + BOOL IsInChildList( SvListEntry* pParent, SvListEntry* pChild) const; + SvListEntry* GetEntry( SvListEntry* pParent, ULONG nPos ) const; + SvListEntry* GetEntry( ULONG nRootPos ) const; + SvListEntry* GetEntryAtAbsPos( ULONG nAbsPos ) const; + SvListEntry* GetParent( SvListEntry* pEntry ) const; + SvListEntry* GetRootLevelParent( SvListEntry* pEntry ) const; +*/ + +//#define CHECK( pMemo ) if ( pMemo && !aEditTree.GetViewData( pMemo ) ) pMemo = NULL +#define CHECK( pMemo ) if ( pMemo && !aEditTree.GetModel()->IsInChildList( NULL, pMemo ) ) pMemo = NULL +void MsgEdit::Delete() +{ + aEditTree.RemoveSelection(); + CHECK( pCurrentRun ); + CHECK( pCurrentTestCase ); + CHECK( pCurrentAssertion ); + CHECK( pCurrentError ); + bModified = TRUE; + lModify.Call( NULL ); +} + +void MsgEdit::Cut(){ Copy(); Delete(); bModified = TRUE; lModify.Call( NULL ); } +void MsgEdit::Copy(){ ::svt::OStringTransfer::CopyString( GetSelected(), &aEditTree ); } +/**/void MsgEdit::Paste(){ Sound::Beep(); } +void MsgEdit::Undo(){ Sound::Beep(); } +void MsgEdit::Redo(){ Sound::Beep(); } + + +String MsgEdit::Impl_MakeText( SvLBoxEntry *pEntry ) const +{ + String aRet; + TTDebugData *aData = (TTDebugData*)pEntry->GetUserData(); + switch ( aData->aLogType ) + { + case LOG_RUN: aRet.AppendAscii("\n"); break; + case LOG_TEST_CASE: break; + case LOG_ERROR: break; + case LOG_CALL_STACK:aRet.AppendAscii("--> "); break; + case LOG_MESSAGE: break; + case LOG_WARNING: break; + case LOG_ASSERTION: break; + case LOG_ASSERTION_STACK:aRet.AppendAscii("--> "); break; + case LOG_QA_ERROR: break; + default:DBG_ERROR("Unknown type in ResultWindow!"); + } + aRet += aEditTree.GetEntryText( pEntry ); + return aRet; +} + +String MsgEdit::Impl_MakeSaveText( TTDebugData aData ) const +{ +// LogType;Filename;Line;Col1;Col2;Message + String aRet; + aRet += String::CreateFromInt32( (int)aData.aLogType ); + aRet += ';'; + aRet += aData.aFilename; + aRet += ';'; + aRet += String::CreateFromInt32( aData.nLine ); + aRet += ';'; + aRet += String::CreateFromInt32( aData.nCol1 ); + aRet += ';'; + aRet += String::CreateFromInt32( aData.nCol2 ); + aRet += ';'; + aRet += '"'; + aRet += aData.aMsg; + aRet += '"'; + return aRet; +} + +String MsgEdit::Impl_MakeSaveText( SvLBoxEntry *pEntry ) const +{ +// LogType;Filename;Line;Col1;Col2;Message + String aRet; + TTDebugData *aData = (TTDebugData*)pEntry->GetUserData(); + + if ( aEditTree.PrevSibling( pEntry ) && LOGTYPE( aEditTree.PrevSibling( pEntry ) ) == LOG_TEST_CASE ) + { // To properly finish cases and warnings/msgs are in correct hierarchie + aRet += String::CreateFromInt32( (int)LOG_TEST_CASE ); + aRet.AppendAscii(";;0;0;0;\"\"\n"); + } + aRet += Impl_MakeSaveText( *aData ); + return aRet; +} + +String MsgEdit::GetSelected() +{ + String aRet; + SvLBoxEntry *pEntry = aEditTree.FirstSelected(); + while ( pEntry ) + { + aRet += Impl_MakeText( pEntry ); + aRet += '\n'; + pEntry = aEditTree.NextSelected( pEntry ); + } + aRet.ConvertLineEnd(); + return aRet; +} + +TextSelection MsgEdit::GetSelection() const +{ + ULONG nStart=0,nEnd=0; + + if ( aEditTree.FirstSelected() ) + { + nStart = aEditTree.GetModel()->GetAbsPos(aEditTree.FirstSelected() ); + if ( aEditTree.LastSelected() ) + nEnd = aEditTree.GetModel()->GetAbsPos(aEditTree.LastSelected() ); + return TextSelection( TextPaM( nStart, 0 ), TextPaM( nEnd, STRING_MAXLEN ) ); + } + else + return TextSelection(); +} + +void MsgEdit::SetSelection( const TextSelection& rSelection ) +{ + ULONG nStart,nEnd; + + while ( aEditTree.GetSelectionCount() ) + aEditTree.Select( aEditTree.FirstSelected(), FALSE ); + + if ( rSelection.HasRange() ) + { + nStart = rSelection.GetStart().GetPara(); + nEnd = rSelection.GetEnd().GetPara(); + + for ( ULONG i = nStart ; i <= nEnd ; i++ ) + aEditTree.Select( aEditTree.GetModel()->GetEntryAtAbsPos( i ), TRUE ); + } +} + +USHORT MsgEdit::GetLineNr() const +{ + if ( aEditTree.GetCurEntry() ) + return (USHORT)aEditTree.GetModel()->GetAbsPos(aEditTree.GetCurEntry() ) + 1; + else + return 0; +} + +void MsgEdit::ReplaceSelected( const String& rStr ) +{ + (void) rStr; /* avoid warning about unused parameter */ + Sound::Beep(); + DBG_ERROR("Not Implemented"); +} + +BOOL MsgEdit::IsModified(){ return bModified; } +void MsgEdit::SetModifyHdl( Link l ){ lModify = l; } + +String MsgEdit::GetText() const +{ + String aRet; + SvLBoxEntry *pEntry = aEditTree.First(); + while ( pEntry ) + { + aRet += Impl_MakeText( pEntry ); + aRet += '\n'; + pEntry = aEditTree.Next( pEntry ); + } + aRet.ConvertLineEnd(); + return aRet; +} + +void MsgEdit::SetText( const String& rStr ) +{ + (void) rStr; /* avoid warning about unused parameter */ + Sound::Beep(); + DBG_ERROR("Not Implemented"); +} + +BOOL MsgEdit::HasText() const +{ + return aEditTree.First() != NULL; +} + +// Search from the beginning or mark start + 1 +BOOL MsgEdit::Find( const String& s ) +{ + TextSelection r = GetSelection(); + USHORT bgn = (USHORT) r.GetStart().GetPara() + 1; + if ( r.GetStart().GetPara() == 0 ) + bgn = 0; // Search from the beginning + + SvLBoxEntry *pEntry = aEditTree.GetModel()->GetEntryAtAbsPos( bgn ); + while ( pEntry ) + { + if( aEditTree.GetEntryText( pEntry ).Search( s, 0 ) != STRING_NOTFOUND ) + { + aEditTree.SetCurEntry( pEntry ); + return TRUE; + } + pEntry = aEditTree.Next( pEntry ); + } + return FALSE; +} + +/****************************************************************** + + Fileformat of *.res file: + Information are stored as semicolon separated strings + Order: + + LogType;Filename;Line;Col1;Col2;Message + +******************************************************************/ + +BOOL MsgEdit::Load( const String& aName ) +{ + aLogFileName = aName; + BOOL bOk = TRUE, bFirstLine = TRUE; + BOOL bLoadError = FALSE; + SvFileStream aStrm( aName, STREAM_STD_READ ); + if( aStrm.IsOpen() ) + { + aEditTree.Clear(); + String aLine; + bFileLoading = TRUE; // To avoid logging to disk + TTLogMsg *pLogMsg = new TTLogMsg; + while( !aStrm.IsEof() && bOk ) + { + if ( nVersion >= 3 ) // utf8 + aStrm.ReadByteStringLine( aLine, RTL_TEXTENCODING_UTF8 ); + else + aStrm.ReadByteStringLine( aLine, RTL_TEXTENCODING_IBM_850 ); + + if( aStrm.GetError() != SVSTREAM_OK ) + bOk = FALSE; + +#define TOKEN( n ) aLine.GetToken( n ) + + if ( aLine.GetTokenCount() >= 6 ) + { +// LogType;Filename;Line;Col1;Col2;Message + TTDebugData aDebugData; + aDebugData.aLogType = TTLogType( TOKEN(0).ToInt32() ); + aDebugData.aFilename = TOKEN(1); + aDebugData.nLine = USHORT( TOKEN(2).ToInt32() ); + aDebugData.nCol1 = USHORT( TOKEN(3).ToInt32() ); + aDebugData.nCol2 = USHORT( TOKEN(4).ToInt32() ); + aDebugData.aMsg = aLine.GetQuotedToken( 5, CUniString("\"\"") ); + + // Remove leading and trailing quotes + aDebugData.aMsg.Erase(0,1); + aDebugData.aMsg.Erase(aDebugData.aMsg.Len()-1,1); + + pLogMsg->aLogFileName.Erase(); + pLogMsg->aDebugData = aDebugData; + + AddAnyMsg( pLogMsg ); + } + else if ( bFirstLine && (aLine.Search( VERSION_STRING ) == 0) ) + nVersion = USHORT( aLine.Copy( VERSION_STRING.Len() ).ToInt32() ); + else if ( aLine.Len() ) + bLoadError = TRUE; + + bFirstLine = FALSE; + } + bFileLoading = FALSE; + delete pLogMsg; + aStrm.Close(); + if ( nVersion < 2 && !bLoadError ) + Save( aName ); // Necessary to avoid mess + + } + else + bOk = FALSE; + return bOk; +} + +BOOL MsgEdit::Save( const String& aName ) +{ + BOOL bOk = TRUE; + BOOL bIsText = DirEntry( aName ).GetExtension().CompareIgnoreCaseToAscii("TXT") == COMPARE_EQUAL; + if ( bIsText && !QueryBox( NULL, SttResId( IDS_LOSS_OF_INFORMATION ) ).Execute() ) + return FALSE; + SvFileStream aStrm( aName, STREAM_STD_WRITE | STREAM_TRUNC ); + if( aStrm.IsOpen() ) + { + if ( bIsText ) + { + String aSave = GetText(); + aSave.ConvertLineEnd(LINEEND_CRLF); + aStrm << ByteString( aSave, RTL_TEXTENCODING_UTF8 ).GetBuffer(); + } + else + { +// LogType;Filename;Line;Col1;Col2;Message + String aSave = VERSION_STRING.Append( UniString::CreateFromInt32( 3 ) ).AppendAscii("\n"); // Version 3 + SvLBoxEntry *pRun = aEditTree.First(); + while ( pRun && aEditTree.NextSibling( pRun ) ) + pRun = aEditTree.NextSibling( pRun ); + + aSave.ConvertLineEnd(LINEEND_CRLF); + aStrm << ByteString( aSave, RTL_TEXTENCODING_IBM_850 ).GetBuffer(); + + SvLBoxEntry *pEntry; + while ( pRun ) + { + pEntry = pRun; + while ( pEntry && ( pEntry == pRun || LOGTYPE( pEntry ) != LOG_RUN ) ) + { + aSave = Impl_MakeSaveText( pEntry ); + aSave += '\n'; + aSave.ConvertLineEnd(LINEEND_CRLF); + aStrm << ByteString( aSave, RTL_TEXTENCODING_UTF8 ).GetBuffer(); + pEntry = aEditTree.Next( pEntry ); + } + pRun = aEditTree.PrevSibling( pRun ); + + } + } + if( aStrm.GetError() != SVSTREAM_OK ) + bOk = FALSE; + else + { + bModified = FALSE; + lModify.Call( NULL ); + } + + } + else + bOk = FALSE; + return bOk; +} + + +TTTreeListBox::TTTreeListBox( AppError* pParent, BasicFrame* pBF, WinBits nWinStyle ) +: SvTreeListBox( pParent, nWinStyle ) +, pBasicFrame(pBF) +, pAppError( pParent ) +//, nDeselectParent(0) +{} + +BOOL TTTreeListBox::JumpToSourcecode( SvLBoxEntry *pThisEntry ) +{ + if ( pThisEntry && pThisEntry->GetUserData() && ((TTDebugData*)pThisEntry->GetUserData())->aFilename.Len() > 0 ) + { + TTDebugData *aData = (TTDebugData*)pThisEntry->GetUserData(); + String aFilename = aData->aFilename; + if ( aData->aFilename.GetChar(0) == '~' ) + { + if ( aData->aFilename.GetChar(1) == '-' ) + { + aFilename.Erase( 0,2 ); + } + else + { + aFilename.Erase( 0,1 ); + DirEntry aConvert( pAppError->aBaseDir ); + aConvert += DirEntry( aFilename, FSYS_STYLE_VFAT ); + aFilename = aConvert.GetFull(); + } + } + + if ( pBasicFrame->FindModuleWin( aFilename ) ) + { + AppWin *pWin = pBasicFrame->FindModuleWin( aFilename ); + pWin->ToTop(); + } + else if ( pBasicFrame->Basic().FindModule( CUniString( "--" ).Append( aFilename ) ) ) + { + SbModule* pMod = pBasicFrame->Basic().FindModule( CUniString( "--" ).Append( aFilename ) ); + pBasicFrame->CreateModuleWin( pMod ); + } + else + pBasicFrame->LoadFile( aFilename ); + + if ( pBasicFrame->pWork && pBasicFrame->pWork->ISA(AppEdit) ) + ((AppEdit*)pBasicFrame->pWork)->Highlight( aData->nLine, aData->nCol1, aData->nCol2 ); + return FALSE; + } + return TRUE; +} + +BOOL TTTreeListBox::DoubleClickHdl() +{ + return JumpToSourcecode( GetHdlEntry() ); +} + +/*ULONG TTTreeListBox::SelectChildren( SvLBoxEntry* pParent, BOOL bSelect ) +{ + SvLBoxEntry *pEntry = FirstChild( pParent ); + ULONG nRet = 0; + while ( pEntry ) + { + nRet++; + Select( pEntry, bSelect ); + pEntry = NextSibling( pEntry ); + } + return nRet; +} + + +void TTTreeListBox::SelectHdl() +{ + SvLBoxEntry* pHdlEntry = GetHdlEntry(); + + SelectChildren( pHdlEntry, TRUE ); + Select( pHdlEntry, TRUE ); +// InitMenu(pApp->GetAppMenu()->GetPopupMenu( RID_APPEDIT )); // So daß Delete richtig ist +} + +void TTTreeListBox::DeselectHdl() +{ + SvLBoxEntry* pHdlEntry = GetHdlEntry(); + if ( GetParent( pHdlEntry ) ) + { + nDeselectParent++; + Select( GetParent( pHdlEntry ), FALSE ); + nDeselectParent--; + } + if ( !nDeselectParent ) + { + SelectChildren( pHdlEntry, FALSE ); + Select( pHdlEntry, FALSE ); + } + Invalidate(); +} */ + + +void TTTreeListBox::KeyInput( const KeyEvent& rKEvt ) +{ + switch ( rKEvt.GetKeyCode().GetFunction() ) + { + case KEYFUNC_CUT: + Control::GetParent()->Command( CommandEvent( Point(), RID_EDITCUT ) ); + break; + case KEYFUNC_COPY: + Control::GetParent()->Command( CommandEvent( Point(), RID_EDITCOPY ) ); + break; + case KEYFUNC_PASTE: + Control::GetParent()->Command( CommandEvent( Point(), RID_EDITPASTE ) ); + break; + case KEYFUNC_DELETE: + Control::GetParent()->Command( CommandEvent( Point(), RID_EDITDEL ) ); + break; + default: + if ( rKEvt.GetKeyCode().GetCode() == KEY_RETURN ) + JumpToSourcecode( GetCurEntry() ); + else + SvTreeListBox::KeyInput( rKEvt ); + } +} + + +TTFeatures TTTreeListBox::GetFeatures( SvLBoxEntry* pEntry ) +{ + switch ( LOGTYPE( pEntry ) ) + { + case LOG_MESSAGE: + return HasNothing; + case LOG_WARNING : + return HasWarning; + case LOG_ERROR: + case LOG_CALL_STACK: + return HasError; + case LOG_RUN: + case LOG_TEST_CASE: + { + SvLBoxEntry* pThisEntry = FirstChild( pEntry ); + TTFeatures aResult = HasNothing; + while ( pThisEntry && !( (aResult & HasError) == HasError ) ) + { + if ( !IsEntryVisible( pThisEntry ) ) + aResult |= GetFeatures( pThisEntry ); + pThisEntry = NextSibling( pThisEntry ); + } + return aResult; + } + case LOG_ASSERTION: + case LOG_ASSERTION_STACK: + return HasAssertion; + case LOG_QA_ERROR: + return HasQAError; + default: + DBG_ERROR("Unknown type in ResultWindow"); + } + return HasNothing; +} + + +class TTLBoxString : public SvLBoxString +{ +public: + + TTLBoxString( SvLBoxEntry* pEntry, USHORT nFlags, + const String& rStr ) : SvLBoxString(pEntry,nFlags,rStr) {} + + virtual void Paint( const Point& rPos, SvLBox& rDev, USHORT nFlags, + SvLBoxEntry* pEntry); +}; + + +void TTLBoxString::Paint( const Point& rPos, SvLBox& rDev, USHORT nFlags, + SvLBoxEntry* pEntry ) +{ + TTFeatures aFeatures = ((TTTreeListBox*)&rDev)->GetFeatures( pEntry ); + + Font aOldFont( rDev.GetFont()); + Font aFont( aOldFont ); + if ( aFeatures != HasNothing ) + { + Color aCol; + if ( ( aFeatures & HasError ) == HasError ) + aCol = Color( 255, 130, 130 ); // Red + else if ( ( aFeatures & HasWarning ) == HasWarning ) + aCol = Color( 255, 200, 120 ); // Ocker oder so + else if ( ( aFeatures & HasAssertion ) == HasAssertion ) + aCol = Color( 0xd0, 0xd0, 0xff ); // blueish + else + aCol = Color( 0xd0, 0xff, 0xd0 ); // greenish + + if( rDev.IsSelected(pEntry) ) + aFont.SetColor( aCol ); + else + { + aFont.SetFillColor( aCol ); + aFont.SetTransparent( FALSE ); + Color aCol2( COL_BLACK ); + aFont.SetColor( aCol2 ); + } + + rDev.SetFont( aFont ); + rDev.DrawText( rPos, GetText() ); + } + else + { + if( !rDev.IsSelected(pEntry) ) + { + Color aCol( COL_BLACK ); + aFont.SetColor( aCol ); + } + rDev.SetFont( aFont ); + SvLBoxString::Paint( rPos, rDev, nFlags, pEntry ); + } + rDev.SetFont( aOldFont ); +} + + +void TTTreeListBox::InitEntry(SvLBoxEntry* pEntry, + const String& rStr ,const Image& rImg1, const Image& rImg2, + SvLBoxButtonKind eButtonKind ) +{ + USHORT nColToHilite = 1; //0==Bitmap;1=="Column1";2=="Column2" + SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2, eButtonKind ); + SvLBoxString* pCol = (SvLBoxString*)pEntry->GetItem( nColToHilite ); + TTLBoxString* pStr = new TTLBoxString( pEntry, 0, pCol->GetText() ); + pEntry->ReplaceItem( pStr, nColToHilite ); +} + diff --git a/basic/source/app/msgedit.hxx b/basic/source/app/msgedit.hxx new file mode 100644 index 000000000000..21af563834c0 --- /dev/null +++ b/basic/source/app/msgedit.hxx @@ -0,0 +1,117 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: msgedit.hxx,v $ + * $Revision: 1.11.40.1 $ + * + * 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 _MSGEDIT_HXX +#define _MSGEDIT_HXX + +#include <svtools/svtreebx.hxx> +#include <basic/testtool.hxx> +#include "dataedit.hxx" + +class BasicFrame; +class AppError; + +#define SelectChildren SelectChilds // Sonst wird mir schlecht + +typedef USHORT TTFeatures; // Bitfield for features of the entries +#define HasNothing TTFeatures(0x00) +#define HasError TTFeatures(0x01) +#define HasWarning TTFeatures(0x02) +#define HasAssertion TTFeatures(0x04) +#define HasQAError TTFeatures(0x08) + + +class TTTreeListBox : public SvTreeListBox +{ +protected: +// virtual void Command( const CommandEvent& rCEvt ); +// USHORT nDeselectParent; + BasicFrame *pBasicFrame; + void InitEntry( SvLBoxEntry*, const String&, const Image&, + const Image&, SvLBoxButtonKind eButtonKind ); + AppError *pAppError; + + BOOL JumpToSourcecode( SvLBoxEntry *pThisEntry ); + +public: + TTTreeListBox( AppError* pParent, BasicFrame* pBF, WinBits nWinStyle=0 ); + ~TTTreeListBox(){} + +// virtual void SelectHdl(); +// virtual void DeselectHdl(); + virtual BOOL DoubleClickHdl(); + + virtual void KeyInput( const KeyEvent& rKEvt ); + +// ULONG SelectChildren( SvLBoxEntry* pParent, BOOL bSelect ); + TTFeatures GetFeatures( SvLBoxEntry* ); +}; + +class MsgEdit : public DataEdit +{ + BasicFrame *pBasicFrame; + + SvLBoxEntry *pCurrentRun; + SvLBoxEntry *pCurrentTestCase; + SvLBoxEntry *pCurrentAssertion; + SvLBoxEntry *pCurrentError; + BOOL bModified; + Link lModify; + BOOL bFileLoading; // TRUE while loading a file + String Impl_MakeText( SvLBoxEntry *pEntry ) const; + String Impl_MakeSaveText( SvLBoxEntry *pEntry ) const; + String Impl_MakeSaveText( TTDebugData aData ) const; + USHORT nVersion; // Stores file version + AppError* pAppError; + String aLogFileName; + + static USHORT nMaxLogLen; + static BOOL bLimitLogLen; + static BOOL bPrintLogToStdout; + static BOOL bPrintLogToStdoutSet; // has it been initialized yet +public: + MsgEdit( AppError*, BasicFrame *pBF, const WinBits& ); + ~MsgEdit(); + void AddAnyMsg( TTLogMsg *LogMsg ); + void AddRun( String aMsg, TTDebugData aDebugData ); + void AddTestCase( String aMsg, TTDebugData aDebugData ); + void AddError( String aMsg, TTDebugData aDebugData ); + void AddCallStack( String aMsg, TTDebugData aDebugData ); + void AddMessage( String aMsg, TTDebugData aDebugData ); + void AddWarning( String aMsg, TTDebugData aDebugData ); + void AddAssertion( String aMsg, TTDebugData aDebugData ); + void AddAssertionStack( String aMsg, TTDebugData aDebugData ); + void AddQAError( String aMsg, TTDebugData aDebugData ); + + static void SetMaxLogLen( USHORT nLen ) { nMaxLogLen = nLen; bLimitLogLen = TRUE; } +DATA_FUNC_DEF( aEditTree, TTTreeListBox ) +}; + +#endif diff --git a/basic/source/app/mybasic.cxx b/basic/source/app/mybasic.cxx new file mode 100644 index 000000000000..4ec6cc6b86e6 --- /dev/null +++ b/basic/source/app/mybasic.cxx @@ -0,0 +1,307 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: mybasic.cxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <basic/sbx.hxx> + +// AB-Uno-Test +//#define unotest +#ifdef unotest +#ifndef _USR_UNO_HXX +#include <usr/uno.hxx> +#endif +#include <basic/sbuno.hxx> +#include <sbunoobj.hxx> +#endif + +#include "sbintern.hxx" + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif +#include <basic/mybasic.hxx> +#include "basic.hrc" +#include "appbased.hxx" + +#include "status.hxx" +#include "basic.hrc" + +#include "object.hxx" + +#include "processw.hxx" +#include "basrid.hxx" + +TYPEINIT1(MyBasic,StarBASIC) + +class MyFactory : public SbxFactory +{ +public: + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); +}; + +static SampleObjectFac aFac1; +static MyFactory aFac2; +static ProcessFactory aProcessFac; +static short nInst = 0; + +SbxBase* MyFactory::Create( UINT16 nSbxId, UINT32 nCr ) +{ + if( nCr == SBXCR_TEST && nSbxId == SBXID_MYBASIC ) + return new MyBasic; + else + return NULL; +} + +MyBasic::MyBasic() : StarBASIC() +{ + nError = 0; + if( !nInst++ ) + { + AddFactory( &aFac1 ); + AddFactory( &aFac2 ); + AddFactory( &aProcessFac ); + } + SbxVariable* p = new SbxCollection( CUniString("MyColl") ); + p->SetName( CUniString("Objects") ); + Insert( p ); + + // AB-Uno-Test +#ifdef unotest + // Get Uno-Service-Manager and Reflection Service + createAndSetDefaultServiceManager(); // done later + + // Get Uno-Test-Object + UsrAny aObjAny = getIntrospectionTestObject(); + + // Box object into SbUnoObject + String aName( "UnoObject" ); + SbxObjectRef xSbUnoObj = GetSbUnoObject( aName, aObjAny ); + //SbxObjectRef xSbUnoObj = new SbUnoObject( aName, aObjAny ); + Insert( (SbxObject*)xSbUnoObj ); +#endif + + pTestObject = NULL; +} + +Link MyBasic::GenLogHdl() +{ + return LINK( GetpApp()->GetAppWindow(), BasicFrame, Log ); +} + +Link MyBasic::GenWinInfoHdl() +{ + return LINK( GetpApp()->GetAppWindow(), BasicFrame, WinInfo ); +} + +Link MyBasic::GenModuleWinExistsHdl() +{ + return LINK( GetpApp()->GetAppWindow(), BasicFrame, ModuleWinExists ); +} + +Link MyBasic::GenWriteStringHdl() +{ + return LINK( GetpApp()->GetAppWindow(), BasicFrame, WriteString ); +} + +void MyBasic::StartListeningTT( SfxBroadcaster &rBroadcaster ) +{ + ((BasicFrame*)GetpApp()->GetAppWindow())->StartListening( rBroadcaster ); +} + +void MyBasic::SetCompileModule( SbModule *pMod ) +{ + GetSbData()->pCompMod = pMod; +} + +SbModule *MyBasic::GetCompileModule() +{ + return GetSbData()->pCompMod; +} + +String MyBasic::GenRealString( const String &aResString ) +{ + return ((BasicFrame*)GetpApp()->GetAppWindow())->GenRealString( aResString ); +} + +void MyBasic::LoadIniFile() +{ +} + +SbTextType MyBasic::GetSymbolType( const String &rSymbol, BOOL bWasTTControl ) +{ + (void) rSymbol; /* avoid warning about unused parameter */ + (void) bWasTTControl; /* avoid warning about unused parameter */ + return SB_SYMBOL; // Everything here is of type SB_SYMBOL and continues to be so +} + + +MyBasic::~MyBasic() +{ + aErrors.Clear(); + if( !--nInst ) + { + RemoveFactory( &aFac1 ); + RemoveFactory( &aFac2 ); + RemoveFactory( &aProcessFac ); + } +} + +void MyBasic::Reset() +{ + aErrors.Clear(); + nError = 0; +} + +BOOL MyBasic::Compile( SbModule* p ) +{ + Reset(); + return StarBASIC::Compile( p ); +} + +BOOL MyBasic::ErrorHdl() +{ + AppBasEd* pWin = aBasicApp.pFrame->FindModuleWin( GetActiveModule()->GetName() ); + if( !pWin ) + { // open a window + pWin = aBasicApp.pFrame->CreateModuleWin( GetActiveModule() ); + } + else + pWin->ToTop(); + if( IsCompilerError() ) + { + aErrors.Insert( + new BasicError + ( pWin, + 0, StarBASIC::GetErrorText(), GetLine(), GetCol1(), GetCol2() ), + LIST_APPEND ); + nError++; + return BOOL( nError < 20 ); // Cancel after 20 errors + } + else + { + ReportRuntimeError( pWin ); + return FALSE; + } +} + +void MyBasic::ReportRuntimeError( AppBasEd *pEditWin ) +{ + String nErrorText; + nErrorText = GetSpechialErrorText(); + + if ( pEditWin ) // just in case the focus is not right + pEditWin->ToTop(); + + BasicError( pEditWin, + GetVBErrorCode( GetErrorCode() ), nErrorText, GetLine(), + GetCol1(), GetCol2() ).Show(); +} + +void MyBasic::DebugFindNoErrors( BOOL bDebugFindNoErrors ) +{ + (void) bDebugFindNoErrors; /* avoid warning about unused parameter */ +} + +const String MyBasic::GetSpechialErrorText() +{ + return GetErrorText(); +} + +USHORT MyBasic::BreakHdl() +{ + SbModule* pMod = GetActiveModule(); + if( pMod ) + { + AppBasEd* pWin = aBasicApp.pFrame->FindModuleWin( pMod->GetName() ); + if( !pWin ) + { // open a window + pWin = aBasicApp.pFrame->CreateModuleWin( pMod ); + } + else + pWin->ToTop(); + pWin->Highlight( GetLine(), GetCol1(), GetCol2() ); + } + + if( IsBreak() ) // If Breakpoint (or "Run to Cursor") + { +// if ( GetActiveModule()->IsBP(GetLine()) ) +// GetActiveModule()->ClearBP(GetLine()); + return aBasicApp.pFrame->BreakHandler(); + } + else + { + return aBasicApp.pFrame->BreakHandler(); + } +} + +/*************************************************************************** +|* +|* class BasicError +|* +***************************************************************************/ + +BasicError::BasicError + ( AppBasEd* w, USHORT nE, const String& r, USHORT nL, USHORT nC1, USHORT nC2 ) + : aText( SttResId( IDS_ERROR1 ) ) +{ + pWin = w; + nLine = nL; + nCol1 = nC1; + nCol2 = nC2; + if( nE ) + { + aText += String::CreateFromInt32( nE ); + aText.AppendAscii(": "); + aText += r; + } + else + aText = r; +} + +// This is a sample how to build the error information +// to highlight a statement +void BasicError::Show() +{ + if( pWin && aBasicApp.pFrame->IsWinValid( pWin ) ) + { + pWin->Highlight( nLine, nCol1, nCol2 ); + aBasicApp.pFrame->pStatus->Message( aText ); + } + else + MessBox( aBasicApp.pFrame, WB_OK, aBasicApp.pFrame->GetText(), + aText ).Execute(); +} + + diff --git a/basic/source/app/printer.cxx b/basic/source/app/printer.cxx new file mode 100644 index 000000000000..6f173fd53ffa --- /dev/null +++ b/basic/source/app/printer.cxx @@ -0,0 +1,197 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: printer.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#ifndef _PRINT_HXX //autogen +#include <vcl/print.hxx> +#endif +#ifndef _DIALOG_HXX //autogen +#include <vcl/dialog.hxx> +#endif +#ifndef _FIXED_HXX //autogen +#include <vcl/fixed.hxx> +#endif +#ifndef _BUTTON_HXX //autogen +#include <vcl/button.hxx> +#endif +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +#include <algorithm> + +#include "app.hxx" +#include "printer.hxx" +#include "basic.hrc" +#include "resids.hrc" +#include "basrid.hxx" + +class PrintingDialog : public ModelessDialog { + String aName; + FixedText aText; + CancelButton aCancel; +public: + PrintingDialog( Window*, BasicPrinter*, ResId&, String& ); + void ChangeMessage( short ); +}; + +BasicPrinter::BasicPrinter() : Printer() +{ + nPage = 0; nLine = 9999; + SetMapMode( MapMode( MAP_POINT ) ); + Size s( GetOutputSize() ); + // Use 10 point font + Font aFont( FAMILY_MODERN, Size( 0, 10 ) ); + aFont.SetPitch( PITCH_FIXED ); + SetFont( aFont ); + // Output: 6 Lines/Inch = 12 Point + nLines = (short) s.Height() / 12; + nYoff = 12; + SetStartPrintHdl( LINK( this, BasicPrinter, StartPrintHdl ) ); + SetEndPrintHdl( LINK( this, BasicPrinter, EndPrintHdl ) ); + SetPrintPageHdl( LINK( this, BasicPrinter, PrintPageHdl ) ); +} + +void BasicPrinter::Header() +{ + if( nPage ) EndPage(); + nPage++; + StartPage(); + String aHdr; + String aPage( SttResId( IDS_PAGE ) ); + aPage.Append( String::CreateFromInt32(nPage) ); + aHdr = aFile.Copy( 0, 80 - aPage.Len() ); + aHdr.Expand( 80 - aPage.Len(), ' ' ); + aHdr += aPage; + DrawText( Point( 0, 0 ), aHdr ); + nLine = 2; +} + +void BasicPrinter::Print( const String& rFile, const String& rText, BasicFrame *pFrame ) +{ + nPage = 0; nLine = 9999; + aFile = rFile; + // Setup dialog + SttResId aResId( IDD_PRINT_DIALOG ); + pDlg = new PrintingDialog + ( aBasicApp.pFrame, this, aResId, aFile ); + // Set position of dialog + Size s1 = aBasicApp.pFrame->GetSizePixel(); + Size s2 = pDlg->GetSizePixel(); + pDlg->SetPosPixel( Point( (s1.Width() - s2.Width() ) / 2, + (s1.Height()- s2.Height() ) / 2 ) ); + // Disable PRINT-Menu + MenuBar* pBar = pFrame->GetMenuBar(); + Menu* pFileMenu = pBar->GetPopupMenu( RID_APPFILE ); + pFileMenu->EnableItem( RID_FILEPRINT, FALSE ); + + pDlg->ChangeMessage( 1 ); + pDlg->Show(); + StartJob( rFile ); + StartPage(); + xub_StrLen nDone=0; + while( nDone < rText.Len() ) + { + if( nLine >= nLines ) Header(); + xub_StrLen nLineEnd = std::min( rText.Search( '\n', nDone ), rText.Search( '\r', nDone ) ); + DrawText( Point( 0, nLine * nYoff ), rText, nDone, nLineEnd-nDone-1 ); + nDone = nLineEnd; + if( nDone <= rText.Len() && rText.GetChar(nDone) == '\r' ) nDone++; + if( nDone <= rText.Len() && rText.GetChar(nDone) == '\n' ) nDone++; + nLine++; + Application::Reschedule(); + } + EndPage(); + EndJob(); + nPage = 1; + while( IsPrinting() ) Application::Reschedule(); + delete pDlg; pDlg = NULL; + pFileMenu->EnableItem( RID_FILEPRINT, TRUE ); +} + +IMPL_LINK_INLINE_START( BasicPrinter, StartPrintHdl, Printer *, pPrinter ) +{ + (void) pPrinter; /* avoid warning about unused parameter */ + if( pDlg != NULL ) + pDlg->Show(); + return 0; +} +IMPL_LINK_INLINE_END( BasicPrinter, StartPrintHdl, Printer *, pPrinter ) + +IMPL_LINK_INLINE_START( BasicPrinter, EndPrintHdl, Printer *, pPrinter ) +{ + (void) pPrinter; /* avoid warning about unused parameter */ + if( pDlg != NULL) + pDlg->Hide(); + return 0; +} +IMPL_LINK_INLINE_END( BasicPrinter, EndPrintHdl, Printer *, pPrinter ) + +IMPL_LINK_INLINE_START( BasicPrinter, PrintPageHdl, Printer *, pPrinter ) +{ + (void) pPrinter; /* avoid warning about unused parameter */ + if( pDlg != NULL) + pDlg->ChangeMessage( nPage ); + return 0; +} +IMPL_LINK_INLINE_END( BasicPrinter, PrintPageHdl, Printer *, pPrinter ) + +IMPL_LINK_INLINE( BasicPrinter, Abort , void *, EMPTYARG, +{ + AbortJob(); + return 0L; +} +) + +///////////////////////////////////////////////////////////////////////// + +PrintingDialog::PrintingDialog + ( Window* pParent, BasicPrinter* pPrn, ResId& rId, String& rName ) +: ModelessDialog( pParent, rId ) +, aName ( rName ) +, aText ( this, ResId( RID_TEXT, *rId.GetResMgr() ) ) +, aCancel( this, ResId( RID_CANCEL, *rId.GetResMgr() ) ) +{ + FreeResource(); + aCancel.SetClickHdl( LINK( pPrn, BasicPrinter, Abort ) ); +} + +void PrintingDialog::ChangeMessage( short nPage ) +{ + String aMsg( SttResId( IDS_PRINTMSG ) ); + aMsg += aName; + aMsg += CUniString("\n"); + aMsg += String( SttResId( IDS_PAGE ) ); + aMsg += String::CreateFromInt32( nPage ); + aText.SetText( aMsg ); +} + diff --git a/basic/source/app/printer.hxx b/basic/source/app/printer.hxx new file mode 100644 index 000000000000..d6db8154c57f --- /dev/null +++ b/basic/source/app/printer.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: printer.hxx,v $ + * $Revision: 1.3 $ + * + * 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 _BASICPRN_HXX +#define _BASICPRN_HXX + +#ifndef _PRINT_HXX //autogen +#include <vcl/print.hxx> +#endif + +class PrintingDialog; + +class BasicPrinter : public Printer { + short nLine; // aktuelle Zeile + short nPage; // aktuelle Seite + short nLines; // Zeilen pro Seite + short nYoff; // Zeilenabstand in Points + String aFile; // Dateiname + PrintingDialog* pDlg; // Druck-Dialog + void Header(); // Seitenkopf drucken +public: + BasicPrinter(); + void Print( const String& rFile, const String& rText, BasicFrame *pFrame ); + DECL_LINK( Abort, void * ); + DECL_LINK( StartPrintHdl, Printer * ); + DECL_LINK( EndPrintHdl, Printer * ); + DECL_LINK( PrintPageHdl, Printer * ); +#if defined( PM20 ) + // StarView-Bug, bald wieder zu entfernen: + virtual void SetPageQueueSize( USHORT ) {} +#endif +}; + +#endif diff --git a/basic/source/app/process.cxx b/basic/source/app/process.cxx new file mode 100644 index 000000000000..aba775778337 --- /dev/null +++ b/basic/source/app/process.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: process.cxx,v $ + * $Revision: 1.16 $ + * + * 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" + + +#ifdef WNT +#include <tools/prewin.h> +#include "winbase.h" +#include <tools/postwin.h> +#endif +#include <tools/errcode.hxx> +#include <vos/process.hxx> +#include <basic/sbxcore.hxx> +#include <tools/string.hxx> +#include <osl/file.hxx> + +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +//#ifndef _BYTE_STRING_LIST +//DECLARE_LIST( ByteStringList, ByteString * ); +//#define _BYTE_STRING_LIST +//#endif + +#include <basic/process.hxx> + +Process::Process() +: pArgumentList( NULL ) +, pEnvList( NULL ) +, pProcess( NULL ) +, bWasGPF( FALSE ) +, bHasBeenStarted( FALSE ) +{ +} + +Process::~Process() +{ +// delete pArgumentList; +// delete pEnvList; + delete pProcess; +} + + +BOOL Process::ImplIsRunning() +{ + if ( pProcess && bHasBeenStarted ) + { + NAMESPACE_VOS(OProcess::TProcessInfo) aProcessInfo; + pProcess->getInfo( NAMESPACE_VOS(OProcess::TData_ExitCode), &aProcessInfo ); + if ( !(aProcessInfo.Fields & NAMESPACE_VOS(OProcess::TData_ExitCode)) ) + return TRUE; + else + return FALSE; + } + else + return FALSE; +} + +long Process::ImplGetExitCode() +{ + if ( pProcess ) + { + NAMESPACE_VOS(OProcess::TProcessInfo) aProcessInfo; + pProcess->getInfo( NAMESPACE_VOS(OProcess::TData_ExitCode), &aProcessInfo ); + if ( !(aProcessInfo.Fields & NAMESPACE_VOS(OProcess::TData_ExitCode)) ) + SbxBase::SetError( SbxERR_NO_ACTIVE_OBJECT ); + return aProcessInfo.Code; + } + else + SbxBase::SetError( SbxERR_NO_ACTIVE_OBJECT ); + return 0; +} + + +//////////////////////////////////////////////////////////////////////////// + +void Process::SetImage( const String &aAppPath, const String &aAppParams, const Environment *pEnv ) +{ // Set image file of executable + if ( pProcess && ImplIsRunning() ) + SbxBase::SetError( SbxERR_NO_ACTIVE_OBJECT ); + else + { + delete pArgumentList; pArgumentList = NULL; + delete pEnvList; pEnvList = NULL; + delete pProcess; pProcess = NULL; + + xub_StrLen i, nCount = aAppParams.GetQuotedTokenCount( CUniString("\"\"" ), ' ' ); + ::rtl::OUString *pParamList = new ::rtl::OUString[nCount]; + + xub_StrLen nParamCount = 0; + for ( i = 0 ; i < nCount ; i++ ) + { + ::rtl::OUString aTemp = ::rtl::OUString(aAppParams.GetQuotedToken( i, CUniString("\"\"''" ), ' ' )); + if ( aTemp.getLength() ) + { + pParamList[nParamCount] = aTemp; + nParamCount++; + } + } + pArgumentList = new NAMESPACE_VOS(OArgumentList)( pParamList, nCount ); + + + ::rtl::OUString *pEnvArray = NULL; + if ( pEnv ) + { + pEnvArray = new ::rtl::OUString[pEnv->size()]; + + xub_StrLen nEnvCount = 0; + Environment::const_iterator aIter = pEnv->begin(); + while ( aIter != pEnv->end() ) + { + ::rtl::OUString aTemp = ::rtl::OUString( (*aIter).first ); + aTemp += ::rtl::OUString::createFromAscii( "=" ); + aTemp += ::rtl::OUString( (*aIter).second ); + pEnvArray[nEnvCount] = aTemp; + nEnvCount++; + aIter++; + } + pEnvList = new NAMESPACE_VOS(OEnvironment)( pEnvArray, nEnvCount ); + } + + ::rtl::OUString aNormalizedAppPath; + osl::FileBase::getFileURLFromSystemPath( ::rtl::OUString(aAppPath), aNormalizedAppPath ); + pProcess = new NAMESPACE_VOS(OProcess)( aNormalizedAppPath ); + bHasBeenStarted = FALSE; + + delete [] pParamList; + delete [] pEnvArray; + } +} + +BOOL Process::Start() +{ // Start program + BOOL bSuccess=FALSE; + if ( pProcess && !ImplIsRunning() ) + { + bWasGPF = FALSE; +#ifdef WNT +// sal_uInt32 nErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_NOALIGNMENTFAULTEXCEPT | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + sal_uInt32 nErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX); + try + { +#endif + if ( pEnvList ) + { + bSuccess = pProcess->execute( (NAMESPACE_VOS(OProcess)::TProcessOption) + ( NAMESPACE_VOS(OProcess)::TOption_SearchPath + /*| NAMESPACE_VOS(OProcess)::TOption_Detached*/ + /*| NAMESPACE_VOS(OProcess)::TOption_Wait*/ ), + *pArgumentList, + *pEnvList ) == NAMESPACE_VOS(OProcess)::E_None; + } + else + { + bSuccess = pProcess->execute( (NAMESPACE_VOS(OProcess)::TProcessOption) + ( NAMESPACE_VOS(OProcess)::TOption_SearchPath + /*| NAMESPACE_VOS(OProcess)::TOption_Detached*/ + /*| NAMESPACE_VOS(OProcess)::TOption_Wait*/ ), + *pArgumentList ) == NAMESPACE_VOS(OProcess)::E_None; + } +#ifdef WNT + } + catch( ... ) + { + bWasGPF = TRUE; + // TODO: Output debug message !! + } + nErrorMode = SetErrorMode(nErrorMode); +#endif + bHasBeenStarted = bSuccess; + } + else + SbxBase::SetError( SbxERR_NO_ACTIVE_OBJECT ); + return bSuccess; +} + +ULONG Process::GetExitCode() +{ // ExitCode of program after execution + return ImplGetExitCode(); +} + +BOOL Process::IsRunning() +{ + return ImplIsRunning(); +} + +BOOL Process::WasGPF() +{ // Did the process fail? +#ifdef WNT + return ImplGetExitCode() == 3221225477; +#else + return bWasGPF; +#endif +} + +BOOL Process::Terminate() +{ + if ( ImplIsRunning() ) + return pProcess->terminate() == vos::OProcess::E_None; + return TRUE; +} + diff --git a/basic/source/app/processw.cxx b/basic/source/app/processw.cxx new file mode 100644 index 000000000000..8ace95008062 --- /dev/null +++ b/basic/source/app/processw.cxx @@ -0,0 +1,285 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: processw.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include <tools/errcode.hxx> +#include <basic/sbxobj.hxx> +#include <basic/sbx.hxx> +#ifndef __SBX_SBXVARIABLE_HXX //autogen +#include <basic/sbxvar.hxx> +#endif + +//#include <osl/thread.h> +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +#include "processw.hxx" + +// Process has the following elements: +// 1) Properties: +// none +// 2) Methods: +// SetImage( Filename ) +// BOOL Start +// USHORT GetExitCode +// BOOL IsRunning +// BOOL WasGPF + + +// This implementation is a sample for a table driven version that +// can contain lots of elements. The elements are taken into the object +// when they are needed. + +// The nArgs field of a table entry is scrambled as follows: +#define _ARGSMASK 0x00FF // Up to 255 arguments +#define _RWMASK 0x0F00 // Mask for R/W-Bits +#define _TYPEMASK 0xF000 // Mask for entry type + +#define _READ 0x0100 // can be read +#define _BWRITE 0x0200 // can be used as Lvaluen +#define _LVALUE _BWRITE +#define _READWRITE 0x0300 // can read and written +#define _OPT 0x0400 // TRUE: optional parameter +#define _METHOD 0x1000 // Mask-Bit for a method +#define _PROPERTY 0x2000 // Mask-Bit for a property +#define _COLL 0x4000 // Mask-Bit for a collection + +// Combination of the bits above: +#define _FUNCTION 0x1100 // Mask for a Function +#define _LFUNCTION 0x1300 // Mask for a Function, that can be uses as Lvalue +#define _ROPROP 0x2100 // Mask Read Only-Property +#define _WOPROP 0x2200 // Mask Write Only-Property +#define _RWPROP 0x2300 // Mask Read/Write-Property +#define _COLLPROP 0x4100 // Mask Read-Collection-Element + +#define COLLNAME "Elements" // Name of the collection, hard coded + + +ProcessWrapper::Methods ProcessWrapper::aProcessMethods[] = { +// Imagefile of the Executable +{ "SetImage", SbxEMPTY, &ProcessWrapper::PSetImage, 1 | _FUNCTION }, + // Two Named Parameter + { "Filename", SbxSTRING, NULL, 0 }, + { "Params", SbxSTRING, NULL, _OPT }, +// Program is started +{ "Start", SbxBOOL, &ProcessWrapper::PStart, 0 | _FUNCTION }, +// ExitCode of the program +{ "GetExitCode", SbxULONG, &ProcessWrapper::PGetExitCode, 0 | _FUNCTION }, +// Program is running +{ "IsRunning", SbxBOOL, &ProcessWrapper::PIsRunning, 0 | _FUNCTION }, +// Program has faulted with GPF etc. +{ "WasGPF", SbxBOOL, &ProcessWrapper::PWasGPF, 0 | _FUNCTION }, + +{ NULL, SbxNULL, NULL, -1 }}; // End of table + + +ProcessWrapper::ProcessWrapper() : SbxObject( CUniString("Process") ) +{ + pProcess = new Process(); + SetName( CUniString("Process") ); + pMethods = &aProcessMethods[0]; +} + +ProcessWrapper::~ProcessWrapper() +{ + delete pProcess; +} + +// Search for an element: +// Linear search through the method table until an appropriate one +// can be found. +// If the the method/property cannot be found, NULL is return +// without an error code, so that we can ask the whole +// chain of objects for the method/property. +SbxVariable* ProcessWrapper::Find( const String& rName, SbxClassType t ) +{ + // Is the element already available? + SbxVariable* pRes = SbxObject::Find( rName, t ); + if( !pRes && t != SbxCLASS_OBJECT ) + { + // otherwise search + Methods* p = pMethods; + short nIndex = 0; + BOOL bFound = FALSE; + while( p->nArgs != -1 ) + { + if( rName.EqualsIgnoreCaseAscii( p->pName ) ) + { + bFound = TRUE; break; + } + nIndex += ( p->nArgs & _ARGSMASK ) + 1; + p = pMethods + nIndex; + } + if( bFound ) + { + // isolate Args fields: + short nAccess = ( p->nArgs & _RWMASK ) >> 8; + short nType = ( p->nArgs & _TYPEMASK ); + String aMethodName( p->pName, RTL_TEXTENCODING_ASCII_US ); + SbxClassType eCT = SbxCLASS_OBJECT; + if( nType & _PROPERTY ) + eCT = SbxCLASS_PROPERTY; + else if( nType & _METHOD ) + eCT = SbxCLASS_METHOD; + pRes = Make( aMethodName, eCT, p->eType ); + // We set array index + 1 because there are other + // default properties that must be activated + pRes->SetUserData( nIndex + 1 ); + pRes->SetFlags( nAccess ); + } + } + return pRes; +} + +// Activation of an element or request for an info block +void ProcessWrapper::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCT, + const SfxHint& rHint, const TypeId& rHT ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pNotifyPar = pVar->GetParameters(); + USHORT nIndex = (USHORT) pVar->GetUserData(); + // No index: put through + if( nIndex ) + { + ULONG t = pHint->GetId(); + if( t == SBX_HINT_INFOWANTED ) + pVar->SetInfo( GetInfo( (short) pVar->GetUserData() ) ); + else + { + BOOL bWrite = FALSE; + if( t == SBX_HINT_DATACHANGED ) + bWrite = TRUE; + if( t == SBX_HINT_DATAWANTED || bWrite ) + { + // Parameter-Test for methods: + USHORT nPar = pMethods[ --nIndex ].nArgs & 0x00FF; + // Element 0 is the return value + if( ( !pNotifyPar && nPar ) + || ( pNotifyPar && pNotifyPar->Count() < nPar+1 ) ) + SetError( SbxERR_WRONG_ARGS ); + // ready for call + else + { + (this->*(pMethods[ nIndex ].pFunc))( pVar, pNotifyPar, bWrite ); + } + } + } + } + SbxObject::SFX_NOTIFY( rBC, rBCT, rHint, rHT ); + } +} + +// Building the info struct for single elements +SbxInfo* ProcessWrapper::GetInfo( short nIdx ) +{ + Methods* p = &pMethods[ nIdx ]; + // Wenn mal eine Hilfedatei zur Verfuegung steht: + // SbxInfo* pResultInfo = new SbxInfo( Hilfedateiname, p->nHelpId ); + SbxInfo* pResultInfo = new SbxInfo; + short nPar = p->nArgs & _ARGSMASK; + for( short i = 0; i < nPar; i++ ) + { + p++; + String aMethodName( p->pName, RTL_TEXTENCODING_ASCII_US ); + USHORT nInfoFlags = ( p->nArgs >> 8 ) & 0x03; + if( p->nArgs & _OPT ) + nInfoFlags |= SBX_OPTIONAL; + pResultInfo->AddParam( aMethodName, p->eType, nInfoFlags ); + } + return pResultInfo; +} + + +//////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////// + +// Properties and methods save the return value in argv[0] (Get, bPut = FALSE) +// and store the value from argv[0] (Put, bPut = TRUE) + +void ProcessWrapper::PSetImage( SbxVariable* pVar, SbxArray* pMethodePar, BOOL bWriteIt ) +{ // Imagefile of the executable + (void) pVar; /* avoid warning about unused parameter */ + (void) bWriteIt; /* avoid warning about unused parameter */ + if ( pMethodePar->Count() >= 2 ) + pProcess->SetImage(pMethodePar->Get( 1 )->GetString(), pMethodePar->Get( 2 )->GetString() ); + else + pProcess->SetImage(pMethodePar->Get( 1 )->GetString(), String() ); +} + +void ProcessWrapper::PStart( SbxVariable* pVar, SbxArray* pMethodePar, BOOL bWriteIt ) +{ // Program is started + (void) pMethodePar; /* avoid warning about unused parameter */ + (void) bWriteIt; /* avoid warning about unused parameter */ + pVar->PutBool( pProcess->Start() ); +} + +void ProcessWrapper::PGetExitCode( SbxVariable* pVar, SbxArray* pMethodePar, BOOL bWriteIt ) +{ // ExitCode of the program after it was finished + (void) pMethodePar; /* avoid warning about unused parameter */ + (void) bWriteIt; /* avoid warning about unused parameter */ + pVar->PutULong( pProcess->GetExitCode() ); +} + +void ProcessWrapper::PIsRunning( SbxVariable* pVar, SbxArray* pMethodePar, BOOL bWriteIt ) +{ // Program is still running + (void) pMethodePar; /* avoid warning about unused parameter */ + (void) bWriteIt; /* avoid warning about unused parameter */ + pVar->PutBool( pProcess->IsRunning() ); +} + +void ProcessWrapper::PWasGPF( SbxVariable* pVar, SbxArray* pMethodePar, BOOL bWriteIt ) +{ // Program faulted with GPF etc. + (void) pMethodePar; /* avoid warning about unused parameter */ + (void) bWriteIt; /* avoid warning about unused parameter */ + pVar->PutBool( pProcess->WasGPF() ); +} + + + + + + +// The factory creates our object +SbxObject* ProcessFactory::CreateObject( const String& rClass ) +{ + if( rClass.CompareIgnoreCaseToAscii( "Process" ) == COMPARE_EQUAL ) + return new ProcessWrapper(); + return NULL; +} + diff --git a/basic/source/app/processw.hxx b/basic/source/app/processw.hxx new file mode 100644 index 000000000000..0b46ecd2cf0f --- /dev/null +++ b/basic/source/app/processw.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: processw.hxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PROCESSW_HXX +#define _PROCESSW_HXX + +#include <basic/sbxfac.hxx> +#ifndef __SBX_SBXVARIABLE_HXX //autogen +#include <basic/sbxvar.hxx> +#endif +#include <basic/sbxobj.hxx> +#include <basic/process.hxx> + +class ProcessWrapper : public SbxObject +{ +using SbxVariable::GetInfo; +// Definition of a table entry. This is done here because +// through this methods and property can declared as private. +#if defined ( ICC ) || defined ( HPUX ) || defined ( C50 ) || defined ( C52 ) +public: +#endif + typedef void( ProcessWrapper::*pMeth ) + ( SbxVariable* pThis, SbxArray* pArgs, BOOL bWrite ); +#if defined ( ICC ) || defined ( HPUX ) +private: +#endif + + struct Methods { + const char* pName; // Name of the entry + SbxDataType eType; // Data type + pMeth pFunc; // Function Pointer + short nArgs; // Arguments and flags + }; + static Methods aProcessMethods[]; // Method table + Methods *pMethods; // Current method table + + void PSetImage( SbxVariable* pVar, SbxArray* pPar, BOOL bWrite ); + void PStart( SbxVariable* pVar, SbxArray* pPar, BOOL bWrite ); + void PGetExitCode( SbxVariable* pVar, SbxArray* pPar, BOOL bWrite ); + void PIsRunning( SbxVariable* pVar, SbxArray* pPar, BOOL bWrite ); + void PWasGPF( SbxVariable* pVar, SbxArray* pPar, BOOL bWrite ); + + // Internal members and methods + Process *pProcess; + + // Fill info block + SbxInfo* GetInfo( short nIdx ); + + // Broadcaster Notification + virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ); +public: + ProcessWrapper(); + ~ProcessWrapper(); + // Search for an element + virtual SbxVariable* Find( const String&, SbxClassType ); +}; + +// Factory +class ProcessFactory : public SbxFactory +{ +public: + virtual SbxObject* CreateObject( const String& ); +}; + +#endif diff --git a/basic/source/app/resids.hrc b/basic/source/app/resids.hrc new file mode 100644 index 000000000000..b0e48dc15b88 --- /dev/null +++ b/basic/source/app/resids.hrc @@ -0,0 +1,161 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: resids.hrc,v $ + * $Revision: 1.9 $ + * + * 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 _RESIDS_HRC +#define _RESIDS_HRC + +#define RID_OK 1 +#define RID_CANCEL 2 +#define RID_FILENAME 3 +#define RID_PATHNAME 4 +#define RID_FILELIST 5 +#define RID_DIRSLIST 6 +#define RID_FIND 7 +#define RID_REPLACE 8 +//#define RID_ICON 9 +//#define RID_EDITFIELD 10 +#define RID_TEXT 11 +//#define RID_FRAME1 12 +//#define RID_FRAME2 13 +#define RID_VERSIONSTRING 14 +#define RID_FIXEDTEXT1 15 +#define RID_FIXEDTEXT2 16 + + +// OptionsDialog +#define RES_TC_OPTIONS 20 + +// GenericOptions +#define RID_TP_GEN 30 +#define RID_FL_AREA 31 +#define RID_CB_AREA 32 +#define RID_PB_NEW_AREA 33 +#define RID_PD_DEL_AREA 34 +#define RID_FL_VALUE 35 +#define RID_CB_VALUE 36 +#define RID_PB_SELECT_FILE 37 +#define RID_PB_NEW_VALUE 38 +#define RID_PB_DEL_VALUE 39 + +// ProfileOptions +#define RID_TP_PRO 40 +#define RID_FL_PROFILE 41 +#define RID_CB_PROFILE 42 +#define RID_PB_NEW_PROFILE 43 +#define RID_PD_DEL_PROFILE 44 +#define FL_DIRECTORIES 45 +#define LOG_TEXT 46 +#define BASIS_TEXT 47 +#define HID_CHECK 48 +#define LOG_NAME 49 +#define BASIS_NAME 50 +#define HID_NAME 51 +#define LOG_SET 52 +#define BASIS_SET 53 +#define HID_SET 54 +#define CB_AUTORELOAD 55 +#define CB_AUTOSAVE 56 +#define CB_STOPONSYNTAXERRORS 57 + +// Crashreporter Options +#define RID_TP_CRA 50 +#define FL_CRASHREPORT 51 +#define CB_USEPROXY 52 +#define FT_CRHOST 53 +#define ED_CRHOST 54 +#define FT_CRPORT 55 +#define NF_CRPORT 56 +#define CB_ALLOWCONTACT 57 +#define FT_EMAIL 58 +#define ED_EMAIL 59 + +// MiscOptions +#define RID_TP_MIS 60 +#define FL_COMMUNICATION 61 +#define FT_HOST 62 +#define ED_HOST 63 +#define FT_TTPORT 64 +#define NF_TTPORT 65 +#define FT_UNOPORT 66 +#define NF_UNOPORT 67 +#define FL_OTHER 68 +#define TIMEOUT_TEXT 69 +#define SERVER_TIMEOUT 70 +#define FT_LRU 71 +#define TF_MAX_LRU 72 +#define FT_PROGDIR 73 +#define ED_PROGDIR 74 +#define PB_PROGDIR 75 + + +// Font Settings +#define RID_TP_FON 70 +#define FT_FONTNAME 71 +#define CB_FONTNAME 72 +#define FT_FONTSTYLE 73 +#define CB_FONTSTYLE 74 +#define FT_FONTSIZE 75 +#define MB_FONTSIZE 76 +#define FT_PREVIEW 77 + +// DisplayHId +#define RID_TB_CONF 80 +#define RID_FT_CONTROLS 81 +#define RID_MLB_CONTROLS 82 +#define RID_FT_SLOTS 83 +#define RID_MLB_SLOTS 84 +#define RID_PB_KOPIEREN 85 +#define RID_PB_BENENNEN 86 +#define RID_PB_SELECTALL 87 +#define RID_OK_CLOSE 88 + + +// BreakpointWindow +#define IMGID_BRKENABLED 30838 +#define IMGID_BRKDISABLED 30839 +#define IMGID_STEPMARKER 30840 +#define IMGID_ERRORMARKER 30841 + + +// Edit Variables +#define RID_FT_NAME 100 +#define RID_FT_CONTENT 101 +#define RID_FT_NEW_CONTENT 102 +#define RID_FT_NAME_VALUE 103 +#define RID_FT_CONTENT_VALUE 104 + +#define RID_RB_NEW_BOOL_T 105 +#define RID_RB_NEW_BOOL_F 106 +#define RID_NF_NEW_INTEGER 107 +#define RID_NF_NEW_LONG 108 +#define RID_ED_NEW_STRING 109 + +#endif + diff --git a/basic/source/app/status.cxx b/basic/source/app/status.cxx new file mode 100644 index 000000000000..c4d71c905d59 --- /dev/null +++ b/basic/source/app/status.cxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: status.cxx,v $ + * $Revision: 1.11 $ + * + * 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 "app.hxx" +#include "basic.hrc" +#include "appwin.hxx" +#include "status.hxx" + +#include <vcl/decoview.hxx> + +StatusLine::StatusLine( BasicFrame* p ) +: TaskBar( p ) +, pFrame( p ) +{ + // initialize TaskToolBox + TaskToolBox* pTempTaskToolBox = GetTaskToolBox(); + pTempTaskToolBox->SetActivateTaskHdl( LINK( this, StatusLine, ActivateTask ) ); + + // initialize TaskStatusBar + TaskStatusBar* pTempStatusBar = GetStatusBar(); + long nCharWidth = GetTextWidth( '0' ); // We state: All numbers has the same width + pTempStatusBar->InsertItem( ST_MESSAGE, GetTextWidth( 'X' ) * 20, SIB_LEFT | SIB_IN | SIB_AUTOSIZE ); + pTempStatusBar->InsertItem( ST_LINE, 5*nCharWidth ); + pTempStatusBar->InsertItem( ST_PROF, GetTextWidth( 'X' ) * 10 ); + pTempStatusBar->InsertStatusField(); + + Show(); +} + +void StatusLine::Message( const String& s ) +{ + GetStatusBar()->SetItemText( ST_MESSAGE, s ); +} + +void StatusLine::Pos( const String& s ) +{ + GetStatusBar()->SetItemText( ST_LINE, s ); +} + +void StatusLine::SetProfileName( const String& s ) +{ + GetStatusBar()->SetItemText( ST_PROF, s ); +} + + +IMPL_LINK( StatusLine, ActivateTask, TaskToolBox*, pTTB ) +{ + USHORT nFirstWinPos=0; + MenuBar* pMenu = pFrame->GetMenuBar(); + PopupMenu* pWinMenu = pMenu->GetPopupMenu( RID_APPWINDOW ); + + while ( pWinMenu->GetItemId( nFirstWinPos ) < RID_WIN_FILE1 && nFirstWinPos < pWinMenu->GetItemCount() ) + nFirstWinPos++; + + nFirstWinPos += pTTB->GetItemPos( pTTB->GetCurItemId() ) / 2; + + USHORT x; + x = pTTB->GetItemPos( pTTB->GetCurItemId() ); + x = pWinMenu->GetItemId( nFirstWinPos ); + x = pWinMenu->GetItemCount(); + AppWin* pWin = pFrame->FindWin( pWinMenu->GetItemText( pWinMenu->GetItemId( nFirstWinPos ) ).EraseAllChars( L'~' ) ); + if ( pWin ) + { + pWin->Minimize( FALSE ); + pWin->ToTop(); + } + return 0; +} + +void StatusLine::LoadTaskToolBox() +{ + USHORT nFirstWinPos=0; + MenuBar* pMenu = pFrame->GetMenuBar(); + PopupMenu* pWinMenu = pMenu->GetPopupMenu( RID_APPWINDOW ); + + while ( pWinMenu->GetItemId( nFirstWinPos ) < RID_WIN_FILE1 && nFirstWinPos < pWinMenu->GetItemCount() ) + nFirstWinPos++; + + TaskToolBox* pTaskToolBox = GetTaskToolBox(); + + pTaskToolBox->StartUpdateTask(); + + while ( nFirstWinPos < pWinMenu->GetItemCount() ) + { // There are windows + Window* pWin = pFrame->FindWin( pWinMenu->GetItemId( nFirstWinPos ) ); + + if ( pWin ) + pTaskToolBox->UpdateTask( Image(), pWin->GetText(), pWin == pFrame->pList->Last() && !( pFrame->pList->Last()->GetWinState() & TT_WIN_STATE_HIDE ) ); + + nFirstWinPos++; + } + + pTaskToolBox->EndUpdateTask(); + Resize(); + Invalidate(); +} + + diff --git a/basic/source/app/status.hxx b/basic/source/app/status.hxx new file mode 100644 index 000000000000..689d10d9e731 --- /dev/null +++ b/basic/source/app/status.hxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: status.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BASICSTATUS_HXX +#define _BASICSTATUS_HXX + +#include <svtools/taskbar.hxx> +#include <vcl/status.hxx> + +#define ST_MESSAGE 1 +#define ST_LINE 2 +#define ST_PROF 3 + +class BasicFrame; + +class StatusLine : public TaskBar +{ +protected: + BasicFrame* pFrame; + DECL_LINK( ActivateTask, TaskToolBox* ); + +public: + StatusLine( BasicFrame* ); + void Message( const String& ); // Show text + void Pos( const String& s ); // Show text position + void SetProfileName( const String& s ); // Current Profile + void LoadTaskToolBox(); +}; + +#endif diff --git a/basic/source/app/svtmsg.src b/basic/source/app/svtmsg.src new file mode 100644 index 000000000000..02c4bfe5e231 --- /dev/null +++ b/basic/source/app/svtmsg.src @@ -0,0 +1,342 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: svtmsg.src,v $ + * $Revision: 1.77 $ + * + * 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 "svtmsg.hrc" + + +// Hier sind die Messages aus dem Verzeichnis /basic/source/app enhalten + + +/////////////////////////////// +// Fehlermeldungen, die in das Resultfile gelangen. +// ********************* +// *** !!ACHTUNG!! *** +// ********************* +// Die Nummern dürfen sich NIE! ändern, +// da sie in den Resultfiles gespeichert sind, und bei erneutem Anzeigen +// statdessen die entsprechenden neuen oder garkeine Strings angzeigt werden. +/////////////////////////////// +String S_GPF_ABORT +{ + Text[ en-US ] = "Program aborted with GPF"; +}; +String S_APP_SHUTDOWN +{ + Text[ en-US ] = "Application has been shut down"; +}; +String S_SID_EXECUTE_FAILED_NO_DISPATCHER +{ + Text[ en-US ] = "Slot ID cannot be executed. No ActiveDispatcher"; +}; +String S_SID_EXECUTE_FAILED +{ + Text[ en-US ] = "Slot ID could not be executed"; +}; +String S_UNO_PROPERTY_NITIALIZE_FAILED +{ + Text[ en-US ] = "UnoSlot: Properties could not be initialized"; +}; +String S_RESETAPPLICATION_FAILED_COMPLEX +{ + Text[ en-US ] = "ResetApplication failed: too complex"; +}; +String S_RESETAPPLICATION_FAILED_UNKNOWN +{ + Text[ en-US ] = "ResetApplication failed: unknown window type"; +}; +String S_NO_ACTIVE_WINDOW +{ + Text[ en-US ] = "No active window found (GetNextCloseWindow)"; +}; +String S_NO_DIALOG_IN_GETACTIVE +{ + Text[ en-US ] = "GetActive does not return a dialog! Inform development"; +}; +String S_NO_POPUP +{ + Text[ en-US ] = "Pop-up menu not open"; +}; +String S_NO_SUBMENU +{ + Text[ en-US ] = "Submenu does not exist"; +}; +String S_CONTROLTYPE_NOT_SUPPORTED +{ + Text[ en-US ] = "ControlType ($Arg1) is not supported"; +}; +String S_SELECTION_BY_ATTRIBUTE_ONLY_DIRECTORIES +{ + Text[ en-US ] = "Selection by attributes only possible for directories"; +}; +String S_NO_MORE_FILES +{ + Text[ en-US ] = "No more files"; +}; +String S_UNKNOWN_METHOD +{ + Text[ en-US ] = "Unknown method '($Arg1)' on ($Arg2)"; +}; +String S_INVALID_PARAMETERS +{ + Text[ en-US ] = "Invalid Parameters"; +}; +String S_POINTER_OUTSIDE_APPWIN +{ + Text[ en-US ] = "Pointer not inside application window at '($Arg1)'"; +}; +String S_UNKNOWN_COMMAND +{ + Text[ en-US ] = "Unknown command '($Arg1)'"; +}; +String S_WIN_NOT_FOUND +{ + Text[ en-US ] = "($Arg1) could not be found"; +}; +String S_WIN_INVISIBLE +{ + Text[ en-US ] = "($Arg1) is not visible"; +}; +String S_WIN_DISABLED +{ + Text[ en-US ] = "($Arg1) could not be accessed. Disabled"; +}; +String S_NUMBER_TOO_BIG +{ + Text[ en-US ] = "Entry number ($Arg2) is too large in ($Arg1). Max. allowed is ($Arg3)"; +}; +String S_NUMBER_TOO_SMALL +{ + Text[ en-US ] = "The entry number ($Arg2) is too small in ($Arg1). Min allowed is ($Arg3)"; +}; +String S_WINDOW_DISAPPEARED +{ + Text[ en-US ] = "Window disappeared in the meantime at ($Arg1)"; +}; +String S_ERROR_SAVING_IMAGE +{ + Text[ en-US ] = "Error #($Arg1) when saving the image"; +}; +String S_INVALID_POSITION +{ + Text[ en-US ] = "Invalid position at ($Arg1)"; +}; +String S_SPLITWIN_NOT_FOUND +{ + Text[ en-US ] = "SplitWindow not found at ($Arg1)"; +}; +String S_INTERNAL_ERROR +{ + Text[ en-US ] = "Internal error at ($Arg1)"; +}; +String S_NO_STATUSBAR +{ + Text[ en-US ] = "No status bar at ($Arg1)"; +}; +String S_ITEMS_INVISIBLE +{ + Text[ en-US ] = "The items are hidden at ($Arg1)"; +}; +String S_TABPAGE_NOT_FOUND +{ + Text[ en-US ] = "Tab page not found at ($Arg1)"; +}; +String S_TRISTATE_NOT_ALLOWED +{ + Text[ en-US ] = "Tristate cannot be set at ($Arg1)"; +}; +String S_ERROR_IN_SET_TEXT +{ + Text[ en-US ] = "Set text did not function"; +}; +String S_ATTEMPT_TO_WRITE_READONLY +{ + Text[ en-US ] = "Attempt to write on read-only ($Arg1)"; +}; +String S_NO_SELECT_FALSE +{ + Text[ en-US ] = "Select FALSE not allowed. Use MultiSelect at ($Arg1)"; +}; +String S_ENTRY_NOT_FOUND +{ + Text[ en-US ] = "\"($Arg2)\" entry at ($Arg1) not found"; +}; +String S_METHOD_FAILED +{ + Text[ en-US ] = "($Arg1) of entry \"($Arg2)\" failed"; +}; +String S_HELPID_ON_TOOLBOX_NOT_FOUND +{ + Text[ en-US ] = "HelpID in ToolBox not found at ($Arg1)"; +}; +String S_BUTTON_DISABLED_ON_TOOLBOX +{ + Text[ en-US ] = "The button is disabled in ToolBox at ($Arg1)"; +}; +String S_BUTTON_HIDDEN_ON_TOOLBOX +{ + Text[ en-US ] = "The button is hidden in ToolBox at ($Arg1)"; +}; +String S_CANNOT_MAKE_BUTTON_VISIBLE_IN_TOOLBOX +{ + Text[ en-US ] = "Button cannot be made visible in ToolBox at ($Arg1)"; +}; +String S_TEAROFF_FAILED +{ + Text[ en-US ] = "TearOff failed in ToolBox at ($Arg1)"; +}; + +// Has to stay in for old res files +String S_NO_SELECTED_ENTRY_DEPRECATED +{ + Text[ en-US ] = "No entry is selected in TreeListBox at ($Arg1)"; +}; +String S_NO_SELECTED_ENTRY +{ + Text[ en-US ] = "No entry is selected in ($Arg2) at ($Arg1)"; +}; +String S_SELECT_DESELECT_VIA_STRING_NOT_IMPLEMENTED +{ + Text[ en-US ] = "Select/Deselect with string not implemented at ($Arg1)"; +}; +String S_ALLOWED_ONLY_IN_FLOATING_MODE +{ + Text[ en-US ] = "Method only allowed in floating mode at ($Arg1)"; +}; +String S_ALLOWED_ONLY_IN_DOCKING_MODE +{ + Text[ en-US ] = "Method only allowed in docking mode at ($Arg1)"; +}; +String S_SIZE_NOT_CHANGEABLE +{ + Text[ en-US ] = "Size cannot be altered at ($Arg1)"; +}; +String S_NO_OK_BUTTON +{ + Text[ en-US ] = "There is no OK button at ($Arg1)"; +}; +String S_NO_CANCEL_BUTTON +{ + Text[ en-US ] = "There is no Cancel button at ($Arg1)"; +}; +String S_NO_YES_BUTTON +{ + Text[ en-US ] = "There is no Yes button at ($Arg1)"; +}; +String S_NO_NO_BUTTON +{ + Text[ en-US ] = "There is no No button at ($Arg1)"; +}; +String S_NO_RETRY_BUTTON +{ + Text[ en-US ] = "There is no Repeat button at ($Arg1)"; +}; +String S_NO_HELP_BUTTON +{ + Text[ en-US ] = "There is no Help button at ($Arg1)"; +}; +String S_NO_DEFAULT_BUTTON +{ + Text[ en-US ] = "There is no Default button defined at ($Arg1)"; +}; +String S_BUTTON_ID_NOT_THERE +{ + Text[ en-US ] = "There is no button with ID ($Arg1) at ($Arg2)"; +}; +String S_BUTTONID_REQUIRED +{ + Text[ en-US ] = "A button ID needs to be given at ($Arg1)"; +}; +String S_UNKNOWN_TYPE +{ + Text[ en-US ] = "Unknown object type ($Arg1) from UId or method '($Arg2)' not supported"; +}; +String S_UNPACKING_STORAGE_FAILED +{ + Text[ en-US ] = "Unpacking storage \"($Arg1)\" to \"($Arg2)\" failed"; +}; +String S_NO_LIST_BOX_BUTTON +{ + Text[ en-US ] = "ListBoxButton does not exist in ($Arg1)"; +}; +String S_UNO_URL_EXECUTE_FAILED_NO_DISPATCHER +{ + Text[ en-US ] = "UNO URL \"($Arg1)\" could not be executed: No dispatcher was found."; +}; +String S_UNO_URL_EXECUTE_FAILED_NO_FRAME +{ + Text[ en-US ] = "UNO URL \"($Arg1)\" could not be executed: No ActiveFrame on desktop."; +}; +String S_NO_MENU +{ + Text[ en-US ] = "There is no menu at ($Arg1)"; +}; +String S_UNO_URL_EXECUTE_FAILED_DISABLED +{ + Text[ en-US ] = "UNO URL \"($Arg1)\" could not be run: Disabled"; +}; +String S_NO_SCROLLBAR +{ + Text[ en-US ] = "No scroll bar at ($Arg1)"; +}; +String S_NO_SAX_PARSER +{ + Text[ en-US ] = "No SAX Parser when using ($Arg1). Initialize with 'SAXReadFile' first."; +}; +String S_CANNOT_CREATE_DIRECTORY +{ + Text[ en-US ] = "Cannot create Directory: \"($Arg1)\""; +}; +String S_DIRECTORY_NOT_EMPTY +{ + Text[ en-US ] = "Directory has to be Empty to unpack to. Directory: \"($Arg1)\""; +}; +String S_DEPRECATED +{ + Text[ en-US ] = "Deprecated! Please change the script."; +}; +String S_SIZE_BELOW_MINIMUM +{ + Text[ en-US ] = "The Size is below the minimum. x=($Arg1) ,y=($Arg2)"; +}; +String S_CANNOT_FIND_FLOATING_WIN +{ + Text[ en-US ] = "Cannot find FloatingWindow for floating DockingWindow at ($Arg1)."; +}; +String S_NO_LIST_BOX_STRING +{ + Text[ en-US ] = "String does not exist in ($Arg1)"; +}; +String S_SLOT_IN_EXECUTE +{ + Text[ en-US ] = "Another Slot is being executed already."; +}; +String S_MENU_NOT_CLOSING +{ + Text[ en-US ] = "Menu not closing."; +}; diff --git a/basic/source/app/testbasi.cxx b/basic/source/app/testbasi.cxx new file mode 100644 index 000000000000..aca34f9b3ea8 --- /dev/null +++ b/basic/source/app/testbasi.cxx @@ -0,0 +1,34 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: testbasi.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#define testtool +#include "mybasic.cxx" diff --git a/basic/source/app/testtool.idl b/basic/source/app/testtool.idl new file mode 100644 index 000000000000..f754dfe4966e --- /dev/null +++ b/basic/source/app/testtool.idl @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: testtool.idl,v $ + * $Revision: 1.3 $ + * + * 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. + * + ************************************************************************/ +module +"484E40E0-1F23-101C-9961-04021C007002" +"5A30E000-1F23-101C-9961-04021C007002" +App +[ +HelpText( "Test" ), +TypeLibFile( "testtool.tlb" ) +] +{ + interface TestToolAutomation + [ + uuid( "6706E171-FB05-101B-804c-04021c007002" ) + ] + { + void Start( String aFilePath ); + BOOL Call( String aProcName, UINT32 nUId ); + void Close( ); + } +} + + diff --git a/basic/source/app/testtool.src b/basic/source/app/testtool.src new file mode 100644 index 000000000000..f273f3ce81c7 --- /dev/null +++ b/basic/source/app/testtool.src @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: testtool.src,v $ + * $Revision: 1.28 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include "testtool.hrc" + + +/////////////////////////////// +// Strings +/////////////////////////////// +String S_INVALID_KEYCODE +{ + Text[ en-US ] = "Is an invalid KeyCode!"; +}; +String S_MANDATORY_FILE +{ + Text[ en-US ] = "\ncould not be found.\nThis file is indispensable."; +}; +String S_READING_LONGNAMES +{ + Text[ en-US ] = "Reading long-names"; +}; +String S_READING_SLOT_IDS +{ + Text[ en-US ] = "Reading Slot IDs"; +}; +String S_READING_CONTROLS +{ + Text[ en-US ] = "Reading Controls"; +}; +String S_READING_BASIC_MODULE +{ + Text[ en-US ] = "Reading BASIC module"; +}; +String S_STARTING_APPLICATION +{ + Text[ en-US ] = "Starting application"; +}; + diff --git a/basic/source/app/textedit.cxx b/basic/source/app/textedit.cxx new file mode 100644 index 000000000000..0bc6e7c16e37 --- /dev/null +++ b/basic/source/app/textedit.cxx @@ -0,0 +1,869 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textedit.cxx,v $ + * $Revision: 1.24 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <svtools/texteng.hxx> +#include <svtools/textview.hxx> +#include <svtools/txtattr.hxx> +#include <basic/sbxmeth.hxx> +#ifndef _BASIC_TTRESHLP_HXX +#include <basic/ttstrhlp.hxx> +#endif + +#include "basic.hrc" +#include "textedit.hxx" +#include "appedit.hxx" +#include "brkpnts.hxx" +#include <basic/testtool.hxx> // defines for syntax highlighting + +TextEditImp::TextEditImp( AppEdit* pParent, const WinBits& aBits ) +: Window( pParent, aBits ) +, pAppEdit( pParent ) +, bHighlightning( FALSE ) +, bDoSyntaxHighlight( FALSE ) +, bDelayHighlight( TRUE ) +, nTipId( 0 ) +, bViewMoved( FALSE ) +{ + pTextEngine = new TextEngine(); + pTextEngine->SetMaxTextLen( STRING_MAXLEN ); + pTextEngine->EnableUndo( TRUE ); + + pTextView = new TextView( pTextEngine, this ); + pTextEngine->InsertView( pTextView ); + pTextEngine->SetModified( FALSE ); + + aSyntaxIdleTimer.SetTimeout( 200 ); + aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, TextEditImp, SyntaxTimerHdl ) ); + + aImplSyntaxIdleTimer.SetTimeout( 1 ); + aImplSyntaxIdleTimer.SetTimeoutHdl( LINK( this, TextEditImp, SyntaxTimerHdl ) ); + + StartListening( *pTextEngine ); + + HideTipTimer.SetTimeout( 5000 ); // 5 seconds + ShowTipTimer.SetTimeout( 500 ); // 1/2 seconds + HideTipTimer.SetTimeoutHdl( LINK( this, TextEditImp, HideVarContents ) ); + ShowTipTimer.SetTimeoutHdl( LINK( this, TextEditImp, ShowVarContents ) ); +} + +TextEditImp::~TextEditImp() +{ + pTextEngine->RemoveView( pTextView ); + delete pTextView; + delete pTextEngine; +} + +BOOL TextEditImp::ViewMoved() +{ + BOOL bOld = bViewMoved; + bViewMoved = FALSE; + return bOld; +} + +void TextEditImp::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + (void) rBC; /* avoid warning about unused parameter */ + if ( rHint.ISA( TextHint ) ) + { + const TextHint& rTextHint = (const TextHint&)rHint; + if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED ) + { + pAppEdit->pHScroll->SetThumbPos( pTextView->GetStartDocPos().X() ); + pAppEdit->pVScroll->SetThumbPos( pTextView->GetStartDocPos().Y() ); + if ( ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow() ) + ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow()->Scroll( 0, ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow()->GetCurYOffset() - pTextView->GetStartDocPos().Y() ); + bViewMoved = TRUE; + } + else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED ) + { + if ( pTextView->GetStartDocPos().Y() ) + { + long nOutHeight = GetOutputSizePixel().Height(); + long nTextHeight = pTextEngine->GetTextHeight(); + if ( nTextHeight < nOutHeight ) + pTextView->Scroll( 0, pTextView->GetStartDocPos().Y() ); + } + + pAppEdit->SetScrollBarRanges(); + } + else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED ) + { + ULONG nWidth = pTextEngine->CalcTextWidth(); + if ( (ULONG)nWidth != pAppEdit->nCurTextWidth ) + { + pAppEdit->nCurTextWidth = nWidth; + if ( pAppEdit->pHScroll ) + { // Initialization finished? + pAppEdit->pHScroll->SetRange( Range( 0, (long)nWidth) ); + pAppEdit->pHScroll->SetThumbPos( pTextView->GetStartDocPos().X() ); + } + } + } + else if( rTextHint.GetId() == TEXT_HINT_PARAINSERTED ) + { + if ( ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow() ) + ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow()->AdjustBreakpoints( rTextHint.GetValue()+1, TRUE ); + } + else if( rTextHint.GetId() == TEXT_HINT_PARAREMOVED ) + { + if ( ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow() ) + ((TextEdit*)(pAppEdit->pDataEdit))->GetBreakpointWindow()->AdjustBreakpoints( rTextHint.GetValue()+1, FALSE ); + + // Itchy adaption for two signs at line ends instead of one (hard coded default) + pTextEngine->SetMaxTextLen( STRING_MAXLEN - pTextEngine->GetParagraphCount() ); + } + else if( rTextHint.GetId() == TEXT_HINT_FORMATPARA ) + { + DoDelayedSyntaxHighlight( + sal::static_int_cast< xub_StrLen >( rTextHint.GetValue() ) ); + if ( pTextView->GetTextEngine()->IsModified() ) + ModifyHdl.Call( NULL ); + } + } +} + +#define TEXTATTR_SPECHIAL 55 +class TextAttribSpechial : public TextAttrib +{ +private: + FontWeight maFontWeight; + +public: + TextAttribSpechial( const FontWeight& rFontWeight ); + TextAttribSpechial( const TextAttribSpechial& rAttr ); + ~TextAttribSpechial() {;} + + virtual void SetFont( Font& rFont ) const; + virtual TextAttrib* Clone() const; + virtual int operator==( const TextAttrib& rAttr ) const; +}; + +TextAttribSpechial::TextAttribSpechial( const FontWeight& rFontWeight ) + : TextAttrib( TEXTATTR_SPECHIAL ), maFontWeight( rFontWeight ) +{} + +TextAttribSpechial::TextAttribSpechial( const TextAttribSpechial& rAttr ) + : TextAttrib( rAttr ), maFontWeight( rAttr.maFontWeight ) +{} + +void TextAttribSpechial::SetFont( Font& rFont ) const +{ + rFont.SetWeight( maFontWeight ); +} + +TextAttrib* TextAttribSpechial::Clone() const +{ + return new TextAttribSpechial( *this ); +} + +int TextAttribSpechial::operator==( const TextAttrib& rAttr ) const +{ + return ( ( TextAttrib::operator==(rAttr ) ) && + ( maFontWeight == ((const TextAttribSpechial&)rAttr).maFontWeight ) ); +} + +void TextEditImp::ImpDoHighlight( const String& rSource, ULONG nLineOff ) +{ + SbTextPortions aPortionList; + pAppEdit->GetBasicFrame()->Basic().Highlight( rSource, aPortionList ); + + USHORT nCount = aPortionList.Count(); + if ( !nCount ) + return; + + SbTextPortion& rLast = aPortionList[nCount-1]; + if ( rLast.nStart > rLast.nEnd ) // Nur bis Bug von MD behoben + { +#if OSL_DEBUG_LEVEL > 1 + DBG_ERROR( "MD-Bug nicht beseitigt!" ); +#endif + nCount--; + aPortionList.Remove( nCount); + if ( !nCount ) + return; + } + + // here is the postprocessing for types for the TestTool + USHORT i; + BOOL bWasTTControl = FALSE; + for ( i = 0; i < aPortionList.Count(); i++ ) + { + SbTextPortion& r = aPortionList[i]; +// DBG_ASSERT( r.nStart <= r.nEnd, "Highlight: Start > End?" ); + if ( r.nStart > r.nEnd ) // Nur bis Bug von MD behoben + continue; + + SbTextType eType = r.eType; + Color aColor; + switch ( eType ) + { + case SB_SYMBOL: + { + String aSymbol = rSource.Copy( r.nStart, r.nEnd - r.nStart +1 ); + r.eType = pAppEdit->GetBasicFrame()->Basic().GetSymbolType( aSymbol, bWasTTControl ); + + if ( r.eType == TT_CONTROL ) + bWasTTControl = TRUE; + else + bWasTTControl = FALSE; + } + break; + case SB_PUNCTUATION: + { + String aPunctuation = rSource.Copy( r.nStart, r.nEnd - r.nStart +1 ); + if ( aPunctuation.CompareToAscii( "." ) != COMPARE_EQUAL ) + bWasTTControl = FALSE; + } + break; + default: + bWasTTControl = FALSE; + } + } + + // Es muessen nur die Blanks und Tabs mit attributiert werden. + // If there are two equal attributes one after another, + // they are optimized by the EditEngine. + xub_StrLen nLastEnd = 0; +#ifdef DBG_UTIL + xub_StrLen nLine1 = aPortionList[0].nLine; +#endif + for ( i = 0; i < nCount; i++ ) + { + SbTextPortion& r = aPortionList[i]; + DBG_ASSERT( r.nLine == nLine1, "doch mehrere Zeilen ?" ); + DBG_ASSERT( r.nStart <= r.nEnd, "Highlight: Start > End?" ); + if ( r.nStart > r.nEnd ) // Nur bis Bug von MD behoben + continue; + + if ( r.nStart > nLastEnd ) + { + // Kann ich mich drauf verlassen, dass alle ausser + // Blank und Tab gehighlightet wird ?! + r.nStart = nLastEnd; + } + nLastEnd = r.nEnd+1; + if ( ( i == (nCount-1) ) && ( r.nEnd < rSource.Len() ) ) + r.nEnd = rSource.Len()-1; + } + + BOOL bWasModified = pTextEngine->IsModified(); + for ( i = 0; i < aPortionList.Count(); i++ ) + { + SbTextPortion& r = aPortionList[i]; +// DBG_ASSERT( r.nStart <= r.nEnd, "Highlight: Start > End?" ); + if ( r.nStart > r.nEnd ) // Nur bis Bug von MD behoben + continue; + + SbTextType eCol = r.eType; + Color aColor; + ULONG nLine = nLineOff+r.nLine-1; // -1, because BASIC starts with 1 + switch ( +eCol ) + { + case SB_KEYWORD: + aColor = Color( COL_BLUE ); + break; + case SB_SYMBOL: + aColor = Color( RGB_COLORDATA( 0x00, 0x60, 0x00 ) ); + break; + case SB_STRING: + aColor = Color( COL_RED ); + break; + case SB_NUMBER: + aColor = Color( COL_MAGENTA ); + break; + case SB_PUNCTUATION: + aColor = Color( COL_BLACK ); + break; + case SB_COMMENT: + aColor = Color( COL_GRAY ); + break; + case TT_KEYWORD: + case TT_LOCALCMD: + aColor = Color( COL_LIGHTBLUE ); + break; + case TT_REMOTECMD: + aColor = Color( RGB_COLORDATA( 0x00, 0xB0, 0xB0 ) ); + break; + case TT_CONTROL: + case TT_SLOT: + aColor = Color( RGB_COLORDATA( 0x00, 0xB0, 0x00 ) ); + break; + case TT_METHOD: + aColor = Color( RGB_COLORDATA( 0x00, 0xB0, 0x00 ) ); + break; + case TT_NOMETHOD: + { + aColor = Color( COL_RED ); + pTextEngine->SetAttrib( TextAttribSpechial( WEIGHT_BOLD ), nLine, r.nStart, r.nEnd+1 ); + } + break; + default: + { + aColor = Color( RGB_COLORDATA( 0xff, 0x80, 0x80 ) ); + DBG_ERROR( "Unknown syntax color" ); + } + } + pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLine, r.nStart, r.nEnd+1 ); + } + // Highlighting should not modify the text + pTextEngine->SetModified( bWasModified ); +} + +void TextEditImp::DoSyntaxHighlight( ULONG nPara ) +{ + // Due to delayed syntax highlight it can happend that the + // paragraph does no longer exist + if ( nPara < pTextEngine->GetParagraphCount() ) + { + // leider weis ich nicht, ob genau diese Zeile Modified() ... +// if ( pProgress ) +// pProgress->StepProgress(); + pTextEngine->RemoveAttribs( nPara ); + String aSource( pTextEngine->GetText( nPara ) ); + ImpDoHighlight( aSource, nPara ); + } +} + +void TextEditImp::DoDelayedSyntaxHighlight( xub_StrLen nPara ) +{ + // Paragraph is added to 'List', processed in TimerHdl. + // => Do not manipulate paragraphs while EditEngine is formatting +// if ( pProgress ) +// pProgress->StepProgress(); + + if ( !bHighlightning && bDoSyntaxHighlight ) + { + if ( bDelayHighlight ) + { + aSyntaxLineTable.Insert( nPara, (void*)(ULONG)1 ); + aSyntaxIdleTimer.Start(); + } + else + DoSyntaxHighlight( nPara ); + } +} + +IMPL_LINK( TextEditImp, SyntaxTimerHdl, Timer *, EMPTYARG ) +{ + DBG_ASSERT( pTextView, "Not yet a View but Syntax-Highlight ?!" ); + pTextEngine->SetUpdateMode( FALSE ); + + bHighlightning = TRUE; + USHORT nLine; + while ( aSyntaxLineTable.First() && !Application::AnyInput( INPUT_MOUSEANDKEYBOARD ) ) + { + nLine = (USHORT)aSyntaxLineTable.GetCurKey(); + DoSyntaxHighlight( nLine ); + aSyntaxLineTable.Remove( nLine ); +/* if ( Application::AnyInput() ) + { + aSyntaxIdleTimer.Start(); // Starten, falls wir in einem Dialog landen + pTextView->ShowCursor( TRUE, TRUE ); + pTextEngine->SetUpdateMode( TRUE ); + bHighlightning = FALSE; + GetpApp()->Reschedule(); + bHighlightning = TRUE; + pTextEngine->SetUpdateMode( FALSE ); + }*/ + } + + BOOL bWasModified = pTextEngine->IsModified(); + if ( aSyntaxLineTable.Count() > 3 ) // Without VDev + { + pTextEngine->SetUpdateMode( TRUE ); + pTextView->ShowCursor( TRUE, TRUE ); + } + else + pTextEngine->SetUpdateMode( TRUE ); // ! With VDev +// pTextView->ForceUpdate(); + + // SetUpdateMode( TRUE ) soll kein Modify setzen + pTextEngine->SetModified( bWasModified ); + + // SyntaxTimerHdl wird gerufen, wenn Text-Aenderung + // => gute Gelegenheit, Textbreite zu ermitteln! +// long nPrevTextWidth = nCurTextWidth; +// nCurTextWidth = pTextEngine->CalcTextWidth(); +// if ( nCurTextWidth != nPrevTextWidth ) +// SetScrollBarRanges(); + bHighlightning = FALSE; + + if ( aSyntaxLineTable.First() ) + aImplSyntaxIdleTimer.Start(); + +// while ( Application::AnyInput() ) +// Application::Reschedule(); // Reschedule, da der UserEvent keine Paints etc. durchlässt + + return 0; +} + +void TextEditImp::InvalidateSyntaxHighlight() +{ + for ( xub_StrLen i = 0; i < pTextEngine->GetParagraphCount(); i++ ) + DoDelayedSyntaxHighlight( i ); +} + +void TextEditImp::SyntaxHighlight( BOOL bNew ) +{ + if ( ( bNew && bDoSyntaxHighlight ) || ( !bNew && !bDoSyntaxHighlight ) ) + return; + + bDoSyntaxHighlight = bNew; + if ( !pTextEngine ) + return; + + + if ( bDoSyntaxHighlight ) + { + InvalidateSyntaxHighlight(); + } + else + { + aSyntaxIdleTimer.Stop(); + pTextEngine->SetUpdateMode( FALSE ); + for ( ULONG i = 0; i < pTextEngine->GetParagraphCount(); i++ ) + pTextEngine->RemoveAttribs( i ); + +// pTextEngine->QuickFormatDoc(); + pTextEngine->SetUpdateMode( TRUE ); + pTextView->ShowCursor(TRUE, TRUE ); + } +} + + +void TextEditImp::SetFont( const Font& rNewFont ) +{ + pTextEngine->SetFont(rNewFont); +} + +BOOL TextEditImp::IsModified() +{ + return pTextEngine->IsModified(); +} + +void TextEditImp::KeyInput( const KeyEvent& rKeyEvent ) +{ + BOOL bWasModified = pTextView->GetTextEngine()->IsModified(); + pTextView->GetTextEngine()->SetModified( FALSE ); + + if ( !pTextView->KeyInput( rKeyEvent ) ) + Window::KeyInput( rKeyEvent ); + + if ( pTextView->GetTextEngine()->IsModified() ) + ModifyHdl.Call( NULL ); + else + pTextView->GetTextEngine()->SetModified( bWasModified ); +} + +void TextEditImp::Paint( const Rectangle& rRect ){ pTextView->Paint( rRect );} +void TextEditImp::MouseButtonUp( const MouseEvent& rMouseEvent ){ pTextView->MouseButtonUp( rMouseEvent );} +//void TextEditImp::MouseButtonDown( const MouseEvent& rMouseEvent ){ pTextView->MouseButtonDown( rMouseEvent );} +//void TextEditImp::MouseMove( const MouseEvent& rMouseEvent ){ pTextView->MouseMove( rMouseEvent );} +//void TextEditImp::Command( const CommandEvent& rCEvt ){ pTextView->Command( rCEvt );} +//BOOL TextEditImp::Drop( const DropEvent& rEvt ){ return FALSE /*pTextView->Drop( rEvt )*/;} +//BOOL TextEditImp::QueryDrop( DropEvent& rEvt ){ return FALSE /*pTextView->QueryDrop( rEvt )*/;} + + +void TextEditImp::Command( const CommandEvent& rCEvt ) +{ + switch( rCEvt.GetCommand() ) { + case COMMAND_CONTEXTMENU: + case COMMAND_WHEEL: + GetParent()->Command( rCEvt ); + break; + default: + pTextView->Command( rCEvt ); + } +} + + +void TextEditImp::MouseButtonDown( const MouseEvent& rMouseEvent ) +{ + pTextView->MouseButtonDown( rMouseEvent ); + HideVarContents( NULL ); + ShowTipTimer.Stop(); +} + + +void TextEditImp::MouseMove( const MouseEvent& rMEvt ) +{ + pTextView->MouseMove( rMEvt ); + HideVarContents( NULL ); + if ( rMEvt.GetButtons() == 0 ) + ShowTipTimer.Start(); + if ( rMEvt.IsLeaveWindow() ) + ShowTipTimer.Stop(); +} + + +IMPL_LINK( TextEditImp, HideVarContents, void*, EMPTYARG ) +{ + if ( nTipId ) + { + Help::HideTip( nTipId ); + nTipId = 0; + aTipWord = String(); + } + return 0; +} + +static const char cSuffixes[] = "%&!#@$"; + + +SbxBase* TextEditImp::GetSbxAtMousePos( String &aWord ) +{ + Point aPos = GetPointerPosPixel(); + Point aDocPos = pTextView->GetDocPos( aPos ); + aWord = pTextEngine->GetWord( pTextEngine->GetPaM( aDocPos ) ); + + if ( aWord.Len() /*&& !Application::GetAppInternational().IsNumeric( aWord )*/ ) + { + xub_StrLen nLastChar = aWord.Len()-1; + String aSuffixes = CUniString( cSuffixes ); + if ( aSuffixes.Search( aWord.GetChar(nLastChar) ) != STRING_NOTFOUND ) + aWord.Erase( nLastChar, 1 ); + // because perhaps TestTools throws an error + BOOL bWasError = SbxBase::IsError(); + pAppEdit->GetBasicFrame()->Basic().DebugFindNoErrors( TRUE ); + SbxBase* pSBX = StarBASIC::FindSBXInCurrentScope( aWord ); + pAppEdit->GetBasicFrame()->Basic().DebugFindNoErrors( FALSE ); + DBG_ASSERT( !( !bWasError && SbxBase::IsError()), "Error generated while retrieving Variable data for viewing" ); + if ( !bWasError && SbxBase::IsError() ) + SbxBase::ResetError(); + + return pSBX; + } + return NULL; +} + + +IMPL_LINK( TextEditImp, ShowVarContents, void*, EMPTYARG ) +{ + String aWord; + SbxBase* pSBX = GetSbxAtMousePos( aWord ); + String aHelpText; + Point aPos = GetPointerPosPixel(); + + if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) ) + { + SbxVariable* pVar = (SbxVariable*)pSBX; + SbxDataType eType = pVar->GetType(); + if ( eType == SbxOBJECT ) + { + // Can cause a crash: Type == Object does not mean pVar == Object + if ( pVar->GetObject() && pVar->GetObject()->ISA( SbxObject ) ) + aHelpText = ((SbxObject*)(pVar->GetObject()))->GetClassName(); + else + aHelpText = CUniString("Object"); + } + else if ( eType & SbxARRAY ) + aHelpText = CUniString("{...}"); + else if ( eType != SbxEMPTY ) + { + aHelpText = pVar->GetName(); + if ( !aHelpText.Len() ) // Name is not copied in arguments + aHelpText = aWord; + aHelpText += '='; + aHelpText += pVar->GetString(); + } + } + + + if ( aHelpText.Len() && aTipPos != aPos && aTipWord != aWord ) + { + if ( nTipId ) + Help::HideTip( nTipId ); + nTipId = Help::ShowTip( this, Rectangle(), aHelpText ); + + HideTipTimer.Start(); + aTipWord = aWord; + aTipPos = aPos; + } + if ( nTipId && aTipPos != aPos ) + { + Help::HideTip( nTipId ); + nTipId = 0; + aTipWord = String(); + } + + return 0; +} + + +void TextEditImp::BuildKontextMenu( PopupMenu *&pMenu ) +{ + String aWord; + SbxBase* pSBX = GetSbxAtMousePos( aWord ); + if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) ) + { + SbxVariable* pVar = (SbxVariable*)pSBX; + SbxDataType eType = pVar->GetType(); + + if ( ( eType & ( SbxVECTOR | SbxARRAY | SbxBYREF )) == 0 ) + { + +/* +Boolean +Currency +Date +Double +Integer +Long +Object +Single +String +Variant(Empty) +*/ + switch ( eType ) + { + case SbxBOOL: +// case SbxCURRENCY: +// case SbxDATE: + case SbxDOUBLE: + case SbxINTEGER: + case SbxLONG: +// case SbxOBJECT: // cannot be edited + case SbxSINGLE: + case SbxSTRING: + + case SbxVARIANT: // does not occure, instead SbxEMPTY + case SbxEMPTY: + { + pAppEdit->GetBasicFrame()->SetEditVar( pVar ); + if ( !pMenu ) + pMenu = new PopupMenu(); + else + pMenu->InsertSeparator(); + + pMenu->InsertItem( RID_POPUPEDITVAR, ((BasicFrame*)GetpApp()->GetAppWindow())->GenRealString( GEN_RES_STR1( IDS_EDIT_VAR, aWord ) ) ); + } + break; + default: + ; + } + } + } +} + + + + +DBG_NAME(TextEdit) + +TextEdit::TextEdit( AppEdit* pParent, const WinBits& aBits ) +: pBreakpointWindow( NULL ) +, bFileWasUTF8( FALSE ) +, bSaveAsUTF8( FALSE ) +, aEdit( pParent, aBits | WB_NOHIDESELECTION ) +{ +DBG_CTOR(TextEdit,0); +} + +TextEdit::~TextEdit() +{DBG_DTOR(TextEdit,0);} + +void TextEdit::Highlight( ULONG nLine, xub_StrLen nCol1, xub_StrLen nCol2 ) +{ + if ( nLine ) // Should not occure but at 'Sub expected' in first line + nLine--; + + String s = aEdit.pTextEngine->GetText( nLine ); + + if( nCol1 == STRING_NOTFOUND ) + { + // No column given + nCol1 = 0; + nCol2 = STRING_NOTFOUND; + } + if( nCol2 == STRING_NOTFOUND ) + { + nCol2 = s.Len(); + } + // Adaption to the Precompiler | EditText != Compilied Text + if ( nCol2 > s.Len() ) + nCol2 = s.Len(); + if ( nCol1 >= nCol2 ) + nCol1 = 0; + + // Because nCol2 *may* point after the current statement + // (because the next one starts there) there are space + // that must be removed + BOOL bColon = FALSE; + + while ( s.GetChar( nCol2 ) == ' ' && nCol2 > nCol1 && !bColon ) + { + nCol2--; + if ( s.GetChar( nCol2 ) == ':' ) + { + nCol2--; + bColon = TRUE; + } + } + + aEdit.ViewMoved(); + aEdit.pTextView->SetSelection( TextSelection(TextPaM(nLine,nCol2+1), TextPaM(nLine,nCol1)) ); + if ( aEdit.ViewMoved() ) + { + aEdit.pTextView->SetSelection( TextSelection(TextPaM(TEXT_PARA_ALL,1)) ); // fix #105169# + aEdit.pTextView->SetSelection( TextSelection(TextPaM((nLine>=2?nLine-2:0),nCol2+1)) ); + aEdit.pTextView->SetSelection( TextSelection(TextPaM(nLine,nCol2+1), TextPaM(nLine,nCol1)) ); + } +} + + +void TextEdit::Delete(){ aEdit.pTextView->KeyInput( KeyEvent( 0, KeyCode( KEYFUNC_DELETE ) )); } +void TextEdit::Cut(){ aEdit.pTextView->Cut(); } +void TextEdit::Copy(){ aEdit.pTextView->Copy(); } +void TextEdit::Paste(){ aEdit.pTextView->Paste(); } +void TextEdit::Undo(){ aEdit.pTextView->Undo(); } +void TextEdit::Redo(){ aEdit.pTextView->Redo(); } +String TextEdit::GetSelected(){ return aEdit.pTextView->GetSelected(); } +TextSelection TextEdit::GetSelection() const{ return aEdit.pTextView->GetSelection(); } +void TextEdit::SetSelection( const TextSelection& rSelection ){ aEdit.pTextView->SetSelection( rSelection ); } + +USHORT TextEdit::GetLineNr() const +{ + return sal::static_int_cast< USHORT >( + aEdit.pTextView->GetSelection().GetEnd().GetPara()+1); +} + +void TextEdit::ReplaceSelected( const String& rStr ){ aEdit.pTextView->InsertText(rStr); } +BOOL TextEdit::IsModified(){ return aEdit.IsModified(); } + +String TextEdit::GetText() const +{ + return aEdit.pTextEngine->GetText( GetSystemLineEnd() ); +} + +void TextEdit::SetText( const String& rStr ){ aEdit.pTextEngine->SetText(rStr); aEdit.pTextEngine->SetModified( FALSE ); } +void TextEdit::SetModifyHdl( Link l ){ aEdit.SetModifyHdl(l); } +BOOL TextEdit::HasText() const { return aEdit.pTextEngine->GetTextLen() > 0; } + +// Search from the beginning or at mark + 1 +BOOL TextEdit::Find( const String& s ) +{ + DBG_CHKTHIS(TextEdit,0); + + TextSelection aSelection = aEdit.pTextView->GetSelection(); + ULONG nPara = aSelection.GetStart().GetPara(); + xub_StrLen nIndex = aSelection.GetStart().GetIndex(); + + if ( aSelection.HasRange() ) + nIndex ++; + + while ( nPara <= aEdit.pTextEngine->GetParagraphCount() ) + { + String aText = aEdit.pTextEngine->GetText( nPara ); + + nIndex = aText.Search( s, nIndex ); + if( nIndex != STRING_NOTFOUND ) + { + aEdit.pTextView->SetSelection( TextSelection( TextPaM( nPara, nIndex ), TextPaM( nPara, nIndex + s.Len() ) ) ); + return TRUE; + } + nIndex = 0; + nPara++; + } + return FALSE; +} + +BOOL TextEdit::Load( const String& aName ) +{ +DBG_CHKTHIS(TextEdit,0); + BOOL bOk = TRUE; + SvFileStream aStrm( aName, STREAM_STD_READ ); + if( aStrm.IsOpen() ) + { + String aText, aLine, aLineBreak; + BOOL bIsFirstLine = TRUE; + aLineBreak += '\n'; + aLineBreak.ConvertLineEnd(); + rtl_TextEncoding aFileEncoding = RTL_TEXTENCODING_IBM_850; + while( !aStrm.IsEof() && bOk ) + { + aStrm.ReadByteStringLine( aLine, aFileEncoding ); + if ( bIsFirstLine && IsTTSignatureForUnicodeTextfile( aLine ) ) + { + aFileEncoding = RTL_TEXTENCODING_UTF8; + bFileWasUTF8 = TRUE; + } + else + { + if ( !bIsFirstLine ) + aText += aLineBreak; + aText += aLine; + bIsFirstLine = FALSE; + } + if( aStrm.GetError() != SVSTREAM_OK ) + bOk = FALSE; + } + SetText( aText ); + } + else + bOk = FALSE; + return bOk; +} + +BOOL TextEdit::Save( const String& aName ) +{ +DBG_CHKTHIS(TextEdit,0); + BOOL bOk = TRUE; + SvFileStream aStrm( aName, STREAM_STD_WRITE | STREAM_TRUNC ); + rtl_TextEncoding aFileEncoding = RTL_TEXTENCODING_IBM_850; + if( aStrm.IsOpen() ) + { + if ( bFileWasUTF8 || bSaveAsUTF8 ) + { + aStrm << TT_SIGNATURE_FOR_UNICODE_TEXTFILES; + aStrm << sal_Char(_LF); + aFileEncoding = RTL_TEXTENCODING_UTF8; + } + String aSave = GetText(); + aSave.ConvertLineEnd(LINEEND_LF); + aStrm << ByteString( aSave, aFileEncoding ).GetBuffer(); + if( aStrm.GetError() != SVSTREAM_OK ) + bOk = FALSE; + else + aEdit.pTextEngine->SetModified(FALSE); + } else bOk = FALSE; + return bOk; +} + + +void TextEdit::BuildKontextMenu( PopupMenu *&pMenu ) +{ + DataEdit::BuildKontextMenu( pMenu ); + aEdit.BuildKontextMenu( pMenu ); +} + + diff --git a/basic/source/app/textedit.hxx b/basic/source/app/textedit.hxx new file mode 100644 index 000000000000..1598d4867140 --- /dev/null +++ b/basic/source/app/textedit.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textedit.hxx,v $ + * $Revision: 1.9 $ + * + * 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 _TEXTEDIT_HXX +#define _TEXTEDIT_HXX + +class AppEdit; +class TextEngine; +class TextView; +class TextEdit; +class BreakpointWindow; + +#include <vcl/timer.hxx> +#include <tools/table.hxx> +#include <tools/debug.hxx> +#include <svtools/lstner.hxx> +#include <svtools/svmedit.hxx> + +#include "dataedit.hxx" + +//#include <xtextedt.hxx> + +class TextEditImp : public Window, public SfxListener +{ +using Window::Notify; + +protected: + void DoSyntaxHighlight( ULONG nPara ); + + +private: + AppEdit *pAppEdit; + Link ModifyHdl; + + Timer aSyntaxIdleTimer; + Timer aImplSyntaxIdleTimer; + DECL_LINK( SyntaxTimerHdl, Timer * ); + Table aSyntaxLineTable; + + void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + + void ImpDoHighlight( const String& rSource, ULONG nLineOff ); + BOOL bHighlightning; + BOOL bDoSyntaxHighlight; + BOOL bDelayHighlight; + + + SbxBase* GetSbxAtMousePos( String &aWord ); + virtual void MouseMove( const MouseEvent& rMEvt ); + DECL_LINK( HideVarContents, void* ); + DECL_LINK( ShowVarContents, void* ); + Point aTipPos; + String aTipWord; + ULONG nTipId; + + Timer HideTipTimer; + Timer ShowTipTimer; + + BOOL bViewMoved; + +public: + TextEditImp( AppEdit *pParent, const WinBits& aBits ); + ~TextEditImp(); + + TextEngine *pTextEngine; + TextView *pTextView; + + void SetFont( const Font& rNewFont ); + BOOL IsModified(); + void SetModifyHdl( Link l ){ ModifyHdl = l; } + + void KeyInput( const KeyEvent& rKeyEvent ); + void Paint( const Rectangle& rRect ); + void MouseButtonUp( const MouseEvent& rMouseEvent ); + void MouseButtonDown( const MouseEvent& rMouseEvent ); +// void MouseMove( const MouseEvent& rMouseEvent ); + void Command( const CommandEvent& rCEvt ); + //BOOL Drop( const DropEvent& rEvt ); + //BOOL QueryDrop( DropEvent& rEvt ); + + BOOL ViewMoved(); + + void DoDelayedSyntaxHighlight( xub_StrLen nPara ); + void InvalidateSyntaxHighlight(); + void SyntaxHighlight( BOOL bNew ); + void BuildKontextMenu( PopupMenu *&pMenu ); +}; + + + +DBG_NAMEEX(TextEdit) +class TextEdit : public DataEdit { + + BreakpointWindow *pBreakpointWindow; + BOOL bFileWasUTF8; + BOOL bSaveAsUTF8; + +public: + TextEdit( AppEdit*, const WinBits& ); + ~TextEdit(); + void Highlight( ULONG nLine, xub_StrLen nCol1, xub_StrLen nCol2 ); + TextEditImp& GetTextEditImp() { return aEdit; } + + void SetBreakpointWindow( BreakpointWindow *pBPWindow ){ pBreakpointWindow = pBPWindow; } + BreakpointWindow *GetBreakpointWindow(){ return pBreakpointWindow; } + + DATA_FUNC_DEF( aEdit, TextEditImp ) + + virtual void BuildKontextMenu( PopupMenu *&pMenu ); + + void SaveAsUTF8( BOOL bUTF8 ) { bSaveAsUTF8 = bUTF8; } +}; + +#endif diff --git a/basic/source/app/ttbasic.cxx b/basic/source/app/ttbasic.cxx new file mode 100644 index 000000000000..b0e8eb4a8a39 --- /dev/null +++ b/basic/source/app/ttbasic.cxx @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ttbasic.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <basic/mybasic.hxx> +#include "ttbasic.hxx" + +MyBasic* TTBasic::CreateMyBasic() +{ + return new MyBasic; +} diff --git a/basic/source/app/ttbasic.hxx b/basic/source/app/ttbasic.hxx new file mode 100644 index 000000000000..96a00d791916 --- /dev/null +++ b/basic/source/app/ttbasic.hxx @@ -0,0 +1,35 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ttbasic.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +class TTBasic +{ +public: + static MyBasic* CreateMyBasic(); +}; + diff --git a/basic/source/app/ttmsg.src b/basic/source/app/ttmsg.src new file mode 100644 index 000000000000..81d595cee55f --- /dev/null +++ b/basic/source/app/ttmsg.src @@ -0,0 +1,163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ttmsg.src,v $ + * $Revision: 1.47 $ + * + * 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 "ttmsg.hrc" + + +// Hier sind die Messages aus dem Verzeichnis /basic/source/testtool enhalten + + +/////////////////////////////// +// Fehlermeldungen, die in das Resultfile gelangen. +// ********************* +// *** !!ACHTUNG!! *** +// ********************* +// Die Nummern dürfen sich NIE! ändern, +// da sie in den Resultfiles gespeichert sind, und bei erneutem Anzeigen +// statdessen die entsprechenden neuen oder garkeine Strings angzeigt werden. +/////////////////////////////// +String S_NAME_NOT_THERE +{ + Text[ en-US ] = "Name doesn't exist: #($Arg1)"; +}; +String S_DOUBLE_NAME +{ + Text[ en-US ] = "Name double: ($Arg1)"; +}; +String S_READING_FILE +{ + Text[ en-US ] = "Reading the files"; +}; +String S_CANNOT_OPEN_FILE +{ + Text[ en-US ] = "File cannot be opened: ($Arg1)"; +}; +String S_INVALID_LINE +{ + Text[ en-US ] = "Line \"($Arg1)\" is invalid."; +}; +String S_SHORTNAME_UNKNOWN +{ + Text[ en-US ] = "Short-name unknown during copying: ($Arg1)"; +}; +String S_LONGNAME_UNKNOWN +{ + Text[ en-US ] = "Long-name unknown: ($Arg1)"; +}; +String S_FIRST_SHORTNAME_REQ_ASTRX +{ + Text[ en-US ] = "First short-name must start with * . Ignoring."; +}; +String S_TIMOUT_WAITING +{ + Text[ en-US ] = "Server Timeout while waiting for answer. Sequence No: ($Arg1)"; +}; +String S_APPLICATION_RESTARTED +{ + Text[ en-US ] = "Application has been restarted."; +}; +String S_APPLICATION_START_FAILED +{ + Text[ en-US ] = "Application \"($Arg1)\" cannot be started. "; +}; +String S_TIMOUT_SENDING +{ + Text[ en-US ] = "Server Timeout while sending. Sequence No: ($Arg1)"; +}; +String S_NO_CONNECTION +{ + Text[ en-US ] = "No connection. Sequence No: ($Arg1)"; +}; +String S_NO_FILES_FOUND // Not used anymore. needed only for old *.res files +{ + Text[ en-US ] = "No ($Arg1) files found"; +}; +String S_ERRORS_DETECTED +{ + Text[ en-US ] = "** ($Arg1) errors occurred"; +}; +String S_NO_ERRORS_DETECTED +{ + Text[ en-US ] = "** No errors have occurred"; +}; +String S_WARNINGS_DETECTED +{ + Text[ en-US ] = "** ($Arg1) warnings occurred"; +}; +String S_NO_WARNINGS_DETECTED +{ + Text[ en-US ] = "** No warnings have occurred"; +}; +String S_INCLUDE_FILE_WARNINGS_DETECTED +{ + Text[ en-US ] = "** ($Arg1) warnings occurred during initialization"; +}; +String S_NO_INCLUDE_FILE_WARNINGS_DETECTED +{ + Text[ en-US ] = "** No warnings occurred during initialization"; +}; +String S_UNKNOWN_SLOT_CONTROL +{ + Text[ en-US ] = "Slot/Control unknown :\"($Arg1)\""; +}; +String S_RETURN_SEQUENCE_MISSMATCH +{ + Text[ en-US ] = "Return Stream has wrong sequence: ($Arg1) instead of ($Arg2)"; +}; +String S_RETURNED_VALUE_ID_MISSMATCH +{ + Text[ en-US ] = "Return value received but different Id expected"; +}; +String S_RETURNED_VALUE_NO_RECEIVER +{ + Text[ en-US ] = "Return value received but no receiver defined"; +}; +String S_UNKNOWN_METHOD +{ + Text[ en-US ] = "Unknown method on object :($Arg1).($Arg2)"; +}; +/* +String +{ + Text[ en-US ] = ; +}; +String +{ + Text[ en-US ] = ; +}; +String +{ + Text[ en-US ] = ; +}; +String +{ + Text[ en-US ] = ; +}; +*/ + diff --git a/basic/source/basmgr/basicmanagerrepository.cxx b/basic/source/basmgr/basicmanagerrepository.cxx new file mode 100644 index 000000000000..17bd8a712763 --- /dev/null +++ b/basic/source/basmgr/basicmanagerrepository.cxx @@ -0,0 +1,644 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basicmanagerrepository.cxx,v $ + * $Revision: 1.11 $ + * + * 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 <basic/basicmanagerrepository.hxx> +#include <basic/basmgr.hxx> +#include "scriptcont.hxx" +#include "dlgcont.hxx" +#include <basic/sbuno.hxx> +#include "sbintern.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> +/** === end UNO includes === **/ +#include <svtools/ehdl.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/pathoptions.hxx> +#include <svtools/smplhint.hxx> +#include <vcl/svapp.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/urlobj.hxx> +#include <comphelper/stl_types.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/documentinfo.hxx> +#include <unotools/eventlisteneradapter.hxx> + +#ifndef INCLUDED_OSL_DOUBLECHECKEDLOCKING_H +#include <rtl/instance.hxx> +#endif + +#include <map> + +//........................................................................ +namespace basic +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::embed::XStorage; + using ::com::sun::star::script::XPersistentLibraryContainer; + using ::com::sun::star::uno::Any; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::document::XStorageBasedDocument; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::document::XEmbeddedScripts; + /** === end UNO using === **/ + + typedef BasicManager* BasicManagerPointer; + typedef ::std::map< Reference< XInterface >, BasicManagerPointer, ::comphelper::OInterfaceCompare< XInterface > > BasicManagerStore; + + typedef ::std::vector< BasicManagerCreationListener* > CreationListeners; + + //==================================================================== + //= BasicManagerCleaner + //==================================================================== + /// is the only instance which is allowed to delete a BasicManager instance + class BasicManagerCleaner + { + public: + static void deleteBasicManager( BasicManager*& _rpManager ) + { + delete _rpManager; + _rpManager = NULL; + } + }; + + //==================================================================== + //= ImplRepository + //==================================================================== + class ImplRepository : public ::utl::OEventListenerAdapter, public SfxListener + { + private: + friend struct CreateImplRepository; + ImplRepository(); + + private: + ::osl::Mutex m_aMutex; + BasicManagerStore m_aStore; + CreationListeners m_aCreationListeners; + + public: + static ImplRepository& Instance(); + + BasicManager* getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel ); + BasicManager* getApplicationBasicManager( bool _bCreate ); + void setApplicationBasicManager( BasicManager* _pBasicManager ); + void registerCreationListener( BasicManagerCreationListener& _rListener ); + void revokeCreationListener( BasicManagerCreationListener& _rListener ); + + private: + /** retrieves the location at which the BasicManager for the given model + is stored. + + If previously, the BasicManager for this model has never been requested, + then the model is added to the map, with an initial NULL BasicManager. + + @param _rxDocumentModel + the model whose BasicManager's location is to be retrieved. Must not be <NULL/>. + + @precond + our mutex is locked + */ + BasicManagerPointer& + impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel ); + + /** creates a new BasicManager instance for the given model + */ + BasicManagerPointer + impl_createManagerForModel( const Reference< XModel >& _rxDocumentModel ); + + /** creates the application-wide BasicManager + */ + BasicManagerPointer impl_createApplicationBasicManager(); + + /** notifies all listeners which expressed interest in the creation of BasicManager instances. + */ + void impl_notifyCreationListeners( + const Reference< XModel >& _rxDocumentModel, + BasicManager& _rManager + ); + + /** retrieves the current storage of a given document + + @param _rxDocument + the document whose storage is to be retrieved. + + @param _out_rStorage + takes the storage upon successful return. Note that this might be <NULL/> even + if <TRUE/> is returned. In this case, the document has not yet been saved. + + @return + <TRUE/> if the storage could be successfully retrieved (in which case + <arg>_out_rStorage</arg> might or might not be <NULL/>), <FALSE/> otherwise. + In the latter case, processing this document should stop. + */ + bool impl_getDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, Reference< XStorage >& _out_rStorage ); + + /** retrieves the containers for Basic and Dialog libraries for a given document + + @param _rxDocument + the document whose containers are to be retrieved. + + @param _out_rxBasicLibraries + takes the basic library container upon successful return + + @param _out_rxDialogLibraries + takes the dialog library container upon successful return + + @return + <TRUE/> if and only if both containers exist, and could successfully be retrieved + */ + bool impl_getDocumentLibraryContainers_nothrow( + const Reference< XModel >& _rxDocument, + Reference< XPersistentLibraryContainer >& _out_rxBasicLibraries, + Reference< XPersistentLibraryContainer >& _out_rxDialogLibraries + ); + + /** initializes the given library containers, which belong to a document + */ + void impl_initDocLibraryContainers_nothrow( + const Reference< XPersistentLibraryContainer >& _rxBasicLibraries, + const Reference< XPersistentLibraryContainer >& _rxDialogLibraries + ); + + // OEventListenerAdapter overridables + virtual void _disposing( const ::com::sun::star::lang::EventObject& _rSource ); + + // SfxListener overridables + virtual void Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ); + + /** removes the Model/BasicManager pair given by iterator from our store + */ + void impl_removeFromRepository( BasicManagerStore::iterator _pos ); + + private: + StarBASIC* impl_getDefaultAppBasicLibrary(); + }; + + //==================================================================== + //= CreateImplRepository + //==================================================================== + struct CreateImplRepository + { + ImplRepository* operator()() + { + static ImplRepository* pRepository = new ImplRepository; + return pRepository; + } + }; + + + //==================================================================== + //= ImplRepository + //==================================================================== + //-------------------------------------------------------------------- + ImplRepository::ImplRepository() + { + } + + //-------------------------------------------------------------------- + ImplRepository& ImplRepository::Instance() + { + return *rtl_Instance< ImplRepository, CreateImplRepository, ::osl::MutexGuard, ::osl::GetGlobalMutex >:: + create( CreateImplRepository(), ::osl::GetGlobalMutex() ); + } + + //-------------------------------------------------------------------- + BasicManager* ImplRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + BasicManagerPointer& pBasicManager = impl_getLocationForModel( _rxDocumentModel ); + if ( pBasicManager == NULL ) + pBasicManager = impl_createManagerForModel( _rxDocumentModel ); + + return pBasicManager; + } + + //-------------------------------------------------------------------- + BasicManager* ImplRepository::getApplicationBasicManager( bool _bCreate ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + BasicManager* pAppManager = GetSbData()->pAppBasMgr; + if ( ( pAppManager == NULL ) && _bCreate ) + pAppManager = impl_createApplicationBasicManager(); + + return pAppManager; + } + + //-------------------------------------------------------------------- + void ImplRepository::setApplicationBasicManager( BasicManager* _pBasicManager ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + BasicManager* pPreviousManager = getApplicationBasicManager( false ); + BasicManagerCleaner::deleteBasicManager( pPreviousManager ); + + GetSbData()->pAppBasMgr = _pBasicManager; + } + + //-------------------------------------------------------------------- + BasicManager* ImplRepository::impl_createApplicationBasicManager() + { + ::osl::MutexGuard aGuard( m_aMutex ); + OSL_PRECOND( getApplicationBasicManager( false ) == NULL, "ImplRepository::impl_createApplicationBasicManager: there already is one!" ); + + // Determine Directory + SvtPathOptions aPathCFG; + String aAppBasicDir( aPathCFG.GetBasicPath() ); + if ( !aAppBasicDir.Len() ) + aPathCFG.SetBasicPath( String::CreateFromAscii("$(prog)") ); + + // #58293# soffice.new search only in user dir => first dir + String aAppFirstBasicDir = aAppBasicDir.GetToken(1); + + // Create basic and load it + // MT: #47347# AppBasicDir is now a PATH + INetURLObject aAppBasic( SvtPathOptions().SubstituteVariable( String::CreateFromAscii("$(progurl)") ) ); + aAppBasic.insertName( Application::GetAppName() ); + + BasicManager* pBasicManager = new BasicManager( new StarBASIC, &aAppBasicDir ); + setApplicationBasicManager( pBasicManager ); + + // Als Destination das erste Dir im Pfad: + String aFileName( aAppBasic.getName() ); + aAppBasic = INetURLObject( aAppBasicDir.GetToken(1) ); + DBG_ASSERT( aAppBasic.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + aAppBasic.insertName( aFileName ); + pBasicManager->SetStorageName( aAppBasic.PathToFileName() ); + + // Basic container + SfxScriptLibraryContainer* pBasicCont = new SfxScriptLibraryContainer( Reference< XStorage >() ); + Reference< XPersistentLibraryContainer > xBasicCont( pBasicCont ); + pBasicCont->setBasicManager( pBasicManager ); + + // Dialog container + SfxDialogLibraryContainer* pDialogCont = new SfxDialogLibraryContainer( Reference< XStorage >() ); + Reference< XPersistentLibraryContainer > xDialogCont( pDialogCont ); + + LibraryContainerInfo aInfo( xBasicCont, xDialogCont, static_cast< OldBasicPassword* >( pBasicCont ) ); + pBasicManager->SetLibraryContainerInfo( aInfo ); + + // global constants + + // StarDesktop + Reference< XMultiServiceFactory > xSMgr = ::comphelper::getProcessServiceFactory(); + pBasicManager->SetGlobalUNOConstant( + "StarDesktop", + makeAny( xSMgr->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ) ) + ); + + // (BasicLibraries and DialogLibraries have automatically been added in SetLibraryContainerInfo) + + // notify + impl_notifyCreationListeners( NULL, *pBasicManager ); + + // outta here + return pBasicManager; + } + + //-------------------------------------------------------------------- + void ImplRepository::registerCreationListener( BasicManagerCreationListener& _rListener ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_aCreationListeners.push_back( &_rListener ); + } + + //-------------------------------------------------------------------- + void ImplRepository::revokeCreationListener( BasicManagerCreationListener& _rListener ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + CreationListeners::iterator pos = ::std::find( m_aCreationListeners.begin(), m_aCreationListeners.end(), &_rListener ); + if ( pos != m_aCreationListeners.end() ) + m_aCreationListeners.erase( pos ); + else { + DBG_ERROR( "ImplRepository::revokeCreationListener: listener is not registered!" ); + } + } + + //-------------------------------------------------------------------- + void ImplRepository::impl_notifyCreationListeners( const Reference< XModel >& _rxDocumentModel, BasicManager& _rManager ) + { + for ( CreationListeners::const_iterator loop = m_aCreationListeners.begin(); + loop != m_aCreationListeners.end(); + ++loop + ) + { + (*loop)->onBasicManagerCreated( _rxDocumentModel, _rManager ); + } + } + + //-------------------------------------------------------------------- + StarBASIC* ImplRepository::impl_getDefaultAppBasicLibrary() + { + BasicManager* pAppManager = getApplicationBasicManager( true ); + + StarBASIC* pAppBasic = pAppManager ? pAppManager->GetLib(0) : NULL; + DBG_ASSERT( pAppBasic != NULL, "impl_getApplicationBasic: unable to determine the default application's Basic library!" ); + return pAppBasic; + } + + //-------------------------------------------------------------------- + BasicManagerPointer& ImplRepository::impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel ) + { + Reference< XInterface > xNormalized( _rxDocumentModel, UNO_QUERY ); + DBG_ASSERT( xNormalized.is(), "ImplRepository::impl_getLocationForModel: invalid model!" ); + + BasicManagerPointer& location = m_aStore[ xNormalized ]; + return location; + } + + //-------------------------------------------------------------------- + void ImplRepository::impl_initDocLibraryContainers_nothrow( const Reference< XPersistentLibraryContainer >& _rxBasicLibraries, const Reference< XPersistentLibraryContainer >& _rxDialogLibraries ) + { + OSL_PRECOND( _rxBasicLibraries.is() && _rxDialogLibraries.is(), + "ImplRepository::impl_initDocLibraryContainers_nothrow: illegal library containers, this will crash!" ); + + try + { + // ensure there's a standard library in the basic container + ::rtl::OUString aStdLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( !_rxBasicLibraries->hasByName( aStdLibName ) ) + _rxBasicLibraries->createLibrary( aStdLibName ); + // as well as in the dialog container + if ( !_rxDialogLibraries->hasByName( aStdLibName ) ) + _rxDialogLibraries->createLibrary( aStdLibName ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + BasicManagerPointer ImplRepository::impl_createManagerForModel( const Reference< XModel >& _rxDocumentModel ) + { + StarBASIC* pAppBasic = impl_getDefaultAppBasicLibrary(); + + BasicManager* pBasicManager( NULL ); + Reference< XStorage > xStorage; + if ( !impl_getDocumentStorage_nothrow( _rxDocumentModel, xStorage ) ) + // the document is not able to provide the storage it is based on. + return pBasicManager; + + Reference< XPersistentLibraryContainer > xBasicLibs; + Reference< XPersistentLibraryContainer > xDialogLibs; + if ( !impl_getDocumentLibraryContainers_nothrow( _rxDocumentModel, xBasicLibs, xDialogLibs ) ) + // the document does not have BasicLibraries and DialogLibraries + return pBasicManager; + + if ( xStorage.is() ) + { + // load BASIC-manager + SfxErrorContext aErrContext( ERRCTX_SFX_LOADBASIC, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocumentModel ) ); + String aAppBasicDir = SvtPathOptions().GetBasicPath(); + + // Storage and BaseURL are only needed by binary documents! + SotStorageRef xDummyStor = new SotStorage( ::rtl::OUString() ); + pBasicManager = new BasicManager( *xDummyStor, String() /* TODO/LATER: xStorage */, + pAppBasic, + &aAppBasicDir, TRUE ); + if ( pBasicManager->HasErrors() ) + { + // handle errors + BasicError* pErr = pBasicManager->GetFirstError(); + while ( pErr ) + { + // show message to user + if ( ERRCODE_BUTTON_CANCEL == ErrorHandler::HandleError( pErr->GetErrorId() ) ) + { + // user wants to break loading of BASIC-manager + BasicManagerCleaner::deleteBasicManager( pBasicManager ); + xStorage.clear(); + break; + } + pErr = pBasicManager->GetNextError(); + } + } + } + + // not loaded? + if ( !xStorage.is() ) + { + // create new BASIC-manager + StarBASIC* pBasic = new StarBASIC( pAppBasic ); + pBasic->SetFlag( SBX_EXTSEARCH ); + pBasicManager = new BasicManager( pBasic, NULL, TRUE ); + } + + // knit the containers with the BasicManager + LibraryContainerInfo aInfo( xBasicLibs, xDialogLibs, dynamic_cast< OldBasicPassword* >( xBasicLibs.get() ) ); + OSL_ENSURE( aInfo.mpOldBasicPassword, "ImplRepository::impl_createManagerForModel: wrong BasicLibraries implementation!" ); + pBasicManager->SetLibraryContainerInfo( aInfo ); + //pBasicCont->setBasicManager( pBasicManager ); + // that's not needed anymore today. The containers will retrieve their associated + // BasicManager from the BasicManagerRepository, when needed. + + // initialize the containers + impl_initDocLibraryContainers_nothrow( xBasicLibs, xDialogLibs ); + + // damit auch Dialoge etc. 'qualifiziert' angesprochen werden k"onnen + pBasicManager->GetLib(0)->SetParent( pAppBasic ); + + // global properties in the document's Basic + pBasicManager->SetGlobalUNOConstant( "ThisComponent", makeAny( _rxDocumentModel ) ); + + // notify + impl_notifyCreationListeners( _rxDocumentModel, *pBasicManager ); + + // register as listener for this model being disposed/closed + Reference< XComponent > xDocumentComponent( _rxDocumentModel, UNO_QUERY ); + OSL_ENSURE( xDocumentComponent.is(), "ImplRepository::impl_createManagerForModel: the document must be an XComponent!" ); + startComponentListening( xDocumentComponent ); + + // register as listener for the BasicManager being destroyed + StartListening( *pBasicManager ); + + return pBasicManager; + } + + //-------------------------------------------------------------------- + bool ImplRepository::impl_getDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, Reference< XStorage >& _out_rStorage ) + { + _out_rStorage.clear(); + try + { + Reference< XStorageBasedDocument > xStorDoc( _rxDocument, UNO_QUERY_THROW ); + _out_rStorage.set( xStorDoc->getDocumentStorage() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return false; + } + return true; + } + + //-------------------------------------------------------------------- + bool ImplRepository::impl_getDocumentLibraryContainers_nothrow( const Reference< XModel >& _rxDocument, + Reference< XPersistentLibraryContainer >& _out_rxBasicLibraries, Reference< XPersistentLibraryContainer >& _out_rxDialogLibraries ) + { + _out_rxBasicLibraries.clear(); + _out_rxDialogLibraries.clear(); + try + { + Reference< XEmbeddedScripts > xScripts( _rxDocument, UNO_QUERY_THROW ); + _out_rxBasicLibraries.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW ); + _out_rxDialogLibraries.set( xScripts->getDialogLibraries(), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return _out_rxBasicLibraries.is() && _out_rxDialogLibraries.is(); + } + + //-------------------------------------------------------------------- + void ImplRepository::impl_removeFromRepository( BasicManagerStore::iterator _pos ) + { + OSL_PRECOND( _pos != m_aStore.end(), "ImplRepository::impl_removeFromRepository: invalid position!" ); + + BasicManager* pManager = _pos->second; + + // *first* remove from map (else Notify won't work properly) + m_aStore.erase( _pos ); + + // *then* delete the BasicManager + EndListening( *pManager ); + BasicManagerCleaner::deleteBasicManager( pManager ); + } + + //-------------------------------------------------------------------- + void ImplRepository::_disposing( const ::com::sun::star::lang::EventObject& _rSource ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Reference< XInterface > xNormalizedSource( _rSource.Source, UNO_QUERY ); + #if OSL_DEBUG_LEVEL > 0 + bool bFound = false; + #endif + + for ( BasicManagerStore::iterator loop = m_aStore.begin(); + loop != m_aStore.end(); + ++loop + ) + { + if ( loop->first.get() == xNormalizedSource.get() ) + { + impl_removeFromRepository( loop ); + #if OSL_DEBUG_LEVEL > 0 + bFound = true; + #endif + break; + } + } + + OSL_ENSURE( bFound, "ImplRepository::_disposing: where does this come from?" ); + } + + //-------------------------------------------------------------------- + void ImplRepository::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ) + { + const SfxSimpleHint* pSimpleHint = dynamic_cast< const SfxSimpleHint* >( &_rHint ); + if ( !pSimpleHint || ( pSimpleHint->GetId() != SFX_HINT_DYING ) ) + // not interested in + return; + + BasicManager* pManager = dynamic_cast< BasicManager* >( &_rBC ); + OSL_ENSURE( pManager, "ImplRepository::Notify: where does this come from?" ); + + for ( BasicManagerStore::iterator loop = m_aStore.begin(); + loop != m_aStore.end(); + ++loop + ) + { + if ( loop->second == pManager ) + { + // a BasicManager which is still in our repository is being deleted. + // That's bad, since by definition, we *own* all instances in our + // repository. + OSL_ENSURE( false, "ImplRepository::Notify: nobody should tamper with the managers, except ourself!" ); + m_aStore.erase( loop ); + break; + } + } + } + + //==================================================================== + //= BasicManagerRepository + //==================================================================== + //-------------------------------------------------------------------- + BasicManager* BasicManagerRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel ) + { + return ImplRepository::Instance().getDocumentBasicManager( _rxDocumentModel ); + } + + //-------------------------------------------------------------------- + BasicManager* BasicManagerRepository::getApplicationBasicManager( bool _bCreate ) + { + return ImplRepository::Instance().getApplicationBasicManager( _bCreate ); + } + + //-------------------------------------------------------------------- + void BasicManagerRepository::resetApplicationBasicManager() + { + return ImplRepository::Instance().setApplicationBasicManager( NULL ); + } + + //-------------------------------------------------------------------- + void BasicManagerRepository::registerCreationListener( BasicManagerCreationListener& _rListener ) + { + ImplRepository::Instance().registerCreationListener( _rListener ); + } + + //-------------------------------------------------------------------- + void BasicManagerRepository::revokeCreationListener( BasicManagerCreationListener& _rListener ) + { + ImplRepository::Instance().revokeCreationListener( _rListener ); + } + +//........................................................................ +} // namespace basic +//........................................................................ + diff --git a/basic/source/basmgr/basmgr.cxx b/basic/source/basmgr/basmgr.cxx new file mode 100644 index 000000000000..2620852370b1 --- /dev/null +++ b/basic/source/basmgr/basmgr.cxx @@ -0,0 +1,2473 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basmgr.cxx,v $ + * $Revision: 1.45 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <sot/storage.hxx> +#include <tools/urlobj.hxx> +#include <svtools/smplhint.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/msgbox.hxx> +#include <basic/sbx.hxx> +#include <sot/storinfo.hxx> +#include <svtools/pathoptions.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <basic/sbmod.hxx> + +#include <basic/sbuno.hxx> +#include <basic/basmgr.hxx> +#include <sbunoobj.hxx> +#include "basrid.hxx" +#include "sbintern.hxx" +#include <sb.hrc> + + +#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 <com/sun/star/script/XLibraryContainerPassword.hpp> + +#include <cppuhelper/implbase1.hxx> + +using com::sun::star::uno::Reference; +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; + +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( String::CreateFromAscii(szBasicStorage) ); +static const String ManagerStreamName( String::CreateFromAscii(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 maContainerInfo; + + // Save stream data + SvMemoryStream* mpManagerStream; + SvMemoryStream** mppLibStreams; + sal_Int32 mnLibStreamCount; + sal_Bool mbModifiedByLibraryContainer; + sal_Bool mbError; + + BasicManagerImpl( void ) + : mpManagerStream( NULL ) + , mppLibStreams( NULL ) + , mnLibStreamCount( 0 ) + , mbModifiedByLibraryContainer( sal_False ) + , mbError( sal_False ) + {} + ~BasicManagerImpl(); +}; + +BasicManagerImpl::~BasicManagerImpl() +{ + 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; + ::rtl::OUString maLibName; // empty -> no lib, but lib container + +public: + BasMgrContainerListenerImpl( BasicManager* pMgr, ::rtl::OUString aLibName ) + : mpMgr( pMgr ) + , maLibName( aLibName ) {} + + static void insertLibraryImpl( const Reference< XLibraryContainer >& xScriptCont, BasicManager* pMgr, + Any aLibAny, ::rtl::OUString aLibName ); + static void addLibraryModulesImpl( BasicManager* pMgr, Reference< XNameAccess > xLibNameAccess, + ::rtl::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, ::rtl::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, ::rtl::OUString aLibName ) +{ + Sequence< ::rtl::OUString > aModuleNames = xLibNameAccess->getElementNames(); + sal_Int32 nModuleCount = aModuleNames.getLength(); + + StarBASIC* pLib = pMgr->GetLib( aLibName ); + DBG_ASSERT( pLib, "BasMgrContainerListenerImpl::addLibraryModulesImpl: Unknown lib!"); + if( pLib ) + { + const ::rtl::OUString* pNames = aModuleNames.getConstArray(); + for( sal_Int32 j = 0 ; j < nModuleCount ; j++ ) + { + ::rtl::OUString aModuleName = pNames[ j ]; + Any aElement = xLibNameAccess->getByName( aModuleName ); + ::rtl::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 ); + ::rtl::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 + { + ::rtl::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 ) +{ + ::rtl::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 ); + ::rtl::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 ) +{ + ::rtl::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() +{ + nErrorId = 0; + nReason = 0; +} + +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 is sufficient, unique at runtime + String aRelStorageName; + String aPassword; + + BOOL bDoLoad; + BOOL bReference; + BOOL bPasswordVerified; + BOOL bFoundInPath; // Must not relativated again! + + // Lib represents library in new UNO library container + Reference< XLibraryContainer > mxScriptCont; + +public: + BasicLibInfo(); + BasicLibInfo( const String& rStorageName ); + + 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; } + + // Only temporary for Load/Save + 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; // TODO: Should be member of manager, but currently not incompatible +}; + +BasicLibInfo::BasicLibInfo() +{ + bReference = FALSE; + bPasswordVerified = FALSE; + bDoLoad = FALSE; + bFoundInPath = FALSE; + mxScriptCont = NULL; + aStorageName = String::CreateFromAscii(szImbedded); + aRelStorageName = String::CreateFromAscii(szImbedded); +} + +BasicLibInfo::BasicLibInfo( const String& rStorageName ) +{ + bReference = TRUE; + bPasswordVerified = FALSE; + bDoLoad = FALSE; + mxScriptCont = NULL; + aStorageName = rStorageName; +} + +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"); + + // If not set initialize StorageName + if ( aStorageName.Len() == 0 ) + aStorageName = aCurStorageName; + + // Load again? + BOOL bDoLoad_ = xLib.Is(); + if ( bUseOldReloadInfo ) + bDoLoad_ = DoLoad(); + rSStream << bDoLoad_; + + // The name of the lib... + rSStream.WriteByteString(GetLibName()); + + // Absolute path... + 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 ); + + // Relative path... + if ( ( aStorageName == aCurStorageName ) || ( aStorageName.EqualsAscii(szImbedded) ) ) + rSStream.WriteByteString( szImbedded ); + else + { + // Do not determine the relative path if the file was only found in path: + // because the relative path would change and after moving the lib the + // the file cannot be found. + if ( !IsFoundInPath() ) + CalcRelStorageName( aCurStorageName ); + rSStream.WriteByteString(aRelStorageName); + } + + // ------------------------------ + // Version 2 + // ------------------------------ + + // reference... + rSStream << bReference; + + // ------------------------------ + // End + // ------------------------------ + + 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 ) + { + // Reload? + BOOL bDoLoad; + rSStream >> bDoLoad; + pInfo->bDoLoad = bDoLoad; + + // The name of the lib... + String aName; + rSStream.ReadByteString(aName); + pInfo->SetLibName( aName ); + + // Absolute path... + String aStorageName; + rSStream.ReadByteString(aStorageName); + pInfo->SetStorageName( aStorageName ); + + // Relative path... + 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, BOOL bDocMgr ) : mbDocMgr( bDocMgr ) +{ + 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"); + + // If there is no Manager Stream, no further actions are necessary + if ( rStorage.IsStream( ManagerStreamName ) ) + { + LoadBasicManager( rStorage, rBaseURL ); + // StdLib contains Parent: + StarBASIC* pStdLib = GetStdLib(); + DBG_ASSERT( pStdLib, "Standard-Lib not loaded?" ); + if ( !pStdLib ) + { + // Should never happen, but if it happens we wont crash... + pStdLib = new StarBASIC( NULL, mbDocMgr ); + 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 ); + // The other get StdLib as parent: + for ( USHORT nBasic = 1; nBasic < GetLibCount(); nBasic++ ) + { + StarBASIC* pBasic = GetLib( nBasic ); + if ( pBasic ) + { +// pBasic->SetParent( pStdLib ); + pStdLib->Insert( pBasic ); + pBasic->SetFlag( SBX_EXTSEARCH ); + } + } + // Modified through insert + 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, const LibraryContainerInfo& rInfo ) +{ + Reference< XLibraryContainer > xScriptCont( rInfo.mxScriptCont.get() ); + if ( !xScriptCont.is() ) + return; + + String aLibName = pBasic->GetName(); + if( !xScriptCont->hasByName( aLibName ) ) + xScriptCont->createLibrary( aLibName ); + + Any aLibAny = xScriptCont->getByName( aLibName ); + Reference< XNameContainer > xLib; + aLibAny >>= xLib; + if ( !xLib.is() ) + return; + + 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 ) ) + { + ::rtl::OUString aSource = pModule->GetSource32(); + Any aSourceAny; + aSourceAny <<= aSource; + xLib->insertByName( aModName, aSourceAny ); + } + } +} + +const Reference< XPersistentLibraryContainer >& BasicManager::GetDialogLibraryContainer() const +{ + return mpImpl->maContainerInfo.mxDialogCont; +} + +const Reference< XPersistentLibraryContainer >& BasicManager::GetScriptLibraryContainer() const +{ + return mpImpl->maContainerInfo.mxScriptCont; +} + +void BasicManager::SetLibraryContainerInfo( const LibraryContainerInfo& rInfo ) +{ + mpImpl->maContainerInfo = rInfo; + + Reference< XLibraryContainer > xScriptCont( mpImpl->maContainerInfo.mxScriptCont.get() ); + StarBASIC* pStdLib = GetStdLib(); + String aLibName = pStdLib->GetName(); + if( xScriptCont.is() ) + { + // Register listener for lib container + ::rtl::OUString aEmptyLibName; + Reference< XContainerListener > xLibContainerListener + = static_cast< XContainerListener* > + ( new BasMgrContainerListenerImpl( this, aEmptyLibName ) ); + + Reference< XContainer> xLibContainer( xScriptCont, UNO_QUERY ); + xLibContainer->addContainerListener( xLibContainerListener ); + + Sequence< ::rtl::OUString > aScriptLibNames = xScriptCont->getElementNames(); + const ::rtl::OUString* pScriptLibName = aScriptLibNames.getConstArray(); + sal_Int32 i, nNameCount = aScriptLibNames.getLength(); + + if( nNameCount ) + { + for( i = 0 ; i < nNameCount ; ++i, ++pScriptLibName ) + { + Any aLibAny = xScriptCont->getByName( *pScriptLibName ); + + if ( pScriptLibName->equalsAscii( "Standard" ) ) + xScriptCont->loadLibrary( *pScriptLibName ); + + BasMgrContainerListenerImpl::insertLibraryImpl + ( xScriptCont, this, aLibAny, *pScriptLibName ); + } + } + 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->maContainerInfo ); + if( pBasLibInfo->HasPassword() ) + { + OldBasicPassword* pOldBasicPassword = + mpImpl->maContainerInfo.mpOldBasicPassword; + if( pOldBasicPassword ) + { + pOldBasicPassword->setLibraryPassword + ( pLib->GetName(), pBasLibInfo->GetPassword() ); + pBasLibInfo->SetPasswordVerified(); + } + } + } + } + + mpImpl->mbModifiedByLibraryContainer = sal_False; + } + } + + SetGlobalUNOConstant( "BasicLibraries", makeAny( mpImpl->maContainerInfo.mxScriptCont ) ); + SetGlobalUNOConstant( "DialogLibraries", makeAny( mpImpl->maContainerInfo.mxDialogCont ) ); +} + +BasicManager::BasicManager( StarBASIC* pSLib, String* pLibPath, BOOL bDocMgr ) : mbDocMgr( bDocMgr ) +{ + DBG_CTOR( BasicManager, 0 ); + Init(); + DBG_ASSERT( pSLib, "BasicManager cannot be created with a NULL-Pointer!" ); + + 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 ); + + // Save is only necessary if basic has changed + xStdLib->SetModified( FALSE ); + bBasMgrModified = FALSE; +} + +BasicManager::BasicManager() +{ + DBG_CTOR( BasicManager, 0 ); + // This ctor may only be used to adapt relative paths for 'Save As'. + // There is no AppBasic so libs must not be loaded... + Init(); +} + +void BasicManager::ImpMgrNotLoaded( const String& rStorageName ) +{ + // pErrInf is only destroyed if the error os processed by an + // ErrorHandler + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_MGROPEN, rStorageName, ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_OPENMGRSTREAM, rStorageName ) ); + + // Create a stdlib otherwise we crash! + BasicLibInfo* pStdLibInfo = CreateLibInfo(); + pStdLibInfo->SetLib( new StarBASIC( NULL, mbDocMgr ) ); + 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, mbDocMgr ); + 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; // for relative paths, can be modified through BaseURL + + // If loaded from template, only BaseURL is used: + //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 defect!" ); + return; + } + for ( USHORT nL = 0; nL < nLibs; nL++ ) + { + BasicLibInfo* pInfo = BasicLibInfo::Create( *xManagerStream ); + + // Correct absolute pathname if relative is existing. + // Always try relative first if there are two stands on disk + 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() ) + { + // Search lib in path + 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 from external files should be loaded only when necessary. + // But references are loaded at once, otherwise some big customers get into trouble + 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 as separator + String aLibs; + xManagerStream->ReadByteString(aLibs); + xManagerStream->SetBufferSize( 0 ); + xManagerStream.Clear(); // Close stream + + 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 ) ); + // TODO: Remove == 2 + 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 ); + + // Notify listener if something needs to be saved + Broadcast( SfxSimpleHint( SFX_HINT_DYING) ); + + // Destroy Basic-Infos... + // In reverse order + 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::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; + // The current must not be opened again... + 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 the Basic-Storage every lib is in a 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(), mbDocMgr ) ); + 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 + { + // Skip Basic... + 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 + { + // Perhaps there are additional information in the 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() ); + } + 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 ) + { + // Should only be the case for encrypted Streams + bProtected = TRUE; + rStrm.SetKey( szCryptingKey ); + rStrm.RefreshBuffer(); + } + return bProtected; +} + +// This code is necessary to load the BASIC of Beta 1 +// TODO: Which Beta 1? +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; + // Use the Parent of the old BASICs + 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->maContainerInfo ); + +/* + 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 compile in referenced libs should not + // cause modified + 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(); + // Use original name otherwise ImpLoadLibary failes... + pLibInfo->SetLibName( rLibName ); + // Funktioniert so aber nicht, wenn Name doppelt +// USHORT nLibId = GetLibId( rLibName ); + USHORT nLibId = (USHORT) pLibs->GetPos( pLibInfo ); + + // Set StorageName before load because it is compared with pCurStorage + pLibInfo->SetStorageName( aStorageName ); + BOOL bLoaded = ImpLoadLibary( pLibInfo, &rStorage ); + + if ( bLoaded ) + { + if ( aNewLibName != rLibName ) + SetLibName( nLibId, aNewLibName ); + + if ( bReference ) + { + pLibInfo->GetLib()->SetModified( FALSE ); // Don't save in this case + pLibInfo->SetRelStorageName( String() ); +// pLibInfo->CalcRelStorageName( GetStorageName() ); + pLibInfo->IsReference() = TRUE; + } + else + { + pLibInfo->GetLib()->SetModified( TRUE ); // Must be saved after Add! + pLibInfo->SetStorageName( String::CreateFromAscii(szImbedded) ); // Save in BasicManager-Storage + } + 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 ) +{ + // Only pyhsical deletion if no reference + return RemoveLib( nLib, !IsReference( nLib ) ); +} + +BOOL BasicManager::RemoveLib( USHORT nLib, BOOL bDelBasicFromStorage ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + DBG_ASSERT( nLib, "Standard-Lib cannot be removed!" ); + + BasicLibInfo* pLibInfo = pLibs->GetObject( nLib ); + DBG_ASSERT( pLibInfo, "Lib not found!" ); + + 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; + } + + // If one of the streams cannot be opened, this is not an error, + // because BASIC was never written before... + 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(); + + // If no further stream available, + // delete the SubStorage. + SvStorageInfoList aInfoList( 0, 4 ); + xBasicStorage->FillInfoList( &aInfoList ); + if ( !aInfoList.Count() ) + { + xBasicStorage.Clear(); + xStorage->Remove( BasicStreamName ); + xStorage->Commit(); + // If no further Streams or SubStorages available, + // delete the Storage, too. + 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 was successful, del unimportant +} + +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 )// Check if available... + 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(); +} + +BOOL BasicManager::LoadLib( USHORT nLib ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BOOL bDone = FALSE; + BasicLibInfo* pLibInfo = pLibs->GetObject( nLib ); + DBG_ASSERT( pLibInfo, "Lib?!" ); + if ( pLibInfo ) + { + Reference< XLibraryContainer > xLibContainer = pLibInfo->GetLibraryContainer(); + if( xLibContainer.is() ) + { + String aLibName = pLibInfo->GetLibName(); + xLibContainer->loadLibrary( aLibName ); + bDone = xLibContainer->isLibraryLoaded( aLibName );; + } + else + { + bDone = ImpLoadLibary( pLibInfo, NULL, FALSE ); + StarBASIC* pLib = GetLib( nLib ); + if ( pLib ) + { + // pLib->SetParent( GetStdLib() ); + GetStdLib()->Insert( pLib ); + pLib->SetFlag( SBX_EXTSEARCH ); + } + } + } + else + { +// String aErrorText( BasicResId( IDS_SBERR_LIBLOAD ) ); +// aErrorText.SearchAndReplace( "XX", "" ); + StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD, String(), ERRCODE_BUTTON_OK ); + pErrorMgr->InsertError( BasicError( *pErrInf, BASERR_REASON_LIBNOTFOUND, String::CreateFromInt32(nLib) ) ); + } + return bDone; +} + +StarBASIC* BasicManager::CreateLib( const String& rLibName ) +{ + DBG_CHKTHIS( BasicManager, 0 ); + if ( GetLib( rLibName ) ) + return 0; + + BasicLibInfo* pLibInfo = CreateLibInfo(); + StarBASIC* pNew = new StarBASIC( GetStdLib(), mbDocMgr ); + 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(), mbDocMgr ); + 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; +} + + +BOOL BasicManager::IsModified() const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + if ( bBasMgrModified ) + return TRUE; + return IsBasicModified(); +} + +BOOL BasicManager::IsBasicModified() const +{ + DBG_CHKTHIS( BasicManager, 0 ); + + BasicLibInfo* pInf = pLibs->First(); + while ( pInf ) + { + if ( pInf->GetLib().Is() && pInf->GetLib()->IsModified() ) + return TRUE; + + pInf = pLibs->Next(); + } + return FALSE; +} + +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(); +} + +BasicError* BasicManager::GetFirstError() +{ + DBG_CHKTHIS( BasicManager, 0 ); + return pErrorMgr->GetFirstError(); +} + +BasicError* BasicManager::GetNextError() +{ + DBG_CHKTHIS( BasicManager, 0 ); + return pErrorMgr->GetNextError(); +} +bool BasicManager::GetGlobalUNOConstant( const sal_Char* _pAsciiName, ::com::sun::star::uno::Any& aOut ) +{ + bool bRes = false; + StarBASIC* pStandardLib = GetStdLib(); + OSL_PRECOND( pStandardLib, "BasicManager::SetGlobalUNOConstant: no lib to insert into!" ); + if ( pStandardLib ) + bRes = pStandardLib->GetUNOConstant( _pAsciiName, aOut ); + return bRes; +} + +Any BasicManager::SetGlobalUNOConstant( const sal_Char* _pAsciiName, const Any& _rValue ) +{ + Any aOldValue; + + StarBASIC* pStandardLib = GetStdLib(); + OSL_PRECOND( pStandardLib, "BasicManager::SetGlobalUNOConstant: no lib to insert into!" ); + if ( !pStandardLib ) + return aOldValue; + + ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); + + // obtain the old value + SbxVariable* pVariable = pStandardLib->Find( sVarName, SbxCLASS_OBJECT ); + if ( pVariable ) + aOldValue = sbxToUnoValue( pVariable ); + + SbxObjectRef xUnoObj = GetSbUnoObject( sVarName, _rValue ); + xUnoObj->SetFlag( SBX_DONTSTORE ); + pStandardLib->Insert( xUnoObj ); + + return aOldValue; +} + +bool BasicManager::LegacyPsswdBinaryLimitExceeded( ::com::sun::star::uno::Sequence< rtl::OUString >& _out_rModuleNames ) +{ + try + { + Reference< XNameAccess > xScripts( GetScriptLibraryContainer(), UNO_QUERY_THROW ); + Reference< XLibraryContainerPassword > xPassword( GetScriptLibraryContainer(), UNO_QUERY_THROW ); + + Sequence< ::rtl::OUString > aNames( xScripts->getElementNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength(); + for ( ; pNames != pNamesEnd; ++pNames ) + { + if( /*pLib->mbSharedIndexFile ||*/ !xPassword->isLibraryPasswordProtected( *pNames ) ) + continue; + + StarBASIC* pBasicLib = GetLib( *pNames ); + if ( !pBasicLib ) + continue; + + Reference< XNameAccess > xScriptLibrary( xScripts->getByName( *pNames ), UNO_QUERY_THROW ); + Sequence< ::rtl::OUString > aElementNames( xScriptLibrary->getElementNames() ); + sal_Int32 nLen = aElementNames.getLength(); + + Sequence< ::rtl::OUString > aBigModules( nLen ); + sal_Int32 nBigModules = 0; + + const ::rtl::OUString* pElementNames = aElementNames.getConstArray(); + const ::rtl::OUString* pElementNamesEnd = aElementNames.getConstArray() + aElementNames.getLength(); + for ( ; pElementNames != pElementNamesEnd; ++pElementNames ) + { + SbModule* pMod = pBasicLib->FindModule( *pElementNames ); + if ( pMod && pMod->ExceedsLegacyModuleSize() ) + aBigModules[ nBigModules++ ] = *pElementNames; + } + + if ( nBigModules ) + { + aBigModules.realloc( nBigModules ); + _out_rModuleNames = aBigModules; + return true; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return false; +} + +//===================================================================== + +class ModuleInfo_Impl : public ModuleInfoHelper +{ + ::rtl::OUString maName; + ::rtl::OUString maLanguage; + ::rtl::OUString maSource; + +public: + ModuleInfo_Impl( const ::rtl::OUString& aName, const ::rtl::OUString& aLanguage, const ::rtl::OUString& aSource ) + : maName( aName ), maLanguage( aLanguage), maSource( aSource ) {} + + // Methods XStarBasicModuleInfo + virtual ::rtl::OUString SAL_CALL getName() throw(RuntimeException) + { return maName; } + virtual ::rtl::OUString SAL_CALL getLanguage() throw(RuntimeException) + { return maLanguage; } + virtual ::rtl::OUString SAL_CALL getSource() throw(RuntimeException) + { return maSource; } +}; + + +//===================================================================== + +class DialogInfo_Impl : public DialogInfoHelper +{ + ::rtl::OUString maName; + Sequence< sal_Int8 > mData; + +public: + DialogInfo_Impl( const ::rtl::OUString& aName, Sequence< sal_Int8 > Data ) + : maName( aName ), mData( Data ) {} + + // Methods XStarBasicDialogInfo + virtual ::rtl::OUString SAL_CALL getName() throw(RuntimeException) + { return maName; } + virtual Sequence< sal_Int8 > SAL_CALL getData() throw(RuntimeException) + { return mData; } +}; + + +//===================================================================== + +class LibraryInfo_Impl : public LibraryInfoHelper +{ + ::rtl::OUString maName; + Reference< XNameContainer > mxModuleContainer; + Reference< XNameContainer > mxDialogContainer; + ::rtl::OUString maPassword; + ::rtl::OUString maExternaleSourceURL; + ::rtl::OUString maLinkTargetURL; + +public: + LibraryInfo_Impl + ( + const ::rtl::OUString& aName, + Reference< XNameContainer > xModuleContainer, + Reference< XNameContainer > xDialogContainer, + const ::rtl::OUString& aPassword, + const ::rtl::OUString& aExternaleSourceURL, + const ::rtl::OUString& aLinkTargetURL + ) + : maName( aName ) + , mxModuleContainer( xModuleContainer ) + , mxDialogContainer( xDialogContainer ) + , maPassword( aPassword ) + , maExternaleSourceURL( aExternaleSourceURL ) + , maLinkTargetURL( aLinkTargetURL ) + {} + + // Methods XStarBasicLibraryInfo + virtual ::rtl::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 ::rtl::OUString SAL_CALL getPassword() throw(RuntimeException) + { return maPassword; } + virtual ::rtl::OUString SAL_CALL getExternalSourceURL() throw(RuntimeException) + { return maExternaleSourceURL; } + virtual ::rtl::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 ::rtl::OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeByName( const ::rtl::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 ::rtl::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, ::rtl::OUString::createFromAscii( szScriptLanguage ), pMod->GetSource32() ); + Any aRetAny; + aRetAny <<= xMod; + return aRetAny; +} + +Sequence< ::rtl::OUString > ModuleContainer_Impl::getElementNames() + throw(RuntimeException) +{ + SbxArray* pMods = mpLib ? mpLib->GetModules() : NULL; + USHORT nMods = pMods ? pMods->Count() : 0; + Sequence< ::rtl::OUString > aRetSeq( nMods ); + ::rtl::OUString* pRetSeq = aRetSeq.getArray(); + for( USHORT i = 0 ; i < nMods ; i++ ) + { + SbxVariable* pMod = pMods->Get( i ); + pRetSeq[i] = ::rtl::OUString( pMod->GetName() ); + } + return aRetSeq; +} + +sal_Bool ModuleContainer_Impl::hasByName( const ::rtl::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 ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + removeByName( aName ); + insertByName( aName, aElement ); +} + + +// Methods XNameContainer +void ModuleContainer_Impl::insertByName( const ::rtl::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 ::rtl::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 ::rtl::OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeByName( const ::rtl::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 ::rtl::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< ::rtl::OUString > DialogContainer_Impl::getElementNames() + throw(RuntimeException) +{ + mpLib->GetAll( SbxCLASS_OBJECT ); + sal_Int16 nCount = mpLib->GetObjects()->Count(); + Sequence< ::rtl::OUString > aRetSeq( nCount ); + ::rtl::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 ] = ::rtl::OUString( pVar->GetName() ); + nDialogCounter++; + } + } + aRetSeq.realloc( nDialogCounter ); + return aRetSeq; +} + +sal_Bool DialogContainer_Impl::hasByName( const ::rtl::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 ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + removeByName( aName ); + insertByName( aName, aElement ); +} + + +// Methods XNameContainer +void DialogContainer_Impl::insertByName( const ::rtl::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 ::rtl::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 ::rtl::OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeByName( const ::rtl::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 ::rtl::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 ); + + ::rtl::OUString aPassword = pLibInfo->GetPassword(); + + // TODO Only provide extern info! + ::rtl::OUString aExternaleSourceURL; + ::rtl::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< ::rtl::OUString > LibraryContainer_Impl::getElementNames() + throw(RuntimeException) +{ + USHORT nLibs = mpMgr->GetLibCount(); + Sequence< ::rtl::OUString > aRetSeq( nLibs ); + ::rtl::OUString* pRetSeq = aRetSeq.getArray(); + for( USHORT i = 0 ; i < nLibs ; i++ ) + { + pRetSeq[i] = ::rtl::OUString( mpMgr->GetLibName( i ) ); + } + return aRetSeq; +} + +sal_Bool LibraryContainer_Impl::hasByName( const ::rtl::OUString& aName ) + throw(RuntimeException) +{ + sal_Bool bRet = mpMgr->HasLib( aName ); + return bRet; +} + +// Methods XNameReplace +void LibraryContainer_Impl::replaceByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + removeByName( aName ); + insertByName( aName, aElement ); +} + +// Methods XNameContainer +void LibraryContainer_Impl::insertByName( const ::rtl::OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + (void)aName; + (void)aElement; + // TODO: Insert a complete Library?! +} + +void LibraryContainer_Impl::removeByName( const ::rtl::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 ::rtl::OUString& LibName, const ::rtl::OUString& Password, + const ::rtl::OUString& ExternalSourceURL, const ::rtl::OUString& LinkTargetURL ) + throw(ElementExistException, RuntimeException); + virtual void SAL_CALL addModule( const ::rtl::OUString& LibraryName, const ::rtl::OUString& ModuleName, + const ::rtl::OUString& Language, const ::rtl::OUString& Source ) + throw(NoSuchElementException, RuntimeException); + virtual void SAL_CALL addDialog( const ::rtl::OUString& LibraryName, const ::rtl::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 ::rtl::OUString& LibName, + const ::rtl::OUString& Password, + const ::rtl::OUString& ExternalSourceURL, + const ::rtl::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 ::rtl::OUString& LibraryName, + const ::rtl::OUString& ModuleName, + const ::rtl::OUString& Language, + const ::rtl::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 ::rtl::OUString& LibraryName, + const ::rtl::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; +} + diff --git a/basic/source/basmgr/makefile.mk b/basic/source/basmgr/makefile.mk new file mode 100644 index 000000000000..4252099d2603 --- /dev/null +++ b/basic/source/basmgr/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.9 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=basic +TARGET=basicmgr +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + + +# --- Allgemein ----------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/basmgr.obj \ + $(SLO)$/basicmanagerrepository.obj + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/basic/source/classes/disas.cxx b/basic/source/classes/disas.cxx new file mode 100644 index 000000000000..783e7ae98b6d --- /dev/null +++ b/basic/source/classes/disas.cxx @@ -0,0 +1,667 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: disas.cxx,v $ + * $Revision: 1.28 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdio.h> +#include <string.h> +#include <tools/stream.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include "iosys.hxx" +#include "disas.hxx" + + +static const char* pOp1[] = { + "NOP", + + // Operators + // the following operators have the same order as in + // enum SbxVarOp + "EXP", "MUL", "DIV", "MOD", "PLUS", "MINUS", "NEG", + "EQ", "NE", "LT", "GT", "LE", "GE", + "IDIV", "AND", "OR", "XOR", "EQV", "IMP", "NOT", + "CAT", + // End enum SbxVarOp + "LIKE", "IS", + // Load/Store + "ARGC", // Create new Argv + "ARGV", // TOS ==> current Argv + "INPUT", // Input ==> TOS + "LINPUT", // Line Input ==> TOS + "GET", // get TOS + "SET", // Save Object TOS ==> TOS-1 + "PUT", // TOS ==> TOS-1 + "CONST", // TOS ==> TOS-1, then ReadOnly + "DIM", // DIM + "REDIM", // REDIM + "REDIMP", // REDIM PRESERVE + "ERASE", // delete TOS + // Branch + "STOP", // End of program + "INITFOR", // FOR-Variable init + "NEXT", // FOR-Variable increment + "CASE", // Begin CASE + "ENDCASE", // End CASE + "STDERR", // Default error handling + "NOERROR", // No error handling + "LEAVE", // leave UP + // I/O + "CHANNEL", // TOS = Channelnumber + "PRINT", // print TOS + "PRINTF", // print TOS in field + "WRITE", // write TOS + "RENAME", // Rename Tos+1 to Tos + "PROMPT", // TOS = Prompt for Input + "RESTART", // Define restart point + "STDIO", // Switch to I/O channel 0 + // Misc + "EMPTY", // Empty statement to stack + "ERROR", // TOS = error code + "LSET", // Save object TOS ==> TOS-1 + "RSET", // Save object TOS ==> TOS-1 (TODO: Same as above?) + "REDIMP_ERASE", + "INITFOREACH", + "VBASET", + "ERASE_CLEAR", + "ARRAYACCESS" +}; + +static const char* pOp2[] = { + "NUMBER", // Load a numeric constant (+ID) + "STRING", // Load a string constant (+ID) + "CONSTANT", // Immediate Load (+value) + "ARGN", // Save named args in argv (+StringID) + "PAD", // Pad String to defined length (+length) + // Branches + "JUMP", // Jump to target (+Target) + "JUMP.T", // evaluate TOS, conditional jump (+Target) + "JUMP.F", // evaluate TOS, conditional jump (+Target) + "ONJUMP", // evaluate TOS, jump into JUMP-table (+MaxVal) + "GOSUB", // UP-Call (+Target) + "RETURN", // UP-Return (+0 or Target) + "TESTFOR", // Test FOR-Variable, increment (+Endlabel) + "CASETO", // Tos+1 <= Case <= Tos, 2xremove (+Target) + "ERRHDL", // Error-Handler (+Offset) + "RESUME", // Resume after errors (+0 or 1 or Label) + // I/O + "CLOSE", // (+channel/0) + "PRCHAR", // (+char) + // Objects + "SETCLASS", // Test Set + Classname (+StringId) + "TESTCLASS", // Check TOS class (+StringId) + "LIB", // Set Libname for Declare-Procs (+StringId) + // New since Beta 3 (TODO: Which Beta3?) + "BASED", // TOS is incremted about BASE, push BASE before + "ARGTYP", // Convert last parameter in argv (+Type) + "VBASETCLASS", +}; + +static const char* pOp3[] = { + // All opcodes with two operands + "RTL", // Load from RTL (+StringID+Typ) + "FIND", // Load (+StringID+Typ) + "ELEM", // Load element (+StringID+Typ) + "PARAM", // Parameter (+Offset+Typ) + + // Branching + "CALL", // Call DECLARE method (+StringID+Typ) + "CALL.C", // Call Cdecl-DECLARE method (+StringID+Typ) + "CASEIS", // Case-Test (+Test-Opcode+False-Target) + "STMNT", // Start of a statement (+Line+Col) + + // I/O + "OPEN", // (+SvStreamFlags+Flags) + + // Objects and variables + "LOCAL", // Local variables (+StringID+Typ) + "PUBLIC", // Modul global var (+StringID+Typ) + "GLOBAL", // Global var (+StringID+Typ) + "CREATE", // Create object (+StringId+StringId) + "STATIC", // Create static object (+StringId+StringId) + "TCREATE", // Create User defined Object (+StringId+StringId) + "DCREATE", // Create User defined Object-Array kreieren (+StringId+StringId) + "GLOBAL_P", // Define persistent global var (existing after basic restart) + // P=PERSIST (+StringID+Typ) + "FIND_G", // Searches for global var with special handling due to _GLOBAL_P + "DCREATE_REDIMP", // Change dimensions of a user defined Object-Array (+StringId+StringId) + "FIND_CM", // Search inside a class module (CM) to enable global search in time + "PUBLIC_P", // Module global Variable (persisted between calls)(+StringID+Typ) +}; + +static const char** pOps[3] = { pOp1, pOp2, pOp3 }; + +typedef void( SbiDisas::*Func )( String& ); // Processing routines + +static const Func pOperand2[] = { + &SbiDisas::StrOp, // Load a numeric constant (+ID) + &SbiDisas::StrOp, // Load a string constant (+ID) + &SbiDisas::ImmOp, // Immediate Load (+Wert) + &SbiDisas::StrOp, // Save a named argument (+ID) + &SbiDisas::ImmOp, // Strip String to fixed size (+length) + + // Branches + &SbiDisas::LblOp, // Jump (+Target) + &SbiDisas::LblOp, // eval TOS, conditional jump (+Target) + &SbiDisas::LblOp, // eval TOS, conditional jump (+Target) + &SbiDisas::OnOp, // eval TOS, jump in JUMP table (+MaxVal) + &SbiDisas::LblOp, // UP call (+Target) + &SbiDisas::ReturnOp, // UP Return (+0 or Target) + &SbiDisas::LblOp, // test FOR-Variable, increment (+Endlabel) + &SbiDisas::LblOp, // Tos+1 <= Case <= Tos), 2xremove (+Target) + &SbiDisas::LblOp, // Error handler (+Offset) + &SbiDisas::ResumeOp, // Resume after errors (+0 or 1 or Label) + + // I/O + &SbiDisas::CloseOp, // (+channel/0) + &SbiDisas::CharOp, // (+char) + + // Objects + &SbiDisas::StrOp, // Test classname (+StringId) + &SbiDisas::StrOp, // TESTCLASS, Check TOS class (+StringId) + &SbiDisas::StrOp, // Set libname for declare procs (+StringId) + &SbiDisas::ImmOp, // TOS is incremented about BASE erhoeht, BASE pushed before + &SbiDisas::TypeOp, // Convert last parameter to/in(?) argv (+Typ) + &SbiDisas::StrOp, // VBASETCLASS (+StringId) +}; + +static const Func pOperand3[] = { + // All opcodes with two operands + &SbiDisas::VarOp, // Load from RTL (+StringID+Typ) + &SbiDisas::VarOp, // Load (+StringID+Typ) + &SbiDisas::VarOp, // Load Element (+StringID+Typ) + &SbiDisas::OffOp, // Parameter (+Offset+Typ) + + // Branch + &SbiDisas::VarOp, // Call DECLARE-Method (+StringID+Typ) + &SbiDisas::VarOp, // Call CDecl-DECLARE-Methode (+StringID+Typ) + &SbiDisas::CaseOp, // Case-Test (+Test-Opcode+False-Target) + &SbiDisas::StmntOp, // Statement (+Row+Column) + + // I/O + &SbiDisas::StrmOp, // (+SvStreamFlags+Flags) + + // Objects + &SbiDisas::VarDefOp, // Define local var (+StringID+Typ) + &SbiDisas::VarDefOp, // Define Module global var (+StringID+Typ) + &SbiDisas::VarDefOp, // Define global var (+StringID+Typ) + &SbiDisas::Str2Op, // Create object (+StringId+StringId) + &SbiDisas::VarDefOp, // Define static object (+StringID+Typ) + &SbiDisas::Str2Op, // Create User defined Object (+StringId+StringId) + &SbiDisas::Str2Op, // Create User defined Object-Array (+StringId+StringId) + &SbiDisas::VarDefOp, // Define persistent global var P=PERSIST (+StringID+Typ) + &SbiDisas::VarOp, // Searches for global var with special handling due to _GLOBAL_P + &SbiDisas::Str2Op, // Redimensionate User defined Object-Array (+StringId+StringId) + &SbiDisas::VarOp, // FIND_CM + &SbiDisas::VarDefOp, // PUBLIC_P +}; + +// TODO: Why as method? Isn't a simple define sufficient? +static const char* _crlf() +{ +#if defined (UNX) || defined( PM2 ) + return "\n"; +#else + return "\r\n"; +#endif +} + +// This method exists because we want to load the file as own segment +BOOL SbModule::Disassemble( String& rText ) +{ + rText.Erase(); + if( pImage ) + { + SbiDisas aDisas( this, pImage ); + aDisas.Disas( rText ); + } + return BOOL( rText.Len() != 0 ); +} + +SbiDisas::SbiDisas( SbModule* p, const SbiImage* q ) : rImg( *q ), pMod( p ) +{ + memset( cLabels, 0, 8192 ); + nLine = 0; + nOff = 0; + nPC = 0; + nOp1 = nOp2 = nParts = 0; + eOp = _NOP; + // Set Label-Bits + nOff = 0; + while( Fetch() ) + { + switch( eOp ) + { + case _RESUME: if( nOp1 <= 1 ) break; + case _RETURN: if( !nOp1 ) break; + case _JUMP: + case _JUMPT: + case _JUMPF: + case _GOSUB: + case _TESTFOR: + case _CASEIS: + case _CASETO: + case _ERRHDL: + cLabels[ (nOp1 & 0xffff) >> 3 ] |= ( 1 << ( nOp1 & 7 ) ); + break; + default: break; + } + } + nOff = 0; + // Add the publics + for( USHORT i = 0; i < pMod->GetMethods()->Count(); i++ ) + { + SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i )); + if( pMeth ) + { + USHORT nPos = (USHORT) (pMeth->GetId()); + cLabels[ nPos >> 3 ] |= ( 1 << ( nPos & 7 ) ); + } + } +} + +// Read current opcode +BOOL SbiDisas::Fetch() +{ + nPC = nOff; + if( nOff >= rImg.GetCodeSize() ) + return FALSE; + const unsigned char* p = (const unsigned char*)( rImg.GetCode() + nOff ); + eOp = (SbiOpcode) ( *p++ & 0xFF ); + if( eOp <= SbOP0_END ) + { + nOp1 = nOp2 = 0; + nParts = 1; + nOff++; + return TRUE; + } + else if( eOp <= SbOP1_END ) + { + nOff += 5; + if( nOff > rImg.GetCodeSize() ) + return FALSE; + nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; + nParts = 2; + return TRUE; + } + else if( eOp <= SbOP2_END ) + { + nOff += 9; + if( nOff > rImg.GetCodeSize() ) + return FALSE; + nOp1 = *p++; nOp1 |= *p++ << 8; nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; + nOp2 = *p++; nOp2 |= *p++ << 8; nOp2 |= *p++ << 16; nOp2 |= *p++ << 24; + nParts = 3; + return TRUE; + } + else + return FALSE; +} + +void SbiDisas::Disas( SvStream& r ) +{ + String aText; + nOff = 0; + while( DisasLine( aText ) ) + { + ByteString aByteText( aText, gsl_getSystemTextEncoding() ); + r.WriteLine( aByteText ); + } +} + +void SbiDisas::Disas( String& r ) +{ + r.Erase(); + String aText; + nOff = 0; + while( DisasLine( aText ) ) + { + r += aText; + r.AppendAscii( _crlf() ); + } + aText.ConvertLineEnd(); +} + +BOOL SbiDisas::DisasLine( String& rText ) +{ + char cBuf[ 100 ]; + const char* pMask[] = { + "%08" SAL_PRIXUINT32 " ", + "%08" SAL_PRIXUINT32 " %02X ", + "%08" SAL_PRIXUINT32 " %02X %08X ", + "%08" SAL_PRIXUINT32 " %02X %08X %08X " }; + rText.Erase(); + if( !Fetch() ) + return FALSE; + // New line? + if( eOp == _STMNT && nOp1 != nLine ) + { + // Find line + String aSource = rImg.aOUSource; + nLine = nOp1; + USHORT n = 0; + USHORT l = (USHORT)nLine; + while( --l ) { + n = aSource.SearchAscii( "\n", n ); + if( n == STRING_NOTFOUND ) break; + else n++; + } + // Show position + if( n != STRING_NOTFOUND ) + { + USHORT n2 = aSource.SearchAscii( "\n", n ); + if( n2 == STRING_NOTFOUND ) n2 = aSource.Len() - n; + String s( aSource.Copy( n, n2 - n + 1 ) ); + BOOL bDone; + do { + bDone = TRUE; + n = s.Search( '\r' ); + if( n != STRING_NOTFOUND ) bDone = FALSE, s.Erase( n, 1 ); + n = s.Search( '\n' ); + if( n != STRING_NOTFOUND ) bDone = FALSE, s.Erase( n, 1 ); + } while( !bDone ); +// snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC ); +// rText += cBuf; + rText.AppendAscii( "; " ); + rText += s; + rText.AppendAscii( _crlf() ); + } + } + // Label? + const char* p = ""; + if( cLabels[ nPC >> 3 ] & ( 1 << ( nPC & 7 ) ) ) + { + // Public? + ByteString aByteMethName; + for( USHORT i = 0; i < pMod->GetMethods()->Count(); i++ ) + { + SbMethod* pMeth = PTR_CAST(SbMethod,pMod->GetMethods()->Get( i )); + if( pMeth ) + { + aByteMethName = ByteString( pMeth->GetName(), gsl_getSystemTextEncoding() ); + if( pMeth->GetId() == nPC ) + { + p = aByteMethName.GetBuffer(); + break; + } + if( pMeth->GetId() >= nPC ) + break; + } + } + snprintf( cBuf, sizeof(cBuf), pMask[ 0 ], nPC ); + rText.AppendAscii( cBuf ); + if( p && *p ) + { + rText.AppendAscii( p ); + } + else + { + // fix warning (now error) for "Lbl%04lX" format + snprintf( cBuf, sizeof(cBuf), "Lbl%08" SAL_PRIXUINT32, nPC ); + rText.AppendAscii( cBuf ); + } + rText += ':'; + rText.AppendAscii( _crlf() ); + } + snprintf( cBuf, sizeof(cBuf), pMask[ nParts ], nPC, (USHORT) eOp, nOp1, nOp2 ); + rText.AppendAscii( cBuf ); + int n = eOp; + if( eOp >= SbOP2_START ) + n -= SbOP2_START; + else if( eOp >= SbOP1_START ) + n -= SbOP1_START; + rText += '\t'; + rText.AppendAscii( pOps[ nParts-1 ][ n ] ); + rText += '\t'; + switch( nParts ) + { + case 2: (this->*( pOperand2[ n ] ) )( rText ); break; + case 3: (this->*( pOperand3[ n ] ) )( rText ); break; + } + return TRUE; +} + +// Read from StringPool +void SbiDisas::StrOp( String& rText ) +{ + String aStr = rImg.GetString( (USHORT)nOp1 ); + ByteString aByteString( aStr, RTL_TEXTENCODING_ASCII_US ); + const char* p = aByteString.GetBuffer(); + if( p ) + { + rText += '"'; + rText.AppendAscii( p ); + rText += '"'; + } + else + { + rText.AppendAscii( "?String? " ); + rText += (USHORT)nOp1; + } +} + +void SbiDisas::Str2Op( String& rText ) +{ + StrOp( rText ); + rText += ','; + String s; + nOp1 = nOp2; + StrOp( s ); + rText += s; +} + +// Immediate Operand +void SbiDisas::ImmOp( String& rText ) +{ + rText += String::CreateFromInt32(nOp1); +} + +// OnGoto Operand +void SbiDisas::OnOp( String& rText ) +{ + rText += String::CreateFromInt32(nOp1 & 0x7FFF); + if( nOp1 & 0x800 ) + rText.AppendAscii( "\t; Gosub" ); +} + +// Label +void SbiDisas::LblOp( String& rText ) +{ + char cBuf[ 10 ]; + snprintf( cBuf, sizeof(cBuf), "Lbl%04" SAL_PRIXUINT32, nOp1 ); + rText.AppendAscii( cBuf ); +} + +// 0 or Label +void SbiDisas::ReturnOp( String& rText ) +{ + if( nOp1 ) + LblOp( rText ); +} + +// 0, 1 or Label +void SbiDisas::ResumeOp( String& rText ) +{ + switch( nOp1 ) + { + case 1: rText.AppendAscii( "NEXT" ); break; + case 2: LblOp( rText ); + } +} + +// print Prompt +// FALSE/TRUE +void SbiDisas::PromptOp( String& rText ) +{ + if( nOp1 ) + rText.AppendAscii( "\"? \"" ); +} + +// 0 or 1 +void SbiDisas::CloseOp( String& rText ) +{ + rText.AppendAscii( nOp1 ? "Channel" : "All" ); +} + +// Print character +void SbiDisas::CharOp( String& rText ) +{ + const char* p = NULL; + switch( nOp1 ) + { + case 7: p = "'\\a'"; break; + case 9: p = "'\\t'"; break; + case 10: p = "'\\n'"; break; + case 12: p = "'\\f'"; break; + case 13: p = "'\\r'"; break; + } + if( p ) rText.AppendAscii( p ); + else if( nOp1 >= ' ' ) + rText += '\'', + rText += (char) nOp1, + rText += '\''; + else + rText.AppendAscii( "char " ), + rText += (USHORT)nOp1; +} + +// Print var: String-ID and type +void SbiDisas::VarOp( String& rText ) +{ + rText += rImg.GetString( (USHORT)(nOp1 & 0x7FFF) ); + rText.AppendAscii( "\t; " ); + // The type + UINT32 n = nOp1; + nOp1 = nOp2; + TypeOp( rText ); + if( n & 0x8000 ) + rText.AppendAscii( ", Args" ); +} + +// Define variable: String-ID and type +void SbiDisas::VarDefOp( String& rText ) +{ + rText += rImg.GetString( (USHORT)(nOp1 & 0x7FFF) ); + rText.AppendAscii( "\t; " ); + // The Typ + nOp1 = nOp2; + TypeOp( rText ); +} + +// Print variable: Offset and Typ +void SbiDisas::OffOp( String& rText ) +{ + rText += String::CreateFromInt32( nOp1 & 0x7FFF ); + rText.AppendAscii( "\t; " ); + // The type + UINT32 n = nOp1; + nOp1 = nOp2; + TypeOp( rText ); + if( n & 0x8000 ) + rText.AppendAscii( ", Args" ); +} + +// Data type +#ifdef HP9000 // TODO: remove this! +static char* SbiDisas_TypeOp_pTypes[13] = { + "Empty","Null","Integer","Long","Single","Double", + "Currency","Date","String","Object","Error","Boolean", + "Variant" }; +#define pTypes SbiDisas_TypeOp_pTypes +#endif +void SbiDisas::TypeOp( String& rText ) +{ + // AB 19.1.96: Typ kann Flag für BYVAL enthalten (StepARGTYP) + if( nOp1 & 0x8000 ) + { + nOp1 &= 0x7FFF; // Flag wegfiltern + rText.AppendAscii( "BYVAL " ); + } + if( nOp1 < 13 ) + { +#ifndef HP9000 + static char pTypes[][13] = { + "Empty","Null","Integer","Long","Single","Double", + "Currency","Date","String","Object","Error","Boolean", + "Variant" }; +#endif + rText.AppendAscii( pTypes[ nOp1 ] ); + } + else + { + rText.AppendAscii( "type " ); + rText += (USHORT)nOp1; + } +} +#ifdef HP9000 +#undef pTypes +#endif + +// TRUE-Label, condition Opcode +void SbiDisas::CaseOp( String& rText ) +{ + LblOp( rText ); + rText += ','; + rText.AppendAscii( pOp1[ nOp2 - SbxEQ + _EQ ] ); +} + +// Row, column +void SbiDisas::StmntOp( String& rText ) +{ + rText += String::CreateFromInt32( nOp1 ); + rText += ','; + UINT32 nCol = nOp2 & 0xFF; + UINT32 nFor = nOp2 / 0x100; + rText += String::CreateFromInt32( nCol ); + rText.AppendAscii( " (For-Level: " ); + rText += String::CreateFromInt32( nFor ); + rText += ')'; +} + +// open mode, flags +void SbiDisas::StrmOp( String& rText ) +{ + char cBuf[ 10 ]; + snprintf( cBuf, sizeof(cBuf), "%04" SAL_PRIXUINT32, nOp1 ); + rText.AppendAscii( cBuf ); + if( nOp2 & SBSTRM_INPUT ) + rText.AppendAscii( ", Input" ); + if( nOp2 & SBSTRM_OUTPUT ) + rText.AppendAscii( ", Output" ); + if( nOp2 & SBSTRM_APPEND ) + rText.AppendAscii( ", Append" ); + if( nOp2 & SBSTRM_RANDOM ) + rText.AppendAscii( ", Random" ); + if( nOp2 & SBSTRM_BINARY ) + rText.AppendAscii( ", Binary" ); +} + + diff --git a/basic/source/classes/eventatt.cxx b/basic/source/classes/eventatt.cxx new file mode 100644 index 000000000000..b0c8f4b3c36c --- /dev/null +++ b/basic/source/classes/eventatt.cxx @@ -0,0 +1,599 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: eventatt.cxx,v $ + * $Revision: 1.35.40.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +//#include <stl_queue.h> +#include <osl/mutex.hxx> +#include <comphelper/processfactory.hxx> + + +#include <com/sun/star/script/XEventAttacher.hpp> +#include <com/sun/star/script/XAllListener.hpp> +#include <com/sun/star/script/XScriptEventsSupplier.hpp> +#include <com/sun/star/script/XScriptEventsAttacher.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/resource/XStringResourceSupplier.hpp> +#include <com/sun/star/resource/XStringResourceManager.hpp> +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/awt/XDialog.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/script/provider/XScriptProviderFactory.hpp> + +#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp> +#include <com/sun/star/script/provider/XScriptProvider.hpp> +#include <com/sun/star/awt/XDialogProvider.hpp> + +#include <com/sun/star/frame/XModel.hpp> + +//================================================================================================== + +#include <xmlscript/xmldlg_imexp.hxx> +#include <sbunoobj.hxx> +#include <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <runtime.hxx> +#include <sbintern.hxx> + + +#include <cppuhelper/implbase1.hxx> +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::resource; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::reflection; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::cppu; +using namespace ::osl; + + + +//=================================================================== +void unoToSbxValue( SbxVariable* pVar, const Any& aValue ); +Any sbxToUnoValue( SbxVariable* pVar ); + + +Reference< frame::XModel > getModelFromBasic( SbxObject* pBasic ) +{ + OSL_PRECOND( pBasic != NULL, "getModelFromBasic: illegal call!" ); + if ( !pBasic ) + return NULL; + + // look for the ThisComponent variable, first in the parent (which + // might be the document's Basic), then in the parent's parent (which might be + // the application Basic) + const ::rtl::OUString sThisComponent( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ); + SbxVariable* pThisComponent = NULL; + + SbxObject* pLookup = pBasic->GetParent(); + while ( pLookup && !pThisComponent ) + { + pThisComponent = pLookup->Find( sThisComponent, SbxCLASS_OBJECT ); + pLookup = pLookup->GetParent(); + } + if ( !pThisComponent ) + { + OSL_TRACE("Failed to get ThisComponent"); + // the application Basic, at the latest, should have this variable + return NULL; + } + + Any aThisComponent( sbxToUnoValue( pThisComponent ) ); + Reference< frame::XModel > xModel( aThisComponent, UNO_QUERY ); + if ( !xModel.is() ) + { + // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller. + Reference< frame::XController > xController( aThisComponent, UNO_QUERY ); + if ( xController.is() ) + xModel = xController->getModel(); + } + + if ( !xModel.is() ) + return NULL; + +#if OSL_DEBUG_LEVEL > 0 + OSL_TRACE("Have model ThisComponent points to url %s", + ::rtl::OUStringToOString( xModel->getURL(), + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); +#endif + + return xModel; +} + +void SFURL_firing_impl( const ScriptEvent& aScriptEvent, Any* pRet, const Reference< frame::XModel >& xModel ) +{ + OSL_TRACE("SFURL_firing_impl() processing script url %s", + ::rtl::OUStringToOString( aScriptEvent.ScriptCode, + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + try + { + Reference< provider::XScriptProvider > xScriptProvider; + if ( xModel.is() ) + { + Reference< provider::XScriptProviderSupplier > xSupplier( xModel, UNO_QUERY ); + OSL_ENSURE( xSupplier.is(), "SFURL_firing_impl: failed to get script provider supplier" ); + if ( xSupplier.is() ) + xScriptProvider.set( xSupplier->getScriptProvider() ); + } + else + { + Reference< XComponentContext > xContext; + Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + OSL_VERIFY( xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "DefaultContext" ) ) >>= xContext ); + if ( xContext.is() ) + { + Reference< provider::XScriptProviderFactory > xFactory( + xContext->getValueByName( + ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory" ) ), + UNO_QUERY ); + OSL_ENSURE( xFactory.is(), "SFURL_firing_impl: failed to get master script provider factory" ); + if ( xFactory.is() ) + { + Any aCtx; + aCtx <<= ::rtl::OUString::createFromAscii( "user" ); + xScriptProvider.set( xFactory->createScriptProvider( aCtx ), UNO_QUERY ); + } + } + } + + if ( !xScriptProvider.is() ) + { + OSL_TRACE("SFURL_firing_impl() Failed to create msp"); + return; + } + Sequence< Any > inArgs( 0 ); + Sequence< Any > outArgs( 0 ); + Sequence< sal_Int16 > outIndex; + + // get Arguments for script + inArgs = aScriptEvent.Arguments; + + Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode ); + + if ( !xScript.is() ) + { + OSL_TRACE("SFURL_firing_impl() Failed to obtain XScript"); + return; + } + + Any result = xScript->invoke( inArgs, outIndex, outArgs ); + if ( pRet ) + { + *pRet = result; + } + } + catch ( RuntimeException& re ) + { + OSL_TRACE("SFURL_firing_impl() Caught RuntimeException reason %s.", + ::rtl::OUStringToOString( re.Message, + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + catch ( Exception& e ) + { + OSL_TRACE("SFURL_firing_impl() Caught Exception reason %s.", + ::rtl::OUStringToOString( e.Message, + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + +} + + +class BasicScriptListener_Impl : public WeakImplHelper1< XScriptListener > +{ + StarBASICRef maBasicRef; + Reference< frame::XModel > m_xModel; + + virtual void firing_impl(const ScriptEvent& aScriptEvent, Any* pRet); + +public: + BasicScriptListener_Impl( StarBASIC* pBasic, const Reference< frame::XModel >& xModel ) + : maBasicRef( pBasic ), m_xModel( xModel ) {} + + // Methods of XAllListener + virtual void SAL_CALL firing(const ScriptEvent& aScriptEvent) + throw( RuntimeException ); + virtual Any SAL_CALL approveFiring(const ScriptEvent& aScriptEvent) + throw( InvocationTargetException, RuntimeException ); + + // Methods of XEventListener + virtual void SAL_CALL disposing(const EventObject& Source) + throw( RuntimeException ); +}; + +// Methods XAllListener +void BasicScriptListener_Impl::firing( const ScriptEvent& aScriptEvent ) throw ( RuntimeException ) +{ + firing_impl( aScriptEvent, NULL ); +} + +Any BasicScriptListener_Impl::approveFiring( const ScriptEvent& aScriptEvent ) + throw ( InvocationTargetException, RuntimeException ) +{ + Any aRetAny; + firing_impl( aScriptEvent, &aRetAny ); + return aRetAny; +} + +// Methods XEventListener +void BasicScriptListener_Impl::disposing(const EventObject& ) throw ( RuntimeException ) +{ + // TODO: ??? + //NAMESPACE_VOS(OGuard) guard( Application::GetSolarMutex() ); + //xSbxObj.Clear(); +} + + +void BasicScriptListener_Impl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet ) +{ + //Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + //{ + if( aScriptEvent.ScriptType.compareToAscii( "StarBasic" ) == 0 ) + { + // Full qualified name? + String aMacro( aScriptEvent.ScriptCode ); + String aLibName; + String aLocation; + if( aMacro.GetTokenCount( '.' ) == 3 ) + { + sal_uInt16 nLast = 0; + ::rtl::OUString aFullLibName = aMacro.GetToken( 0, '.', nLast ); + + sal_Int32 nIndex = aFullLibName.indexOf( (sal_Unicode)':' ); + if (nIndex >= 0) + { + aLocation = aFullLibName.copy( 0, nIndex ); + aLibName = aFullLibName.copy( nIndex + 1 ); + } + + String aModul = aMacro.GetToken( 0, '.', nLast ); + aMacro.Erase( 0, nLast ); + } + + SbxObject* p = maBasicRef; + SbxObject* pParent = p->GetParent(); + SbxObject* pParentParent = pParent ? pParent->GetParent() : NULL; + + StarBASICRef xAppStandardBasic; + StarBASICRef xDocStandardBasic; + if( pParentParent ) + { + // Own basic must be document library + xAppStandardBasic = (StarBASIC*)pParentParent; + xDocStandardBasic = (StarBASIC*)pParent; + } + else if( pParent ) + { + String aName = p->GetName(); + if( aName.EqualsAscii("Standard") ) + { + // Own basic is doc standard lib + xDocStandardBasic = (StarBASIC*)p; + } + xAppStandardBasic = (StarBASIC*)pParent; + } + else + { + xAppStandardBasic = (StarBASIC*)p; + } + + sal_Bool bSearchLib = true; + StarBASICRef xLibSearchBasic; + if( aLocation.EqualsAscii("application") ) + xLibSearchBasic = xAppStandardBasic; + else if( aLocation.EqualsAscii("document") ) + xLibSearchBasic = xDocStandardBasic; + else + bSearchLib = false; + + SbxVariable* pMethVar = NULL; + // Be still tolerant and make default search if no search basic exists + if( bSearchLib && xLibSearchBasic.Is() ) + { + StarBASICRef xLibBasic; + sal_Int16 nCount = xLibSearchBasic->GetObjects()->Count(); + for( sal_Int16 nObj = -1; nObj < nCount ; nObj++ ) + { + StarBASIC* pBasic; + if( nObj == -1 ) + { + pBasic = (StarBASIC*)xLibSearchBasic; + } + else + { + SbxVariable* pVar = xLibSearchBasic->GetObjects()->Get( nObj ); + pBasic = PTR_CAST(StarBASIC,pVar); + } + if( pBasic ) + { + String aName = pBasic->GetName(); + if( aName == aLibName ) + { + // Search only in the lib, not automatically in application basic + USHORT nFlags = pBasic->GetFlags(); + pBasic->ResetFlag( SBX_GBLSEARCH ); + pMethVar = pBasic->Find( aMacro, SbxCLASS_DONTCARE ); + pBasic->SetFlags( nFlags ); + break; + } + } + } + } + + // Default: Be tolerant and search everywhere + if( (!pMethVar || !pMethVar->ISA(SbMethod)) && maBasicRef.Is() ) + pMethVar = maBasicRef->FindQualified( aMacro, SbxCLASS_DONTCARE ); + + SbMethod* pMeth = PTR_CAST(SbMethod,pMethVar); + if( !pMeth ) + return; + + // Setup parameters + SbxArrayRef xArray; + String aTmp; + sal_Int32 nCnt = aScriptEvent.Arguments.getLength(); + if( nCnt ) + { + xArray = new SbxArray; + const Any *pArgs = aScriptEvent.Arguments.getConstArray(); + for( sal_Int32 i = 0; i < nCnt; i++ ) + { + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, pArgs[i] ); + xArray->Put( xVar, sal::static_int_cast< USHORT >(i+1) ); + } + } + + // Call method + SbxVariableRef xValue = pRet ? new SbxVariable : 0; + if( xArray.Is() ) + pMeth->SetParameters( xArray ); + pMeth->Call( xValue ); + if( pRet ) + *pRet = sbxToUnoValue( xValue ); + pMeth->SetParameters( NULL ); + } + else // scripting framework script + { + //callBasic via scripting framework + SFURL_firing_impl( aScriptEvent, pRet, m_xModel ); + + } +} + +Any implFindDialogLibForDialog( const Any& rDlgAny, SbxObject* pBasic ) +{ + Any aRetDlgLibAny; + + SbxVariable* pDlgLibContVar = pBasic->Find + ( String::CreateFromAscii("DialogLibraries"), SbxCLASS_OBJECT ); + if( pDlgLibContVar && pDlgLibContVar->ISA(SbUnoObject) ) + { + SbUnoObject* pDlgLibContUnoObj = (SbUnoObject*)(SbxBase*)pDlgLibContVar; + Any aDlgLibContAny = pDlgLibContUnoObj->getUnoAny(); + + Reference< XLibraryContainer > xDlgLibContNameAccess( aDlgLibContAny, UNO_QUERY ); + OSL_ENSURE( xDlgLibContNameAccess.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" ); + if( xDlgLibContNameAccess.is() ) + { + Sequence< ::rtl::OUString > aLibNames = xDlgLibContNameAccess->getElementNames(); + const ::rtl::OUString* pLibNames = aLibNames.getConstArray(); + sal_Int32 nLibNameCount = aLibNames.getLength(); + + for( sal_Int32 iLib = 0 ; iLib < nLibNameCount ; iLib++ ) + { + if ( !xDlgLibContNameAccess->isLibraryLoaded( pLibNames[ iLib ] ) ) + // if the library isn't loaded, then the dialog cannot originate from this lib + continue; + + Any aDlgLibAny = xDlgLibContNameAccess->getByName( pLibNames[ iLib ] ); + + Reference< XNameAccess > xDlgLibNameAccess( aDlgLibAny, UNO_QUERY ); + OSL_ENSURE( xDlgLibNameAccess.is(), "implFindDialogLibForDialog: invalid dialog lib!" ); + if( xDlgLibNameAccess.is() ) + { + Sequence< ::rtl::OUString > aDlgNames = xDlgLibNameAccess->getElementNames(); + const ::rtl::OUString* pDlgNames = aDlgNames.getConstArray(); + sal_Int32 nDlgNameCount = aDlgNames.getLength(); + + for( sal_Int32 iDlg = 0 ; iDlg < nDlgNameCount ; iDlg++ ) + { + Any aDlgAny = xDlgLibNameAccess->getByName( pDlgNames[ iDlg ] ); + if( aDlgAny == rDlgAny ) + { + aRetDlgLibAny = aDlgLibAny; + break; + } + } + } + } + } + } + + return aRetDlgLibAny; +} + +static ::rtl::OUString aDecorationPropName = + ::rtl::OUString::createFromAscii( "Decoration" ); +static ::rtl::OUString aTitlePropName = + ::rtl::OUString::createFromAscii( "Title" ); + +void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + static ::rtl::OUString aResourceResolverPropName = ::rtl::OUString::createFromAscii( "ResourceResolver" ); + + (void)pBasic; + (void)bWrite; + + Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() ); + if( !xMSF.is() ) + return; + + // We need at least 1 parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Get dialog + SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject(); + if( !(pObj && pObj->ISA(SbUnoObject)) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj; + Any aAnyISP = pUnoObj->getUnoAny(); + TypeClass eType = aAnyISP.getValueType().getTypeClass(); + + if( eType != TypeClass_INTERFACE ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Create new uno dialog + Reference< XNameContainer > xDialogModel( xMSF->createInstance + ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ) ), + UNO_QUERY ); + if( !xDialogModel.is() ) + return; + + Reference< XInputStreamProvider > xISP; + aAnyISP >>= xISP; + if( !xISP.is() ) + return; + + Reference< XComponentContext > xContext; + Reference< XPropertySet > xProps( xMSF, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + OSL_VERIFY( xProps->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext ); + + // Import the DialogModel + Reference< XInputStream > xInput( xISP->createInputStream() ); + + // i83963 Force decoration + uno::Reference< beans::XPropertySet > xDlgModPropSet( xDialogModel, uno::UNO_QUERY ); + if( xDlgModPropSet.is() ) + { + bool bDecoration = true; + try + { + Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName ); + aDecorationAny >>= bDecoration; + if( !bDecoration ) + { + xDlgModPropSet->setPropertyValue( aDecorationPropName, makeAny( true ) ); + xDlgModPropSet->setPropertyValue( aTitlePropName, makeAny( ::rtl::OUString() ) ); + } + } + catch( UnknownPropertyException& ) + {} + } + + // Find dialog library for dialog, direct access is not possible here + StarBASIC* pStartedBasic = pINST->GetBasic(); + SbxObject* pParentBasic = pStartedBasic ? pStartedBasic->GetParent() : NULL; + SbxObject* pParentParentBasic = pParentBasic ? pParentBasic->GetParent() : NULL; + + SbxObject* pSearchBasic1 = NULL; + SbxObject* pSearchBasic2 = NULL; + if( pParentParentBasic ) + { + pSearchBasic1 = pParentBasic; + pSearchBasic2 = pParentParentBasic; + } + else + { + pSearchBasic1 = pStartedBasic; + pSearchBasic2 = pParentBasic; + } + + Any aDlgLibAny; + if( pSearchBasic1 ) + { + aDlgLibAny = implFindDialogLibForDialog( aAnyISP, pSearchBasic1 ); + if( pSearchBasic2 && aDlgLibAny.getValueType().getTypeClass() == TypeClass_VOID ) + aDlgLibAny = implFindDialogLibForDialog( aAnyISP, pSearchBasic2 ); + } + + + OSL_TRACE("About to try get a hold of ThisComponent"); + Reference< frame::XModel > xModel = getModelFromBasic( pStartedBasic ) ; + Reference< XScriptListener > xScriptListener = new BasicScriptListener_Impl( pStartedBasic, xModel ); + + Sequence< Any > aArgs( 4 ); + aArgs[ 0 ] <<= xModel; + aArgs[ 1 ] <<= xInput; + aArgs[ 2 ] = aDlgLibAny; + aArgs[ 3 ] <<= xScriptListener; + // Create a "living" Dialog + Reference< XControl > xCntrl; + try + { + Reference< XDialogProvider > xDlgProv( xMSF->createInstanceWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.DialogProvider" ) ), aArgs ), UNO_QUERY ); + xCntrl.set( xDlgProv->createDialog( rtl::OUString() ), UNO_QUERY_THROW ); + // Add dialog model to dispose vector + Reference< XComponent > xDlgComponent( xCntrl->getModel(), UNO_QUERY ); + pINST->getComponentVector().push_back( xDlgComponent ); + // need ThisCompoent from calling script + } + // preserve existing bad behaviour, it's possible... but probably + // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes + // create dialog fails. So, in this case let's not throw, just leave basic + // detect the unset object. + catch( uno::Exception& ) + { + } + + // Return dialog + Any aRetVal; + aRetVal <<= xCntrl; + SbxVariableRef refVar = rPar.Get(0); + unoToSbxValue( (SbxVariable*)refVar, aRetVal ); +} + + +//=================================================================== + diff --git a/basic/source/classes/image.cxx b/basic/source/classes/image.cxx new file mode 100644 index 000000000000..891e0787cbd8 --- /dev/null +++ b/basic/source/classes/image.cxx @@ -0,0 +1,547 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: image.cxx,v $ + * $Revision: 1.25 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <tools/tenccvt.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include <string.h> // memset() etc +#include "image.hxx" +#include <codegen.hxx> +SbiImage::SbiImage() +{ + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + pLegacyPCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nCodeSize = 0; + nLegacyCodeSize = + nDimBase = 0; + bInit = + bError = 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-Routines for Load/Store +* +**************************************************************************/ + +BOOL SbiGood( SvStream& r ) +{ + return BOOL( !r.IsEof() && r.GetError() == SVSTREAM_OK ); +} + +// Open Record +ULONG SbiOpenRecord( SvStream& r, UINT16 nSignature, UINT16 nElem ) +{ + ULONG nPos = r.Tell(); + r << nSignature << (INT32) 0 << nElem; + return nPos; +} + +// Close Record +void SbiCloseRecord( SvStream& r, ULONG nOff ) +{ + ULONG nPos = r.Tell(); + r.Seek( nOff + 2 ); + r << (INT32) ( nPos - nOff - 8 ); + r.Seek( nPos ); +} + +/************************************************************************** +* +* Load/Store +* +**************************************************************************/ + +// If the version number does not find, binary parts are omitted, but not +// source, comments and name +BOOL SbiImage::Load( SvStream& r ) +{ + UINT32 nVersion = 0; // Versionsnumber + return Load( r, nVersion ); +} +BOOL SbiImage::Load( SvStream& r, UINT32& nVersion ) +{ + + UINT16 nSign, nCount; + UINT32 nLen, nOff; + + Clear(); + // Read Master-Record + r >> nSign >> nLen >> nCount; + ULONG nLast = r.Tell() + nLen; + UINT32 nCharSet; // System charset + 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; + } + // First of all the 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 ); + } + // Comment? + if( aComment.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_COMMENT, 1 ); + r.WriteByteString( aComment, eCharSet ); + //r << aComment; + SbiCloseRecord( r, nPos ); + } + // Source? + if( aOUSource.getLength() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_SOURCE, 1 ); + String aTmp; + sal_Int32 nLen = aOUSource.getLength(); + const sal_Int32 nMaxUnitSize = STRING_MAXLEN - 1; + if( nLen > STRING_MAXLEN ) + aTmp = aOUSource.copy( 0, nMaxUnitSize ); + else + aTmp = aOUSource; + r.WriteByteString( aTmp, eCharSet ); + //r << aSource; + SbiCloseRecord( r, nPos ); + +#ifdef EXTENDED_BINARY_MODULES + if( nLen > STRING_MAXLEN ) + { + sal_Int32 nRemainingLen = nLen - nMaxUnitSize; + 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 + } + // Binary data? + 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 ); + // For every String: + // UINT32 Offset of the Strings in the Stringblock + short i; + + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + r << (UINT32) pStringOff[ i ]; + + // Then the 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 ); + } + // Set overall length + SbiCloseRecord( r, nStart ); + if( !SbiGood( r ) ) + bError = TRUE; + return BOOL( !bError ); +} + +/************************************************************************** +* +* Routines called by the compiler +* +**************************************************************************/ + +void SbiImage::MakeStrings( short nSize ) +{ + nStrings = 0; + nStringIdx = 0; + nStringOff = 0; + nStringSize = 1024; + pStrings = new sal_Unicode[ nStringSize ]; + pStringOff = new UINT32[ nSize ]; + if( pStrings && pStringOff ) + { + nStrings = nSize; + memset( pStringOff, 0, nSize * sizeof( UINT32 ) ); + memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) ); + } + else + bError = TRUE; +} + +// Hinzufuegen eines Strings an den StringPool. Der String-Puffer +// waechst dynamisch in 1K-Schritten +// Add a string to StringPool. The String buffer is dynamically +// growing in 1K-Steps +void SbiImage::AddString( const String& r ) +{ + if( nStringIdx >= nStrings ) + bError = TRUE; + if( !bError ) + { + xub_StrLen len = r.Len() + 1; + UINT32 needed = nStringOff + len; + if( needed > 0xFFFFFF00L ) + bError = TRUE; // out of mem! + else if( needed > nStringSize ) + { + UINT32 nNewLen = needed + 1024; + nNewLen &= 0xFFFFFC00; // trim to 1K border + if( nNewLen > 0xFFFFFF00L ) + nNewLen = 0xFFFFFF00L; + sal_Unicode* p = NULL; + if( (p = new sal_Unicode[ nNewLen ]) != NULL ) + { + memcpy( p, pStrings, nStringSize * sizeof( sal_Unicode ) ); + delete[] pStrings; + pStrings = p; + nStringSize = sal::static_int_cast< UINT16 >(nNewLen); + } + else + bError = TRUE; + } + if( !bError ) + { + pStringOff[ nStringIdx++ ] = nStringOff; + //ByteString aByteStr( r, eCharSet ); + memcpy( pStrings + nStringOff, r.GetBuffer(), len * sizeof( sal_Unicode ) ); + nStringOff = nStringOff + len; + // Last String? The update the size of the buffer + if( nStringIdx >= nStrings ) + nStringSize = nStringOff; + } + } +} + +// Add code block +// The block was fetched by the compiler from class SbBuffer and +// is already created with new. Additionally it contains all Integers +// in Big Endian format, so can be directly read/written. +void SbiImage::AddCode( char* p, UINT32 s ) +{ + pCode = p; + nCodeSize = s; +} + +// Add user type +void SbiImage::AddType(SbxObject* pObject) +{ + if( !rTypes.Is() ) + rTypes = new SbxArray; + SbxObject *pCopyObject = new SbxObject(*pObject); + rTypes->Insert (pCopyObject,rTypes->Count()); +} + +void SbiImage::AddEnum(SbxObject* pObject) // Register enum type +{ + if( !rEnums.Is() ) + rEnums = new SbxArray; + rEnums->Insert( pObject, rEnums->Count() ); +} + + +/************************************************************************** +* +* Accessing the image +* +**************************************************************************/ + +// Note: IDs start with 1 +String SbiImage::GetString( short nId ) const +{ + if( nId && nId <= nStrings ) + { + UINT32 nOff = pStringOff[ nId - 1 ]; + sal_Unicode* pStr = pStrings + nOff; + + // #i42467: Special treatment for vbNullChar + if( *pStr == 0 ) + { + UINT32 nNextOff = (nId < nStrings) ? pStringOff[ nId ] : nStringOff; + UINT32 nLen = nNextOff - nOff - 1; + if( nLen == 1 ) + { + // Force length 1 and make char 0 afterwards + String aNullCharStr( String::CreateFromAscii( " " ) ); + aNullCharStr.SetChar( 0, 0 ); + return aNullCharStr; + } + } + else + { + String aStr( pStr ); + return aStr; + } + } + return String(); +} + +const SbxObject* SbiImage::FindType (String aTypeName) const +{ + return rTypes.Is() ? (SbxObject*)rTypes->Find(aTypeName,SbxCLASS_OBJECT) : NULL; +} + +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; +} diff --git a/basic/source/classes/makefile.mk b/basic/source/classes/makefile.mk new file mode 100644 index 000000000000..92d0f1194fdc --- /dev/null +++ b/basic/source/classes/makefile.mk @@ -0,0 +1,70 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.16 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=classes +LIBTARGET=NO + +# --- Settings ----------------------------------------------------------- + +ENABLE_EXCEPTIONS=TRUE + +.INCLUDE : settings.mk + +# --- Allgemein ----------------------------------------------------------- + +COMMON_SLOFILES= \ + $(SLO)$/sb.obj \ + $(SLO)$/sbxmod.obj \ + $(SLO)$/image.obj \ + $(SLO)$/sbintern.obj \ + $(SLO)$/sbunoobj.obj \ + $(SLO)$/propacc.obj \ + $(SLO)$/disas.obj + +SLOFILES= $(COMMON_SLOFILES) \ + $(SLO)$/eventatt.obj + +OBJFILES= \ + $(OBJ)$/sbintern.obj + +SRS1NAME=$(TARGET) +SRC1FILES= sb.src + +LIB1TARGET= $(SLB)$/$(TARGET).lib +LIB1OBJFILES = $(SLOFILES) + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/basic/source/classes/propacc.cxx b/basic/source/classes/propacc.cxx new file mode 100644 index 000000000000..aed5b2b3c575 --- /dev/null +++ b/basic/source/classes/propacc.cxx @@ -0,0 +1,433 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: propacc.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "propacc.hxx" + +#include <tools/urlobj.hxx> +#include <tools/errcode.hxx> +#include <svtools/svarray.hxx> +#include <basic/sbstar.hxx> +#include <sbunoobj.hxx> + +using com::sun::star::uno::Reference; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace cppu; + + +//======================================================================== + +// Declaration conversion from Sbx to UNO with known target type +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty = NULL ); + +//======================================================================== + +#ifdef WNT +#define CDECL _cdecl +#endif +#if defined(UNX) || defined(OS2) +#define CDECL +#endif + +int CDECL SbCompare_PropertyValues_Impl( const void *arg1, const void *arg2 ) +{ + return ((PropertyValue*)arg1)->Name.compareTo( ((PropertyValue*)arg2)->Name ); +} + +extern "C" int CDECL SbCompare_UString_PropertyValue_Impl( const void *arg1, const void *arg2 ) +{ + const ::rtl::OUString *pArg1 = (::rtl::OUString*) arg1; + const PropertyValue **pArg2 = (const PropertyValue**) arg2; + return pArg1->compareTo( (*pArg2)->Name ); +} + +int CDECL SbCompare_Properties_Impl( const void *arg1, const void *arg2 ) +{ + return ((Property*)arg1)->Name.compareTo( ((Property*)arg2)->Name ); +} + +extern "C" int CDECL SbCompare_UString_Property_Impl( const void *arg1, const void *arg2 ) +{ + const ::rtl::OUString *pArg1 = (::rtl::OUString*) arg1; + const Property *pArg2 = (Property*) arg2; + return pArg1->compareTo( pArg2->Name ); +} + +//---------------------------------------------------------------------------- + +SbPropertyValues::SbPropertyValues() +{ +} + +//---------------------------------------------------------------------------- + +SbPropertyValues::~SbPropertyValues() +{ + _xInfo = Reference< XPropertySetInfo >(); + + for ( USHORT n = 0; n < _aPropVals.Count(); ++n ) + delete _aPropVals.GetObject( n ); +} + +//---------------------------------------------------------------------------- + +Reference< XPropertySetInfo > SbPropertyValues::getPropertySetInfo(void) throw( RuntimeException ) +{ + // create on demand? + if ( !_xInfo.is() ) + { + SbPropertySetInfo *pInfo = new SbPropertySetInfo( _aPropVals ); + ((SbPropertyValues*)this)->_xInfo = (XPropertySetInfo*)pInfo; + } + return _xInfo; +} + +//------------------------------------------------------------------------- + +INT32 SbPropertyValues::GetIndex_Impl( const ::rtl::OUString &rPropName ) const +{ + PropertyValue **ppPV; + ppPV = (PropertyValue **) + bsearch( &rPropName, _aPropVals.GetData(), _aPropVals.Count(), + sizeof( PropertyValue* ), + SbCompare_UString_PropertyValue_Impl ); + return ppPV ? ( (ppPV-_aPropVals.GetData()) / sizeof(ppPV) ) : USHRT_MAX; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::setPropertyValue( + const ::rtl::OUString& aPropertyName, + const Any& aValue) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + INT32 nIndex = GetIndex_Impl( aPropertyName ); + PropertyValue *pPropVal = _aPropVals.GetObject( + sal::static_int_cast< USHORT >(nIndex)); + pPropVal->Value = aValue; +} + +//---------------------------------------------------------------------------- + +Any SbPropertyValues::getPropertyValue( + const ::rtl::OUString& aPropertyName) + throw(::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + INT32 nIndex = GetIndex_Impl( aPropertyName ); + if ( nIndex != USHRT_MAX ) + return _aPropVals.GetObject( + sal::static_int_cast< USHORT >(nIndex))->Value; + return Any(); +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::addPropertyChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XPropertyChangeListener >& ) + throw () +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::removePropertyChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XPropertyChangeListener >& ) + throw () +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::addVetoableChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XVetoableChangeListener >& ) + throw() +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::removeVetoableChangeListener( + const ::rtl::OUString& aPropertyName, + const Reference< XVetoableChangeListener >& ) + throw() +{ + (void)aPropertyName; +} + +//---------------------------------------------------------------------------- + +Sequence< PropertyValue > SbPropertyValues::getPropertyValues(void) throw (::com::sun::star::uno::RuntimeException) +{ + Sequence<PropertyValue> aRet( _aPropVals.Count()); + for ( USHORT n = 0; n < _aPropVals.Count(); ++n ) + aRet.getArray()[n] = *_aPropVals.GetObject(n); + return aRet; +} + +//---------------------------------------------------------------------------- + +void SbPropertyValues::setPropertyValues(const Sequence< PropertyValue >& rPropertyValues ) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + if ( _aPropVals.Count() ) + throw PropertyExistException(); + + const PropertyValue *pPropVals = rPropertyValues.getConstArray(); + for ( sal_Int16 n = 0; n < rPropertyValues.getLength(); ++n ) + { + PropertyValue *pPropVal = new PropertyValue(pPropVals[n]); + _aPropVals.Insert( pPropVal, n ); + } +} + +//============================================================================ +//PropertySetInfoImpl + +PropertySetInfoImpl::PropertySetInfoImpl() +{ +} + +INT32 PropertySetInfoImpl::GetIndex_Impl( const ::rtl::OUString &rPropName ) const +{ + Property *pP; + pP = (Property*) + bsearch( &rPropName, _aProps.getConstArray(), _aProps.getLength(), + sizeof( Property ), + SbCompare_UString_Property_Impl ); + return pP ? sal::static_int_cast<INT32>( (pP-_aProps.getConstArray()) / sizeof(pP) ) : -1; +} + +Sequence< Property > PropertySetInfoImpl::getProperties(void) throw() +{ + return _aProps; +} + +Property PropertySetInfoImpl::getPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ) +{ + sal_Int32 nIndex = GetIndex_Impl( Name ); + if( USHRT_MAX != nIndex ) + return _aProps.getConstArray()[ nIndex ]; + return Property(); +} + +sal_Bool PropertySetInfoImpl::hasPropertyByName(const ::rtl::OUString& Name) throw( RuntimeException ) +{ + sal_Int32 nIndex = GetIndex_Impl( Name ); + return USHRT_MAX != nIndex; +} + + +//============================================================================ + +SbPropertySetInfo::SbPropertySetInfo() +{ +} + +//---------------------------------------------------------------------------- + +SbPropertySetInfo::SbPropertySetInfo( const SbPropertyValueArr_Impl &rPropVals ) +{ + aImpl._aProps.realloc( rPropVals.Count() ); + for ( USHORT n = 0; n < rPropVals.Count(); ++n ) + { + Property &rProp = aImpl._aProps.getArray()[n]; + const PropertyValue &rPropVal = *rPropVals.GetObject(n); + rProp.Name = rPropVal.Name; + rProp.Handle = rPropVal.Handle; + rProp.Type = getCppuVoidType(); + rProp.Attributes = 0; + } +} + +//---------------------------------------------------------------------------- + +SbPropertySetInfo::~SbPropertySetInfo() +{ +} + +//------------------------------------------------------------------------- + +Sequence< Property > SbPropertySetInfo::getProperties(void) throw( RuntimeException ) +{ + return aImpl.getProperties(); +} + +Property SbPropertySetInfo::getPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.getPropertyByName( Name ); +} + +BOOL SbPropertySetInfo::hasPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.hasPropertyByName( Name ); +} + + +//---------------------------------------------------------------------------- + +SbPropertyContainer::SbPropertyContainer() +{ +} + +//---------------------------------------------------------------------------- + +SbPropertyContainer::~SbPropertyContainer() +{ +} + +//---------------------------------------------------------------------------- +void SbPropertyContainer::addProperty(const ::rtl::OUString& Name, + INT16 Attributes, + const Any& DefaultValue) + throw( PropertyExistException, IllegalTypeException, + IllegalArgumentException, RuntimeException ) +{ + (void)Name; + (void)Attributes; + (void)DefaultValue; +} + +//---------------------------------------------------------------------------- +void SbPropertyContainer::removeProperty(const ::rtl::OUString& Name) + throw( UnknownPropertyException, RuntimeException ) +{ + (void)Name; +} + +//---------------------------------------------------------------------------- +// XPropertySetInfo +Sequence< Property > SbPropertyContainer::getProperties(void) throw () +{ + return aImpl.getProperties(); +} + +Property SbPropertyContainer::getPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.getPropertyByName( Name ); +} + +BOOL SbPropertyContainer::hasPropertyByName(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + return aImpl.hasPropertyByName( Name ); +} + +//---------------------------------------------------------------------------- + +Sequence< PropertyValue > SbPropertyContainer::getPropertyValues(void) +{ + return Sequence<PropertyValue>(); +} + +//---------------------------------------------------------------------------- + +void SbPropertyContainer::setPropertyValues(const Sequence< PropertyValue >& PropertyValues_) +{ + (void)PropertyValues_; +} + +//---------------------------------------------------------------------------- + +void RTL_Impl_CreatePropertySet( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // We need at least one parameter + // TODO: In this case < 2 is not correct ;-) + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Get class names of struct + String aServiceName( RTL_CONSTASCII_USTRINGPARAM("stardiv.uno.beans.PropertySet") ); + +#if 0 + // Service suchen und instanzieren + Reference< XMultiServiceFactory > xServiceManager = getProcessServiceFactory(); + Reference< XInterface > xInterface; + if( xProv.is() ) + xInterface = xProv->newInstance(); +#else + Reference< XInterface > xInterface = (OWeakObject*) new SbPropertyValues(); +#endif + + SbxVariableRef refVar = rPar.Get(0); + if( xInterface.is() ) + { + // Set PropertyValues + Any aArgAsAny = sbxToUnoValue( rPar.Get(1), + getCppuType( (Sequence<PropertyValue>*)0 ) ); + Sequence<PropertyValue> *pArg = + (Sequence<PropertyValue>*) aArgAsAny.getValue(); + Reference< XPropertyAccess > xPropAcc = Reference< XPropertyAccess >::query( xInterface ); + xPropAcc->setPropertyValues( *pArg ); + + // Build a SbUnoObject and return it + Any aAny; + aAny <<= xInterface; + SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny ); + if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID ) + { + // Return object + refVar->PutObject( (SbUnoObject*)xUnoObj ); + return; + } + } + + // Object could not be created + refVar->PutObject( NULL ); +} + diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx new file mode 100644 index 000000000000..80fa3c6bb836 --- /dev/null +++ b/basic/source/classes/sb.cxx @@ -0,0 +1,1836 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sb.cxx,v $ + * $Revision: 1.34 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdio.h> + +#include "sb.hxx" +#include <tools/rcid.h> +#include <tools/config.hxx> +#include <tools/stream.hxx> +#ifndef __RSC //autogen +#include <tools/errinf.hxx> +#endif +#include <basic/sbx.hxx> +#include <tools/list.hxx> +#include <tools/shl.hxx> +#include <tools/rc.hxx> +#include <vcl/svapp.hxx> +#include "sbunoobj.hxx" +#include "sbjsmeth.hxx" +#include "sbjsmod.hxx" +#include "sbintern.hxx" +#include "disas.hxx" +#include "runtime.hxx" +#include <basic/sbuno.hxx> +#include "stdobj.hxx" +#include "filefmt.hxx" +#include "sb.hrc" +#include <basrid.hxx> +#include <vos/mutex.hxx> + +// #pragma SW_SEGMENT_CLASS( SBASIC, SBASIC_CODE ) + +SV_IMPL_VARARR(SbTextPortions,SbTextPortion) + +TYPEINIT1(StarBASIC,SbxObject) + +#define RTLNAME "@SBRTL" +// i#i68894# + +const static String aThisComponent( RTL_CONSTASCII_USTRINGPARAM("ThisComponent") ); +const static String aVBAHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) ); + +SbxObject* StarBASIC::getVBAGlobals( ) +{ + if ( !pVBAGlobals ) + pVBAGlobals = (SbUnoObject*)Find( aVBAHook , SbxCLASS_DONTCARE ); + return pVBAGlobals; +} + +// i#i68894# +SbxVariable* StarBASIC::VBAFind( const String& rName, SbxClassType t ) +{ + if( rName == aThisComponent ) + return NULL; + // rename to init globals + if ( getVBAGlobals( ) ) + return pVBAGlobals->Find( rName, t ); + return NULL; + +} +// Create array for conversion SFX <-> VB error code +struct SFX_VB_ErrorItem +{ + 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 mark +}; + +// The StarBASIC factory is a hack. When a SbModule is created, its pointer +// is saved and given to the following SbProperties/SbMethods. This restores +// the Modul-relationshop. But it works only when a modul is loaded. +// Can cause troubles with separately loaded properties! + +SbxBase* SbiFactory::Create( 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 ); + if( pVar->GetType() & SbxARRAY ) + { + SbxBase* pParObj = pVar->GetObject(); + SbxDimArray* pSource = PTR_CAST(SbxDimArray,pParObj); + SbxDimArray* pDest = new SbxDimArray( pVar->GetType() ); + INT32 lb = 0; + INT32 ub = 0; + + pDest->setHasFixedSize( pSource->hasFixedSize() ); + if ( pSource->GetDims() && pSource->hasFixedSize() ) + { + for ( INT32 j = 1 ; j <= pSource->GetDims(); ++j ) + { + pSource->GetDim32( (INT32)j, lb, ub ); + pDest->AddDim32( lb, ub ); + } + } + else + pDest->unoAddDim( 0, -1 ); // variant array + + USHORT nSavFlags = pVar->GetFlags(); + pNewProp->ResetFlag( SBX_FIXED ); + // need to reset the FIXED flag + // when calling PutObject ( because the type will not match Object ) + pNewProp->PutObject( pDest ); + pNewProp->SetFlags( nSavFlags ); + } + 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; +} + +SbxObject* createUserTypeImpl( const String& rClassName ) +{ + SbxObject* pRetObj = pTYPEFAC->CreateObject( rClassName ); + return pRetObj; +} + +TYPEINIT1(SbClassModuleObject,SbModule) + +SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule ) + : SbModule( pClassModule->GetName() ) + , mpClassModule( pClassModule ) + , mbInitializeEventDone( false ) +{ + aOUSource = pClassModule->aOUSource; + aComment = pClassModule->aComment; + pImage = pClassModule->pImage; + pBreaks = pClassModule->pBreaks; + + SetClassName( pClassModule->GetName() ); + + // Allow search only internally + ResetFlag( SBX_GBLSEARCH ); + + // Copy the methods from original class module + SbxArray* pClassMethods = pClassModule->GetMethods(); + 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->SetFlags( nFlags_ ); // Copy flags + pNewProp->ResetFlag( SBX_NO_BROADCAST ); // except the Broadcast if it was set + pProcedureProp->SetFlags( nFlags_ ); + pProps->PutDirect( pNewProp, i ); + StartListening( pNewProp->GetBroadcaster(), 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; + pBreaks = 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 ); + } +} + + +SbClassData::SbClassData( void ) +{ + mxIfaces = new SbxArray(); +} + +void SbClassData::clear( void ) +{ + mxIfaces->Clear(); +} + +SbClassFactory::SbClassFactory( void ) +{ + String aDummyName; + xClassModules = new SbxObject( aDummyName ); +} + +SbClassFactory::~SbClassFactory() +{} + +void SbClassFactory::AddClassModule( SbModule* pClassModule ) +{ + SbxObject* pParent = pClassModule->GetParent(); + xClassModules->Insert( pClassModule ); + pClassModule->SetParent( pParent ); +} + +void SbClassFactory::RemoveClassModule( SbModule* pClassModule ) +{ + xClassModules->Remove( pClassModule ); +} + +SbxBase* SbClassFactory::Create( 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; +} + +SbModule* SbClassFactory::FindClass( const String& rClassName ) +{ + SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE ); + SbModule* pMod = pVar ? (SbModule*)pVar : NULL; + return pMod; +} + +StarBASIC::StarBASIC( StarBASIC* p, BOOL bIsDocBasic ) + : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ), bDocBasic( bIsDocBasic ) +{ + 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 ); + // Search via StarBasic is always global + SetFlag( SBX_GBLSEARCH ); + pVBAGlobals = NULL; + bQuit = FALSE; +} + +// #51727 Override SetModified so that the modified state +// is not given to the parent +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; + +#ifdef DBG_UTIL + // There is no need to clean SbiData at program end, + // but we dislike MLK's at Purify + // TODO: Where else??? + SbiGlobals** pp = (SbiGlobals**) ::GetAppData( SHL_SBC ); + SbiGlobals* p = *pp; + if( p ) + { + delete p; + *pp = 0; + } +#endif + } + + // #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; + } +} + +// Override new() operator, so that everyone can create a new instance +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 ); +} + +/************************************************************************** +* +* Creation/Managment of modules +* +**************************************************************************/ + +SbModule* StarBASIC::MakeModule( const String& rName, const String& rSrc ) +{ + return MakeModule32( rName, rSrc ); +} + +SbModule* StarBASIC::MakeModule32( const String& rName, const ::rtl::OUString& rSrc ) +{ + 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 ); +} + +BOOL StarBASIC::Compile( SbModule* pMod ) +{ + return pMod ? pMod->Compile() : FALSE; +} + +BOOL StarBASIC::Disassemble( SbModule* pMod, String& rText ) +{ + rText.Erase(); + if( pMod ) + pMod->Disassemble( rText ); + return BOOL( rText.Len() != 0 ); +} + +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; +} + +// Run Init-Code of all modules (including inserted libraries) +void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) +{ + // Init own modules + for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( !pModule->IsCompiled() ) + pModule->Compile(); + } + // compile modules first then RunInit ( otherwise there is + // can be order dependency, e.g. classmodule A has a member + // of of type classmodule B and classmodule B hasn't been compiled yet ) + for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + pModule->RunInit(); + } + + // Check all objects if they are BASIC, + // if yes initialize + 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 ) +{ + // Deinit own modules + for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( pModule->pImage ) + pModule->pImage->bInit = false; + } + + for ( USHORT nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic ) + pBasic->DeInitAllModules(); + } +} + +// #43011 For TestTool, to delete global vars +void StarBASIC::ClearGlobalVars( void ) +{ + SbxArrayRef xProps( GetProperties() ); + USHORT nPropCount = xProps->Count(); + for ( USHORT nProp = 0 ; nProp < nPropCount ; ++nProp ) + { + SbxBase* pVar = xProps->Get( nProp ); + pVar->Clear(); + } + SetModified( TRUE ); +} + +// This implementation at first searches within the runtime library, +// then it looks for an element within one module. This moudle can be +// a public var or an entrypoint. If it is not found and we look for a +// method and a module with the given name is found the search continues +// for entrypoint "Main". +// If this fails again a conventional search over objects is performend. +SbxVariable* StarBASIC::Find( const String& rName, SbxClassType t ) +{ + static String aMainStr( RTL_CONSTASCII_USTRINGPARAM("Main") ); + + SbxVariable* pRes = NULL; + SbModule* pNamed = NULL; + // "Extended" search in Runtime Lib + // but only if SbiRuntime has not set the flag + if( !bNoRtl ) + { + if( t == SbxCLASS_DONTCARE || t == SbxCLASS_OBJECT ) + { + if( rName.EqualsIgnoreCaseAscii( RTLNAME ) ) + pRes = pRtl; + } + if( !pRes ) + pRes = ((SbiStdObject*) (SbxObject*) pRtl)->Find( rName, t ); + if( pRes ) + pRes->SetFlag( SBX_EXTFOUND ); + } + // Search module + if( !pRes ) + for( USHORT i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*) pModules->Get( i ); + if( p->IsVisible() ) + { + // Remember modul fpr Main() call + // or is the name equal?!? + if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) + { + if( t == SbxCLASS_OBJECT || t == SbxCLASS_DONTCARE ) + { + pRes = p; break; + } + pNamed = p; + } + // otherwise check if the element is available + // unset GBLSEARCH-Flag (due to 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; +} + +// Find method via name (e.g. query via BASIC IDE) +SbxBase* StarBASIC::FindSBXInCurrentScope( const String& rName ) +{ + if( !pINST ) + return NULL; + if( !pINST->pRun ) + return NULL; + return pINST->pRun->FindElementExtern( rName ); +} + +// Preserve old interface +SbxVariable* StarBASIC::FindVarInCurrentScopy +( const String& rName, USHORT& rStatus ) +{ + rStatus = 1; // Presumption: nothing found + SbxVariable* pVar = NULL; + SbxBase* pSbx = FindSBXInCurrentScope( rName ); + if( pSbx ) + { + if( !pSbx->ISA(SbxMethod) && !pSbx->ISA(SbxObject) ) + pVar = PTR_CAST(SbxVariable,pSbx); + } + if( pVar ) + rStatus = 0; // We found something + return pVar; +} + +void StarBASIC::QuitAndExitApplication() +{ + Stop(); + bQuit = TRUE; +} + +void StarBASIC::Stop() +{ + SbiInstance* p = pINST; + while( p ) + { + p->Stop(); + p = p->pNext; + } +} + +BOOL StarBASIC::IsRunning() +{ + return BOOL( pINST != NULL ); +} + +/************************************************************************** +* +* Object factories and others +* +**************************************************************************/ + +// Activation of an object. There is no need to access active objects +// with name via BASIC. If NULL is given, everything is activated. +void StarBASIC::ActivateObject( const String* pName, BOOL bActivate ) +{ + if( pName ) + { + SbxObject* p = (SbxObject*) SbxObject::Find( *pName, SbxCLASS_OBJECT ); + if( p ) + { + if( bActivate ) + p->SetFlag( SBX_EXTSEARCH ); + else + p->ResetFlag( SBX_EXTSEARCH ); + } + } + else + { + for( USHORT i = 0; i < GetObjects()->Count(); i++ ) + { + SbxObject* p = (SbxObject*) GetObjects()->Get( i ); + if( bActivate ) + p->SetFlag( SBX_EXTSEARCH ); + else + p->ResetFlag( SBX_EXTSEARCH ); + } + } +} + +/************************************************************************** +* +* Debugging and error handling +* +**************************************************************************/ + +SbMethod* StarBASIC::GetActiveMethod( USHORT nLevel ) +{ + if( pINST ) + return pINST->GetCaller( nLevel ); + else + return NULL; +} + +SbModule* StarBASIC::GetActiveModule() +{ + if( pINST && !IsCompilerError() ) + return pINST->GetActiveModule(); + else + return pCMOD; +} + +USHORT StarBASIC::BreakPoint( USHORT l, USHORT c1, USHORT c2 ) +{ + SetErrorData( 0, l, c1, c2 ); + bBreak = TRUE; + if( GetSbData()->aBreakHdl.IsSet() ) + return (USHORT) GetSbData()->aBreakHdl.Call( this ); + else + return BreakHdl(); +} + +USHORT StarBASIC::StepPoint( USHORT l, USHORT c1, USHORT c2 ) +{ + SetErrorData( 0, l, c1, c2 ); + bBreak = FALSE; + if( GetSbData()->aBreakHdl.IsSet() ) + return (USHORT) GetSbData()->aBreakHdl.Call( this ); + else + return BreakHdl(); +} + +USHORT __EXPORT StarBASIC::BreakHdl() +{ + return (USHORT) ( aBreakHdl.IsSet() + ? aBreakHdl.Call( this ) : SbDEBUG_CONTINUE ); +} + +// Calls for error handler and break handler +USHORT StarBASIC::GetLine() { return GetSbData()->nLine; } +USHORT StarBASIC::GetCol1() { return GetSbData()->nCol1; } +USHORT StarBASIC::GetCol2() { return GetSbData()->nCol2; } + +// Specific to error handler +SbError StarBASIC::GetErrorCode() { return GetSbData()->nCode; } +const String& StarBASIC::GetErrorText() { return GetSbData()->aErrMsg; } +BOOL StarBASIC::IsCompilerError() { return GetSbData()->bCompiler; } +void StarBASIC::SetGlobalLanguageMode( SbLanguageMode eLanguageMode ) +{ + GetSbData()->eLanguageMode = eLanguageMode; +} +SbLanguageMode StarBASIC::GetGlobalLanguageMode() +{ + return GetSbData()->eLanguageMode; +} +// Local settings +SbLanguageMode StarBASIC::GetLanguageMode() +{ + // Use global settings? + if( eLanguageMode == SB_LANG_GLOBAL ) + return GetSbData()->eLanguageMode; + else + return eLanguageMode; +} + +// AB: 29.3.96 +// Das Mapping zwischen alten und neuen Fehlercodes erfolgt, indem die Tabelle +// SFX_VB_ErrorTab[] durchsucht wird. Dies ist zwar nicht besonders performant, +// verbraucht aber viel weniger Speicher als entsprechende switch-Bloecke. +// Die Umrechnung von Fehlercodes muss nicht schnell sein, daher auch keine +// binaere Suche bei VB-Error -> SFX-Error. + +// Neue Fehler-Codes auf alte, Sbx-Kompatible zurueckmappen +USHORT StarBASIC::GetVBErrorCode( SbError nError ) +{ + USHORT nRet = 0; + + if( SbiRuntime::isVBAEnabled() ) + { + switch( nError ) + { + case SbERR_BASIC_ARRAY_FIX: + return 10; + case SbERR_BASIC_STRING_OVERFLOW: + return 14; + case SbERR_BASIC_EXPR_TOO_COMPLEX: + return 16; + case SbERR_BASIC_OPER_NOT_PERFORM: + return 17; + case SbERR_BASIC_TOO_MANY_DLL: + return 47; + case SbERR_BASIC_LOOP_NOT_INIT: + return 92; + default: + nRet = 0; + } + } + + // Suchschleife + const SFX_VB_ErrorItem* pErrItem; + 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; + + if( SbiRuntime::isVBAEnabled() ) + { + switch( nError ) + { + case 1: + case 2: + case 4: + case 8: + case 12: + case 73: + return 0L; + case 10: + return SbERR_BASIC_ARRAY_FIX; + case 14: + return SbERR_BASIC_STRING_OVERFLOW; + case 16: + return SbERR_BASIC_EXPR_TOO_COMPLEX; + case 17: + return SbERR_BASIC_OPER_NOT_PERFORM; + case 47: + return SbERR_BASIC_TOO_MANY_DLL; + case 92: + return SbERR_BASIC_LOOP_NOT_INIT; + default: + nRet = 0L; + } + } + const SFX_VB_ErrorItem* pErrItem; + 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::StaticSuppressSfxResource( BOOL bSuppress ) +{ + bStaticSuppressSfxResource = bSuppress; +} + +// Hack for #83750, use bStaticSuppressSfxResource as setup flag +BOOL runsInSetup( void ) +{ + return bStaticSuppressSfxResource; +} + + +void StarBASIC::MakeErrorText( SbError nId, const String& aMsg ) +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + if( bStaticSuppressSfxResource ) + { + GetSbData()->aErrMsg = String( RTL_CONSTASCII_USTRINGPARAM("No resource: Error message not available") ); + return; + } + + USHORT nOldID = GetVBErrorCode( nId ); + + // Hilfsklasse instanzieren + BasResId 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 ) + { + String aStdMsg( RTL_CONSTASCII_USTRINGPARAM("Fehler ") ); + aStdMsg += String::CreateFromInt32( nOldID); + aStdMsg += String( RTL_CONSTASCII_USTRINGPARAM(": Kein Fehlertext verfuegbar!") ); + GetSbData()->aErrMsg = aStdMsg; + } + else + GetSbData()->aErrMsg = String::EmptyString(); +} + +BOOL StarBASIC::CError + ( SbError code, const String& rMsg, USHORT l, USHORT c1, USHORT c2 ) +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + // Compiler-Fehler waehrend der Laufzeit -> Programm anhalten + if( IsRunning() ) + { + // #109018 Check if running Basic is affected + StarBASIC* pStartedBasic = pINST->GetBasic(); + if( pStartedBasic != this ) + return 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 ) +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + SbError c = code; + if( (c & ERRCODE_CLASS_MASK) == ERRCODE_CLASS_COMPILER ) + c = 0; + MakeErrorText( c, rMsg ); + + // Umsetzung des Codes fuer String-Transport in SFX-Error + if( rMsg.Len() ) + 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 ); +} + +void StarBASIC::FatalError( SbError _errCode, const String& _details ) +{ + if( pINST ) + pINST->FatalError( _errCode, _details ); +} + +SbError StarBASIC::GetErrBasic() +{ + if( pINST ) + return pINST->GetErr(); + else + return 0; +} + +// #66536 Zusatz-Message fuer RTL-Funktion Error zugreifbar machen +String StarBASIC::GetErrorMsg() +{ + if( pINST ) + return pINST->GetErrorMsg(); + else + return String(); +} + +USHORT StarBASIC::GetErl() +{ + if( pINST ) + return pINST->GetErl(); + else + return 0; +} + +BOOL __EXPORT StarBASIC::ErrorHdl() +{ + return (BOOL) ( aErrorHdl.IsSet() + ? aErrorHdl.Call( this ) : FALSE ); +} + +Link StarBASIC::GetGlobalErrorHdl() +{ + return GetSbData()->aErrHdl; +} + +void StarBASIC::SetGlobalErrorHdl( const Link& rLink ) +{ + GetSbData()->aErrHdl = rLink; +} + + +Link StarBASIC::GetGlobalBreakHdl() +{ + return GetSbData()->aBreakHdl; +} + +void StarBASIC::SetGlobalBreakHdl( const Link& rLink ) +{ + GetSbData()->aBreakHdl = rLink; +} + +SbxArrayRef StarBASIC::getUnoListeners( void ) +{ + if( !xUnoListeners.Is() ) + xUnoListeners = new SbxArray(); + return xUnoListeners; +} + + +/************************************************************************** +* +* Laden und Speichern +* +**************************************************************************/ + +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; +} + +BOOL StarBASIC::LoadOldModules( SvStream& ) +{ + return FALSE; +} + +bool StarBASIC::GetUNOConstant( const sal_Char* _pAsciiName, ::com::sun::star::uno::Any& aOut ) +{ + bool bRes = false; + ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); + SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( Find( sVarName, SbxCLASS_DONTCARE ) ); + if ( pGlobs ) + { + aOut = pGlobs->getUnoAny(); + bRes = true; + } + return bRes; +} + +//======================================================================== +// #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; + +SbxInfoRef BasicCollection::xAddInfo = NULL; +SbxInfoRef BasicCollection::xItemInfo = NULL; + +BasicCollection::BasicCollection( const XubString& rClass ) + : SbxObject( rClass ) +{ + if( !nCountHash ) + { + nCountHash = MakeHashCode( String::CreateFromAscii( pCountStr ) ); + nAddHash = MakeHashCode( String::CreateFromAscii( pAddStr ) ); + nItemHash = MakeHashCode( String::CreateFromAscii( pItemStr ) ); + nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemoveStr ) ); + } + Initialize(); + +} + +BasicCollection::~BasicCollection() +{} + +void BasicCollection::Clear() +{ + SbxObject::Clear(); + Initialize(); +} + +void BasicCollection::Initialize() +{ + xItemArray = new SbxArray(); + SetType( SbxOBJECT ); + SetFlag( SBX_FIXED ); + ResetFlag( SBX_WRITE ); + SbxVariable* p; + p = Make( String::CreateFromAscii( pCountStr ), SbxCLASS_PROPERTY, SbxINTEGER ); + p->ResetFlag( SBX_WRITE ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pAddStr ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pItemStr ), SbxCLASS_METHOD, SbxVARIANT ); + p->SetFlag( SBX_DONTSTORE ); + p = Make( String::CreateFromAscii( pRemoveStr ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + if ( !xAddInfo.Is() ) + { + xAddInfo = new SbxInfo; + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Item") ), SbxVARIANT, SBX_READ ); + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Key") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Before") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); + xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("After") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); + } + if ( !xItemInfo.Is() ) + { + xItemInfo = new SbxInfo; + xItemInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Index") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL); + } +} + +SbxVariable* BasicCollection::Find( const XubString& rName, SbxClassType t ) +{ + SbxVariable* pFind = SbxObject::Find( rName, t ); + return pFind; +} + +void BasicCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1, + const SfxHint& rHint, const TypeId& rId2 ) +{ + const SbxHint* p = PTR_CAST(SbxHint,&rHint); + if( p ) + { + ULONG nId = p->GetId(); + BOOL bRead = BOOL( nId == SBX_HINT_DATAWANTED ); + BOOL bWrite = BOOL( nId == SBX_HINT_DATACHANGED ); + BOOL bRequestInfo = BOOL( nId == SBX_HINT_INFOWANTED ); + SbxVariable* pVar = p->GetVar(); + SbxArray* pArg = pVar->GetParameters(); + XubString aVarName( pVar->GetName() ); + if( bRead || bWrite ) + { + if( pVar->GetHashCode() == nCountHash + && aVarName.EqualsIgnoreCaseAscii( pCountStr ) ) + pVar->PutLong( xItemArray->Count32() ); + else if( pVar->GetHashCode() == nAddHash + && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) + CollAdd( pArg ); + else if( pVar->GetHashCode() == nItemHash + && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) + CollItem( pArg ); + else if( pVar->GetHashCode() == nRemoveHash + && aVarName.EqualsIgnoreCaseAscii( pRemoveStr ) ) + CollRemove( pArg ); + else + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); + return; + } + else if ( bRequestInfo ) + { + if( pVar->GetHashCode() == nAddHash + && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) + pVar->SetInfo( xAddInfo ); + else if( pVar->GetHashCode() == nItemHash + && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) + pVar->SetInfo( xItemInfo ); + } + } + SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); +} + +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() || ( pBefore->GetType() == SbxEMPTY ) ) ) + { + 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() || ( pKey->GetType() == SbxEMPTY ) ) ) + { + if( pKey->GetType() != SbxSTRING ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + String aKey = pKey->GetString(); + if( implGetIndexForName( aKey ) != -1 ) + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } + pNewItem->SetName( aKey ); + } + } + pNewItem->SetFlag( SBX_READWRITE ); + xItemArray->Insert32( pNewItem, nNextIndex ); + } + else + { + SetError( SbERR_BAD_ARGUMENT ); + return; + } +} + +void BasicCollection::CollItem( SbxArray* pPar_ ) +{ + if( pPar_->Count() != 2 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + SbxVariable* pRes = NULL; + SbxVariable* p = pPar_->Get( 1 ); + INT32 nIndex = implGetIndex( p ); + if( nIndex >= 0 && nIndex < (INT32)xItemArray->Count32() ) + pRes = xItemArray->Get32( nIndex ); + if( !pRes ) + SetError( SbxERR_BAD_INDEX ); + else + *(pPar_->Get(0)) = *pRes; +} + +void BasicCollection::CollRemove( SbxArray* pPar_ ) +{ + if( pPar_ == NULL || pPar_->Count() != 2 ) + { + SetError( SbxERR_WRONG_ARGS ); + return; + } + + SbxVariable* p = pPar_->Get( 1 ); + INT32 nIndex = implGetIndex( p ); + if( nIndex >= 0 && nIndex < (INT32)xItemArray->Count32() ) + xItemArray->Remove32( nIndex ); + else + SetError( SbxERR_BAD_INDEX ); +} + diff --git a/basic/source/classes/sb.src b/basic/source/classes/sb.src new file mode 100644 index 000000000000..214831b8da13 --- /dev/null +++ b/basic/source/classes/sb.src @@ -0,0 +1,680 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sb.src,v $ + * $Revision: 1.48 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#define __RSC +#ifndef _ERRCODE_HXX //autogen +#include <tools/errcode.hxx> +#endif +#include "sb.hrc" +#include <basic/sberrors.hxx> + +Resource RID_BASIC_START +{ + String SbERR_SYNTAX & ERRCODE_RES_MASK + { + Text [ en-US ] = "Syntax error." ; + }; + String SbERR_NO_GOSUB & ERRCODE_RES_MASK + { + Text [ en-US ] = "Return without Gosub." ; + }; + String SbERR_REDO_FROM_START & ERRCODE_RES_MASK + { + Text [ en-US ] = "Incorrect entry; please retry." ; + }; + String SbERR_BAD_ARGUMENT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiger Prozeduraufruf : Ungltiger Prozeduraufruf */ + Text [ en-US ] = "Invalid procedure call." ; + }; + String SbERR_MATH_OVERFLOW & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? šberlauf : Überlauf */ + Text [ en-US ] = "Overflow." ; + }; + String SbERR_NO_MEMORY & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Nicht gen³gend Speicher : Nicht gengend Speicher */ + Text [ en-US ] = "Not enough memory." ; + }; + String SbERR_ALREADY_DIM & ERRCODE_RES_MASK + { + Text [ en-US ] = "Array already dimensioned." ; + }; + String SbERR_OUT_OF_RANGE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Index au˜erhalb des definierten Bereichs : Index auÿerhalb des definierten Bereichs */ + Text [ en-US ] = "Index out of defined range." ; + }; + String SbERR_DUPLICATE_DEF & ERRCODE_RES_MASK + { + Text [ en-US ] = "Duplicate definition." ; + }; + String SbERR_ZERODIV & ERRCODE_RES_MASK + { + Text [ en-US ] = "Division by zero." ; + }; + String SbERR_VAR_UNDEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable not defined." ; + }; + String SbERR_CONVERSION & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Datentypen unvertrõglich : Datentypen unvertr§glich */ + Text [ en-US ] = "Data type mismatch." ; + }; + String SbERR_BAD_PARAMETER & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiger Parameter : Ungltiger Parameter */ + Text [ en-US ] = "Invalid parameter." ; + }; + String SbERR_USER_ABORT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Process interrupted by user." ; + }; + String SbERR_BAD_RESUME & ERRCODE_RES_MASK + { + Text [ en-US ] = "Resume without error." ; + }; + String SbERR_STACK_OVERFLOW & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Nicht gen³gend Stapelspeicher : Nicht gengend Stapelspeicher */ + Text [ en-US ] = "Not enough stack memory." ; + }; + String SbERR_PROC_UNDEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Sub-procedure or function procedure not defined." ; + }; + String SbERR_BAD_DLL_LOAD & ERRCODE_RES_MASK + { + Text [ en-US ] = "Error loading DLL file." ; + }; + String SbERR_BAD_DLL_CALL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Wrong DLL call convention." ; + }; + String SbERR_INTERNAL_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "Internal error $(ARG1)." ; + }; + String SbERR_BAD_CHANNEL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Invalid file name or file number." ; + }; + String SbERR_FILE_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "File not found." ; + }; + String SbERR_BAD_FILE_MODE & ERRCODE_RES_MASK + { + Text [ en-US ] = "Incorrect file mode." ; + }; + String SbERR_FILE_ALREADY_OPEN & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Datei bereits ge÷ffnet : Datei bereits ge”ffnet */ + Text [ en-US ] = "File already open." ; + }; + String SbERR_IO_ERROR & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Gerõte-E/A-Fehler : Ger§te-E/A-Fehler */ + Text [ en-US ] = "Device I/O error." ; + }; + String SbERR_FILE_EXISTS & ERRCODE_RES_MASK + { + Text [ en-US ] = "File already exists." ; + }; + String SbERR_BAD_RECORD_LENGTH & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Falsche Datensatzlõnge : Falsche Datensatzl§nge */ + Text [ en-US ] = "Incorrect record length." ; + }; + String SbERR_DISK_FULL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Disk or hard drive full." ; + }; + String SbERR_READ_PAST_EOF & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Lesen ³ber das Ende der Datei hinaus : Lesen ber das Ende der Datei hinaus */ + Text [ en-US ] = "Reading exceeds EOF." ; + }; + String SbERR_BAD_RECORD_NUMBER & ERRCODE_RES_MASK + { + Text [ en-US ] = "Incorrect record number." ; + }; + String SbERR_TOO_MANY_FILES & ERRCODE_RES_MASK + { + Text [ en-US ] = "Too many files." ; + }; + String SbERR_NO_DEVICE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Gerõt nicht verf³gbar : Ger§t nicht verfgbar */ + Text [ en-US ] = "Device not available." ; + }; + String SbERR_ACCESS_DENIED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Access denied." ; + }; + String SbERR_NOT_READY & ERRCODE_RES_MASK + { + Text [ en-US ] = "Disk not ready." ; + }; + String SbERR_NOT_IMPLEMENTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Not implemented." ; + }; + String SbERR_DIFFERENT_DRIVE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Umbenennen auf verschiedenen Laufwerken nicht m÷glich : Umbenennen auf verschiedenen Laufwerken nicht m”glich */ + Text [ en-US ] = "Renaming on different drives impossible." ; + }; + String SbERR_ACCESS_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "Path/File access error." ; + }; + String SbERR_PATH_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Path not found." ; + }; + String SbERR_NO_OBJECT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object variable not set." ; + }; + String SbERR_BAD_PATTERN & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Zeichenfolgenmuster unzulõssig : Zeichenfolgenmuster unzul§ssig */ + Text [ en-US ] = "Invalid string pattern." ; + }; + String SBERR_IS_NULL & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Verwendung von Null unzulõssig : Verwendung von Null unzul§ssig */ + Text [ en-US ] = "Use of zero not permitted." ; + }; + String SbERR_DDE_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE Error." ; + }; + String SbERR_DDE_WAITINGACK & ERRCODE_RES_MASK + { + Text [ en-US ] = "Awaiting response to DDE connection." ; + }; + String SbERR_DDE_OUTOFCHANNELS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Keine freien DDE-Kanõle : Keine freien DDE-Kan§le */ + Text [ en-US ] = "No DDE channels available." ; + }; + String SbERR_DDE_NO_RESPONSE & ERRCODE_RES_MASK + { + Text [ en-US ] = "No application responded to DDE connect initiation." ; + }; + String SbERR_DDE_MULT_RESPONSES & ERRCODE_RES_MASK + { + Text [ en-US ] = "Too many applications responded to DDE connect initiation." ; + }; + String SbERR_DDE_CHANNEL_LOCKED & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE channel locked." ; + }; + String SbERR_DDE_NOTPROCESSED & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Fremdapplikation kann DDE-Operation nicht ausf³hren : Fremdapplikation kann DDE-Operation nicht ausfhren */ + Text [ en-US ] = "External application cannot execute DDE operation." ; + }; + String SbERR_DDE_TIMEOUT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Zeit³berschreitung wõhrend des Wartens auf DDE-Antwort : Zeitberschreitung w§hrend des Wartens auf DDE-Antwort */ + Text [ en-US ] = "Timeout while waiting for DDE response." ; + }; + String SbERR_DDE_USER_INTERRUPT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Benutzer dr³ckte ESCAPE wõhrend der DDE-Operation : Benutzer drckte ESCAPE w§hrend der DDE-Operation */ + Text [ en-US ] = "User pressed ESCAPE during DDE operation." ; + }; + String SbERR_DDE_BUSY & ERRCODE_RES_MASK + { + Text [ en-US ] = "External application busy." ; + }; + String SbERR_DDE_NO_DATA & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE operation without data." ; + }; + String SbERR_DDE_WRONG_DATA_FORMAT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Data are in wrong format." ; + }; + String SbERR_DDE_PARTNER_QUIT & ERRCODE_RES_MASK + { + Text [ en-US ] = "External application has been terminated." ; + }; + String SbERR_DDE_CONV_CLOSED & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? DDE-Verbindung ist unterbrochen oder geõndert worden : DDE-Verbindung ist unterbrochen oder ge§ndert worden */ + Text [ en-US ] = "DDE connection interrupted or modified." ; + }; + String SbERR_DDE_NO_CHANNEL & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE method invoked with no channel open." ; + }; + String SbERR_DDE_INVALID_LINK & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiges DDE-Linkformat : Ungltiges DDE-Linkformat */ + Text [ en-US ] = "Invalid DDE link format." ; + }; + String SbERR_DDE_QUEUE_OVERFLOW & ERRCODE_RES_MASK + { + Text [ en-US ] = "DDE message has been lost." ; + }; + String SbERR_DDE_LINK_ALREADY_EST & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Paste Link bereits durchgef³hrt : Paste Link bereits durchgefhrt */ + Text [ en-US ] = "Paste link already performed." ; + }; + String SbERR_DDE_LINK_INV_TOPIC & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? LinkMode kann wegen ung³ltigen Link-Topics nicht gesetzt werden : LinkMode kann wegen ungltigen Link-Topics nicht gesetzt werden */ + Text [ en-US ] = "Link mode cannot be set due to invalid link topic." ; + }; + String SbERR_DDE_DLL_NOT_FOUND & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? F³r DDE wird DDEML.DLL ben÷tigt : Fr DDE wird DDEML.DLL ben”tigt */ + Text [ en-US ] = "DDE requires the DDEML.DLL file." ; + }; + String SbERR_CANNOT_LOAD & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Das Modul kann nicht geladen werden, ung³ltiges Format : Das Modul kann nicht geladen werden, ungltiges Format */ + Text [ en-US ] = "Module cannot be loaded; invalid format." ; + }; + String SbERR_BAD_INDEX & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiger Objektindex : Ungltiger Objektindex */ + Text [ en-US ] = "Invalid object index." ; + }; + String SbERR_NO_ACTIVE_OBJECT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Objekt ist nicht verf³gbar : Objekt ist nicht verfgbar */ + Text [ en-US ] = "Object is not available." ; + }; + String SbERR_BAD_PROP_VALUE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Falscher Wert f³r Eigenschaft : Falscher Wert fr Eigenschaft */ + Text [ en-US ] = "Incorrect property value." ; + }; + String SbERR_PROP_READONLY & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Eigenschaft ist schreibgesch³tzt : Eigenschaft ist schreibgeschtzt */ + Text [ en-US ] = "This property is read-only." ; + }; + String SbERR_PROP_WRITEONLY & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Eigenschaft ist lesegesch³tzt : Eigenschaft ist lesegeschtzt */ + Text [ en-US ] = "This property is write only." ; + }; + String SbERR_INVALID_OBJECT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltige Objektreferenz : Ungltige Objektreferenz */ + Text [ en-US ] = "Invalid object reference." ; + }; + String SbERR_NO_METHOD & ERRCODE_RES_MASK + { + Text [ en-US ] = "Property or method not found: $(ARG1)." ; + }; + String SbERR_NEEDS_OBJECT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object required." ; + }; + String SbERR_INVALID_USAGE_OBJECT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Invalid use of an object." ; + }; + String SbERR_NO_OLE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? OLE-Automatisierung wird von diesem Objekt nicht unterst³tzt : OLE-Automatisierung wird von diesem Objekt nicht untersttzt */ + Text [ en-US ] = "OLE Automation is not supported by this object." ; + }; + String SbERR_BAD_METHOD & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Objekt unterst³tzt diese Eigenschaft oder Methode nicht : Objekt untersttzt diese Eigenschaft oder Methode nicht */ + Text [ en-US ] = "This property or method is not supported by the object." ; + }; + String SbERR_OLE_ERROR & ERRCODE_RES_MASK + { + Text [ en-US ] = "OLE Automation Error." ; + }; + String SbERR_BAD_ACTION & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Diese Aktion wird vom angegebenen Objekt nicht unterst³tzt : Diese Aktion wird vom angegebenen Objekt nicht untersttzt */ + Text [ en-US ] = "This action is not supported by given object." ; + }; + String SbERR_NO_NAMED_ARGS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Benannte Argumente werden vom angegebenen Objekt nicht unterst³tzt : Benannte Argumente werden vom angegebenen Objekt nicht untersttzt */ + Text [ en-US ] = "Named arguments are not supported by given object." ; + }; + String SbERR_BAD_LOCALE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Das aktuelle Gebietsschema wird vom angegebenen Objekt nicht unterst³tzt : Das aktuelle Gebietsschema wird vom angegebenen Objekt nicht untersttzt */ + Text [ en-US ] = "The current locale setting is not supported by the given object." ; + }; + String SbERR_NAMED_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Named argument not found." ; + }; + String SbERR_NOT_OPTIONAL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Argument is not optional." ; + }; + String SbERR_WRONG_ARGS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Invalid number of arguments." ; + }; + String SbERR_NOT_A_COLL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object is not a list." ; + }; + String SbERR_BAD_ORDINAL & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ordnungszahl ung³ltig : Ordnungszahl ungltig */ + Text [ en-US ] = "Invalid ordinal number." ; + }; + String SbERR_DLLPROC_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Specified DLL function not found." ; + }; + String SbERR_BAD_CLIPBD_FORMAT & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiges Clipboard-Format : Ungltiges Clipboard-Format */ + Text [ en-US ] = "Invalid clipboard format." ; + }; + String SbERR_PROPERTY_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object does not have this property." ; + }; + String SbERR_METHOD_NOT_FOUND & ERRCODE_RES_MASK + { + Text [ en-US ] = "Object does not have this method." ; + }; + String SbERR_ARG_MISSING & ERRCODE_RES_MASK + { + Text [ en-US ] = "Required argument lacking." ; + }; + String SbERR_BAD_NUMBER_OF_ARGS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltige Anzahl von Argumenten : Ungltige Anzahl von Argumenten */ + Text [ en-US ] = "Invalid number of arguments." ; + }; + String SbERR_METHOD_FAILED & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Fehler in Ausf³hrung einer Methode : Fehler in Ausfhrung einer Methode */ + Text [ en-US ] = "Error executing a method." ; + }; + String SbERR_SETPROP_FAILED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unable to set property." ; + }; + String SbERR_GETPROP_FAILED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unable to determine property." ; + }; + // Compiler errors. These are not runtime errors. + String SbERR_UNEXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unexpected symbol: $(ARG1)." ; + }; + String SbERR_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Expected: $(ARG1)." ; + }; + String SbERR_SYMBOL_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Symbol expected." ; + }; + String SbERR_VAR_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable expected." ; + }; + String SbERR_LABEL_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Label expected." ; + }; + String SbERR_LVALUE_EXPECTED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Value cannot be applied." ; + }; + String SbERR_VAR_DEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable $(ARG1) already defined." ; + }; + String SbERR_PROC_DEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Sub procedure or function procedure $(ARG1) already defined." ; + }; + String SbERR_LABEL_DEFINED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Label $(ARG1) already defined." ; + }; + String SbERR_UNDEF_VAR & ERRCODE_RES_MASK + { + Text [ en-US ] = "Variable $(ARG1) not found." ; + }; + String SbERR_UNDEF_ARRAY & ERRCODE_RES_MASK + { + Text [ en-US ] = "Array or procedure $(ARG1) not found." ; + }; + String SbERR_UNDEF_PROC & ERRCODE_RES_MASK + { + Text [ en-US ] = "Procedure $(ARG1) not found." ; + }; + String SbERR_UNDEF_LABEL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Label $(ARG1) undefined." ; + }; + String SbERR_UNDEF_TYPE & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unknown data type $(ARG1)." ; + }; + String SbERR_BAD_EXIT & ERRCODE_RES_MASK + { + Text [ en-US ] = "Exit $(ARG1) expected." ; + }; + String SbERR_BAD_BLOCK & ERRCODE_RES_MASK + { + Text [ en-US ] = "Statement block still open: $(ARG1) missing." ; + }; + String SbERR_BAD_BRACKETS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Parentheses do not match." ; + }; + String SbERR_BAD_DECLARATION & ERRCODE_RES_MASK + { + Text [ en-US ] = "Symbol $(ARG1) already defined differently." ; + }; + String SbERR_BAD_PARAMETERS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Parameters do not correspond to procedure." ; + }; + String SbERR_BAD_CHAR_IN_NUMBER & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Ung³ltiges Zeichen in Zahl : Ungltiges Zeichen in Zahl */ + Text [ en-US ] = "Invalid character in number." ; + }; + String SbERR_MUST_HAVE_DIMS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Array mu˜ dimensioniert werden : Array muÿ dimensioniert werden */ + Text [ en-US ] = "Array must be dimensioned." ; + }; + String SbERR_NO_IF & ERRCODE_RES_MASK + { + Text [ en-US ] = "Else/Endif without If." ; + }; + String SbERR_NOT_IN_SUBR & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? $(ARG1) innerhalb einer Prozedur unzulõssig : $(ARG1) innerhalb einer Prozedur unzul§ssig */ + Text [ en-US ] = "$(ARG1) not allowed within a procedure." ; + }; + String SbERR_NOT_IN_MAIN & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? $(ARG1) au˜erhalb einer Prozedur unzulõssig : $(ARG1) auÿerhalb einer Prozedur unzul§ssig */ + Text [ en-US ] = "$(ARG1) not allowed outside a procedure." ; + }; + String SbERR_WRONG_DIMS & ERRCODE_RES_MASK + { + Text [ en-US ] = "Dimension specifications do not match." ; + }; + String SbERR_BAD_OPTION & ERRCODE_RES_MASK + { + Text [ en-US ] = "Unknown option: $(ARG1)." ; + }; + String SbERR_CONSTANT_REDECLARED & ERRCODE_RES_MASK + { + Text [ en-US ] = "Constant $(ARG1) redefined." ; + }; + String SbERR_PROG_TOO_LARGE & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Programm ist zu gro˜ : Programm ist zu groÿ */ + Text [ en-US ] = "Program too large." ; + }; + String SbERR_NO_STRINGS_ARRAYS & ERRCODE_RES_MASK + { + /* ### ACHTUNG: Neuer Text in Resource? Strings oder Arrays unzulõssig : Strings oder Arrays unzul§ssig */ + Text [ en-US ] = "Strings or arrays not permitted." ; + }; + String ERRCODE_BASIC_EXCEPTION & ERRCODE_RES_MASK + { + Text [ en-US ] = "An exception occurred $(ARG1)." ; + }; + String ERRCODE_BASIC_ARRAY_FIX & ERRCODE_RES_MASK + { + Text [ en-US ] = "This array is fixed or temporarily locked." ; + }; + String ERRCODE_BASIC_STRING_OVERFLOW & ERRCODE_RES_MASK + { + Text [ en-US ] = "Out of string space." ; + }; + String ERRCODE_BASIC_EXPR_TOO_COMPLEX & ERRCODE_RES_MASK + { + Text [ en-US ] = "Expression Too Complex." ; + }; + String ERRCODE_BASIC_OPER_NOT_PERFORM & ERRCODE_RES_MASK + { + Text [ en-US ] = "Can't perform requested operation." ; + }; + String ERRCODE_BASIC_TOO_MANY_DLL & ERRCODE_RES_MASK + { + Text [ en-US ] = "Too many DLL application clients." ; + }; + String ERRCODE_BASIC_LOOP_NOT_INIT & ERRCODE_RES_MASK + { + Text [ en-US ] = "For loop not initialized." ; + }; +}; + // Hinweis: IDS_SBERR_TERMINATED = IDS_SBERR_START+2000. +String IDS_SBERR_TERMINATED +{ + Text [ en-US ] = "The macro running has been interrupted" ; +}; +String IDS_SBERR_STOREREF +{ + Text [ en-US ] = "Reference will not be saved: "; +}; +String ERRCODE_BASMGR_LIBLOAD & ERRCODE_RES_MASK +{ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1)'' */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Laden der Bibliothek '$(ARG1)' : Fehler beim Laden der Bibliothek ''$(ARG1)'' */ + Text [ en-US ] = "Error loading library '$(ARG1)'." ; +}; +String ERRCODE_BASMGR_LIBSAVE & ERRCODE_RES_MASK +{ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1)'' */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1) */ + /* ### ACHTUNG: Neuer Text in Resource? Fehler beim Speichern der Bibliothek: '$(ARG1)' : Fehler beim Speichern der Bibliothek: ''$(ARG1)'' */ + Text [ en-US ] = "Error saving library: '$(ARG1)'." ; +}; +String ERRCODE_BASMGR_MGROPEN & ERRCODE_RES_MASK +{ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + /* ### ACHTUNG: Neuer Text in Resource? Das BASIC aus der Datei '$(ARG1)' konnte nicht initialisiert werden : Das BASIC aus der Datei ''$(ARG1)'' konnte nicht initialisiert werden */ + Text [ en-US ] = "The BASIC from the file '$(ARG1)' could not be initialized." ; +}; +String ERRCODE_BASMGR_MGRSAVE & ERRCODE_RES_MASK +{ + Text [ en-US ] = "Error saving BASIC: '$(ARG1)'." ; +}; +String ERRCODE_BASMGR_REMOVELIB & ERRCODE_RES_MASK +{ + Text [ en-US ] = "Error removing library." ; +}; +String ERRCODE_BASMGR_UNLOADLIB & ERRCODE_RES_MASK +{ + Text [ en-US ] = "The library could not be removed from memory." ; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/basic/source/classes/sbintern.cxx b/basic/source/classes/sbintern.cxx new file mode 100644 index 000000000000..1dd1d64fbf86 --- /dev/null +++ b/basic/source/classes/sbintern.cxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbintern.cxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/shl.hxx> + +#include "sbintern.hxx" +#include "sbunoobj.hxx" +#include "token.hxx" // Tokenizer +#include "symtbl.hxx" // Symbolverwaltung +#include "parser.hxx" // Parser +#include "codegen.hxx" // Code-Generator +#include <basic/basmgr.hxx> + +SV_IMPL_PTRARR(SbErrorStack, SbErrorStackEntry*) + +SbiGlobals* GetSbData() +{ + SbiGlobals** pp = (SbiGlobals**) ::GetAppData( SHL_SBC ); + SbiGlobals* p = *pp; + if( !p ) + p = *pp = new SbiGlobals; + return p; +} + +SbiGlobals::SbiGlobals() +{ + pInst = NULL; + pMod = NULL; + pSbFac= NULL; + pUnoFac = NULL; + pTypeFac = NULL; + pOLEFac = NULL; + pCompMod = NULL; // JSM + nInst = 0; + nCode = 0; + nLine = 0; + nCol1 = nCol2 = 0; + bCompiler = FALSE; + bGlobalInitErr = FALSE; + bRunInit = FALSE; + eLanguageMode = SB_LANG_BASIC; + pErrStack = NULL; + pTransliterationWrapper = NULL; + bBlockCompilerError = FALSE; + pAppBasMgr = NULL; + pMSOMacroRuntimLib = NULL; +} + +SbiGlobals::~SbiGlobals() +{ + delete pErrStack; + delete pSbFac; + delete pUnoFac; + delete pTransliterationWrapper; +} + diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx new file mode 100644 index 000000000000..a6ae8cac29af --- /dev/null +++ b/basic/source/classes/sbunoobj.cxx @@ -0,0 +1,4022 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbunoobj.cxx,v $ + * $Revision: 1.54 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +//#include <stl_queue.h> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#ifndef _TOOLERR_HXX //autogen +#include <tools/errcode.hxx> +#endif +#include <svtools/hint.hxx> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/exc_hlp.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/XServiceConstructorDescription.hpp> +#include <com/sun/star/bridge/oleautomation/NamedArgument.hpp> +#include <com/sun/star/bridge/oleautomation/Date.hpp> +#include <com/sun/star/bridge/oleautomation/Decimal.hpp> +#include <com/sun/star/bridge/oleautomation/Currency.hpp> + + +using com::sun::star::uno::Reference; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::beans; +using namespace com::sun::star::script; +using namespace com::sun::star::container; +using namespace com::sun::star::bridge; +using namespace cppu; + + +#include<basic/sbstar.hxx> +#include<basic/sbuno.hxx> +#include<basic/sberrors.hxx> +#include<sbunoobj.hxx> +#include"sbjsmod.hxx" +#include<basic/basmgr.hxx> +#include<sbintern.hxx> +#include<runtime.hxx> + +#include<math.h> +#include <hash_map> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include <com/sun/star/reflection/XConstantsTypeDescription.hpp> + +TYPEINIT1(SbUnoMethod,SbxMethod) +TYPEINIT1(SbUnoProperty,SbxProperty) +TYPEINIT1(SbUnoObject,SbxObject) +TYPEINIT1(SbUnoClass,SbxObject) +TYPEINIT1(SbUnoService,SbxObject) +TYPEINIT1(SbUnoServiceCtor,SbxMethod) + +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 ::rtl::OUString aSeqLevelStr( RTL_CONSTASCII_USTRINGPARAM("[]") ); +static ::rtl::OUString defaultNameSpace( RTL_CONSTASCII_USTRINGPARAM("ooo.vba") ); + +// Gets the default property for an uno object. Note: There is some +// redirection built in. The property name specifies the name +// of the default property. + +bool SbUnoObject::getDefaultPropName( SbUnoObject* pUnoObj, String& sDfltProp ) +{ + bool result = false; + Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY ); + if ( xDefaultProp.is() ) + { + sDfltProp = xDefaultProp->getDefaultPropertyName(); + if ( sDfltProp.Len() ) + result = true; + } + return result; +} + +SbxVariable* getDefaultProp( SbxVariable* pRef ) +{ + SbxVariable* pDefaultProp = NULL; + SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pRef); + if ( !pObj ) + { + SbxBase* pObjVarObj = pRef->GetObject(); + pObj = PTR_CAST(SbxObject,pObjVarObj); + } + if ( pObj && pObj->ISA(SbUnoObject) ) + { + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj); + pDefaultProp = pUnoObj->GetDfltProperty(); + } + return pDefaultProp; +} + +Reference< XComponentContext > getComponentContext_Impl( void ) +{ + static Reference< XComponentContext > xContext; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xContext.is() ) + { + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + xProps->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; + OSL_ASSERT( xContext.is() ); + } + } + return xContext; +} + +// CoreReflection statisch speichern +Reference< XIdlReflection > getCoreReflection_Impl( void ) +{ + static Reference< XIdlReflection > xCoreReflection; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xCoreReflection.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) ) + >>= xCoreReflection; + OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessable!?" ); + } + if( !xCoreReflection.is() ) + { + throw DeploymentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessable") ), + Reference< XInterface >() ); + } + } + return xCoreReflection; +} + +// CoreReflection statisch speichern +Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl( void ) +{ + static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess; + + if( !xCoreReflection_HierarchicalNameAccess.is() ) + { + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( xCoreReflection.is() ) + { + xCoreReflection_HierarchicalNameAccess = + Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY ); + } + } + return xCoreReflection_HierarchicalNameAccess; +} + +// Hold TypeProvider statically +Reference< XHierarchicalNameAccess > getTypeProvider_Impl( void ) +{ + static Reference< XHierarchicalNameAccess > xAccess; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xAccess.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) ) + >>= xAccess; + OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessable!?" ); + } + if( !xAccess.is() ) + { + throw DeploymentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM + ("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessable") ), + Reference< XInterface >() ); + } + } + return xAccess; +} + +// Hold TypeConverter statically +Reference< XTypeConverter > getTypeConverter_Impl( void ) +{ + static Reference< XTypeConverter > xTypeConverter; + + // Haben wir schon CoreReflection, sonst besorgen + if( !xTypeConverter.is() ) + { + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); + xTypeConverter = Reference<XTypeConverter>( + xSMgr->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter")), + xContext ), UNO_QUERY ); + } + if( !xTypeConverter.is() ) + { + throw DeploymentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM + ("com.sun.star.script.Converter service not accessable") ), + Reference< XInterface >() ); + } + } + return xTypeConverter; +} + + +// #111851 factory function to create an OLE object +SbUnoObject* createOLEObject_Impl( const String& aType ) +{ + static Reference< XMultiServiceFactory > xOLEFactory; + static bool bNeedsInit = true; + + if( bNeedsInit ) + { + bNeedsInit = false; + + Reference< XComponentContext > xContext = getComponentContext_Impl(); + if( xContext.is() ) + { + Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); + xOLEFactory = Reference<XMultiServiceFactory>( + xSMgr->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.OleObjectFactory")), + xContext ), UNO_QUERY ); + } + } + + SbUnoObject* pUnoObj = NULL; + if( xOLEFactory.is() ) + { + Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aType ); + if( xOLEObject.is() ) + { + Any aAny; + aAny <<= xOLEObject; + pUnoObj = new SbUnoObject( aType, aAny ); + } + } + return pUnoObj; +} + + +namespace +{ + void lcl_indent( ::rtl::OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel ) + { + while ( _nLevel-- > 0 ) + _inout_rBuffer.appendAscii( " " ); + } +} + +void implAppendExceptionMsg( ::rtl::OUStringBuffer& _inout_rBuffer, const Exception& _e, const ::rtl::OUString& _rExceptionType, sal_Int32 _nLevel ) +{ + _inout_rBuffer.appendAscii( "\n" ); + lcl_indent( _inout_rBuffer, _nLevel ); + _inout_rBuffer.appendAscii( "Type: " ); + + if ( _rExceptionType.getLength() == 0 ) + _inout_rBuffer.appendAscii( "Unknown" ); + else + _inout_rBuffer.append( _rExceptionType ); + + _inout_rBuffer.appendAscii( "\n" ); + lcl_indent( _inout_rBuffer, _nLevel ); + _inout_rBuffer.appendAscii( "Message: " ); + _inout_rBuffer.append( _e.Message ); + +} + +// Fehlermeldungs-Message bei Exception zusammenbauen +::rtl::OUString implGetExceptionMsg( const Exception& e, const ::rtl::OUString& aExceptionType_ ) +{ + ::rtl::OUStringBuffer aMessageBuf; + implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 ); + return aMessageBuf.makeStringAndClear(); +} + +String implGetExceptionMsg( const Any& _rCaughtException ) +{ + OSL_PRECOND( _rCaughtException.getValueTypeClass() == TypeClass_EXCEPTION, "implGetExceptionMsg: illegal argument!" ); + if ( _rCaughtException.getValueTypeClass() != TypeClass_EXCEPTION ) + return String(); + + return implGetExceptionMsg( *static_cast< const Exception* >( _rCaughtException.getValue() ), _rCaughtException.getValueTypeName() ); +} + +Any convertAny( const Any& rVal, const Type& aDestType ) +{ + Any aConvertedVal; + Reference< XTypeConverter > xConverter = getTypeConverter_Impl(); + try + { + aConvertedVal = xConverter->convertTo( rVal, aDestType ); + } + catch( const IllegalArgumentException& ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + return aConvertedVal; + } + catch( CannotConvertException& e2 ) + { + String aCannotConvertExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) ); + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e2, aCannotConvertExceptionName ) ); + return aConvertedVal; + } + return aConvertedVal; +} + + +// #105565 Special Object to wrap a strongly typed Uno Any +TYPEINIT1(SbUnoAnyObject,SbxObject) + + +// TODO: Spaeter auslagern +Reference<XIdlClass> TypeToIdlClass( const Type& rType ) +{ + // void als Default-Klasse eintragen + Reference<XIdlClass> xRetClass; + typelib_TypeDescription * pTD = 0; + rType.getDescription( &pTD ); + + if( pTD ) + { + ::rtl::OUString sOWName( pTD->pTypeName ); + Reference< XIdlReflection > xRefl = getCoreReflection_Impl(); + xRetClass = xRefl->forName( sOWName ); + } + return xRetClass; +} + +// Exception type unknown +template< class EXCEPTION > +String implGetExceptionMsg( const EXCEPTION& e ) +{ + return implGetExceptionMsg( e, ::getCppuType( &e ).getTypeName() ); +} + +// Error-Message fuer WrappedTargetExceptions +String implGetWrappedMsg( const WrappedTargetException& e ) +{ + String aMsg; + Any aWrappedAny = e.TargetException; + Type aExceptionType = aWrappedAny.getValueType(); + + // Really an Exception? + if( aExceptionType.getTypeClass() == TypeClass_EXCEPTION ) + { + Exception& e_ = *( (Exception*)aWrappedAny.getValue() ); + aMsg = implGetExceptionMsg( e_, String( aExceptionType.getTypeName() ) ); + } + // Otherwise use WrappedTargetException itself + else + { + aMsg = implGetExceptionMsg( e ); + } + + return aMsg; +} + +void implHandleBasicErrorException( BasicErrorException& e ) +{ + SbError nError = StarBASIC::GetSfxFromVBError( (USHORT)e.ErrorCode ); + StarBASIC::Error( nError, e.ErrorMessageArgument ); +} + +void implHandleWrappedTargetException( const Any& _rWrappedTargetException ) +{ + Any aExamine( _rWrappedTargetException ); + + // completely strip the first InvocationTargetException, its error message isn't of any + // interest to the user, it just says something like "invoking the UNO method went wrong.". + InvocationTargetException aInvocationError; + if ( aExamine >>= aInvocationError ) + aExamine = aInvocationError.TargetException; + + BasicErrorException aBasicError; + + SbError nError( ERRCODE_BASIC_EXCEPTION ); + ::rtl::OUStringBuffer aMessageBuf; + + // strip any other WrappedTargetException instances, but this time preserve the error messages. + WrappedTargetException aWrapped; + sal_Int32 nLevel = 0; + while ( aExamine >>= aWrapped ) + { + // special handling for BasicErrorException errors + if ( aWrapped.TargetException >>= aBasicError ) + { + nError = StarBASIC::GetSfxFromVBError( (USHORT)aBasicError.ErrorCode ); + aMessageBuf.append( aBasicError.ErrorMessageArgument ); + aExamine.clear(); + break; + } + + // append this round's message + implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel ); + if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION ) + // there is a next chain element + aMessageBuf.appendAscii( "\nTargetException:" ); + + // next round + aExamine = aWrapped.TargetException; + ++nLevel; + } + + if ( aExamine.getValueTypeClass() == TypeClass_EXCEPTION ) + { + // the last element in the chain is still an exception, but no WrappedTargetException + implAppendExceptionMsg( aMessageBuf, *static_cast< const Exception* >( aExamine.getValue() ), aExamine.getValueTypeName(), nLevel ); + } + + StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() ); +} + +static void implHandleAnyException( const Any& _rCaughtException ) +{ + BasicErrorException aBasicError; + WrappedTargetException aWrappedError; + + if ( _rCaughtException >>= aBasicError ) + { + implHandleBasicErrorException( aBasicError ); + } + else if ( _rCaughtException >>= aWrappedError ) + { + implHandleWrappedTargetException( _rCaughtException ); + } + else + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) ); + } +} + +// 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* pType = NULL ) +{ + Type aType = aValue.getValueType(); + TypeClass eTypeClass = aType.getTypeClass(); + + sal_Int32 indicesIndex = indices.getLength() -1; + sal_Int32 dimCopy = dimension; + + if ( eTypeClass == TypeClass_SEQUENCE ) + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); + Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); + typelib_TypeDescription * pTD = 0; + aType.getDescription( &pTD ); + Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType ); + ::typelib_typedescription_release( pTD ); + + sal_Int32 nLen = xIdlArray->getLen( aValue ); + for ( sal_Int32 index = 0; index < nLen; ++index ) + { + Any aElementAny = xIdlArray->get( aValue, (UINT32)index ); + // This detects the dimension were currently processing + if ( dimCopy == dimension ) + { + ++dimCopy; + if ( sizes.getLength() < dimCopy ) + { + sizes.realloc( sizes.getLength() + 1 ); + sizes[ sizes.getLength() - 1 ] = nLen; + indices.realloc( indices.getLength() + 1 ); + indicesIndex = indices.getLength() - 1; + } + } + + if ( bIsZeroIndex ) + indices[ dimCopy - 1 ] = index; + else + indices[ dimCopy - 1] = index + 1; + + implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType ); + } + + } + else + { + if ( indices.getLength() < 1 ) + { + // Should never ever get here ( indices.getLength() + // should equal number of dimensions in the array ) + // And that should at least be 1 ! + // #QUESTION is there a better error? + StarBASIC::Error( SbERR_INVALID_OBJECT ); + return; + } + + SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() ); + if ( !pArray ) + { + pArray = new SbxDimArray( eSbxElementType ); + sal_Int32 nIndexLen = indices.getLength(); + + // Dimension the array + for ( sal_Int32 index = 0; index < nIndexLen; ++index ) + { + if ( bIsZeroIndex ) + pArray->unoAddDim32( 0, sizes[ index ] - 1); + else + pArray->unoAddDim32( 1, sizes[ index ] ); + + } + } + + if ( pArray ) + { + SbxVariableRef xVar = new SbxVariable( eSbxElementType ); + unoToSbxValue( (SbxVariable*)xVar, aValue ); + + sal_Int32* pIndices = indices.getArray(); + pArray->Put32( (SbxVariable*)xVar, pIndices ); + + } + } +} + +void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) +{ + Type aType = aValue.getValueType(); + TypeClass eTypeClass = aType.getTypeClass(); + switch( eTypeClass ) + { + case TypeClass_TYPE: + { + // Map Type to IdlClass + Type aType_; + aValue >>= aType_; + Reference<XIdlClass> xClass = TypeToIdlClass( aType_ ); + Any aClassAny; + aClassAny <<= xClass; + + // SbUnoObject instanzieren + String aName; + SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny ); + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + + // #51475 Wenn das Objekt ungueltig ist null liefern + if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID ) + { + pVar->PutObject( NULL ); + } + else + { + pVar->PutObject( xWrapper ); + } + } + break; + // Interfaces und Structs muessen in ein SbUnoObject gewrappt werden + case TypeClass_INTERFACE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + { + if( eTypeClass == TypeClass_STRUCT ) + { + ArrayWrapper aWrap; + 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; + } + else + { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + oleautomation::Date aDate; + if( (aValue >>= aDate) ) + { + pVar->PutDate( aDate.Value ); + break; + } + else + { + oleautomation::Decimal aDecimal; + if( (aValue >>= aDecimal) ) + { + pVar->PutDecimal( aDecimal ); + break; + } + else + { + oleautomation::Currency aCurrency; + if( (aValue >>= aCurrency) ) + { + sal_Int64 nValue64 = aCurrency.Value; + SbxINT64 aInt64; + aInt64.nHigh = + sal::static_int_cast< INT32 >( + nValue64 >> 32); + aInt64.nLow = (UINT32)( nValue64 & 0xffffffff ); + pVar->PutCurrency( aInt64 ); + break; + } + } + } + } + } + } + // SbUnoObject instanzieren + String aName; + SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aValue ); + //If this is called externally e.g. from the scripting
+ //framework then there is no 'active' runtime the default property will not be set up
+ //only a vba object will have XDefaultProp set anyway so... this
+ //test seems a bit of overkill
+ //if ( SbiRuntime::isVBAEnabled() )
+ { + String sDfltPropName; + + if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) ) + pSbUnoObject->SetDfltProperty( sDfltPropName ); + } + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + + // #51475 Wenn das Objekt ungueltig ist null liefern + if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID ) + { + pVar->PutObject( NULL ); + } + else + { + pVar->PutObject( xWrapper ); + } + } + break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_ARRAY: break; + */ + + case TypeClass_ENUM: + { + sal_Int32 nEnum = 0; + enum2int( nEnum, aValue ); + pVar->PutLong( nEnum ); + } + break; + + case TypeClass_SEQUENCE: + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); + Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); + sal_Int32 i, nLen = xIdlArray->getLen( aValue ); + + typelib_TypeDescription * pTD = 0; + aType.getDescription( &pTD ); + OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE ); + Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType ); + ::typelib_typedescription_release( pTD ); + + // In Basic Array anlegen + SbxDimArrayRef xArray; + SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() ); + xArray = new SbxDimArray( eSbxElementType ); + if( nLen > 0 ) + { + xArray->unoAddDim32( 0, nLen - 1 ); + + // Elemente als Variablen eintragen + for( i = 0 ; i < nLen ; i++ ) + { + // Elemente wandeln + Any aElementAny = xIdlArray->get( aValue, (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: { ::rtl::OUString val; aValue >>= val; pVar->PutString( String( val ) ); } break; + case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break; + case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break; + //case TypeClass_OCTET: break; + case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; + //case TypeClass_INT: break; + case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; + case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break; + case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break; + //case TypeClass_UNSIGNED_OCTET:break; + case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break; + case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break; + case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break; + //case TypeClass_UNSIGNED_INT: break; + //case TypeClass_UNSIGNED_BYTE: break; + default: pVar->PutEmpty(); break; + } +} + +// Reflection fuer Sbx-Typen liefern +Type getUnoTypeForSbxBaseType( SbxDataType eType ) +{ + Type aRetType = getCppuVoidType(); + switch( eType ) + { + //case SbxEMPTY: eRet = TypeClass_VOID; break; + case SbxNULL: aRetType = ::getCppuType( (const Reference< XInterface > *)0 ); break; + case SbxINTEGER: aRetType = ::getCppuType( (sal_Int16*)0 ); break; + case SbxLONG: aRetType = ::getCppuType( (sal_Int32*)0 ); break; + case SbxSINGLE: aRetType = ::getCppuType( (float*)0 ); break; + case SbxDOUBLE: aRetType = ::getCppuType( (double*)0 ); break; + case SbxCURRENCY: aRetType = ::getCppuType( (oleautomation::Currency*)0 ); break; + case SbxDECIMAL: aRetType = ::getCppuType( (oleautomation::Decimal*)0 ); break; + case SbxDATE: { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + aRetType = ::getCppuType( (double*)0 ); + else + aRetType = ::getCppuType( (oleautomation::Date*)0 ); + } + break; + // case SbxDATE: aRetType = ::getCppuType( (double*)0 ); break; + case SbxSTRING: aRetType = ::getCppuType( (::rtl::OUString*)0 ); break; + //case SbxOBJECT: break; + //case SbxERROR: break; + case SbxBOOL: aRetType = ::getCppuType( (sal_Bool*)0 ); break; + case SbxVARIANT: aRetType = ::getCppuType( (Any*)0 ); break; + //case SbxDATAOBJECT: break; + case SbxCHAR: aRetType = ::getCppuType( (sal_Unicode*)0 ); break; + case SbxBYTE: aRetType = ::getCppuType( (sal_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; + } + } + } + + ::rtl::OUString aSeqTypeName( aSeqLevelStr ); + aSeqTypeName += aElementType.getTypeName(); + aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); + } + // #i33795 Map also multi dimensional arrays to corresponding sequences + else if( nDims > 1 ) + { + if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) + { + // For this check the array's dim structure does not matter + 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; + } + } + } + + ::rtl::OUString aSeqTypeName; + for( short iDim = 0 ; iDim < nDims ; iDim++ ) + aSeqTypeName += aSeqLevelStr; + aSeqTypeName += aElementType.getTypeName(); + aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); + } + } + // Kein Array, sondern... + else if( xObj->ISA(SbUnoObject) ) + { + aRetType = ((SbUnoObject*)(SbxBase*)xObj)->getUnoAny().getValueType(); + } + // SbUnoAnyObject? + else if( xObj->ISA(SbUnoAnyObject) ) + { + aRetType = ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue().getValueType(); + } + // Sonst ist es ein Nicht-Uno-Basic-Objekt -> default==void liefern + } + // Kein Objekt, Basistyp konvertieren + else + { + aRetType = getUnoTypeForSbxBaseType( eBaseType ); + } + return aRetType; +} + +// Deklaration Konvertierung von Sbx nach Uno mit bekannter Zielklasse +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty = NULL ); + +// Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY +Any sbxToUnoValueImpl( SbxVariable* pVar, bool bBlockConversionToSmallestType = false ) +{ + SbxDataType eBaseType = pVar->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj.Is() && 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; + ::rtl::OUString aSeqTypeName; + sal_Int32 i; + for( i = 0 ; i < nSeqLevel ; i++ ) + aSeqTypeName += aSeqLevelStr; + + aSeqTypeName += aElemType.getTypeName(); + Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName ); + + // Create Sequence instance + Any aRetVal; + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType ); + xIdlTargetClass->createObject( aRetVal ); + + // Alloc sequence according to array bounds + sal_Int32 nUpper = pUpperBounds[nActualDim]; + sal_Int32 nLower = pLowerBounds[nActualDim]; + sal_Int32 nSeqSize = nUpper - nLower + 1; + Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); + xArray->realloc( aRetVal, nSeqSize ); + + sal_Int32& ri = pActualIndices[nActualDim]; + + for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ ) + { + Any aElementVal; + + if( nActualDim < nMaxDimIndex ) + { + aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType, + nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds ); + } + else + { + SbxVariable* pSource = pArray->Get32( pActualIndices ); + aElementVal = sbxToUnoValue( pSource, aElemType ); + } + + try + { + // In die Sequence uebernehmen + xArray->set( aRetVal, i, aElementVal ); + } + catch( const IllegalArgumentException& ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + } + catch (IndexOutOfBoundsException&) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + } + return aRetVal; +} + +// Map old interface +Any sbxToUnoValue( SbxVariable* pVar ) +{ + return sbxToUnoValueImpl( pVar ); +} + +// Konvertierung von Sbx nach Uno mit bekannter Zielklasse +Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty ) +{ + Any aRetVal; + + // #94560 No conversion of empty/void for MAYBE_VOID properties + if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID ) + { + if( pVar->IsEmpty() ) + return aRetVal; + } + + SbxDataType eBaseType = pVar->SbxValue::GetType(); + if( eBaseType == SbxOBJECT ) + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj.Is() && xObj->ISA(SbUnoAnyObject) ) + { + return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue(); + } + } + + TypeClass eType = rType.getTypeClass(); + switch( eType ) + { + case TypeClass_INTERFACE: + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + { + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); + + // Null-Referenz? + if( pVar->IsNull() && eType == TypeClass_INTERFACE ) + { + Reference< XInterface > xRef; + ::rtl::OUString aClassName = xIdlTargetClass->getName(); + Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() ); + aRetVal.setValue( &xRef, aClassType ); + } + else + { + // #112368 Special conversion for Decimal, Currency and Date + if( eType == TypeClass_STRUCT ) + { + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + if( rType == ::getCppuType( (oleautomation::Decimal*)0 ) ) + { + oleautomation::Decimal aDecimal; + pVar->fillAutomationDecimal( aDecimal ); + aRetVal <<= aDecimal; + break; + } + else if( rType == ::getCppuType( (oleautomation::Currency*)0 ) ) + { + SbxINT64 aInt64 = pVar->GetCurrency(); + oleautomation::Currency aCurrency; + sal_Int64& rnValue64 = aCurrency.Value; + rnValue64 = aInt64.nHigh; + rnValue64 <<= 32; + rnValue64 |= aInt64.nLow; + aRetVal <<= aCurrency; + break; + } + else if( rType == ::getCppuType( (oleautomation::Date*)0 ) ) + { + oleautomation::Date aDate; + aDate.Value = pVar->GetDate(); + aRetVal <<= aDate; + break; + } + } + } + + SbxBaseRef pObj = (SbxBase*)pVar->GetObject(); + if( pObj && pObj->ISA(SbUnoObject) ) + { + aRetVal = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + } + else + { + // #109936 NULL object -> NULL XInterface + Reference<XInterface> xInt; + aRetVal <<= xInt; + } + } + } + break; + + /* folgende Typen lassen wir erstmal weg + case TypeClass_SERVICE: break; + case TypeClass_CLASS: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_ARRAY: break; + */ + + // Array -> Sequence + case TypeClass_ENUM: + { + aRetVal = int2enum( pVar->GetLong(), rType ); + } + break; + + case TypeClass_SEQUENCE: + { + SbxBaseRef xObj = (SbxBase*)pVar->GetObject(); + if( xObj && xObj->ISA(SbxDimArray) ) + { + SbxBase* pObj = (SbxBase*)xObj; + SbxDimArray* pArray = (SbxDimArray*)pObj; + + short nDims = pArray->GetDims(); + + // Normal case: One dimensional array + sal_Int32 nLower, nUpper; + if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) + { + sal_Int32 nSeqSize = nUpper - nLower + 1; + + // Instanz der geforderten Sequence erzeugen + Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); + xIdlTargetClass->createObject( aRetVal ); + Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); + xArray->realloc( aRetVal, nSeqSize ); + + // Element-Type + ::rtl::OUString aClassName = xIdlTargetClass->getName(); + typelib_TypeDescription * pSeqTD = 0; + typelib_typedescription_getByName( &pSeqTD, aClassName.pData ); + OSL_ASSERT( pSeqTD ); + Type aElemType( ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + // Reference< XIdlClass > xElementClass = TypeToIdlClass( aElemType ); + + // Alle Array-Member umwandeln und eintragen + sal_Int32 nIdx = nLower; + for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ ) + { + SbxVariableRef xVar = pArray->Get32( &nIdx ); + + // Wert von Sbx nach Uno wandeln + Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType ); + + try + { + // In die Sequence uebernehmen + xArray->set( aRetVal, i, aAnyValue ); + } + catch( const IllegalArgumentException& ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + } + catch (IndexOutOfBoundsException&) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + } + } + // #i33795 Map also multi dimensional arrays to corresponding sequences + else if( nDims > 1 ) + { + // Element-Type + typelib_TypeDescription * pSeqTD = 0; + Type aCurType( rType ); + sal_Int32 nSeqLevel = 0; + Type aElemType; + do + { + ::rtl::OUString aTypeName = aCurType.getTypeName(); + typelib_typedescription_getByName( &pSeqTD, aTypeName.pData ); + OSL_ASSERT( pSeqTD ); + if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE ) + { + aCurType = Type( ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + nSeqLevel++; + } + else + { + aElemType = aCurType; + break; + } + } + while( true ); + + if( nSeqLevel == nDims ) + { + sal_Int32* pLowerBounds = new sal_Int32[nDims]; + sal_Int32* pUpperBounds = new sal_Int32[nDims]; + sal_Int32* pActualIndices = new sal_Int32[nDims]; + for( short i = 1 ; i <= nDims ; i++ ) + { + sal_Int32 lBound, uBound; + pArray->GetDim32( i, lBound, uBound ); + + short j = i - 1; + pActualIndices[j] = pLowerBounds[j] = lBound; + pUpperBounds[j] = uBound; + } + + aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType, + nDims - 1, 0, pActualIndices, pLowerBounds, pUpperBounds ); + + delete[] pUpperBounds; + delete[] pLowerBounds; + delete[] pActualIndices; + } + } + } + } + break; + + /* + case TypeClass_VOID: break; + case TypeClass_UNKNOWN: break; + */ + + // Bei Any die Klassen-unabhaengige Konvertierungs-Routine nutzen + case TypeClass_ANY: + { + aRetVal = sbxToUnoValueImpl( pVar ); + } + break; + + case TypeClass_BOOLEAN: + { + sal_Bool b = pVar->GetBool(); + aRetVal.setValue( &b, getBooleanCppuType() ); + break; + } + case TypeClass_CHAR: + { + sal_Unicode c = pVar->GetChar(); + aRetVal.setValue( &c , getCharCppuType() ); + break; + } + case TypeClass_STRING: aRetVal <<= ::rtl::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() ); + ::rtl::OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + + // Pruefen, ob das Interface wirklich unterstuetzt wird + if( !x->queryInterface( aClassType ).hasValue() ) + { + aRetStr.AppendAscii( " (ERROR: Not really supported!)\n" ); + } + // Gibt es Super-Interfaces + else + { + aRetStr.AppendAscii( "\n" ); + + // Super-Interfaces holen + Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses(); + const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray(); + 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; +} + +String getBasicObjectTypeName( SbxObject* pObj ) +{ + String aName; + if( pObj ) + { + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + if( pUnoObj ) + aName = getDbgObjectNameImpl( pUnoObj ); + } + return aName; +} + +bool checkUnoObjectType( SbUnoObject* pUnoObj, + const String& aClass ) +{ + bool result = false; + Any aToInspectObj = pUnoObj->getUnoAny(); + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + if( eType != TypeClass_INTERFACE ) + return false; + const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue(); + Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY ); + if( xTypeProvider.is() ) + { + 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() ) + { + DBG_ERROR("failed to get XIdlClass for type"); + break; + } + ::rtl::OUString sClassName = xClass->getName(); + OSL_TRACE("Checking if object implements %s", + OUStringToOString( defaultNameSpace + aClass, + RTL_TEXTENCODING_UTF8 ).getStr() ); + // although interfaces in the ooo.vba.vba namespace + // obey the idl rules and have a leading X, in basic we + // want to be able to do something like + // 'dim wrkbooks as WorkBooks' + // so test assumes the 'X' has been dropped + sal_Int32 indexLastDot = sClassName.lastIndexOf('.'); + if ( indexLastDot > -1 && sClassName.copy( indexLastDot + 1).equalsIgnoreAsciiCase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("X") ) + aClass ) ) + { + result = true; + break; + } + } + } + return result; +} + +// Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces +String Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj ) +{ + Any aToInspectObj = pUnoObj->getUnoAny(); + + // #54898: Nur TypeClass Interface zulasssen + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + String aRet; + if( eType != TypeClass_INTERFACE ) + { + aRet += 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( ::rtl::OUString( pTD->pTypeName ) ); + + aRet.AppendAscii( "*** ERROR: No IdlClass for type \"" ); + aRet += TypeName; + aRet.AppendAscii( "\"\n*** Please check type library\n" ); + } + } + } + else if( xClassProvider.is() ) + { + + DBG_ERROR( "XClassProvider not supported in UNO3" ); + } + } + return aRet; +} + + + +// Dbg-Hilfsmethode SbxDataType -> String +String Dbg_SbxDataType2String( SbxDataType eType ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Unknown Sbx-Type!") ); + switch( +eType ) + { + case SbxEMPTY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxEMPTY") ); break; + case SbxNULL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxNULL") ); break; + case SbxINTEGER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINTEGER") ); break; + case SbxLONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG") ); break; + case SbxSINGLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSINGLE") ); break; + case SbxDOUBLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDOUBLE") ); break; + case SbxCURRENCY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCURRENCY") ); break; + case SbxDECIMAL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDECIMAL") ); break; + case SbxDATE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATE") ); break; + case SbxSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSTRING") ); break; + case SbxOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxOBJECT") ); break; + case SbxERROR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxERROR") ); break; + case SbxBOOL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBOOL") ); break; + case SbxVARIANT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVARIANT") ); break; + case SbxDATAOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATAOBJECT") ); break; + case SbxCHAR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCHAR") ); break; + case SbxBYTE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBYTE") ); break; + case SbxUSHORT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSHORT") ); break; + case SbxULONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG") ); break; + case SbxLONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG64") ); break; + case SbxULONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG64") ); break; + case SbxSALINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT64") ); break; + case SbxSALUINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT64") ); break; + case SbxINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT") ); break; + case SbxUINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT") ); break; + case SbxVOID: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVOID") ); break; + case SbxHRESULT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxHRESULT") ); break; + case SbxPOINTER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxPOINTER") ); break; + case SbxDIMARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDIMARRAY") ); break; + case SbxCARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCARRAY") ); break; + case SbxUSERDEF: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSERDEF") ); break; + case SbxLPSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPSTR") ); break; + case SbxLPWSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPWSTR") ); break; + case SbxCoreSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCoreSTRING" ) ); break; + case SbxOBJECT | SbxARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxARRAY") ); break; + default: break; + } + return aRet; +} + +// Dbg-Hilfsmethode zum Anzeigen der Properties eines SbUnoObjects +String Impl_DumpProperties( SbUnoObject* pUnoObj ) +{ + String aRet( RTL_CONSTASCII_USTRINGPARAM("Properties of object ") ); + String aObjName = getDbgObjectName( pUnoObj ); + aRet += aObjName; + + // Uno-Infos auswerten, um Arrays zu erkennen + Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess(); + if( !xAccess.is() ) + { + Reference< XInvocation > xInvok = pUnoObj->getInvocation(); + if( xInvok.is() ) + xAccess = xInvok->getIntrospection(); + } + if( !xAccess.is() ) + { + aRet.AppendAscii( "\nUnknown, no introspection available\n" ); + return aRet; + } + + Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + 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( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + else if( bInvocation && mxInvocation.is() ) + { + try + { + // Wert holen + Any aRetAny = mxInvocation->getValue( pProp->GetName() ); + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + if( !bInvocation && mxUnoAccess.is() ) + { + if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY ) + { + StarBASIC::Error( SbERR_PROP_READONLY ); + return; + } + + // Wert von Uno nach Sbx uebernehmen + Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); + try + { + // Wert setzen + Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + xPropSet->setPropertyValue( pProp->GetName(), aAnyValue ); + // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist + // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an + // Ansonsten kann auch FastPropertySet genutzt werden + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + else if( bInvocation && mxInvocation.is() ) + { + // Wert von Uno nach Sbx uebernehmen + Any aAnyValue = sbxToUnoValueImpl( pVar ); + try + { + // Wert setzen + mxInvocation->setValue( pProp->GetName(), aAnyValue ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + } + else if( pMeth ) + { + bool bInvocation = pMeth->isInvocationBased(); + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Anzahl Parameter -1 wegen Param0 == this + 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 = pINST->IsCompatibility(); + if( pArgNamesArray ) + { + Sequence< ::rtl::OUString >& rNameSeq = pArgNamesArray->getNames(); + ::rtl::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 ); + + ::rtl::OUString aParamName = pNames[iSbx]; + if( aParamName.getLength() ) + { + oleautomation::NamedArgument aNamedArgument; + aNamedArgument.Name = aParamName; + aNamedArgument.Value = aValAny; + pAnyArgs[i] <<= aNamedArgument; + } + else + { + pAnyArgs[i] = aValAny; + } + } + } + else + { + for( i = 0 ; i < nParamCount ; i++ ) + { + // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen! + pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (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( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + 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_ ) + , bNeedIntrospection( TRUE ) +{ + 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; + } + } + + 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; + +void clearUnoMethods( void ) +{ + SbUnoMethod* pMeth = pFirst; + while( pMeth ) + { + pMeth->SbxValue::Clear(); + pMeth = pMeth->pNext; + } +} + + +SbUnoMethod::SbUnoMethod +( + const String& aName_, + SbxDataType eSbxType, + Reference< XIdlMethod > xUnoMethod_, + bool bInvocation +) + : 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]; + ::rtl::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() +{} + + +SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t ) +{ + static Reference< XIdlMethod > xDummyMethod; + static Property aDummyProp; + + SbxVariable* pRes = SbxObject::Find( rName, t ); + + if( bNeedIntrospection ) + doIntrospection(); + + // Neu 4.3.1999: Properties on Demand anlegen, daher jetzt perIntrospectionAccess + // suchen, ob doch eine Property oder Methode des geforderten Namens existiert + if( !pRes ) + { + ::rtl::OUString aUName( rName ); + if( mxUnoAccess.is() ) + { + if( mxExactName.is() ) + { + ::rtl::OUString aUExactName = mxExactName->getExactName( aUName ); + if( aUExactName.getLength() ) + aUName = aUExactName; + } + if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) ) + { + const Property& rProp = mxUnoAccess-> + getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + + // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden + SbxDataType eSbxType; + if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) + eSbxType = SbxVARIANT; + else + eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); + + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, 0, false ); + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + else if( mxUnoAccess->hasMethod( aUName, + MethodConcept::ALL - MethodConcept::DANGEROUS ) ) + { + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = mxUnoAccess-> + getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS ); + + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(), + unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + + // Wenn immer noch nichts gefunden wurde, muss geprueft werden, ob NameAccess vorliegt + if( !pRes ) + { + try + { + Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); + ::rtl::OUString aUName2( rName ); + + if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) ) + { + Any aAny = xNameAccess->getByName( aUName2 ); + + // ACHTUNG: Die hier erzeugte Variable darf wegen bei XNameAccess + // nicht als feste Property in das Object aufgenommen werden und + // wird daher nirgendwo gehalten. + // Wenn das Probleme gibt, muss das kuenstlich gemacht werden oder + // es muss eine Klasse SbUnoNameAccessProperty geschaffen werden, + // bei der die Existenz staendig neu ueberprueft und die ggf. weg- + // geworfen wird, wenn der Name nicht mehr gefunden wird. + pRes = new SbxVariable( SbxVARIANT ); + unoToSbxValue( pRes, aAny ); + } + } + catch( NoSuchElementException& e ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); + } + catch( const Exception& ) + { + // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird + if( !pRes ) + pRes = new SbxVariable( SbxVARIANT ); + + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + if( !pRes && mxInvocation.is() ) + { + if( mxExactNameInvocation.is() ) + { + ::rtl::OUString aUExactName = mxExactNameInvocation->getExactName( aUName ); + if( aUExactName.getLength() ) + aUName = aUExactName; + } + + try + { + if( mxInvocation->hasProperty( aUName ) ) + { + // Property anlegen und reinbraten + SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, aDummyProp, 0, true ); + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + else if( mxInvocation->hasMethod( aUName ) ) + { + // SbUnoMethode anlegen und reinbraten + SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + } + 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 ) && ( eType != TypeClass_EXCEPTION ) ) + return NULL; + + // Instanz erzeugen + Any aNewAny; + xClass->createObject( aNewAny ); + + // SbUnoObject daraus basteln + SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny ); + return pUnoObj; +} + + +// Factory-Klasse fuer das Anlegen von Uno-Structs per DIM AS NEW +SbxBase* SbUnoFactory::Create( UINT16, UINT32 ) +{ + // Ueber SbxId laeuft in Uno nix + return NULL; +} + +SbxObject* SbUnoFactory::CreateObject( const String& rClassName ) +{ + return Impl_CreateUnoStruct( rClassName ); +} + + +// Provisorische Schnittstelle fuer UNO-Anbindung +// Liefert ein SbxObject, das ein Uno-Interface wrappt +SbxObjectRef GetSbUnoObject( const String& aName, const Any& aUnoObj_ ) +{ + return new SbUnoObject( aName, aUnoObj_ ); +} + +// Force creation of all properties for debugging +void createAllObjectProperties( SbxObject* pObj ) +{ + if( !pObj ) + return; + + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + if( pUnoObj ) + pUnoObj->createAllProperties(); + else + pObj->GetAll( SbxCLASS_DONTCARE ); +} + + +void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 1 Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aClassName = rPar.Get(1)->GetString(); + + // Versuchen, gleichnamige Struct zu erzeugen + SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName ); + if( !xUnoObj ) + return; + + // Objekt zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( (SbUnoObject*)xUnoObj ); +} + +void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 1 Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aServiceName = rPar.Get(1)->GetString(); + + // Service suchen und instanzieren + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + Reference< XInterface > xInterface; + if ( xFactory.is() ) + { + try + { + xInterface = xFactory->createInstance( aServiceName ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + + SbxVariableRef refVar = rPar.Get(0); + if( xInterface.is() ) + { + Any aAny; + aAny <<= xInterface; + + // SbUnoObject daraus basteln und zurueckliefern + SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny ); + if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID ) + { + // Objekt zurueckliefern + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } + } + else + { + refVar->PutObject( NULL ); + } +} + +void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 2 Parameter + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aServiceName = rPar.Get(1)->GetString(); + Any aArgAsAny = sbxToUnoValue( rPar.Get(2), + getCppuType( (Sequence<Any>*)0 ) ); + Sequence< Any > aArgs; + aArgAsAny >>= aArgs; + + // Service suchen und instanzieren + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + Reference< XInterface > xInterface; + if ( xFactory.is() ) + { + try + { + xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + + SbxVariableRef refVar = rPar.Get(0); + if( xInterface.is() ) + { + Any aAny; + aAny <<= xInterface; + + // SbUnoObject daraus basteln und zurueckliefern + SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny ); + if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID ) + { + // Objekt zurueckliefern + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } + } + else + { + refVar->PutObject( NULL ); + } +} + +void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + SbxVariableRef refVar = rPar.Get(0); + + // Globalen Service-Manager holen + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + if( xFactory.is() ) + { + Any aAny; + aAny <<= xFactory; + + // SbUnoObject daraus basteln und zurueckliefern + SbUnoObjectRef xUnoObj = new SbUnoObject( String( RTL_CONSTASCII_USTRINGPARAM("ProcessServiceManager") ), aAny ); + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } +} + +void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 2 Parameter + USHORT nParCount = rPar.Count(); + if( nParCount < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Variable fuer Rueckgabewert + SbxVariableRef refVar = rPar.Get(0); + refVar->PutBool( FALSE ); + + // Uno-Objekt holen + SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject(); + if( !(pObj && pObj->ISA(SbUnoObject)) ) + return; + Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + TypeClass eType = aAny.getValueType().getTypeClass(); + if( eType != TypeClass_INTERFACE ) + return; + + // Interface aus dem Any besorgen + Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue(); + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( !xCoreReflection.is() ) + return; + + for( USHORT i = 2 ; i < nParCount ; i++ ) + { + // Interface-Name der struct holen + String aIfaceName = rPar.Get( i )->GetString(); + + // Klasse suchen + Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName ); + if( !xClass.is() ) + return; + + // Pruefen, ob das Interface unterstuetzt wird + ::rtl::OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + if( !x->queryInterface( aClassType ).hasValue() ) + return; + } + + // Alles hat geklappt, dann TRUE liefern + refVar->PutBool( TRUE ); +} + +void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen mindestens 1 Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Variable fuer Rueckgabewert + SbxVariableRef refVar = rPar.Get(0); + refVar->PutBool( FALSE ); + + // Uno-Objekt holen + SbxVariableRef xParam = rPar.Get( 1 ); + if( !xParam->IsObject() ) + return; + SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject(); + if( !(pObj && pObj->ISA(SbUnoObject)) ) + return; + Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); + TypeClass eType = aAny.getValueType().getTypeClass(); + if( eType == TypeClass_STRUCT ) + refVar->PutBool( TRUE ); +} + + +void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Variable fuer Rueckgabewert + SbxVariableRef refVar = rPar.Get(0); + refVar->PutBool( FALSE ); + + // Uno-Objekte holen + SbxVariableRef xParam1 = rPar.Get( 1 ); + if( !xParam1->IsObject() ) + return; + SbxBaseRef pObj1 = (SbxBase*)xParam1->GetObject(); + if( !(pObj1 && pObj1->ISA(SbUnoObject)) ) + return; + Any aAny1 = ((SbUnoObject*)(SbxBase*)pObj1)->getUnoAny(); + TypeClass eType1 = aAny1.getValueType().getTypeClass(); + if( eType1 != TypeClass_INTERFACE ) + return; + Reference< XInterface > x1; + aAny1 >>= x1; + //XInterfaceRef x1 = *(XInterfaceRef*)aAny1.get(); + + SbxVariableRef xParam2 = rPar.Get( 2 ); + if( !xParam2->IsObject() ) + return; + SbxBaseRef pObj2 = (SbxBase*)xParam2->GetObject(); + if( !(pObj2 && pObj2->ISA(SbUnoObject)) ) + return; + Any aAny2 = ((SbUnoObject*)(SbxBase*)pObj2)->getUnoAny(); + TypeClass eType2 = aAny2.getValueType().getTypeClass(); + if( eType2 != TypeClass_INTERFACE ) + return; + Reference< XInterface > x2; + aAny2 >>= x2; + //XInterfaceRef x2 = *(XInterfaceRef*)aAny2.get(); + + if( x1 == x2 ) + refVar->PutBool( TRUE ); +} + +typedef std::hash_map< ::rtl::OUString, std::vector< ::rtl::OUString >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleHash; + + +// helper wrapper function to interact with TypeProvider and +// XTypeDescriptionEnumerationAccess. +// if it fails for whatever reason +// returned Reference<> be null e.g. .is() will be false + +Reference< XTypeDescriptionEnumeration > +getTypeDescriptorEnumeration( const ::rtl::OUString& sSearchRoot, + const Sequence< TypeClass >& types, TypeDescriptionSearchDepth depth ) +{ + Reference< XTypeDescriptionEnumeration > xEnum; + Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY ); + if ( xTypeEnumAccess.is() ) + { + try + { + xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration( + sSearchRoot, types, depth ); + } + catch( NoSuchTypeNameException& /*nstne*/ ) {} + catch( InvalidTypeNameException& /*nstne*/ ) {} + } + return xEnum; +} + +typedef std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > VBAConstantsHash; + +SbxVariable* getVBAConstant( const String& rName ) +{ + SbxVariable* pConst = NULL; + static VBAConstantsHash aConstCache; + static bool isInited = false; + if ( !isInited ) + { + Sequence< TypeClass > types(1); + types[ 0 ] = TypeClass_CONSTANTS; + Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( defaultNameSpace, types, TypeDescriptionSearchDepth_INFINITE ); + + if ( !xEnum.is() ) + return NULL; + + while ( xEnum->hasMoreElements() ) + { + Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY ); + if ( xConstants.is() ) + { + Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants(); + Reference< XConstantTypeDescription >* pSrc = aConsts.getArray(); + sal_Int32 nLen = aConsts.getLength(); + for ( sal_Int32 index =0; index<nLen; ++pSrc, ++index ) + { + Reference< XConstantTypeDescription >& rXConst = + *pSrc; + ::rtl::OUString sFullName = rXConst->getName(); + sal_Int32 indexLastDot = sFullName.lastIndexOf('.'); + ::rtl::OUString sLeafName; + if ( indexLastDot > -1 ) + sLeafName = sFullName.copy( indexLastDot + 1); + aConstCache[ sLeafName.toAsciiLowerCase() ] = rXConst->getConstantValue(); + } + } + } + isInited = true; + } + ::rtl::OUString sKey( rName ); + VBAConstantsHash::const_iterator it = aConstCache.find( sKey.toAsciiLowerCase() ); + if ( it != aConstCache.end() ) + { + pConst = new SbxVariable( SbxVARIANT ); + pConst->SetName( rName ); + unoToSbxValue( pConst, it->second ); + } + return pConst; +} + +// Funktion, um einen globalen Bezeichner im +// UnoScope zu suchen und fuer Sbx zu wrappen +SbUnoClass* findUnoClass( const String& rName ) +{ + // #105550 Check if module exists + SbUnoClass* pUnoClass = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS ) + pUnoClass = new SbUnoClass( rName ); + } + } + return pUnoClass; +} + +SbxVariable* SbUnoClass::Find( const XubString& rName, SbxClassType t ) +{ + (void)t; + + SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE ); + + // Wenn nichts gefunden wird, ist das Sub-Modul noch nicht bekannt + if( !pRes ) + { + // Wenn es schon eine Klasse ist, nach einen Feld fragen + if( m_xClass.is() ) + { + // Ist es ein Field + ::rtl::OUString aUStr( rName ); + Reference< XIdlField > xField = m_xClass->getField( aUStr ); + Reference< XIdlClass > xClass; + if( xField.is() ) + { + try + { + Any aAny; + aAny = xField->get( aAny ); + + // Nach Sbx wandeln + pRes = new SbxVariable( SbxVARIANT ); + pRes->SetName( rName ); + unoToSbxValue( pRes, aAny ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + } + } + else + { + // Vollqualifizierten Namen erweitern + String aNewName = GetName(); + aNewName.AppendAscii( "." ); + aNewName += rName; + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( xCoreReflection.is() ) + { + // Ist es eine Konstante? + Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY ); + if( xHarryName.is() ) + { + try + { + Any aValue = xHarryName->getByHierarchicalName( aNewName ); + TypeClass eType = aValue.getValueType().getTypeClass(); + + // Interface gefunden? Dann ist es eine Klasse + if( eType == TypeClass_INTERFACE ) + { + Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue(); + Reference< XIdlClass > xClass( xIface, UNO_QUERY ); + if( xClass.is() ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass ); + pRes->PutObject( xWrapper ); + } + } + else + { + pRes = new SbxVariable( SbxVARIANT ); + unoToSbxValue( pRes, aValue ); + } + } + catch( NoSuchElementException& e1 ) + { + String aMsg = implGetExceptionMsg( e1 ); + } + } + + // Sonst wieder als Klasse annehmen + if( !pRes ) + { + SbUnoClass* pNewClass = findUnoClass( aNewName ); + if( pNewClass ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pNewClass; + pRes->PutObject( xWrapper ); + } + } + + // An UNO service? + if( !pRes ) + { + SbUnoService* pUnoService = findUnoService( aNewName ); + if( pUnoService ) + { + pRes = new SbxVariable( SbxVARIANT ); + SbxObjectRef xWrapper = (SbxObject*)pUnoService; + pRes->PutObject( xWrapper ); + } + } + } + } + + 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; +} + + +SbUnoService* findUnoService( const String& rName ) +{ + SbUnoService* pSbUnoService = NULL; + + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + if( xTypeAccess->hasByHierarchicalName( rName ) ) + { + Any aRet = xTypeAccess->getByHierarchicalName( rName ); + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + + if( xTypeDesc.is() ) + { + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + if( eTypeClass == TypeClass_SERVICE ) + { + Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY ); + if( xServiceTypeDesc.is() ) + pSbUnoService = new SbUnoService( rName, xServiceTypeDesc ); + } + } + } + return pSbUnoService; +} + +SbxVariable* SbUnoService::Find( const String& rName, SbxClassType ) +{ + SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD ); + + if( !pRes ) + { + // Wenn es schon eine Klasse ist, nach einen Feld fragen + if( m_bNeedsInit && m_xServiceTypeDesc.is() ) + { + m_bNeedsInit = false; + + Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors(); + const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray(); + int nCtorCount = aSCDSeq.getLength(); + for( int i = 0 ; i < nCtorCount ; ++i ) + { + Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i]; + + String aName( xCtor->getName() ); + if( !aName.Len() ) + { + if( xCtor->isDefaultConstructor() ) + aName = String::CreateFromAscii( "create" ); + } + + if( aName.Len() ) + { + // Create and insert SbUnoServiceCtor + SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor ); + QuickInsert( (SbxVariable*)xSbCtorRef ); + pRes = xSbCtorRef; + } + } + } + } + + return pRes; +} + +void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pParams = pVar->GetParameters(); + SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar); + if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Parameter count -1 because of Param0 == this + UINT32 nParamCount = pParams ? ((UINT32)pParams->Count() - 1) : 0; + Sequence<Any> args; + BOOL bOutParams = FALSE; + + Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc(); + Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters(); + const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray(); + UINT32 nUnoParamCount = aParameterSeq.getLength(); + + // Default: Ignore not needed parameters + bool bParameterError = false; + + // Is the last parameter a rest parameter? + bool bRestParameterMode = false; + if( nUnoParamCount > 0 ) + { + Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ]; + if( xLastParam.is() ) + { + if( xLastParam->isRestParameter() ) + bRestParameterMode = true; + } + } + + // Too many parameters with context as first parameter? + USHORT nSbxParameterOffset = 1; + USHORT nParameterOffsetByContext = 0; + Reference < XComponentContext > xFirstParamContext; + if( nParamCount > nUnoParamCount ) + { + // Check if first parameter is a context and use it + // then in createInstanceWithArgumentsAndContext + Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) ); + if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() ) + nParameterOffsetByContext = 1; + } + + UINT32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext; + UINT32 nAllocParamCount = nEffectiveParamCount; + if( nEffectiveParamCount > nUnoParamCount ) + { + if( !bRestParameterMode ) + { + nEffectiveParamCount = nUnoParamCount; + nAllocParamCount = nUnoParamCount; + } + } + // Not enough parameters? + else if( nUnoParamCount > nEffectiveParamCount ) + { + // RestParameterMode only helps if one (the last) parameter is missing + int nDiff = nUnoParamCount - nEffectiveParamCount; + if( !bRestParameterMode || nDiff > 1 ) + { + bParameterError = true; + StarBASIC::Error( SbERR_NOT_OPTIONAL ); + } + } + + if( !bParameterError ) + { + if( nAllocParamCount > 0 ) + { + args.realloc( nAllocParamCount ); + Any* pAnyArgs = args.getArray(); + for( UINT32 i = 0 ; i < nEffectiveParamCount ; i++ ) + { + USHORT iSbx = (USHORT)(i + nSbxParameterOffset + nParameterOffsetByContext); + + // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount + Reference< XParameter > xParam; + if( i < nUnoParamCount ) + { + xParam = pParameterSeq[i]; + if( !xParam.is() ) + continue; + + Reference< XTypeDescription > xParamTypeDesc = xParam->getType(); + if( !xParamTypeDesc.is() ) + continue; + com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() ); + + // sbx paramter needs offset 1 + pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType ); + + // Check for out parameter if not already done + if( !bOutParams ) + { + if( xParam->isOut() ) + bOutParams = TRUE; + } + } + else + { + pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) ); + } + } + } + + // "Call" ctor using createInstanceWithArgumentsAndContext + Reference < XComponentContext > xContext; + if( xFirstParamContext.is() ) + { + xContext = xFirstParamContext; + } + else + { + Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); + xContext.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW ); + } + Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); + + Any aRetAny; + if( xServiceMgr.is() ) + { + String aServiceName = GetName(); + Reference < XInterface > xRet; + try + { + xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext ); + } + catch( const Exception& ) + { + implHandleAnyException( ::cppu::getCaughtException() ); + } + aRetAny <<= xRet; + } + unoToSbxValue( pVar, aRetAny ); + + // Copy back out parameters? + if( bOutParams ) + { + const Any* pAnyArgs = args.getConstArray(); + + for( UINT32 j = 0 ; j < nUnoParamCount ; j++ ) + { + Reference< XParameter > xParam = pParameterSeq[j]; + if( !xParam.is() ) + continue; + + if( xParam->isOut() ) + unoToSbxValue( (SbxVariable*)pParams->Get( (USHORT)(j+1) ), pAnyArgs[ j ] ); + } + } + } + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + + + +static SbUnoServiceCtor* pFirstCtor = NULL; + +void clearUnoServiceCtors( void ) +{ + SbUnoServiceCtor* pCtor = pFirstCtor; + while( pCtor ) + { + pCtor->SbxValue::Clear(); + pCtor = pCtor->pNext; + } +} + +SbUnoServiceCtor::SbUnoServiceCtor( const String& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc ) + : SbxMethod( aName_, SbxOBJECT ) + , m_xServiceCtorDesc( xServiceCtorDesc ) +{ +} + +SbUnoServiceCtor::~SbUnoServiceCtor() +{ +} + +SbxInfo* SbUnoServiceCtor::GetInfo() +{ + SbxInfo* pRet = NULL; + + return pRet; +} + + + +//======================================================================== +//======================================================================== +//======================================================================== + +// Implementation eines EventAttacher-bezogenen AllListeners, der +// nur einzelne Events an einen allgemeinen AllListener weiterleitet +class BasicAllListener_Impl : public BasicAllListenerHelper +{ + virtual void firing_impl(const AllEventObject& Event, Any* pRet); + +public: + SbxObjectRef xSbxObj; + ::rtl::OUString aPrefixName; + + BasicAllListener_Impl( const ::rtl::OUString& aPrefixName ); + ~BasicAllListener_Impl(); + + // Methoden von XInterface + //virtual BOOL queryInterface( Uik aUik, Reference< XInterface > & rOut ); + + // Methoden von XAllListener + virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException ); + virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException ); + + // Methoden von XEventListener + virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException ); +}; + + +//======================================================================== +BasicAllListener_Impl::BasicAllListener_Impl +( + const ::rtl::OUString & aPrefixName_ +) + : aPrefixName( aPrefixName_ ) +{ +} + +//======================================================================== +BasicAllListener_Impl::~BasicAllListener_Impl() +{ +} + +//======================================================================== + +void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet ) +{ + NAMESPACE_VOS(OGuard) guard( Application::GetSolarMutex() ); + + if( xSbxObj.Is() ) + { + ::rtl::OUString aMethodName = aPrefixName; + aMethodName = aMethodName + Event.MethodName; + + SbxVariable * pP = xSbxObj; + while( pP->GetParent() ) + { + pP = pP->GetParent(); + StarBASIC * pLib = PTR_CAST(StarBASIC,pP); + if( pLib ) + { + // In Basic Array anlegen + SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT ); + const Any * pArgs = Event.Arguments.getConstArray(); + INT32 nCount = Event.Arguments.getLength(); + for( INT32 i = 0; i < nCount; i++ ) + { + // Elemente wandeln + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, pArgs[i] ); + xSbxArray->Put( xVar, sal::static_int_cast< USHORT >(i+1) ); + } + + pLib->Call( aMethodName, xSbxArray ); + + // Return-Wert aus dem Param-Array holen, wenn verlangt + if( pRet ) + { + SbxVariable* pVar = xSbxArray->Get( 0 ); + if( pVar ) + { + // #95792 Avoid a second call + USHORT nFlags = pVar->GetFlags(); + pVar->SetFlag( SBX_NO_BROADCAST ); + *pRet = sbxToUnoValueImpl( pVar ); + pVar->SetFlags( nFlags ); + } + } + break; + } + } + } +} + + +// Methoden von XAllListener +void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException ) +{ + firing_impl( Event, NULL ); +} + +Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException ) +{ + Any aRetAny; + firing_impl( Event, &aRetAny ); + return aRetAny; +} + +//======================================================================== +// Methoden von XEventListener +void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException ) +{ + NAMESPACE_VOS(OGuard) guard( Application::GetSolarMutex() ); + + xSbxObj.Clear(); +} + + + +//************************************************************************* +// class InvocationToAllListenerMapper +// helper class to map XInvocation to XAllListener (also in project eventattacher!) +//************************************************************************* +class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation > +{ +public: + InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType, + const Reference< XAllListener >& AllListener, const Any& Helper ); + + // XInvocation + virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException ); + virtual Any SAL_CALL invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) + throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ); + virtual void SAL_CALL setValue(const ::rtl::OUString& PropertyName, const Any& Value) + throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ); + virtual Any SAL_CALL getValue(const ::rtl::OUString& PropertyName) throw( UnknownPropertyException, RuntimeException ); + virtual sal_Bool SAL_CALL hasMethod(const ::rtl::OUString& Name) throw( RuntimeException ); + virtual sal_Bool SAL_CALL hasProperty(const ::rtl::OUString& Name) throw( RuntimeException ); + +private: + Reference< XIdlReflection > m_xCoreReflection; + Reference< XAllListener > m_xAllListener; + Reference< XIdlClass > m_xListenerType; + Any m_Helper; +}; + + +// Function to replace AllListenerAdapterService::createAllListerAdapter +Reference< XInterface > createAllListenerAdapter +( + const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory, + const Reference< XIdlClass >& xListenerType, + const Reference< XAllListener >& xListener, + const Any& Helper +) +{ + Reference< XInterface > xAdapter; + if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() ) + { + Reference< XInvocation > xInvocationToAllListenerMapper = + (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper ); + Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() ); + xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType ); + } + return xAdapter; +} + + +//-------------------------------------------------------------------------------------------------- +// InvocationToAllListenerMapper +InvocationToAllListenerMapper::InvocationToAllListenerMapper + ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper ) + : m_xAllListener( AllListener ) + , m_xListenerType( ListenerType ) + , m_Helper( Helper ) +{ +} + +//************************************************************************* +Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void) + throw( RuntimeException ) +{ + return Reference< XIntrospectionAccess >(); +} + +//************************************************************************* +Any SAL_CALL InvocationToAllListenerMapper::invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params, + Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) + throw( IllegalArgumentException, CannotConvertException, + InvocationTargetException, RuntimeException ) +{ + (void)OutParamIndex; + (void)OutParam ; + + Any aRet; + + // Check if to firing or approveFiring has to be called + Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName ); + sal_Bool bApproveFiring = sal_False; + if( !xMethod.is() ) + return aRet; + Reference< XIdlClass > xReturnType = xMethod->getReturnType(); + Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes(); + if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) || + aExceptionSeq.getLength() > 0 ) + { + bApproveFiring = sal_True; + } + else + { + Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos(); + sal_uInt32 nParamCount = aParamSeq.getLength(); + if( nParamCount > 1 ) + { + const ParamInfo* pInfos = aParamSeq.getConstArray(); + for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) + { + if( pInfos[ i ].aMode != ParamMode_IN ) + { + bApproveFiring = sal_True; + break; + } + } + } + } + + AllEventObject aAllEvent; + aAllEvent.Source = (OWeakObject*) this; + aAllEvent.Helper = m_Helper; + aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() ); + aAllEvent.MethodName = FunctionName; + aAllEvent.Arguments = Params; + if( bApproveFiring ) + aRet = m_xAllListener->approveFiring( aAllEvent ); + else + m_xAllListener->firing( aAllEvent ); + return aRet; +} + +//************************************************************************* +void SAL_CALL InvocationToAllListenerMapper::setValue(const ::rtl::OUString& PropertyName, const Any& Value) + throw( UnknownPropertyException, CannotConvertException, + InvocationTargetException, RuntimeException ) +{ + (void)PropertyName; + (void)Value; +} + +//************************************************************************* +Any SAL_CALL InvocationToAllListenerMapper::getValue(const ::rtl::OUString& PropertyName) + throw( UnknownPropertyException, RuntimeException ) +{ + (void)PropertyName; + + return Any(); +} + +//************************************************************************* +sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name ); + return xMethod.is(); +} + +//************************************************************************* +sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const ::rtl::OUString& Name) + throw( RuntimeException ) +{ + Reference< XIdlField > xField = m_xListenerType->getField( Name ); + return xField.is(); +} + +//======================================================================== +// Uno-Service erzeugen +// 1. Parameter == Prefix-Name der Makros +// 2. Parameter == voll qualifizierter Name des Listeners +void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +//RTLFUNC(CreateUnoListener) +{ + (void)bWrite; + + // Wir brauchen 2 Parameter + if ( rPar.Count() != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aPrefixName = rPar.Get(1)->GetString(); + String aListenerClassName = rPar.Get(2)->GetString(); + + // CoreReflection holen + Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); + if( !xCoreReflection.is() ) + return; + + // AllListenerAdapterService holen + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + if( !xFactory.is() ) + return; + + // Klasse suchen + Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName ); + if( !xClass.is() ) + return; + + // AB, 30.11.1999 InvocationAdapterFactory holen + Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >( + xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ), UNO_QUERY ); + + BasicAllListener_Impl * p; + Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName ); + Any aTmp; + Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp ); + if( !xLst.is() ) + return; + + ::rtl::OUString aClassName = xClass->getName(); + Type aClassType( xClass->getTypeClass(), aClassName.getStr() ); + aTmp = xLst->queryInterface( aClassType ); + if( !aTmp.hasValue() ) + return; + + SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp ); + p->xSbxObj = pUnoObj; + p->xSbxObj->SetParent( pBasic ); + + // #100326 Register listener object to set Parent NULL in Dtor + SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners(); + xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() ); + + // Objekt zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( p->xSbxObj ); +} + +//======================================================================== +// Represents the DefaultContext property of the ProcessServiceManager +// in the Basic runtime system. +void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + SbxVariableRef refVar = rPar.Get(0); + + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet> xPSMPropertySet( xFactory, UNO_QUERY ); + if( xPSMPropertySet.is() ) + { + Any aContextAny = xPSMPropertySet->getPropertyValue( + String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ); + + SbUnoObjectRef xUnoObj = new SbUnoObject + ( String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ), + aContextAny ); + refVar->PutObject( (SbUnoObject*)xUnoObj ); + } + else + { + refVar->PutObject( NULL ); + } +} + +//======================================================================== +// Creates a Basic wrapper object for a strongly typed Uno value +// 1. parameter: Uno type as full qualified type name, e.g. "byte[]" +void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + // 2 parameters needed + if ( rPar.Count() != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Klassen-Name der struct holen + String aTypeName = rPar.Get(1)->GetString(); + SbxVariable* pVal = rPar.Get(2); + + // Check the type + Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl(); + Any aRet; + try + { + aRet = xTypeAccess->getByHierarchicalName( aTypeName ); + } + catch( NoSuchElementException& e1 ) + { + String aNoSuchElementExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.NoSuchElementException" ) ); + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e1, aNoSuchElementExceptionName ) ); + return; + } + Reference< XTypeDescription > xTypeDesc; + aRet >>= xTypeDesc; + TypeClass eTypeClass = xTypeDesc->getTypeClass(); + Type aDestType( eTypeClass, aTypeName ); + + + // Preconvert value + Any aVal = sbxToUnoValueImpl( pVal ); + Any aConvertedVal = convertAny( aVal, aDestType ); + + /* + // Convert + Reference< XTypeConverter > xConverter = getTypeConverter_Impl(); + try + { + aConvertedVal = xConverter->convertTo( aVal, aDestType ); + } + catch( IllegalArgumentException& e1 ) + { + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( ::cppu::getCaughtException() ) ); + return; + } + catch( CannotConvertException& e2 ) + { + String aCannotConvertExceptionName + ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) ); + StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, + implGetExceptionMsg( e2, aCannotConvertExceptionName ) ); + return; + } + */ + + SbxVariableRef refVar = rPar.Get(0); + SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal ); + refVar->PutObject( xUnoAnyObject ); +} + diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx new file mode 100644 index 000000000000..2d5f4f7cdf89 --- /dev/null +++ b/basic/source/classes/sbxmod.cxx @@ -0,0 +1,1503 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxmod.cxx,v $ + * $Revision: 1.44.10.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <list> + +#include <vos/macros.hxx> +#include <vcl/svapp.hxx> +#include <tools/stream.hxx> +#include <svtools/brdcst.hxx> +#include <tools/shl.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include <sbjsmeth.hxx> +#include "sbjsmod.hxx" +#include "sbintern.hxx" +#include "image.hxx" +#include "opcodes.hxx" +#include "runtime.hxx" +#include "token.hxx" +#include "sbunoobj.hxx" + + +//#include <basic/hilight.hxx> +#include <svtools/syntaxhighlight.hxx> + +#include <basic/basrdll.hxx> +#include <vos/mutex.hxx> + + +// for the bsearch +#ifdef WNT +#define CDECL _cdecl +#endif +#if defined(UNX) || defined(OS2) +#define CDECL +#endif +#ifdef UNX +#include <sys/resource.h> +#endif + +#include <stdio.h> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> + using namespace ::com::sun::star; + + +TYPEINIT1(SbModule,SbxObject) +TYPEINIT1(SbMethod,SbxMethod) +TYPEINIT1(SbProperty,SbxProperty) +TYPEINIT1(SbProcedureProperty,SbxProperty) +TYPEINIT1(SbJScriptModule,SbModule) +TYPEINIT1(SbJScriptMethod,SbMethod) + +SV_DECL_VARARR(SbiBreakpoints,USHORT,4,4) +SV_IMPL_VARARR(SbiBreakpoints,USHORT) + + +SV_IMPL_VARARR(HighlightPortions, HighlightPortion) + +class AsyncQuitHandler +{ + AsyncQuitHandler() {} + AsyncQuitHandler( const AsyncQuitHandler&); +public: + static AsyncQuitHandler& instance() + { + static AsyncQuitHandler dInst; + return dInst; + } + + void QuitApplication() + { + uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + if ( xFactory.is() ) + { + uno::Reference< frame::XDesktop > xDeskTop( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ) ), uno::UNO_QUERY ); + if ( xDeskTop.is() ) + xDeskTop->terminate(); + } + } + DECL_LINK( OnAsyncQuit, void* ); +}; + +IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ ) +{ + QuitApplication(); + return 0L; +} + +#if 0 +bool UnlockControllerHack( StarBASIC* pBasic ) +{ + bool bRes = false; + if ( pBasic && pBasic->IsDocBasic() ) + { + uno::Any aUnoVar; + ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( "ThisComponent" ) ); + SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( pBasic->Find( sVarName, SbxCLASS_DONTCARE ) ); + if ( pGlobs ) + aUnoVar = pGlobs->getUnoAny(); + uno::Reference< frame::XModel > xModel( aUnoVar, uno::UNO_QUERY); + if ( xModel.is() ) + { + try + { + xModel->unlockControllers(); + bRes = true; + } + catch( uno::Exception& ) + { + } + } + } + return bRes; +} +#endif +///////////////////////////////////////////////////////////////////////////// + +// 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 ), pBreaks( NULL ), pClassData( NULL ) +{ + SetName( rName ); + SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH ); +} + +SbModule::~SbModule() +{ + if( pImage ) + delete pImage; + if( pBreaks ) + delete pBreaks; + 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 + +SbProperty* SbModule::GetProperty( const String& rName, SbxDataType t ) +{ + SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY ); + SbProperty* pProp = p ? PTR_CAST(SbProperty,p) : NULL; + if( p && !pProp ) + pProps->Remove( p ); + if( !pProp ) + { + pProp = new SbProperty( rName, t, this ); + pProp->SetFlag( SBX_READWRITE ); + pProp->SetParent( this ); + pProps->Put( pProp, pProps->Count() ); + StartListening( pProp->GetBroadcaster(), TRUE ); + } + return pProp; +} + +SbProcedureProperty* SbModule::GetProcedureProperty + ( const String& rName, SbxDataType t ) +{ + SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY ); + SbProcedureProperty* pProp = p ? PTR_CAST(SbProcedureProperty,p) : NULL; + if( p && !pProp ) + pProps->Remove( p ); + if( !pProp ) + { + pProp = new SbProcedureProperty( rName, t ); + pProp->SetFlag( SBX_READWRITE ); + pProp->SetParent( this ); + pProps->Put( pProp, pProps->Count() ); + StartListening( pProp->GetBroadcaster(), TRUE ); + } + return pProp; +} + +SbIfaceMapperMethod* SbModule::GetIfaceMapperMethod + ( const String& rName, SbMethod* pImplMeth ) +{ + SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD ); + SbIfaceMapperMethod* pMapperMethod = p ? PTR_CAST(SbIfaceMapperMethod,p) : NULL; + if( p && !pMapperMethod ) + pMethods->Remove( p ); + if( !pMapperMethod ) + { + pMapperMethod = new SbIfaceMapperMethod( rName, pImplMeth ); + pMapperMethod->SetParent( this ); + pMapperMethod->SetFlags( SBX_READ ); + pMethods->Put( pMapperMethod, pMethods->Count() ); + } + pMapperMethod->bInvalid = FALSE; + return pMapperMethod; +} + +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 + || ( ( eCurTok == VBASUPPORT ) && ( aTok.Next() == NUMBER ) && ( aTok.GetDbl()== 1 ) ) ) + 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 ); +} + +void SbModule::SetComment( const String& r ) +{ + aComment = r; + SetModified( 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 ); + } +} + +void ClearUnoObjectsInRTL_Impl( StarBASIC* pBasic ) +{ + // #67781 Rueckgabewerte der Uno-Methoden loeschen + clearUnoMethods(); + clearUnoServiceCtors();
+ + ClearUnoObjectsInRTL_Impl_Rek( pBasic ); + + // Oberstes Basic suchen + SbxObject* p = pBasic; + while( p->GetParent() ) + p = p->GetParent(); + if( ((StarBASIC*)p) != pBasic ) + ClearUnoObjectsInRTL_Impl_Rek( (StarBASIC*)p ); +} + +// Ausfuehren eines BASIC-Unterprogramms +USHORT SbModule::Run( SbMethod* pMeth ) +{ + static USHORT nMaxCallLevel = 0; + static String aMSOMacroRuntimeLibName = String::CreateFromAscii( "Launcher" ); + static String aMSOMacroRuntimeAppSymbol = String::CreateFromAscii( "Application" ); + + USHORT nRes = 0; + BOOL bDelInst = BOOL( pINST == NULL ); + StarBASICRef xBasic; + if( bDelInst ) + { + // #32779: Basic waehrend der Ausfuehrung festhalten + xBasic = (StarBASIC*) GetParent(); + + pINST = new SbiInstance( (StarBASIC*) GetParent() ); + + // Launcher problem + // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already + BOOL bWasError = SbxBase::GetError() != 0; + SbxVariable* pMSOMacroRuntimeLibVar = Find( aMSOMacroRuntimeLibName, SbxCLASS_OBJECT ); + if ( !bWasError && (SbxBase::GetError() == SbxERR_PROC_UNDEFINED) ) + SbxBase::ResetError(); + if( pMSOMacroRuntimeLibVar ) + { + StarBASIC* pMSOMacroRuntimeLib = PTR_CAST(StarBASIC,pMSOMacroRuntimeLibVar); + if( pMSOMacroRuntimeLib ) + { + USHORT nGblFlag = pMSOMacroRuntimeLib->GetFlags() & SBX_GBLSEARCH; + pMSOMacroRuntimeLib->ResetFlag( SBX_GBLSEARCH ); + SbxVariable* pAppSymbol = pMSOMacroRuntimeLib->Find( aMSOMacroRuntimeAppSymbol, SbxCLASS_METHOD ); + pMSOMacroRuntimeLib->SetFlag( nGblFlag ); + if( pAppSymbol ) + { + pMSOMacroRuntimeLib->SetFlag( SBX_EXTSEARCH ); // Could have been disabled before + GetSbData()->pMSOMacroRuntimLib = pMSOMacroRuntimeLib; + } + } + } + + // Error-Stack loeschen + SbErrorStack*& rErrStack = GetSbData()->pErrStack; + delete rErrStack; + rErrStack = NULL; + + if( nMaxCallLevel == 0 ) + { +#ifdef UNX + struct rlimit rl; + getrlimit ( RLIMIT_STACK, &rl ); + // printf( "RLIMIT_STACK = %ld\n", rl.rlim_cur ); +#endif +#if defined LINUX + // Empiric value, 900 = needed bytes/Basic call level + // for Linux including 10% safety margin + nMaxCallLevel = rl.rlim_cur / 900; +#elif defined SOLARIS + // Empiric value, 1650 = needed bytes/Basic call level + // for Solaris including 10% safety margin + nMaxCallLevel = rl.rlim_cur / 1650; +#elif defined WIN32 + nMaxCallLevel = 5800; +#else + nMaxCallLevel = MAXRECURSION; +#endif + } + } + + // Rekursion zu tief? + if( ++pINST->nCallLvl <= nMaxCallLevel ) + { + // Globale Variable in allen Mods definieren + GlobalRunInit( /* bBasicStart = */ bDelInst ); + + // Trat ein Compiler-Fehler auf? Dann starten wir nicht + if( GetSbData()->bGlobalInitErr == FALSE ) + { + if( bDelInst ) + { + SendHint( GetParent(), SBX_HINT_BASICSTART, pMeth ); + + // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out + // Erklaerung siehe runtime.cxx bei SbiInstance::CalcBreakCallLevel() + // BreakCallLevel ermitteln + pINST->CalcBreakCallLevel( pMeth->GetDebugFlags() ); + } + + SbModule* pOldMod = pMOD; + pMOD = this; + SbiRuntime* pRt = new SbiRuntime( this, pMeth, pMeth->nStart ); + pRt->pNext = pINST->pRun; + if( pRt->pNext ) + pRt->pNext->block(); + pINST->pRun = pRt; + if ( SbiRuntime ::isVBAEnabled() ) + { + pINST->EnableCompatibility( TRUE ); + pRt->SetVBAEnabled( true ); + } + while( pRt->Step() ) {} + if( pRt->pNext ) + pRt->pNext->unblock(); + + // #63710 Durch ein anderes Thread-Handling bei Events kann es passieren, + // dass show-Aufruf an einem Dialog zurueckkehrt (durch schliessen des + // Dialogs per UI), BEVOR ein per Event ausgeloester weitergehender Call, + // der in Basic weiter oben im Stack steht und auf einen Basic-Breakpoint + // gelaufen ist, zurueckkehrt. Dann wird unten die Instanz zerstoert und + // wenn das noch im Call stehende Basic weiterlaeuft, gibt es einen GPF. + // Daher muss hier gewartet werden, bis andere Call zurueckkehrt. + if( bDelInst ) + { + // Hier mit 1 statt 0 vergleichen, da vor nCallLvl-- + while( pINST->nCallLvl != 1 ) + GetpApp()->Yield(); + } + + nRes = TRUE; + pINST->pRun = pRt->pNext; + pINST->nCallLvl--; // Call-Level wieder runter + + // Gibt es eine uebergeordnete Runtime-Instanz? + // Dann SbDEBUG_BREAK uebernehmen, wenn gesetzt + SbiRuntime* pRtNext = pRt->pNext; + if( pRtNext && (pRt->GetDebugFlags() & SbDEBUG_BREAK) ) + pRtNext->SetDebugFlags( SbDEBUG_BREAK ); + + delete pRt; + pMOD = pOldMod; + if( bDelInst ) + { + // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, + // beim Programm-Ende freigeben, damit nichts gehalten wird. + ClearUnoObjectsInRTL_Impl( xBasic ); + + DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0"); + delete pINST, pINST = NULL, bDelInst = FALSE; + + // #i30690 + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth ); + + GlobalRunDeInit(); + } + } + else + pINST->nCallLvl--; // Call-Level wieder runter + } + else + { + pINST->nCallLvl--; // Call-Level wieder runter + StarBASIC::FatalError( SbERR_STACK_OVERFLOW ); + } + + // VBA always ensure screenupdating is enabled after completing + StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent()); +#if 0 + if ( pBasic && pBasic->IsDocBasic() && !pINST ) + UnlockControllerHack( pBasic ); +#endif + if( bDelInst ) + { + // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, + // beim Programm-Ende freigeben, damit nichts gehalten wird. + ClearUnoObjectsInRTL_Impl( xBasic ); + + delete pINST; + pINST = NULL; + } + if ( pBasic && pBasic->IsDocBasic() && pBasic->IsQuitApplication() && !pINST ) + { + Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ), NULL ); + } + + return nRes; +} + +// Ausfuehren der Init-Methode eines Moduls nach dem Laden +// oder der Compilation + +void SbModule::RunInit() +{ + if( pImage + && !pImage->bInit + && pImage->GetFlag( SBIMG_INITCODE ) ) + { + // Flag setzen, dass RunInit aktiv ist (Testtool) + GetSbData()->bRunInit = TRUE; + + // BOOL bDelInst = BOOL( pINST == NULL ); + // if( bDelInst ) + // pINST = new SbiInstance( (StarBASIC*) GetParent() ); + SbModule* pOldMod = pMOD; + pMOD = this; + // Der Init-Code beginnt immer hier + SbiRuntime* pRt = new SbiRuntime( this, NULL, 0 ); + pRt->pNext = pINST->pRun; + pINST->pRun = pRt; + while( pRt->Step() ) {} + pINST->pRun = pRt->pNext; + delete pRt; + pMOD = pOldMod; + // if( bDelInst ) + // delete pINST, pINST = NULL; + pImage->bInit = TRUE; + pImage->bFirstInit = FALSE; + + // RunInit ist nicht mehr aktiv + GetSbData()->bRunInit = FALSE; + } +} + +// Mit private/dim deklarierte Variablen loeschen +void SbModule::ClearPrivateVars() +{ + for( USHORT i = 0 ; i < pProps->Count() ; i++ ) + { + SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) ); + if( p ) + { + // Arrays nicht loeschen, sondern nur deren Inhalt + if( p->GetType() & SbxARRAY ) + { + SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject()); + if( pArray ) + { + for( USHORT j = 0 ; j < pArray->Count() ; j++ ) + { + SbxVariable* pj = PTR_CAST(SbxVariable,pArray->Get( j )); + pj->SbxValue::Clear(); + /* + USHORT nFlags = pj->GetFlags(); + pj->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) ); + pj->PutEmpty(); + pj->SetFlags( nFlags ); + */ + } + } + } + else + { + p->SbxValue::Clear(); + /* + USHORT nFlags = p->GetFlags(); + p->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) ); + p->PutEmpty(); + p->SetFlags( nFlags ); + */ + } + } + } +} + +// Zunaechst in dieses Modul, um 358-faehig zu bleiben +// (Branch in sb.cxx vermeiden) +void StarBASIC::ClearAllModuleVars( void ) +{ + // Eigene Module initialisieren + for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + // Nur initialisieren, wenn der Startcode schon ausgefuehrt wurde + if( pModule->pImage && pModule->pImage->bInit ) + pModule->ClearPrivateVars(); + } + + /* #88042 This code can delete already used public vars during runtime! + // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt + // Wenn ja, auch dort initialisieren + for ( USHORT nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic ) + pBasic->ClearAllModuleVars(); + } + */ +} + +// Ausfuehren des Init-Codes aller Module +void SbModule::GlobalRunInit( BOOL bBasicStart ) +{ + // Wenn kein Basic-Start, nur initialisieren, wenn Modul uninitialisiert + if( !bBasicStart ) + if( !(pImage && !pImage->bInit) ) + return; + + // GlobalInitErr-Flag fuer Compiler-Error initialisieren + // Anhand dieses Flags kann in SbModule::Run() nach dem Aufruf + // von GlobalRunInit festgestellt werden, ob beim initialisieren + // der Module ein Fehler auftrat. Dann wird nicht gestartet. + GetSbData()->bGlobalInitErr = FALSE; + + // Parent vom Modul ist ein Basic + StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent()); + if( pBasic ) + { + pBasic->InitAllModules(); + + SbxObject* pParent_ = pBasic->GetParent(); + if( pParent_ ) + { + StarBASIC * pParentBasic = PTR_CAST(StarBASIC,pParent_); + if( pParentBasic ) + { + pParentBasic->InitAllModules( pBasic ); + + // #109018 Parent can also have a parent (library in doc) + SbxObject* pParentParent = pParentBasic->GetParent(); + if( pParentParent ) + { + StarBASIC * pParentParentBasic = PTR_CAST(StarBASIC,pParentParent); + if( pParentParentBasic ) + pParentParentBasic->InitAllModules( pParentBasic ); + } + } + } + } +} + +void SbModule::GlobalRunDeInit( void ) +{ + StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent()); + if( pBasic ) + { + pBasic->DeInitAllModules(); + + SbxObject* pParent_ = pBasic->GetParent(); + if( pParent_ ) + pBasic = PTR_CAST(StarBASIC,pParent_); + if( pBasic ) + pBasic->DeInitAllModules(); + } +} + +// Suche nach dem naechsten STMNT-Befehl im Code. Wird vom STMNT- +// Opcode verwendet, um die Endspalte zu setzen. + +const 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 +{ + 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 pBreaks ? pBreaks->Count() : 0; +} + +USHORT SbModule::GetBP( USHORT n ) const +{ + if( pBreaks && n < pBreaks->Count() ) + return pBreaks->GetObject( n ); + else + return 0; +} + +BOOL SbModule::IsBP( USHORT nLine ) const +{ + if( pBreaks ) + { + const USHORT* p = pBreaks->GetData(); + USHORT n = pBreaks->Count(); + for( USHORT i = 0; i < n; i++, p++ ) + { + USHORT b = *p; + if( b == nLine ) + return TRUE; + if( b < nLine ) + break; + } + } + return FALSE; +} + +BOOL SbModule::SetBP( USHORT nLine ) +{ + if( !IsBreakable( nLine ) ) + return FALSE; + if( !pBreaks ) + pBreaks = new SbiBreakpoints; + const USHORT* p = pBreaks->GetData(); + USHORT n = pBreaks->Count(); + USHORT i; + for( i = 0; i < n; i++, p++ ) + { + USHORT b = *p; + if( b == nLine ) + return TRUE; + if( b < nLine ) + break; + } + pBreaks->Insert( &nLine, 1, i ); + + // #38568: Zur Laufzeit auch hier SbDEBUG_BREAK setzen + if( pINST && pINST->pRun ) + pINST->pRun->SetDebugFlags( SbDEBUG_BREAK ); + + return IsBreakable( nLine ); +} + +BOOL SbModule::ClearBP( USHORT nLine ) +{ + BOOL bRes = FALSE; + if( pBreaks ) + { + const USHORT* p = pBreaks->GetData(); + USHORT n = pBreaks->Count(); + for( USHORT i = 0; i < n; i++, p++ ) + { + USHORT b = *p; + if( b == nLine ) + { + pBreaks->Remove( i, 1 ); bRes = TRUE; break; + } + if( b < nLine ) + break; + } + if( !pBreaks->Count() ) + delete pBreaks, pBreaks = NULL; + } + return bRes; +} + +void SbModule::ClearAllBP() +{ + delete pBreaks; pBreaks = NULL; +} + +void +SbModule::fixUpMethodStart( bool bCvtToLegacy, SbiImage* pImg ) const +{ + if ( !pImg ) + pImg = pImage; + for( 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 ); + } +} + +BOOL SbModule::ExceedsLegacyModuleSize() +{ + if ( !IsCompiled() ) + Compile(); + if ( pImage && pImage->ExceedsLegacyLimits() ) + return true; + return false; +} + + +// Store only image, no source +BOOL SbModule::StoreBinaryData( SvStream& rStrm ) +{ + return StoreBinaryData( rStrm, 0 ); +} + +BOOL SbModule::StoreBinaryData( SvStream& rStrm, USHORT nVer ) +{ + BOOL bRet = Compile(); + if( bRet ) + { + BOOL bFixup = ( !nVer && !pImage->ExceedsLegacyLimits() );// save in old image format, fix up method starts + + if ( bFixup ) // save in old image format, fix up method starts + fixUpMethodStart( true ); + bRet = SbxObject::StoreData( rStrm ); + if( bRet ) + { + pImage->aOUSource = ::rtl::OUString(); + pImage->aComment = aComment; + pImage->aName = GetName(); + + rStrm << (BYTE) 1; + if ( nVer ) + bRet = pImage->Save( rStrm, B_EXT_IMG_VERSION ); + else + bRet = pImage->Save( rStrm, B_LEGACYVERSION ); + if ( bFixup ) + fixUpMethodStart( false ); // restore method starts + + pImage->aOUSource = aOUSource; + } + } + return bRet; +} + +// Called for >= OO 1.0 passwd protected libraries only +// + +BOOL SbModule::LoadBinaryData( SvStream& rStrm ) +{ + ::rtl::OUString aKeepSource = aOUSource; + bool bRet = LoadData( rStrm, 2 ); + LoadCompleted(); + aOUSource = aKeepSource; + return bRet; +} + + +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; +} + +///////////////////////////////////////////////////////////////////////// +// 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; + refStatics = new SbxArray; + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + SetFlag( SBX_NO_MODIFY ); +} + +SbMethod::SbMethod( const SbMethod& r ) + : SvRefBase( r ), SbxMethod( r ) +{ + pMod = r.pMod; + bInvalid = r.bInvalid; + nStart = r.nStart; + nDebugFlags = r.nDebugFlags; + nLine1 = r.nLine1; + nLine2 = r.nLine2; + refStatics = r.refStatics; + SetFlag( SBX_NO_MODIFY ); +} + +SbMethod::~SbMethod() +{ +} + +SbxArray* SbMethod::GetLocals() +{ + if( pINST ) + return pINST->GetLocals( this ); + else + return NULL; +} + +void SbMethod::ClearStatics() +{ + refStatics = new SbxArray; + +} +SbxArray* SbMethod::GetStatics() +{ + return refStatics; +} + +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; +} + +void SbMethod::GetLineRange( USHORT& l1, USHORT& l2 ) +{ + l1 = nLine1; l2 = nLine2; +} + +// Kann spaeter mal weg + +SbxInfo* SbMethod::GetInfo() +{ + return pInfo; +} + +// Schnittstelle zum Ausfuehren einer Methode aus den Applikationen +// #34191# Mit speziellem RefCounting, damit das Basic nicht durch CloseDocument() +// abgeschossen werden kann. Rueckgabewert wird als String geliefert. +ErrCode SbMethod::Call( SbxValue* pRet ) +{ + // RefCount vom Modul hochzaehlen + SbModule* pMod_ = (SbModule*)GetParent(); + pMod_->AddRef(); + + // RefCount vom Basic hochzaehlen + StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent(); + pBasic->AddRef(); + + // Values anlegen, um Return-Wert zu erhalten + SbxValues aVals; + aVals.eType = SbxVARIANT; + + // #104083: Compile BEFORE get + if( bInvalid && !pMod_->Compile() ) + StarBASIC::Error( SbERR_BAD_PROP_VALUE ); + + Get( aVals ); + if ( pRet ) + pRet->Put( aVals ); + + // Gab es einen Error + ErrCode nErr = SbxBase::GetError(); + SbxBase::ResetError(); + + // Objekte freigeben + pMod_->ReleaseRef(); + pBasic->ReleaseRef(); + + return nErr; +} + + +// #100883 Own Broadcast for SbMethod +void SbMethod::Broadcast( 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! + if( GetType() != SbxVOID ) + 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() +{} + diff --git a/basic/source/comp/buffer.cxx b/basic/source/comp/buffer.cxx new file mode 100644 index 000000000000..59fd1a48d324 --- /dev/null +++ b/basic/source/comp/buffer.cxx @@ -0,0 +1,253 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: buffer.cxx,v $ + * $Revision: 1.13 $ + * + * 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 "sbcomp.hxx" +#include "buffer.hxx" +#include <string.h> + +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; +} + +// Angleich des Puffers auf die uebergebene Byte-Grenze + +void SbiBuffer::Align( INT32 n ) +{ + if( nOff % n ) { + UINT32 nn =( ( nOff + n ) / n ) * n; + if( nn <= UP_LIMIT ) + { + nn = nn - nOff; + if( Check( static_cast<USHORT>(nn) ) ) + { + memset( pCur, 0, nn ); + pCur += nn; + nOff = nOff + nn; + } + } + } +} + +// Patch einer Location + +void SbiBuffer::Patch( UINT32 off, UINT32 val ) +{ + if( ( off + sizeof( UINT32 ) ) < nOff ) + { + UINT16 val1 = static_cast<UINT16>( val & 0xFFFF ); + UINT16 val2 = static_cast<UINT16>( val >> 16 ); + BYTE* p = (BYTE*) pBuf + off; + *p++ = (char) ( val1 & 0xFF ); + *p++ = (char) ( val1 >> 8 ); + *p++ = (char) ( val2 & 0xFF ); + *p = (char) ( val2 >> 8 ); + } +} + +// Forward References auf Labels und Prozeduren +// bauen eine Kette auf. Der Anfang der Kette ist beim uebergebenen +// Parameter, das Ende der Kette ist 0. + +void SbiBuffer::Chain( UINT32 off ) +{ + if( off && pBuf ) + { + BYTE *ip; + UINT32 i = off; + UINT32 val1 = (nOff & 0xFFFF); + UINT32 val2 = (nOff >> 16); + do + { + ip = (BYTE*) pBuf + i; + BYTE* pTmp = ip; + i = *pTmp++; i |= *pTmp++ << 8; i |= *pTmp++ << 16; i |= *pTmp++ << 24; + + if( i >= nOff ) + { + pParser->Error( SbERR_INTERNAL_ERROR, "BACKCHAIN" ); + break; + } + *ip++ = (char) ( val1 & 0xFF ); + *ip++ = (char) ( val1 >> 8 ); + *ip++ = (char) ( val2 & 0xFF ); + *ip = (char) ( val2 >> 8 ); + } while( i ); + } +} + +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; +} + +BOOL SbiBuffer::Add( const void* p, USHORT len ) +{ + if( Check( len ) ) + { + memcpy( pCur, p, len ); + pCur += len; + nOff = nOff + len; + return TRUE; + } else return FALSE; +} + + + diff --git a/basic/source/comp/codegen.cxx b/basic/source/comp/codegen.cxx new file mode 100644 index 000000000000..c3e8a000cf8c --- /dev/null +++ b/basic/source/comp/codegen.cxx @@ -0,0 +1,531 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: codegen.cxx,v $ + * $Revision: 1.20 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <basic/sbx.hxx> +#include "sbcomp.hxx" +#include "image.hxx" +#include <limits> + +// nInc ist die Inkrementgroesse der Puffer + +SbiCodeGen::SbiCodeGen( SbModule& r, SbiParser* p, short nInc ) + : rMod( r ), aCode( p, nInc ) +{ + pParser = p; + bStmnt = FALSE; + nLine = 0; + nCol = 0; + nForLevel = 0; +} + +UINT32 SbiCodeGen::GetPC() +{ + return aCode.GetSize(); +} + +// Statement merken + +void SbiCodeGen::Statement() +{ + bStmnt = TRUE; + + nLine = pParser->GetLine(); + nCol = pParser->GetCol1(); + + // #29955 Information der for-Schleifen-Ebene + // in oberen Byte der Spalte speichern + nCol = (nCol & 0xff) + 0x100 * nForLevel; +} + +// Anfang eines Statements markieren + +void SbiCodeGen::GenStmnt() +{ + if( bStmnt ) + { + bStmnt = FALSE; + Gen( _STMNT, nLine, nCol ); + } +} + +// Die Gen-Routinen returnen den Offset des 1. Operanden, +// damit Jumps dort ihr Backchain versenken koennen + +UINT32 SbiCodeGen::Gen( SbiOpcode eOpcode ) +{ +#ifndef PRODUCT + if( eOpcode < SbOP0_START || eOpcode > SbOP0_END ) + pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE1" ); +#endif + GenStmnt(); + aCode += (UINT8) eOpcode; + return GetPC(); +} + +UINT32 SbiCodeGen::Gen( SbiOpcode eOpcode, UINT32 nOpnd ) +{ +#ifndef PRODUCT + if( eOpcode < SbOP1_START || eOpcode > SbOP1_END ) + pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE2" ); +#endif + GenStmnt(); + aCode += (UINT8) eOpcode; + UINT32 n = GetPC(); + aCode += nOpnd; + return n; +} + +UINT32 SbiCodeGen::Gen( SbiOpcode eOpcode, UINT32 nOpnd1, UINT32 nOpnd2 ) +{ +#ifndef PRODUCT + if( eOpcode < SbOP2_START || eOpcode > SbOP2_END ) + pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE3" ); +#endif + GenStmnt(); + aCode += (UINT8) eOpcode; + UINT32 n = GetPC(); + aCode += nOpnd1; + aCode += nOpnd2; + return n; +} + +// Abspeichern des erzeugten Images im Modul + +void SbiCodeGen::Save() +{ + SbiImage* p = new SbiImage; + rMod.StartDefinitions(); + // OPTION BASE-Wert: + p->nDimBase = pParser->nBase; + // OPTION EXPLICIT-Flag uebernehmen + if( pParser->bExplicit ) + p->SetFlag( SBIMG_EXPLICIT ); + if( pParser->IsVBASupportOn() ) + p->SetFlag( SBIMG_VBASUPPORT ); + + int nIfaceCount = 0; + if( pParser->bClassModule ) + { + p->SetFlag( SBIMG_CLASSMODULE ); + pCLASSFAC->AddClassModule( &rMod ); + + nIfaceCount = pParser->aIfaceVector.size(); + if( nIfaceCount ) + { + if( !rMod.pClassData ) + rMod.pClassData = new SbClassData; + + for( int i = 0 ; i < nIfaceCount ; i++ ) + { + const String& rIfaceName = pParser->aIfaceVector[i]; + SbxVariable* pIfaceVar = new SbxVariable( SbxVARIANT ); + pIfaceVar->SetName( rIfaceName ); + SbxArray* pIfaces = rMod.pClassData->mxIfaces; + pIfaces->Insert( pIfaceVar, pIfaces->Count() ); + } + } + } + else + { + pCLASSFAC->RemoveClassModule( &rMod ); + } + if( pParser->bText ) + p->SetFlag( SBIMG_COMPARETEXT ); + // GlobalCode-Flag + if( pParser->HasGlobalCode() ) + p->SetFlag( SBIMG_INITCODE ); + // Die Entrypoints: + for( SbiSymDef* pDef = pParser->aPublics.First(); pDef; + pDef = pParser->aPublics.Next() ) + { + SbiProcDef* pProc = pDef->GetProcDef(); + if( pProc && pProc->IsDefined() ) + { + String aProcName = pProc->GetName(); + String aIfaceProcName; + String aIfaceName; + USHORT nPassCount = 1; + if( nIfaceCount ) + { + int nPropPrefixFound = + aProcName.Search( String( RTL_CONSTASCII_USTRINGPARAM("Property ") ) ); + String aPureProcName = aProcName; + String aPropPrefix; + if( nPropPrefixFound == 0 ) + { + aPropPrefix = aProcName.Copy( 0, 13 ); // 13 == Len( "Property ?et " ) + aPureProcName = aProcName.Copy( 13 ); + } + for( int i = 0 ; i < nIfaceCount ; i++ ) + { + const String& rIfaceName = pParser->aIfaceVector[i]; + int nFound = aPureProcName.Search( rIfaceName ); + if( nFound == 0 && '_' == aPureProcName.GetChar( rIfaceName.Len() ) ) + { + if( nPropPrefixFound == 0 ) + aIfaceProcName += aPropPrefix; + aIfaceProcName += aPureProcName.Copy( rIfaceName.Len() + 1 ); + aIfaceName = rIfaceName; + nPassCount = 2; + break; + } + } + } + SbMethod* pMeth = NULL; + for( USHORT nPass = 0 ; nPass < nPassCount ; nPass++ ) + { + if( nPass == 1 ) + aProcName = aIfaceProcName; + + PropertyMode ePropMode = pProc->getPropertyMode(); + if( ePropMode != PROPERTY_MODE_NONE ) + { + SbxDataType ePropType = SbxEMPTY; + switch( ePropMode ) + { + case PROPERTY_MODE_GET: + ePropType = pProc->GetType(); + break; + case PROPERTY_MODE_LET: + { + // type == type of first parameter + ePropType = SbxVARIANT; // Default + SbiSymPool* pPool = &pProc->GetParams(); + if( pPool->GetSize() > 1 ) + { + SbiSymDef* pPar = pPool->Get( 1 ); + if( pPar ) + ePropType = pPar->GetType(); + } + break; + } + case PROPERTY_MODE_SET: + ePropType = SbxOBJECT; + break; + case PROPERTY_MODE_NONE: + DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" ); + break; + } + String aPropName = pProc->GetPropName(); + if( nPass == 1 ) + aPropName = aPropName.Copy( aIfaceName.Len() + 1 ); + SbProcedureProperty* pProcedureProperty = NULL; + pProcedureProperty = rMod.GetProcedureProperty( aPropName, ePropType ); + } + if( nPass == 1 ) + { + SbIfaceMapperMethod* pMapperMeth = NULL; + pMapperMeth = rMod.GetIfaceMapperMethod( aProcName, pMeth ); + } + else + { + pMeth = rMod.GetMethod( aProcName, pProc->GetType() ); + + // #110004 + if( !pProc->IsPublic() ) + pMeth->SetFlag( SBX_PRIVATE ); + + pMeth->nStart = pProc->GetAddr(); + pMeth->nLine1 = pProc->GetLine1(); + pMeth->nLine2 = pProc->GetLine2(); + // Die Parameter: + SbxInfo* pInfo = pMeth->GetInfo(); + String aHelpFile, aComment; + ULONG nHelpId = 0; + if( pInfo ) + { + // Die Zusatzdaten retten + aHelpFile = pInfo->GetHelpFile(); + aComment = pInfo->GetComment(); + nHelpId = pInfo->GetHelpId(); + } + // Und die Parameterliste neu aufbauen + pInfo = new SbxInfo( aHelpFile, nHelpId ); + pInfo->SetComment( aComment ); + SbiSymPool* pPool = &pProc->GetParams(); + // Das erste Element ist immer der Funktionswert! + for( USHORT i = 1; i < pPool->GetSize(); i++ ) + { + SbiSymDef* pPar = pPool->Get( i ); + SbxDataType t = pPar->GetType(); + if( !pPar->IsByVal() ) + t = (SbxDataType) ( t | SbxBYREF ); + if( pPar->GetDims() ) + t = (SbxDataType) ( t | SbxARRAY ); + // #33677 Optional-Info durchreichen + USHORT nFlags = SBX_READ; + if( pPar->IsOptional() ) + nFlags |= SBX_OPTIONAL; + + pInfo->AddParam( pPar->GetName(), t, nFlags ); + + UINT32 nUserData = 0; + USHORT nDefaultId = pPar->GetDefaultId(); + if( nDefaultId ) + nUserData |= nDefaultId; + if( pPar->IsParamArray() ) + nUserData |= PARAM_INFO_PARAMARRAY; + if( nUserData ) + { + SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i ); + pParam->nUserData = nUserData; + } + } + pMeth->SetInfo( pInfo ); + } + + } // for( iPass... + } + } + // Der Code + p->AddCode( aCode.GetBuffer(), aCode.GetSize() ); + + // Der globale StringPool. 0 ist nicht belegt. + SbiStringPool* pPool = &pParser->aGblStrings; + USHORT nSize = pPool->GetSize(); + p->MakeStrings( nSize ); + USHORT i; + for( i = 1; i <= nSize; i++ ) + p->AddString( pPool->Find( i ) ); + + // Typen einfuegen + USHORT nCount = pParser->rTypeArray->Count(); + for (i = 0; i < nCount; i++) + p->AddType((SbxObject *)pParser->rTypeArray->Get(i)); + + // Insert enum objects + nCount = pParser->rEnumArray->Count(); + for (i = 0; i < nCount; i++) + p->AddEnum((SbxObject *)pParser->rEnumArray->Get(i)); + + if( !p->IsError() ) + rMod.pImage = p; + else + delete p; + + rMod.EndDefinitions(); +} + +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() ); +} + +template class PCodeBuffConvertor< UINT16, UINT32 >; +template class PCodeBuffConvertor< UINT32, UINT16 >; diff --git a/basic/source/comp/dim.cxx b/basic/source/comp/dim.cxx new file mode 100644 index 000000000000..54e98f401594 --- /dev/null +++ b/basic/source/comp/dim.cxx @@ -0,0 +1,1107 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dim.cxx,v $ + * $Revision: 1.30 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <basic/sbx.hxx> +#include "sbcomp.hxx" + +// Deklaration einer Variablen +// Bei Fehlern wird bis zum Komma oder Newline geparst. +// Returnwert: eine neue Instanz, die eingefuegt und dann geloescht wird. +// Array-Indexe werden als SbiDimList zurueckgegeben + +SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, BOOL bStatic, BOOL bConst ) +{ + if( !TestSymbol() ) return NULL; + SbxDataType t = eScanType; + SbiSymDef* pDef = bConst ? new SbiConstDef( aSym ) : new SbiSymDef( aSym ); + SbiDimList* pDim = NULL; + // Klammern? + if( Peek() == LPAREN ) + pDim = new SbiDimList( this ); + pDef->SetType( t ); + if( bStatic ) + pDef->SetStatic(); + TypeDecl( *pDef ); + if( !ppDim && pDim ) + { + if(pDim->GetDims() ) + Error( SbERR_EXPECTED, "()" ); + delete pDim; + } + else if( ppDim ) + *ppDim = pDim; + return pDef; +} + +// Aufloesen einer AS-Typdeklaration +// Der Datentyp wird in die uebergebene Variable eingetragen + +void SbiParser::TypeDecl( SbiSymDef& rDef, BOOL bAsNewAlreadyParsed ) +{ + SbxDataType eType = rDef.GetType(); + short nSize = 0; + if( bAsNewAlreadyParsed || Peek() == AS ) + { + if( !bAsNewAlreadyParsed ) + Next(); + rDef.SetDefinedAs(); + String aType; + SbiToken eTok = Next(); + if( !bAsNewAlreadyParsed && eTok == NEW ) + { + rDef.SetNew(); + eTok = Next(); + } + switch( eTok ) + { + case ANY: + if( rDef.IsNew() ) + Error( SbERR_SYNTAX ); + eType = SbxVARIANT; break; + case TINTEGER: + case TLONG: + case TSINGLE: + case TDOUBLE: + case TCURRENCY: + case TDATE: + case TSTRING: + case TOBJECT: + case _ERROR_: + case TBOOLEAN: + case TVARIANT: + case TBYTE: + if( rDef.IsNew() ) + Error( SbERR_SYNTAX ); + eType = (eTok==TBYTE) ? SbxBYTE : SbxDataType( eTok - TINTEGER + SbxINTEGER ); + if( eType == SbxSTRING ) + { + // STRING*n ? + if( Peek() == MUL ) + { // fixed size! + Next(); + SbiConstExpression aSize( this ); + nSize = aSize.GetShortValue(); + if( nSize < 0 ) + Error( SbERR_OUT_OF_RANGE ); + } + } + break; + case SYMBOL: // kann nur ein TYPE oder eine Objektklasse sein! + if( eScanType != SbxVARIANT ) + Error( SbERR_SYNTAX ); + else + { + String aCompleteName = aSym; + + // #52709 DIM AS NEW fuer Uno mit voll-qualifizierten Namen + if( Peek() == DOT ) + { + String aDotStr( '.' ); + while( Peek() == DOT ) + { + aCompleteName += aDotStr; + Next(); + SbiToken ePeekTok = Peek(); + if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) ) + { + Next(); + aCompleteName += aSym; + } + else + { + Next(); + Error( SbERR_UNEXPECTED, SYMBOL ); + break; + } + } + } + else if( rEnumArray->Find( aCompleteName, SbxCLASS_OBJECT ) ) + { + eType = SbxLONG; + break; + } + + // In den String-Pool uebernehmen + rDef.SetTypeId( aGblStrings.Add( aCompleteName ) ); + } + eType = SbxOBJECT; + break; + case FIXSTRING: // new syntax for complex UNO types + rDef.SetTypeId( aGblStrings.Add( aSym ) ); + eType = SbxOBJECT; + break; + default: + Error( SbERR_UNEXPECTED, eTok ); + Next(); + } + // Die Variable koennte mit Suffix deklariert sein + if( rDef.GetType() != SbxVARIANT ) + { + if( rDef.GetType() != eType ) + Error( SbERR_VAR_DEFINED, rDef.GetName() ); + else if( eType == SbxSTRING && rDef.GetLen() != nSize ) + Error( SbERR_VAR_DEFINED, rDef.GetName() ); + } + rDef.SetType( eType ); + rDef.SetLen( nSize ); + } +} + +// Hier werden Variable, Arrays und Strukturen definiert. +// DIM/PRIVATE/PUBLIC/GLOBAL + +void SbiParser::Dim() +{ + DefVar( _DIM, ( pProc && bVBASupportOn ) ? pProc->IsStatic() : FALSE ); +} + +void SbiParser::DefVar( SbiOpcode eOp, BOOL bStatic ) +{ + SbiSymPool* pOldPool = pPool; + BOOL bSwitchPool = FALSE; + BOOL bPersistantGlobal = FALSE; + SbiToken eFirstTok = eCurTok; + if( pProc && ( eCurTok == GLOBAL || eCurTok == PUBLIC || eCurTok == PRIVATE ) ) + Error( SbERR_NOT_IN_SUBR, eCurTok ); + if( eCurTok == PUBLIC || eCurTok == GLOBAL ) + { + bSwitchPool = TRUE; // im richtigen Moment auf globalen Pool schalten + if( eCurTok == GLOBAL ) + bPersistantGlobal = TRUE; + } + // behavior in VBA is that a module scope variable's lifetime is + // tied to the document. e.g. a module scope variable is global + if( GetBasic()->IsDocBasic() && bVBASupportOn && !pProc ) + bPersistantGlobal = TRUE; + // PRIVATE ist Synonym fuer DIM + // _CONST_? + BOOL bConst = FALSE; + if( eCurTok == _CONST_ ) + bConst = TRUE; + else if( Peek() == _CONST_ ) + Next(), bConst = TRUE; + + // #110004 It can also be a sub/function + if( !bConst && (eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY || + eCurTok == STATIC || eCurTok == ENUM || eCurTok == DECLARE) ) + { + // Next token is read here, because !bConst + bool bPrivate = ( eFirstTok == PRIVATE ); + + if( eCurTok == STATIC ) + { + Next(); + DefStatic( bPrivate ); + } + else if( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) + { + // End global chain if necessary (not done in + // SbiParser::Parse() under these conditions + if( bNewGblDefs && nGblChain == 0 ) + { + nGblChain = aGen.Gen( _JUMP, 0 ); + bNewGblDefs = FALSE; + } + Next(); + DefProc( FALSE, bPrivate ); + return; + } + else if( eCurTok == ENUM ) + { + Next(); + DefEnum( bPrivate ); + return; + } + else if( eCurTok == DECLARE )
+ {
+ Next();
+ DefDeclare( bPrivate );
+ return;
+ }
+ } + +#ifdef SHARED +#define tmpSHARED +#undef SHARED +#endif + // SHARED wird ignoriert + if( Peek() == SHARED ) Next(); +#ifdef tmpSHARED +#define SHARED +#undef tmpSHARED +#endif + // PRESERVE nur bei REDIM + if( Peek() == PRESERVE ) + { + Next(); + if( eOp == _REDIM ) + eOp = _REDIMP; + else + Error( SbERR_UNEXPECTED, eCurTok ); + } + SbiSymDef* pDef; + SbiDimList* pDim; + + // AB 9.7.97, #40689, Statics -> Modul-Initialisierung, in Sub ueberspringen + UINT32 nEndOfStaticLbl = 0; + if( !bVBASupportOn && bStatic ) + { + nEndOfStaticLbl = aGen.Gen( _JUMP, 0 ); + aGen.Statement(); // bei static hier nachholen + } + + BOOL bDefined = FALSE; + while( ( pDef = VarDecl( &pDim, bStatic, bConst ) ) != NULL ) + { + EnableErrors(); + // Variable suchen: + if( bSwitchPool ) + pPool = &aGlobals; + SbiSymDef* pOld = pPool->Find( pDef->GetName() ); + // AB 31.3.1996, #25651#, auch in Runtime-Library suchen + BOOL bRtlSym = FALSE; + if( !pOld ) + { + pOld = CheckRTLForSym( pDef->GetName(), SbxVARIANT ); + if( pOld ) + bRtlSym = TRUE; + } + if( pOld && !(eOp == _REDIM || eOp == _REDIMP) ) + { + if( pDef->GetScope() == SbLOCAL && pOld->GetScope() != SbLOCAL ) + pOld = NULL; + } + if( pOld ) + { + bDefined = TRUE; + // Bei RTL-Symbol immer Fehler + if( !bRtlSym && (eOp == _REDIM || eOp == _REDIMP) ) + { + // Bei REDIM die Attribute vergleichen + SbxDataType eDefType; + bool bError_ = false; + if( pOld->IsStatic() ) + { + bError_ = true; + } + else if( pOld->GetType() != ( eDefType = pDef->GetType() ) ) + { + if( !( eDefType == SbxVARIANT && !pDef->IsDefinedAs() ) ) + bError_ = true; + } + if( bError_ ) + Error( SbERR_VAR_DEFINED, pDef->GetName() ); + } + else + Error( SbERR_VAR_DEFINED, pDef->GetName() ); + delete pDef; pDef = pOld; + } + else + pPool->Add( pDef ); + + // #36374: Variable vor Unterscheidung IsNew() anlegen + // Sonst Error bei Dim Identifier As New Type und option explicit + if( !bDefined && !(eOp == _REDIM || eOp == _REDIMP) + && ( !bConst || pDef->GetScope() == SbGLOBAL ) ) + { + // Variable oder globale Konstante deklarieren + SbiOpcode eOp2; + switch ( pDef->GetScope() ) + { + case SbGLOBAL: eOp2 = bPersistantGlobal ? _GLOBAL_P : _GLOBAL; + goto global; + case SbPUBLIC: eOp2 = bPersistantGlobal ? _PUBLIC_P : _PUBLIC; + // AB 9.7.97, #40689, kein eigener Opcode mehr + if( bVBASupportOn && bStatic ) + { + eOp2 = _STATIC; + break; + } + global: aGen.BackChain( nGblChain ); + nGblChain = 0; + bGblDefs = bNewGblDefs = TRUE; + break; + default: eOp2 = _LOCAL; + } + aGen.Gen( + eOp2, pDef->GetId(), + sal::static_int_cast< UINT16 >( pDef->GetType() ) ); + } + + // Initialisierung fuer selbstdefinierte Datentypen + // und per NEW angelegte Variable + if( pDef->GetType() == SbxOBJECT + && pDef->GetTypeId() ) + { + if( !bCompatible && !pDef->IsNew() ) + { + String aTypeName( aGblStrings.Find( pDef->GetTypeId() ) ); + if( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) == NULL ) + Error( SbERR_UNDEF_TYPE, aTypeName ); + } + + if( bConst ) + { + Error( SbERR_SYNTAX ); + } + + if( pDim ) + { + if( eOp == _REDIMP ) + { + SbiExpression aExpr( this, *pDef, NULL ); + aExpr.Gen(); + aGen.Gen( _REDIMP_ERASE ); + + pDef->SetDims( pDim->GetDims() ); + SbiExpression aExpr2( this, *pDef, pDim ); + aExpr2.Gen(); + aGen.Gen( _DCREATE_REDIMP, pDef->GetId(), pDef->GetTypeId() ); + } + else + { + pDef->SetDims( pDim->GetDims() ); + SbiExpression aExpr( this, *pDef, pDim ); + aExpr.Gen(); + aGen.Gen( _DCREATE, pDef->GetId(), pDef->GetTypeId() ); + } + } + else + { + SbiExpression aExpr( this, *pDef ); + aExpr.Gen(); + SbiOpcode eOp_ = pDef->IsNew() ? _CREATE : _TCREATE; + aGen.Gen( eOp_, pDef->GetId(), pDef->GetTypeId() ); + aGen.Gen( _SET ); + } + } + else + { + if( bConst ) + { + // Konstanten-Definition + if( pDim ) + { + Error( SbERR_SYNTAX ); + delete pDim; + } + SbiExpression aVar( this, *pDef ); + if( !TestToken( EQ ) ) + goto MyBreak; // AB 24.6.1996 (s.u.) + SbiConstExpression aExpr( this ); + if( !bDefined && aExpr.IsValid() ) + { + if( pDef->GetScope() == SbGLOBAL ) + { + // Nur Code fuer globale Konstante erzeugen! + aVar.Gen(); + aExpr.Gen(); + aGen.Gen( _PUTC ); + } + SbiConstDef* pConst = pDef->GetConstDef(); + if( aExpr.GetType() == SbxSTRING ) + pConst->Set( aExpr.GetString() ); + else + pConst->Set( aExpr.GetValue(), aExpr.GetType() ); + } + } + else if( pDim ) + { + // Die Variable dimensionieren + // Bei REDIM die Var vorher loeschen + if( eOp == _REDIM ) + { + SbiExpression aExpr( this, *pDef, NULL ); + aExpr.Gen(); + if ( bVBASupportOn ) + // delete the array but + // clear the variable ( this + // allows the processing of + // the param to happen as normal without errors ( ordinary ERASE just clears the array ) + aGen.Gen( _ERASE_CLEAR ); + else + aGen.Gen( _ERASE ); + } + else if( eOp == _REDIMP ) + { + SbiExpression aExpr( this, *pDef, NULL ); + aExpr.Gen(); + aGen.Gen( _REDIMP_ERASE ); + } + pDef->SetDims( pDim->GetDims() ); + if( bPersistantGlobal ) + pDef->SetGlobal( TRUE ); + SbiExpression aExpr( this, *pDef, pDim ); + aExpr.Gen(); + pDef->SetGlobal( FALSE ); + aGen.Gen( (eOp == _STATIC) ? _DIM : eOp ); + } + } + if( !TestComma() ) + goto MyBreak; // AB 24.6.1996 (s.u.) + + // #27963# AB, 24.6.1996 + // Einfuehrung bSwitchPool (s.o.): pPool darf beim VarDecl-Aufruf + // noch nicht auf &aGlobals gesetzt sein. + // Ansonsten soll das Verhalten aber absolut identisch bleiben, + // d.h. pPool muss immer am Schleifen-Ende zurueckgesetzt werden. + // auch bei break + pPool = pOldPool; + continue; // MyBreak überspingen + MyBreak: + pPool = pOldPool; + break; + } + + // AB 9.7.97, #40689, Sprung ueber Statics-Deklaration abschliessen + if( !bVBASupportOn && bStatic ) + { + // globalen Chain pflegen + nGblChain = aGen.Gen( _JUMP, 0 ); + bGblDefs = bNewGblDefs = TRUE; + + // fuer Sub Sprung auf Ende der statics eintragen + aGen.BackChain( nEndOfStaticLbl ); + } + + //pPool = pOldPool; +} + +// Hier werden Arrays redimensioniert. + +void SbiParser::ReDim() +{ + DefVar( _REDIM, ( pProc && bVBASupportOn ) ? pProc->IsStatic() : FALSE ); +} + +// ERASE array, ... + +void SbiParser::Erase() +{ + while( !bAbort ) + { + if( !TestSymbol() ) return; + String aName( aSym ); + SbxDataType eType = eScanType; + SbiSymDef* pDef = pPool->Find( aName ); + if( !pDef ) + { + if( bExplicit ) + Error( SbERR_UNDEF_VAR, aName ); + pDef = pPool->AddSym( aName ); + pDef->SetType( eType ); + } + SbiExpression aExpr( this, *pDef ); + aExpr.Gen(); + aGen.Gen( _ERASE ); + if( !TestComma() ) break; + } +} + +// Deklaration eines Datentyps + +void SbiParser::Type() +{ + DefType( FALSE ); +} + +void SbiParser::DefType( BOOL bPrivate ) +{ + // TODO: Use bPrivate + (void)bPrivate; + + // Neues Token lesen, es muss ein Symbol sein + if (!TestSymbol()) + return; + + if (rTypeArray->Find(aSym,SbxCLASS_OBJECT)) + { + Error( SbERR_VAR_DEFINED, aSym ); + return; + } + + SbxObject *pType = new SbxObject(aSym); + + SbiSymDef* pElem; + SbiDimList* pDim = NULL; + BOOL bDone = FALSE; + + while( !bDone && !IsEof() ) + { + switch( Peek() ) + { + case ENDTYPE : + pElem = NULL; + bDone = TRUE; + Next(); + break; + + case EOLN : + case REM : + pElem = NULL; + Next(); + break; + + default: + pDim = NULL; + pElem = VarDecl(&pDim,FALSE,FALSE); + if( !pElem ) + bDone = TRUE; // Error occured + } + if( pElem ) + { + SbxArray *pTypeMembers = pType -> GetProperties(); + if (pTypeMembers -> Find (pElem->GetName(),SbxCLASS_DONTCARE)) + Error (SbERR_VAR_DEFINED); + else + { + SbxProperty *pTypeElem = new SbxProperty (pElem->GetName(),pElem->GetType()); + if( pDim )
+ {
+ SbxDimArray* pArray = new SbxDimArray( pElem->GetType() );
+ if ( pDim->GetSize() )
+ {
+ // Dimension the target array
+
+ for ( short i=0; i<pDim->GetSize();++i )
+ {
+ INT32 ub = -1;
+ INT32 lb = nBase;
+ SbiExprNode* pNode = pDim->Get(i)->GetExprNode();
+ ub = pNode->GetNumber();
+ if ( !pDim->Get( i )->IsBased() ) // each dim is low/up
+ {
+ if ( ++i >= pDim->GetSize() ) // trouble
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ pNode = pDim->Get(i)->GetExprNode();
+ lb = ub;
+ ub = pNode->GetNumber();
+ }
+ else if ( !bCompatible )
+ ub += nBase;
+ pArray->AddDim32( lb, ub );
+ }
+ pArray->setHasFixedSize( true );
+ }
+ else
+ pArray->unoAddDim( 0, -1 ); // variant array
+ USHORT nSavFlags = pTypeElem->GetFlags();
+ // need to reset the FIXED flag
+ // when calling PutObject ( because the type will not match Object )
+ pTypeElem->ResetFlag( SBX_FIXED );
+ pTypeElem->PutObject( pArray );
+ pTypeElem->SetFlags( nSavFlags );
+ }
+ delete pDim; + pTypeMembers->Insert( pTypeElem, pTypeMembers->Count() ); + } + delete pElem; + } + } + + pType->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE ); + pType->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE ); + + rTypeArray->Insert (pType,rTypeArray->Count()); +} + + +// Declaration of Enum type + +void SbiParser::Enum() +{ + DefEnum( FALSE ); +} + +void SbiParser::DefEnum( BOOL bPrivate ) +{ + // Neues Token lesen, es muss ein Symbol sein + if (!TestSymbol()) + return; + + String aEnumName = aSym; + if( rEnumArray->Find(aEnumName,SbxCLASS_OBJECT) ) + { + Error( SbERR_VAR_DEFINED, aSym ); + return; + } + + SbxObject *pEnum = new SbxObject( aEnumName ); + if( bPrivate ) + pEnum->SetFlag( SBX_PRIVATE ); + + SbiSymDef* pElem; + SbiDimList* pDim; + BOOL bDone = FALSE; + + // Starting with -1 to make first default value 0 after ++ + sal_Int32 nCurrentEnumValue = -1; + while( !bDone && !IsEof() ) + { + switch( Peek() ) + { + case ENDENUM : + pElem = NULL; + bDone = TRUE; + Next(); + break; + + case EOLN : + case REM : + pElem = NULL; + Next(); + break; + + default: + { + // TODO: Check existing! + BOOL bDefined = FALSE; + + pDim = NULL; + pElem = VarDecl( &pDim, FALSE, TRUE ); + if( !pElem ) + { + bDone = TRUE; // Error occured + break; + } + else if( pDim ) + { + delete pDim; + Error( SbERR_SYNTAX ); + bDone = TRUE; // Error occured + break; + } + + SbiExpression aVar( this, *pElem ); + if( Peek() == EQ ) + { + Next(); + + SbiConstExpression aExpr( this ); + if( !bDefined && aExpr.IsValid() ) + { + SbxVariableRef xConvertVar = new SbxVariable(); + if( aExpr.GetType() == SbxSTRING ) + xConvertVar->PutString( aExpr.GetString() ); + else + xConvertVar->PutDouble( aExpr.GetValue() ); + + nCurrentEnumValue = xConvertVar->GetLong(); + } + } + else + nCurrentEnumValue++; + + SbiSymPool* pPoolToUse = bPrivate ? pPool : &aGlobals; + + SbiSymDef* pOld = pPoolToUse->Find( pElem->GetName() ); + if( pOld ) + { + Error( SbERR_VAR_DEFINED, pElem->GetName() ); + bDone = TRUE; // Error occured + break; + } + + pPool->Add( pElem ); + + if( !bPrivate ) + { + SbiOpcode eOp = _GLOBAL; + aGen.BackChain( nGblChain ); + nGblChain = 0; + bGblDefs = bNewGblDefs = TRUE; + aGen.Gen( + eOp, pElem->GetId(), + sal::static_int_cast< UINT16 >( pElem->GetType() ) ); + + aVar.Gen(); + USHORT nStringId = aGen.GetParser()->aGblStrings.Add( nCurrentEnumValue, SbxLONG ); + aGen.Gen( _NUMBER, nStringId ); + aGen.Gen( _PUTC ); + } + + SbiConstDef* pConst = pElem->GetConstDef(); + pConst->Set( nCurrentEnumValue, SbxLONG ); + } + } + if( pElem ) + { + SbxArray *pEnumMembers = pEnum->GetProperties(); + SbxProperty *pEnumElem = new SbxProperty( pElem->GetName(), SbxLONG ); + pEnumElem->PutLong( nCurrentEnumValue ); + pEnumElem->ResetFlag( SBX_WRITE ); + pEnumElem->SetFlag( SBX_CONST ); + pEnumMembers->Insert( pEnumElem, pEnumMembers->Count() ); + } + } + + pEnum->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE ); + pEnum->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE ); + + rEnumArray->Insert( pEnum, rEnumArray->Count() ); +} + + +// Prozedur-Deklaration +// das erste Token ist bereits eingelesen (SUB/FUNCTION) +// xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE] + +SbiProcDef* SbiParser::ProcDecl( BOOL bDecl ) +{ + BOOL bFunc = BOOL( eCurTok == FUNCTION ); + BOOL bProp = BOOL( eCurTok == GET || eCurTok == SET || eCurTok == LET );
+ if( !TestSymbol() ) return NULL; + String aName( aSym ); + SbxDataType eType = eScanType; + SbiProcDef* pDef = new SbiProcDef( this, aName, true ); + pDef->SetType( eType ); + if( Peek() == _CDECL_ ) + { + Next(); pDef->SetCdecl(); + } + if( Peek() == LIB ) + { + Next(); + if( Next() == FIXSTRING ) + pDef->GetLib() = aSym; + else + Error( SbERR_SYNTAX ); + } + if( Peek() == ALIAS ) + { + Next(); + if( Next() == FIXSTRING ) + pDef->GetAlias() = aSym; + else + Error( SbERR_SYNTAX ); + } + if( !bDecl ) + { + // CDECL, LIB und ALIAS sind unzulaessig + if( pDef->GetLib().Len() ) + Error( SbERR_UNEXPECTED, LIB ); + if( pDef->GetAlias().Len() ) + Error( SbERR_UNEXPECTED, ALIAS ); + if( pDef->IsCdecl() ) + Error( SbERR_UNEXPECTED, _CDECL_ ); + pDef->SetCdecl( FALSE ); + pDef->GetLib().Erase(); + pDef->GetAlias().Erase(); + } + else if( !pDef->GetLib().Len() ) + { + // ALIAS und CDECL nur zusammen mit LIB + if( pDef->GetAlias().Len() ) + Error( SbERR_UNEXPECTED, ALIAS ); + if( pDef->IsCdecl() ) + Error( SbERR_UNEXPECTED, _CDECL_ ); + pDef->SetCdecl( FALSE ); + pDef->GetAlias().Erase(); + } + // Klammern? + if( Peek() == LPAREN ) + { + Next(); + if( Peek() == RPAREN ) + Next(); + else + for(;;) { + BOOL bByVal = FALSE; + BOOL bOptional = FALSE; + BOOL bParamArray = FALSE; + while( Peek() == BYVAL || Peek() == BYREF || Peek() == _OPTIONAL_ ) + { + if ( Peek() == BYVAL ) Next(), bByVal = TRUE; + else if ( Peek() == BYREF ) Next(), bByVal = FALSE; + else if ( Peek() == _OPTIONAL_ ) Next(), bOptional = TRUE; + } + if( bCompatible && Peek() == PARAMARRAY ) + { + if( bByVal || bByVal || bOptional ) + Error( SbERR_UNEXPECTED, PARAMARRAY ); + Next(); + bParamArray = TRUE; + } + SbiSymDef* pPar = VarDecl( NULL, FALSE, FALSE ); + if( !pPar ) + break; + if( bByVal ) + pPar->SetByVal(); + if( bOptional ) + pPar->SetOptional(); + if( bParamArray ) + pPar->SetParamArray(); + pDef->GetParams().Add( pPar ); + SbiToken eTok = Next(); + if( eTok != COMMA && eTok != RPAREN ) + { + BOOL bError2 = TRUE; + if( bOptional && bCompatible && eTok == EQ ) + { + SbiConstExpression* pDefaultExpr = new SbiConstExpression( this ); + SbxDataType eType2 = pDefaultExpr->GetType(); + + USHORT nStringId; + if( eType2 == SbxSTRING ) + nStringId = aGblStrings.Add( pDefaultExpr->GetString() ); + else + nStringId = aGblStrings.Add( pDefaultExpr->GetValue(), eType2 ); + + pPar->SetDefaultId( nStringId ); + delete pDefaultExpr; + + eTok = Next(); + if( eTok == COMMA || eTok == RPAREN ) + bError2 = FALSE; + } + if( bError2 ) + { + Error( SbERR_EXPECTED, RPAREN ); + break; + } + } + if( eTok == RPAREN ) + break; + } + } + TypeDecl( *pDef ); + if( eType != SbxVARIANT && pDef->GetType() != eType ) + Error( SbERR_BAD_DECLARATION, aName ); +// if( pDef->GetType() == SbxOBJECT ) +// pDef->SetType( SbxVARIANT ), +// Error( SbERR_SYNTAX ); + if( pDef->GetType() == SbxVARIANT && !( bFunc || bProp ) )
+ pDef->SetType( SbxEMPTY ); + return pDef; +} + +// DECLARE + +void SbiParser::Declare() +{ + DefDeclare( FALSE );
+}
+
+void SbiParser::DefDeclare( BOOL bPrivate )
+{
+ Next(); + if( eCurTok != SUB && eCurTok != FUNCTION ) + Error( SbERR_UNEXPECTED, eCurTok ); + else + { + SbiProcDef* pDef = ProcDecl( TRUE ); + if( pDef ) + { + if( !pDef->GetLib().Len() ) + Error( SbERR_EXPECTED, LIB ); + // gibts den schon? + SbiSymDef* pOld = aPublics.Find( pDef->GetName() ); + if( pOld ) + { + SbiProcDef* p = pOld->GetProcDef(); + if( !p ) + { + // Als Variable deklariert + Error( SbERR_BAD_DECLARATION, pDef->GetName() ); + delete pDef; + pDef = NULL; + } + else + pDef->Match( p ); + } + else + aPublics.Add( pDef ); + + if ( pDef )
+ pDef->SetPublic( !bPrivate );
+ } + } +} + +// Aufruf einer SUB oder FUNCTION + +void SbiParser::Call() +{ + String aName( aSym ); + SbiExpression aVar( this, SbSYMBOL ); + aVar.Gen( FORCE_CALL ); + aGen.Gen( _GET ); +} + +// SUB/FUNCTION + +void SbiParser::SubFunc() +{ + DefProc( FALSE, FALSE ); +} + +// Einlesen einer Prozedur + +BOOL runsInSetup( void ); + +void SbiParser::DefProc( BOOL bStatic, BOOL bPrivate ) +{ + USHORT l1 = nLine, l2 = nLine; + BOOL bSub = BOOL( eCurTok == SUB ); + BOOL bProperty = BOOL( eCurTok == PROPERTY ); + PropertyMode ePropertyMode = PROPERTY_MODE_NONE; + if( bProperty ) + { + Next(); + if( eCurTok == GET ) + ePropertyMode = PROPERTY_MODE_GET; + else if( eCurTok == LET ) + ePropertyMode = PROPERTY_MODE_LET; + else if( eCurTok == SET ) + ePropertyMode = PROPERTY_MODE_SET; + else + Error( SbERR_EXPECTED, "Get or Let or Set" ); + } + + SbiToken eExit = eCurTok; + SbiProcDef* pDef = ProcDecl( FALSE ); + if( !pDef ) + return; + pDef->setPropertyMode( ePropertyMode ); + + // Ist die Proc bereits deklariert? + SbiSymDef* pOld = aPublics.Find( pDef->GetName() ); + if( pOld ) + { + bool bError_ = false; + + pProc = pOld->GetProcDef(); + if( !pProc ) + { + // Als Variable deklariert + Error( SbERR_BAD_DECLARATION, pDef->GetName() ); + delete pDef; + pProc = NULL; + bError_ = true; + } + // #100027: Multiple declaration -> Error + // #112787: Not for setup, REMOVE for 8 + else if( !runsInSetup() && pProc->IsUsedForProcDecl() ) + { + PropertyMode ePropMode = pDef->getPropertyMode(); + if( ePropMode == PROPERTY_MODE_NONE || ePropMode == pProc->getPropertyMode() ) + { + Error( SbERR_PROC_DEFINED, pDef->GetName() ); + delete pDef; + pProc = NULL; + bError_ = true; + } + } + + if( !bError_ ) + { + pDef->Match( pProc ); + pProc = pDef; + } + } + else + aPublics.Add( pDef ), pProc = pDef; + + if( !pProc ) + return; + pProc->SetPublic( !bPrivate ); + + // Nun setzen wir die Suchhierarchie fuer Symbole sowie die aktuelle + // Prozedur. + aPublics.SetProcId( pProc->GetId() ); + pProc->GetParams().SetParent( &aPublics ); + if( bStatic ) + { + if ( bVBASupportOn ) + pProc->SetStatic( TRUE ); + else + Error( SbERR_NOT_IMPLEMENTED ); // STATIC SUB ... + } + else + { + pProc->SetStatic( FALSE ); + } + // Normalfall: Lokale Variable->Parameter->Globale Variable + pProc->GetLocals().SetParent( &pProc->GetParams() ); + pPool = &pProc->GetLocals(); + + pProc->Define(); + OpenBlock( eExit ); + StmntBlock( bSub ? ENDSUB : (bProperty ? ENDPROPERTY : ENDFUNC) ); + l2 = nLine; + pProc->SetLine1( l1 ); + pProc->SetLine2( l2 ); + pPool = &aPublics; + aPublics.SetProcId( 0 ); + // Offene Labels? + pProc->GetLabels().CheckRefs(); + CloseBlock(); + aGen.Gen( _LEAVE ); + pProc = NULL; +} + +// STATIC variable|procedure + +void SbiParser::Static() +{ + DefStatic( FALSE ); +} + +void SbiParser::DefStatic( BOOL bPrivate ) +{ + switch( Peek() ) + { + case SUB: + case FUNCTION: + case PROPERTY: + // End global chain if necessary (not done in + // SbiParser::Parse() under these conditions + if( bNewGblDefs && nGblChain == 0 ) + { + nGblChain = aGen.Gen( _JUMP, 0 ); + bNewGblDefs = FALSE; + } + Next(); + DefProc( TRUE, bPrivate ); + break; + default: { + if( !pProc ) + Error( SbERR_NOT_IN_SUBR ); + // Pool umsetzen, damit STATIC-Deklarationen im globalen + // Pool landen + SbiSymPool* p = pPool; pPool = &aPublics; + DefVar( _STATIC, TRUE ); + pPool = p; + } break; + } +} + diff --git a/basic/source/comp/exprgen.cxx b/basic/source/comp/exprgen.cxx new file mode 100644 index 000000000000..c18501c98e40 --- /dev/null +++ b/basic/source/comp/exprgen.cxx @@ -0,0 +1,300 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: exprgen.cxx,v $ + * $Revision: 1.19 $ + * + * 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 "sbcomp.hxx" +#include "expr.hxx" + +// Umsetztabelle fuer Token-Operatoren und Opcodes + +typedef struct { + SbiToken eTok; // Token + SbiOpcode eOp; // Opcode +} OpTable; + +static OpTable aOpTable [] = { + { EXPON,_EXP }, + { MUL, _MUL }, + { DIV, _DIV }, + { IDIV, _IDIV }, + { MOD, _MOD }, + { PLUS, _PLUS }, + { MINUS,_MINUS }, + { EQ, _EQ }, + { NE, _NE }, + { LE, _LE }, + { GE, _GE }, + { LT, _LT }, + { GT, _GT }, + { AND, _AND }, + { OR, _OR }, + { XOR, _XOR }, + { EQV, _EQV }, + { IMP, _IMP }, + { NOT, _NOT }, + { NEG, _NEG }, + { CAT, _CAT }, + { LIKE, _LIKE }, + { IS, _IS }, + { NIL, _NOP }}; + +// Ausgabe eines Elements +void SbiExprNode::Gen( RecursiveMode eRecMode ) +{ + if( IsConstant() ) + { + switch( GetType() ) + { + case SbxEMPTY: pGen->Gen( _EMPTY ); break; + case SbxINTEGER: pGen->Gen( _CONST, (short) nVal ); break; + case SbxSTRING: + { + USHORT nStringId = pGen->GetParser()->aGblStrings.Add( aStrVal, TRUE ); + pGen->Gen( _SCONST, nStringId ); break; + } + default: + { + USHORT nStringId = pGen->GetParser()->aGblStrings.Add( nVal, eType ); + pGen->Gen( _NUMBER, nStringId ); + } + } + } + else if( IsOperand() ) + { + SbiExprNode* pWithParent_ = NULL; + SbiOpcode eOp; + if( aVar.pDef->GetScope() == SbPARAM ) + { + eOp = _PARAM; + if( 0 == aVar.pDef->GetPos() ) + { + bool bTreatFunctionAsParam = true; + if( eRecMode == FORCE_CALL ) + { + bTreatFunctionAsParam = false; + } + else if( eRecMode == UNDEFINED ) + { + if( aVar.pPar && aVar.pPar->IsBracket() ) + bTreatFunctionAsParam = false; + } + if( !bTreatFunctionAsParam ) + eOp = aVar.pDef->IsGlobal() ? _FIND_G : _FIND; + } + } + // AB: 17.12.1995, Spezialbehandlung fuer WITH + else if( (pWithParent_ = GetWithParent()) != NULL ) + { + eOp = _ELEM; // .-Ausdruck in WITH + } + else + { + SbiProcDef* pProc = aVar.pDef->GetProcDef(); + // per DECLARE definiert? + if( pProc && pProc->GetLib().Len() ) + eOp = pProc->IsCdecl() ? _CALLC : _CALL; + else + eOp = ( aVar.pDef->GetScope() == SbRTL ) ? _RTL : + (aVar.pDef->IsGlobal() ? _FIND_G : _FIND); + } + + if( eOp == _FIND ) + { + + SbiProcDef* pProc = aVar.pDef->GetProcDef(); + if ( pGen->GetParser()->bClassModule ) + eOp = _FIND_CM; + else if ( aVar.pDef->IsStatic() || (pProc && pProc->IsStatic()) ) + { + eOp = _FIND_STATIC; + } + } + for( SbiExprNode* p = this; p; p = p->aVar.pNext ) + { + if( p == this && pWithParent_ != NULL ) + pWithParent_->Gen(); + p->GenElement( eOp ); + eOp = _ELEM; + } + } + else if( IsTypeOf() ) + { + pLeft->Gen(); + pGen->Gen( _TESTCLASS, nTypeStrId ); + } + else + { + pLeft->Gen(); + if( pRight ) + pRight->Gen(); + for( OpTable* p = aOpTable; p->eTok != NIL; p++ ) + { + if( p->eTok == eTok ) + { + pGen->Gen( p->eOp ); break; + } + } + } +} + +// Ausgabe eines Operanden-Elements + +void SbiExprNode::GenElement( SbiOpcode eOp ) +{ +#ifndef PRODUCT + if( (eOp < _RTL || eOp > _CALLC) && eOp != _FIND_G && eOp != _FIND_CM ) + pGen->GetParser()->Error( SbERR_INTERNAL_ERROR, "Opcode" ); +#endif + SbiSymDef* pDef = aVar.pDef; + // Das ID ist entweder die Position oder das String-ID + // Falls das Bit 0x8000 gesetzt ist, hat die Variable + // eine Parameterliste. + USHORT nId = ( eOp == _PARAM ) ? pDef->GetPos() : pDef->GetId(); + // Parameterliste aufbauen + if( aVar.pPar && aVar.pPar->GetSize() ) + { + nId |= 0x8000; + aVar.pPar->Gen(); + } + + SbiProcDef* pProc = aVar.pDef->GetProcDef(); + // per DECLARE definiert? + if( pProc ) + { + // Dann evtl. einen LIB-Befehl erzeugen + if( pProc->GetLib().Len() ) + pGen->Gen( _LIB, pGen->GetParser()->aGblStrings.Add( pProc->GetLib() ) ); + // und den Aliasnamen nehmen + if( pProc->GetAlias().Len() ) + nId = ( nId & 0x8000 ) | pGen->GetParser()->aGblStrings.Add( pProc->GetAlias() ); + } + pGen->Gen( eOp, nId, sal::static_int_cast< UINT16 >( GetType() ) ); + + if( aVar.pvMorePar ) + { + SbiExprListVector* pvMorePar = aVar.pvMorePar; + SbiExprListVector::iterator it; + for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it ) + { + SbiExprList* pExprList = *it; + pExprList->Gen(); + pGen->Gen( _ARRAYACCESS ); + } + } +} + +// Erzeugen einer Argv-Tabelle +// Das erste Element bleibt immer frei fuer Returnwerte etc. +// Siehe auch SbiProcDef::SbiProcDef() in symtbl.cxx + +void SbiExprList::Gen() +{ + if( pFirst ) + { + pParser->aGen.Gen( _ARGC ); + // AB 10.1.96: Typ-Anpassung bei DECLARE + USHORT nCount = 1, nParAnz = 0; + SbiSymPool* pPool = NULL; + if( pProc ) + { + pPool = &pProc->GetParams(); + nParAnz = pPool->GetSize(); + } + for( SbiExpression* pExpr = pFirst; pExpr; pExpr = pExpr->pNext,nCount++ ) + { + pExpr->Gen(); + if( pExpr->GetName().Len() ) + { + // named arg + USHORT nSid = pParser->aGblStrings.Add( pExpr->GetName() ); + pParser->aGen.Gen( _ARGN, nSid ); + + // AB 10.1.96: Typanpassung bei named -> passenden Parameter suchen + if( pProc ) + { + // Vorerst: Error ausloesen + pParser->Error( SbERR_NO_NAMED_ARGS ); + + // Spaeter, wenn Named Args bei DECLARE moeglich + /* + for( USHORT i = 1 ; i < nParAnz ; i++ ) + { + SbiSymDef* pDef = pPool->Get( i ); + const String& rName = pDef->GetName(); + if( rName.Len() ) + { + if( pExpr->GetName().ICompare( rName ) + == COMPARE_EQUAL ) + { + pParser->aGen.Gen( _ARGTYP, pDef->GetType() ); + break; + } + } + } + */ + } + } + else + { + pParser->aGen.Gen( _ARGV ); + + // Funktion mit DECLARE -> Typ-Anpassung + if( pProc && nCount < nParAnz ) + { + SbiSymDef* pDef = pPool->Get( nCount ); + USHORT nTyp = sal::static_int_cast< USHORT >( + pDef->GetType() ); + // Zusätzliches Flag für BYVAL einbauen + if( pDef->IsByVal() ) + nTyp |= 0x8000; + pParser->aGen.Gen( _ARGTYP, nTyp ); + } + } + } + } +} + +void SbiExpression::Gen( RecursiveMode eRecMode ) +{ + // AB: 17.12.1995, Spezialbehandlung fuer WITH + // Wenn pExpr == .-Ausdruck in With, zunaechst Gen fuer Basis-Objekt + pExpr->Gen( eRecMode ); + if( bBased ) + { + USHORT uBase = pParser->nBase; + if( pParser->IsCompatible() ) + uBase |= 0x8000; // #109275 Flag compatiblity + pParser->aGen.Gen( _BASED, uBase ); + pParser->aGen.Gen( _ARGV ); + } +} + diff --git a/basic/source/comp/exprnode.cxx b/basic/source/comp/exprnode.cxx new file mode 100644 index 000000000000..92da5d4f22fd --- /dev/null +++ b/basic/source/comp/exprnode.cxx @@ -0,0 +1,481 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: exprnode.cxx,v $ + * $Revision: 1.19.40.1 $ + * + * 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 <math.h> + +#include <rtl/math.hxx> +#include "sbcomp.hxx" +#include "expr.hxx" + +////////////////////////////////////////////////////////////////////////// + +SbiExprNode::SbiExprNode( void ) +{ + pLeft = NULL; + pRight = NULL; + eNodeType = SbxDUMMY; +} + +SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r ) +{ + BaseInit( p ); + + pLeft = l; + pRight = r; + eTok = t; + nVal = 0; + eType = SbxVARIANT; // Nodes sind immer Variant + eNodeType = SbxNODE; + bComposite= TRUE; +} + +SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t ) +{ + BaseInit( p ); + + eType = t; + eNodeType = SbxNUMVAL; + nVal = n; +} + +SbiExprNode::SbiExprNode( SbiParser* p, const String& rVal ) +{ + BaseInit( p ); + + eType = SbxSTRING; + eNodeType = SbxSTRVAL; + aStrVal = rVal; +} + +SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l ) +{ + BaseInit( p ); + + eType = ( t == SbxVARIANT ) ? r.GetType() : t; + eNodeType = SbxVARVAL; + aVar.pDef = (SbiSymDef*) &r; + aVar.pPar = l; + aVar.pvMorePar = NULL; + aVar.pNext= NULL; + + // Funktionsergebnisse sind nie starr + bComposite= BOOL( aVar.pDef->GetProcDef() != NULL ); +} + +// #120061 TypeOf +SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, USHORT nId ) +{ + BaseInit( p ); + + pLeft = l; + eType = SbxBOOL; + eNodeType = SbxTYPEOF; + nTypeStrId = nId; +} + + +// AB: 17.12.95, Hilfsfunktion fuer Ctor fuer einheitliche Initialisierung +void SbiExprNode::BaseInit( SbiParser* p ) +{ + pGen = &p->aGen; + eTok = NIL; + pLeft = NULL; + pRight = NULL; + pWithParent = NULL; + bComposite = FALSE; + bError = FALSE; +} + +SbiExprNode::~SbiExprNode() +{ + delete pLeft; + delete pRight; + if( IsVariable() ) + { + delete aVar.pPar; + delete aVar.pNext; + SbiExprListVector* pvMorePar = aVar.pvMorePar; + if( pvMorePar ) + { + SbiExprListVector::iterator it; + for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it ) + delete *it; + delete pvMorePar; + } + } +} + +SbiSymDef* SbiExprNode::GetVar() +{ + if( eNodeType == SbxVARVAL ) + return aVar.pDef; + else + return NULL; +} + +SbiSymDef* SbiExprNode::GetRealVar() +{ + SbiExprNode* p = GetRealNode(); + if( p ) + return p->GetVar(); + else + return NULL; +} + +// AB: 18.12.95 +SbiExprNode* SbiExprNode::GetRealNode() +{ + if( eNodeType == SbxVARVAL ) + { + SbiExprNode* p = this; + while( p->aVar.pNext ) + p = p->aVar.pNext; + return p; + } + else + return NULL; +} + +// Diese Methode setzt den Typ um, falls er in den Integer-Bereich hineinpasst + +BOOL SbiExprNode::IsIntConst() +{ + if( eNodeType == SbxNUMVAL ) + { + if( eType >= SbxINTEGER && eType <= SbxDOUBLE ) + { + double n; + if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 ) + { + nVal = (double) (short) nVal; + eType = SbxINTEGER; + return TRUE; + } + } + } + return FALSE; +} + +BOOL SbiExprNode::IsNumber() +{ + return BOOL( eNodeType == SbxNUMVAL ); +} + +BOOL SbiExprNode::IsString() +{ + return BOOL( eNodeType == SbxSTRVAL ); +} + +BOOL SbiExprNode::IsVariable() +{ + return BOOL( eNodeType == SbxVARVAL ); +} + +BOOL SbiExprNode::IsLvalue() +{ + return IsVariable(); +} + +// Ermitteln der Tiefe eines Baumes + +short SbiExprNode::GetDepth() +{ + if( IsOperand() ) return 0; + else + { + short d1 = pLeft->GetDepth(); + short d2 = pRight->GetDepth(); + return( (d1 < d2 ) ? d2 : d1 ) + 1; + } +} + + +// Abgleich eines Baumes: +// 1. Constant Folding +// 2. Typabgleich +// 3. Umwandlung der Operanden in Strings +// 4. Hochziehen der Composite- und Error-Bits + +void SbiExprNode::Optimize() +{ + FoldConstants(); + CollectBits(); +} + +// Hochziehen der Composite- und Fehlerbits + +void SbiExprNode::CollectBits() +{ + if( pLeft ) + { + pLeft->CollectBits(); + bError |= pLeft->bError; + bComposite |= pLeft->bComposite; + } + if( pRight ) + { + pRight->CollectBits(); + bError |= pRight->bError; + bComposite |= pRight->bComposite; + } +} + +// Kann ein Zweig umgeformt werden, wird TRUE zurueckgeliefert. In diesem +// Fall ist das Ergebnis im linken Zweig. + +void SbiExprNode::FoldConstants() +{ + if( IsOperand() || eTok == LIKE ) return; + pLeft->FoldConstants(); + if( pRight ) + { + pRight->FoldConstants(); + if( pLeft->IsConstant() && pRight->IsConstant() + && pLeft->eNodeType == pRight->eNodeType ) + { + CollectBits(); + if( eTok == CAT ) + // CAT verbindet auch zwei Zahlen miteinander! + eType = SbxSTRING; + if( pLeft->eType == SbxSTRING ) + // Kein Type Mismatch! + eType = SbxSTRING; + if( eType == SbxSTRING ) + { + String rl( pLeft->GetString() ); + String rr( pRight->GetString() ); + delete pLeft; pLeft = NULL; + delete pRight; pRight = NULL; + bComposite = FALSE; + if( eTok == PLUS || eTok == CAT ) + { + eTok = CAT; + // Verkettung: + aStrVal = rl; + aStrVal += rr; + eType = SbxSTRING; + eNodeType = SbxSTRVAL; + } + else + { + eType = SbxDOUBLE; + eNodeType = SbxNUMVAL; + StringCompare eRes = rr.CompareTo( rl ); + switch( eTok ) + { + case EQ: + nVal = ( eRes == COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE; + break; + case NE: + nVal = ( eRes != COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE; + break; + case LT: + nVal = ( eRes == COMPARE_LESS ) ? SbxTRUE : SbxFALSE; + break; + case GT: + nVal = ( eRes == COMPARE_GREATER ) ? SbxTRUE : SbxFALSE; + break; + case LE: + nVal = ( eRes != COMPARE_GREATER ) ? SbxTRUE : SbxFALSE; + break; + case GE: + nVal = ( eRes != COMPARE_LESS ) ? SbxTRUE : SbxFALSE; + break; + default: + pGen->GetParser()->Error( SbERR_CONVERSION ); + bError = TRUE; + } + } + } + else + { + double nl = pLeft->nVal; + double nr = pRight->nVal; + long ll = 0, lr = 0; + long llMod = 0, lrMod = 0; + if( ( eTok >= AND && eTok <= IMP ) + || eTok == IDIV || eTok == MOD ) + { + // Integer-Operationen + BOOL err = FALSE; + if( nl > SbxMAXLNG ) err = TRUE, nl = SbxMAXLNG; + else + if( nl < SbxMINLNG ) err = TRUE, nl = SbxMINLNG; + if( nr > SbxMAXLNG ) err = TRUE, nr = SbxMAXLNG; + else + if( nr < SbxMINLNG ) err = TRUE, nr = SbxMINLNG; + ll = (long) nl; lr = (long) nr; + llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5); + lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5); + if( err ) + { + pGen->GetParser()->Error( SbERR_MATH_OVERFLOW ); + bError = TRUE; + } + } + BOOL bBothInt = BOOL( pLeft->eType < SbxSINGLE + && pRight->eType < SbxSINGLE ); + delete pLeft; pLeft = NULL; + delete pRight; pRight = NULL; + nVal = 0; + eType = SbxDOUBLE; + eNodeType = SbxNUMVAL; + bComposite = FALSE; + BOOL bCheckType = FALSE; + switch( eTok ) + { + case EXPON: + nVal = pow( nl, nr ); break; + case MUL: + bCheckType = TRUE; + nVal = nl * nr; break; + case DIV: + if( !nr ) + { + pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL; + bError = TRUE; + } else nVal = nl / nr; + break; + case PLUS: + bCheckType = TRUE; + nVal = nl + nr; break; + case MINUS: + bCheckType = TRUE; + nVal = nl - nr; break; + case EQ: + nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE; + eType = SbxINTEGER; break; + case NE: + nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE; + eType = SbxINTEGER; break; + case LT: + nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE; + eType = SbxINTEGER; break; + case GT: + nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE; + eType = SbxINTEGER; break; + case LE: + nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE; + eType = SbxINTEGER; break; + case GE: + nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE; + eType = SbxINTEGER; break; + case IDIV: + if( !lr ) + { + pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL; + bError = TRUE; + } else nVal = ll / lr; + eType = SbxLONG; break; + case MOD: + if( !lr ) + { + pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL; + bError = TRUE; + } else nVal = llMod % lrMod; + eType = SbxLONG; break; + case AND: + nVal = (double) ( ll & lr ); eType = SbxLONG; break; + case OR: + nVal = (double) ( ll | lr ); eType = SbxLONG; break; + case XOR: + nVal = (double) ( ll ^ lr ); eType = SbxLONG; break; + case EQV: + nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break; + case IMP: + nVal = (double) ( ~ll | lr ); eType = SbxLONG; break; + default: break; + } + + if( !::rtl::math::isFinite( nVal ) ) + pGen->GetParser()->Error( SbERR_MATH_OVERFLOW ); + + // Den Datentyp wiederherstellen, um Rundungsfehler + // zu killen + if( bCheckType && bBothInt + && nVal >= SbxMINLNG && nVal <= SbxMAXLNG ) + { + // NK-Stellen weg + long n = (long) nVal; + nVal = n; + eType = ( n >= SbxMININT && n <= SbxMAXINT ) + ? SbxINTEGER : SbxLONG; + } + } + } + } + else if( pLeft->IsNumber() ) + { + nVal = pLeft->nVal; + delete pLeft; + pLeft = NULL; + eType = SbxDOUBLE; + eNodeType = SbxNUMVAL; + bComposite = FALSE; + switch( eTok ) + { + case NEG: + nVal = -nVal; break; + case NOT: { + // Integer-Operation! + BOOL err = FALSE; + if( nVal > SbxMAXLNG ) err = TRUE, nVal = SbxMAXLNG; + else + if( nVal < SbxMINLNG ) err = TRUE, nVal = SbxMINLNG; + if( err ) + { + pGen->GetParser()->Error( SbERR_MATH_OVERFLOW ); + bError = TRUE; + } + nVal = (double) ~((long) nVal); + eType = SbxLONG; + } break; + default: break; + } + } + if( eNodeType == SbxNUMVAL ) + { + // Evtl auf INTEGER falten (wg. besserem Opcode)? + if( eType == SbxSINGLE || eType == SbxDOUBLE ) + { + double x; + if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG + && !modf( nVal, &x ) ) + eType = SbxLONG; + } + if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT ) + eType = SbxINTEGER; + } +} + + diff --git a/basic/source/comp/exprtree.cxx b/basic/source/comp/exprtree.cxx new file mode 100644 index 000000000000..701ecdd7bc16 --- /dev/null +++ b/basic/source/comp/exprtree.cxx @@ -0,0 +1,1104 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: exprtree.cxx,v $ + * $Revision: 1.24.40.1 $ + * + * 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 "sbcomp.hxx" +#include <basic/sbx.hxx> // w.g. ...IMPL_REF(...sbxvariable) +#include "expr.hxx" + +/*************************************************************************** +|* +|* SbiExpression +|* +***************************************************************************/ + +SbiExpression::SbiExpression( SbiParser* p, SbiExprType t, SbiExprMode eMode ) +{ + pParser = p; + bError = bByVal = bBased = bBracket = FALSE; + nParenLevel = 0; + eCurExpr = t; + m_eMode = eMode; + pNext = NULL; + pExpr = (t != SbSTDEXPR ) ? Term() : Boolean(); + if( t != SbSYMBOL ) + pExpr->Optimize(); + if( t == SbLVALUE && !pExpr->IsLvalue() ) + p->Error( SbERR_LVALUE_EXPECTED ); + if( t == SbOPERAND && !IsVariable() ) + p->Error( SbERR_VAR_EXPECTED ); +} + +SbiExpression::SbiExpression( SbiParser* p, double n, SbxDataType t ) +{ + pParser = p; + eCurExpr = SbOPERAND; + pNext = NULL; + bError = bByVal = bBased = bBracket = FALSE; + pExpr = new SbiExprNode( pParser, n, t ); + pExpr->Optimize(); +} + +SbiExpression::SbiExpression( SbiParser* p, const String& r ) +{ + pParser = p; + pNext = NULL; + bError = bByVal = bBased = bBracket = FALSE; + eCurExpr = SbOPERAND; + pExpr = new SbiExprNode( pParser, r ); +} + +SbiExpression::SbiExpression( SbiParser* p, const SbiSymDef& r, SbiExprList* pPar ) +{ + pParser = p; + pNext = NULL; + bError = bByVal = bBased = bBracket = FALSE; + eCurExpr = SbOPERAND; + pExpr = new SbiExprNode( pParser, r, SbxVARIANT, pPar ); +} + +SbiExpression::SbiExpression( SbiParser* p, SbiToken t ) +{ + pParser = p; + pNext = NULL; + bError = bByVal = bBased = bBracket = FALSE; + eCurExpr = SbOPERAND; + pExpr = new SbiExprNode( pParser, NULL, t, NULL ); +} + +SbiExpression::~SbiExpression() +{ + delete pExpr; +} + +// Einlesen eines kompletten Bezeichners +// Ein Bezeichner hat folgende Form: +// name[(Parameter)][.Name[(parameter)]]... +// Strukturelemente werden ueber das Element pNext verkoppelt, +// damit sie nicht im Baum stehen. + +// Folgen Parameter ohne Klammer? Dies kann eine Zahl, ein String, +// ein Symbol oder auch ein Komma sein (wenn der 1. Parameter fehlt) + +static BOOL DoParametersFollow( SbiParser* p, SbiExprType eCurExpr, SbiToken eTok ) +{ + if( eTok == LPAREN ) + return TRUE; + // Aber nur, wenn CALL-aehnlich! + if( !p->WhiteSpace() || eCurExpr != SbSYMBOL ) + return FALSE; + if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING + || eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT ) + { + return TRUE; + } + else // check for default params with reserved names ( e.g. names of tokens ) + { + SbiTokenizer tokens( *(SbiTokenizer*)p ); + // Urk the Next() / Peek() symantics are... weird + tokens.Next(); + if ( tokens.Peek() == ASSIGN ) + return TRUE; + } + return FALSE; +} + +// Definition eines neuen Symbols + +static SbiSymDef* AddSym + ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr, + const String& rName, SbxDataType eType, SbiParameters* pPar ) +{ + SbiSymDef* pDef; + // A= ist keine Prozedur + BOOL bHasType = BOOL( eTok == EQ || eTok == DOT ); + if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar ) + { + // Dies ist also eine Prozedur + // da suche man doch den richtigen Pool raus, da Procs + // immer in einem Public-Pool landen muessen + SbiSymPool* pPool = &rPool; + if( pPool->GetScope() != SbPUBLIC ) + pPool = &rPool.GetParser()->aPublics; + SbiProcDef* pProc = pPool->AddProc( rName ); + + // Sonderbehandlung fuer Colls wie Documents(1) + if( eCurExpr == SbSTDEXPR ) + bHasType = TRUE; + + pDef = pProc; + pDef->SetType( bHasType ? eType : SbxEMPTY ); + if( pPar ) + { + // Dummy-Parameter generieren + USHORT n = 1; + for( short i = 0; i < pPar->GetSize(); i++ ) + { + String aPar = String::CreateFromAscii( "PAR" ); + aPar += ++n; + pProc->GetParams().AddSym( aPar ); + } + } + } + else + { + // oder ein normales Symbol + pDef = rPool.AddSym( rName ); + pDef->SetType( eType ); + } + return pDef; +} + +// Zur Zeit sind sogar Keywords zugelassen (wg. gleichnamiger Dflt-Properties) + +SbiExprNode* SbiExpression::Term( void ) +{ + if( pParser->Peek() == DOT ) + { + // eine WITH-Variable + SbiExprNode* pWithVar = pParser->GetWithVar(); + // #26608: Ans Ende der Node-Kette gehen, um richtiges Objekt zu uebergeben + SbiSymDef* pDef = pWithVar ? pWithVar->GetRealVar() : NULL; + SbiExprNode* pNd = NULL; + if( !pDef ) + { + pParser->Next(); + } + else + { + pNd = ObjTerm( *pDef ); + if( pNd ) + pNd->SetWithParent( pWithVar ); + } + if( !pNd ) + { + pParser->Error( SbERR_UNEXPECTED, DOT ); + pNd = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); + } + return pNd; + } + + SbiToken eTok = pParser->Next(); + // Anfang des Parsings merken + pParser->LockColumn(); + String aSym( pParser->GetSym() ); + SbxDataType eType = pParser->GetType(); + SbiParameters* pPar = NULL; + SbiExprListVector* pvMoreParLcl = NULL; + // Folgen Parameter? + SbiToken eNextTok = pParser->Peek(); + // Ist es ein benannter Parameter? + // Dann einfach eine Stringkonstante erzeugen. Diese wird + // im SbiParameters-ctor erkannt und weiterverarbeitet + if( eNextTok == ASSIGN ) + { + pParser->UnlockColumn(); + return new SbiExprNode( pParser, aSym ); + } + // ab hier sind keine Keywords zugelassen! + if( pParser->IsKwd( eTok ) ) + { + if( pParser->IsCompatible() && eTok == INPUT ) + { + eTok = SYMBOL; + } + else + { + pParser->Error( SbERR_SYNTAX ); + bError = TRUE; + } + } + + if( DoParametersFollow( pParser, eCurExpr, eTok = eNextTok ) ) + { + bool bStandaloneExpression = (m_eMode == EXPRMODE_STANDALONE); + pPar = new SbiParameters( pParser, bStandaloneExpression ); + bError |= !pPar->IsValid(); + if( !bError ) + bBracket = pPar->IsBracket(); + eTok = pParser->Peek(); + + // i75443 check for additional sets of parameters + while( eTok == LPAREN ) + { + if( pvMoreParLcl == NULL ) + pvMoreParLcl = new SbiExprListVector(); + SbiParameters* pAddPar = new SbiParameters( pParser ); + pvMoreParLcl->push_back( pAddPar ); + bError |= !pPar->IsValid(); + eTok = pParser->Peek(); + } + } + // Es koennte ein Objektteil sein, wenn . oder ! folgt + // Bei . muss aber die Variable bereits definiert sein; wenn pDef + // nach der Suche NULL ist, isses ein Objekt! + BOOL bObj = BOOL( ( eTok == DOT || eTok == EXCLAM ) + && !pParser->WhiteSpace() ); + if( bObj ) + { + bBracket = FALSE; // Now the bracket for the first term is obsolete + if( eType == SbxVARIANT ) + eType = SbxOBJECT; + else + { + // Name%. geht wirklich nicht! + pParser->Error( SbERR_BAD_DECLARATION, aSym ); + bError = TRUE; + } + } + // Suche: + SbiSymDef* pDef = pParser->pPool->Find( aSym ); + if( !pDef ) + { + // Teil der Runtime-Library? + // AB 31.3.1996: In Parser-Methode ausgelagert + // (wird auch in SbiParser::DefVar() in DIM.CXX benoetigt) + pDef = pParser->CheckRTLForSym( aSym, eType ); + } + if( !pDef ) + { + // Falls ein Punkt angegeben war, isses Teil eines Objekts, + // also muss der Returnwert ein Objekt sein + if( bObj ) + eType = SbxOBJECT; + pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar ); + // Looks like this is a local ( but undefined variable ) + // if it is in a static procedure then make this Symbol + // static + if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() ) + pDef->SetStatic(); + } + else + { + + // Symbol ist bereits definiert. + // Ist es eine Konstante? + SbiConstDef* pConst = pDef->GetConstDef(); + if( pConst ) + { + if( pConst->GetType() == SbxSTRING ) + return new SbiExprNode( pParser, pConst->GetString() ); + else + return new SbiExprNode( pParser, pConst->GetValue(), pConst->GetType() ); + } + // Hat es Dimensionen, + // und sind auch Parameter angegeben? + // (Wobei 0 Parameter () entsprechen) + if( pDef->GetDims() ) + { + if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() ) + pParser->Error( SbERR_WRONG_DIMS ); + } + if( pDef->IsDefinedAs() ) + { + SbxDataType eDefType = pDef->GetType(); + // #119187 Only error if types conflict + if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType ) + { + // Wie? Erst mit AS definieren und dann einen Suffix nehmen? + pParser->Error( SbERR_BAD_DECLARATION, aSym ); + bError = TRUE; + } + else if ( eType == SbxVARIANT ) + // Falls nix angegeben, den Typ des Eintrags nehmen + // aber nur, wenn die Var nicht mit AS XXX definiert ist + // damit erwischen wir n% = 5 : print n + eType = eDefType; + } + // Funktion? + if( pDef->GetProcDef() ) + { + SbiProcDef* pProc = pDef->GetProcDef(); + if( pPar && pProc->GetLib().Len() ) // DECLARE benutzt? + pPar->SetProc( pProc ); + // Wenn keine Pars, vorerst nichts machen + // Pruefung auf Typ-Anzahl waere denkbar + } + // Typcheck bei Variablen: + // ist explizit im Scanner etwas anderes angegeben? + // Bei Methoden ist dies OK! + if( eType != SbxVARIANT && // Variant nimmt alles + eType != pDef->GetType() && + !pDef->GetProcDef() ) + { + // Es kann sein, dass pDef ein Objekt beschreibt, das bisher + // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern + // AB, 16.12.95 (Vielleicht noch aehnliche Faelle moeglich ?!?) + if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT ) + { + pDef->SetType( SbxOBJECT ); + } + else + { + pParser->Error( SbERR_BAD_DECLARATION, aSym ); + bError = TRUE; + } + } + } + SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType ); + if( !pPar ) + pPar = new SbiParameters( pParser,FALSE,FALSE ); + pNd->aVar.pPar = pPar; + pNd->aVar.pvMorePar = pvMoreParLcl; + if( bObj ) + { + // AB, 8.1.95: Objekt kann auch vom Typ SbxVARIANT sein + if( pDef->GetType() == SbxVARIANT ) + pDef->SetType( SbxOBJECT ); + // Falls wir etwas mit Punkt einscannen, muss der + // Typ SbxOBJECT sein + if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT ) + { + pParser->Error( SbERR_BAD_DECLARATION, aSym ); + bError = TRUE; + } + if( !bError ) + pNd->aVar.pNext = ObjTerm( *pDef ); + } + // Merken der Spalte 1 wieder freigeben + pParser->UnlockColumn(); + return pNd; +} + +// Aufbau eines Objekt-Terms. Ein derartiger Term ist Teil +// eines Ausdrucks, der mit einer Objektvariablen beginnt. + +SbiExprNode* SbiExpression::ObjTerm( SbiSymDef& rObj ) +{ + pParser->Next(); + SbiToken eTok = pParser->Next(); + if( eTok != SYMBOL && !pParser->IsKwd( eTok ) && !pParser->IsExtra( eTok ) ) + { + // #66745 Einige Operatoren koennen in diesem Kontext auch + // als Identifier zugelassen werden, wichtig fuer StarOne + if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR && + eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS ) + { + pParser->Error( SbERR_VAR_EXPECTED ); + bError = TRUE; + } + } + /* #118410 Allow type for Class methods and RTL object, e.g. RTL.Chr$(97) + else + { + if( pParser->GetType() != SbxVARIANT ) + pParser->Error( SbERR_SYNTAX ), bError = TRUE; + } + */ + if( bError ) + return NULL; + + String aSym( pParser->GetSym() ); + SbxDataType eType = pParser->GetType(); + SbiParameters* pPar = NULL; + eTok = pParser->Peek(); + // Parameter? + if( DoParametersFollow( pParser, eCurExpr, eTok ) ) + { + pPar = new SbiParameters( pParser ); + bError |= !pPar->IsValid(); + eTok = pParser->Peek(); + } + BOOL bObj = BOOL( ( eTok == DOT || eTok == EXCLAM ) && !pParser->WhiteSpace() ); + if( bObj ) + { + if( eType == SbxVARIANT ) + eType = SbxOBJECT; + else + { + // Name%. geht wirklich nicht! + pParser->Error( SbERR_BAD_DECLARATION, aSym ); + bError = TRUE; + } + } + + // Der Symbol-Pool eines Objekts ist immer PUBLIC + SbiSymPool& rPool = rObj.GetPool(); + rPool.SetScope( SbPUBLIC ); + SbiSymDef* pDef = rPool.Find( aSym ); + if( !pDef ) + { + pDef = AddSym( eTok, rPool, eCurExpr, aSym, eType, pPar ); + pDef->SetType( eType ); + } + + SbiExprNode* pNd = new SbiExprNode( pParser, *pDef, eType ); + pNd->aVar.pPar = pPar; + if( bObj ) + { + // Falls wir etwas mit Punkt einscannen, muss der + // Typ SbxOBJECT sein + + // AB, 3.1.96 + // Es kann sein, dass pDef ein Objekt beschreibt, das bisher + // nur als SbxVARIANT erkannt wurde, dann Typ von pDef aendern + if( pDef->GetType() == SbxVARIANT ) + pDef->SetType( SbxOBJECT ); + + if( pDef->GetType() != SbxOBJECT ) + { + pParser->Error( SbERR_BAD_DECLARATION, aSym ); + bError = TRUE; + } + if( !bError ) + { + pNd->aVar.pNext = ObjTerm( *pDef ); + pNd->eType = eType; + } + } + return pNd; +} + +// Als Operanden kommen in Betracht: +// Konstante +// skalare Variable +// Strukturelemente +// Array-Elemente +// Funktionen +// geklammerte Ausdruecke + +SbiExprNode* SbiExpression::Operand() +{ + SbiExprNode *pRes; + SbiToken eTok; + + // Operand testen: + switch( eTok = pParser->Peek() ) + { + case SYMBOL: + pRes = Term(); + // process something like "IF Not r Is Nothing Then .." + if( pParser->IsVBASupportOn() && pParser->Peek() == IS ) + { + eTok = pParser->Next(); + pRes = new SbiExprNode( pParser, pRes, eTok, Like() ); + } + break; + case DOT: // .with + pRes = Term(); break; + case NUMBER: + pParser->Next(); + pRes = new SbiExprNode( pParser, pParser->GetDbl(), pParser->GetType() ); + break; + case FIXSTRING: + pParser->Next(); + pRes = new SbiExprNode( pParser, pParser->GetSym() ); break; + case LPAREN: + pParser->Next(); + if( nParenLevel == 0 && m_eMode == EXPRMODE_LPAREN_PENDING && pParser->Peek() == RPAREN ) + { + m_eMode = EXPRMODE_EMPTY_PAREN; + pRes = new SbiExprNode(); // Dummy node + pParser->Next(); + break; + } + nParenLevel++; + pRes = Boolean(); + if( pParser->Peek() != RPAREN ) + { + // If there was a LPARAM, it does not belong to the expression + if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING ) + m_eMode = EXPRMODE_LPAREN_NOT_NEEDED; + else + pParser->Error( SbERR_BAD_BRACKETS ); + } + else + { + pParser->Next(); + if( nParenLevel == 1 && m_eMode == EXPRMODE_LPAREN_PENDING ) + { + SbiToken eTokAfterRParen = pParser->Peek(); + if( eTokAfterRParen == EQ || eTokAfterRParen == LPAREN || eTokAfterRParen == DOT ) + m_eMode = EXPRMODE_ARRAY_OR_OBJECT; + else + m_eMode = EXPRMODE_STANDARD; + } + } + nParenLevel--; + pRes->bComposite = TRUE; + break; + default: + // Zur Zeit sind Keywords hier OK! + if( pParser->IsKwd( eTok ) ) + pRes = Term(); + else + { + pParser->Next(); + pRes = new SbiExprNode( pParser, 1.0, SbxDOUBLE ); // bei Fehlern + pParser->Error( SbERR_UNEXPECTED, eTok ); + } + } + return pRes; +} + +SbiExprNode* SbiExpression::Unary() +{ + SbiExprNode* pNd; + SbiToken eTok = pParser->Peek(); + switch( eTok ) + { + case MINUS: + eTok = NEG; + case NOT: + pParser->Next(); + pNd = new SbiExprNode( pParser, Unary(), eTok, NULL ); + break; + case PLUS: + pParser->Next(); + pNd = Unary(); + break; + case TYPEOF: + { + pParser->Next(); + SbiExprNode* pObjNode = Operand(); + pParser->TestToken( IS ); + String aDummy; + SbiSymDef* pTypeDef = new SbiSymDef( aDummy ); + pParser->TypeDecl( *pTypeDef, TRUE ); + pNd = new SbiExprNode( pParser, pObjNode, pTypeDef->GetTypeId() ); + break; + } + default: + pNd = Operand(); + } + return pNd; +} + +SbiExprNode* SbiExpression::Exp() +{ + SbiExprNode* pNd = Unary(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + while( pParser->Peek() == EXPON ) { + SbiToken eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, Unary() ); + } + } + return pNd; +} + +SbiExprNode* SbiExpression::MulDiv() +{ + SbiExprNode* pNd = Exp(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + for( ;; ) + { + SbiToken eTok = pParser->Peek(); + if( eTok != MUL && eTok != DIV ) + break; + eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, Exp() ); + } + } + return pNd; +} + +SbiExprNode* SbiExpression::IntDiv() +{ + SbiExprNode* pNd = MulDiv(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + while( pParser->Peek() == IDIV ) { + SbiToken eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, MulDiv() ); + } + } + return pNd; +} + +SbiExprNode* SbiExpression::Mod() +{ + SbiExprNode* pNd = IntDiv(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + while( pParser->Peek() == MOD ) { + SbiToken eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, IntDiv() ); + } + } + return pNd; +} + +SbiExprNode* SbiExpression::AddSub() +{ + SbiExprNode* pNd = Mod(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + for( ;; ) + { + SbiToken eTok = pParser->Peek(); + if( eTok != PLUS && eTok != MINUS ) + break; + eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, Mod() ); + } + } + return pNd; +} + +SbiExprNode* SbiExpression::Cat() +{ + SbiExprNode* pNd = AddSub(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + for( ;; ) + { + SbiToken eTok = pParser->Peek(); + if( eTok != CAT ) + break; + eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, AddSub() ); + } + } + return pNd; +} + +SbiExprNode* SbiExpression::Comp() +{ + SbiExprNode* pNd = Cat(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + short nCount = 0; + for( ;; ) + { + SbiToken eTok = pParser->Peek(); + if( m_eMode == EXPRMODE_ARRAY_OR_OBJECT ) + break; + if( eTok != EQ && eTok != NE && eTok != LT + && eTok != GT && eTok != LE && eTok != GE ) + break; + eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, Cat() ); + nCount++; + } + } + return pNd; +} + +SbiExprNode* SbiExpression::Like() +{ + SbiExprNode* pNd = Comp(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + short nCount = 0; + while( pParser->Peek() == LIKE ) { + SbiToken eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, Comp() ), nCount++; + } + // Mehrere Operatoren hintereinander gehen nicht + if( nCount > 1 ) + { + pParser->Error( SbERR_SYNTAX ); + bError = TRUE; + } + } + return pNd; +} + +SbiExprNode* SbiExpression::Boolean() +{ + SbiExprNode* pNd = Like(); + if( m_eMode != EXPRMODE_EMPTY_PAREN ) + { + for( ;; ) + { + SbiToken eTok = pParser->Peek(); + if( eTok != AND && eTok != OR && eTok != XOR + && eTok != EQV && eTok != IMP && eTok != IS ) + break; + eTok = pParser->Next(); + pNd = new SbiExprNode( pParser, pNd, eTok, Like() ); + } + } + return pNd; +} + +/*************************************************************************** +|* +|* SbiConstExpression +|* +***************************************************************************/ + +// Parsing einer Expression, die sich zu einer numerischen +// Konstanten verarbeiten laesst. + +SbiConstExpression::SbiConstExpression( SbiParser* p ) : SbiExpression( p ) +{ + if( pExpr->IsConstant() ) + { + eType = pExpr->GetType(); + if( pExpr->IsNumber() ) + { + nVal = pExpr->nVal; + } + else + { + nVal = 0; + aVal = pExpr->aStrVal; + } + } + else + { + // #40204 Spezialbehandlung fuer BOOL-Konstanten + BOOL bIsBool = FALSE; + if( pExpr->eNodeType == SbxVARVAL ) + { + SbiSymDef* pVarDef = pExpr->GetVar(); + + // Ist es eine BOOL-Konstante? + BOOL bBoolVal = FALSE; + if( pVarDef->GetName().EqualsIgnoreCaseAscii( "true" ) ) + //if( pVarDef->GetName().ICompare( "true" ) == COMPARE_EQUAL ) + { + bIsBool = TRUE; + bBoolVal = TRUE; + } + else if( pVarDef->GetName().EqualsIgnoreCaseAscii( "false" ) ) + //else if( pVarDef->GetName().ICompare( "false" ) == COMPARE_EQUAL ) + { + bIsBool = TRUE; + bBoolVal = FALSE; + } + + // Wenn es ein BOOL ist, Node austauschen + if( bIsBool ) + { + delete pExpr; + pExpr = new SbiExprNode( pParser, (bBoolVal ? SbxTRUE : SbxFALSE), SbxINTEGER ); + eType = pExpr->GetType(); + nVal = pExpr->nVal; + } + } + + if( !bIsBool ) + { + pParser->Error( SbERR_SYNTAX ); + eType = SbxDOUBLE; + nVal = 0; + } + } +} + +short SbiConstExpression::GetShortValue() +{ + if( eType == SbxSTRING ) + { + SbxVariableRef refConv = new SbxVariable; + refConv->PutString( aVal ); + return refConv->GetInteger(); + } + else + { + double n = nVal; + if( n > 0 ) n += .5; else n -= .5; + if( n > SbxMAXINT ) n = SbxMAXINT, pParser->Error( SbERR_OUT_OF_RANGE ); + else + if( n < SbxMININT ) n = SbxMININT, pParser->Error( SbERR_OUT_OF_RANGE ); + return (short) n; + } +} + + +/*************************************************************************** +|* +|* SbiExprList +|* +***************************************************************************/ + +SbiExprList::SbiExprList( SbiParser* p ) +{ + pParser = p; + pFirst = NULL; + pProc = NULL; + nExpr = + nDim = 0; + bError = + bBracket = FALSE; +} + +SbiExprList::~SbiExprList() +{ + SbiExpression* p = pFirst; + while( p ) + { + SbiExpression* q = p->pNext; + delete p; + p = q; + } +} + +// Parameter anfordern (ab 0) + +SbiExpression* SbiExprList::Get( short n ) +{ + SbiExpression* p = pFirst; + while( n-- && p ) + p = p->pNext; + return p; +} + +void SbiExprList::addExpression( SbiExpression* pExpr ) +{ + SbiExpression* p = pFirst; + while( p && p->pNext ) + p = p->pNext; + + p->pNext = pExpr; +} + + +/*************************************************************************** +|* +|* SbiParameters +|* +***************************************************************************/ + +// Parsender Konstruktor: +// Die Parameterliste wird komplett geparst. +// "Prozedurname()" ist OK. +// Dann handelt es sich um eine Funktion ohne Parameter +// respektive um die Angabe eines Arrays als Prozedurparameter. + +// #i79918/#i80532: bConst has never been set to true +// -> reused as bStandaloneExpression +//SbiParameters::SbiParameters( SbiParser* p, BOOL bConst, BOOL bPar) : +SbiParameters::SbiParameters( SbiParser* p, BOOL bStandaloneExpression, BOOL bPar) : + SbiExprList( p ) +{ + if( !bPar ) + return; + + SbiExpression *pExpr; + SbiToken eTok = pParser->Peek(); + + // evtl. Klammer auf weg: + bool bAssumeExprLParenMode = false; + bool bAssumeArrayMode = false; + if( eTok == LPAREN ) + { + if( bStandaloneExpression ) + { + bAssumeExprLParenMode = true; + } + else + { + bBracket = TRUE; + pParser->Next(); + eTok = pParser->Peek(); + } + } + + // Ende-Test + if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) ) + { + if( eTok == RPAREN ) + pParser->Next(); + return; + } + // Parametertabelle einlesen und in richtiger Folge ablegen! + SbiExpression* pLast = NULL; + String aName; + while( !bError ) + { + aName.Erase(); + // Fehlendes Argument + if( eTok == COMMA ) + { + pExpr = new SbiExpression( pParser, 0, SbxEMPTY ); + //if( bConst ) + // pParser->Error( SbERR_SYNTAX ), bError = TRUE; + } + // Benannte Argumente: entweder .name= oder name:= + else + { + if( bAssumeExprLParenMode ) + { + pExpr = new SbiExpression( pParser, SbSTDEXPR, EXPRMODE_LPAREN_PENDING ); + bAssumeExprLParenMode = FALSE; + + SbiExprMode eModeAfter = pExpr->m_eMode; + if( eModeAfter == EXPRMODE_LPAREN_NOT_NEEDED ) + { + bBracket = TRUE; + } + else if( eModeAfter == EXPRMODE_ARRAY_OR_OBJECT ) + { + // Expression "looks" like an array assignment + // a(...)[(...)] = ? or a(...).b(...) + // RPAREN is already parsed + bBracket = TRUE; + bAssumeArrayMode = true; + eTok = NIL; + } + else if( eModeAfter == EXPRMODE_EMPTY_PAREN ) + { + bBracket = TRUE; + delete pExpr; + return; + } + } + else + pExpr = new SbiExpression( pParser ); + + //pExpr = bConst ? new SbiConstExpression( pParser ) + // : new SbiExpression( pParser ); + if( !bAssumeArrayMode ) + { + if( pParser->Peek() == ASSIGN ) + { + // VBA mode: name:= + // SbiExpression::Term() hat einen String daraus gemacht + aName = pExpr->GetString(); + delete pExpr; + pParser->Next(); + pExpr = new SbiExpression( pParser ); + //if( bConst ) + // pParser->Error( SbERR_SYNTAX ), bError = TRUE; + } + pExpr->GetName() = aName; + } + } + pExpr->pNext = NULL; + if( !pLast ) + pFirst = pLast = pExpr; + else + pLast->pNext = pExpr, pLast = pExpr; + nExpr++; + bError |= !pExpr->IsValid(); + + if( bAssumeArrayMode ) + break; + + // Naechstes Element? + eTok = pParser->Peek(); + if( eTok != COMMA ) + { + if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) ) + break; + pParser->Error( bBracket + ? SbERR_BAD_BRACKETS + : SbERR_EXPECTED, COMMA ); + bError = TRUE; + } + else + { + pParser->Next(); + eTok = pParser->Peek(); + if( ( bBracket && eTok == RPAREN ) || pParser->IsEoln( eTok ) ) + break; + } + } + // Schliessende Klammer + if( eTok == RPAREN ) + { + pParser->Next(); + pParser->Peek(); + if( !bBracket ) + { + pParser->Error( SbERR_BAD_BRACKETS ); + bError = TRUE; + } + } + nDim = nExpr; +} + +/*************************************************************************** +|* +|* SbiDimList +|* +***************************************************************************/ + +// Parsender Konstruktor: +// Eine Liste von Array-Dimensionen wird geparst. Die Ausdruecke werden +// auf numerisch getestet. Das bCONST-Bit wird gesetzt, wenn alle Ausdruecke +// Integer-Konstanten sind. + +SbiDimList::SbiDimList( SbiParser* p ) : SbiExprList( p ) +{ + bConst = TRUE; + + if( pParser->Next() != LPAREN ) + { + pParser->Error( SbERR_EXPECTED, LPAREN ); + bError = TRUE; return; + } + + if( pParser->Peek() != RPAREN ) + { + SbiExpression *pExpr1, *pExpr2, *pLast = NULL; + SbiToken eTok; + for( ;; ) + { + pExpr1 = new SbiExpression( pParser ); + eTok = pParser->Next(); + if( eTok == TO ) + { + pExpr2 = new SbiExpression( pParser ); + eTok = pParser->Next(); + bConst &= pExpr1->IsIntConstant() & pExpr2->IsIntConstant(); + bError |= !pExpr1->IsValid(); + bError |= !pExpr2->IsValid(); + pExpr1->pNext = pExpr2; + if( !pLast ) + pFirst = pExpr1; + else + pLast->pNext = pExpr1; + pLast = pExpr2; + nExpr += 2; + } + else + { + // Nur eine Dim-Angabe + pExpr1->SetBased(); + pExpr1->pNext = NULL; + bConst &= pExpr1->IsIntConstant(); + bError |= !pExpr1->IsValid(); + if( !pLast ) + pFirst = pLast = pExpr1; + else + pLast->pNext = pExpr1, pLast = pExpr1; + nExpr++; + } + nDim++; + if( eTok == RPAREN ) break; + if( eTok != COMMA ) + { + pParser->Error( SbERR_BAD_BRACKETS ); + pParser->Next(); + break; + } + } + } + else pParser->Next(); +} + diff --git a/basic/source/comp/io.cxx b/basic/source/comp/io.cxx new file mode 100644 index 000000000000..829f657bbe43 --- /dev/null +++ b/basic/source/comp/io.cxx @@ -0,0 +1,324 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: io.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include <tools/stream.hxx> +#include "sbcomp.hxx" +#include "iosys.hxx" + +// Test, ob ein I/O-Channel angegeben wurde + +BOOL SbiParser::Channel( BOOL bAlways ) +{ + BOOL bRes = FALSE; + Peek(); + if( IsHash() ) + { + SbiExpression aExpr( this ); + while( Peek() == COMMA || Peek() == SEMICOLON ) + Next(); + aExpr.Gen(); + aGen.Gen( _CHANNEL ); + bRes = TRUE; + } + else if( bAlways ) + Error( SbERR_EXPECTED, "#" ); + return bRes; +} + +// Fuer PRINT und WRITE wird bei Objektvariablen versucht, +// die Default-Property anzusprechen. + +// PRINT + +void SbiParser::Print() +{ + BOOL bChan = Channel(); + // Die Ausdruecke zum Drucken: + while( !bAbort ) + { + if( !IsEoln( Peek() ) ) + { + SbiExpression* pExpr = new SbiExpression( this ); + pExpr->Gen(); + delete pExpr; + Peek(); + aGen.Gen( eCurTok == COMMA ? _PRINTF : _BPRINT ); + } + if( eCurTok == COMMA || eCurTok == SEMICOLON ) + { + Next(); + if( IsEoln( Peek() ) ) break; + } + else + { + aGen.Gen( _PRCHAR, '\n' ); + break; + } + } + if( bChan ) + aGen.Gen( _CHAN0 ); +} + +// WRITE #chan, expr, ... + +void SbiParser::Write() +{ + BOOL bChan = Channel(); + // Die Ausdruecke zum Drucken: + while( !bAbort ) + { + SbiExpression* pExpr = new SbiExpression( this ); + pExpr->Gen(); + delete pExpr; + aGen.Gen( _BWRITE ); + if( Peek() == COMMA ) + { + aGen.Gen( _PRCHAR, ',' ); + Next(); + if( IsEoln( Peek() ) ) break; + } + else + { + aGen.Gen( _PRCHAR, '\n' ); + break; + } + } + if( bChan ) + aGen.Gen( _CHAN0 ); +} + +// LINE INPUT [prompt], var$ + +void SbiParser::LineInput() +{ + Channel( TRUE ); + // BOOL bChan = Channel( TRUE ); + SbiExpression* pExpr = new SbiExpression( this, SbOPERAND ); + /* AB 15.1.96: Keinen allgemeinen Ausdruck mehr zulassen + SbiExpression* pExpr = new SbiExpression( this ); + if( !pExpr->IsVariable() ) + { + SbiToken eTok = Peek(); + if( eTok == COMMA || eTok == SEMICOLON ) Next(); + else Error( SbERR_EXPECTED, COMMA ); + // mit Prompt + if( !bChan ) + { + pExpr->Gen(); + aGen.Gen( _PROMPT ); + } + else + Error( SbERR_VAR_EXPECTED ); + delete pExpr; + pExpr = new SbiExpression( this, SbOPERAND ); + } + */ + if( !pExpr->IsVariable() ) + Error( SbERR_VAR_EXPECTED ); + if( pExpr->GetType() != SbxVARIANT && pExpr->GetType() != SbxSTRING ) + Error( SbERR_CONVERSION ); + pExpr->Gen(); + aGen.Gen( _LINPUT ); + delete pExpr; + aGen.Gen( _CHAN0 ); // ResetChannel() nicht mehr in StepLINPUT() +} + +// INPUT + +void SbiParser::Input() +{ + aGen.Gen( _RESTART ); + Channel( TRUE ); + // BOOL bChan = Channel( TRUE ); + SbiExpression* pExpr = new SbiExpression( this, SbOPERAND ); + /* ALT: Jetzt keinen allgemeinen Ausdruck mehr zulassen + SbiExpression* pExpr = new SbiExpression( this ); + ... + siehe LineInput + */ + while( !bAbort ) + { + if( !pExpr->IsVariable() ) + Error( SbERR_VAR_EXPECTED ); + pExpr->Gen(); + aGen.Gen( _INPUT ); + if( Peek() == COMMA ) + { + Next(); + delete pExpr; + pExpr = new SbiExpression( this, SbOPERAND ); + } + else break; + } + delete pExpr; + aGen.Gen( _CHAN0 ); // ResetChannel() nicht mehr in StepINPUT() +} + +// OPEN stringexpr FOR mode ACCCESS access mode AS Channel [Len=n] + +void SbiParser::Open() +{ + SbiExpression aFileName( this ); + SbiToken eTok; + TestToken( FOR ); + short nMode = 0; + short nFlags = 0; + switch( Next() ) + { + case INPUT: + nMode = STREAM_READ; nFlags |= SBSTRM_INPUT; break; + case OUTPUT: + nMode = STREAM_WRITE | STREAM_TRUNC; nFlags |= SBSTRM_OUTPUT; break; + case APPEND: + nMode = STREAM_WRITE; nFlags |= SBSTRM_APPEND; break; + case RANDOM: + nMode = STREAM_READ | STREAM_WRITE; nFlags |= SBSTRM_RANDOM; break; + case BINARY: + nMode = STREAM_READ | STREAM_WRITE; nFlags |= SBSTRM_BINARY; break; + default: + Error( SbERR_SYNTAX ); + } + if( Peek() == ACCESS ) + { + Next(); + eTok = Next(); + // #27964# Nur STREAM_READ,STREAM_WRITE-Flags in nMode beeinflussen + nMode &= ~(STREAM_READ | STREAM_WRITE); // loeschen + if( eTok == READ ) + { + if( Peek() == WRITE ) + { + Next(); + nMode |= (STREAM_READ | STREAM_WRITE); + } + else + nMode |= STREAM_READ; + } + else if( eTok == WRITE ) + nMode |= STREAM_WRITE; + else + Error( SbERR_SYNTAX ); + } + switch( Peek() ) + { +#ifdef SHARED +#undef SHARED +#define tmpSHARED +#endif + case SHARED: + Next(); nMode |= STREAM_SHARE_DENYNONE; break; +#ifdef tmpSHARED +#define SHARED +#undef tmpSHARED +#endif + case LOCK: + Next(); + eTok = Next(); + if( eTok == READ ) + { + if( Peek() == WRITE ) Next(), nMode |= STREAM_SHARE_DENYALL; + else nMode |= STREAM_SHARE_DENYREAD; + } + else if( eTok == WRITE ) + nMode |= STREAM_SHARE_DENYWRITE; + else + Error( SbERR_SYNTAX ); + break; + default: break; + } + TestToken( AS ); + // Die Kanalnummer + SbiExpression* pChan = new SbiExpression( this ); + if( !pChan ) + Error( SbERR_SYNTAX ); + SbiExpression* pLen = NULL; + if( Peek() == SYMBOL ) + { + Next(); + String aLen( aSym ); + if( aLen.EqualsIgnoreCaseAscii( "LEN" ) ) + { + TestToken( EQ ); + pLen = new SbiExpression( this ); + } + } + if( !pLen ) pLen = new SbiExpression( this, 128, SbxINTEGER ); + // Der Stack fuer den OPEN-Befehl sieht wie folgt aus: + // Blocklaenge + // Kanalnummer + // Dateiname + pLen->Gen(); + if( pChan ) + pChan->Gen(); + aFileName.Gen(); + aGen.Gen( _OPEN, nMode, nFlags ); + delete pLen; + delete pChan; +} + +// NAME file AS file + +void SbiParser::Name() +{ + SbiExpression aExpr1( this ); + TestToken( AS ); + SbiExpression aExpr2( this ); + aExpr1.Gen(); + aExpr2.Gen(); + aGen.Gen( _RENAME ); +} + +// CLOSE [n,...] + +void SbiParser::Close() +{ + Peek(); + if( IsEoln( eCurTok ) ) + aGen.Gen( _CLOSE, 0 ); + else + for( ;; ) + { + SbiExpression aExpr( this ); + while( Peek() == COMMA || Peek() == SEMICOLON ) + Next(); + aExpr.Gen(); + aGen.Gen( _CHANNEL ); + aGen.Gen( _CLOSE, 1 ); + + if( IsEoln( Peek() ) ) + break; + } +} + + diff --git a/basic/source/comp/loops.cxx b/basic/source/comp/loops.cxx new file mode 100644 index 000000000000..264946d27c46 --- /dev/null +++ b/basic/source/comp/loops.cxx @@ -0,0 +1,561 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: loops.cxx,v $ + * $Revision: 1.13 $ + * + * 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 "sbcomp.hxx" + +// Single-line IF und Multiline IF + +void SbiParser::If() +{ + UINT32 nEndLbl; + SbiToken eTok = NIL; + // Ende-Tokens ignorieren: + SbiExpression aCond( this ); + aCond.Gen(); + TestToken( THEN ); + if( IsEoln( Next() ) ) + { + // AB 13.5.1996: #27720# Am Ende jeden Blocks muss ein Jump zu ENDIF + // eingefuegt werden, damit bei ELSEIF nicht erneut die Bedingung + // ausgewertet wird. Die Tabelle nimmt alle Absprungstellen auf. +#define JMP_TABLE_SIZE 100 + UINT32 pnJmpToEndLbl[JMP_TABLE_SIZE]; // 100 ELSEIFs zulaessig + USHORT iJmp = 0; // aktueller Tabellen-Index + + // multiline IF + nEndLbl = aGen.Gen( _JUMPF, 0 ); + eTok = Peek(); + while( !( eTok == ELSEIF || eTok == ELSE || eTok == ENDIF ) && + !bAbort && Parse() ) + { + eTok = Peek(); + if( IsEof() ) + { + Error( SbERR_BAD_BLOCK, IF ); bAbort = TRUE; return; + } + } + // ELSEIF? + while( eTok == ELSEIF ) + { + // #27720# Bei erfolgreichem IF/ELSEIF auf ENDIF springen + if( iJmp >= JMP_TABLE_SIZE ) + { + Error( SbERR_PROG_TOO_LARGE ); bAbort = TRUE; return; + } + pnJmpToEndLbl[iJmp++] = aGen.Gen( _JUMP, 0 ); + + Next(); + aGen.BackChain( nEndLbl ); + + aGen.Statement(); + SbiExpression* pCond = new SbiExpression( this ); + pCond->Gen(); + nEndLbl = aGen.Gen( _JUMPF, 0 ); + delete pCond; + TestToken( THEN ); + eTok = Peek(); + while( !( eTok == ELSEIF || eTok == ELSE || eTok == ENDIF ) && + !bAbort && Parse() ) + { + eTok = Peek(); + if( IsEof() ) + { + Error( SbERR_BAD_BLOCK, ELSEIF ); bAbort = TRUE; return; + } + } + } + if( eTok == ELSE ) + { + Next(); + UINT32 nElseLbl = nEndLbl; + nEndLbl = aGen.Gen( _JUMP, 0 ); + aGen.BackChain( nElseLbl ); + + aGen.Statement(); + StmntBlock( ENDIF ); + } + else if( eTok == ENDIF ) + Next(); + + // #27720# Jmp-Tabelle abarbeiten + while( iJmp > 0 ) + { + iJmp--; + aGen.BackChain( pnJmpToEndLbl[iJmp] ); + } + } + else + { + // single line IF + bSingleLineIf = TRUE; + nEndLbl = aGen.Gen( _JUMPF, 0 ); + Push( eCurTok ); + while( !bAbort ) + { + if( !Parse() ) break; + eTok = Peek(); + if( eTok == ELSE || eTok == EOLN || eTok == REM ) + break; + } + if( eTok == ELSE ) + { + Next(); + UINT32 nElseLbl = nEndLbl; + nEndLbl = aGen.Gen( _JUMP, 0 ); + aGen.BackChain( nElseLbl ); + while( !bAbort ) + { + if( !Parse() ) break; + eTok = Peek(); + if( eTok == EOLN ) + break; + } + } + bSingleLineIf = FALSE; + } + aGen.BackChain( nEndLbl ); +} + +// ELSE/ELSEIF/ENDIF ohne IF + +void SbiParser::NoIf() +{ + Error( SbERR_NO_IF ); + StmntBlock( ENDIF ); +} + +// DO WHILE...LOOP +// DO ... LOOP WHILE + +void SbiParser::DoLoop() +{ + UINT32 nStartLbl = aGen.GetPC(); + OpenBlock( DO ); + SbiToken eTok = Next(); + if( IsEoln( eTok ) ) + { + // DO ... LOOP [WHILE|UNTIL expr] + StmntBlock( LOOP ); + eTok = Next(); + if( eTok == UNTIL || eTok == WHILE ) + { + SbiExpression aExpr( this ); + aExpr.Gen(); + aGen.Gen( eTok == UNTIL ? _JUMPF : _JUMPT, nStartLbl ); + } else + if (eTok == EOLN || eTok == REM) + aGen.Gen (_JUMP, nStartLbl); + else + Error( SbERR_EXPECTED, WHILE ); + } + else + { + // DO [WHILE|UNTIL expr] ... LOOP + if( eTok == UNTIL || eTok == WHILE ) + { + SbiExpression aCond( this ); + aCond.Gen(); + } + UINT32 nEndLbl = aGen.Gen( eTok == UNTIL ? _JUMPT : _JUMPF, 0 ); + StmntBlock( LOOP ); + TestEoln(); + aGen.Gen( _JUMP, nStartLbl ); + aGen.BackChain( nEndLbl ); + } + CloseBlock(); +} + +// WHILE ... WEND + +void SbiParser::While() +{ + SbiExpression aCond( this ); + UINT32 nStartLbl = aGen.GetPC(); + aCond.Gen(); + UINT32 nEndLbl = aGen.Gen( _JUMPF, 0 ); + StmntBlock( WEND ); + aGen.Gen( _JUMP, nStartLbl ); + aGen.BackChain( nEndLbl ); +} + +// FOR var = expr TO expr STEP + +void SbiParser::For() +{ + bool bForEach = ( Peek() == EACH ); + if( bForEach ) + Next(); + SbiExpression aLvalue( this, SbOPERAND ); + aLvalue.Gen(); // Variable auf dem Stack + + if( bForEach ) + { + TestToken( _IN_ ); + SbiExpression aCollExpr( this, SbOPERAND ); + aCollExpr.Gen(); // Colletion var to for stack + TestEoln(); + aGen.Gen( _INITFOREACH ); + } + else + { + TestToken( EQ ); + SbiExpression aStartExpr( this ); + aStartExpr.Gen(); // Startausdruck auf dem Stack + TestToken( TO ); + SbiExpression aStopExpr( this ); + aStopExpr.Gen(); // Endausdruck auf dem Stack + if( Peek() == STEP ) + { + Next(); + SbiExpression aStepExpr( this ); + aStepExpr.Gen(); + } + else + { + SbiExpression aOne( this, 1, SbxINTEGER ); + aOne.Gen(); + } + TestEoln(); + // Der Stack hat jetzt 4 Elemente: Variable, Start, Ende, Inkrement + // Startwert binden + aGen.Gen( _INITFOR ); + } + + UINT32 nLoop = aGen.GetPC(); + // Test durchfuehren, evtl. Stack freigeben + UINT32 nEndTarget = aGen.Gen( _TESTFOR, 0 ); + OpenBlock( FOR ); + StmntBlock( NEXT ); + aGen.Gen( _NEXT ); + aGen.Gen( _JUMP, nLoop ); + // Kommen Variable nach NEXT? + if( Peek() == SYMBOL ) + { + SbiExpression aVar( this, SbOPERAND ); + if( aVar.GetRealVar() != aLvalue.GetRealVar() ) + Error( SbERR_EXPECTED, aLvalue.GetRealVar()->GetName() ); + } + aGen.BackChain( nEndTarget ); + CloseBlock(); +} + +// WITH .. END WITH + +void SbiParser::With() +{ + SbiExpression aVar( this, SbOPERAND ); + + // Letzten Knoten in der Objekt-Kette ueberpruefen + SbiExprNode *pNode = aVar.GetExprNode()->GetRealNode(); + SbiSymDef* pDef = pNode->GetVar(); + // Variant, AB 27.6.1997, #41090: bzw. empty -> muß Object sein + if( pDef->GetType() == SbxVARIANT || pDef->GetType() == SbxEMPTY ) + pDef->SetType( SbxOBJECT ); + else if( pDef->GetType() != SbxOBJECT ) + Error( SbERR_NEEDS_OBJECT ); + + // Knoten auch auf SbxOBJECT setzen, damit spaeter Gen() klappt + pNode->SetType( SbxOBJECT ); + + OpenBlock( NIL, aVar.GetExprNode() ); + StmntBlock( ENDWITH ); + CloseBlock(); +} + +// LOOP/NEXT/WEND ohne Konstrukt + +void SbiParser::BadBlock() +{ + if( eEndTok ) + Error( SbERR_BAD_BLOCK, eEndTok ); + else + Error( SbERR_BAD_BLOCK, "Loop/Next/Wend" ); +} + +// On expr Goto/Gosub n,n,n... + +void SbiParser::OnGoto() +{ + SbiExpression aCond( this ); + aCond.Gen(); + UINT32 nLabelsTarget = aGen.Gen( _ONJUMP, 0 ); + SbiToken eTok = Next(); + if( eTok != GOTO && eTok != GOSUB ) + { + Error( SbERR_EXPECTED, "GoTo/GoSub" ); + eTok = GOTO; + } + // Label-Tabelle einlesen: + UINT32 nLbl = 0; + do + { + SbiToken eTok2 = NIL; + eTok2 = Next(); // Label holen + if( MayBeLabel() ) + { + UINT32 nOff = pProc->GetLabels().Reference( aSym ); + aGen.Gen( _JUMP, nOff ); + nLbl++; + } + else Error( SbERR_LABEL_EXPECTED ); + } + while( !bAbort && TestComma() ); + if( eTok == GOSUB ) + nLbl |= 0x8000; + aGen.Patch( nLabelsTarget, nLbl ); +} + +// GOTO/GOSUB + +void SbiParser::Goto() +{ + SbiOpcode eOp = eCurTok == GOTO ? _JUMP : _GOSUB; + Next(); + if( MayBeLabel() ) + { + UINT32 nOff = pProc->GetLabels().Reference( aSym ); + aGen.Gen( eOp, nOff ); + } + else Error( SbERR_LABEL_EXPECTED ); +} + +// RETURN [label] + +void SbiParser::Return() +{ + Next(); + if( MayBeLabel() ) + { + UINT32 nOff = pProc->GetLabels().Reference( aSym ); + aGen.Gen( _RETURN, nOff ); + } + else aGen.Gen( _RETURN, 0 ); +} + +// SELECT CASE + +void SbiParser::Select() +{ + TestToken( CASE ); + SbiExpression aCase( this ); + SbiToken eTok = NIL; + aCase.Gen(); + aGen.Gen( _CASE ); + TestEoln(); + UINT32 nNextTarget = 0; + UINT32 nDoneTarget = 0; + BOOL bElse = FALSE; + // Die Cases einlesen: + while( !bAbort ) + { + eTok = Next(); + if( eTok == CASE ) + { + if( nNextTarget ) + aGen.BackChain( nNextTarget ), nNextTarget = 0; + aGen.Statement(); + // Jeden Case einlesen + BOOL bDone = FALSE; + UINT32 nTrueTarget = 0; + if( Peek() == ELSE ) + { + // CASE ELSE + Next(); + bElse = TRUE; + } + else while( !bDone ) + { + if( bElse ) + Error( SbERR_SYNTAX ); + SbiToken eTok2 = Peek(); + if( eTok2 == IS || ( eTok2 >= EQ && eTok2 <= GE ) ) + { // CASE [IS] operator expr + if( eTok2 == IS ) + Next(); + eTok2 = Peek(); + if( eTok2 < EQ || eTok2 > GE ) + Error( SbERR_SYNTAX ); + else Next(); + SbiExpression aCompare( this ); + aCompare.Gen(); + nTrueTarget = aGen.Gen( + _CASEIS, nTrueTarget, + sal::static_int_cast< UINT16 >( + SbxEQ + ( eTok2 - EQ ) ) ); + } + else + { // CASE expr | expr TO expr + SbiExpression aCase1( this ); + aCase1.Gen(); + if( Peek() == TO ) + { + // CASE a TO b + Next(); + SbiExpression aCase2( this ); + aCase2.Gen(); + nTrueTarget = aGen.Gen( _CASETO, nTrueTarget ); + } + else + // CASE a + nTrueTarget = aGen.Gen( _CASEIS, nTrueTarget, SbxEQ ); + + } + if( Peek() == COMMA ) Next(); + else TestEoln(), bDone = TRUE; + } + // Alle Cases abgearbeitet + if( !bElse ) + { + nNextTarget = aGen.Gen( _JUMP, nNextTarget ); + aGen.BackChain( nTrueTarget ); + } + // den Statement-Rumpf bauen + while( !bAbort ) + { + eTok = Peek(); + if( eTok == CASE || eTok == ENDSELECT ) + break; + if( !Parse() ) goto done; + eTok = Peek(); + if( eTok == CASE || eTok == ENDSELECT ) + break; + } + if( !bElse ) + nDoneTarget = aGen.Gen( _JUMP, nDoneTarget ); + } + else if( !IsEoln( eTok ) ) + break; + } +done: + if( eTok != ENDSELECT ) + Error( SbERR_EXPECTED, ENDSELECT ); + if( nNextTarget ) + aGen.BackChain( nNextTarget ); + aGen.BackChain( nDoneTarget ); + aGen.Gen( _ENDCASE ); +} + +// ON Error/Variable + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + +void SbiParser::On() +{ + SbiToken eTok = Peek(); + String aString = SbiTokenizer::Symbol(eTok); + if (aString.EqualsIgnoreCaseAscii("ERROR")) + //if (!aString.ICompare("ERROR")) + eTok = _ERROR_; // Error kommt als SYMBOL + if( eTok != _ERROR_ && eTok != LOCAL ) OnGoto(); + else + { + if( eTok == LOCAL ) Next(); + Next (); // Kein TestToken mehr, da es sonst einen Fehler gibt + + Next(); // Token nach Error holen + if( eCurTok == GOTO ) + { + // ON ERROR GOTO label|0 + Next(); + bool bError_ = false; + if( MayBeLabel() ) + { + if( eCurTok == NUMBER && !nVal ) + aGen.Gen( _STDERROR ); + else + { + UINT32 nOff = pProc->GetLabels().Reference( aSym ); + aGen.Gen( _ERRHDL, nOff ); + } + } + else if( eCurTok == MINUS ) + { + Next(); + if( eCurTok == NUMBER && nVal == 1 ) + aGen.Gen( _STDERROR ); + else + bError_ = true; + } + if( bError_ ) + Error( SbERR_LABEL_EXPECTED ); + } + else if( eCurTok == RESUME ) + { + TestToken( NEXT ); + aGen.Gen( _NOERROR ); + } + else Error( SbERR_EXPECTED, "GoTo/Resume" ); + } +} + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + +// RESUME [0]|NEXT|label + +void SbiParser::Resume() +{ + UINT32 nLbl; + + switch( Next() ) + { + case EOS: + case EOLN: + aGen.Gen( _RESUME, 0 ); + break; + case NEXT: + aGen.Gen( _RESUME, 1 ); + Next(); + break; + case NUMBER: + if( !nVal ) + { + aGen.Gen( _RESUME, 0 ); + break; + } // fall thru + case SYMBOL: + if( MayBeLabel() ) + { + nLbl = pProc->GetLabels().Reference( aSym ); + aGen.Gen( _RESUME, nLbl ); + Next(); + break; + } // fall thru + default: + Error( SbERR_LABEL_EXPECTED ); + } +} + diff --git a/basic/source/comp/makefile.mk b/basic/source/comp/makefile.mk new file mode 100644 index 000000000000..ef0e24ad288e --- /dev/null +++ b/basic/source/comp/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=comp + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +CXXFILES= \ + sbcomp.cxx \ + dim.cxx \ + exprtree.cxx \ + exprnode.cxx \ + exprgen.cxx \ + codegen.cxx \ + io.cxx \ + loops.cxx \ + parser.cxx \ + scanner.cxx \ + token.cxx \ + symtbl.cxx \ + buffer.cxx + +SLOFILES= \ + $(SLO)$/sbcomp.obj \ + $(SLO)$/dim.obj \ + $(SLO)$/exprtree.obj \ + $(SLO)$/exprnode.obj \ + $(SLO)$/exprgen.obj \ + $(SLO)$/codegen.obj \ + $(SLO)$/io.obj \ + $(SLO)$/loops.obj \ + $(SLO)$/parser.obj \ + $(SLO)$/scanner.obj \ + $(SLO)$/token.obj \ + $(SLO)$/symtbl.obj \ + $(SLO)$/buffer.obj + +EXCEPTIONSFILES= \ + $(SLO)$/parser.obj \ + $(SLO)$/exprtree.obj + +# --- Targets -------------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/basic/source/comp/parser.cxx b/basic/source/comp/parser.cxx new file mode 100644 index 000000000000..d4da9d0faeb1 --- /dev/null +++ b/basic/source/comp/parser.cxx @@ -0,0 +1,819 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: parser.cxx,v $ + * $Revision: 1.24 $ + * + * 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 <basic/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_VER +// '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; + 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() +{ + SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD; + SbiExpression aVar( this, SbSYMBOL, eMode ); + + bool bEQ = ( Peek() == EQ ); + if( !bEQ && bVBASupportOn && aVar.IsBracket() ) + Error( SbERR_EXPECTED, "=" ); + + 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() ) + { + if ( bVBASupportOn ) + aGen.Gen( _VBASETCLASS, pDef->GetTypeId() ); + else + 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 ); +} + diff --git a/basic/source/comp/sbcomp.cxx b/basic/source/comp/sbcomp.cxx new file mode 100644 index 000000000000..ca748f239cf8 --- /dev/null +++ b/basic/source/comp/sbcomp.cxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbcomp.cxx,v $ + * $Revision: 1.16 $ + * + * 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 <basic/sbx.hxx> +#include "sbcomp.hxx" +#include "image.hxx" + + +// For debugging only +// #define DBG_SAVE_DISASSEMBLY + +#ifdef DBG_SAVE_DISASSEMBLY +static bool dbg_bDisassemble = true; +#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> + +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() +{ + if( pImage ) + return TRUE; + StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent()); + if( !pBasic ) + return FALSE; + SbxBase::ResetError(); + // Aktuelles Modul! + SbModule* pOld = pCMOD; + pCMOD = this; + + SbiParser* pParser = new SbiParser( (StarBASIC*) GetParent(), this ); + while( pParser->Parse() ) {} + if( !pParser->GetErrors() ) + pParser->aGen.Save(); + delete pParser; + // fuer den Disassembler + if( pImage ) + pImage->aOUSource = aOUSource; + + pCMOD = pOld; + + // Beim Compilieren eines Moduls werden die Modul-globalen + // Variablen aller Module ungueltig + BOOL bRet = IsCompiled(); + if( bRet ) + { + pBasic->ClearAllModuleVars(); + // clear all method statics + for( USHORT i = 0; i < pMethods->Count(); i++ ) + { + SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) ); + if( p ) + p->ClearStatics(); + } + + // #i31510 Init other libs only if Basic isn't running + if( pINST == NULL ) + { + SbxObject* pParent_ = pBasic->GetParent(); + if( pParent_ ) + pBasic = PTR_CAST(StarBASIC,pParent_); + if( pBasic ) + pBasic->ClearAllModuleVars(); + } + } + +#ifdef DBG_SAVE_DISASSEMBLY + dbg_SaveDisassembly( this ); +#endif + + return bRet; +} + +/************************************************************************** +* +* Syntax-Highlighting +* +**************************************************************************/ + +void StarBASIC::Highlight( const String& rSrc, SbTextPortions& rList ) +{ + SbiTokenizer aTok( rSrc ); + aTok.Hilite( rList ); +} + diff --git a/basic/source/comp/scanner.cxx b/basic/source/comp/scanner.cxx new file mode 100644 index 000000000000..2cc496f9cb02 --- /dev/null +++ b/basic/source/comp/scanner.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scanner.cxx,v $ + * $Revision: 1.25 $ + * + * 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 "sbcomp.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> + +#include <runtime.hxx> + +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 = + bVBASupportOn = + 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++; +} + +// Falls sofort ein Doppelpunkt folgt, wird TRUE zurueckgeliefert. +// Wird von SbiTokenizer::MayBeLabel() verwendet, um einen Label zu erkennen + +BOOL SbiScanner::DoesColonFollow() +{ + if( pLine && *pLine == ':' ) + { + pLine++; nCol++; return TRUE; + } + else return FALSE; +} + +// 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 ); + } + // If VBA Interop then doen't eat the [] chars + if ( cSep == ']' && bVBASupportOn ) + aSym = aLine.copy( n - 1, nCol - n + 1); + else + 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;
+ bool bRes = NextSym();
+ if( bVBASupportOn && aSym.GetBuffer()[0] == '.' )
+ {
+ // object _
+ // .Method
+ // ^^^ <- spaces is legal in MSO VBA
+ OSL_TRACE("*** resetting bSpaces***");
+ bSpaces = FALSE;
+ }
+ return bRes;
+ } + 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; +} diff --git a/basic/source/comp/symtbl.cxx b/basic/source/comp/symtbl.cxx new file mode 100644 index 000000000000..2eb87dcdcc52 --- /dev/null +++ b/basic/source/comp/symtbl.cxx @@ -0,0 +1,537 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: symtbl.cxx,v $ + * $Revision: 1.20 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "sbcomp.hxx" +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +SV_IMPL_PTRARR(SbiStrings,String*) +SV_IMPL_PTRARR(SbiSymbols,SbiSymDef*) + +// Alle Symbolnamen werden im Stringpool des Symbol-Pools abgelegt, damit +// alle Symbole im gleichen Case verarbeitet werden. Beim Speichern des +// Code-Images wird der globale Stringpool mit den entsprechenden Sympools +// gespeichert. Der lokale Stringpool nimmt alle Symbole auf, die nicht +// ins Image wandern (Labels, Konstantennamen etc). + +/*************************************************************************** +|* +|* SbiStringPool +|* +***************************************************************************/ + +SbiStringPool::SbiStringPool( SbiParser* p ) +{ + pParser = p; +} + +SbiStringPool::~SbiStringPool() +{} + +// Suchen + +const String& SbiStringPool::Find( USHORT n ) const +{ + if( !n || n > aData.Count() ) + return aEmpty; + else + return *aData.GetObject( n-1 ); +} + +// Hinzufuegen eines Strings. Der String wird Case-Insensitiv +// verglichen. + +short SbiStringPool::Add( const String& rVal, BOOL bNoCase ) +{ + USHORT n = aData.Count(); + for( USHORT i = 0; i < n; i++ ) + { + String* p = aData.GetObject( i ); + if( ( bNoCase && p->Equals( rVal ) ) + || ( !bNoCase && p->EqualsIgnoreCaseAscii( rVal ) ) ) + return i+1; + } + const String* pNew = new String( rVal ); + aData.Insert( pNew, n++ ); + return (short) n; +} + +short SbiStringPool::Add( double n, SbxDataType t ) +{ + char buf[ 40 ]; + switch( t ) + { + case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", (short) n ); break; + case SbxLONG: snprintf( buf, sizeof(buf), "%ld", (long) n ); break; + case SbxSINGLE: snprintf( buf, sizeof(buf), "%.6g", (float) n ); break; + case SbxDOUBLE: snprintf( buf, sizeof(buf), "%.16g", n ); break; + default: break; + } + return Add( String::CreateFromAscii( buf ) ); +} + +/*************************************************************************** +|* +|* SbiSymPool +|* +***************************************************************************/ + +SbiSymPool::SbiSymPool( SbiStringPool& r, SbiSymScope s ) : rStrings( r ) +{ + pParser = r.GetParser(); + eScope = s; + pParent = NULL; + nCur = + nProcId = 0; +} + +SbiSymPool::~SbiSymPool() +{} + +// Inhalt loeschen + +void SbiSymPool::Clear() +{ + aData.DeleteAndDestroy( 0, aData.Count() ); +} + +SbiSymDef* SbiSymPool::First() +{ + nCur = (USHORT) -1; + return Next(); +} + +SbiSymDef* SbiSymPool::Next() +{ + if( ++nCur >= aData.Count() ) + return NULL; + else + return aData.GetObject( nCur ); +} + +// Hinzufuegen eines Symbols + +SbiSymDef* SbiSymPool::AddSym( const String& rName ) +{ + SbiSymDef* p = new SbiSymDef( rName ); + p->nPos = aData.Count(); + p->nId = rStrings.Add( rName ); + p->nProcId = nProcId; + p->pIn = this; + const SbiSymDef* q = p; + aData.Insert( q, q->nPos ); + return p; +} + +SbiProcDef* SbiSymPool::AddProc( const String& rName ) +{ + SbiProcDef* p = new SbiProcDef( pParser, rName ); + p->nPos = aData.Count(); + p->nId = rStrings.Add( rName ); + // Procs sind immer global + p->nProcId = 0; + p->pIn = this; + const SbiSymDef* q = p; + aData.Insert( q, q->nPos ); + return p; +} + +// Hinzufuegen einer extern aufgebauten Symboldefinition + +void SbiSymPool::Add( SbiSymDef* pDef ) +{ + if( pDef && pDef->pIn != this ) + { + if( pDef->pIn ) + { +#ifndef PRODUCT + // schon in einem anderen Pool drin! + pParser->Error( SbERR_INTERNAL_ERROR, "Dbl Pool" ); +#endif + return; + } + + pDef->nPos = aData.Count(); + if( !pDef->nId ) + { + // Bei statischen Variablen muss ein eindeutiger Name + // im Stringpool erzeugt werden (Form ProcName:VarName) + String aName( pDef->aName ); + if( pDef->IsStatic() ) + { + aName = pParser->aGblStrings.Find( nProcId ); + aName += ':'; + aName += pDef->aName; + } + pDef->nId = rStrings.Add( aName ); + } + // Procs sind immer global + if( !pDef->GetProcDef() ) + pDef->nProcId = nProcId; + pDef->pIn = this; + const SbiSymDef* q = pDef; + aData.Insert( q, q->nPos ); + } +} + +// Suchen eines Eintrags ueber den Namen. Es wird auch im Parent gesucht. + +SbiSymDef* SbiSymPool::Find( const String& rName ) const +{ + for( USHORT i = 0; i < aData.Count(); i++ ) + { + SbiSymDef* p = aData.GetObject( i ); + if( ( !p->nProcId || ( p->nProcId == nProcId ) ) + && ( p->aName.EqualsIgnoreCaseAscii( rName ) ) ) + return p; + } + if( pParent ) + return pParent->Find( rName ); + else + return NULL; +} + +// Suchen ueber ID-Nummer + +SbiSymDef* SbiSymPool::FindId( USHORT n ) const +{ + for( USHORT i = 0; i < aData.Count(); i++ ) + { + SbiSymDef* p = aData.GetObject( i ); + if( p->nId == n && ( !p->nProcId || ( p->nProcId == nProcId ) ) ) + return p; + } + if( pParent ) + return pParent->FindId( n ); + else + return NULL; +} + +// Suchen ueber Position (ab 0) + +SbiSymDef* SbiSymPool::Get( USHORT n ) const +{ + if( n >= aData.Count() ) + return NULL; + else + return aData.GetObject( n ); +} + +UINT32 SbiSymPool::Define( const String& rName ) +{ + SbiSymDef* p = Find( rName ); + if( p ) + { if( p->IsDefined() ) + pParser->Error( SbERR_LABEL_DEFINED, rName ); + } + else + p = AddSym( rName ); + return p->Define(); +} + +UINT32 SbiSymPool::Reference( const String& rName ) +{ + SbiSymDef* p = Find( rName ); + if( !p ) + p = AddSym( rName ); + //Sicherheitshalber + pParser->aGen.GenStmnt(); + return p->Reference(); +} + +// Alle offenen Referenzen anmaulen + +void SbiSymPool::CheckRefs() +{ + for( USHORT i = 0; i < aData.Count(); i++ ) + { + SbiSymDef* p = aData.GetObject( i ); + if( !p->IsDefined() ) + pParser->Error( SbERR_UNDEF_LABEL, p->GetName() ); + } +} + +/*************************************************************************** +|* +|* Symbol-Definitionen +|* +***************************************************************************/ + +SbiSymDef::SbiSymDef( const String& rName ) : aName( rName ) +{ + eType = SbxEMPTY; + nDims = 0; + nTypeId = 0; + nProcId = 0; + nId = 0; + nPos = 0; + nLen = 0; + nChain = 0; + bAs = + bNew = + bStatic = + bOpt = + bParamArray = + bByVal = + bChained = + bGlobal = FALSE; + pIn = + pPool = NULL; + nDefaultId = 0; +} + +SbiSymDef::~SbiSymDef() +{ + delete pPool; +} + +SbiProcDef* SbiSymDef::GetProcDef() +{ + return NULL; +} + +SbiConstDef* SbiSymDef::GetConstDef() +{ + return NULL; +} + +// Wenn der Name benoetigt wird, den aktuellen Namen +// aus dem Stringpool nehmen + +const String& SbiSymDef::GetName() +{ + if( pIn ) + aName = pIn->rStrings.Find( nId ); + return aName; +} + +// Eintragen eines Datentyps + +void SbiSymDef::SetType( SbxDataType t ) +{ + if( t == SbxVARIANT && pIn ) + { + sal_Unicode cu = aName.GetBuffer()[0]; + if( cu < 256 ) + { + char ch = (char)aName.GetBuffer()[0]; + if( ch == '_' ) ch = 'Z'; + int ch2 = toupper( ch ); + unsigned char c = (unsigned char)ch2; + if( c > 0 && c < 128 ) + t = pIn->pParser->eDefTypes[ ch2 - 'A' ]; + } + } + eType = t; +} + +// Aufbau einer Backchain, falls noch nicht definiert +// Es wird der Wert zurueckgeliefert, der als Operand gespeichert +// werden soll. + +UINT32 SbiSymDef::Reference() +{ + if( !bChained ) + { + UINT32 n = nChain; + nChain = pIn->pParser->aGen.GetOffset(); + return n; + } + else return nChain; +} + +// Definition eines Symbols. +// Hier wird der Backchain aufgeloest, falls vorhanden + +UINT32 SbiSymDef::Define() +{ + UINT32 n = pIn->pParser->aGen.GetPC(); + pIn->pParser->aGen.GenStmnt(); + if( nChain ) pIn->pParser->aGen.BackChain( nChain ); + nChain = n; + bChained = TRUE; + return nChain; +} + +// Eine Symboldefinition kann einen eigenen Pool haben. Dies ist +// der Fall bei Objekten und Prozeduren (lokale Variable) + +SbiSymPool& SbiSymDef::GetPool() +{ + if( !pPool ) + pPool = new SbiSymPool( pIn->pParser->aGblStrings, SbLOCAL ); // wird gedumpt + return *pPool; +} + +SbiSymScope SbiSymDef::GetScope() const +{ + return pIn ? pIn->GetScope() : SbLOCAL; +} + +//////////////////////////////////////////////////////////////////////////// + +// Die Prozedur-Definition hat drei Pools: +// 1) aParams: wird durch die Definition gefuellt. Enthaelt die Namen +// der Parameter, wie sie innerhalb des Rumpfes verwendet werden. +// Das erste Element ist der Returnwert. +// 2) pPool: saemtliche lokale Variable +// 3) aLabels: Labels + +SbiProcDef::SbiProcDef( SbiParser* pParser, const String& rName, + BOOL bProcDecl ) + : SbiSymDef( rName ) + , aParams( pParser->aGblStrings, SbPARAM ) // wird gedumpt + , aLabels( pParser->aLclStrings, SbLOCAL ) // wird nicht gedumpt + , mbProcDecl( bProcDecl ) +{ + aParams.SetParent( &pParser->aPublics ); + pPool = new SbiSymPool( pParser->aGblStrings, SbLOCAL ); // Locals + pPool->SetParent( &aParams ); + nLine1 = + nLine2 = 0; + mePropMode = PROPERTY_MODE_NONE; + bPublic = TRUE; + bCdecl = FALSE; + bStatic = FALSE; + // Fuer Returnwerte ist das erste Element der Parameterliste + // immer mit dem Namen und dem Typ der Proc definiert + aParams.AddSym( aName ); +} + +SbiProcDef::~SbiProcDef() +{} + +SbiProcDef* SbiProcDef::GetProcDef() +{ + return this; +} + +void SbiProcDef::SetType( SbxDataType t ) +{ + SbiSymDef::SetType( t ); + aParams.Get( 0 )->SetType( eType ); +} + +// Match mit einer Forward-Deklaration +// Falls der Match OK ist, wird pOld durch this im Pool ersetzt +// pOld wird immer geloescht! + +void SbiProcDef::Match( SbiProcDef* pOld ) +{ + SbiSymDef* po, *pn=NULL; + // Parameter 0 ist der Funktionsname + USHORT i; + for( i = 1; i < aParams.GetSize(); i++ ) + { + po = pOld->aParams.Get( i ); + pn = aParams.Get( i ); + // Kein Typabgleich; das wird beim Laufen erledigt + // aber ist sie evtl. mit zu wenigen Parametern aufgerufen + // worden? + if( !po && !pn->IsOptional() && !pn->IsParamArray() ) + break; + po = pOld->aParams.Next(); + } + // Wurden zu viele Parameter angegeben? + if( pn && i < aParams.GetSize() && pOld->pIn ) + { + // Die ganze Zeile markieren + pOld->pIn->GetParser()->SetCol1( 0 ); + pOld->pIn->GetParser()->Error( SbERR_BAD_DECLARATION, aName ); + } + if( !pIn && pOld->pIn ) + { + // Alten Eintrag durch neuen ersetzen + SbiSymDef** pData = (SbiSymDef**) pOld->pIn->aData.GetData(); + pData[ pOld->nPos ] = this; + nPos = pOld->nPos; + nId = pOld->nId; + pIn = pOld->pIn; + } + delete pOld; +} + +void SbiProcDef::setPropertyMode( PropertyMode ePropMode ) +{ + mePropMode = ePropMode; + if( mePropMode != PROPERTY_MODE_NONE ) + { + // Prop name = original scanned procedure name + maPropName = aName; + + // CompleteProcName includes "Property xxx " + // to avoid conflicts with other symbols + String aCompleteProcName; + aCompleteProcName.AppendAscii( "Property " ); + switch( mePropMode ) + { + case PROPERTY_MODE_GET: aCompleteProcName.AppendAscii( "Get " ); break; + case PROPERTY_MODE_LET: aCompleteProcName.AppendAscii( "Let " ); break; + case PROPERTY_MODE_SET: aCompleteProcName.AppendAscii( "Set " ); break; + case PROPERTY_MODE_NONE: + DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" ); + break; + } + aCompleteProcName += aName; + aName = aCompleteProcName; + } +} + + +////////////////////////////////////////////////////////////////////////// + +SbiConstDef::SbiConstDef( const String& rName ) + : SbiSymDef( rName ) +{ + nVal = 0; eType = SbxINTEGER; +} + +void SbiConstDef::Set( double n, SbxDataType t ) +{ + aVal.Erase(); nVal = n; eType = t; +} + +void SbiConstDef::Set( const String& n ) +{ + aVal = n; nVal = 0; eType = SbxSTRING; +} + +SbiConstDef::~SbiConstDef() +{} + +SbiConstDef* SbiConstDef::GetConstDef() +{ + return this; +} + diff --git a/basic/source/comp/token.cxx b/basic/source/comp/token.cxx new file mode 100644 index 000000000000..67ba6567dc73 --- /dev/null +++ b/basic/source/comp/token.cxx @@ -0,0 +1,701 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: token.cxx,v $ + * $Revision: 1.23 $ + * + * 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 <ctype.h> +#include "sbcomp.hxx" + +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" }, + { LIKE, "Like" }, + { 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() +{} + +// Wiederablage (Pushback) eines Tokens. (Bis zu 2 Tokens) + +void SbiTokenizer::Push( SbiToken t ) +{ + if( ePush != NIL ) + Error( SbERR_INTERNAL_ERROR, "PUSH" ); + else ePush = t; +} + +void SbiTokenizer::Error( SbError code, const char* pMsg ) +{ + aError = String::CreateFromAscii( pMsg ); + Error( code ); +} + +void SbiTokenizer::Error( SbError code, String aMsg ) +{ + aError = aMsg; + Error( code ); +} + +void SbiTokenizer::Error( SbError code, SbiToken tok ) +{ + aError = Symbol( tok ); + Error( code ); +} + +// 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; +} + +// Dies ist fuer die Decompilation. +// Zahlen und Symbole liefern einen Leerstring zurueck. + +const String& SbiTokenizer::Symbol( SbiToken t ) +{ + // Zeichen-Token? + if( t < FIRSTKWD ) + { + aSym = (char) t; + return aSym; + } + switch( t ) + { + case NEG : aSym = '-'; return aSym; + case EOS : aSym = String::CreateFromAscii( ":/CRLF" ); return aSym; + case EOLN : aSym = String::CreateFromAscii( "CRLF" ); return aSym; + default: break; + } + TokenTable* tp = pTokTable; + for( short i = 0; i < nToken; i++, tp++ ) + { + if( tp->t == t ) + { + aSym = String::CreateFromAscii( tp->s ); + return aSym; + } + } + const sal_Unicode *p = aSym.GetBuffer(); + if (*p <= ' ') aSym = String::CreateFromAscii( "???" ); + return aSym; +} + +// 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; +} + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + +// Kann das aktuell eingelesene Token ein Label sein? + +BOOL SbiTokenizer::MayBeLabel( BOOL bNeedsColon ) +{ + if( eCurTok == SYMBOL ) + return bNeedsColon ? DoesColonFollow() : TRUE; + else + return BOOL( eCurTok == NUMBER + && eScanType == SbxINTEGER + && nVal >= 0 ); +} + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + + +void SbiTokenizer::Hilite( SbTextPortions& rList ) +{ + bErrors = FALSE; + bUsedForHilite = TRUE; + SbiToken eLastTok = NIL; + for( ;; ) + { + Next(); + if( IsEof() ) + break; + SbTextPortion aRes; + aRes.nLine = nLine; + aRes.nStart = nCol1; + aRes.nEnd = nCol2; + switch( eCurTok ) + { + case REM: + aRes.eType = SB_COMMENT; break; + case SYMBOL: + aRes.eType = SB_SYMBOL; break; + case FIXSTRING: + aRes.eType = SB_STRING; break; + case NUMBER: + aRes.eType = SB_NUMBER; break; + default: + if( ( eCurTok >= FIRSTKWD && eCurTok <= LASTKWD ) + || (eCurTok >= _CDECL_ ) ) + aRes.eType = SB_KEYWORD; + else + aRes.eType = SB_PUNCTUATION; + } + // Die Folge xxx.Keyword sollte nicht als Kwd geflagt werden + if( aRes.eType == SB_KEYWORD + && ( eLastTok == DOT|| eLastTok == EXCLAM ) ) + aRes.eType = SB_SYMBOL; + if( eCurTok != EOLN && aRes.nStart <= aRes.nEnd ) + rList.Insert( aRes, rList.Count() ); + if( aRes.eType == SB_COMMENT ) + break; + eLastTok = eCurTok; + } + bUsedForHilite = FALSE; +} + diff --git a/basic/source/inc/buffer.hxx b/basic/source/inc/buffer.hxx new file mode 100644 index 000000000000..e3a83548dd11 --- /dev/null +++ b/basic/source/inc/buffer.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: buffer.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BUFFER_HXX +#define _BUFFER_HXX + +#include <tools/solar.h> +#include <tools/string.hxx> + +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(); + void Patch( UINT32, UINT32 ); // Patchen + void Chain( UINT32 ); // Back-Chain + void Align( INT32 ); // Alignment + BOOL Add( const void*, USHORT );// Element anfuegen + 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 diff --git a/basic/source/inc/codegen.hxx b/basic/source/inc/codegen.hxx new file mode 100644 index 000000000000..c7f568129180 --- /dev/null +++ b/basic/source/inc/codegen.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: codegen.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CODEGEN_HXX +#define _CODEGEN_HXX + +class SbiImage; +class SbiParser; +class SbModule; +#include "opcodes.hxx" +#include "buffer.hxx" + +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 diff --git a/basic/source/inc/collelem.hxx b/basic/source/inc/collelem.hxx new file mode 100644 index 000000000000..03242dbd8278 --- /dev/null +++ b/basic/source/inc/collelem.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: collelem.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SAMPLE_COLLELEM_HXX +#define _SAMPLE_COLLELEM_HXX + +#include <basic/sbxobj.hxx> + +// Das Sample-Element ist ein kleines Objekt, das die Properties +// Name und Value enth„lt sowie die Methode Say, die den bergebenen +// Text mit dem eigenen Namen verkoppelt. Der Name ist von aussen setzbar. +// Die Implementation arbeitet ausschliesslich mit dynamischen Elementen. + +class SampleElement : public SbxObject +{ + // Broadcaster Notification + virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ); +public: + SampleElement( const String& ); +}; + +#endif diff --git a/basic/source/inc/disas.hxx b/basic/source/inc/disas.hxx new file mode 100644 index 000000000000..37fde71f4c36 --- /dev/null +++ b/basic/source/inc/disas.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: disas.hxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DISAS_HXX +#define _DISAS_HXX + +#include "image.hxx" +#include "opcodes.hxx" +// find a place for this limit ( also used in +class SvStream; +#define MAX_LABELS 0x2000L +class SbiDisas { + const SbiImage& rImg; + SbModule* pMod; + char cLabels[ MAX_LABELS ]; // Bitvektor fuer Labels + UINT32 nOff; // aktuelle Position + UINT32 nPC; // Position des Opcodes + SbiOpcode eOp; // Opcode + UINT32 nOp1, nOp2; // Operanden + UINT32 nParts; // 1, 2 oder 3 + UINT32 nLine; // aktuelle Zeile + BOOL DisasLine( String& ); + BOOL Fetch(); // naechster Opcode +public: + SbiDisas( SbModule*, const SbiImage* ); + void Disas( SvStream& ); + void Disas( String& ); + // NICHT AUFRUFEN + void StrOp( String& ); + void Str2Op( String& ); + void ImmOp( String& ); + void OnOp( String& ); + void LblOp( String& ); + void ReturnOp( String& ); + void ResumeOp( String& ); + void PromptOp( String& ); + void CloseOp( String& ); + void CharOp( String& ); + void VarOp( String& ); + void VarDefOp( String& ); + void OffOp( String& ); + void TypeOp( String& ); + void CaseOp( String& ); + void StmntOp( String& ); + void StrmOp( String& ); +}; + +#endif diff --git a/basic/source/inc/dlgcont.hxx b/basic/source/inc/dlgcont.hxx new file mode 100644 index 000000000000..4917975e8ee2 --- /dev/null +++ b/basic/source/inc/dlgcont.hxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dlgcont.hxx,v $ + * $Revision: 1.9 $ + * + * 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 BASIC_DIALOGCONTAINER_HXX +#define BASIC_DIALOGCONTAINER_HXX + +#include "namecont.hxx" + +#ifndef _COM_SUN_STAR_AWT_XSTRINGRESOURCESUPPLIER_HPP_ +#include <com/sun/star/resource/XStringResourceSupplier.hpp> +#endif +#include "com/sun/star/resource/XStringResourcePersistence.hpp" + +#include <cppuhelper/implbase1.hxx> +#include <comphelper/uno3.hxx> + +namespace basic +{ + +//============================================================================ + +class SfxDialogLibraryContainer : public SfxLibraryContainer +{ + // Methods to distinguish between different library types + virtual SfxLibrary* SAL_CALL implCreateLibrary( const ::rtl::OUString& aName ); + virtual SfxLibrary* SAL_CALL implCreateLibraryLink + ( const ::rtl::OUString& aName, const ::rtl::OUString& aLibInfoFileURL, + const ::rtl::OUString& StorageURL, sal_Bool ReadOnly ); + virtual ::com::sun::star::uno::Any SAL_CALL createEmptyLibraryElement( void ); + virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const; + virtual void SAL_CALL writeLibraryElement + ( + ::com::sun::star::uno::Any aElement, + const ::rtl::OUString& aElementName, + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xOutput + ) + throw(::com::sun::star::uno::Exception); + + virtual ::com::sun::star::uno::Any SAL_CALL importLibraryElement + ( const ::rtl::OUString& aFile, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xElementStream ); + + virtual void SAL_CALL importFromOldStorage( const ::rtl::OUString& aFile ); + + virtual SfxLibraryContainer* createInstanceImpl( void ); + + virtual void onNewRootStorage(); + + virtual const sal_Char* SAL_CALL getInfoFileName() const; + virtual const sal_Char* SAL_CALL getOldInfoFileName() const; + virtual const sal_Char* SAL_CALL getLibElementFileExtension() const; + virtual const sal_Char* SAL_CALL getLibrariesDir() const; + +public: + SfxDialogLibraryContainer( void ); + SfxDialogLibraryContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ); + + // Methods XStorageBasedLibraryContainer + virtual void SAL_CALL storeLibrariesToStorage( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& RootStorage ) + throw (::com::sun::star::uno::RuntimeException); + + // Resource handling + ::com::sun::star::uno::Reference< ::com::sun::star::resource::XStringResourcePersistence > + implCreateStringResource( class SfxDialogLibrary* pDialog ); + + // Methods XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + + // Service + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(); + static ::rtl::OUString getImplementationName_static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create + ( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xServiceManager ) + throw( ::com::sun::star::uno::Exception ); +}; + +//============================================================================ + +typedef ::cppu::ImplHelper1 < ::com::sun::star::resource::XStringResourceSupplier + > SfxDialogLibrary_BASE; + +class SfxDialogLibrary :public SfxLibrary + ,public SfxDialogLibrary_BASE +{ + SfxDialogLibraryContainer* m_pParent; + ::com::sun::star::uno::Reference + < ::com::sun::star::resource::XStringResourcePersistence> m_xStringResourcePersistence; + ::rtl::OUString m_aName; + + // Provide modify state including resources + virtual sal_Bool isModified( void ); + virtual void storeResources( void ); + virtual void storeResourcesAsURL( const ::rtl::OUString& URL, const ::rtl::OUString& NewName ); + virtual void storeResourcesToURL( const ::rtl::OUString& URL, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ); + virtual void storeResourcesToStorage( const ::com::sun::star::uno::Reference + < ::com::sun::star::embed::XStorage >& xStorage ); + +public: + SfxDialogLibrary + ( + ModifiableHelper& _rModifiable, + const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xMSF, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xSFI, + SfxDialogLibraryContainer* pParent + ); + + SfxDialogLibrary + ( + ModifiableHelper& _rModifiable, + const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xMSF, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xSFI, + const ::rtl::OUString& aLibInfoFileURL, const ::rtl::OUString& aStorageURL, sal_Bool ReadOnly, + SfxDialogLibraryContainer* pParent + ); + + DECLARE_XINTERFACE() + DECLARE_XTYPEPROVIDER() + + // XStringResourceSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::resource::XStringResourceResolver > + SAL_CALL getStringResource( ) throw (::com::sun::star::uno::RuntimeException); + + ::rtl::OUString getName( void ) + { return m_aName; } + + ::com::sun::star::uno::Reference< ::com::sun::star::resource::XStringResourcePersistence > + getStringResourcePersistence( void ) + { + return m_xStringResourcePersistence; + } + + static bool containsValidDialog( const ::com::sun::star::uno::Any& aElement ); + +protected: + virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const; +}; + +} // namespace basic + +#endif + diff --git a/basic/source/inc/expr.hxx b/basic/source/inc/expr.hxx new file mode 100644 index 000000000000..b66006cb639a --- /dev/null +++ b/basic/source/inc/expr.hxx @@ -0,0 +1,260 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: expr.hxx,v $ + * $Revision: 1.15.40.1 $ + * + * 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 _EXPR_HXX +#define _EXPR_HXX + +#include "opcodes.hxx" +#include "token.hxx" + +class SbiExprNode; +class SbiExpression; +class SbiExprList; +class SbiDimList; +class SbiParameters; +class SbiParser; +class SbiCodeGen; +class SbiSymDef; +class SbiProcDef; + + +#include <vector> +typedef ::std::vector<SbiExprList*> SbiExprListVector; + +struct SbVar { // Variablen-Element: + SbiExprNode* pNext; // Weiteres Element (bei Strukturen) + SbiSymDef* pDef; // Symboldefinition + SbiExprList* pPar; // optionale Parameter (wird geloescht) + SbiExprListVector* pvMorePar; // Array of arrays foo(pPar)(avMorePar[0])(avMorePar[1])... +}; + +enum SbiExprType { // Expression-Typen: + SbSTDEXPR, // normaler Ausdruck + SbLVALUE, // beliebiger lValue + SbSYMBOL, // beliebiges zusammengesetztes Symbol + SbOPERAND // Variable/Funktion +}; + +enum SbiExprMode { // Expression context: + EXPRMODE_STANDARD, // default + EXPRMODE_STANDALONE, // a param1, param2 OR a( param1, param2 ) = 42 + EXPRMODE_LPAREN_PENDING, // start of parameter list with bracket, special handling + EXPRMODE_LPAREN_NOT_NEEDED, // pending LPAREN has not been used + EXPRMODE_ARRAY_OR_OBJECT, // '=' or '(' or '.' found after ')' on ParenLevel 0, stopping + // expression, assuming array syntax a(...)[(...)] = ? + // or a(...).b(...) + EXPRMODE_EMPTY_PAREN // It turned out that the paren don't contain anything: a() +}; + +enum SbiNodeType { + SbxNUMVAL, // nVal = Wert + SbxSTRVAL, // aStrVal = Wert, before #i59791/#i45570: nStringId = Wert + SbxVARVAL, // aVar = Wert + SbxTYPEOF, // TypeOf ObjExpr Is Type + SbxNODE, // Node + SbxDUMMY +}; + +enum RecursiveMode +{ + UNDEFINED, + FORCE_CALL, + PREVENT_CALL +}; + +class SbiExprNode { // Operatoren (und Operanden) + friend class SbiExpression; + friend class SbiConstExpression; + union { + USHORT nTypeStrId; // gepoolter String-ID, #i59791/#i45570 Now only for TypeOf + double nVal; // numerischer Wert + SbVar aVar; // oder Variable + }; + String aStrVal; // #i59791/#i45570 Store string directly + SbiExprNode* pLeft; // linker Zweig + SbiExprNode* pRight; // rechter Zweig (NULL bei unaeren Ops) + SbiExprNode* pWithParent; // Knoten, dessen Member this per with ist + SbiCodeGen* pGen; // Code-Generator + SbiNodeType eNodeType; // Art des Nodes + SbxDataType eType; // aktueller Datentyp + SbiToken eTok; // Token des Operators + BOOL bComposite; // TRUE: Zusammengesetzter Ausdruck + BOOL bError; // TRUE: Fehlerhaft + void FoldConstants(); // Constant Folding durchfuehren + void CollectBits(); // Umwandeln von Zahlen in Strings + BOOL IsOperand() // TRUE, wenn Operand + { return BOOL( eNodeType != SbxNODE && eNodeType != SbxTYPEOF ); } + BOOL IsTypeOf() + { return BOOL( eNodeType == SbxTYPEOF ); } + BOOL IsNumber(); // TRUE bei Zahlen + BOOL IsString(); // TRUE bei Strings + BOOL IsLvalue(); // TRUE, falls als Lvalue verwendbar + void GenElement( SbiOpcode ); // Element + void BaseInit( SbiParser* p ); // Hilfsfunktion fuer Ctor, AB 17.12.95 +public: + SbiExprNode( void ); + SbiExprNode( SbiParser*, double, SbxDataType ); + SbiExprNode( SbiParser*, const String& ); + SbiExprNode( SbiParser*, const SbiSymDef&, SbxDataType, SbiExprList* = NULL ); + SbiExprNode( SbiParser*, SbiExprNode*, SbiToken, SbiExprNode* ); + SbiExprNode( SbiParser*, SbiExprNode*, USHORT ); // #120061 TypeOf + virtual ~SbiExprNode(); + + BOOL IsValid() { return BOOL( !bError ); } + BOOL IsConstant() // TRUE bei konstantem Operanden + { return BOOL( eNodeType == SbxSTRVAL || eNodeType == SbxNUMVAL ); } + BOOL IsIntConst(); // TRUE bei Integer-Konstanten + BOOL IsVariable(); // TRUE, wenn Variable + + SbiExprNode* GetWithParent() { return pWithParent; } + void SetWithParent( SbiExprNode* p ) { pWithParent = p; } + + SbxDataType GetType() { return eType; } + void SetType( SbxDataType eTp ) { eType = eTp; } + SbiNodeType GetNodeType() { return eNodeType; } + SbiSymDef* GetVar(); // Variable (falls vorhanden) + SbiSymDef* GetRealVar(); // letzte Variable in x.y.z + SbiExprNode* GetRealNode(); // letzter Knoten in x.y.z + short GetDepth(); // Tiefe eines Baumes berechnen + const String& GetString() { return aStrVal; } + short GetNumber() { return (short)nVal; }
+ SbiExprList* GetParameters() { return aVar.pPar; } + SbiExprListVector* GetMoreParameters() { return aVar.pvMorePar; } + + void Optimize(); // Baumabgleich + + void Gen( RecursiveMode eRecMode = UNDEFINED ); // Ausgabe eines Nodes +}; + +class SbiExpression { // der Ausdruck: + friend class SbiExprList; + friend class SbiParameters; + friend class SbiDimList; +protected: + String aArgName; // Name fuer bananntes Argument + SbiParser* pParser; // fuer Fehlermeldungen, Parsing + SbiExpression* pNext; // Link bei Parameterlisten + SbiExprNode* pExpr; // Der Expression-Baum + SbiExprType eCurExpr; // Art des Ausdrucks + SbiExprMode m_eMode; // Expression context + BOOL bBased; // TRUE: einfacher DIM-Teil (+BASE) + BOOL bError; // TRUE: Fehler + BOOL bByVal; // TRUE: ByVal-Parameter + BOOL bBracket; // TRUE: Parameter list with brackets + USHORT nParenLevel; + SbiExprNode* Term(); + SbiExprNode* ObjTerm( SbiSymDef& ); + SbiExprNode* Operand(); + SbiExprNode* Unary(); + SbiExprNode* Exp(); + SbiExprNode* MulDiv(); + SbiExprNode* IntDiv(); + SbiExprNode* Mod(); + SbiExprNode* AddSub(); + SbiExprNode* Cat(); + SbiExprNode* Like(); + SbiExprNode* Comp(); + SbiExprNode* Boolean(); +public: + SbiExpression( SbiParser*, SbiExprType = SbSTDEXPR, SbiExprMode eMode = EXPRMODE_STANDARD ); // Parsender Ctor + SbiExpression( SbiParser*, const String& ); + SbiExpression( SbiParser*, double, SbxDataType = SbxDOUBLE ); + SbiExpression( SbiParser*, const SbiSymDef&, SbiExprList* = NULL ); + SbiExpression( SbiParser*, SbiToken ); // Spezial-Expr mit Spezial-Tokens + ~SbiExpression(); + String& GetName() { return aArgName; } + void SetBased() { bBased = TRUE; } + BOOL IsBased() { return bBased; } + void SetByVal() { bByVal = TRUE; } + BOOL IsByVal() { return bByVal; } + BOOL IsBracket() { return bBracket; } + BOOL IsValid() { return pExpr->IsValid(); } + BOOL IsConstant() { return pExpr->IsConstant(); } + BOOL IsVariable() { return pExpr->IsVariable(); } + BOOL IsLvalue() { return pExpr->IsLvalue(); } + BOOL IsIntConstant() { return pExpr->IsIntConst(); } + const String& GetString() { return pExpr->GetString(); } + SbiSymDef* GetVar() { return pExpr->GetVar(); } + SbiSymDef* GetRealVar() { return pExpr->GetRealVar(); } + SbiExprNode* GetExprNode() { return pExpr; } + SbxDataType GetType() { return pExpr->GetType(); } + void SetType( SbxDataType eType){ pExpr->eType = eType; } + void Gen( RecursiveMode eRecMode = UNDEFINED ); // Ausgabe eines Nodes +}; + +class SbiConstExpression : public SbiExpression { + double nVal; + String aVal; + SbxDataType eType; +public: // numerische Konstante + SbiConstExpression( SbiParser* ); + SbxDataType GetType() { return eType; } + const String& GetString() { return aVal; } + double GetValue() { return nVal; } + short GetShortValue(); +}; + +class SbiExprList { // Basisklasse fuer Parameter und Dims +protected: + SbiParser* pParser; // Parser + SbiExpression* pFirst; // Expressions + SbiProcDef* pProc; // DECLARE-Funktion (Parameter-Anpassung) + short nExpr; // Anzahl Expressions + short nDim; // Anzahl Dimensionen + BOOL bError; // TRUE: Fehler + BOOL bBracket; // TRUE: Klammern +public: + SbiExprList( SbiParser* ); + virtual ~SbiExprList(); + BOOL IsBracket() { return bBracket; } + BOOL IsValid() { return BOOL( !bError ); } + short GetSize() { return nExpr; } + short GetDims() { return nDim; } + SbiExpression* Get( short ); + BOOL Test( const SbiProcDef& ); // Parameter-Checks + void Gen(); // Code-Erzeugung + // Setzen einer Funktionsdefinition zum Abgleich der Parameter + void SetProc( SbiProcDef* p ) { pProc = p; } + void addExpression( SbiExpression* pExpr ); +}; + +class SbiParameters : public SbiExprList { +public: + SbiParameters( SbiParser*, BOOL bConst = FALSE, BOOL bPar = TRUE);// parsender Ctor +}; + +class SbiDimList : public SbiExprList { + BOOL bConst; // TRUE: Alles sind Integer-Konstanten +public: + SbiDimList( SbiParser* ); // Parsender Ctor + BOOL IsConstant() { return bConst; } +}; + +#endif diff --git a/basic/source/inc/filefmt.hxx b/basic/source/inc/filefmt.hxx new file mode 100644 index 000000000000..4a5593cb7506 --- /dev/null +++ b/basic/source/inc/filefmt.hxx @@ -0,0 +1,181 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: filefmt.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SB_FILEFMT_HXX +#define _SB_FILEFMT_HXX + +#include <tools/solar.h> + +class SvStream; + +// 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 diff --git a/basic/source/inc/image.hxx b/basic/source/inc/image.hxx new file mode 100644 index 000000000000..d08bb5e859ab --- /dev/null +++ b/basic/source/inc/image.hxx @@ -0,0 +1,114 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: image.hxx,v $ + * $Revision: 1.11 $ + * + * 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" +#ifndef _RTL_USTRING_HXX +#include <rtl/ustring.hxx> +#endif +#include <filefmt.hxx> + +// Diese Klasse liest das vom Compiler erzeugte Image ein und verwaltet +// den Zugriff auf die einzelnen Elemente. + +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 + void AddString( const String& );// String zufuegen + void AddCode( char*, UINT32 ); // Codeblock dazu + void AddType(SbxObject *); // User-Type mit aufnehmen + void AddEnum(SbxObject *); // Register enum type + +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 Load( SvStream& ); + 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; } + String GetString( short nId ) const; + //const char* GetString( short nId ) const; + 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 diff --git a/basic/source/inc/iosys.hxx b/basic/source/inc/iosys.hxx new file mode 100644 index 000000000000..d4712dbd048b --- /dev/null +++ b/basic/source/inc/iosys.hxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: iosys.hxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBIOSYS_HXX +#define _SBIOSYS_HXX + +#include <tools/stream.hxx> +#ifndef _SBERRORS_HXX +#include <basic/sberrors.hxx> +#endif + +class SvStream; + +// Zur Zeit sind globale Dateien (Kanalnummern 256 bis 511) +// nicht implementiert. + +#define CHANNELS 256 +#define CONSOLE 0 + +#define SBSTRM_INPUT 0x0001 // Input +#define SBSTRM_OUTPUT 0x0002 // Output +#define SBSTRM_RANDOM 0x0004 // Random +#define SBSTRM_APPEND 0x0008 // Append +#define SBSTRM_BINARY 0x0010 // Binary + +class SbiStream { + SvStream* pStrm; // der Stream + ULONG nExpandOnWriteTo; // bei Schreibzugriff, den Stream + // bis zu dieser Groesse aufblasen + ByteString aLine; // aktuelle Zeile + ULONG nLine; // aktuelle Zeilennummer + short nLen; // Pufferlaenge + short nMode; // Bits: + short nChan; // aktueller Kanal + SbError nError; // letzter Fehlercode + void MapError(); // Fehlercode mappen + +public: + SbiStream(); + ~SbiStream(); + SbError Open( short, const ByteString&, short, short, short ); + SbError Close(); + SbError Read( ByteString&, USHORT = 0, bool bForceReadingPerByte=false ); + SbError Read( char& ); + SbError Write( const ByteString&, USHORT = 0 ); + + bool IsText() const { return (nMode & SBSTRM_BINARY) == 0; } + bool IsRandom() const { return (nMode & SBSTRM_RANDOM) != 0; } + bool IsBinary() const { return (nMode & SBSTRM_BINARY) != 0; } + bool IsSeq() const { return (nMode & SBSTRM_RANDOM) == 0; } + bool IsAppend() const { return (nMode & SBSTRM_APPEND) != 0; } + short GetBlockLen() const { return nLen; } + short GetMode() const { return nMode; } + ULONG GetLine() const { return nLine; } + void SetExpandOnWriteTo( ULONG n ) { nExpandOnWriteTo = n; } + void ExpandFile(); + SvStream* GetStrm() { return pStrm; } +}; + +class SbiIoSystem { + SbiStream* pChan[ CHANNELS ]; + ByteString aPrompt; // Input-Prompt + ByteString aIn, aOut; // Console-Buffer + short nChan; // aktueller Kanal + SbError nError; // letzter Fehlercode + void ReadCon( ByteString& ); + void WriteCon( const ByteString& ); +public: + SbiIoSystem(); + ~SbiIoSystem(); + SbError GetError(); + void Shutdown(); + void SetPrompt( const ByteString& r ) { aPrompt = r; } + void SetChannel( short n ) { nChan = n; } + short GetChannel() const { return nChan;} + void ResetChannel() { nChan = 0; } + void Open( short, const ByteString&, short, short, short ); + void Close(); + void Read( ByteString&, short = 0 ); + char Read(); + void Write( const ByteString&, short = 0 ); + short NextChannel(); + // 0 == bad channel or no SvStream (nChannel=0..CHANNELS-1) + SbiStream* GetStream( short nChannel ) const; + void CloseAll(); // JSM +}; + +#endif + diff --git a/basic/source/inc/namecont.hxx b/basic/source/inc/namecont.hxx new file mode 100644 index 000000000000..02a41a6fc2c8 --- /dev/null +++ b/basic/source/inc/namecont.hxx @@ -0,0 +1,739 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: namecont.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef BASIC_NAMECONTAINER_HXX +#define BASIC_NAMECONTAINER_HXX + +#include <hash_map> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp> +#include <com/sun/star/script/XLibraryContainerPassword.hpp> +#include <com/sun/star/script/XLibraryContainerExport.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/util/XStringSubstitution.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <osl/mutex.hxx> +#include <unotools/eventlisteneradapter.hxx> +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/basemutex.hxx> +#include <sot/storage.hxx> +#include <xmlscript/xmllib_imexp.hxx> +#include <com/sun/star/deployment/XPackage.hpp> + +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/compbase6.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +class BasicManager; + +namespace basic +{ + +typedef ::cppu::WeakComponentImplHelper6< + ::com::sun::star::lang::XInitialization, + ::com::sun::star::script::XStorageBasedLibraryContainer, + ::com::sun::star::script::XLibraryContainerPassword, + ::com::sun::star::script::XLibraryContainerExport, + ::com::sun::star::container::XContainer, + ::com::sun::star::lang::XServiceInfo > LibraryContainerHelper; + +typedef ::cppu::WeakImplHelper2< ::com::sun::star::container::XNameContainer, + ::com::sun::star::container::XContainer > NameContainerHelper; + + +struct hashName_Impl +{ + size_t operator()(const ::rtl::OUString Str) const + { + return (size_t)Str.hashCode(); + } +}; + +struct eqName_Impl +{ + sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const + { + return ( Str1 == Str2 ); + } +}; + +typedef std::hash_map +< + ::rtl::OUString, + sal_Int32, + hashName_Impl, + eqName_Impl +> +NameContainerNameMap; + + +//============================================================================ + +class NameContainer : public ::cppu::BaseMutex, public NameContainerHelper +{ + NameContainerNameMap mHashMap; + ::com::sun::star::uno::Sequence< ::rtl::OUString > mNames; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > mValues; + sal_Int32 mnElementCount; + + ::com::sun::star::uno::Type mType; + ::com::sun::star::uno::XInterface* mpxEventSource; + + ::cppu::OInterfaceContainerHelper maListenerContainer; + +public: + NameContainer( const ::com::sun::star::uno::Type& rType ) + : mnElementCount( 0 ) + , mType( rType ) + , mpxEventSource( NULL ) + , maListenerContainer( m_aMutex ) + {} + + void setEventSource( ::com::sun::star::uno::XInterface* pxEventSource ) + { mpxEventSource = pxEventSource; } + + // Methods XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) + throw(::com::sun::star::uno::RuntimeException); + + // Methods XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::uno::RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::ElementExistException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeByName( const ::rtl::OUString& Name ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // Methods XContainer + virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XContainerListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XContainerListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); +}; + +//============================================================================ + +class SfxLibrary; + +enum InitMode +{ + DEFAULT, + CONTAINER_INIT_FILE, + LIBRARY_INIT_FILE, + OFFICE_DOCUMENT, + OLD_BASIC_STORAGE +}; + +class ModifiableHelper +{ +private: + ::cppu::OInterfaceContainerHelper m_aModifyListeners; + ::cppu::OWeakObject& m_rEventSource; + sal_Bool mbModified; + +public: + ModifiableHelper( ::cppu::OWeakObject& _rEventSource, ::osl::Mutex& _rMutex ) + :m_aModifyListeners( _rMutex ) + ,m_rEventSource( _rEventSource ) + ,mbModified( sal_False ) + { + } + + inline sal_Bool isModified() const { return mbModified; } + void setModified( sal_Bool _bModified ); + + inline void addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& _rxListener ) + { + m_aModifyListeners.addInterface( _rxListener ); + } + + inline void removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& _rxListener ) + { + m_aModifyListeners.removeInterface( _rxListener ); + } +}; + +class SfxLibraryContainer :public LibraryContainerHelper + ,public ::utl::OEventListenerAdapter +{ +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > mxSFI; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XMacroExpander > mxMacroExpander; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XStringSubstitution > mxStringSubstitution; + ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XModel > mxOwnerDocument; + + ::osl::Mutex maMutex; + ModifiableHelper maModifiable; + + NameContainer maNameContainer; + sal_Bool mbOldInfoFormat; + sal_Bool mbOasis2OOoFormat; + + ::rtl::OUString maInitialDocumentURL; + ::rtl::OUString maInfoFileName; + ::rtl::OUString maOldInfoFileName; + ::rtl::OUString maLibElementFileExtension; + ::rtl::OUString maLibraryPath; + ::rtl::OUString maLibrariesDir; + + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > mxStorage; + BasicManager* mpBasMgr; + sal_Bool mbOwnBasMgr; + + InitMode meInitMode; + + void implStoreLibrary( SfxLibrary* pLib, + const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ); + + // New variant for library export + void implStoreLibrary( SfxLibrary* pLib, + const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xToUseSFI, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ); + + void implStoreLibraryIndexFile( SfxLibrary* pLib, const ::xmlscript::LibDescriptor& rLib, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ); + + // New variant for library export + void implStoreLibraryIndexFile( SfxLibrary* pLib, const ::xmlscript::LibDescriptor& rLib, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xToUseSFI ); + + sal_Bool implLoadLibraryIndexFile( SfxLibrary* pLib, + ::xmlscript::LibDescriptor& rLib, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + const ::rtl::OUString& aIndexFileName ); + + void implImportLibDescriptor( SfxLibrary* pLib, ::xmlscript::LibDescriptor& rLib ); + + // Methods to distinguish between deffirent library types + virtual SfxLibrary* SAL_CALL implCreateLibrary( const ::rtl::OUString& aName ) = 0; + virtual SfxLibrary* SAL_CALL implCreateLibraryLink + ( const ::rtl::OUString& aName, const ::rtl::OUString& aLibInfoFileURL, + const ::rtl::OUString& StorageURL, sal_Bool ReadOnly ) = 0; + virtual ::com::sun::star::uno::Any SAL_CALL createEmptyLibraryElement( void ) = 0; + virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const = 0; + virtual void SAL_CALL writeLibraryElement + ( + ::com::sun::star::uno::Any aElement, + const ::rtl::OUString& aElementName, + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xOutput + ) + throw(::com::sun::star::uno::Exception) = 0; + + virtual ::com::sun::star::uno::Any SAL_CALL importLibraryElement + ( const ::rtl::OUString& aFile, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xElementStream ) = 0; + virtual void SAL_CALL importFromOldStorage( const ::rtl::OUString& aFile ) = 0; + + // Password encryption + virtual sal_Bool implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ); + + // New variant for library export + virtual sal_Bool implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xToUseSFI, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ); + + virtual sal_Bool implLoadPasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& Name, + sal_Bool bVerifyPasswordOnly=false ) + throw(::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + virtual void onNewRootStorage() = 0; + + + // #56666, Creates another library container + // instance of the same derived class + virtual SfxLibraryContainer* createInstanceImpl( void ) = 0; + + + // Interface to get the BasicManager (Hack for password implementation) + BasicManager* getBasicManager( void ); + ::rtl::OUString createAppLibraryFolder( SfxLibrary* pLib, const ::rtl::OUString& aName ); + + sal_Bool init( const ::rtl::OUString& rInitialDocumentURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxInitialStorage ); + + virtual const sal_Char* SAL_CALL getInfoFileName() const = 0; + virtual const sal_Char* SAL_CALL getOldInfoFileName() const = 0; + virtual const sal_Char* SAL_CALL getLibElementFileExtension() const = 0; + virtual const sal_Char* SAL_CALL getLibrariesDir() const = 0; + + // Handle maLibInfoFileURL and maStorageURL correctly + void checkStorageURL + ( + const ::rtl::OUString& aSourceURL, + ::rtl::OUString& aLibInfoFileURL, + ::rtl::OUString& aStorageURL, + ::rtl::OUString& aUnexpandedStorageURL + ); + ::rtl::OUString expand_url( const ::rtl::OUString& url ) + throw(::com::sun::star::uno::RuntimeException); + + SfxLibrary* getImplLib( const String& rLibraryName ); + + void storeLibraries_Impl( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + sal_Bool bComplete ); + + void SAL_CALL initializeFromDocumentURL( const ::rtl::OUString& _rInitialDocumentURL ); + void SAL_CALL initializeFromDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XStorageBasedDocument >& _rxDocument ); + + // OEventListenerAdapter + virtual void _disposing( const ::com::sun::star::lang::EventObject& _rSource ); + + // OComponentHelper + virtual void SAL_CALL disposing(); + +private: + sal_Bool init_Impl( const ::rtl::OUString& rInitialDocumentURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxInitialStorage ); + void implScanExtensions( void ); + +public: + SfxLibraryContainer( void ); + ~SfxLibraryContainer(); + + + // Interface to set the BasicManager (Hack for password implementation) + void setBasicManager( BasicManager* pBasMgr ) + { + mpBasMgr = pBasMgr; + } + + void enterMethod(); + void leaveMethod(); + bool isDisposed() const { return rBHelper.bInDispose || rBHelper.bDisposed; } + void checkDisposed() const; + + // Methods XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() + throw(::com::sun::star::uno::RuntimeException); + + // Methods XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::uno::RuntimeException); + + // Members XStorageBasedLibraryContainer + virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > SAL_CALL getRootStorage() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRootStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rootstorage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL storeLibrariesToStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& RootStorage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // Methods XModifiable (base of XPersistentLibraryContainer) + virtual ::sal_Bool SAL_CALL isModified( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setModified( ::sal_Bool bModified ) throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // Methods XPersistentLibraryContainer (base of XStorageBasedLibraryContainer) + virtual ::com::sun::star::uno::Any SAL_CALL getRootLocation() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getContainerLocationName() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL storeLibraries( ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // Methods XLibraryContainer2 (base of XPersistentLibraryContainer) + virtual sal_Bool SAL_CALL isLibraryLink( const ::rtl::OUString& Name ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLibraryLinkURL( const ::rtl::OUString& Name ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLibraryReadOnly( const ::rtl::OUString& Name ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLibraryReadOnly( const ::rtl::OUString& Name, sal_Bool bReadOnly ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL renameLibrary( const ::rtl::OUString& Name, const ::rtl::OUString& NewName ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::container::ElementExistException, + ::com::sun::star::uno::RuntimeException); + + // Methods XLibraryContainer (base of XLibraryContainer2) + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > SAL_CALL + createLibrary( const ::rtl::OUString& Name ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::ElementExistException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL createLibraryLink + ( const ::rtl::OUString& Name, const ::rtl::OUString& StorageURL, sal_Bool ReadOnly ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::ElementExistException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeLibrary( const ::rtl::OUString& Name ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLibraryLoaded( const ::rtl::OUString& Name ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL loadLibrary( const ::rtl::OUString& Name ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // Methods XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + + // Methods XLibraryContainerPassword + virtual sal_Bool SAL_CALL isLibraryPasswordProtected( const ::rtl::OUString& Name ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLibraryPasswordVerified( const ::rtl::OUString& Name ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL verifyLibraryPassword( const ::rtl::OUString& Name, const ::rtl::OUString& Password ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL changeLibraryPassword( const ::rtl::OUString& Name, + const ::rtl::OUString& OldPassword, const ::rtl::OUString& NewPassword ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + + // Methods XContainer + virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XContainerListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XContainerListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + // Methods XLibraryContainerExport + virtual void SAL_CALL exportLibrary( const ::rtl::OUString& Name, const ::rtl::OUString& URL, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ) + throw (::com::sun::star::uno::Exception, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + + // Methods XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException) = 0; + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException) = 0; +}; + +class LibraryContainerMethodGuard +{ +private: + SfxLibraryContainer& m_rContainer; +public: + LibraryContainerMethodGuard( SfxLibraryContainer& _rContainer ) + :m_rContainer( _rContainer ) + { + m_rContainer.enterMethod(); + } + + ~LibraryContainerMethodGuard() + { + m_rContainer.leaveMethod(); + } +}; + + +//============================================================================ + +class SfxLibrary + : public ::com::sun::star::container::XNameContainer + , public ::com::sun::star::container::XContainer + , public ::cppu::BaseMutex + , public ::cppu::OComponentHelper +{ + friend class SfxLibraryContainer; + friend class SfxDialogLibraryContainer; + friend class SfxScriptLibraryContainer; + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > mxSFI; + + ModifiableHelper& mrModifiable; + NameContainer maNameContainer; + + sal_Bool mbLoaded; + sal_Bool mbIsModified; + sal_Bool mbInitialised; + +private: + + ::rtl::OUString maLibElementFileExtension; + ::rtl::OUString maLibInfoFileURL; + ::rtl::OUString maStorageURL; + ::rtl::OUString maUnexpandedStorageURL; + sal_Bool mbLink; + sal_Bool mbReadOnly; + sal_Bool mbReadOnlyLink; + sal_Bool mbPreload; + + sal_Bool mbPasswordProtected; + sal_Bool mbPasswordVerified; + sal_Bool mbDoc50Password; + ::rtl::OUString maPassword; + + sal_Bool mbSharedIndexFile; + sal_Bool mbExtension; + + // Additional functionality for localisation + // Provide modify state including resources + virtual sal_Bool isModified( void ) = 0; + virtual void storeResources( void ) = 0; + virtual void storeResourcesAsURL( const ::rtl::OUString& URL, const ::rtl::OUString& NewName ) = 0; + virtual void storeResourcesToURL( const ::rtl::OUString& URL, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ) = 0; + virtual void storeResourcesToStorage( const ::com::sun::star::uno::Reference + < ::com::sun::star::embed::XStorage >& xStorage ) = 0; + +protected: + inline sal_Bool implIsModified() const { return mbIsModified; } + void implSetModified( sal_Bool _bIsModified ); + +private: + /** checks whether the lib is readonly, or a readonly link, throws an IllegalArgumentException if so + */ + void impl_checkReadOnly(); + /** checks whether the library is loaded, throws a LibraryNotLoadedException (wrapped in a WrappedTargetException), + if not. + */ + void impl_checkLoaded(); + +private: + void impl_removeWithoutChecks( const ::rtl::OUString& _rElementName ); + +public: + SfxLibrary( + ModifiableHelper& _rModifiable, + const ::com::sun::star::uno::Type& aType, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xMSF, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xSFI + ); + SfxLibrary( + ModifiableHelper& _rModifiable, + const ::com::sun::star::uno::Type& aType, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xMSF, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xSFI, + const ::rtl::OUString& aLibInfoFileURL, + const ::rtl::OUString& + aStorageURL, + sal_Bool ReadOnly + ); + + // Methods XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& rType ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire() throw() { OComponentHelper::acquire(); } + virtual void SAL_CALL release() throw() { OComponentHelper::release(); } + + // Methods XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) + throw(::com::sun::star::uno::RuntimeException); + + // Methods XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::uno::RuntimeException); + + // Methods XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // Methods XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::ElementExistException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeByName( const ::rtl::OUString& Name ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // XTypeProvider + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) + throw( ::com::sun::star::uno::RuntimeException ); + ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) + throw( ::com::sun::star::uno::RuntimeException ); + + // Methods XContainer + virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XContainerListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XContainerListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + +public: + struct LibraryContainerAccess { friend class SfxLibraryContainer; private: LibraryContainerAccess() { } }; + void removeElementWithoutChecks( const ::rtl::OUString& _rElementName, LibraryContainerAccess ) + { + impl_removeWithoutChecks( _rElementName ); + } + +protected: + virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const = 0; +}; + +//=================================================================== +class ScriptSubPackageIterator +{ + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > m_xMainPackage; + + bool m_bIsValid; + bool m_bIsBundle; + + com::sun::star::uno::Sequence< com::sun::star::uno::Reference + < com::sun::star::deployment::XPackage > > m_aSubPkgSeq; + sal_Int32 m_nSubPkgCount; + sal_Int32 m_iNextSubPkg; + + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > + implDetectScriptPackage( const com::sun::star::uno::Reference + < com::sun::star::deployment::XPackage > xPackage, bool& rbPureDialogLib ); + +public: + ScriptSubPackageIterator( com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xMainPackage ); + + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > getNextScriptSubPackage( bool& rbPureDialogLib ); +}; + +enum IteratorState +{ + USER_EXTENSIONS, + SHARED_EXTENSIONS, + END_REACHED +}; + +class ScriptExtensionIterator +{ +public: + ScriptExtensionIterator( void ); + rtl::OUString nextBasicOrDialogLibrary( bool& rbPureDialogLib ); + +private: + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > implGetScriptPackageFromPackage + ( const com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage, + bool& rbPureDialogLib ); + +protected: + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > + implGetNextUserScriptPackage( bool& rbPureDialogLib ); + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > + implGetNextSharedScriptPackage( bool& rbPureDialogLib ); + + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext; + + IteratorState m_eState; + + com::sun::star::uno::Sequence< com::sun::star::uno::Reference + < com::sun::star::deployment::XPackage > > m_aUserPackagesSeq; + bool m_bUserPackagesLoaded; + + com::sun::star::uno::Sequence< com::sun::star::uno::Reference + < com::sun::star::deployment::XPackage > > m_aSharedPackagesSeq; + bool m_bSharedPackagesLoaded; + + int m_iUserPackage; + int m_iSharedPackage; + + ScriptSubPackageIterator* m_pScriptSubPackageIterator; + +}; // end class ScriptExtensionIterator + + + +} // namespace basic + +#endif + diff --git a/basic/source/inc/object.hxx b/basic/source/inc/object.hxx new file mode 100644 index 000000000000..402b5f53bc63 --- /dev/null +++ b/basic/source/inc/object.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: object.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SAMPLE_OBJECT_HXX +#define _SAMPLE_OBJECT_HXX + +#include <basic/sbxfac.hxx> +#ifndef __SBX_SBXVARIABLE_HXX //autogen +#include <basic/sbxvar.hxx> +#endif +#include <basic/sbxobj.hxx> + +// 1) Properties: +// Name der Name, R/O +// Value ein double-Wert, R/W +// 2) Methoden: +// Display Ausgabe eines Textes +// Square Argument * Argument +// Event Aufruf eines Basic-Programms +// 3) Unterobjekte: +// eine Collection names "Elements". Der Zugriff ist sowohl als +// Property (fuer das gesamte Objekt) als auch als Methode (fuer +// einzelne Elemente, wird durchgereicht) implementiert. +// Diese Implementation ist ein Beispiel fuer eine tabellengesteuerte +// Version, die sehr viele Elemente enthalten kann. +// Die Collection findet sich in COLLECTN.*, die in der Collection +// enthaltenen Objekte in COLLELEM.* + +class SampleObject : public SbxObject +{ +using SbxVariable::GetInfo; + // Definition eines Tabelleneintrags. Dies wird hier gemacht, + // da dadurch die Methoden und Properties als private deklariert + // werden koennen. +#if defined ( ICC ) || defined ( HPUX ) || defined ( C50 ) || defined ( C52 ) +public: +#endif + typedef void( SampleObject::*pMeth ) + ( SbxVariable* pThis, SbxArray* pArgs, BOOL bWrite ); +#if defined ( ICC ) || defined ( HPUX ) +private: +#endif + + struct Methods { + const char* pName; // Name des Eintrags + SbxDataType eType; // Datentyp + pMeth pFunc; // Function Pointer + short nArgs; // Argumente und Flags + }; + static Methods aMethods[]; // Methodentabelle + + // Methoden + void Display( SbxVariable*, SbxArray*, BOOL ); + void Event( SbxVariable*, SbxArray*, BOOL ); + void Square( SbxVariable*, SbxArray*, BOOL ); + void Create( SbxVariable*, SbxArray*, BOOL ); + // Infoblock auffuellen + SbxInfo* GetInfo( short nIdx ); + // Broadcaster Notification + virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ); +public: + SampleObject( const String& ); + // Suchen eines Elements + virtual SbxVariable* Find( const String&, SbxClassType ); +}; + +// Die dazugehoerige Factory: + +class SampleObjectFac : public SbxFactory +{ +public: + virtual SbxObject* CreateObject( const String& ); +}; + +#endif diff --git a/basic/source/inc/opcodes.hxx b/basic/source/inc/opcodes.hxx new file mode 100644 index 000000000000..8dede6571baf --- /dev/null +++ b/basic/source/inc/opcodes.hxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: opcodes.hxx,v $ + * $Revision: 1.15 $ + * + * 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 + _ERASE_CLEAR, // Erase array and clear variable + _ARRAYACCESS, // Assign parameters to TOS and get value, used for array of arrays + 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) + _VBASETCLASS, // VBA-like Set + 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 + _PUBLIC_P, // Module global Variable (persisted between calls)(+StringID+Typ) + _FIND_STATIC, // local static var lookup (+StringID+Typ) + + SbOP2_END + +}; + + + +#endif diff --git a/basic/source/inc/parser.hxx b/basic/source/inc/parser.hxx new file mode 100644 index 000000000000..379ae962834b --- /dev/null +++ b/basic/source/inc/parser.hxx @@ -0,0 +1,154 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: parser.hxx,v $ + * $Revision: 1.12 $ + * + * 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 _PARSER_HXX +#define _PARSER_HXX + +#include "expr.hxx" +#include "codegen.hxx" +#include "symtbl.hxx" + + +#include <vector> +typedef ::std::vector< String > IfaceVector; + +struct SbiParseStack; + +class SbiParser : public SbiTokenizer +{ + friend class SbiExpression; + + SbiParseStack* pStack; // Block-Stack + SbiProcDef* pProc; // aktuelle Prozedur + SbiExprNode* pWithVar; // aktuelle With-Variable + SbiToken eEndTok; // das Ende-Token + UINT32 nGblChain; // Chainkette fuer globale DIMs + BOOL bGblDefs; // TRUE globale Definitionen allgemein + BOOL bNewGblDefs; // TRUE globale Definitionen vor Sub + BOOL bSingleLineIf; // TRUE einzeiliges if-Statement + + SbiSymDef* VarDecl( SbiDimList**,BOOL,BOOL );// Variablen-Deklaration + SbiProcDef* ProcDecl(BOOL bDecl);// Prozedur-Deklaration + void DefStatic( BOOL bPrivate ); + void DefProc( BOOL bStatic, BOOL bPrivate ); // Prozedur einlesen + void DefVar( SbiOpcode eOp, BOOL bStatic ); // DIM/REDIM einlesen + void TypeDecl( SbiSymDef&, BOOL bAsNewAlreadyParsed=FALSE ); // AS-Deklaration + void OpenBlock( SbiToken, SbiExprNode* = NULL ); // Block oeffnen + void CloseBlock(); // Block aufloesen + BOOL Channel( BOOL=FALSE ); // Kanalnummer parsen + void StmntBlock( SbiToken ); // Statement-Block abarbeiten + void DefType( BOOL bPrivate ); // Parse type declaration + void DefEnum( BOOL bPrivate ); // Parse enum declaration + void DefDeclare( BOOL bPrivate );
+ void EnableCompatibility(); +public: + SbxArrayRef rTypeArray; // das Type-Array + SbxArrayRef rEnumArray; // Enum types + SbiStringPool aGblStrings; // der String-Pool + SbiStringPool aLclStrings; // der String-Pool + SbiSymPool aGlobals; // globale Variable + SbiSymPool aPublics; // modulglobale Variable + SbiSymPool aRtlSyms; // Runtime-Library + SbiCodeGen aGen; // Code-Generator + StarBASIC* pBasic; // StarBASIC-Instanz + SbiSymPool* pPool; // aktueller Pool + SbiExprType eCurExpr; // aktueller Expr-Typ + short nBase; // OPTION BASE-Wert + BOOL bText; // OPTION COMPARE TEXT + BOOL bExplicit; // TRUE: OPTION EXPLICIT + BOOL bClassModule; // TRUE: OPTION ClassModule + IfaceVector aIfaceVector; // Holds all interfaces implemented by a class module + SbxDataType eDefTypes[26]; // DEFxxx-Datentypen + + SbiParser( StarBASIC*, SbModule* ); + BOOL Parse(); // die Aktion + SbiExprNode* GetWithVar(); // Innerste With-Variable liefern + + // AB 31.3.1996, Symbol in Runtime-Library suchen + SbiSymDef* CheckRTLForSym( const String& rSym, SbxDataType eType ); + void AddConstants( void ); + + BOOL HasGlobalCode(); // Globaler Code definiert? + + BOOL TestToken( SbiToken ); // bestimmtes TOken? + BOOL TestSymbol( BOOL=FALSE ); // Symbol? + BOOL TestComma(); // Komma oder EOLN? + void TestEoln(); // EOLN? + + void Symbol(); // Let oder Call + void ErrorStmnt(); // ERROR n + void NotImp(); // nicht implementiert + void BadBlock(); // LOOP/WEND/NEXT + void BadSyntax(); // Falsches SbiToken + void NoIf(); // ELSE/ELSE IF ohne IF + void Assign(); // LET + void Call(); // CALL + void Close(); // CLOSE + void Declare(); // DECLARE + void DefXXX(); // DEFxxx + void Dim(); // DIM + void ReDim(); // ReDim(); + void Erase(); // ERASE + void Exit(); // EXIT + void For(); // FOR...NEXT + void Goto(); // GOTO / GOSUB + void If(); // IF + void Implements(); // IMPLEMENTS + void Input(); // INPUT, INPUT # + void LineInput(); // LINE INPUT, LINE INPUT # + void LSet(); // LSET + void Name(); // NAME .. AS .. + void On(); // ON ERROR/variable + void OnGoto(); // ON...GOTO / GOSUB + void Open(); // OPEN + void Option(); // OPTION + void Print(); // PRINT, PRINT # + void SubFunc(); // SUB / FUNCTION + void Resume(); // RESUME + void Return(); // RETURN + void RSet(); // RSET + void DoLoop(); // DO...LOOP + void Select(); // SELECT ... CASE + void Set(); // SET + void Static(); // STATIC + void Stop(); // STOP/SYSTEM + void Type(); // TYPE...AS...END TYPE + void Enum(); // TYPE...END ENUM + void While(); // WHILE/WEND + void With(); // WITH + void Write(); // WRITE +}; + + + + + + +#endif diff --git a/basic/source/inc/propacc.hxx b/basic/source/inc/propacc.hxx new file mode 100644 index 000000000000..565c7a358a97 --- /dev/null +++ b/basic/source/inc/propacc.hxx @@ -0,0 +1,206 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: propacc.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_PROPBAG_HXX +#define _SFX_PROPBAG_HXX + +#include <svtools/svarray.hxx> +#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HXX_ +#include <com/sun/star/beans/PropertyValue.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HXX_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HXX_ +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYACCESS_HXX_ +#include <com/sun/star/beans/XPropertyAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCONTAINER_HXX_ +#include <com/sun/star/beans/XPropertyContainer.hpp> +#endif +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> + +#define NS_BEANS ::com::sun::star::beans +#define NS_LANG ::com::sun::star::lang +#define NS_UNO ::com::sun::star::uno + +typedef NS_BEANS::PropertyValue* SbPropertyValuePtr; +SV_DECL_PTRARR( SbPropertyValueArr_Impl, SbPropertyValuePtr, 4, 4 ) + +typedef ::cppu::WeakImplHelper2< NS_BEANS::XPropertySet, + NS_BEANS::XPropertyAccess > SbPropertyValuesHelper; + + +//========================================================================== + +class SbPropertyValues: public SbPropertyValuesHelper +{ + SbPropertyValueArr_Impl _aPropVals; + NS_UNO::Reference< ::com::sun::star::beans::XPropertySetInfo > _xInfo; + +private: + INT32 GetIndex_Impl( const ::rtl::OUString &rPropName ) const; + +public: + SbPropertyValues(); + virtual ~SbPropertyValues(); + + // XPropertySet + virtual NS_UNO::Reference< NS_BEANS::XPropertySetInfo > SAL_CALL + getPropertySetInfo(void) throw( NS_UNO::RuntimeException ); + virtual void SAL_CALL setPropertyValue( + const ::rtl::OUString& aPropertyName, + const NS_UNO::Any& aValue) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual NS_UNO::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) + throw( NS_BEANS::UnknownPropertyException, + NS_LANG::WrappedTargetException, + NS_UNO::RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( + const ::rtl::OUString& aPropertyName, + const NS_UNO::Reference< NS_BEANS::XPropertyChangeListener >& ) + throw (); + virtual void SAL_CALL removePropertyChangeListener( + const ::rtl::OUString& aPropertyName, + const NS_UNO::Reference< NS_BEANS::XPropertyChangeListener >& ) + throw (); + virtual void SAL_CALL addVetoableChangeListener( + const ::rtl::OUString& aPropertyName, + const NS_UNO::Reference< NS_BEANS::XVetoableChangeListener >& ) + throw (); + virtual void SAL_CALL removeVetoableChangeListener( + const ::rtl::OUString& aPropertyName, + const NS_UNO::Reference< NS_BEANS::XVetoableChangeListener >& ) + throw (); + + // XPropertyAccess + virtual NS_UNO::Sequence< NS_BEANS::PropertyValue > SAL_CALL getPropertyValues(void) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues(const NS_UNO::Sequence< NS_BEANS::PropertyValue >& PropertyValues_) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); +}; + +//========================================================================== + +typedef ::cppu::WeakImplHelper1< NS_BEANS::XPropertySetInfo > SbPropertySetInfoHelper; + +// AB 20.3.2000 Help Class for XPropertySetInfo implementation +class PropertySetInfoImpl +{ + friend class SbPropertySetInfo; + friend class SbPropertyContainer; + + NS_UNO::Sequence< NS_BEANS::Property > _aProps; + + sal_Int32 GetIndex_Impl( const ::rtl::OUString &rPropName ) const; + +public: + PropertySetInfoImpl(); + PropertySetInfoImpl( NS_UNO::Sequence< NS_BEANS::Property >& rProps ); + + // XPropertySetInfo + NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) throw (); + NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name) + throw( NS_UNO::RuntimeException ); + sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name) + throw ( NS_UNO::RuntimeException ); +}; + +class SbPropertySetInfo: public SbPropertySetInfoHelper +{ + PropertySetInfoImpl aImpl; + +public: + SbPropertySetInfo(); + SbPropertySetInfo( const SbPropertyValueArr_Impl &rPropVals ); + virtual ~SbPropertySetInfo(); + + // XPropertySetInfo + virtual NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) + throw( NS_UNO::RuntimeException ); + virtual NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name) + throw( NS_UNO::RuntimeException ); + virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name) + throw( NS_UNO::RuntimeException ); +}; + +//========================================================================== + +typedef ::cppu::WeakImplHelper2< NS_BEANS::XPropertySetInfo, NS_BEANS::XPropertyContainer > SbPropertyContainerHelper; + +class SbPropertyContainer: public SbPropertyContainerHelper +{ + PropertySetInfoImpl aImpl; + +public: + SbPropertyContainer(); + virtual ~SbPropertyContainer(); + + // XPropertyContainer + virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, + INT16 Attributes, + const NS_UNO::Any& DefaultValue) + throw( NS_BEANS::PropertyExistException, NS_BEANS::IllegalTypeException, + NS_LANG::IllegalArgumentException, NS_UNO::RuntimeException ); + virtual void SAL_CALL removeProperty(const ::rtl::OUString& Name) + throw( NS_BEANS::UnknownPropertyException, NS_UNO::RuntimeException ); + + // XPropertySetInfo + virtual NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) throw(); + virtual NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name) + throw( NS_UNO::RuntimeException ); + virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name) + throw( NS_UNO::RuntimeException ); + + // XPropertyAccess + virtual NS_UNO::Sequence< NS_BEANS::PropertyValue > SAL_CALL getPropertyValues(void); + virtual void SAL_CALL setPropertyValues(const NS_UNO::Sequence< NS_BEANS::PropertyValue >& PropertyValues_); +}; + +//========================================================================= + +class StarBASIC; +class SbxArray; + +void RTL_Impl_CreatePropertySet( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); + + +#undef NS_BEANS +#undef NS_LANG +#undef NS_UNO + + + +#endif + diff --git a/basic/source/inc/runtime.hxx b/basic/source/inc/runtime.hxx new file mode 100644 index 000000000000..31f99fb93169 --- /dev/null +++ b/basic/source/inc/runtime.hxx @@ -0,0 +1,529 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: runtime.hxx,v $ + * $Revision: 1.39 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBRUNTIME_HXX +#define _SBRUNTIME_HXX + +#ifndef _SBX_HXX +#include <basic/sbx.hxx> +#endif + +#include "sb.hxx" + +// Define activates class UCBStream in iosys.cxx +#define _USE_UNO + +#ifdef _USE_UNO +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <osl/file.hxx> +#include <rtl/math.hxx> +#include <i18npool/lang.h> + +#include <vector> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <unotools/localedatawrapper.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; + + +// Define activates old file implementation +// (only in non UCB case) +// #define _OLD_FILE_IMPL + + +//#include <sal/types.h> +//#include <rtl/byteseq.hxx> +//#include <rtl/ustring> + + +namespace basicEncoder +{ + +// TODO: Use exported functionality (code is copied from deamons2/ucb) +class AsciiEncoder +{ +public: + static ::rtl::OUString decodeUnoUrlParamValue(const rtl::OUString & rSource); + //static ::rtl::OUString encodeUnoUrlParamValue(const rtl::OUString & rSource); + //static ::rtl::ByteSequence decode(const ::rtl::OUString & string); + //static ::rtl::OUString encode(const ::rtl::ByteSequence & bytes); + //static void test(); +}; + +} + +#endif /* _USE_UNO */ + +class SbiInstance; // aktiver StarBASIC-Prozess +class SbiRuntime; // aktive StarBASIC-Prozedur-Instanz + +struct SbiArgvStack; // Argv stack element +struct SbiGosubStack; // GOSUB stack element +class SbiImage; // Code-Image +class SbiIoSystem; // Dateisystem +class SbiDdeControl; // DDE-Steuerung +class SbiDllMgr; // Aufrufe in DLLs +class SvNumberFormatter; // Zeit/Datumsfunktionen + +enum ForType +{ + FOR_TO, + FOR_EACH_ARRAY, + FOR_EACH_COLLECTION, + FOR_EACH_XENUMERATION +}; + +struct SbiForStack { // for/next stack: + SbiForStack* pNext; // Chain + SbxVariableRef refVar; // loop variable + SbxVariableRef refEnd; // end expression / for each: Array/BasicCollection object + SbxVariableRef refInc; // increment expression + + // For each support + ForType eForType; + INT32 nCurCollectionIndex; + INT32* pArrayCurIndices; + INT32* pArrayLowerBounds; + INT32* pArrayUpperBounds; + Reference< XEnumeration > xEnumeration; + + SbiForStack( void ) + : pArrayCurIndices( NULL ) + , pArrayLowerBounds( NULL ) + , pArrayUpperBounds( NULL ) + {} + ~SbiForStack() + { + delete[] pArrayCurIndices; + delete[] pArrayLowerBounds; + delete[] pArrayUpperBounds; + } +}; + +struct SbiGosubStack { // GOSUB-Stack: + SbiGosubStack* pNext; // Chain + const BYTE* pCode; // Return-Pointer + USHORT nStartForLvl; // #118235: For Level in moment of gosub +}; + +#define MAXRECURSION 500 // max. 500 Rekursionen + +#define Sb_ATTR_NORMAL 0x0000 +#define Sb_ATTR_HIDDEN 0x0002 +#define Sb_ATTR_SYSTEM 0x0004 +#define Sb_ATTR_VOLUME 0x0008 +#define Sb_ATTR_DIRECTORY 0x0010 +#define Sb_ATTR_ARCHIVE 0x0020 + + +class Dir; +class WildCard; + +class SbiRTLData +{ +public: + +#ifdef _OLD_FILE_IMPL + Dir* pDir; +#else + ::osl::Directory* pDir; +#endif + INT16 nDirFlags; + short nCurDirPos; + + String sFullNameToBeChecked; + WildCard* pWildCard; + +#ifdef _USE_UNO + Sequence< ::rtl::OUString > aDirSeq; +#endif /* _USE_UNO */ + + SbiRTLData(); + ~SbiRTLData(); +}; + +// Die Instanz entspricht einem laufenden StarBASIC. Mehrere gleichzeitig +// laufende BASICs werden ueber verkettete Instanzen verwaltet. Hier liegen +// alle Daten, die nur leben, wenn BASIC auch lebt, wie z.B. das I/O-System. + +typedef ::std::vector +< + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > +> +ComponentVector_t; + + +class SbiInstance +{ + friend class SbiRuntime; + + SbiRTLData aRTLData; + + SbiIoSystem* pIosys; // Dateisystem + SbiDdeControl* pDdeCtrl; // DDE + SbiDllMgr* pDllMgr; // DLL-Calls (DECLARE) + StarBASIC* pBasic; + SvNumberFormatter* pNumberFormatter; + LanguageType meFormatterLangType; + DateFormat meFormatterDateFormat; + sal_uInt32 nStdDateIdx, nStdTimeIdx, nStdDateTimeIdx; + + SbError nErr; // aktueller Fehlercode + String aErrorMsg; // letzte Error-Message fuer $ARG + USHORT nErl; // aktuelle Fehlerzeile + BOOL bReschedule; // Flag: TRUE = Reschedule in Hauptschleife + BOOL bCompatibility; // Flag: TRUE = VBA runtime compatibility mode + + ComponentVector_t ComponentVector; + +public: + SbiRuntime* pRun; // Call-Stack + SbiInstance* pNext; // Instanzen-Chain + + // #31460 Neues Konzept fuer StepInto/Over/Out, + // Erklaerung siehe runtime.cxx bei SbiInstance::CalcBreakCallLevel() + USHORT nCallLvl; // Call-Level (wg. Rekursion) + USHORT nBreakCallLvl; // Call-Level zum Anhalten + void CalcBreakCallLevel( USHORT nFlags ); // Gemaess Flags setzen + + SbiInstance( StarBASIC* ); + ~SbiInstance(); + + void Error( SbError ); // trappable Error + void Error( SbError, const String& rMsg ); // trappable Error mit Message + void FatalError( SbError ); // non-trappable Error + void FatalError( SbError, const String& ); // non-trappable Error + void Abort(); // Abbruch mit aktuellem Fehlercode + + void Stop(); + SbError GetErr() { return nErr; } + String GetErrorMsg() { return aErrorMsg; } + xub_StrLen GetErl() { return nErl; } + void EnableReschedule( BOOL bEnable ) { bReschedule = bEnable; } + BOOL IsReschedule( void ) { return bReschedule; } + void EnableCompatibility( BOOL bEnable ) { bCompatibility = bEnable; } + BOOL IsCompatibility( void ) { return bCompatibility; } + + ComponentVector_t& getComponentVector( void ) { return ComponentVector; } + + SbMethod* GetCaller( USHORT ); + SbModule* GetActiveModule(); + SbxArray* GetLocals( SbMethod* ); + + SbiIoSystem* GetIoSystem() { return pIosys; } + SbiDdeControl* GetDdeControl() { return pDdeCtrl; } + StarBASIC* GetBasic( void ) { return pBasic; } + SbiDllMgr* GetDllMgr(); + SbiRTLData* GetRTLData() const { return (SbiRTLData*)&aRTLData; } + + SvNumberFormatter* GetNumberFormatter(); + sal_uInt32 GetStdDateIdx() const { return nStdDateIdx; } + sal_uInt32 GetStdTimeIdx() const { return nStdTimeIdx; } + sal_uInt32 GetStdDateTimeIdx() const { return nStdDateTimeIdx; } + + // #39629# NumberFormatter auch statisch anbieten + static void PrepareNumberFormatter( SvNumberFormatter*& rpNumberFormatter, + sal_uInt32 &rnStdDateIdx, sal_uInt32 &rnStdTimeIdx, sal_uInt32 &rnStdDateTimeIdx, + LanguageType* peFormatterLangType=NULL, DateFormat* peFormatterDateFormat=NULL ); +}; + +SbiIoSystem* SbGetIoSystem(); // das aktuelle I/O-System + + +// Verkettbare Items, um Referenzen temporaer zu halten +struct RefSaveItem +{ + SbxVariableRef xRef; + RefSaveItem* pNext; + + RefSaveItem() { pNext = NULL; } +}; + + +// Eine Instanz dieser Klasse wird fuer jedes ausgefuehrte Unterprogramm +// aufgesetzt. Diese Instanz ist das Herz der BASIC-Maschine und enthaelt +// nur lokale Daten. + +class SbiRuntime +{ + typedef void( SbiRuntime::*pStep0 )(); + typedef void( SbiRuntime::*pStep1 )( UINT32 nOp1 ); + typedef void( SbiRuntime::*pStep2 )( UINT32 nOp1, UINT32 nOp2 ); + static pStep0 aStep0[]; // Opcode-Tabelle Gruppe 0 + static pStep1 aStep1[]; // Opcode-Tabelle Gruppe 1 + static pStep2 aStep2[]; // Opcode-Tabelle Gruppe 2 + + StarBASIC& rBasic; // StarBASIC-Instanz + SbiInstance* pInst; // aktiver Thread + SbModule* pMod; // aktuelles Modul + SbMethod* pMeth; // Methoden-Instanz + SbiIoSystem* pIosys; // I/O-System + const SbiImage* pImg; // Code-Image + SbxArrayRef refExprStk; // expression stack + SbxArrayRef refCaseStk; // CASE expression stack + SbxArrayRef refRedimpArray; // Array saved to use for REDIM PRESERVE + SbxVariableRef xDummyVar; // Ersatz fuer nicht gefundene Variablen + SbiArgvStack* pArgvStk; // ARGV-Stack + SbiGosubStack* pGosubStk; // GOSUB stack + SbiForStack* pForStk; // FOR/NEXT-Stack + USHORT nExprLvl; // Tiefe des Expr-Stacks + USHORT nGosubLvl; // Zum Vermeiden von Tot-Rekursionen + USHORT nForLvl; // #118235: Maintain for level + const BYTE* pCode; // aktueller Code-Pointer + const BYTE* pStmnt; // Beginn des lezten Statements + const BYTE* pError; // Adresse des aktuellen Error-Handlers + const BYTE* pRestart; // Restart-Adresse + const BYTE* pErrCode; // Restart-Adresse RESUME NEXT + const BYTE* pErrStmnt; // Restart-Adresse RESUMT 0 + String aLibName; // Lib-Name fuer Declare-Call + SbxArrayRef refParams; // aktuelle Prozedur-Parameter + SbxArrayRef refLocals; // lokale Variable + SbxArrayRef refArgv; // aktueller Argv + // AB, 28.3.2000 #74254, Ein refSaveObj reicht nicht! Neu: pRefSaveList (s.u.) + //SbxVariableRef refSaveObj; // #56368 Bei StepElem Referenz sichern + short nArgc; // aktueller Argc + BOOL bRun; // TRUE: Programm ist aktiv + BOOL bError; // TRUE: Fehler behandeln + BOOL bInError; // TRUE: in einem Fehler-Handler + BOOL bBlocked; // TRUE: blocked by next call level, #i48868 + BOOL bVBAEnabled; + USHORT nFlags; // Debugging-Flags + SbError nError; // letzter Fehler + USHORT nOps; // Opcode-Zaehler + sal_uInt32 m_nLastTime; + + RefSaveItem* pRefSaveList; // #74254 Temporaere Referenzen sichern + RefSaveItem* pItemStoreList; // Unbenutzte Items aufbewahren + void SaveRef( SbxVariable* pVar ) + { + RefSaveItem* pItem = pItemStoreList; + if( pItem ) + pItemStoreList = pItem->pNext; + else + pItem = new RefSaveItem(); + pItem->pNext = pRefSaveList; + pItem->xRef = pVar; + pRefSaveList = pItem; + } + void ClearRefs( void ) + { + while( pRefSaveList ) + { + RefSaveItem* pToClearItem = pRefSaveList; + pRefSaveList = pToClearItem->pNext; + pToClearItem->xRef = NULL; + pToClearItem->pNext = pItemStoreList; + pItemStoreList = pToClearItem; + } + } + + SbxVariable* FindElement + ( SbxObject* pObj, UINT32 nOp1, UINT32 nOp2, SbError, BOOL bLocal, BOOL bStatic = FALSE ); + void SetupArgs( SbxVariable*, UINT32 ); + SbxVariable* CheckArray( SbxVariable* ); + + void PushVar( SbxVariable* ); // Variable push + SbxVariableRef PopVar(); // Variable pop + SbxVariable* GetTOS( short=0 ); // Variable vom TOS holen + void TOSMakeTemp(); // TOS in temp. Variable wandeln + BOOL ClearExprStack(); // Expr-Stack freigeben + + void PushGosub( const BYTE* ); // GOSUB-Element push + void PopGosub(); // GOSUB-Element pop + void ClearGosubStack(); // GOSUB-Stack freigeben + + void PushArgv(); // Argv-Element push + void PopArgv(); // Argv-Element pop + void ClearArgvStack(); // Argv-Stack freigeben + + void PushFor(); // For-Element push + void PushForEach(); // For-Each-Element push + void PopFor(); // For-Element pop + void ClearForStack(); // For-Stack freigeben + + void StepArith( SbxOperator ); // arithmetische Verknuepfungen + void StepUnary( SbxOperator ); // unaere Verknuepfungen + void StepCompare( SbxOperator );// Vergleiche + + void SetParameters( SbxArray* );// Parameter uebernehmen + + // MUSS NOCH IMPLEMENTIERT WERDEN + void DllCall( const String&, const String&, SbxArray*, SbxDataType, BOOL ); + + // #56204 DIM-Funktionalitaet in Hilfsmethode auslagern (step0.cxx) + void DimImpl( SbxVariableRef refVar ); + + // #115829 + bool implIsClass( SbxObject* pObj, const String& aClass ); + + void StepSETCLASS_impl( UINT32 nOp1, bool bHandleDflt = false ); + + // Die nachfolgenden Routinen werden vom Single Stepper + // gerufen und implementieren die einzelnen Opcodes + void StepNOP(), StepEXP(), StepMUL(), StepDIV(); + void StepMOD(), StepPLUS(), StepMINUS(), StepNEG(); + void StepEQ(), StepNE(), StepLT(), StepGT(); + void StepLE(), StepGE(), StepIDIV(), StepAND(); + void StepOR(), StepXOR(), StepEQV(), StepIMP(); + void StepNOT(), StepCAT(), StepLIKE(), StepIS(); + void StepCLONE(), StepOLDBASED(), StepARGC(); + void StepARGV(), StepINPUT(), StepLINPUT(), StepSTOP(); + void StepGET(), StepSET(), StepVBASET(), StepPUT(), StepPUTC(); + void StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bDefaultHandling = false ); + void StepDIM(), StepREDIM(), StepREDIMP(), StepERASE(); + void StepINITFOR(), StepNEXT(), StepERROR(), StepINITFOREACH(); + void StepCASE(), StepENDCASE(), StepSTDERROR(); + void StepNOERROR(), StepCHANNEL(), StepCHANNEL0(), StepPRINT(); + void StepPRINTF(), StepWRITE(), StepRENAME(), StepPROMPT(); + void StepRESTART(), StepEMPTY(), StepLEAVE(); + void StepLSET(), StepRSET(), StepREDIMP_ERASE(), StepERASE_CLEAR(); + void StepARRAYACCESS(); + // Alle Opcodes mit einem Operanden + void StepLOADNC( UINT32 ), StepLOADSC( UINT32 ), StepLOADI( UINT32 ); + void StepARGN( UINT32 ), StepBASED( UINT32 ), StepPAD( UINT32 ); + void StepJUMP( UINT32 ), StepJUMPT( UINT32 ); + void StepJUMPF( UINT32 ), StepONJUMP( UINT32 ); + void StepGOSUB( UINT32 ), StepRETURN( UINT32 ); + void StepTESTFOR( UINT32 ), StepCASETO( UINT32 ), StepERRHDL( UINT32 ); + void StepRESUME( UINT32 ), StepSETCLASS( UINT32 ), StepVBASETCLASS( UINT32 ), StepTESTCLASS( UINT32 ), StepLIB( UINT32 ); + bool checkClass_Impl( const SbxVariableRef& refVal, const String& aClass, bool bRaiseErrors ); + void StepCLOSE( UINT32 ), StepPRCHAR( UINT32 ), StepARGTYP( UINT32 ); + // Alle Opcodes mit zwei Operanden + void StepRTL( UINT32, UINT32 ), StepPUBLIC( UINT32, UINT32 ), StepPUBLIC_P( UINT32, UINT32 ); + void StepPUBLIC_Impl( UINT32, UINT32, bool bUsedForClassModule ); + void StepFIND_Impl( SbxObject* pObj, UINT32 nOp1, UINT32 nOp2, SbError, BOOL bLocal, BOOL bStatic = FALSE ); + void StepFIND( UINT32, UINT32 ), StepELEM( UINT32, UINT32 ); + void StepGLOBAL( UINT32, UINT32 ), StepLOCAL( UINT32, UINT32 ); + void StepPARAM( UINT32, UINT32), StepCREATE( UINT32, UINT32 ); + void StepCALL( UINT32, UINT32 ), StepCALLC( UINT32, UINT32 ); + void StepCASEIS( UINT32, UINT32 ), StepSTMNT( UINT32, UINT32 ); + SbxVariable* StepSTATIC_Impl( String& aName, SbxDataType& t ); + void StepOPEN( UINT32, UINT32 ), StepSTATIC( UINT32, UINT32 ); + void StepTCREATE(UINT32,UINT32), StepDCREATE(UINT32,UINT32); + void StepGLOBAL_P( UINT32, UINT32 ),StepFIND_G( UINT32, UINT32 ); + void StepDCREATE_REDIMP(UINT32,UINT32), StepDCREATE_IMPL(UINT32,UINT32); + void StepFIND_CM( UINT32, UINT32 ); + void StepFIND_STATIC( UINT32, UINT32 ); +public: + void SetVBAEnabled( bool bEnabled ) { bVBAEnabled = bEnabled; }; + USHORT GetImageFlag( USHORT n ) const; + USHORT GetBase(); + xub_StrLen nLine,nCol1,nCol2; // aktuelle Zeile, Spaltenbereich + SbiRuntime* pNext; // Stack-Chain + + SbiRuntime( SbModule*, SbMethod*, UINT32 ); + ~SbiRuntime(); + void Error( SbError ); // Fehler setzen, falls != 0 + void Error( SbError, const String& ); // Fehler setzen, falls != 0 + void FatalError( SbError ); // Fehlerbehandlung=Standard, Fehler setzen + void FatalError( SbError, const String& ); // Fehlerbehandlung=Standard, Fehler setzen + void DumpPCode(); + BOOL Step(); // Einzelschritt (ein Opcode) + void Stop() { bRun = FALSE; } + BOOL IsRun() { return bRun; } + void block( void ) { bBlocked = TRUE; } + void unblock( void ) { bBlocked = FALSE; } + SbMethod* GetMethod() { return pMeth; } + SbModule* GetModule() { return pMod; } + USHORT GetDebugFlags() { return nFlags; } + void SetDebugFlags( USHORT nFl ) { nFlags = nFl; } + SbMethod* GetCaller(); + SbxArray* GetLocals(); + SbxArray* GetParams(); + + SbxBase* FindElementExtern( const String& rName ); + static bool isVBAEnabled(); + +}; + +inline void checkArithmeticOverflow( double d ) +{ + if( !::rtl::math::isFinite( d ) ) + StarBASIC::Error( SbERR_MATH_OVERFLOW ); +} + +inline void checkArithmeticOverflow( SbxVariable* pVar ) +{ + if( pVar->GetType() == SbxDOUBLE ) + { + double d = pVar->GetDouble(); + checkArithmeticOverflow( d ); + } +} + +// Hilfsfunktion, um aktives Basic zu finden +StarBASIC* GetCurrentBasic( StarBASIC* pRTBasic ); + +// Get information if security restrictions should be +// used (File IO based on UCB, no RTL function SHELL +// no DDE functionality, no DLLCALL) in basic because +// of portal "virtual" users (portal user != UNIX user) +// (Implemented in iosys.cxx) +BOOL needSecurityRestrictions( void ); + +// Returns TRUE if UNO is available, otherwise the old +// file system implementation has to be used +// (Implemented in iosys.cxx) +BOOL hasUno( void ); + +// Converts possibly relative paths to absolute paths +// according to the setting done by ChDir/ChDrive +// (Implemented in methods.cxx) +String getFullPath( const String& aRelPath ); + +// Sets (virtual) current path for UCB file access +void implChDir( const String& aDir ); + +// Sets (virtual) current drive for UCB file access +void implChDrive( const String& aDrive ); + +// Returns (virtual) current path for UCB file access +String implGetCurDir( void ); + +// Implementation of StepRENAME with UCB +// (Implemented in methods.cxx, so step0.cxx +// has not to be infected with UNO) +void implStepRenameUCB( const String& aSource, const String& aDest ); + +//*** OSL file access *** +// #87427 OSL need File URLs, so map to getFullPath +inline String getFullPathUNC( const String& aRelPath ) +{ + return getFullPath( aRelPath ); +} +void implStepRenameOSL( const String& aSource, const String& aDest ); +bool IsBaseIndexOne(); + +#endif + diff --git a/basic/source/inc/sbcomp.hxx b/basic/source/inc/sbcomp.hxx new file mode 100644 index 000000000000..6eb9f640d058 --- /dev/null +++ b/basic/source/inc/sbcomp.hxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbcomp.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBCOMP_HXX +#define _SBCOMP_HXX + +// das folgende habe ich der neuen Datei von MD entnommen! (MT) +#include "sbintern.hxx" +#include "token.hxx" // Tokenizer +#include "symtbl.hxx" // Symbolverwaltung +#include "parser.hxx" // Parser +#include "codegen.hxx" // Code-Generator + +#endif diff --git a/basic/source/inc/sbintern.hxx b/basic/source/inc/sbintern.hxx new file mode 100644 index 000000000000..596b4d0c2804 --- /dev/null +++ b/basic/source/inc/sbintern.hxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbintern.hxx,v $ + * $Revision: 1.16.56.1 $ + * + * 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 <basic/sbxfac.hxx> +#include <unotools/transliterationwrapper.hxx> +#include "sb.hxx" + +namespace utl +{ + class TransliterationWrapper; +} +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 ); + ~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(); + + void AddClassModule( SbModule* pClassModule ); + void RemoveClassModule( SbModule* pClassModule ); + + virtual SbxBase* Create( UINT16 nSbxId, UINT32 = SBXCR_SBX ); + virtual SbxObject* CreateObject( const String& ); + + SbModule* FindClass( const String& rClassName ); +}; + +// 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; + StarBASIC* pMSOMacroRuntimLib; // Lib containing MSO Macro Runtime API entry symbols + + 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 + diff --git a/basic/source/inc/sbjsmeth.hxx b/basic/source/inc/sbjsmeth.hxx new file mode 100644 index 000000000000..131eab023957 --- /dev/null +++ b/basic/source/inc/sbjsmeth.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbjsmeth.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _SB_SBJSMETH_HXX +#define _SB_SBJSMETH_HXX + +#include <basic/sbmeth.hxx> + +// 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 diff --git a/basic/source/inc/sbjsmod.hxx b/basic/source/inc/sbjsmod.hxx new file mode 100644 index 000000000000..8df57e4e9a4d --- /dev/null +++ b/basic/source/inc/sbjsmod.hxx @@ -0,0 +1,53 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbjsmod.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SB_SBJSMOD_HXX +#define _SB_SBJSMOD_HXX + +#include <basic/sbmod.hxx> + +// 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 + + + diff --git a/basic/source/inc/sbunoobj.hxx b/basic/source/inc/sbunoobj.hxx new file mode 100644 index 000000000000..6889aa196c54 --- /dev/null +++ b/basic/source/inc/sbunoobj.hxx @@ -0,0 +1,310 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbunoobj.hxx,v $ + * $Revision: 1.21 $ + * + * 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 <basic/sbxobj.hxx> +#include <basic/sbxmeth.hxx> +#include <basic/sbxprop.hxx> +#include <basic/sbxfac.hxx> +#ifndef __SBX_SBX_HXX //autogen +#include <basic/sbx.hxx> +#endif +#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> +#include <com/sun/star/reflection/XServiceTypeDescription2.hpp> +#include <rtl/ustring.hxx> + +class SbUnoObject: public SbxObject +{ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XIntrospectionAccess > mxUnoAccess; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMaterialHolder > mxMaterialHolder; + ::com::sun::star::uno::Reference< ::com::sun::star::script::XInvocation > mxInvocation; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XExactName > mxExactName; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XExactName > mxExactNameInvocation; + BOOL bNeedIntrospection; + ::com::sun::star::uno::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: + static bool getDefaultPropName( SbUnoObject* pUnoObj, String& sDfltProp ); + TYPEINFO(); + SbUnoObject( const String& aName_, const ::com::sun::star::uno::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 + ::com::sun::star::uno::Any getUnoAny( void ); + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XIntrospectionAccess > getIntrospectionAccess( void ) { return mxUnoAccess; } + ::com::sun::star::uno::Reference< ::com::sun::star::script::XInvocation > getInvocation( void ) { return mxInvocation; } + + void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); +}; +SV_DECL_IMPL_REF(SbUnoObject); + + +// #67781 Rueckgabewerte der Uno-Methoden loeschen +void clearUnoMethods( void ); + +class SbUnoMethod : public SbxMethod +{ + friend class SbUnoObject; + friend void clearUnoMethods( void ); + + ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XIdlMethod > m_xUnoMethod; + ::com::sun::star::uno::Sequence< ::com::sun::star::reflection::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, ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XIdlMethod > xUnoMethod_, + bool bInvocation ); + virtual ~SbUnoMethod(); + virtual SbxInfo* GetInfo(); + + const ::com::sun::star::uno::Sequence< ::com::sun::star::reflection::ParamInfo >& getParamInfos( void ); + + bool isInvocationBased( void ) + { return mbInvocation; } +}; + + +class SbUnoProperty : public SbxProperty +{ + friend class SbUnoObject; + + // Daten der Uno-Property + ::com::sun::star::beans::Property aUnoProp; + INT32 nId; + + bool mbInvocation; // Property is based on invocation + + virtual ~SbUnoProperty(); +public: + TYPEINFO(); + SbUnoProperty( const String& aName_, SbxDataType eSbxType, + const ::com::sun::star::beans::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 ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XIdlClass > m_xClass; + +public: + TYPEINFO(); + SbUnoClass( const String& aName_ ) + : SbxObject( aName_ ) + {} + SbUnoClass( const String& aName_, const ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XIdlClass >& xClass_ ) + : SbxObject( aName_ ) + , m_xClass( xClass_ ) + {} + //~SbUnoClass(); + + // Find ueberladen, um Elemente on Demand anzulegen + virtual SbxVariable* Find( const String&, SbxClassType ); + + // Wert rausgeben + const ::com::sun::star::uno::Reference< ::com::sun::star::reflection::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 +SbUnoClass* findUnoClass( const String& rName ); + + +// Wrapper for UNO Service +class SbUnoService : public SbxObject +{ + const ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XServiceTypeDescription2 > m_xServiceTypeDesc; + bool m_bNeedsInit; + +public: + TYPEINFO(); + SbUnoService( const String& aName_, + const ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XServiceTypeDescription2 >& xServiceTypeDesc ) + : SbxObject( aName_ ) + , m_xServiceTypeDesc( xServiceTypeDesc ) + , m_bNeedsInit( true ) + {} + + virtual SbxVariable* Find( const String&, SbxClassType ); + + void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); +}; +SV_DECL_IMPL_REF(SbUnoService); + +SbUnoService* findUnoService( const String& rName ); + + +void clearUnoServiceCtors( void ); + +class SbUnoServiceCtor : public SbxMethod +{ + friend class SbUnoService; + friend void clearUnoServiceCtors( void ); + + ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XServiceConstructorDescription > m_xServiceCtorDesc; + + SbUnoServiceCtor* pPrev; + SbUnoServiceCtor* pNext; + +public: + TYPEINFO(); + + SbUnoServiceCtor( const String& aName_, ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XServiceConstructorDescription > xServiceCtorDesc ); + virtual ~SbUnoServiceCtor(); + virtual SbxInfo* GetInfo(); + + ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XServiceConstructorDescription > getServiceCtorDesc( void ) + { return m_xServiceCtorDesc; } +}; + + +// #105565 Special Object to wrap a strongly typed Uno Any +class SbUnoAnyObject: public SbxObject +{ + ::com::sun::star::uno::Any mVal; + +public: + SbUnoAnyObject( const ::com::sun::star::uno::Any& rVal ) + : SbxObject( String() ) + , mVal( rVal ) + {} + + const ::com::sun::star::uno::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 +{ + ::com::sun::star::uno::Sequence< ::rtl::OUString > maNameSeq; +public: + TYPEINFO(); + AutomationNamedArgsSbxArray( sal_Int32 nSeqSize ) + : maNameSeq( nSeqSize ) + {} + + ::com::sun::star::uno::Sequence< ::rtl::OUString >& getNames( void ) + { return maNameSeq; } +}; + + +class StarBASIC; + +// Impl-Methoden fuer RTL +void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); + + +//======================================================================== +// #118116 Collection object + +class BasicCollection : public SbxObject +{ + friend class SbiRuntime; + SbxArrayRef xItemArray; + static SbxInfoRef xAddInfo; + static SbxInfoRef xItemInfo; + + 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 + + diff --git a/basic/source/inc/scanner.hxx b/basic/source/inc/scanner.hxx new file mode 100644 index 000000000000..85581a2f4d7e --- /dev/null +++ b/basic/source/inc/scanner.hxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scanner.hxx,v $ + * $Revision: 1.13 $ + * + * 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> +#ifndef _SBERRORS_HXX +#include <basic/sberrors.hxx> +#endif + +// 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 Compatibl + BOOL bVBASupportOn; // TRUE: OPTION VBASupport 1 otherwise default False + 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 IsVBASupportOn() { return bVBASupportOn; } + void SetVBASupportOn( bool b ) { bVBASupportOn = b; } + 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 DoesColonFollow(); + + 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 diff --git a/basic/source/inc/scriptcont.hxx b/basic/source/inc/scriptcont.hxx new file mode 100644 index 000000000000..b679c74b1236 --- /dev/null +++ b/basic/source/inc/scriptcont.hxx @@ -0,0 +1,182 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scriptcont.hxx,v $ + * $Revision: 1.9 $ + * + * 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 BASIC_SCRIPTCONTAINER_HXX +#define BASIC_SCRIPTCONTAINER_HXX + +#include "namecont.hxx" +#include <basic/basmgr.hxx> + +class BasicManager; + +//============================================================================ + +namespace basic +{ + +class SfxScriptLibraryContainer : public SfxLibraryContainer, public OldBasicPassword +{ + ::rtl::OUString maScriptLanguage; + + // Methods to distinguish between deffirent library types + virtual SfxLibrary* SAL_CALL implCreateLibrary( const ::rtl::OUString& aName ); + virtual SfxLibrary* SAL_CALL implCreateLibraryLink + ( const ::rtl::OUString& aName, const ::rtl::OUString& aLibInfoFileURL, + const ::rtl::OUString& StorageURL, sal_Bool ReadOnly ); + virtual ::com::sun::star::uno::Any SAL_CALL createEmptyLibraryElement( void ); + virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const; + virtual void SAL_CALL writeLibraryElement + ( + ::com::sun::star::uno::Any aElement, + const ::rtl::OUString& aElementName, + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xOutput + ) + throw(::com::sun::star::uno::Exception); + + virtual ::com::sun::star::uno::Any SAL_CALL importLibraryElement + ( const ::rtl::OUString& aFile, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xElementStream ); + + virtual void SAL_CALL importFromOldStorage( const ::rtl::OUString& aFile ); + + virtual SfxLibraryContainer* createInstanceImpl( void ); + + + // Password encryption + virtual sal_Bool implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage>& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ); + + // New variant for library export + virtual sal_Bool implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xToUseSFI, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ); + + virtual sal_Bool implLoadPasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& Name, + sal_Bool bVerifyPasswordOnly=false ) + throw(::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + virtual void onNewRootStorage(); + + + // OldBasicPassword interface + virtual void setLibraryPassword( const String& rLibraryName, const String& rPassword ); + virtual String getLibraryPassword( const String& rLibraryName ); + virtual void clearLibraryPassword( const String& rLibraryName ); + virtual sal_Bool hasLibraryPassword( const String& rLibraryName ); + + virtual const sal_Char* SAL_CALL getInfoFileName() const; + virtual const sal_Char* SAL_CALL getOldInfoFileName() const; + virtual const sal_Char* SAL_CALL getLibElementFileExtension() const; + virtual const sal_Char* SAL_CALL getLibrariesDir() const; + +public: + SfxScriptLibraryContainer( void ); + SfxScriptLibraryContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ); + + + // Methods XLibraryContainerPassword + virtual sal_Bool SAL_CALL isLibraryPasswordProtected( const ::rtl::OUString& Name ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLibraryPasswordVerified( const ::rtl::OUString& Name ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL verifyLibraryPassword( const ::rtl::OUString& Name, const ::rtl::OUString& Password ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL changeLibraryPassword( const ::rtl::OUString& Name, + const ::rtl::OUString& OldPassword, const ::rtl::OUString& NewPassword ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + + // Methods XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + + // Service + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(); + static ::rtl::OUString getImplementationName_static(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create + ( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xServiceManager ) + throw( ::com::sun::star::uno::Exception ); + +}; + +//============================================================================ + +class SfxScriptLibrary : public SfxLibrary +{ + friend class SfxScriptLibraryContainer; + + sal_Bool mbLoadedSource; + sal_Bool mbLoadedBinary; + + // Provide modify state including resources + virtual sal_Bool isModified( void ); + virtual void storeResources( void ); + virtual void storeResourcesAsURL( const ::rtl::OUString& URL, const ::rtl::OUString& NewName ); + virtual void storeResourcesToURL( const ::rtl::OUString& URL, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ); + virtual void storeResourcesToStorage( const ::com::sun::star::uno::Reference + < ::com::sun::star::embed::XStorage >& xStorage ); + +public: + SfxScriptLibrary + ( + ModifiableHelper& _rModifiable, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xMSF, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xSFI + ); + + SfxScriptLibrary + ( + ModifiableHelper& _rModifiable, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xMSF, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xSFI, + const ::rtl::OUString& aLibInfoFileURL, const ::rtl::OUString& aStorageURL, sal_Bool ReadOnly + ); + + static bool containsValidModule( const ::com::sun::star::uno::Any& _rElement ); + +protected: + virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const; +}; + +} // namespace base + +#endif + diff --git a/basic/source/inc/stdobj.hxx b/basic/source/inc/stdobj.hxx new file mode 100644 index 000000000000..c424823b5aa2 --- /dev/null +++ b/basic/source/inc/stdobj.hxx @@ -0,0 +1,54 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stdobj.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBSTDOBJ_HXX +#define _SBSTDOBJ_HXX + +#include <basic/sbxobj.hxx> + +class StarBASIC; +class SbStdFactory; + +class SbiStdObject : public SbxObject +{ + SbStdFactory* pStdFactory; + + ~SbiStdObject(); + using SbxVariable::GetInfo; + SbxInfo* GetInfo( short ); + virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ); +public: + SbiStdObject( const String&, StarBASIC* ); + virtual SbxVariable* Find( const String&, SbxClassType ); + virtual void SetModified( BOOL ); +}; + +#endif diff --git a/basic/source/inc/symtbl.hxx b/basic/source/inc/symtbl.hxx new file mode 100644 index 000000000000..f3d691bf059a --- /dev/null +++ b/basic/source/inc/symtbl.hxx @@ -0,0 +1,246 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: symtbl.hxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SYMTBL_HXX +#define _SYMTBL_HXX + +#include <svtools/svarray.hxx> +#include <tools/string.hxx> +#include <basic/sbxdef.hxx> +#include <basic/sbdef.hxx> + +class SbiSymDef; // Basisklasse +class SbiProcDef; // Prozedur +class SbiConstDef; // Konstante +class SbiSymPool; // Symbol-Pool +class SbiStringPool; // gepoolte Strings + +class SvStream; +class SbiParser; + +enum SbiSymScope { SbLOCAL, SbPARAM, SbPUBLIC, SbGLOBAL, SbRTL }; + +/////////////////////////////////////////////////////////////////////////// + +// Der String-Pool nimmt String-Eintraege auf und sorgt dafuer, +// dass sie nicht doppelt vorkommen. + +SV_DECL_PTRARR_DEL(SbiStrings,String*,5,5) + +class SbiStringPool { // String-Pool + SbiStrings aData; // Daten + String aEmpty; // for convenience + SbiParser* pParser; // der Parser +public: + SbiStringPool( SbiParser* ); + ~SbiStringPool(); + USHORT GetSize() const { return aData.Count(); } + // AB 8.4.1999, Default wegen #64236 auf TRUE geaendert + // Wenn der Bug sauber behoben ist, wieder auf FALSE aendern. + short Add( const String&, BOOL=TRUE ); + short Add( double, SbxDataType ); + const String& Find( USHORT ) const; + SbiParser* GetParser() { return pParser; } +}; + +/////////////////////////////////////////////////////////////////////////// + +SV_DECL_PTRARR_DEL(SbiSymbols,SbiSymDef*,5,5) + +class SbiSymPool { // Symbol-Pool + friend class SbiSymDef; + friend class SbiProcDef; +protected: + SbiStringPool& rStrings; // verwendeter Stringpool + SbiSymbols aData; // Daten + SbiSymPool* pParent; // uebergeordneter Symbol-Pool + SbiParser* pParser; // der Parser + SbiSymScope eScope; // Scope des Pools + USHORT nProcId; // aktuelles ProcId fuer STATIC-Variable + USHORT nCur; // Iterator +public: + SbiSymPool( SbiStringPool&, SbiSymScope ); + ~SbiSymPool(); + + void Clear(); + + void SetParent( SbiSymPool* p ) { pParent = p; } + void SetProcId( short n ) { nProcId = n; } + USHORT GetSize() const { return aData.Count(); } + SbiSymScope GetScope() const { return eScope; } + void SetScope( SbiSymScope s ) { eScope = s; } + SbiParser* GetParser() { return pParser; } + + SbiSymDef* AddSym( const String& ); // Symbol hinzufuegen + SbiProcDef* AddProc( const String& );// Prozedur hinzufuegen + void Add( SbiSymDef* ); // Symbol uebernehmen + SbiSymDef* Find( const String& ) const;// Variablenname + SbiSymDef* FindId( USHORT ) const; // Variable per ID suchen + SbiSymDef* Get( USHORT ) const; // Variable per Position suchen + SbiSymDef* First(), *Next(); // Iteratoren + + UINT32 Define( const String& ); // Label definieren + UINT32 Reference( const String& ); // Label referenzieren + void CheckRefs(); // offene Referenzen suchen +}; + +/////////////////////////////////////////////////////////////////////////// + +class SbiSymDef { // Allgemeiner Symboleintrag + friend class SbiSymPool; +protected: + String aName; // Name des Eintrags + SbxDataType eType; // Typ des Eintrags + SbiSymPool* pIn; // Parent-Pool + SbiSymPool* pPool; // Pool fuer Unterelemente + short nLen; // Stringlaenge bei STRING*n + short nDims; // Array-Dimensionen + USHORT nId; // Symbol-Nummer + USHORT nTypeId; // String-ID des Datentyps (Dim X AS Dytentyp) + USHORT nProcId; // aktuelles ProcId fuer STATIC-Variable + USHORT nPos; // Positions-Nummer + UINT32 nChain; // Backchain-Kette + BOOL bNew : 1; // TRUE: Dim As New... + BOOL bChained : 1; // TRUE: Symbol ist in Code definiert + BOOL bByVal : 1; // TRUE: ByVal-Parameter + BOOL bOpt : 1; // TRUE: optionaler Parameter + BOOL bStatic : 1; // TRUE: STATIC-Variable + BOOL bAs : 1; // TRUE: Datentyp per AS XXX definiert + BOOL bGlobal : 1; // TRUE: Global-Variable + BOOL bParamArray : 1; // TRUE: ParamArray parameter + USHORT nDefaultId; // Symbol number of default value +public: + SbiSymDef( const String& ); + virtual ~SbiSymDef(); + virtual SbiProcDef* GetProcDef(); + virtual SbiConstDef* GetConstDef(); + + SbxDataType GetType() const { return eType; } + virtual void SetType( SbxDataType ); + const String& GetName(); + SbiSymScope GetScope() const; + USHORT GetProcId() const{ return nProcId; } + UINT32 GetAddr() const { return nChain; } + USHORT GetId() const { return nId; } + USHORT GetTypeId() const{ return nTypeId; } + void SetTypeId( USHORT n ) { nTypeId = n; eType = SbxOBJECT; } + USHORT GetPos() const { return nPos; } + void SetLen( short n ){ nLen = n; } + short GetLen() const { return nLen; } + void SetDims( short n ) { nDims = n; } + short GetDims() const { return nDims; } + BOOL IsDefined() const{ return bChained; } + void SetOptional() { bOpt = TRUE; } + void SetParamArray() { bParamArray = TRUE; } + void SetByVal() { bByVal = TRUE; } + void SetStatic( BOOL bAsStatic = TRUE ) { bStatic = bAsStatic; } + void SetNew() { bNew = TRUE; } + void SetDefinedAs() { bAs = TRUE; } + void SetGlobal(BOOL b){ bGlobal = b; } + void SetDefaultId( USHORT n ) { nDefaultId = n; } + USHORT GetDefaultId( void ) { return nDefaultId; } + BOOL IsOptional() const{ return bOpt; } + BOOL IsParamArray() const{ return bParamArray; } + BOOL IsByVal() const { return bByVal; } + BOOL IsStatic() const { return bStatic; } + BOOL IsNew() const { return bNew; } + BOOL IsDefinedAs() const { return bAs; } + BOOL IsGlobal() const { return bGlobal; } + + SbiSymPool& GetPool(); + UINT32 Define(); // Symbol in Code definieren + UINT32 Reference(); // Symbol in Code referenzieren + +private: + SbiSymDef( const SbiSymDef& ); + +}; + +class SbiProcDef : public SbiSymDef { // Prozedur-Definition (aus Basic): + SbiSymPool aParams; // Parameter + SbiSymPool aLabels; // lokale Sprungziele + String aLibName; // LIB "name" + String aAlias; // ALIAS "name" + USHORT nLine1, nLine2; // Zeilenbereich + PropertyMode mePropMode; // Marks if this is a property procedure and which + String maPropName; // Property name if property procedure (!= proc name) + BOOL bCdecl : 1; // TRUE: CDECL angegeben + BOOL bPublic : 1; // TRUE: proc ist PUBLIC + BOOL mbProcDecl : 1; // TRUE: instanciated by SbiParser::ProcDecl +public: + SbiProcDef( SbiParser*, const String&, BOOL bProcDecl=false ); + virtual ~SbiProcDef(); + virtual SbiProcDef* GetProcDef(); + virtual void SetType( SbxDataType ); + SbiSymPool& GetParams() { return aParams; } + SbiSymPool& GetLabels() { return aLabels; } + SbiSymPool& GetLocals() { return GetPool();} + String& GetLib() { return aLibName; } + String& GetAlias() { return aAlias; } + void SetPublic( BOOL b ) { bPublic = b; } + BOOL IsPublic() const { return bPublic; } + void SetCdecl( BOOL b = TRUE) { bCdecl = b; } + BOOL IsCdecl() const { return bCdecl; } + BOOL IsUsedForProcDecl() const { return mbProcDecl; } + void SetLine1( USHORT n ) { nLine1 = n; } + USHORT GetLine1() const { return nLine1; } + void SetLine2( USHORT n ) { nLine2 = n; } + USHORT GetLine2() const { return nLine2; } + PropertyMode getPropertyMode() { return mePropMode; } + void setPropertyMode( PropertyMode ePropMode ); + const String& GetPropName() { return maPropName; } + + // Match mit einer Forward-Deklaration. Die Parameternamen + // werden abgeglichen und die Forward-Deklaration wird + // durch this ersetzt + void Match( SbiProcDef* pForward ); + +private: + SbiProcDef( const SbiProcDef& ); + +}; + +class SbiConstDef : public SbiSymDef +{ + double nVal; + String aVal; +public: + SbiConstDef( const String& ); + virtual ~SbiConstDef(); + virtual SbiConstDef* GetConstDef(); + void Set( double, SbxDataType ); + void Set( const String& ); + double GetValue() { return nVal; } + const String& GetString() { return aVal; } +}; + + +#endif + diff --git a/basic/source/inc/token.hxx b/basic/source/inc/token.hxx new file mode 100644 index 000000000000..8b5a929a7e65 --- /dev/null +++ b/basic/source/inc/token.hxx @@ -0,0 +1,168 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: token.hxx,v $ + * $Revision: 1.13 $ + * + * 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" +#ifndef _SBDEF_HXX +#include <basic/sbdef.hxx> +#endif + +#if defined( SHARED ) +#define SbiTokenSHAREDTMPUNDEF +#undef SHARED +#endif + +// 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; } + + void Push( SbiToken ); // Pushback eines Tokens + const String& Symbol( SbiToken );// Rueckumwandlung + + SbiToken Peek(); // das naechste Token lesen + SbiToken Next(); // Ein Token lesen + BOOL MayBeLabel( BOOL= FALSE ); // Kann es ein Label sein? + + void Hilite( SbTextPortions& ); // Syntax-Highlighting + + void Error( SbError c ) { GenError( c ); } + void Error( SbError, SbiToken ); + void Error( SbError, const char* ); + void Error( SbError, String ); + + 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 diff --git a/basic/source/runtime/basrdll.cxx b/basic/source/runtime/basrdll.cxx new file mode 100644 index 000000000000..e4c9ad1fe307 --- /dev/null +++ b/basic/source/runtime/basrdll.cxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: basrdll.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/shl.hxx> +#include <vcl/svapp.hxx> +#ifndef _SOLAR_HRC +#include <svtools/solar.hrc> +#endif +#include <tools/debug.hxx> +#include <vcl/msgbox.hxx> + +#include <basic/sbstar.hxx> +#include <basic/basrdll.hxx> +#include <basrid.hxx> +#include <sb.hrc> + +SttResId::SttResId( sal_uInt32 nId ) : + ResId( nId, *((*(BasicDLL**)GetAppData(SHL_BASIC))->GetSttResMgr()) ) +{ +} + +BasResId::BasResId( sal_uInt32 nId ) : + ResId( nId, *((*(BasicDLL**)GetAppData(SHL_BASIC))->GetBasResMgr()) ) +{ +} + +BasicDLL::BasicDLL() +{ + *(BasicDLL**)GetAppData(SHL_BASIC) = this; + ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); + pSttResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(stt), aLocale ); + pBasResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(sb), aLocale ); + bDebugMode = FALSE; + bBreakEnabled = TRUE; +} + +BasicDLL::~BasicDLL() +{ + delete pSttResMgr; + delete pBasResMgr; +} + +void BasicDLL::EnableBreak( BOOL bEnable ) +{ + BasicDLL* pThis = *(BasicDLL**)GetAppData(SHL_BASIC); + DBG_ASSERT( pThis, "BasicDLL::EnableBreak: Noch keine Instanz!" ); + if ( pThis ) + pThis->bBreakEnabled = bEnable; +} + +void BasicDLL::SetDebugMode( BOOL bDebugMode ) +{ + BasicDLL* pThis = *(BasicDLL**)GetAppData(SHL_BASIC); + DBG_ASSERT( pThis, "BasicDLL::EnableBreak: Noch keine Instanz!" ); + if ( pThis ) + pThis->bDebugMode = bDebugMode; +} + + +void BasicDLL::BasicBreak() +{ + //bJustStopping: Wenn jemand wie wild x-mal STOP drueckt, aber das Basic + // nicht schnell genug anhaelt, kommt die Box ggf. oefters... + static BOOL bJustStopping = FALSE; + + BasicDLL* pThis = *(BasicDLL**)GetAppData(SHL_BASIC); + DBG_ASSERT( pThis, "BasicDLL::EnableBreak: Noch keine Instanz!" ); + if ( pThis ) + { + if ( StarBASIC::IsRunning() && !bJustStopping && ( pThis->bBreakEnabled || pThis->bDebugMode ) ) + { + bJustStopping = TRUE; + StarBASIC::Stop(); + String aMessageStr( BasResId( IDS_SBERR_TERMINATED ) ); + InfoBox( 0, aMessageStr ).Execute(); + bJustStopping = FALSE; + } + } +} + diff --git a/basic/source/runtime/ddectrl.cxx b/basic/source/runtime/ddectrl.cxx new file mode 100644 index 000000000000..751bd57cc808 --- /dev/null +++ b/basic/source/runtime/ddectrl.cxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ddectrl.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <svtools/svdde.hxx> +#include "ddectrl.hxx" +#ifndef _SBERRORS_HXX +#include <basic/sberrors.hxx> +#endif + +#define DDE_FREECHANNEL ((DdeConnection*)0xffffffff) + +#define DDE_FIRSTERR 0x4000 +#define DDE_LASTERR 0x4011 + +static const SbError nDdeErrMap[] = +{ + /* DMLERR_ADVACKTIMEOUT */ 0x4000, SbERR_DDE_TIMEOUT, + /* DMLERR_BUSY */ 0x4001, SbERR_DDE_BUSY, + /* DMLERR_DATAACKTIMEOUT */ 0x4002, SbERR_DDE_TIMEOUT, + /* DMLERR_DLL_NOT_INITIALIZED */ 0x4003, SbERR_DDE_ERROR, + /* DMLERR_DLL_USAGE */ 0x4004, SbERR_DDE_ERROR, + /* DMLERR_EXECACKTIMEOUT */ 0x4005, SbERR_DDE_TIMEOUT, + /* DMLERR_INVALIDPARAMETER */ 0x4006, SbERR_DDE_ERROR, + /* DMLERR_LOW_MEMORY */ 0x4007, SbERR_DDE_ERROR, + /* DMLERR_MEMORY_ERROR */ 0x4008, SbERR_DDE_ERROR, + /* DMLERR_NOTPROCESSED */ 0x4009, SbERR_DDE_NOTPROCESSED, + /* DMLERR_NO_CONV_ESTABLISHED */ 0x400a, SbERR_DDE_NO_CHANNEL, + /* DMLERR_POKEACKTIMEOUT */ 0x400b, SbERR_DDE_TIMEOUT, + /* DMLERR_POSTMSG_FAILED */ 0x400c, SbERR_DDE_QUEUE_OVERFLOW, + /* DMLERR_REENTRANCY */ 0x400d, SbERR_DDE_ERROR, + /* DMLERR_SERVER_DIED */ 0x400e, SbERR_DDE_PARTNER_QUIT, + /* DMLERR_SYS_ERROR */ 0x400f, SbERR_DDE_ERROR, + /* DMLERR_UNADVACKTIMEOUT */ 0x4010, SbERR_DDE_TIMEOUT, + /* DMLERR_UNFOUND_QUEUE_ID */ 0x4011, SbERR_DDE_NO_CHANNEL +}; + +SbError SbiDdeControl::GetLastErr( DdeConnection* pConv ) +{ + if( !pConv ) + return 0; + long nErr = pConv->GetError(); + if( !nErr ) + return 0; + if( nErr < DDE_FIRSTERR || nErr > DDE_LASTERR ) + return SbERR_DDE_ERROR; + return nDdeErrMap[ 2*(nErr - DDE_FIRSTERR) + 1 ]; +} + +IMPL_LINK_INLINE( SbiDdeControl,Data , DdeData*, pData, +{ + aData = String::CreateFromAscii( (char*)(const void*)*pData ); + return 1; +} +) + +SbiDdeControl::SbiDdeControl() +{ + pConvList = new DdeConnections; + DdeConnection* pPtr = DDE_FREECHANNEL; + pConvList->Insert( pPtr ); +} + +SbiDdeControl::~SbiDdeControl() +{ + TerminateAll(); + delete pConvList; +} + +INT16 SbiDdeControl::GetFreeChannel() +{ + INT16 nListSize = (INT16)pConvList->Count(); + DdeConnection* pPtr = pConvList->First(); + pPtr = pConvList->Next(); // nullten eintrag ueberspringen + INT16 nChannel; + for( nChannel = 1; nChannel < nListSize; nChannel++ ) + { + if( pPtr == DDE_FREECHANNEL ) + return nChannel; + pPtr = pConvList->Next(); + } + pPtr = DDE_FREECHANNEL; + pConvList->Insert( pPtr, LIST_APPEND ); + return nChannel; +} + +SbError SbiDdeControl::Initiate( const String& rService, const String& rTopic, + INT16& rnHandle ) +{ + SbError nErr; + DdeConnection* pConv = new DdeConnection( rService, rTopic ); + nErr = GetLastErr( pConv ); + if( nErr ) + { + delete pConv; + rnHandle = 0; + } + else + { + INT16 nChannel = GetFreeChannel(); + pConvList->Replace( pConv, (ULONG)nChannel ); + rnHandle = nChannel; + } + return 0; +} + +SbError SbiDdeControl::Terminate( INT16 nChannel ) +{ + DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel ); + if( !nChannel || !pConv || pConv == DDE_FREECHANNEL ) + return SbERR_DDE_NO_CHANNEL; + pConvList->Replace( DDE_FREECHANNEL, (ULONG)nChannel ); + delete pConv; + return 0L; +} + +SbError SbiDdeControl::TerminateAll() +{ + INT16 nChannel = (INT16)pConvList->Count(); + while( nChannel ) + { + nChannel--; + Terminate( nChannel ); + } + + pConvList->Clear(); + DdeConnection* pPtr = DDE_FREECHANNEL; + pConvList->Insert( pPtr ); + + return 0; +} + +SbError SbiDdeControl::Request( INT16 nChannel, const String& rItem, String& rResult ) +{ + DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel ); + if( !nChannel || !pConv || pConv == DDE_FREECHANNEL ) + return SbERR_DDE_NO_CHANNEL; + + DdeRequest aRequest( *pConv, rItem, 30000 ); + aRequest.SetDataHdl( LINK( this, SbiDdeControl, Data ) ); + aRequest.Execute(); + rResult = aData; + return GetLastErr( pConv ); +} + +SbError SbiDdeControl::Execute( INT16 nChannel, const String& rCommand ) +{ + DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel ); + if( !nChannel || !pConv || pConv == DDE_FREECHANNEL ) + return SbERR_DDE_NO_CHANNEL; + DdeExecute aRequest( *pConv, rCommand, 30000 ); + aRequest.Execute(); + return GetLastErr( pConv ); +} + +SbError SbiDdeControl::Poke( INT16 nChannel, const String& rItem, const String& rData ) +{ + DdeConnection* pConv = pConvList->GetObject( (ULONG)nChannel ); + if( !nChannel || !pConv || pConv == DDE_FREECHANNEL ) + return SbERR_DDE_NO_CHANNEL; + DdePoke aRequest( *pConv, rItem, DdeData(rData), 30000 ); + aRequest.Execute(); + return GetLastErr( pConv ); +} + + diff --git a/basic/source/runtime/ddectrl.hxx b/basic/source/runtime/ddectrl.hxx new file mode 100644 index 000000000000..509e858683ec --- /dev/null +++ b/basic/source/runtime/ddectrl.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ddectrl.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DDECTRL_HXX +#define _DDECTRL_HXX + +#include <tools/link.hxx> +#ifndef _SBERRORS_HXX +#include <basic/sberrors.hxx> +#endif +#include <tools/string.hxx> + +class DdeConnection; +class DdeConnections; +class DdeData; + +class SbiDdeControl +{ +private: + DECL_LINK( Data, DdeData* ); + SbError GetLastErr( DdeConnection* ); + INT16 GetFreeChannel(); + DdeConnections* pConvList; + String aData; + +public: + + SbiDdeControl(); + ~SbiDdeControl(); + + SbError Initiate( const String& rService, const String& rTopic, + INT16& rnHandle ); + SbError Terminate( INT16 nChannel ); + SbError TerminateAll(); + SbError Request( INT16 nChannel, const String& rItem, String& rResult ); + SbError Execute( INT16 nChannel, const String& rCommand ); + SbError Poke( INT16 nChannel, const String& rItem, const String& rData ); +}; + +#endif diff --git a/basic/source/runtime/dllmgr.cxx b/basic/source/runtime/dllmgr.cxx new file mode 100644 index 000000000000..250c8778da9c --- /dev/null +++ b/basic/source/runtime/dllmgr.cxx @@ -0,0 +1,674 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dllmgr.cxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdlib.h> +#ifdef OS2 +#define INCL_DOSMODULEMGR +#include <svpm.h> +#endif + +#if defined( WIN ) || defined( WNT ) +#ifndef _SVWIN_H +#undef WB_LEFT +#undef WB_RIGHT +#include <tools/svwin.h> +#endif +#endif +#include <tools/debug.hxx> +#include <tools/string.hxx> +#include <tools/errcode.hxx> +#include <basic/sbxvar.hxx> +#include <basic/sbx.hxx> + +#if defined(WIN) +typedef HINSTANCE SbiDllHandle; +typedef FARPROC SbiDllProc; +#elif defined(WNT) +typedef HMODULE SbiDllHandle; +typedef int(*SbiDllProc)(); +#elif defined(OS2) +typedef HMODULE SbiDllHandle; +typedef PFN SbiDllProc; +#else +typedef void* SbiDllHandle; +typedef void* SbiDllProc; +#endif + +#define _DLLMGR_CXX +#include "dllmgr.hxx" +#include <basic/sberrors.hxx> + +#ifndef WINAPI +#ifdef WNT +#define WINAPI __far __pascal +#endif +#endif + +extern "C" { +#if defined(INTEL) && (defined(WIN) || defined(WNT)) + +extern INT16 WINAPI CallINT( SbiDllProc, char *stack, short nstack); +extern INT32 WINAPI CallLNG( SbiDllProc, char *stack, short nstack); +#ifndef WNT +extern float WINAPI CallSNG( SbiDllProc, char *stack, short nstack); +#endif +extern double WINAPI CallDBL( SbiDllProc, char *stack, short nstack); +extern char* WINAPI CallSTR( SbiDllProc, char *stack, short nstack); +// extern CallFIX( SbiDllProc, char *stack, short nstack); + +#else + +INT16 CallINT( SbiDllProc, char *, short ) { return 0; } +INT32 CallLNG( SbiDllProc, char *, short ) { return 0; } +float CallSNG( SbiDllProc, char *, short ) { return 0; } +double CallDBL( SbiDllProc, char *, short) { return 0; } +char* CallSTR( SbiDllProc, char *, short ) { return 0; } +#endif +} + +SV_IMPL_OP_PTRARR_SORT(ImplDllArr,ByteStringPtr) + +/* mit Optimierung An stuerzt unter Win95 folgendes Makro ab: +declare Sub MessageBeep Lib "user32" (ByVal long) +sub main + MessageBeep( 1 ) +end sub +*/ +#if defined (WNT) && defined (MSC) +//#pragma optimize ("", off) +#endif + +// +// *********************************************************************** +// + +class ImplSbiProc : public ByteString +{ + SbiDllProc pProc; + ImplSbiProc(); + ImplSbiProc( const ImplSbiProc& ); + +public: + ImplSbiProc( const ByteString& rName, SbiDllProc pFunc ) + : ByteString( rName ) { pProc = pFunc; } + SbiDllProc GetProc() const { return pProc; } +}; + +// +// *********************************************************************** +// + +class ImplSbiDll : public ByteString +{ + ImplDllArr aProcArr; + SbiDllHandle hDLL; + + ImplSbiDll( const ImplSbiDll& ); +public: + ImplSbiDll( const ByteString& rName, SbiDllHandle hHandle ) + : ByteString( rName ) { hDLL = hHandle; } + ~ImplSbiDll(); + SbiDllHandle GetHandle() const { return hDLL; } + SbiDllProc GetProc( const ByteString& rName ) const; + void InsertProc( const ByteString& rName, SbiDllProc pProc ); +}; + +ImplSbiDll::~ImplSbiDll() +{ + USHORT nCount = aProcArr.Count(); + for( USHORT nCur = 0; nCur < nCount; nCur++ ) + { + ImplSbiProc* pProc = (ImplSbiProc*)aProcArr.GetObject( nCur ); + delete pProc; + } +} + +SbiDllProc ImplSbiDll::GetProc( const ByteString& rName ) const +{ + USHORT nPos; + BOOL bRet = aProcArr.Seek_Entry( (ByteStringPtr)&rName, &nPos ); + if( bRet ) + { + ImplSbiProc* pImplProc = (ImplSbiProc*)aProcArr.GetObject(nPos); + return pImplProc->GetProc(); + } + return (SbiDllProc)0; +} + +void ImplSbiDll::InsertProc( const ByteString& rName, SbiDllProc pProc ) +{ + DBG_ASSERT(aProcArr.Seek_Entry((ByteStringPtr)&rName,0)==0,"InsertProc: Already in table"); + ImplSbiProc* pImplProc = new ImplSbiProc( rName, pProc ); + aProcArr.Insert( (ByteStringPtr)pImplProc ); +} + + +// +// *********************************************************************** +// + +SbiDllMgr::SbiDllMgr( const SbiDllMgr& ) +{ +} + +SbiDllMgr::SbiDllMgr() +{ +} + +SbiDllMgr::~SbiDllMgr() +{ + USHORT nCount = aDllArr.Count(); + for( USHORT nCur = 0; nCur < nCount; nCur++ ) + { + ImplSbiDll* pDll = (ImplSbiDll*)aDllArr.GetObject( nCur ); + FreeDllHandle( pDll->GetHandle() ); + delete pDll; + } +} + +void SbiDllMgr::FreeDll( const ByteString& rDllName ) +{ + USHORT nPos; + BOOL bRet = aDllArr.Seek_Entry( (ByteStringPtr)&rDllName, &nPos ); + if( bRet ) + { + ImplSbiDll* pDll = (ImplSbiDll*)aDllArr.GetObject(nPos); + FreeDllHandle( pDll->GetHandle() ); + delete pDll; + aDllArr.Remove( nPos, 1 ); + } +} + + +ImplSbiDll* SbiDllMgr::GetDll( const ByteString& rDllName ) +{ + USHORT nPos; + ImplSbiDll* pDll = 0; + BOOL bRet = aDllArr.Seek_Entry( (ByteStringPtr)&rDllName, &nPos ); + if( bRet ) + pDll = (ImplSbiDll*)aDllArr.GetObject(nPos); + else + { + SbiDllHandle hDll = CreateDllHandle( rDllName ); + if( hDll ) + { + pDll = new ImplSbiDll( rDllName, hDll ); + aDllArr.Insert( (ByteStringPtr)pDll ); + } + } + return pDll; +} + +SbiDllProc SbiDllMgr::GetProc( ImplSbiDll* pDll, const ByteString& rProcName ) +{ + DBG_ASSERT(pDll,"GetProc: No dll-ptr"); + SbiDllProc pProc; + pProc = pDll->GetProc( rProcName ); + if( !pProc ) + { + pProc = GetProcAddr( pDll->GetHandle(), rProcName ); + if( pProc ) + pDll->InsertProc( rProcName, pProc ); + } + return pProc; +} + + +SbError SbiDllMgr::Call( const char* pProcName, const char* pDllName, + SbxArray* pArgs, SbxVariable& rResult, BOOL bCDecl ) +{ + DBG_ASSERT(pProcName&&pDllName,"Call: Bad parms"); + SbError nSbErr = 0; + ByteString aDllName( pDllName ); + CheckDllName( aDllName ); + ImplSbiDll* pDll = GetDll( aDllName ); + if( pDll ) + { + SbiDllProc pProc = GetProc( pDll, pProcName ); + if( pProc ) + { + if( bCDecl ) + nSbErr = CallProcC( pProc, pArgs, rResult ); + else + nSbErr = CallProc( pProc, pArgs, rResult ); + } + else + nSbErr = SbERR_PROC_UNDEFINED; + } + else + nSbErr = SbERR_BAD_DLL_LOAD; + return nSbErr; +} + +// *********************************************************************** +// ******************* abhaengige Implementationen *********************** +// *********************************************************************** + +void SbiDllMgr::CheckDllName( ByteString& rDllName ) +{ +#if defined(WIN) || defined(WNT) || defined(OS2) + if( rDllName.Search('.') == STRING_NOTFOUND ) + rDllName += ".DLL"; +#else + (void)rDllName; +#endif +} + + +SbiDllHandle SbiDllMgr::CreateDllHandle( const ByteString& rDllName ) +{ + (void)rDllName; + +#if defined(UNX) + SbiDllHandle hLib=0; +#else + SbiDllHandle hLib; +#endif + +#if defined(WIN) + hLib = LoadLibrary( (const char*)rDllName ); + if( (ULONG)hLib < 32 ) + hLib = 0; + +#elif defined(WNT) + hLib = LoadLibrary( rDllName.GetBuffer() ); + if( !(ULONG)hLib ) + { +#ifdef DBG_UTIL + ULONG nLastErr; + nLastErr = GetLastError(); +#endif + hLib = 0; + } + +#elif defined(OS2) + char cErr[ 100 ]; + if( DosLoadModule( (PSZ) cErr, 100, (const char*)rDllName.GetBuffer(), &hLib ) ) + hLib = 0; +#endif + return hLib; +} + +void SbiDllMgr::FreeDllHandle( SbiDllHandle hLib ) +{ +#if defined(WIN) || defined(WNT) + if( hLib ) + FreeLibrary ((HINSTANCE) hLib); +#elif defined(OS2) + if( hLib ) + DosFreeModule( (HMODULE) hLib ); +#else + (void)hLib; +#endif +} + +SbiDllProc SbiDllMgr::GetProcAddr(SbiDllHandle hLib, const ByteString& rProcName) +{ + char buf1 [128] = ""; + char buf2 [128] = ""; + + SbiDllProc pProc = 0; + int nOrd = 0; + + // Ordinal? + if( rProcName.GetBuffer()[0] == '@' ) + nOrd = atoi( rProcName.GetBuffer()+1 ); + + // Moegliche Parameter weg: + DBG_ASSERT( sizeof(buf1) > rProcName.Len(), + "SbiDllMgr::GetProcAddr: buffer to small!" ); + strncpy( buf1, rProcName.GetBuffer(), sizeof(buf1)-1 ); + char *p = strchr( buf1, '#' ); + if( p ) + *p = 0; + + DBG_ASSERT( sizeof(buf2) > strlen(buf1) + 1, + "SbiDllMgr::GetProcAddr: buffer to small!" ); + strncpy( buf2, "_", sizeof(buf2)-1 ); + strncat( buf2, buf1, sizeof(buf2)-1-strlen(buf2) ); + +#if defined(WIN) || defined(WNT) + if( nOrd > 0 ) + pProc = (SbiDllProc)GetProcAddress( hLib, (char*)(long) nOrd ); + else + { + // 2. mit Parametern: + pProc = (SbiDllProc)GetProcAddress ( hLib, rProcName.GetBuffer() ); + // 3. nur der Name: + if (!pProc) + pProc = (SbiDllProc)GetProcAddress( hLib, buf1 ); + // 4. der Name mit Underline vorweg: + if( !pProc ) + pProc = (SbiDllProc)GetProcAddress( hLib, buf2 ); + } + +#elif defined(OS2) + PSZ pp; + APIRET rc; + // 1. Ordinal oder mit Parametern: + rc = DosQueryProcAddr( hLib, nOrd, pp = (char*)rProcName.GetBuffer(), &pProc ); + // 2. nur der Name: + if( rc ) + rc = DosQueryProcAddr( hLib, 0, pp = (PSZ)buf1, &pProc ); + // 3. der Name mit Underline vorweg: + if( rc ) + rc = DosQueryProcAddr( hLib, 0, pp = (PSZ)buf2, &pProc ); + if( rc ) + pProc = NULL; + else + { + // 16-bit oder 32-bit? + ULONG nInfo = 0; + if( DosQueryProcType( hLib, nOrd, pp, &nInfo ) ) + nInfo = 0;; + } +#else + (void)hLib; +#endif + return pProc; +} + +SbError SbiDllMgr::CallProc( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ) +{ +// ByteString aStr("Calling DLL at "); +// aStr += (ULONG)pProc; +// InfoBox( 0, aStr ).Execute(); + INT16 nInt16; int nInt; INT32 nInt32; double nDouble; + char* pStr; + + USHORT nSize; + char* pStack = (char*)CreateStack( pArgs, nSize ); + switch( rResult.GetType() ) + { + case SbxINTEGER: + nInt16 = CallINT(pProc, pStack, (short)nSize ); + rResult.PutInteger( nInt16 ); + break; + + case SbxUINT: + case SbxUSHORT: + nInt16 = (INT16)CallINT(pProc, pStack, (short)nSize ); + rResult.PutUShort( (USHORT)nInt16 ); + break; + + case SbxERROR: + nInt16 = (INT16)CallINT(pProc, pStack, (short)nSize ); + rResult.PutErr( (USHORT)nInt16 ); + break; + + case SbxINT: + nInt = CallINT(pProc, pStack, (short)nSize ); + rResult.PutInt( nInt ); + break; + + case SbxLONG: + nInt32 = CallLNG(pProc, pStack, (short)nSize ); + rResult.PutLong( nInt32 ); + break; + + case SbxULONG: + nInt32 = CallINT(pProc, pStack, (short)nSize ); + rResult.PutULong( (ULONG)nInt32 ); + break; + +#ifndef WNT + case SbxSINGLE: + { + float nSingle = CallSNG(pProc, pStack, (short)nSize ); + rResult.PutSingle( nSingle ); + break; + } +#endif + + case SbxDOUBLE: +#ifdef WNT + case SbxSINGLE: +#endif + nDouble = CallDBL(pProc, pStack, (short)nSize ); + rResult.PutDouble( nDouble ); + break; + + case SbxDATE: + nDouble = CallDBL(pProc, pStack, (short)nSize ); + rResult.PutDate( nDouble ); + break; + + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + nInt16 = CallINT(pProc, pStack, (short)nSize ); + rResult.PutByte( (BYTE)nInt16 ); + break; + + case SbxSTRING: + case SbxLPSTR: + pStr = CallSTR(pProc, pStack, (short)nSize ); + rResult.PutString( String::CreateFromAscii( pStr ) ); + break; + + case SbxNULL: + case SbxEMPTY: + nInt16 = CallINT(pProc, pStack, (short)nSize ); + // Rueckgabe nur zulaessig, wenn variant! + if( !rResult.IsFixed() ) + rResult.PutInteger( nInt16 ); + break; + + case SbxCURRENCY: + case SbxOBJECT: + case SbxDATAOBJECT: + default: + CallINT(pProc, pStack, (short)nSize ); + break; + } + delete [] pStack; + + if( pArgs ) + { + // die Laengen aller uebergebenen Strings anpassen + USHORT nCount = pArgs->Count(); + for( USHORT nCur = 1; nCur < nCount; nCur++ ) + { + SbxVariable* pVar = pArgs->Get( nCur ); + BOOL bIsString = ( pVar->GetType() == SbxSTRING ) || + ( pVar->GetType() == SbxLPSTR ); + + if( pVar->GetFlags() & SBX_REFERENCE ) + { + pVar->ResetFlag( SBX_REFERENCE ); // Sbx moechte es so + if( bIsString ) + { + ByteString aByteStr( (char*)pVar->GetUserData() ); + String aStr( aByteStr, gsl_getSystemTextEncoding() ); + pVar->PutString( aStr ); + } + } + if( bIsString ) + { + delete (char*)(pVar->GetUserData()); + pVar->SetUserData( 0 ); + } + } + } + return 0; +} + +SbError SbiDllMgr::CallProcC( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ) +{ + (void)pProc; + (void)pArgs; + (void)rResult; + + DBG_ERROR("C calling convention not supported"); + return SbERR_BAD_ARGUMENT; +} + +void* SbiDllMgr::CreateStack( SbxArray* pArgs, USHORT& rSize ) +{ + if( !pArgs ) + { + rSize = 0; + return 0; + } + char* pStack = new char[ 2048 ]; + char* pTop = pStack; + USHORT nCount = pArgs->Count(); + // erstes Element ueberspringen +#ifndef WIN + for( USHORT nCur = 1; nCur < nCount; nCur++ ) +#else + // unter 16-Bit Windows anders rum (OS/2 ?????) + for( USHORT nCur = nCount-1; nCur >= 1; nCur-- ) +#endif + { + SbxVariable* pVar = pArgs->Get( nCur ); + // AB 22.1.1996, Referenz + if( pVar->GetFlags() & SBX_REFERENCE ) // Es ist eine Referenz + { + switch( pVar->GetType() ) + { + case SbxINTEGER: + case SbxUINT: + case SbxINT: + case SbxUSHORT: + case SbxLONG: + case SbxULONG: + case SbxSINGLE: + case SbxDOUBLE: + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + *((void**)pTop) = (void*)&(pVar->aData); + pTop += sizeof( void* ); + break; + + case SbxSTRING: + case SbxLPSTR: + { + USHORT nLen = 256; + ByteString rStr( pVar->GetString(), gsl_getSystemTextEncoding() ); + if( rStr.Len() > 255 ) + nLen = rStr.Len() + 1; + + char* pStr = new char[ nLen ]; + strcpy( pStr, rStr.GetBuffer() ); // #100211# - checked + // ist nicht so sauber, aber wir sparen ein Pointerarray + DBG_ASSERT(sizeof(UINT32)>=sizeof(char*),"Gleich krachts im Basic"); + pVar->SetUserData( (sal_uIntPtr)pStr ); + *((const char**)pTop) = pStr; + pTop += sizeof( char* ); + } + break; + + case SbxNULL: + case SbxEMPTY: + case SbxERROR: + case SbxDATE: + case SbxCURRENCY: + case SbxOBJECT: + case SbxDATAOBJECT: + default: + break; + } + } + else + { + // ByVal + switch( pVar->GetType() ) + { + case SbxINTEGER: + case SbxUINT: + case SbxINT: + case SbxUSHORT: + *((INT16*)pTop) = pVar->GetInteger(); + pTop += sizeof( INT16 ); + break; + + case SbxLONG: + case SbxULONG: + *((INT32*)pTop) = pVar->GetLong(); + pTop += sizeof( INT32 ); + break; + + case SbxSINGLE: + *((float*)pTop) = pVar->GetSingle(); + pTop += sizeof( float ); + break; + + case SbxDOUBLE: + *((double*)pTop) = pVar->GetDouble(); + pTop += sizeof( double ); + break; + + case SbxSTRING: + case SbxLPSTR: + { + char* pStr = new char[ pVar->GetString().Len() + 1 ]; + ByteString aByteStr( pVar->GetString(), gsl_getSystemTextEncoding() ); + strcpy( pStr, aByteStr.GetBuffer() ); // #100211# - checked + // ist nicht so sauber, aber wir sparen ein Pointerarray + DBG_ASSERT(sizeof(UINT32)>=sizeof(char*),"Gleich krachts im Basic"); + pVar->SetUserData( (sal_uIntPtr)pStr ); + *((const char**)pTop) = pStr; + pTop += sizeof( char* ); + } + break; + + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + *((BYTE*)pTop) = pVar->GetByte(); + pTop += sizeof( BYTE ); + break; + + case SbxNULL: + case SbxEMPTY: + case SbxERROR: + case SbxDATE: + case SbxCURRENCY: + case SbxOBJECT: + case SbxDATAOBJECT: + default: + break; + } + } + } + rSize = (USHORT)((ULONG)pTop - (ULONG)pStack); + return pStack; +} + + + + diff --git a/basic/source/runtime/dllmgr.hxx b/basic/source/runtime/dllmgr.hxx new file mode 100644 index 000000000000..607abaa843fa --- /dev/null +++ b/basic/source/runtime/dllmgr.hxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dllmgr.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DLLMGR_HXX +#define _DLLMGR_HXX + +#define _SVSTDARR_BYTESTRINGSSORT +#include <svtools/svarray.hxx> +#ifndef _SVSTDARR_HXX //autogen +#include <svtools/svstdarr.hxx> +#endif + +// !!! nur zum debuggen fuer infoboxes !!! +//#ifndef _SV_HXX +//#include <sv.hxx> +//#endif + +//#ifndef _TOOLS_HXX +//#include <tools.hxx> +//#endif +#define _SVSTDARR_STRINGS +//#ifndef _SVSTDARR_HXX +//#include <svstdarr.hxx> +//#endif +#ifndef _SBERRORS_HXX +#include <basic/sberrors.hxx> +#endif + +class SbxArray; +class SbxVariable; + +class ImplSbiDll; +class ImplSbiProc; + +SV_DECL_PTRARR_SORT(ImplDllArr,ByteStringPtr,5,5) + +class SbiDllMgr +{ + ImplDllArr aDllArr; + + SbiDllMgr( const SbiDllMgr& ); + +#ifdef _DLLMGR_CXX + ImplSbiDll* GetDll( const ByteString& rDllName ); + SbiDllProc GetProc( ImplSbiDll*, const ByteString& rProcName ); + + SbiDllHandle CreateDllHandle( const ByteString& rDllName ); + void FreeDllHandle( SbiDllHandle ); + SbiDllProc GetProcAddr( SbiDllHandle, const ByteString& pProcName ); + SbError CallProc( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ); + SbError CallProcC( SbiDllProc pProc, SbxArray* pArgs, + SbxVariable& rResult ); + void* CreateStack( SbxArray* pArgs, USHORT& rSize ); + void CheckDllName( ByteString& rName ); +#endif + +public: + SbiDllMgr(); + ~SbiDllMgr(); + + SbError Call( const char* pFunc, const char* pDll, + SbxArray* pArgs, SbxVariable& rResult, + BOOL bCDecl ); + + void FreeDll( const ByteString& rDllName ); +}; + + + +#endif diff --git a/basic/source/runtime/inputbox.cxx b/basic/source/runtime/inputbox.cxx new file mode 100644 index 000000000000..a65b5d6d3786 --- /dev/null +++ b/basic/source/runtime/inputbox.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: inputbox.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#ifndef _SV_BUTTON_HXX //autogen +#include <vcl/button.hxx> +#endif +#include <vcl/fixed.hxx> +#include <vcl/edit.hxx> +#include <vcl/dialog.hxx> +#include <vcl/svapp.hxx> +#include "runtime.hxx" +#include "stdobj.hxx" +#include "rtlproto.hxx" + +class SvRTLInputBox : public ModalDialog +{ + Edit aEdit; + OKButton aOk; + CancelButton aCancel; + FixedText aPromptText; + String aText; + + void PositionDialog( long nXTwips, long nYTwips, const Size& rDlgSize ); + void InitButtons( const Size& rDlgSize ); + void PositionEdit( const Size& rDlgSize ); + void PositionPrompt( const String& rPrompt, const Size& rDlgSize ); + DECL_LINK( OkHdl, Button * ); + DECL_LINK( CancelHdl, Button * ); + +public: + SvRTLInputBox( Window* pParent, const String& rPrompt, const String& rTitle, + const String& rDefault, long nXTwips = -1, long nYTwips = -1 ); + String GetText() const { return aText; } +}; + +SvRTLInputBox::SvRTLInputBox( Window* pParent, const String& rPrompt, + const String& rTitle, const String& rDefault, + long nXTwips, long nYTwips ) : + ModalDialog( pParent,WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ), + aEdit( this, WB_LEFT | WB_BORDER ), + aOk( this ), aCancel( this ), aPromptText( this, WB_WORDBREAK ) +{ + SetMapMode( MapMode( MAP_APPFONT ) ); + Size aDlgSizeApp( 280, 80 ); + PositionDialog( nXTwips, nYTwips, aDlgSizeApp ); + InitButtons( aDlgSizeApp ); + PositionEdit( aDlgSizeApp ); + PositionPrompt( rPrompt, aDlgSizeApp ); + aOk.Show(); + aCancel.Show(); + aEdit.Show(); + aPromptText.Show(); + SetText( rTitle ); + Font aFont( GetFont()); + Color aColor( GetBackground().GetColor() ); + aFont.SetFillColor( aColor ); + aEdit.SetFont( aFont ); + aEdit.SetText( rDefault ); + aEdit.SetSelection( Selection( SELECTION_MIN, SELECTION_MAX ) ); +} + +void SvRTLInputBox::InitButtons( const Size& rDlgSize ) +{ + aOk.SetSizePixel( LogicToPixel( Size( 45, 15) )); + aCancel.SetSizePixel( LogicToPixel( Size( 45, 15) )); + Point aPos( rDlgSize.Width()-45-10, 5 ); + aOk.SetPosPixel( LogicToPixel( Point(aPos) )); + aPos.Y() += 16; + aCancel.SetPosPixel( LogicToPixel( Point(aPos) )); + aOk.SetClickHdl(LINK(this,SvRTLInputBox, OkHdl)); + aCancel.SetClickHdl(LINK(this,SvRTLInputBox,CancelHdl)); +} + +void SvRTLInputBox::PositionDialog(long nXTwips, long nYTwips, const Size& rDlgSize) +{ + SetSizePixel( LogicToPixel(rDlgSize) ); + if( nXTwips != -1 && nYTwips != -1 ) + { + Point aDlgPosApp( nXTwips, nYTwips ); + SetPosPixel( LogicToPixel( aDlgPosApp, MAP_TWIP ) ); + } +} + +void SvRTLInputBox::PositionEdit( const Size& rDlgSize ) +{ + aEdit.SetPosPixel( LogicToPixel( Point( 5,rDlgSize.Height()-35))); + aEdit.SetSizePixel( LogicToPixel( Size(rDlgSize.Width()-15,12))); +} + + +void SvRTLInputBox::PositionPrompt(const String& rPrompt,const Size& rDlgSize) +{ + if ( rPrompt.Len() == 0 ) + return; + String aText_( rPrompt ); + aText_.ConvertLineEnd( LINEEND_CR ); + aPromptText.SetPosPixel( LogicToPixel(Point(5,5))); + aPromptText.SetText( aText_ ); + Size aSize( rDlgSize ); + aSize.Width() -= 70; + aSize.Height() -= 50; + aPromptText.SetSizePixel( LogicToPixel(aSize)); +} + + +IMPL_LINK_INLINE_START( SvRTLInputBox, OkHdl, Button *, pButton ) +{ + (void)pButton; + + aText = aEdit.GetText(); + EndDialog( 1 ); + return 0; +} +IMPL_LINK_INLINE_END( SvRTLInputBox, OkHdl, Button *, pButton ) + +IMPL_LINK_INLINE_START( SvRTLInputBox, CancelHdl, Button *, pButton ) +{ + (void)pButton; + + aText.Erase(); + EndDialog( 0 ); + return 0; +} +IMPL_LINK_INLINE_END( SvRTLInputBox, CancelHdl, Button *, pButton ) + + +// ********************************************************************* +// ********************************************************************* +// ********************************************************************* + +// Syntax: String InputBox( Prompt, [Title], [Default] [, nXpos, nYpos ] ) + +RTLFUNC(InputBox) +{ + (void)pBasic; + (void)bWrite; + + ULONG nArgCount = rPar.Count(); + if ( nArgCount < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aTitle; + String aDefault; + INT32 nX = -1, nY = -1; // zentrieren + const String& rPrompt = rPar.Get(1)->GetString(); + if ( nArgCount > 2 && !rPar.Get(2)->IsErr() ) + aTitle = rPar.Get(2)->GetString(); + if ( nArgCount > 3 && !rPar.Get(3)->IsErr() ) + aDefault = rPar.Get(3)->GetString(); + if ( nArgCount > 4 ) + { + if ( nArgCount != 6 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + nX = rPar.Get(4)->GetLong(); + nY = rPar.Get(5)->GetLong(); + } + SvRTLInputBox *pDlg=new SvRTLInputBox(GetpApp()->GetDefDialogParent(), + rPrompt,aTitle,aDefault,nX,nY); + pDlg->Execute(); + rPar.Get(0)->PutString( pDlg->GetText() ); + delete pDlg; + } +} + + + diff --git a/basic/source/runtime/iosys.cxx b/basic/source/runtime/iosys.cxx new file mode 100644 index 000000000000..3e7bfb86bdf1 --- /dev/null +++ b/basic/source/runtime/iosys.cxx @@ -0,0 +1,1051 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: iosys.cxx,v $ + * $Revision: 1.30 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <vcl/dialog.hxx> +#include <vcl/edit.hxx> +#ifndef _SV_BUTTON_HXX //autogen +#include <vcl/button.hxx> +#endif +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <osl/security.h> +#include <osl/file.hxx> +#include <tools/urlobj.hxx> +#include <vos/mutex.hxx> + +#include "runtime.hxx" + +#ifdef _USE_UNO + +// <-- encoding +#include <sal/alloca.h> + +#include <ctype.h> +#include <rtl/byteseq.hxx> +#include <rtl/textenc.h> +#include <rtl/ustrbuf.hxx> +#include <rtl/textenc.h> +#include <rtl/ustrbuf.hxx> +// encoding --> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/bridge/XBridge.hpp> +#include <com/sun/star/bridge/XBridgeFactory.hpp> + +using namespace comphelper; +using namespace osl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::io; +using namespace com::sun::star::bridge; + +#endif /* _USE_UNO */ + +#include "iosys.hxx" +#include "sbintern.hxx" + +// Der Input-Dialog: + +class SbiInputDialog : public ModalDialog { + Edit aInput; + OKButton aOk; + CancelButton aCancel; + String aText; + DECL_LINK( Ok, Window * ); + DECL_LINK( Cancel, Window * ); +public: + SbiInputDialog( Window*, const String& ); + const String& GetInput() { return aText; } +}; + +SbiInputDialog::SbiInputDialog( Window* pParent, const String& rPrompt ) + :ModalDialog( pParent, WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ), + aInput( this, WB_3DLOOK | WB_LEFT | WB_BORDER ), + aOk( this ), aCancel( this ) +{ + SetText( rPrompt ); + aOk.SetClickHdl( LINK( this, SbiInputDialog, Ok ) ); + aCancel.SetClickHdl( LINK( this, SbiInputDialog, Cancel ) ); + SetMapMode( MapMode( MAP_APPFONT ) ); + + Point aPt = LogicToPixel( Point( 50, 50 ) ); + Size aSz = LogicToPixel( Size( 145, 65 ) ); + SetPosSizePixel( aPt, aSz ); + aPt = LogicToPixel( Point( 10, 10 ) ); + aSz = LogicToPixel( Size( 120, 12 ) ); + aInput.SetPosSizePixel( aPt, aSz ); + aPt = LogicToPixel( Point( 15, 30 ) ); + aSz = LogicToPixel( Size( 45, 15) ); + aOk.SetPosSizePixel( aPt, aSz ); + aPt = LogicToPixel( Point( 80, 30 ) ); + aSz = LogicToPixel( Size( 45, 15) ); + aCancel.SetPosSizePixel( aPt, aSz ); + + aInput.Show(); + aOk.Show(); + aCancel.Show(); +} + +IMPL_LINK_INLINE_START( SbiInputDialog, Ok, Window *, pWindow ) +{ + (void)pWindow; + + aText = aInput.GetText(); + EndDialog( 1 ); + return 0; +} +IMPL_LINK_INLINE_END( SbiInputDialog, Ok, Window *, pWindow ) + +IMPL_LINK_INLINE_START( SbiInputDialog, Cancel, Window *, pWindow ) +{ + (void)pWindow; + + EndDialog( 0 ); + return 0; +} +IMPL_LINK_INLINE_END( SbiInputDialog, Cancel, Window *, pWindow ) + +////////////////////////////////////////////////////////////////////////// + +SbiStream::SbiStream() + : pStrm( 0 ) +{ +} + +SbiStream::~SbiStream() +{ + delete pStrm; +} + +// Ummappen eines SvStream-Fehlers auf einen StarBASIC-Code + +void SbiStream::MapError() +{ + if( pStrm ) + switch( pStrm->GetError() ) + { + case SVSTREAM_OK: + nError = 0; break; + case SVSTREAM_FILE_NOT_FOUND: + nError = SbERR_FILE_NOT_FOUND; break; + case SVSTREAM_PATH_NOT_FOUND: + nError = SbERR_PATH_NOT_FOUND; break; + case SVSTREAM_TOO_MANY_OPEN_FILES: + nError = SbERR_TOO_MANY_FILES; break; + case SVSTREAM_ACCESS_DENIED: + nError = SbERR_ACCESS_DENIED; break; + case SVSTREAM_INVALID_PARAMETER: + nError = SbERR_BAD_ARGUMENT; break; + case SVSTREAM_OUTOFMEMORY: + nError = SbERR_NO_MEMORY; break; + default: + nError = SbERR_IO_ERROR; break; + } +} + +#ifdef _USE_UNO + +// TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx + +::rtl::OUString findUserInDescription( const ::rtl::OUString& aDescription ) +{ + ::rtl::OUString user; + + sal_Int32 index; + sal_Int32 lastIndex = 0; + + do + { + index = aDescription.indexOf((sal_Unicode) ',', lastIndex); + ::rtl::OUString token = (index == -1) ? aDescription.copy(lastIndex) : aDescription.copy(lastIndex, index - lastIndex); + + lastIndex = index + 1; + + sal_Int32 eindex = token.indexOf((sal_Unicode)'='); + ::rtl::OUString left = token.copy(0, eindex).toAsciiLowerCase().trim(); + ::rtl::OUString right = INetURLObject::decode( token.copy(eindex + 1).trim(), '%', + INetURLObject::DECODE_WITH_CHARSET ); + + if(left.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")))) + { + user = right; + break; + } + } + while(index != -1); + + return user; +} + +#endif + + +// Hack for #83750 +BOOL runsInSetup( void ); + +BOOL needSecurityRestrictions( void ) +{ +#ifdef _USE_UNO + static BOOL bNeedInit = TRUE; + static BOOL bRetVal = TRUE; + + if( bNeedInit ) + { + // Hack for #83750, use internal flag until + // setup provides own service manager + if( runsInSetup() ) + { + // Setup is not critical + bRetVal = FALSE; + return bRetVal; + } + + bNeedInit = FALSE; + + // Get system user to compare to portal user + oslSecurity aSecurity = osl_getCurrentSecurity(); + ::rtl::OUString aSystemUser; + sal_Bool bRet = osl_getUserName( aSecurity, &aSystemUser.pData ); + if( !bRet ) + { + // No valid security! -> Secure mode! + return TRUE; + } + + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + if( !xSMgr.is() ) + return TRUE; + Reference< XBridgeFactory > xBridgeFac( xSMgr->createInstance + ( ::rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" ) ), UNO_QUERY ); + + Sequence< Reference< XBridge > > aBridgeSeq; + sal_Int32 nBridgeCount = 0; + if( xBridgeFac.is() ) + { + aBridgeSeq = xBridgeFac->getExistingBridges(); + nBridgeCount = aBridgeSeq.getLength(); + } + + if( nBridgeCount == 0 ) + { + // No bridges -> local + bRetVal = FALSE; + return bRetVal; + } + + // Iterate through all bridges to find (portal) user property + const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray(); + bRetVal = FALSE; // Now only TRUE if user different from portal user is found + sal_Int32 i; + for( i = 0 ; i < nBridgeCount ; i++ ) + { + const Reference< XBridge >& rxBridge = pBridges[ i ]; + ::rtl::OUString aDescription = rxBridge->getDescription(); + ::rtl::OUString aPortalUser = findUserInDescription( aDescription ); + if( aPortalUser.getLength() > 0 ) + { + // User Found, compare to system user + if( aPortalUser == aSystemUser ) + { + // Same user -> system security is ok, bRetVal stays FALSE + break; + } + else + { + // Different user -> Secure mode! + bRetVal = TRUE; + break; + } + } + } + // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value) + } + + return bRetVal; +#else + return FALSE; +#endif +} + +// Returns TRUE if UNO is available, otherwise the old file +// system implementation has to be used +// #89378 New semantic: Don't just ask for UNO but for UCB +BOOL hasUno( void ) +{ +#ifdef _USE_UNO + static BOOL bNeedInit = TRUE; + static BOOL bRetVal = TRUE; + + if( bNeedInit ) + { + bNeedInit = FALSE; + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + if( !xSMgr.is() ) + { + // No service manager at all + bRetVal = FALSE; + } + else + { + Reference< XContentProviderManager > xManager( xSMgr->createInstance( ::rtl::OUString::createFromAscii + ( "com.sun.star.ucb.UniversalContentBroker" ) ), UNO_QUERY ); + + if ( !( xManager.is() && xManager->queryContentProvider( ::rtl::OUString::createFromAscii( "file:///" ) ).is() ) ) + { + // No UCB + bRetVal = FALSE; + } + } + } + return bRetVal; +#else + return FALSE; +#endif +} + + + +#ifndef _OLD_FILE_IMPL + +class OslStream : public SvStream +{ + File maFile; + short mnStrmMode; + +public: + OslStream( const String& rName, short nStrmMode ); + ~OslStream(); + virtual ULONG GetData( void* pData, ULONG nSize ); + virtual ULONG PutData( const void* pData, ULONG nSize ); + virtual ULONG SeekPos( ULONG nPos ); + virtual void FlushData(); + virtual void SetSize( ULONG nSize ); +}; + +OslStream::OslStream( const String& rName, short nStrmMode ) + : maFile( rName ) + , mnStrmMode( nStrmMode ) +{ + sal_uInt32 nFlags; + + if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) ) + { + nFlags = OpenFlag_Read | OpenFlag_Write; + } + else if( nStrmMode & STREAM_WRITE ) + { + nFlags = OpenFlag_Write; + } + else //if( nStrmMode & STREAM_READ ) + { + nFlags = OpenFlag_Read; + } + + FileBase::RC nRet = maFile.open( nFlags ); + if( nRet == FileBase::E_NOENT && nFlags != OpenFlag_Read ) + { + nFlags |= OpenFlag_Create; + nRet = maFile.open( nFlags ); + } + + if( nRet != FileBase::E_None ) + { + SetError( ERRCODE_IO_GENERAL ); + } +} + + +OslStream::~OslStream() +{ + maFile.close(); +} + +ULONG OslStream::GetData( void* pData, ULONG nSize ) +{ + sal_uInt64 nBytesRead = nSize; + FileBase::RC nRet = FileBase::E_None; + nRet = maFile.read( pData, nBytesRead, nBytesRead ); + return (ULONG)nBytesRead; +} + +ULONG OslStream::PutData( const void* pData, ULONG nSize ) +{ + sal_uInt64 nBytesWritten; + FileBase::RC nRet = FileBase::E_None; + nRet = maFile.write( pData, (sal_uInt64)nSize, nBytesWritten ); + return (ULONG)nBytesWritten; +} + +ULONG OslStream::SeekPos( ULONG nPos ) +{ + FileBase::RC nRet; + if( nPos == STREAM_SEEK_TO_END ) + { + nRet = maFile.setPos( Pos_End, 0 ); + } + else + { + nRet = maFile.setPos( Pos_Absolut, (sal_uInt64)nPos ); + } + sal_uInt64 nRealPos; + nRet = maFile.getPos( nRealPos ); + return sal::static_int_cast<ULONG>(nRealPos); +} + +void OslStream::FlushData() +{ +} + +void OslStream::SetSize( ULONG nSize ) +{ + FileBase::RC nRet = FileBase::E_None; + nRet = maFile.setSize( (sal_uInt64)nSize ); +} + +#endif + + +#ifdef _USE_UNO + +class UCBStream : public SvStream +{ + Reference< XInputStream > xIS; + Reference< XOutputStream > xOS; + Reference< XStream > xS; + Reference< XSeekable > xSeek; +public: + UCBStream( Reference< XInputStream > & xIS ); + UCBStream( Reference< XOutputStream > & xOS ); + UCBStream( Reference< XStream > & xS ); + ~UCBStream(); + virtual ULONG GetData( void* pData, ULONG nSize ); + virtual ULONG PutData( const void* pData, ULONG nSize ); + virtual ULONG SeekPos( ULONG nPos ); + virtual void FlushData(); + virtual void SetSize( ULONG nSize ); +}; + +/* +ULONG UCBErrorToSvStramError( ucb::IOErrorCode nError ) +{ + ULONG eReturn = ERRCODE_IO_GENERAL; + switch( nError ) + { + case ucb::IOErrorCode_ABORT: eReturn = SVSTREAM_GENERALERROR; break; + case ucb::IOErrorCode_NOT_EXISTING: eReturn = SVSTREAM_FILE_NOT_FOUND; break; + case ucb::IOErrorCode_NOT_EXISTING_PATH: eReturn = SVSTREAM_PATH_NOT_FOUND; break; + case ucb::IOErrorCode_OUT_OF_FILE_HANDLES: eReturn = SVSTREAM_TOO_MANY_OPEN_FILES; break; + case ucb::IOErrorCode_ACCESS_DENIED: eReturn = SVSTREAM_ACCESS_DENIED; break; + case ucb::IOErrorCode_LOCKING_VIOLATION: eReturn = SVSTREAM_SHARING_VIOLATION; break; + + case ucb::IOErrorCode_INVALID_ACCESS: eReturn = SVSTREAM_INVALID_ACCESS; break; + case ucb::IOErrorCode_CANT_CREATE: eReturn = SVSTREAM_CANNOT_MAKE; break; + case ucb::IOErrorCode_INVALID_PARAMETER: eReturn = SVSTREAM_INVALID_PARAMETER; break; + + case ucb::IOErrorCode_CANT_READ: eReturn = SVSTREAM_READ_ERROR; break; + case ucb::IOErrorCode_CANT_WRITE: eReturn = SVSTREAM_WRITE_ERROR; break; + case ucb::IOErrorCode_CANT_SEEK: eReturn = SVSTREAM_SEEK_ERROR; break; + case ucb::IOErrorCode_CANT_TELL: eReturn = SVSTREAM_TELL_ERROR; break; + + case ucb::IOErrorCode_OUT_OF_MEMORY: eReturn = SVSTREAM_OUTOFMEMORY; break; + + case SVSTREAM_FILEFORMAT_ERROR: eReturn = SVSTREAM_FILEFORMAT_ERROR; break; + case ucb::IOErrorCode_WRONG_VERSION: eReturn = SVSTREAM_WRONGVERSION; + case ucb::IOErrorCode_OUT_OF_DISK_SPACE: eReturn = SVSTREAM_DISK_FULL; break; + + case ucb::IOErrorCode_BAD_CRC: eReturn = ERRCODE_IO_BADCRC; break; + } + return eReturn; +} +*/ + +UCBStream::UCBStream( Reference< XInputStream > & rStm ) + : xIS( rStm ) + , xSeek( rStm, UNO_QUERY ) +{ +} + +UCBStream::UCBStream( Reference< XOutputStream > & rStm ) + : xOS( rStm ) + , xSeek( rStm, UNO_QUERY ) +{ +} + +UCBStream::UCBStream( Reference< XStream > & rStm ) + : xS( rStm ) + , xSeek( rStm, UNO_QUERY ) +{ +} + + +UCBStream::~UCBStream() +{ + try + { + if( xIS.is() ) + xIS->closeInput(); + else if( xOS.is() ) + xOS->closeOutput(); + else if( xS.is() ) + { + Reference< XInputStream > xIS_ = xS->getInputStream(); + if( xIS_.is() ) + xIS_->closeInput(); + } + } + catch( Exception & ) + { + SetError( ERRCODE_IO_GENERAL ); + } +} + +ULONG UCBStream::GetData( void* pData, ULONG nSize ) +{ + try + { + Reference< XInputStream > xISFromS; + if( xIS.is() ) + { + Sequence<sal_Int8> aData; + nSize = xIS->readBytes( aData, nSize ); + rtl_copyMemory( pData, aData.getConstArray(), nSize ); + return nSize; + } + else if( xS.is() && (xISFromS = xS->getInputStream()).is() ) + { + Sequence<sal_Int8> aData; + nSize = xISFromS->readBytes( aData, nSize ); + rtl_copyMemory( pData, aData.getConstArray(), nSize ); + return nSize; + } + else + SetError( ERRCODE_IO_GENERAL ); + } + catch( Exception & ) + { + SetError( ERRCODE_IO_GENERAL ); + } + return 0; +} + +ULONG UCBStream::PutData( const void* pData, ULONG nSize ) +{ + try + { + Reference< XOutputStream > xOSFromS; + if( xOS.is() ) + { + Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize ); + xOS->writeBytes( aData ); + return nSize; + } + else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() ) + { + Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize ); + xOSFromS->writeBytes( aData ); + return nSize; + } + else + SetError( ERRCODE_IO_GENERAL ); + } + catch( Exception & ) + { + SetError( ERRCODE_IO_GENERAL ); + } + return 0; +} + +ULONG UCBStream::SeekPos( ULONG nPos ) +{ + try + { + if( xSeek.is() ) + { + ULONG nLen = sal::static_int_cast<ULONG>( xSeek->getLength() ); + if( nPos > nLen ) + nPos = nLen; + xSeek->seek( nPos ); + return nPos; + } + else + SetError( ERRCODE_IO_GENERAL ); + } + catch( Exception & ) + { + SetError( ERRCODE_IO_GENERAL ); + } + return 0; +} + +void UCBStream::FlushData() +{ + try + { + Reference< XOutputStream > xOSFromS; + if( xOS.is() ) + xOS->flush(); + else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() ) + xOSFromS->flush(); + else + SetError( ERRCODE_IO_GENERAL ); + } + catch( Exception & ) + { + SetError( ERRCODE_IO_GENERAL ); + } +} + +void UCBStream::SetSize( ULONG nSize ) +{ + (void)nSize; + + DBG_ERROR( "not allowed to call from basic" ); + SetError( ERRCODE_IO_GENERAL ); +} + +#endif + +// Oeffnen eines Streams +SbError SbiStream::Open +( short nCh, const ByteString& rName, short nStrmMode, short nFlags, short nL ) +{ + nMode = nFlags; + nLen = nL; + nChan = nCh; + nLine = 0; + nExpandOnWriteTo = 0; + if( ( nStrmMode & ( STREAM_READ|STREAM_WRITE ) ) == STREAM_READ ) + nStrmMode |= STREAM_NOCREATE; + String aStr( rName, gsl_getSystemTextEncoding() ); + String aNameStr = getFullPath( aStr ); + +#ifdef _USE_UNO + if( hasUno() ) + { + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + if( xSMgr.is() ) + { + Reference< XSimpleFileAccess > + xSFI( xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); + if( xSFI.is() ) + { + try + { + + // #??? For write access delete file if it already exists (not for appending) + if( (nStrmMode & STREAM_WRITE) != 0 && !IsAppend() && !IsBinary() && + xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) ) + { + xSFI->kill( aNameStr ); + } + + if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) ) + { + Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr ); + pStrm = new UCBStream( xIS ); + } + else if( nStrmMode & STREAM_WRITE ) + { + Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr ); + pStrm = new UCBStream( xIS ); + // Open for writing is not implemented in ucb yet!!! + //Reference< XOutputStream > xIS = xSFI->openFileWrite( aNameStr ); + //pStrm = new UCBStream( xIS ); + } + else //if( nStrmMode & STREAM_READ ) + { + Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr ); + pStrm = new UCBStream( xIS ); + } + + } + catch( Exception & ) + { + nError = ERRCODE_IO_GENERAL; + } + } + } + } + +#endif + if( !pStrm ) + { +#ifdef _OLD_FILE_IMPL + pStrm = new SvFileStream( aNameStr, nStrmMode ); +#else + pStrm = new OslStream( aNameStr, nStrmMode ); +#endif + } + if( IsAppend() ) + pStrm->Seek( STREAM_SEEK_TO_END ); + MapError(); + if( nError ) + delete pStrm, pStrm = NULL; + return nError; +} + +SbError SbiStream::Close() +{ + if( pStrm ) + { + if( !hasUno() ) + { +#ifdef _OLD_FILE_IMPL + ((SvFileStream *)pStrm)->Close(); +#endif + } + MapError(); + delete pStrm; + pStrm = NULL; + } + nChan = 0; + return nError; +} + +SbError SbiStream::Read( ByteString& rBuf, USHORT n, bool bForceReadingPerByte ) +{ + nExpandOnWriteTo = 0; + if( !bForceReadingPerByte && IsText() ) + { + pStrm->ReadLine( rBuf ); + nLine++; + } + else + { + if( !n ) n = nLen; + if( !n ) + return nError = SbERR_BAD_RECORD_LENGTH; + rBuf.Fill( n, ' ' ); + pStrm->Read( (void*)rBuf.GetBuffer(), n ); + } + MapError(); + if( !nError && pStrm->IsEof() ) + nError = SbERR_READ_PAST_EOF; + return nError; +} + +SbError SbiStream::Read( char& ch ) +{ + nExpandOnWriteTo = 0; + if( !aLine.Len() ) + { + Read( aLine, 0 ); + aLine += '\n'; + } + ch = aLine.GetBuffer()[0]; + aLine.Erase( 0, 1 ); + return nError; +} + +void SbiStream::ExpandFile() +{ + if ( nExpandOnWriteTo ) + { + ULONG nCur = pStrm->Seek(STREAM_SEEK_TO_END); + if( nCur < nExpandOnWriteTo ) + { + ULONG nDiff = nExpandOnWriteTo - nCur; + char c = 0; + while( nDiff-- ) + *pStrm << c; + } + else + { + pStrm->Seek( nExpandOnWriteTo ); + } + nExpandOnWriteTo = 0; + } +} + +SbError SbiStream::Write( const ByteString& rBuf, USHORT n ) +{ + ExpandFile(); + if( IsAppend() ) + pStrm->Seek( STREAM_SEEK_TO_END ); + + if( IsText() ) + { + aLine += rBuf; + // Raus damit, wenn das Ende ein LF ist, aber CRLF vorher + // strippen, da der SvStrm ein CRLF anfuegt! + USHORT nLineLen = aLine.Len(); + if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0A ) + { + aLine.Erase( nLineLen ); + if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0D ) + aLine.Erase( nLineLen ); + pStrm->WriteLines( aLine ); + aLine.Erase(); + } + } + else + { + if( !n ) n = nLen; + if( !n ) + return nError = SbERR_BAD_RECORD_LENGTH; + pStrm->Write( rBuf.GetBuffer(), n ); + MapError(); + } + return nError; +} + +////////////////////////////////////////////////////////////////////////// + +// Zugriff auf das aktuelle I/O-System: + +SbiIoSystem* SbGetIoSystem() +{ + SbiInstance* pInst = pINST; + return pInst ? pInst->GetIoSystem() : NULL; +} + +////////////////////////////////////////////////////////////////////////// + +SbiIoSystem::SbiIoSystem() +{ + for( short i = 0; i < CHANNELS; i++ ) + pChan[ i ] = NULL; + nChan = 0; + nError = 0; +} + +SbiIoSystem::~SbiIoSystem() +{ + Shutdown(); +} + +SbError SbiIoSystem::GetError() +{ + SbError n = nError; nError = 0; + return n; +} + +void SbiIoSystem::Open + ( short nCh, const ByteString& rName, short nMode, short nFlags, short nLen ) +{ + nError = 0; + if( nCh >= CHANNELS || !nCh ) + nError = SbERR_BAD_CHANNEL; + else if( pChan[ nCh ] ) + nError = SbERR_FILE_ALREADY_OPEN; + else + { + pChan[ nCh ] = new SbiStream; + nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen ); + if( nError ) + delete pChan[ nCh ], pChan[ nCh ] = NULL; + } + nChan = 0; +} + +// Aktuellen Kanal schliessen + +void SbiIoSystem::Close() +{ + if( !nChan ) + nError = SbERR_BAD_CHANNEL; + else if( !pChan[ nChan ] ) + nError = SbERR_BAD_CHANNEL; + else + { + nError = pChan[ nChan ]->Close(); + delete pChan[ nChan ]; + pChan[ nChan ] = NULL; + } + nChan = 0; +} + +// Shutdown nach Programmlauf + +void SbiIoSystem::Shutdown() +{ + for( short i = 1; i < CHANNELS; i++ ) + { + if( pChan[ i ] ) + { + SbError n = pChan[ i ]->Close(); + delete pChan[ i ]; + pChan[ i ] = NULL; + if( n && !nError ) + nError = n; + } + } + nChan = 0; + // Noch was zu PRINTen? + if( aOut.Len() ) + { + String aOutStr( aOut, gsl_getSystemTextEncoding() ); +#if defined GCC + Window* pParent = Application::GetDefDialogParent(); + MessBox( pParent, WinBits( WB_OK ), String(), aOutStr ).Execute(); +#else + MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), String(), aOutStr ).Execute(); +#endif + } + aOut.Erase(); +} + +// Aus aktuellem Kanal lesen + +void SbiIoSystem::Read( ByteString& rBuf, short n ) +{ + if( !nChan ) + ReadCon( rBuf ); + else if( !pChan[ nChan ] ) + nError = SbERR_BAD_CHANNEL; + else + nError = pChan[ nChan ]->Read( rBuf, n ); +} + +char SbiIoSystem::Read() +{ + char ch = ' '; + if( !nChan ) + { + if( !aIn.Len() ) + { + ReadCon( aIn ); + aIn += '\n'; + } + ch = aIn.GetBuffer()[0]; + aIn.Erase( 0, 1 ); + } + else if( !pChan[ nChan ] ) + nError = SbERR_BAD_CHANNEL; + else + nError = pChan[ nChan ]->Read( ch ); + return ch; +} + +void SbiIoSystem::Write( const ByteString& rBuf, short n ) +{ + if( !nChan ) + WriteCon( rBuf ); + else if( !pChan[ nChan ] ) + nError = SbERR_BAD_CHANNEL; + else + nError = pChan[ nChan ]->Write( rBuf, n ); +} + +short SbiIoSystem::NextChannel() +{ + for( short i = 1; i < CHANNELS; i++ ) + { + if( !pChan[ i ] ) + return i; + } + nError = SbERR_TOO_MANY_FILES; + return CHANNELS; +} + +// nChannel == 0..CHANNELS-1 + +SbiStream* SbiIoSystem::GetStream( short nChannel ) const +{ + SbiStream* pRet = 0; + if( nChannel >= 0 && nChannel < CHANNELS ) + pRet = pChan[ nChannel ]; + return pRet; +} + +void SbiIoSystem::CloseAll(void) +{ + for( short i = 1; i < CHANNELS; i++ ) + { + if( pChan[ i ] ) + { + SbError n = pChan[ i ]->Close(); + delete pChan[ i ]; + pChan[ i ] = NULL; + if( n && !nError ) + nError = n; + } + } +} + +/*************************************************************************** +* +* Console Support +* +***************************************************************************/ + +// Einlesen einer Zeile von der Console + +void SbiIoSystem::ReadCon( ByteString& rIn ) +{ + String aPromptStr( aPrompt, gsl_getSystemTextEncoding() ); + SbiInputDialog aDlg( NULL, aPromptStr ); + if( aDlg.Execute() ) + rIn = ByteString( aDlg.GetInput(), gsl_getSystemTextEncoding() ); + else + nError = SbERR_USER_ABORT; + aPrompt.Erase(); +} + +// Ausgabe einer MessageBox, wenn im Console-Puffer ein CR ist + +void SbiIoSystem::WriteCon( const ByteString& rText ) +{ + aOut += rText; + USHORT n1 = aOut.Search( '\n' ); + USHORT n2 = aOut.Search( '\r' ); + if( n1 != STRING_NOTFOUND || n2 != STRING_NOTFOUND ) + { + if( n1 == STRING_NOTFOUND ) n1 = n2; + else + if( n2 == STRING_NOTFOUND ) n2 = n1; + if( n1 > n2 ) n1 = n2; + ByteString s( aOut.Copy( 0, n1 ) ); + aOut.Erase( 0, n1 ); + while( aOut.GetBuffer()[0] == '\n' || aOut.GetBuffer()[0] == '\r' ) + aOut.Erase( 0, 1 ); + String aStr( s, gsl_getSystemTextEncoding() ); + { + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + if( !MessBox( GetpApp()->GetDefDialogParent(), + WinBits( WB_OK_CANCEL | WB_DEF_OK ), + String(), aStr ).Execute() ) + nError = SbERR_USER_ABORT; + } + } +} + diff --git a/basic/source/runtime/makefile.mk b/basic/source/runtime/makefile.mk new file mode 100644 index 000000000000..9c9886e05f94 --- /dev/null +++ b/basic/source/runtime/makefile.mk @@ -0,0 +1,93 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=runtime + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + + +# --- Allgemein ----------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/basrdll.obj \ + $(SLO)$/inputbox.obj \ + $(SLO)$/runtime.obj \ + $(SLO)$/step0.obj \ + $(SLO)$/step1.obj \ + $(SLO)$/step2.obj \ + $(SLO)$/iosys.obj \ + $(SLO)$/stdobj.obj \ + $(SLO)$/stdobj1.obj \ + $(SLO)$/methods.obj \ + $(SLO)$/methods1.obj \ + $(SLO)$/props.obj \ + $(SLO)$/ddectrl.obj \ + $(SLO)$/dllmgr.obj + +.IF "$(GUI)$(CPU)" == "WINI" +SLOFILES+= $(SLO)$/win.obj +.ENDIF + +.IF "$(GUI)$(COM)$(CPU)" == "WNTMSCI" +SLOFILES+= $(SLO)$/wnt.obj +.ENDIF + +.IF "$(GUI)$(COM)$(CPU)" == "WNTGCCI" +SLOFILES+= $(SLO)$/wnt-mingw.obj +.ENDIF + +.IF "$(GUI)$(CPU)" == "OS2I" +#FIXME SLOFILES+= $(SLO)$/os2.obj +.ENDIF + +EXCEPTIONSFILES=$(SLO)$/step0.obj \ + $(SLO)$/step2.obj \ + $(SLO)$/methods.obj \ + $(SLO)$/methods1.obj \ + $(SLO)$/iosys.obj \ + $(SLO)$/runtime.obj + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + +$(SLO)$/%.obj: %.s +#kendy: Cut'n'paste from bridges/source/cpp_uno/mingw_intel/makefile.mk +#cmc: Ideally --noexecstack would be in operations, but with #i51385# pyuno +#remote bridgeing breaks +# $(CC) -Wa,--noexecstack -c -o $(SLO)$/$(@:b).o $< + $(CC) -c -o $(SLO)$/$(@:b).obj $< + touch $@ diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx new file mode 100644 index 000000000000..e92c8c974eb2 --- /dev/null +++ b/basic/source/runtime/methods.cxx @@ -0,0 +1,4547 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: methods.cxx,v $ + * $Revision: 1.82 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include <tools/date.hxx> +#include <basic/sbxvar.hxx> +#ifndef _VOS_PROCESS_HXX +#include <vos/process.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <vcl/sound.hxx> +#include <vcl/wintypes.hxx> +#include <vcl/msgbox.hxx> +#include <basic/sbx.hxx> +#include <svtools/zforlist.hxx> +#include <rtl/math.hxx> +#include <tools/urlobj.hxx> +#include <osl/time.h> +#include <unotools/charclass.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <tools/wldcrd.hxx> +#include <i18npool/lang.h> + +#include "runtime.hxx" +#include "sbunoobj.hxx" +#ifdef WNT +#include <tools/prewin.h> +#include "winbase.h" +#include <tools/postwin.h> +#ifndef _FSYS_HXX //autogen +#include <tools/fsys.hxx> +#endif +#else +#include <osl/file.hxx> +#endif + +#ifdef _USE_UNO +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess3.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> + +using namespace comphelper; +using namespace osl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::io; + +#endif /* _USE_UNO */ + +//#define _ENABLE_CUR_DIR + +#include "stdobj.hxx" +#include <basic/sbstdobj.hxx> +#include "rtlproto.hxx" +#include "basrid.hxx" +#include "image.hxx" +#include "sb.hrc" +#include "iosys.hxx" +#include "ddectrl.hxx" +#include <sbintern.hxx> + +#include <list> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#if defined (WIN) || defined (WNT) || defined (OS2) +#include <direct.h> // _getdcwd get current work directory, _chdrive +#endif + +#ifdef WIN +#include <dos.h> // _dos_getfileattr +#include <errno.h> +#endif + +#ifdef UNX +#include <errno.h> +#include <unistd.h> +#endif + +#ifdef WNT +#include <io.h> +#endif + +static void FilterWhiteSpace( String& rStr ) +{ + rStr.EraseAllChars( ' ' ); + rStr.EraseAllChars( '\t' ); + rStr.EraseAllChars( '\n' ); + rStr.EraseAllChars( '\r' ); +} + +static long GetDayDiff( const Date& rDate ) +{ + Date aRefDate( 1,1,1900 ); + long nDiffDays; + if ( aRefDate > rDate ) + { + nDiffDays = (long)(aRefDate - rDate); + nDiffDays *= -1; + } + else + nDiffDays = (long)(rDate - aRefDate); + nDiffDays += 2; // Anpassung VisualBasic: 1.Jan.1900 == 2 + return nDiffDays; +} + +static CharClass& GetCharClass( void ) +{ + static sal_Bool bNeedsInit = sal_True; + static ::com::sun::star::lang::Locale aLocale; + if( bNeedsInit ) + { + bNeedsInit = sal_False; + aLocale = Application::GetSettings().GetLocale(); + } + static CharClass aCharClass( aLocale ); + return aCharClass; +} + +static inline BOOL isFolder( FileStatus::Type aType ) +{ + return ( aType == FileStatus::Directory || aType == FileStatus::Volume ); +} + + +//*** UCB file access *** + +// Converts possibly relative paths to absolute paths +// according to the setting done by ChDir/ChDrive +String getFullPath( const String& aRelPath ) +{ + ::rtl::OUString aFileURL; + + // #80204 Try first if it already is a valid URL + INetURLObject aURLObj( aRelPath ); + aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE ); + + if( !aFileURL.getLength() ) + { + File::getFileURLFromSystemPath( aRelPath, aFileURL ); + } + + return aFileURL; +} + +// Sets (virtual) current path for UCB file access +void implChDir( const String& aDir ) +{ + (void)aDir; + // TODO +} + +// Sets (virtual) current drive for UCB file access +void implChDrive( const String& aDrive ) +{ + (void)aDrive; + // TODO +} + +// Returns (virtual) current path for UCB file access +String implGetCurDir( void ) +{ + String aRetStr; + + return aRetStr; +} + +// TODO: -> SbiGlobals +static Reference< XSimpleFileAccess3 > getFileAccess( void ) +{ + static Reference< XSimpleFileAccess3 > xSFI; + if( !xSFI.is() ) + { + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + if( xSMgr.is() ) + { + xSFI = Reference< XSimpleFileAccess3 >( xSMgr->createInstance + ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); + } + } + return xSFI; +} + + + +// Properties und Methoden legen beim Get (bPut = FALSE) den Returnwert +// im Element 0 des Argv ab; beim Put (bPut = TRUE) wird der Wert aus +// Element 0 gespeichert. + +// CreateObject( class ) + +RTLFUNC(CreateObject) +{ + (void)bWrite; + + String aClass( rPar.Get( 1 )->GetString() ); + SbxObjectRef p = SbxBase::CreateObject( aClass ); + if( !p ) + StarBASIC::Error( SbERR_CANNOT_LOAD ); + else + { + // Convenience: BASIC als Parent eintragen + p->SetParent( pBasic ); + rPar.Get( 0 )->PutObject( p ); + } +} + +// Error( n ) + +RTLFUNC(Error) +{ + (void)bWrite; + + if( !pBasic ) + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + else + { + String aErrorMsg; + SbError nErr = 0L; + if( rPar.Count() == 1 ) + { + nErr = StarBASIC::GetErrBasic(); + aErrorMsg = StarBASIC::GetErrorMsg(); + } + else + { + INT32 nCode = rPar.Get( 1 )->GetLong(); + if( nCode > 65535L ) + StarBASIC::Error( SbERR_CONVERSION ); + else + nErr = StarBASIC::GetSfxFromVBError( (USHORT)nCode ); + } + pBasic->MakeErrorText( nErr, aErrorMsg ); + rPar.Get( 0 )->PutString( pBasic->GetErrorText() ); + } +} + +// Sinus + +RTLFUNC(Sin) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + rPar.Get( 0 )->PutDouble( sin( pArg->GetDouble() ) ); + } +} + +// Cosinus + +RTLFUNC(Cos) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + rPar.Get( 0 )->PutDouble( cos( pArg->GetDouble() ) ); + } +} + +// Atn + +RTLFUNC(Atn) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + rPar.Get( 0 )->PutDouble( atan( pArg->GetDouble() ) ); + } +} + + + +RTLFUNC(Abs) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + rPar.Get( 0 )->PutDouble( fabs( pArg->GetDouble() ) ); + } +} + + +RTLFUNC(Asc) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + String aStr( pArg->GetString() ); + if ( aStr.Len() == 0 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + rPar.Get(0)->PutEmpty(); + } + else + { + sal_Unicode aCh = aStr.GetBuffer()[0]; + rPar.Get(0)->PutLong( aCh ); + } + } +} + +RTLFUNC(Chr) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + sal_Unicode aCh = (sal_Unicode)pArg->GetUShort(); + String aStr( aCh ); + rPar.Get(0)->PutString( aStr ); + } +} + + +#ifdef UNX +#define _MAX_PATH 260 +#define _PATH_INCR 250 +#endif + +RTLFUNC(CurDir) +{ + (void)pBasic; + (void)bWrite; + + // #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von + // der Anpassung an virtuelle URLs nich betroffen, da bei Nutzung der + // DirEntry-Funktionalitaet keine Moeglichkeit besteht, das aktuelle so + // zu ermitteln, dass eine virtuelle URL geliefert werden koennte. + +// rPar.Get(0)->PutEmpty(); +#if defined (WIN) || defined (WNT) || defined (OS2) + int nCurDir = 0; // Current dir // JSM + if ( rPar.Count() == 2 ) + { + String aDrive = rPar.Get(1)->GetString(); + if ( aDrive.Len() != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + else + { + nCurDir = (int)aDrive.GetBuffer()[0]; + if ( !isalpha( nCurDir ) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + else + nCurDir -= ( 'A' - 1 ); + } + } + char* pBuffer = new char[ _MAX_PATH ]; +#ifdef OS2 + if( !nCurDir ) + nCurDir = _getdrive(); +#endif + if ( _getdcwd( nCurDir, pBuffer, _MAX_PATH ) != 0 ) + rPar.Get(0)->PutString( String::CreateFromAscii( pBuffer ) ); + else + StarBASIC::Error( SbERR_NO_DEVICE ); + delete [] pBuffer; + +#elif defined( UNX ) + + int nSize = _PATH_INCR; + char* pMem; + while( TRUE ) + { + pMem = new char[nSize]; + if( !pMem ) + { + StarBASIC::Error( SbERR_NO_MEMORY ); + return; + } + if( getcwd( pMem, nSize-1 ) != NULL ) + { + rPar.Get(0)->PutString( String::CreateFromAscii(pMem) ); + delete [] pMem; + return; + } + if( errno != ERANGE ) + { + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + delete [] pMem; + return; + } + delete [] pMem; + nSize += _PATH_INCR; + }; + +#endif +} + +RTLFUNC(ChDir) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if (rPar.Count() == 2) + { +#ifdef _ENABLE_CUR_DIR + String aPath = rPar.Get(1)->GetString(); + BOOL bError = FALSE; +#ifdef WNT + // #55997 Laut MI hilft es bei File-URLs einen DirEntry zwischenzuschalten + // #40996 Harmoniert bei Verwendung der WIN32-Funktion nicht mit getdir + DirEntry aEntry( aPath ); + ByteString aFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() ); + if( chdir( aFullPath.GetBuffer()) ) + bError = TRUE; +#else + if (!DirEntry(aPath).SetCWD()) + bError = TRUE; +#endif + if( bError ) + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); +#endif + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(ChDrive) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if (rPar.Count() == 2) + { +#ifdef _ENABLE_CUR_DIR + // Keine Laufwerke in Unix +#ifndef UNX + String aPar1 = rPar.Get(1)->GetString(); + +#if defined (WIN) || defined (WNT) || defined (OS2) + if (aPar1.Len() > 0) + { + int nCurDrive = (int)aPar1.GetBuffer()[0]; ; + if ( !isalpha( nCurDrive ) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + else + nCurDrive -= ( 'A' - 1 ); + if (_chdrive(nCurDrive)) + StarBASIC::Error( SbERR_NO_DEVICE ); + } +#endif + +#endif + // #ifndef UNX +#endif + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + + +// Implementation of StepRENAME with UCB +void implStepRenameUCB( const String& aSource, const String& aDest ) +{ + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + String aSourceFullPath = getFullPath( aSource ); + if( !xSFI->exists( aSourceFullPath ) ) + { + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + return; + } + + String aDestFullPath = getFullPath( aDest ); + if( xSFI->exists( aDestFullPath ) ) + StarBASIC::Error( SbERR_FILE_EXISTS ); + else + xSFI->move( aSourceFullPath, aDestFullPath ); + } + catch( Exception & ) + { + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + } + } +} + +// Implementation of StepRENAME with OSL +void implStepRenameOSL( const String& aSource, const String& aDest ) +{ + FileBase::RC nRet = File::move( getFullPathUNC( aSource ), getFullPathUNC( aDest ) ); + if( nRet != FileBase::E_None ) + { + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + } +} + +RTLFUNC(FileCopy) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if (rPar.Count() == 3) + { + String aSource = rPar.Get(1)->GetString(); + String aDest = rPar.Get(2)->GetString(); + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) ); + } + catch( Exception & ) + { + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + DirEntry aSourceDirEntry(aSource); + if (aSourceDirEntry.Exists()) + { + if (aSourceDirEntry.CopyTo(DirEntry(aDest),FSYS_ACTION_COPYFILE) != FSYS_ERR_OK) + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + } + else + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); +#else + FileBase::RC nRet = File::copy( getFullPathUNC( aSource ), getFullPathUNC( aDest ) ); + if( nRet != FileBase::E_None ) + { + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + } +#endif + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(Kill) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if (rPar.Count() == 2) + { + String aFileSpec = rPar.Get(1)->GetString(); + + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + String aFullPath = getFullPath( aFileSpec ); + if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) ) + { + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + return; + } + try + { + xSFI->kill( aFullPath ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + if(DirEntry(aFileSpec).Kill() != FSYS_ERR_OK) + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); +#else + File::remove( getFullPathUNC( aFileSpec ) ); +#endif + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(MkDir) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if (rPar.Count() == 2) + { + String aPath = rPar.Get(1)->GetString(); + + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + xSFI->createFolder( getFullPath( aPath ) ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + if (!DirEntry(aPath).MakeDir()) + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); +#else + Directory::create( getFullPathUNC( aPath ) ); +#endif + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + + +#ifndef _OLD_FILE_IMPL + +// In OSL only empty directories can be deleted +// so we have to delete all files recursively +void implRemoveDirRecursive( const String& aDirPath ) +{ + DirectoryItem aItem; + FileBase::RC nRet = DirectoryItem::get( aDirPath, aItem ); + sal_Bool bExists = (nRet == FileBase::E_None); + + FileStatus aFileStatus( FileStatusMask_Type ); + nRet = aItem.getFileStatus( aFileStatus ); + FileStatus::Type aType = aFileStatus.getFileType(); + sal_Bool bFolder = isFolder( aType ); + + if( !bExists || !bFolder ) + { + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + return; + } + + Directory aDir( aDirPath ); + nRet = aDir.open(); + if( nRet != FileBase::E_None ) + { + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + return; + } + + for( ;; ) + { + DirectoryItem aItem2; + nRet = aDir.getNextItem( aItem2 ); + if( nRet != FileBase::E_None ) + break; + + // Handle flags + FileStatus aFileStatus2( FileStatusMask_Type | FileStatusMask_FileURL ); + nRet = aItem2.getFileStatus( aFileStatus2 ); + ::rtl::OUString aPath = aFileStatus2.getFileURL(); + + // Directory? + FileStatus::Type aType2 = aFileStatus2.getFileType(); + sal_Bool bFolder2 = isFolder( aType2 ); + if( bFolder2 ) + { + implRemoveDirRecursive( aPath ); + } + else + { + File::remove( aPath ); + } + } + nRet = aDir.close(); + + nRet = Directory::remove( aDirPath ); +} +#endif + + +RTLFUNC(RmDir) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if (rPar.Count() == 2) + { + String aPath = rPar.Get(1)->GetString(); + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + if( !xSFI->isFolder( aPath ) ) + { + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + return; + } + SbiInstance* pInst = pINST; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + Sequence< ::rtl::OUString > aContent = xSFI->getFolderContents( aPath, true ); + sal_Int32 nCount = aContent.getLength(); + if( nCount > 0 ) + { + StarBASIC::Error( SbERR_ACCESS_ERROR ); + return; + } + } + + xSFI->kill( getFullPath( aPath ) ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + DirEntry aDirEntry(aPath); + if (aDirEntry.Kill() != FSYS_ERR_OK) + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); +#else + implRemoveDirRecursive( getFullPathUNC( aPath ) ); +#endif + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(SendKeys) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); +} + +RTLFUNC(Exp) +{ + (void)pBasic; + (void)bWrite; + + if( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double aDouble = rPar.Get( 1 )->GetDouble(); + aDouble = exp( aDouble ); + checkArithmeticOverflow( aDouble ); + rPar.Get( 0 )->PutDouble( aDouble ); + } +} + +RTLFUNC(FileLen) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + String aStr( pArg->GetString() ); + INT32 nLen = 0; + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + nLen = xSFI->getSize( getFullPath( aStr ) ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + FileStat aStat = DirEntry( aStr ); + nLen = aStat.GetSize(); +#else + DirectoryItem aItem; + FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem ); + FileStatus aFileStatus( FileStatusMask_FileSize ); + nRet = aItem.getFileStatus( aFileStatus ); + nLen = (INT32)aFileStatus.getFileSize(); +#endif + } + rPar.Get(0)->PutLong( (long)nLen ); + } +} + + +RTLFUNC(Hex) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + char aBuffer[16]; + SbxVariableRef pArg = rPar.Get( 1 ); + if ( pArg->IsInteger() ) + snprintf( aBuffer, sizeof(aBuffer), "%X", pArg->GetInteger() ); + else + snprintf( aBuffer, sizeof(aBuffer), "%lX", static_cast<long unsigned int>(pArg->GetLong()) ); + rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) ); + } +} + +// InStr( [start],string,string,[compare] ) + +RTLFUNC(InStr) +{ + (void)pBasic; + (void)bWrite; + + ULONG nArgCount = rPar.Count()-1; + if ( nArgCount < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + USHORT nStartPos = 1; + + USHORT nFirstStringPos = 1; + if ( nArgCount >= 3 ) + { + INT32 lStartPos = rPar.Get(1)->GetLong(); + if( lStartPos <= 0 || lStartPos > 0xffff ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + lStartPos = 1; + } + nStartPos = (USHORT)lStartPos; + nFirstStringPos++; + } + + SbiInstance* pInst = pINST; + int bTextMode; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + SbiRuntime* pRT = pInst ? pInst->pRun : NULL; + bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE; + } + else + { + bTextMode = 1;; + } + if ( nArgCount == 4 ) + bTextMode = rPar.Get(4)->GetInteger(); + + USHORT nPos; + const String& rToken = rPar.Get(nFirstStringPos+1)->GetString(); + + // #97545 Always find empty string + if( !rToken.Len() ) + { + nPos = nStartPos; + } + else + { + if( !bTextMode ) + { + const String& rStr1 = rPar.Get(nFirstStringPos)->GetString(); + + nPos = rStr1.Search( rToken, nStartPos-1 ); + if ( nPos == STRING_NOTFOUND ) + nPos = 0; + else + nPos++; + } + else + { + String aStr1 = rPar.Get(nFirstStringPos)->GetString(); + String aToken = rToken; + + aStr1.ToUpperAscii(); + aToken.ToUpperAscii(); + + nPos = aStr1.Search( aToken, nStartPos-1 ); + if ( nPos == STRING_NOTFOUND ) + nPos = 0; + else + nPos++; + } + } + rPar.Get(0)->PutLong( nPos ); + } +} + + +// InstrRev(string1, string2[, start[, compare]]) + +RTLFUNC(InStrRev) +{ + (void)pBasic; + (void)bWrite; + + ULONG nArgCount = rPar.Count()-1; + if ( nArgCount < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr1 = rPar.Get(1)->GetString(); + String aToken = rPar.Get(2)->GetString(); + + INT32 lStartPos = -1; + if ( nArgCount >= 3 ) + { + lStartPos = rPar.Get(3)->GetLong(); + if( (lStartPos <= 0 && lStartPos != -1) || lStartPos > 0xffff ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + lStartPos = -1; + } + } + + SbiInstance* pInst = pINST; + int bTextMode; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + SbiRuntime* pRT = pInst ? pInst->pRun : NULL; + bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE; + } + else + { + bTextMode = 1;; + } + if ( nArgCount == 4 ) + bTextMode = rPar.Get(4)->GetInteger(); + + USHORT nStrLen = aStr1.Len(); + USHORT nStartPos = lStartPos == -1 ? nStrLen : (USHORT)lStartPos; + + USHORT nPos = 0; + if( nStartPos <= nStrLen ) + { + USHORT nTokenLen = aToken.Len(); + if( !nTokenLen ) + { + // Always find empty string + nPos = nStartPos; + } + else if( nStrLen > 0 ) + { + if( !bTextMode ) + { + ::rtl::OUString aOUStr1 ( aStr1 ); + ::rtl::OUString aOUToken( aToken ); + sal_Int32 nRet = aOUStr1.lastIndexOf( aOUToken, nStartPos ); + if( nRet == -1 ) + nPos = 0; + else + nPos = (USHORT)nRet + 1; + } + else + { + aStr1.ToUpperAscii(); + aToken.ToUpperAscii(); + + ::rtl::OUString aOUStr1 ( aStr1 ); + ::rtl::OUString aOUToken( aToken ); + sal_Int32 nRet = aOUStr1.lastIndexOf( aOUToken, nStartPos ); + + if( nRet == -1 ) + nPos = 0; + else + nPos = (USHORT)nRet + 1; + } + } + } + rPar.Get(0)->PutLong( nPos ); + } +} + + +/* + Int( 2.8 ) = 2.0 + Int( -2.8 ) = -3.0 + Fix( 2.8 ) = 2.0 + Fix( -2.8 ) = -2.0 <- !! +*/ + +RTLFUNC(Int) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + double aDouble= pArg->GetDouble(); + /* + floor( 2.8 ) = 2.0 + floor( -2.8 ) = -3.0 + */ + aDouble = floor( aDouble ); + rPar.Get(0)->PutDouble( aDouble ); + } +} + + + +RTLFUNC(Fix) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + double aDouble = pArg->GetDouble(); + if ( aDouble >= 0.0 ) + aDouble = floor( aDouble ); + else + aDouble = ceil( aDouble ); + rPar.Get(0)->PutDouble( aDouble ); + } +} + + +RTLFUNC(LCase) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + CharClass& rCharClass = GetCharClass(); + String aStr( rPar.Get(1)->GetString() ); + rCharClass.toLower( aStr ); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(Left) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 3 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr( rPar.Get(1)->GetString() ); + INT32 lResultLen = rPar.Get(2)->GetLong(); + if( lResultLen > 0xffff ) + { + lResultLen = 0xffff; + } + else if( lResultLen < 0 ) + { + lResultLen = 0; + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + } + aStr.Erase( (USHORT)lResultLen ); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(Log) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double aArg = rPar.Get(1)->GetDouble(); + if ( aArg > 0 ) + { + double d = log( aArg ); + checkArithmeticOverflow( d ); + rPar.Get( 0 )->PutDouble( d ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + } +} + +RTLFUNC(LTrim) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr( rPar.Get(1)->GetString() ); + aStr.EraseLeadingChars(); + rPar.Get(0)->PutString( aStr ); + } +} + + +// Mid( String, nStart, nLength ) + +RTLFUNC(Mid) +{ + (void)pBasic; + (void)bWrite; + + ULONG nArgCount = rPar.Count()-1; + if ( nArgCount < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // #23178: Funktionalitaet von Mid$ als Anweisung nachbilden, indem + // als weiterer (4.) Parameter ein Ersetzungsstring aufgenommen wird. + // Anders als im Original kann in dieser Variante der 3. Parameter + // nLength nicht weggelassen werden. Ist ueber bWrite schon vorgesehen. + if( nArgCount == 4 ) + bWrite = TRUE; + + String aArgStr = rPar.Get(1)->GetString(); + USHORT nStartPos = (USHORT)(rPar.Get(2)->GetLong() ); + if ( nStartPos == 0 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + nStartPos--; + USHORT nLen = 0xffff; + bool bWriteNoLenParam = false; + if ( nArgCount == 3 || bWrite ) + { + INT32 n = rPar.Get(3)->GetLong(); + if( bWrite && n == -1 ) + bWriteNoLenParam = true; + nLen = (USHORT)n; + } + String aResultStr; + if ( bWrite ) + { + SbiInstance* pInst = pINST; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + USHORT nArgLen = aArgStr.Len(); + if( nStartPos + 1 > nArgLen ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aReplaceStr = rPar.Get(4)->GetString(); + USHORT nReplaceStrLen = aReplaceStr.Len(); + USHORT nReplaceLen; + if( bWriteNoLenParam ) + { + nReplaceLen = nReplaceStrLen; + } + else + { + nReplaceLen = nLen; + if( nReplaceLen > nReplaceStrLen ) + nReplaceLen = nReplaceStrLen; + } + + USHORT nReplaceEndPos = nStartPos + nReplaceLen; + if( nReplaceEndPos > nArgLen ) + nReplaceLen -= (nReplaceEndPos - nArgLen); + + aResultStr = aArgStr; + USHORT nErase = nReplaceLen; + aResultStr.Erase( nStartPos, nErase ); + aResultStr.Insert( aReplaceStr, 0, nReplaceLen, nStartPos ); + } + else + { + aResultStr = aArgStr; + aResultStr.Erase( nStartPos, nLen ); + aResultStr.Insert(rPar.Get(4)->GetString(),0,nLen,nStartPos); + } + + rPar.Get(1)->PutString( aResultStr ); + } + else + { + aResultStr = aArgStr.Copy( nStartPos, nLen ); + rPar.Get(0)->PutString( aResultStr ); + } + } + } +} + +RTLFUNC(Oct) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + char aBuffer[16]; + SbxVariableRef pArg = rPar.Get( 1 ); + if ( pArg->IsInteger() ) + snprintf( aBuffer, sizeof(aBuffer), "%o", pArg->GetInteger() ); + else + snprintf( aBuffer, sizeof(aBuffer), "%lo", static_cast<long unsigned int>(pArg->GetLong()) ); + rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) ); + } +} + +// Replace(expression, find, replace[, start[, count[, compare]]]) + +RTLFUNC(Replace) +{ + (void)pBasic; + (void)bWrite; + + ULONG nArgCount = rPar.Count()-1; + if ( nArgCount < 3 || nArgCount > 6 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aExpStr = rPar.Get(1)->GetString(); + String aFindStr = rPar.Get(2)->GetString(); + String aReplaceStr = rPar.Get(3)->GetString(); + + INT32 lStartPos = 1; + if ( nArgCount >= 4 ) + { + if( rPar.Get(4)->GetType() != SbxEMPTY ) + lStartPos = rPar.Get(4)->GetLong(); + if( lStartPos < 1 || lStartPos > 0xffff ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + lStartPos = 1; + } + } + + INT32 lCount = -1; + if( nArgCount >=5 ) + { + if( rPar.Get(5)->GetType() != SbxEMPTY ) + lCount = rPar.Get(5)->GetLong(); + if( lCount < -1 || lCount > 0xffff ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + lCount = -1; + } + } + + SbiInstance* pInst = pINST; + int bTextMode; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + SbiRuntime* pRT = pInst ? pInst->pRun : NULL; + bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE; + } + else + { + bTextMode = 1; + } + if ( nArgCount == 6 ) + bTextMode = rPar.Get(6)->GetInteger(); + + USHORT nExpStrLen = aExpStr.Len(); + USHORT nFindStrLen = aFindStr.Len(); + USHORT nReplaceStrLen = aReplaceStr.Len(); + + if( lStartPos <= nExpStrLen ) + { + USHORT nPos = static_cast<USHORT>( lStartPos - 1 ); + USHORT nCounts = 0; + while( lCount == -1 || lCount > nCounts ) + { + String aSrcStr( aExpStr ); + if( bTextMode ) + { + aSrcStr.ToUpperAscii(); + aFindStr.ToUpperAscii(); + } + nPos = aSrcStr.Search( aFindStr, nPos ); + if( nPos != STRING_NOTFOUND ) + { + aExpStr.Replace( nPos, nFindStrLen, aReplaceStr ); + nPos = nPos - nFindStrLen + nReplaceStrLen + 1; + nCounts++; + } + else + { + break; + } + } + } + rPar.Get(0)->PutString( aExpStr.Copy( static_cast<USHORT>(lStartPos - 1) ) ); + } +} + +RTLFUNC(Right) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 3 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + const String& rStr = rPar.Get(1)->GetString(); + INT32 lResultLen = rPar.Get(2)->GetLong(); + if( lResultLen > 0xffff ) + { + lResultLen = 0xffff; + } + else if( lResultLen < 0 ) + { + lResultLen = 0; + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + } + USHORT nResultLen = (USHORT)lResultLen; + USHORT nStrLen = rStr.Len(); + if ( nResultLen > nStrLen ) + nResultLen = nStrLen; + String aResultStr = rStr.Copy( nStrLen-nResultLen ); + rPar.Get(0)->PutString( aResultStr ); + } +} + +RTLFUNC(RTL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get( 0 )->PutObject( pBasic->getRTL() ); +} + +RTLFUNC(RTrim) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr( rPar.Get(1)->GetString() ); + aStr.EraseTrailingChars(); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(Sgn) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double aDouble = rPar.Get(1)->GetDouble(); + INT16 nResult = 0; + if ( aDouble > 0 ) + nResult = 1; + else if ( aDouble < 0 ) + nResult = -1; + rPar.Get(0)->PutInteger( nResult ); + } +} + +RTLFUNC(Space) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr; + aStr.Fill( (USHORT)(rPar.Get(1)->GetLong() )); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(Spc) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr; + aStr.Fill( (USHORT)(rPar.Get(1)->GetLong() )); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(Sqr) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double aDouble = rPar.Get(1)->GetDouble(); + if ( aDouble >= 0 ) + rPar.Get(0)->PutDouble( sqrt( aDouble )); + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + } +} + +RTLFUNC(Str) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr; + SbxVariableRef pArg = rPar.Get( 1 ); + pArg->Format( aStr ); + + // Numbers start with a space + if( pArg->IsNumericRTL() ) + { + // Kommas durch Punkte ersetzen, damit es symmetrisch zu Val ist! + aStr.SearchAndReplace( ',', '.' ); + + SbiInstance* pInst = pINST; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + xub_StrLen nLen = aStr.Len(); + + const sal_Unicode* pBuf = aStr.GetBuffer(); + + bool bNeg = ( pBuf[0] == '-' ); + USHORT iZeroSearch = 0; + if( bNeg ) + iZeroSearch++; + + USHORT iNext = iZeroSearch + 1; + if( pBuf[iZeroSearch] == '0' && nLen > iNext && pBuf[iNext] == '.' ) + { + aStr.Erase( iZeroSearch, 1 ); + pBuf = aStr.GetBuffer(); + } + if( !bNeg ) + aStr.Insert( ' ', 0 ); + } + else + aStr.Insert( ' ', 0 ); + } + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(StrComp) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + rPar.Get(0)->PutEmpty(); + return; + } + const String& rStr1 = rPar.Get(1)->GetString(); + const String& rStr2 = rPar.Get(2)->GetString(); + + SbiInstance* pInst = pINST; + INT16 nTextCompare; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + SbiRuntime* pRT = pInst ? pInst->pRun : NULL; + nTextCompare = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : FALSE; + } + else + { + nTextCompare = TRUE; + } + if ( rPar.Count() == 4 ) + nTextCompare = rPar.Get(3)->GetInteger(); + + if( !bCompatibility ) + nTextCompare = !nTextCompare; + + StringCompare aResult; + sal_Int32 nRetValue = 0; + if( nTextCompare ) + { + ::utl::TransliterationWrapper* pTransliterationWrapper = GetSbData()->pTransliterationWrapper; + if( !pTransliterationWrapper ) + { + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + pTransliterationWrapper = GetSbData()->pTransliterationWrapper = + new ::utl::TransliterationWrapper( xSMgr, + ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE | + ::com::sun::star::i18n::TransliterationModules_IGNORE_KANA | + ::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH ); + } + + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + pTransliterationWrapper->loadModuleIfNeeded( eLangType ); + nRetValue = pTransliterationWrapper->compareString( rStr1, rStr2 ); + } + else + { + aResult = rStr1.CompareTo( rStr2 ); + if ( aResult == COMPARE_LESS ) + nRetValue = -1; + else if ( aResult == COMPARE_GREATER ) + nRetValue = 1; + } + + rPar.Get(0)->PutInteger( sal::static_int_cast< INT16 >( nRetValue ) ); +} + +RTLFUNC(String) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr; + sal_Unicode aFiller; + INT32 lCount = rPar.Get(1)->GetLong(); + if( lCount < 0 || lCount > 0xffff ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + USHORT nCount = (USHORT)lCount; + if( rPar.Get(2)->GetType() == SbxINTEGER ) + aFiller = (sal_Unicode)rPar.Get(2)->GetInteger(); + else + { + const String& rStr = rPar.Get(2)->GetString(); + aFiller = rStr.GetBuffer()[0]; + } + aStr.Fill( nCount, aFiller ); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(Tan) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + rPar.Get( 0 )->PutDouble( tan( pArg->GetDouble() ) ); + } +} + +RTLFUNC(UCase) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + CharClass& rCharClass = GetCharClass(); + String aStr( rPar.Get(1)->GetString() ); + rCharClass.toUpper( aStr ); + rPar.Get(0)->PutString( aStr ); + } +} + + +RTLFUNC(Val) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double nResult = 0.0; + char* pEndPtr; + + String aStr( rPar.Get(1)->GetString() ); +// lt. Mikkysoft bei Kommas abbrechen! +// for( USHORT n=0; n < aStr.Len(); n++ ) +// if( aStr[n] == ',' ) aStr[n] = '.'; + + FilterWhiteSpace( aStr ); + if ( aStr.GetBuffer()[0] == '&' && aStr.Len() > 1 ) + { + int nRadix = 10; + char aChar = (char)aStr.GetBuffer()[1]; + if ( aChar == 'h' || aChar == 'H' ) + nRadix = 16; + else if ( aChar == 'o' || aChar == 'O' ) + nRadix = 8; + if ( nRadix != 10 ) + { + ByteString aByteStr( aStr, gsl_getSystemTextEncoding() ); + INT16 nlResult = (INT16)strtol( aByteStr.GetBuffer()+2, &pEndPtr, nRadix); + nResult = (double)nlResult; + } + } + else + { + // #57844 Lokalisierte Funktion benutzen + nResult = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL ); + checkArithmeticOverflow( nResult ); + // ATL: nResult = strtod( aStr.GetStr(), &pEndPtr ); + } + + rPar.Get(0)->PutDouble( nResult ); + } +} + + +// Helper functions for date conversion +INT16 implGetDateDay( double aDate ) +{ + aDate -= 2.0; // normieren: 1.1.1900 => 0.0 + Date aRefDate( 1, 1, 1900 ); + if ( aDate >= 0.0 ) + { + aDate = floor( aDate ); + aRefDate += (ULONG)aDate; + } + else + { + aDate = ceil( aDate ); + aRefDate -= (ULONG)(-1.0 * aDate); + } + + INT16 nRet = (INT16)( aRefDate.GetDay() ); + return nRet; +} + +INT16 implGetDateMonth( double aDate ) +{ + Date aRefDate( 1,1,1900 ); + long nDays = (long)aDate; + nDays -= 2; // normieren: 1.1.1900 => 0.0 + aRefDate += nDays; + INT16 nRet = (INT16)( aRefDate.GetMonth() ); + return nRet; +} + +INT16 implGetDateYear( double aDate ) +{ + Date aRefDate( 1,1,1900 ); + long nDays = (long) aDate; + nDays -= 2; // normieren: 1.1.1900 => 0.0 + aRefDate += nDays; + INT16 nRet = (INT16)( aRefDate.GetYear() ); + return nRet; +} + +BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet ) +{ + if ( nYear < 30 && SbiRuntime::isVBAEnabled() )
+ nYear += 2000; + else if ( nYear < 100 )
+ nYear += 1900; + Date aCurDate( nDay, nMonth, nYear ); + if ((nYear < 100 || nYear > 9999) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return FALSE; + } + if ( !SbiRuntime::isVBAEnabled() ) + { + if ( (nMonth < 1 || nMonth > 12 )|| + (nDay < 1 || nDay > 31 ) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return FALSE; + } + } + else + { + // grab the year & month + aCurDate = Date( 1, (( nMonth % 12 ) > 0 ) ? ( nMonth % 12 ) : 12 + ( nMonth % 12 ), nYear ); + + // adjust year based on month value + // e.g. 2000, 0, xx = 1999, 12, xx ( or December of the previous year ) + // 2000, 13, xx = 2001, 1, xx ( or January of the following year ) + if( ( nMonth < 1 ) || ( nMonth > 12 ) ) + { + // inacurrate around leap year, don't use days to calculate, + // just modify the months directory + INT16 nYearAdj = ( nMonth /12 ); // default to positive months inputed + if ( nMonth <=0 ) + nYearAdj = ( ( nMonth -12 ) / 12 ); + aCurDate.SetYear( aCurDate.GetYear() + nYearAdj ); + } + + // adjust day value, + // e.g. 2000, 2, 0 = 2000, 1, 31 or the last day of the previous month + // 2000, 1, 32 = 2000, 2, 1 or the first day of the following month + if( ( nDay < 1 ) || ( nDay > aCurDate.GetDaysInMonth() ) ) + aCurDate += nDay - 1; + else + aCurDate.SetDay( nDay ); + } + + long nDiffDays = GetDayDiff( aCurDate ); + rdRet = (double)nDiffDays; + return TRUE; +} + +// Function to convert date to ISO 8601 date format +RTLFUNC(CDateToIso) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + double aDate = rPar.Get(1)->GetDate(); + + char Buffer[9]; + snprintf( Buffer, sizeof( Buffer ), "%04d%02d%02d", + implGetDateYear( aDate ), + implGetDateMonth( aDate ), + implGetDateDay( aDate ) ); + String aRetStr = String::CreateFromAscii( Buffer ); + rPar.Get(0)->PutString( aRetStr ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +// Function to convert date from ISO 8601 date format +RTLFUNC(CDateFromIso) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + String aStr = rPar.Get(1)->GetString(); + INT16 iMonthStart = aStr.Len() - 4; + String aYearStr = aStr.Copy( 0, iMonthStart ); + String aMonthStr = aStr.Copy( iMonthStart, 2 ); + String aDayStr = aStr.Copy( iMonthStart+2, 2 ); + + double dDate; + if( implDateSerial( (INT16)aYearStr.ToInt32(), + (INT16)aMonthStr.ToInt32(), (INT16)aDayStr.ToInt32(), dDate ) ) + { + rPar.Get(0)->PutDate( dDate ); + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(DateSerial) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nYear = rPar.Get(1)->GetInteger(); + INT16 nMonth = rPar.Get(2)->GetInteger(); + INT16 nDay = rPar.Get(3)->GetInteger(); + + double dDate; + if( implDateSerial( nYear, nMonth, nDay, dDate ) ) + rPar.Get(0)->PutDate( dDate ); +} + +RTLFUNC(TimeSerial) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nHour = rPar.Get(1)->GetInteger(); + if ( nHour == 24 ) + nHour = 0; // Wegen UNO DateTimes, die bis 24 Uhr gehen + INT16 nMinute = rPar.Get(2)->GetInteger(); + INT16 nSecond = rPar.Get(3)->GetInteger(); + if ((nHour < 0 || nHour > 23) || + (nMinute < 0 || nMinute > 59 ) || + (nSecond < 0 || nSecond > 59 )) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + INT32 nSeconds = nHour; + nSeconds *= 3600; + nSeconds += nMinute * 60; + nSeconds += nSecond; + double nDays = ((double)nSeconds) / (double)(86400.0); + rPar.Get(0)->PutDate( nDays ); // JSM +} + +RTLFUNC(DateValue) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden + SvNumberFormatter* pFormatter = NULL; + if( pINST ) + pFormatter = pINST->GetNumberFormatter(); + else + { + sal_uInt32 n; // Dummy + SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n ); + } + + sal_uInt32 nIndex; + double fResult; + String aStr( rPar.Get(1)->GetString() ); + BOOL bSuccess = pFormatter->IsNumberFormat( aStr, nIndex, fResult ); + short nType = pFormatter->GetType( nIndex ); + + // DateValue("February 12, 1969") raises error if the system locale is not en_US + // by using SbiInstance::GetNumberFormatter. + // It seems that both locale number formatter and English number formatter + // are supported in Visual Basic. + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + if( !bSuccess && ( eLangType != LANGUAGE_ENGLISH_US ) ) + { + // Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + xFactory = comphelper::getProcessServiceFactory(); + SvNumberFormatter aFormatter( xFactory, LANGUAGE_ENGLISH_US ); + bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, fResult ); + nType = aFormatter.GetType( nIndex ); + } + + if(bSuccess && (nType==NUMBERFORMAT_DATE || nType==NUMBERFORMAT_DATETIME)) + { + if ( nType == NUMBERFORMAT_DATETIME ) + { + // Zeit abschneiden + if ( fResult > 0.0 ) + fResult = floor( fResult ); + else + fResult = ceil( fResult ); + } + // fResult += 2.0; // Anpassung StarCalcFormatter + rPar.Get(0)->PutDate( fResult ); // JSM + } + else + StarBASIC::Error( SbERR_CONVERSION ); + + // #39629 pFormatter kann selbst angefordert sein + if( !pINST ) + delete pFormatter; + } +} + +RTLFUNC(TimeValue) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden + SvNumberFormatter* pFormatter = NULL; + if( pINST ) + pFormatter = pINST->GetNumberFormatter(); + else + { + sal_uInt32 n; // Dummy + SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n ); + } + + sal_uInt32 nIndex; + double fResult; + BOOL bSuccess = pFormatter->IsNumberFormat( rPar.Get(1)->GetString(), + nIndex, fResult ); + short nType = pFormatter->GetType(nIndex); + if(bSuccess && (nType==NUMBERFORMAT_TIME||nType==NUMBERFORMAT_DATETIME)) + { + if ( nType == NUMBERFORMAT_DATETIME ) + // Tage abschneiden + fResult = fmod( fResult, 1 ); + rPar.Get(0)->PutDate( fResult ); // JSM + } + else + StarBASIC::Error( SbERR_CONVERSION ); + + // #39629 pFormatter kann selbst angefordert sein + if( !pINST ) + delete pFormatter; + } +} + +RTLFUNC(Day) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariableRef pArg = rPar.Get( 1 ); + double aDate = pArg->GetDate(); + + INT16 nDay = implGetDateDay( aDate ); + rPar.Get(0)->PutInteger( nDay ); + } +} + +RTLFUNC(Year) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + INT16 nYear = implGetDateYear( rPar.Get(1)->GetDate() ); + rPar.Get(0)->PutInteger( nYear ); + } +} + +INT16 implGetHour( double dDate ) +{ + if( dDate < 0.0 ) + dDate *= -1.0; + double nFrac = dDate - floor( dDate ); + nFrac *= 86400.0; + INT32 nSeconds = (INT32)(nFrac + 0.5); + INT16 nHour = (INT16)(nSeconds / 3600); + return nHour; +} + +RTLFUNC(Hour) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double nArg = rPar.Get(1)->GetDate(); + INT16 nHour = implGetHour( nArg ); + rPar.Get(0)->PutInteger( nHour ); + } +} + +INT16 implGetMinute( double dDate ) +{ + if( dDate < 0.0 ) + dDate *= -1.0; + double nFrac = dDate - floor( dDate ); + nFrac *= 86400.0; + INT32 nSeconds = (INT32)(nFrac + 0.5); + INT16 nTemp = (INT16)(nSeconds % 3600); + INT16 nMin = nTemp / 60; + return nMin; +} + +RTLFUNC(Minute) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double nArg = rPar.Get(1)->GetDate(); + INT16 nMin = implGetMinute( nArg ); + rPar.Get(0)->PutInteger( nMin ); + } +} + +RTLFUNC(Month) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + INT16 nMonth = implGetDateMonth( rPar.Get(1)->GetDate() ); + rPar.Get(0)->PutInteger( nMonth ); + } +} + +INT16 implGetSecond( double dDate ) +{ + if( dDate < 0.0 ) + dDate *= -1.0; + double nFrac = dDate - floor( dDate ); + nFrac *= 86400.0; + INT32 nSeconds = (INT32)(nFrac + 0.5); + INT16 nTemp = (INT16)(nSeconds / 3600); + nSeconds -= nTemp * 3600; + nTemp = (INT16)(nSeconds / 60); + nSeconds -= nTemp * 60; + + INT16 nRet = (INT16)nSeconds; + return nRet; +} + +RTLFUNC(Second) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double nArg = rPar.Get(1)->GetDate(); + INT16 nSecond = implGetSecond( nArg ); + rPar.Get(0)->PutInteger( nSecond ); + } +} + +double Now_Impl() +{ + Date aDate; + Time aTime; + double aSerial = (double)GetDayDiff( aDate ); + long nSeconds = aTime.GetHour(); + nSeconds *= 3600; + nSeconds += aTime.GetMin() * 60; + nSeconds += aTime.GetSec(); + double nDays = ((double)nSeconds) / (double)(24.0*3600.0); + aSerial += nDays; + return aSerial; +} + +// Date Now(void) + +RTLFUNC(Now) +{ + (void)pBasic; + (void)bWrite; + rPar.Get(0)->PutDate( Now_Impl() ); +} + +// Date Time(void) + +RTLFUNC(Time) +{ + (void)pBasic; + + if ( !bWrite ) + { + Time aTime; + SbxVariable* pMeth = rPar.Get( 0 ); + String aRes; + if( pMeth->IsFixed() ) + { + // Time$: hh:mm:ss + char buf[ 20 ]; + snprintf( buf, sizeof(buf), "%02d:%02d:%02d", + aTime.GetHour(), aTime.GetMin(), aTime.GetSec() ); + aRes = String::CreateFromAscii( buf ); + } + else + { + // Time: system dependent + long nSeconds=aTime.GetHour(); + nSeconds *= 3600; + nSeconds += aTime.GetMin() * 60; + nSeconds += aTime.GetSec(); + double nDays = (double)nSeconds * ( 1.0 / (24.0*3600.0) ); + Color* pCol; + + // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden + SvNumberFormatter* pFormatter = NULL; + sal_uInt32 nIndex; + if( pINST ) + { + pFormatter = pINST->GetNumberFormatter(); + nIndex = pINST->GetStdTimeIdx(); + } + else + { + sal_uInt32 n; // Dummy + SbiInstance::PrepareNumberFormatter( pFormatter, n, nIndex, n ); + } + + pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol ); + + // #39629 pFormatter kann selbst angefordert sein + if( !pINST ) + delete pFormatter; + } + pMeth->PutString( aRes ); + } + else + { + StarBASIC::Error( SbERR_NOT_IMPLEMENTED ); + } +} + +RTLFUNC(Timer) +{ + (void)pBasic; + (void)bWrite; + + Time aTime; + long nSeconds = aTime.GetHour(); + nSeconds *= 3600; + nSeconds += aTime.GetMin() * 60; + nSeconds += aTime.GetSec(); + rPar.Get(0)->PutDate( (double)nSeconds ); +} + + +RTLFUNC(Date) +{ + (void)pBasic; + (void)bWrite; + + if ( !bWrite ) + { + Date aToday; + double nDays = (double)GetDayDiff( aToday ); + SbxVariable* pMeth = rPar.Get( 0 ); + if( pMeth->IsString() ) + { + String aRes; + Color* pCol; + + // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden + SvNumberFormatter* pFormatter = NULL; + sal_uInt32 nIndex; + if( pINST ) + { + pFormatter = pINST->GetNumberFormatter(); + nIndex = pINST->GetStdDateIdx(); + } + else + { + sal_uInt32 n; // Dummy + SbiInstance::PrepareNumberFormatter( pFormatter, nIndex, n, n ); + } + + pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol ); + pMeth->PutString( aRes ); + + // #39629 pFormatter kann selbst angefordert sein + if( !pINST ) + delete pFormatter; + } + else + pMeth->PutDate( nDays ); + } + else + { + StarBASIC::Error( SbERR_NOT_IMPLEMENTED ); + } +} + +RTLFUNC(IsArray) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + rPar.Get(0)->PutBool((rPar.Get(1)->GetType() & SbxARRAY) ? TRUE : FALSE ); +} + +RTLFUNC(IsObject) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxVariable* pVar = rPar.Get(1); + SbxBase* pObj = (SbxBase*)pVar->GetObject(); + + // #100385: GetObject can result in an error, so reset it + SbxBase::ResetError(); + + SbUnoClass* pUnoClass; + BOOL bObject; + if( pObj && NULL != ( pUnoClass=PTR_CAST(SbUnoClass,pObj) ) ) + { + bObject = pUnoClass->getUnoClass().is(); + } + else + { + bObject = pVar->IsObject(); + } + rPar.Get( 0 )->PutBool( bObject ); + } +} + +RTLFUNC(IsDate) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // #46134 Nur String wird konvertiert, andere Typen ergeben FALSE + SbxVariableRef xArg = rPar.Get( 1 ); + SbxDataType eType = xArg->GetType(); + BOOL bDate = FALSE; + + if( eType == SbxDATE ) + { + bDate = TRUE; + } + else if( eType == SbxSTRING ) + { + // Error loeschen + SbxError nPrevError = SbxBase::GetError(); + SbxBase::ResetError(); + + // Konvertierung des Parameters nach SbxDATE erzwingen + xArg->SbxValue::GetDate(); + + // Bei Fehler ist es kein Date + bDate = !SbxBase::IsError(); + + // Error-Situation wiederherstellen + SbxBase::ResetError(); + SbxBase::SetError( nPrevError ); + } + rPar.Get( 0 )->PutBool( bDate ); + } +} + +RTLFUNC(IsEmpty) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + rPar.Get( 0 )->PutBool( rPar.Get(1)->IsEmpty() ); +} + +RTLFUNC(IsError) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() ); +} + +RTLFUNC(IsNull) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // #51475 Wegen Uno-Objekten auch true liefern, + // wenn der pObj-Wert NULL ist + SbxVariableRef pArg = rPar.Get( 1 ); + BOOL bNull = rPar.Get(1)->IsNull(); + if( !bNull && pArg->GetType() == SbxOBJECT ) + { + SbxBase* pObj = pArg->GetObject(); + if( !pObj ) + bNull = TRUE; + } + rPar.Get( 0 )->PutBool( bNull ); + } +} + +RTLFUNC(IsNumeric) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + rPar.Get( 0 )->PutBool( rPar.Get( 1 )->IsNumericRTL() ); +} + +// Das machen wir auf die billige Tour + +RTLFUNC(IsMissing) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + // #57915 Missing wird durch Error angezeigt + rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() ); +} + +// Dir( [Maske] [,Attrs] ) +// ToDo: Library-globaler Datenbereich fuer Dir-Objekt und Flags + + +String getDirectoryPath( String aPathStr ) +{ + String aRetStr; + + DirectoryItem aItem; + FileBase::RC nRet = DirectoryItem::get( aPathStr, aItem ); + if( nRet == FileBase::E_None ) + { + FileStatus aFileStatus( FileStatusMask_Type ); + nRet = aItem.getFileStatus( aFileStatus ); + if( nRet == FileBase::E_None ) + { + FileStatus::Type aType = aFileStatus.getFileType(); + if( isFolder( aType ) ) + { + aRetStr = aPathStr; + } + else if( aType == FileStatus::Link ) + { + FileStatus aFileStatus2( FileStatusMask_LinkTargetURL ); + nRet = aItem.getFileStatus( aFileStatus2 ); + if( nRet == FileBase::E_None ) + aRetStr = getDirectoryPath( aFileStatus2.getLinkTargetURL() ); + } + } + } + return aRetStr; +} + +// Function looks for wildcards, removes them and always returns the pure path +String implSetupWildcard( const String& rFileParam, SbiRTLData* pRTLData ) +{ + static String aAsterisk = String::CreateFromAscii( "*" ); + static sal_Char cDelim1 = (sal_Char)'/'; + static sal_Char cDelim2 = (sal_Char)'\\'; + static sal_Char cWild1 = '*'; + static sal_Char cWild2 = '?'; + + delete pRTLData->pWildCard; + pRTLData->pWildCard = NULL; + pRTLData->sFullNameToBeChecked = String(); + + String aFileParam = rFileParam; + xub_StrLen nLastWild = aFileParam.SearchBackward( cWild1 ); + if( nLastWild == STRING_NOTFOUND ) + nLastWild = aFileParam.SearchBackward( cWild2 ); + sal_Bool bHasWildcards = ( nLastWild != STRING_NOTFOUND ); + + + xub_StrLen nLastDelim = aFileParam.SearchBackward( cDelim1 ); + if( nLastDelim == STRING_NOTFOUND ) + nLastDelim = aFileParam.SearchBackward( cDelim2 ); + + if( bHasWildcards ) + { + // Wildcards in path? + if( nLastDelim != STRING_NOTFOUND && nLastDelim > nLastWild ) + return aFileParam; + } + else + { + String aPathStr = getFullPath( aFileParam ); + if( nLastDelim != aFileParam.Len() - 1 ) + pRTLData->sFullNameToBeChecked = aPathStr; + return aPathStr; + } + + String aPureFileName; + if( nLastDelim == STRING_NOTFOUND ) + { + aPureFileName = aFileParam; + aFileParam = String(); + } + else + { + aPureFileName = aFileParam.Copy( nLastDelim + 1 ); + aFileParam = aFileParam.Copy( 0, nLastDelim ); + } + + // Try again to get a valid URL/UNC-path with only the path + String aPathStr = getFullPath( aFileParam ); + xub_StrLen nPureLen = aPureFileName.Len(); + + // Is there a pure file name left? Otherwise the path is + // invalid anyway because it was not accepted by OSL before + if( nPureLen && aPureFileName != aAsterisk ) + { + pRTLData->pWildCard = new WildCard( aPureFileName ); + } + return aPathStr; +} + +inline sal_Bool implCheckWildcard( const String& rName, SbiRTLData* pRTLData ) +{ + sal_Bool bMatch = sal_True; + + if( pRTLData->pWildCard ) + bMatch = pRTLData->pWildCard->Matches( rName ); + return bMatch; +} + + +bool isRootDir( String aDirURLStr ) +{ + INetURLObject aDirURLObj( aDirURLStr ); + BOOL bRoot = FALSE; + + // Check if it's a root directory + sal_Int32 nCount = aDirURLObj.getSegmentCount(); + + // No segment means Unix root directory "file:///" + if( nCount == 0 ) + { + bRoot = TRUE; + } + // Exactly one segment needs further checking, because it + // can be Unix "file:///foo/" -> no root + // or Windows "file:///c:/" -> root + else if( nCount == 1 ) + { + ::rtl::OUString aSeg1 = aDirURLObj.getName( 0, TRUE, + INetURLObject::DECODE_WITH_CHARSET ); + if( aSeg1.getStr()[1] == (sal_Unicode)':' ) + { + bRoot = TRUE; + } + } + // More than one segments can never be root + // so bRoot remains FALSE + + return bRoot; +} + +RTLFUNC(Dir) +{ + (void)pBasic; + (void)bWrite; + + String aPath; + + USHORT nParCount = rPar.Count(); + if( nParCount > 3 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbiRTLData* pRTLData = pINST->GetRTLData(); + + // #34645: Kann auch von der URL-Zeile ueber 'macro: Dir' aufgerufen werden + // dann existiert kein pRTLData und die Methode muss verlassen werden + if( !pRTLData ) + return; + + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + if ( nParCount >= 2 ) + { + String aFileParam = rPar.Get(1)->GetString(); + + String aFileURLStr = implSetupWildcard( aFileParam, pRTLData ); + if( pRTLData->sFullNameToBeChecked.Len() > 0 ) + { + sal_Bool bExists = sal_False; + try { bExists = xSFI->exists( aFileURLStr ); } + catch( Exception & ) {} + + String aNameOnlyStr; + if( bExists ) + { + INetURLObject aFileURL( aFileURLStr ); + aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT, + true, INetURLObject::DECODE_WITH_CHARSET ); + } + rPar.Get(0)->PutString( aNameOnlyStr ); + return; + } + + try + { + String aDirURLStr; + sal_Bool bFolder = xSFI->isFolder( aFileURLStr ); + + if( bFolder ) + { + aDirURLStr = aFileURLStr; + } + else + { + String aEmptyStr; + rPar.Get(0)->PutString( aEmptyStr ); + } + + USHORT nFlags = 0; + if ( nParCount > 2 ) + pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger(); + else + pRTLData->nDirFlags = 0; + + // Read directory + sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0); + pRTLData->aDirSeq = xSFI->getFolderContents( aDirURLStr, bIncludeFolders ); + pRTLData->nCurDirPos = 0; + + // #78651 Add "." and ".." directories for VB compatibility + if( bIncludeFolders ) + { + BOOL bRoot = isRootDir( aDirURLStr ); + + // If it's no root directory we flag the need for + // the "." and ".." directories by the value -2 + // for the actual position. Later for -2 will be + // returned "." and for -1 ".." + if( !bRoot ) + { + pRTLData->nCurDirPos = -2; + } + } + } + catch( Exception & ) + { + //StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + + + if( pRTLData->aDirSeq.getLength() > 0 ) + { + sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0); + + SbiInstance* pInst = pINST; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + for( ;; ) + { + if( pRTLData->nCurDirPos < 0 ) + { + if( pRTLData->nCurDirPos == -2 ) + { + aPath = ::rtl::OUString::createFromAscii( "." ); + } + else if( pRTLData->nCurDirPos == -1 ) + { + aPath = ::rtl::OUString::createFromAscii( ".." ); + } + pRTLData->nCurDirPos++; + } + else if( pRTLData->nCurDirPos >= pRTLData->aDirSeq.getLength() ) + { + pRTLData->aDirSeq.realloc( 0 ); + aPath.Erase(); + break; + } + else + { + ::rtl::OUString aFile = pRTLData->aDirSeq.getConstArray()[pRTLData->nCurDirPos++]; + + if( bCompatibility ) + { + if( !bFolderFlag ) + { + sal_Bool bFolder = xSFI->isFolder( aFile ); + if( bFolder ) + continue; + } + } + else + { + // Only directories + if( bFolderFlag ) + { + sal_Bool bFolder = xSFI->isFolder( aFile ); + if( !bFolder ) + continue; + } + } + + INetURLObject aURL( aFile ); + aPath = aURL.getName( INetURLObject::LAST_SEGMENT, TRUE, + INetURLObject::DECODE_WITH_CHARSET ); + } + + sal_Bool bMatch = implCheckWildcard( aPath, pRTLData ); + if( !bMatch ) + continue; + + break; + } + } + rPar.Get(0)->PutString( aPath ); + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + if ( nParCount >= 2 ) + { + delete pRTLData->pDir; + pRTLData->pDir = 0; // wg. Sonderbehandlung Sb_ATTR_VOLUME + DirEntry aEntry( rPar.Get(1)->GetString() ); + FileStat aStat( aEntry ); + if(!aStat.GetError() && (aStat.GetKind() & FSYS_KIND_FILE)) + { + // ah ja, ist nur ein dateiname + // Pfad abschneiden (wg. VB4) + rPar.Get(0)->PutString( aEntry.GetName() ); + return; + } + USHORT nFlags = 0; + if ( nParCount > 2 ) + pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger(); + else + pRTLData->nDirFlags = 0; + // Nur diese Bitmaske ist unter Windows erlaubt + #ifdef WIN + if( nFlags & ~0x1E ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ), pRTLData->nDirFlags = 0; + #endif + // Sb_ATTR_VOLUME wird getrennt gehandelt + if( pRTLData->nDirFlags & Sb_ATTR_VOLUME ) + aPath = aEntry.GetVolume(); + else + { + // Die richtige Auswahl treffen + USHORT nMode = FSYS_KIND_FILE; + if( nFlags & Sb_ATTR_DIRECTORY ) + nMode |= FSYS_KIND_DIR; + if( nFlags == Sb_ATTR_DIRECTORY ) + nMode = FSYS_KIND_DIR; + pRTLData->pDir = new Dir( aEntry, (DirEntryKind) nMode ); + pRTLData->nCurDirPos = 0; + } + } + + if( pRTLData->pDir ) + { + for( ;; ) + { + if( pRTLData->nCurDirPos >= pRTLData->pDir->Count() ) + { + delete pRTLData->pDir; + pRTLData->pDir = 0; + aPath.Erase(); + break; + } + DirEntry aNextEntry=(*(pRTLData->pDir))[pRTLData->nCurDirPos++]; + aPath = aNextEntry.GetName(); //Full(); + #ifdef WIN + aNextEntry.ToAbs(); + String sFull(aNextEntry.GetFull()); + unsigned nFlags; + + if (_dos_getfileattr( sFull.GetStr(), &nFlags )) + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + else + { + INT16 nCurFlags = pRTLData->nDirFlags; + if( (nCurFlags == Sb_ATTR_NORMAL) + && !(nFlags & ( _A_HIDDEN | _A_SYSTEM | _A_VOLID | _A_SUBDIR ) ) ) + break; + else if( (nCurFlags & Sb_ATTR_HIDDEN) && (nFlags & _A_HIDDEN) ) + break; + else if( (nCurFlags & Sb_ATTR_SYSTEM) && (nFlags & _A_SYSTEM) ) + break; + else if( (nCurFlags & Sb_ATTR_VOLUME) && (nFlags & _A_VOLID) ) + break; + else if( (nCurFlags & Sb_ATTR_DIRECTORY) && (nFlags & _A_SUBDIR) ) + break; + } + #else + break; + #endif + } + } + rPar.Get(0)->PutString( aPath ); +#else + // TODO: OSL + if ( nParCount >= 2 ) + { + String aFileParam = rPar.Get(1)->GetString(); + + String aDirURL = implSetupWildcard( aFileParam, pRTLData ); + + USHORT nFlags = 0; + if ( nParCount > 2 ) + pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger(); + else + pRTLData->nDirFlags = 0; + + // Read directory + sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0); + pRTLData->pDir = new Directory( aDirURL ); + FileBase::RC nRet = pRTLData->pDir->open(); + if( nRet != FileBase::E_None ) + { + delete pRTLData->pDir; + pRTLData->pDir = NULL; + rPar.Get(0)->PutString( String() ); + return; + } + + // #86950 Add "." and ".." directories for VB compatibility + pRTLData->nCurDirPos = 0; + if( bIncludeFolders ) + { + BOOL bRoot = isRootDir( aDirURL ); + + // If it's no root directory we flag the need for + // the "." and ".." directories by the value -2 + // for the actual position. Later for -2 will be + // returned "." and for -1 ".." + if( !bRoot ) + { + pRTLData->nCurDirPos = -2; + } + } + + } + + if( pRTLData->pDir ) + { + sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0); + for( ;; ) + { + if( pRTLData->nCurDirPos < 0 ) + { + if( pRTLData->nCurDirPos == -2 ) + { + aPath = ::rtl::OUString::createFromAscii( "." ); + } + else if( pRTLData->nCurDirPos == -1 ) + { + aPath = ::rtl::OUString::createFromAscii( ".." ); + } + pRTLData->nCurDirPos++; + } + else + { + DirectoryItem aItem; + FileBase::RC nRet = pRTLData->pDir->getNextItem( aItem ); + if( nRet != FileBase::E_None ) + { + delete pRTLData->pDir; + pRTLData->pDir = NULL; + aPath.Erase(); + break; + } + + // Handle flags + FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileName ); + nRet = aItem.getFileStatus( aFileStatus ); + + // Only directories? + if( bFolderFlag ) + { + FileStatus::Type aType = aFileStatus.getFileType(); + sal_Bool bFolder = isFolder( aType ); + if( !bFolder ) + continue; + } + + aPath = aFileStatus.getFileName(); + } + + sal_Bool bMatch = implCheckWildcard( aPath, pRTLData ); + if( !bMatch ) + continue; + + break; + } + } + rPar.Get(0)->PutString( aPath ); +#endif + } + } +} + + +RTLFUNC(GetAttr) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + INT16 nFlags = 0; + + // In Windows, We want to use Windows API to get the file attributes + // for VBA interoperability. + #if defined( WNT ) + if( SbiRuntime::isVBAEnabled() ) + { + DirEntry aEntry( rPar.Get(1)->GetString() ); + aEntry.ToAbs(); + + // #57064 Bei virtuellen URLs den Real-Path extrahieren + ByteString aByteStrFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() ); + DWORD nRealFlags = GetFileAttributes (aByteStrFullPath.GetBuffer()); + if (nRealFlags != 0xffffffff) + { + if (nRealFlags == FILE_ATTRIBUTE_NORMAL) + nRealFlags = 0; + nFlags = (INT16) (nRealFlags); + } + else + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + + rPar.Get(0)->PutInteger( nFlags ); + + return; + } + #endif + + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + String aPath = getFullPath( rPar.Get(1)->GetString() ); + sal_Bool bExists = sal_False; + try { bExists = xSFI->exists( aPath ); } + catch( Exception & ) {} + if( !bExists ) + { + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + return; + } + + sal_Bool bReadOnly = xSFI->isReadOnly( aPath ); + sal_Bool bHidden = xSFI->isHidden( aPath ); + sal_Bool bDirectory = xSFI->isFolder( aPath ); + if( bReadOnly ) + nFlags |= 0x0001; // ATTR_READONLY + if( bHidden ) + nFlags |= 0x0002; // ATTR_HIDDEN + if( bDirectory ) + nFlags |= 0x0010; // ATTR_DIRECTORY + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { + DirectoryItem aItem; + FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetString() ), aItem ); + FileStatus aFileStatus( FileStatusMask_Attributes | FileStatusMask_Type ); + nRet = aItem.getFileStatus( aFileStatus ); + sal_uInt64 nAttributes = aFileStatus.getAttributes(); + sal_Bool bReadOnly = (nAttributes & Attribute_ReadOnly) != 0; + + FileStatus::Type aType = aFileStatus.getFileType(); + sal_Bool bDirectory = isFolder( aType ); + if( bReadOnly ) + nFlags |= 0x0001; // ATTR_READONLY + if( bDirectory ) + nFlags |= 0x0010; // ATTR_DIRECTORY + } + rPar.Get(0)->PutInteger( nFlags ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + + +RTLFUNC(FileDateTime) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // <-- UCB + String aPath = rPar.Get(1)->GetString(); + Time aTime; + Date aDate; + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + com::sun::star::util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath ); + aTime = Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds ); + aDate = Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + DirEntry aEntry( aPath ); + FileStat aStat( aEntry ); + aTime = Time( aStat.TimeModified() ); + aDate = Date( aStat.DateModified() ); +#else + DirectoryItem aItem; + FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aPath ), aItem ); + FileStatus aFileStatus( FileStatusMask_ModifyTime ); + nRet = aItem.getFileStatus( aFileStatus ); + TimeValue aTimeVal = aFileStatus.getModifyTime(); + oslDateTime aDT; + osl_getDateTimeFromTimeValue( &aTimeVal, &aDT ); + + aTime = Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 10000000*aDT.NanoSeconds ); + aDate = Date( aDT.Day, aDT.Month, aDT.Year ); +#endif + } + + double fSerial = (double)GetDayDiff( aDate ); + long nSeconds = aTime.GetHour(); + nSeconds *= 3600; + nSeconds += aTime.GetMin() * 60; + nSeconds += aTime.GetSec(); + double nDays = ((double)nSeconds) / (double)(24.0*3600.0); + fSerial += nDays; + + Color* pCol; + + // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden + SvNumberFormatter* pFormatter = NULL; + sal_uInt32 nIndex; + if( pINST ) + { + pFormatter = pINST->GetNumberFormatter(); + nIndex = pINST->GetStdDateTimeIdx(); + } + else + { + sal_uInt32 n; // Dummy + SbiInstance::PrepareNumberFormatter( pFormatter, n, n, nIndex ); + } + + String aRes; + pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol ); + rPar.Get(0)->PutString( aRes ); + + // #39629 pFormatter kann selbst angefordert sein + if( !pINST ) + delete pFormatter; + } +} + + +RTLFUNC(EOF) +{ + (void)pBasic; + (void)bWrite; + + // AB 08/16/2000: No changes for UCB + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + INT16 nChannel = rPar.Get(1)->GetInteger(); + // nChannel--; // macht MD beim Oeffnen auch nicht + SbiIoSystem* pIO = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nChannel ); + if ( !pSbStrm ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + BOOL bIsEof; + SvStream* pSvStrm = pSbStrm->GetStrm(); + if ( pSbStrm->IsText() ) + { + char cBla; + (*pSvStrm) >> cBla; // koennen wir noch ein Zeichen lesen + bIsEof = pSvStrm->IsEof(); + if ( !bIsEof ) + pSvStrm->SeekRel( -1 ); + } + else + bIsEof = pSvStrm->IsEof(); // fuer binaerdateien! + rPar.Get(0)->PutBool( bIsEof ); + } +} + +RTLFUNC(FileAttr) +{ + (void)pBasic; + (void)bWrite; + + // AB 08/16/2000: No changes for UCB + + // #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von + // der Anpassung an virtuelle URLs nich betroffen, da sie nur auf bereits + // geoeffneten Dateien arbeitet und der Name hier keine Rolle spielt. + + if ( rPar.Count() != 3 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + INT16 nChannel = rPar.Get(1)->GetInteger(); +// nChannel--; + SbiIoSystem* pIO = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nChannel ); + if ( !pSbStrm ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + INT16 nRet; + if ( rPar.Get(2)->GetInteger() == 1 ) + nRet = (INT16)(pSbStrm->GetMode()); + else + nRet = 0; // System file handle not supported + + rPar.Get(0)->PutInteger( nRet ); + } +} +RTLFUNC(Loc) +{ + (void)pBasic; + (void)bWrite; + + // AB 08/16/2000: No changes for UCB + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + INT16 nChannel = rPar.Get(1)->GetInteger(); + SbiIoSystem* pIO = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nChannel ); + if ( !pSbStrm ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + SvStream* pSvStrm = pSbStrm->GetStrm(); + ULONG nPos; + if( pSbStrm->IsRandom()) + { + short nBlockLen = pSbStrm->GetBlockLen(); + nPos = nBlockLen ? (pSvStrm->Tell() / nBlockLen) : 0; + nPos++; // Blockpositionen beginnen bei 1 + } + else if ( pSbStrm->IsText() ) + nPos = pSbStrm->GetLine(); + else if( pSbStrm->IsBinary() ) + nPos = pSvStrm->Tell(); + else if ( pSbStrm->IsSeq() ) + nPos = ( pSvStrm->Tell()+1 ) / 128; + else + nPos = pSvStrm->Tell(); + rPar.Get(0)->PutLong( (INT32)nPos ); + } +} + +RTLFUNC(Lof) +{ + (void)pBasic; + (void)bWrite; + + // AB 08/16/2000: No changes for UCB + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + INT16 nChannel = rPar.Get(1)->GetInteger(); + SbiIoSystem* pIO = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nChannel ); + if ( !pSbStrm ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + SvStream* pSvStrm = pSbStrm->GetStrm(); + ULONG nOldPos = pSvStrm->Tell(); + ULONG nLen = pSvStrm->Seek( STREAM_SEEK_TO_END ); + pSvStrm->Seek( nOldPos ); + rPar.Get(0)->PutLong( (INT32)nLen ); + } +} + + +RTLFUNC(Seek) +{ + (void)pBasic; + (void)bWrite; + + // AB 08/16/2000: No changes for UCB + int nArgs = (int)rPar.Count(); + if ( nArgs < 2 || nArgs > 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nChannel = rPar.Get(1)->GetInteger(); +// nChannel--; + SbiIoSystem* pIO = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nChannel ); + if ( !pSbStrm ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + SvStream* pStrm = pSbStrm->GetStrm(); + + if ( nArgs == 2 ) // Seek-Function + { + ULONG nPos = pStrm->Tell(); + if( pSbStrm->IsRandom() ) + nPos = nPos / pSbStrm->GetBlockLen(); + nPos++; // Basic zaehlt ab 1 + rPar.Get(0)->PutLong( (INT32)nPos ); + } + else // Seek-Statement + { + INT32 nPos = rPar.Get(2)->GetLong(); + if ( nPos < 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + nPos--; // Basic zaehlt ab 1, SvStreams zaehlen ab 0 + pSbStrm->SetExpandOnWriteTo( 0 ); + if ( pSbStrm->IsRandom() ) + nPos *= pSbStrm->GetBlockLen(); + pStrm->Seek( (ULONG)nPos ); + pSbStrm->SetExpandOnWriteTo( nPos ); + } +} + +RTLFUNC(Format) +{ + (void)pBasic; + (void)bWrite; + + USHORT nArgCount = (USHORT)rPar.Count(); + if ( nArgCount < 2 || nArgCount > 3 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aResult; + if( nArgCount == 2 ) + rPar.Get(1)->Format( aResult ); + else + { + String aFmt( rPar.Get(2)->GetString() ); + rPar.Get(1)->Format( aResult, &aFmt ); + } + rPar.Get(0)->PutString( aResult ); + } +} + +RTLFUNC(Randomize) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() > 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + INT16 nSeed; + if( rPar.Count() == 2 ) + nSeed = (INT16)rPar.Get(1)->GetInteger(); + else + nSeed = (INT16)rand(); + srand( nSeed ); +} + +RTLFUNC(Rnd) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() > 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double nRand = (double)rand(); + nRand = ( nRand / (double)RAND_MAX ); + rPar.Get(0)->PutDouble( nRand ); + } +} + + +// +// Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = FALSE ]]]) +// +// WindowStyles (VBA-kompatibel): +// 2 == Minimized +// 3 == Maximized +// 10 == Full-Screen (Textmodus-Anwendungen OS/2, WIN95, WNT) +// +// !!!HACK der WindowStyle wird im Creator an Application::StartApp +// uebergeben. Format: "xxxx2" +// + + +RTLFUNC(Shell) +{ + (void)pBasic; + (void)bWrite; + + // No shell command for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + ULONG nArgCount = rPar.Count(); + if ( nArgCount < 2 || nArgCount > 5 ) + { + rPar.Get(0)->PutLong(0); + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + } + else + { + USHORT nOptions = NAMESPACE_VOS(OProcess)::TOption_SearchPath| + NAMESPACE_VOS(OProcess)::TOption_Detached; + String aCmdLine = rPar.Get(1)->GetString(); + // Zusaetzliche Parameter anhaengen, es muss eh alles geparsed werden + if( nArgCount >= 4 ) + { + aCmdLine.AppendAscii( " " ); + aCmdLine += rPar.Get(3)->GetString(); + } + else if( !aCmdLine.Len() ) + { + // Spezial-Behandlung (leere Liste) vermeiden + aCmdLine.AppendAscii( " " ); + } + USHORT nLen = aCmdLine.Len(); + + // #55735 Wenn Parameter dabei sind, muessen die abgetrennt werden + // #72471 Auch die einzelnen Parameter trennen + std::list<String> aTokenList; + String aToken; + USHORT i = 0; + sal_Unicode c; + while( i < nLen ) + { + // Spaces weg + for ( ;; ++i ) + { + c = aCmdLine.GetBuffer()[ i ]; + if ( c != ' ' && c != '\t' ) + break; + } + + if( c == '\"' || c == '\'' ) + { + USHORT iFoundPos = aCmdLine.Search( c, i + 1 ); + + // Wenn nichts gefunden wurde, Rest kopieren + if( iFoundPos == STRING_NOTFOUND ) + { + aToken = aCmdLine.Copy( i, STRING_LEN ); + i = nLen; + } + else + { + aToken = aCmdLine.Copy( i + 1, (iFoundPos - i - 1) ); + i = iFoundPos + 1; + } + } + else + { + USHORT iFoundSpacePos = aCmdLine.Search( ' ', i ); + USHORT iFoundTabPos = aCmdLine.Search( '\t', i ); + USHORT iFoundPos = Min( iFoundSpacePos, iFoundTabPos ); + + // Wenn nichts gefunden wurde, Rest kopieren + if( iFoundPos == STRING_NOTFOUND ) + { + aToken = aCmdLine.Copy( i, STRING_LEN ); + i = nLen; + } + else + { + aToken = aCmdLine.Copy( i, (iFoundPos - i) ); + i = iFoundPos; + } + } + + // In die Liste uebernehmen + aTokenList.push_back( aToken ); + } + // #55735 / #72471 Ende + + INT16 nWinStyle = 0; + if( nArgCount >= 3 ) + { + nWinStyle = rPar.Get(2)->GetInteger(); + switch( nWinStyle ) + { + case 2: + nOptions |= NAMESPACE_VOS(OProcess)::TOption_Minimized; + break; + case 3: + nOptions |= NAMESPACE_VOS(OProcess)::TOption_Maximized; + break; + case 10: + nOptions |= NAMESPACE_VOS(OProcess)::TOption_FullScreen; + break; + } + + BOOL bSync = FALSE; + if( nArgCount >= 5 ) + bSync = rPar.Get(4)->GetBool(); + if( bSync ) + nOptions |= NAMESPACE_VOS(OProcess)::TOption_Wait; + } + NAMESPACE_VOS(OProcess)::TProcessOption eOptions = + (NAMESPACE_VOS(OProcess)::TProcessOption)nOptions; + + + // #72471 Parameter aufbereiten + std::list<String>::const_iterator iter = aTokenList.begin(); + const String& rStr = *iter; + ::rtl::OUString aOUStrProg( rStr.GetBuffer(), rStr.Len() ); + String aOUStrProgUNC = getFullPathUNC( aOUStrProg ); + + iter++; + + USHORT nParamCount = sal::static_int_cast< USHORT >( + aTokenList.size() - 1 ); + ::rtl::OUString* pArgumentList = NULL; + //const char** pParamList = NULL; + if( nParamCount ) + { + pArgumentList = new ::rtl::OUString[ nParamCount ]; + //pParamList = new const char*[ nParamCount ]; + USHORT iList = 0; + while( iter != aTokenList.end() ) + { + const String& rParamStr = (*iter); + pArgumentList[iList++] = ::rtl::OUString( rParamStr.GetBuffer(), rParamStr.Len() ); + //pParamList[iList++] = (*iter).GetStr(); + iter++; + } + } + + //const char* pParams = aParams.Len() ? aParams.GetStr() : 0; + NAMESPACE_VOS(OProcess)* pApp; + pApp = new NAMESPACE_VOS(OProcess)( aOUStrProgUNC ); + BOOL bSucc; + if( nParamCount == 0 ) + { + bSucc = pApp->execute( eOptions ) == NAMESPACE_VOS(OProcess)::E_None; + } + else + { + NAMESPACE_VOS(OArgumentList) aArgList( pArgumentList, nParamCount ); + bSucc = pApp->execute( eOptions, aArgList ) == NAMESPACE_VOS(OProcess)::E_None; + } + + /* + if( nParamCount == 0 ) + pApp = new NAMESPACE_VOS(OProcess)( pProg ); + else + pApp = new NAMESPACE_VOS(OProcess)( pProg, pParamList, nParamCount ); + BOOL bSucc = pApp->execute( eOptions ) == NAMESPACE_VOS(OProcess)::E_None; + */ + + delete pApp; + delete[] pArgumentList; + if( !bSucc ) + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + else + rPar.Get(0)->PutLong( 0 ); + } +} + +RTLFUNC(VarType) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxDataType eType = rPar.Get(1)->GetType(); + rPar.Get(0)->PutInteger( (INT16)eType ); + } +} + +// Exported function +String getBasicTypeName( SbxDataType eType ) +{ + static const char* pTypeNames[] = + { + "Empty", // SbxEMPTY + "Null", // SbxNULL + "Integer", // SbxINTEGER + "Long", // SbxLONG + "Single", // SbxSINGLE + "Double", // SbxDOUBLE + "Currency", // SbxCURRENCY + "Date", // SbxDATE + "String", // SbxSTRING + "Object", // SbxOBJECT + "Error", // SbxERROR + "Boolean", // SbxBOOL + "Variant", // SbxVARIANT + "DataObject", // SbxDATAOBJECT + "Unknown Type", // + "Unknown Type", // + "Char", // SbxCHAR + "Byte", // SbxBYTE + "UShort", // SbxUSHORT + "ULong", // SbxULONG + "Long64", // SbxLONG64 + "ULong64", // SbxULONG64 + "Int", // SbxINT + "UInt", // SbxUINT + "Void", // SbxVOID + "HResult", // SbxHRESULT + "Pointer", // SbxPOINTER + "DimArray", // SbxDIMARRAY + "CArray", // SbxCARRAY + "Userdef", // SbxUSERDEF + "Lpstr", // SbxLPSTR + "Lpwstr", // SbxLPWSTR + "Unknown Type", // SbxCoreSTRING + "WString", // SbxWSTRING + "WChar", // SbxWCHAR + "Int64", // SbxSALINT64 + "UInt64", // SbxSALUINT64 + "Decimal", // SbxDECIMAL + }; + + int nPos = ((int)eType) & 0x0FFF; + USHORT nTypeNameCount = sizeof( pTypeNames ) / sizeof( char* ); + if ( nPos < 0 || nPos >= nTypeNameCount ) + nPos = nTypeNameCount - 1; + String aRetStr = String::CreateFromAscii( pTypeNames[nPos] ); + return aRetStr; +} + +RTLFUNC(TypeName) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxDataType eType = rPar.Get(1)->GetType(); + BOOL bIsArray = ( ( eType & SbxARRAY ) != 0 ); + String aRetStr = getBasicTypeName( eType ); + if( bIsArray ) + aRetStr.AppendAscii( "()" ); + rPar.Get(0)->PutString( aRetStr ); + } +} + +RTLFUNC(Len) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + const String& rStr = rPar.Get(1)->GetString(); + rPar.Get(0)->PutLong( (INT32)rStr.Len() ); + } +} + +RTLFUNC(DDEInitiate) +{ + (void)pBasic; + (void)bWrite; + + // No DDE for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + int nArgs = (int)rPar.Count(); + if ( nArgs != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + const String& rApp = rPar.Get(1)->GetString(); + const String& rTopic = rPar.Get(2)->GetString(); + + SbiDdeControl* pDDE = pINST->GetDdeControl(); + INT16 nChannel; + SbError nDdeErr = pDDE->Initiate( rApp, rTopic, nChannel ); + if( nDdeErr ) + StarBASIC::Error( nDdeErr ); + else + rPar.Get(0)->PutInteger( nChannel ); +} + +RTLFUNC(DDETerminate) +{ + (void)pBasic; + (void)bWrite; + + // No DDE for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + rPar.Get(0)->PutEmpty(); + int nArgs = (int)rPar.Count(); + if ( nArgs != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nChannel = rPar.Get(1)->GetInteger(); + SbiDdeControl* pDDE = pINST->GetDdeControl(); + SbError nDdeErr = pDDE->Terminate( nChannel ); + if( nDdeErr ) + StarBASIC::Error( nDdeErr ); +} + +RTLFUNC(DDETerminateAll) +{ + (void)pBasic; + (void)bWrite; + + // No DDE for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + rPar.Get(0)->PutEmpty(); + int nArgs = (int)rPar.Count(); + if ( nArgs != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbiDdeControl* pDDE = pINST->GetDdeControl(); + SbError nDdeErr = pDDE->TerminateAll(); + if( nDdeErr ) + StarBASIC::Error( nDdeErr ); + +} + +RTLFUNC(DDERequest) +{ + (void)pBasic; + (void)bWrite; + + // No DDE for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + int nArgs = (int)rPar.Count(); + if ( nArgs != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nChannel = rPar.Get(1)->GetInteger(); + const String& rItem = rPar.Get(2)->GetString(); + SbiDdeControl* pDDE = pINST->GetDdeControl(); + String aResult; + SbError nDdeErr = pDDE->Request( nChannel, rItem, aResult ); + if( nDdeErr ) + StarBASIC::Error( nDdeErr ); + else + rPar.Get(0)->PutString( aResult ); +} + +RTLFUNC(DDEExecute) +{ + (void)pBasic; + (void)bWrite; + + // No DDE for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + rPar.Get(0)->PutEmpty(); + int nArgs = (int)rPar.Count(); + if ( nArgs != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nChannel = rPar.Get(1)->GetInteger(); + const String& rCommand = rPar.Get(2)->GetString(); + SbiDdeControl* pDDE = pINST->GetDdeControl(); + SbError nDdeErr = pDDE->Execute( nChannel, rCommand ); + if( nDdeErr ) + StarBASIC::Error( nDdeErr ); +} + +RTLFUNC(DDEPoke) +{ + (void)pBasic; + (void)bWrite; + + // No DDE for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + rPar.Get(0)->PutEmpty(); + int nArgs = (int)rPar.Count(); + if ( nArgs != 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nChannel = rPar.Get(1)->GetInteger(); + const String& rItem = rPar.Get(2)->GetString(); + const String& rData = rPar.Get(3)->GetString(); + SbiDdeControl* pDDE = pINST->GetDdeControl(); + SbError nDdeErr = pDDE->Poke( nChannel, rItem, rData ); + if( nDdeErr ) + StarBASIC::Error( nDdeErr ); +} + + +RTLFUNC(FreeFile) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + SbiIoSystem* pIO = pINST->GetIoSystem(); + short nChannel = 1; + while( nChannel < CHANNELS ) + { + SbiStream* pStrm = pIO->GetStream( nChannel ); + if( !pStrm ) + { + rPar.Get(0)->PutInteger( nChannel ); + return; + } + nChannel++; + } + StarBASIC::Error( SbERR_TOO_MANY_FILES ); +} + +RTLFUNC(LBound) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if ( nParCount != 3 && nParCount != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + SbxBase* pParObj = rPar.Get(1)->GetObject(); + SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj); + if( pArr ) + { + INT32 nLower, nUpper; + short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1; + if( !pArr->GetDim32( nDim, nLower, nUpper ) ) + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + else + rPar.Get(0)->PutLong( nLower ); + } + else + StarBASIC::Error( SbERR_MUST_HAVE_DIMS ); +} + +RTLFUNC(UBound) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if ( nParCount != 3 && nParCount != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbxBase* pParObj = rPar.Get(1)->GetObject(); + SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj); + if( pArr ) + { + INT32 nLower, nUpper; + short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1; + if( !pArr->GetDim32( nDim, nLower, nUpper ) ) + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + else + rPar.Get(0)->PutLong( nUpper ); + } + else + StarBASIC::Error( SbERR_MUST_HAVE_DIMS ); +} + +RTLFUNC(RGB) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + ULONG nRed = rPar.Get(1)->GetInteger() & 0xFF; + ULONG nGreen = rPar.Get(2)->GetInteger() & 0xFF; + ULONG nBlue = rPar.Get(3)->GetInteger() & 0xFF; + ULONG nRGB; + + SbiInstance* pInst = pINST; + bool bCompatibility = ( pInst && pInst->IsCompatibility() ); + if( bCompatibility ) + { + nRGB = (nBlue << 16) | (nGreen << 8) | nRed; + } + else + { + nRGB = (nRed << 16) | (nGreen << 8) | nBlue; + } + rPar.Get(0)->PutLong( nRGB ); +} + +RTLFUNC(QBColor) +{ + (void)pBasic; + (void)bWrite; + + static const INT32 pRGB[] = + { + 0x000000, + 0x800000, + 0x008000, + 0x808000, + 0x000080, + 0x800080, + 0x008080, + 0xC0C0C0, + 0x808080, + 0xFF0000, + 0x00FF00, + 0xFFFF00, + 0x0000FF, + 0xFF00FF, + 0x00FFFF, + 0xFFFFFF, + }; + + if ( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + INT16 nCol = rPar.Get(1)->GetInteger(); + if( nCol < 0 || nCol > 15 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT32 nRGB = pRGB[ nCol ]; + rPar.Get(0)->PutLong( nRGB ); +} + +// StrConv(string, conversion, LCID) +RTLFUNC(StrConv) +{ + (void)pBasic; + (void)bWrite; + + ULONG nArgCount = rPar.Count()-1; + if( nArgCount < 2 || nArgCount > 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aOldStr = rPar.Get(1)->GetString(); + INT32 nConversion = rPar.Get(2)->GetLong(); + + USHORT nLanguage = LANGUAGE_SYSTEM; + if( nArgCount == 3 ) + { + // LCID not supported now + //nLanguage = rPar.Get(3)->GetInteger(); + } + + USHORT nOldLen = aOldStr.Len(); + if( nOldLen == 0 ) + { + // null string,return + rPar.Get(0)->PutString(aOldStr); + return; + } + + INT32 nType = 0; + if ( (nConversion & 0x03) == 3 ) // vbProperCase + { + CharClass& rCharClass = GetCharClass(); + aOldStr = rCharClass.toTitle( aOldStr.ToLowerAscii(), 0, nOldLen ); + } + else if ( (nConversion & 0x01) == 1 ) // vbUpperCase + nType |= ::com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE; + else if ( (nConversion & 0x02) == 2 ) // vbLowerCase + nType |= ::com::sun::star::i18n::TransliterationModules_UPPERCASE_LOWERCASE; + + if ( (nConversion & 0x04) == 4 ) // vbWide + nType |= ::com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH; + else if ( (nConversion & 0x08) == 8 ) // vbNarrow + nType |= ::com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH; + + if ( (nConversion & 0x10) == 16) // vbKatakana + nType |= ::com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA; + else if ( (nConversion & 0x20) == 32 ) // vbHiragana + nType |= ::com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA; + + String aNewStr( aOldStr ); + if( nType != 0 ) + { + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + ::utl::TransliterationWrapper aTransliterationWrapper( xSMgr,nType ); + com::sun::star::uno::Sequence<sal_Int32> aOffsets; + aTransliterationWrapper.loadModuleIfNeeded( nLanguage ); + aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets ); + } + + if ( (nConversion & 0x40) == 64 ) // vbUnicode + { + // convert the string to byte string, preserving unicode (2 bytes per character) + USHORT nSize = aNewStr.Len()*2; + const sal_Unicode* pSrc = aNewStr.GetBuffer(); + sal_Char* pChar = new sal_Char[nSize+1]; + for( USHORT i=0; i < nSize; i++ ) + { + pChar[i] = static_cast< sal_Char >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff ); + if( i%2 ) + pSrc++; + } + pChar[nSize] = '\0'; + ::rtl::OString aOStr(pChar); + + // there is no concept about default codepage in unix. so it is incorrectly in unix + ::rtl::OUString aOUStr = ::rtl::OStringToOUString(aOStr, osl_getThreadTextEncoding()); + aNewStr = String(aOUStr); + rPar.Get(0)->PutString( aNewStr ); + return; + } + else if ( (nConversion & 0x80) == 128 ) // vbFromUnicode + { + ::rtl::OUString aOUStr(aNewStr); + // there is no concept about default codepage in unix. so it is incorrectly in unix + ::rtl::OString aOStr = ::rtl::OUStringToOString(aNewStr,osl_getThreadTextEncoding()); + const sal_Char* pChar = aOStr.getStr(); + USHORT nArraySize = static_cast< USHORT >( aOStr.getLength() ); + SbxDimArray* pArray = new SbxDimArray(SbxBYTE); + bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() ); + if(nArraySize) + { + if( bIncIndex ) + pArray->AddDim( 1, nArraySize ); + else + pArray->AddDim( 0, nArraySize-1 ); + } + else + { + pArray->unoAddDim( 0, -1 ); + } + + for( USHORT i=0; i< nArraySize; i++) + { + SbxVariable* pNew = new SbxVariable( SbxBYTE ); + pNew->PutByte(*pChar); + pChar++; + pNew->SetFlag( SBX_WRITE ); + short index = i; + if( bIncIndex ) + ++index; + pArray->Put( pNew, &index ); + } + + SbxVariableRef refVar = rPar.Get(0); + USHORT nFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->PutObject( pArray ); + refVar->SetFlags( nFlags ); + refVar->SetParameters( NULL ); + return; + } + + rPar.Get(0)->PutString(aNewStr); +} + + +RTLFUNC(Beep) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + Sound::Beep(); +} + +RTLFUNC(Load) +{ + (void)pBasic; + (void)bWrite; + + if( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Diesen Call einfach an das Object weiterreichen + SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject(); + if( pObj && pObj->IsA( TYPE( SbxObject ) ) ) + { + SbxVariable* pVar = ((SbxObject*)pObj)-> + Find( String( RTL_CONSTASCII_USTRINGPARAM("Load") ), SbxCLASS_METHOD ); + if( pVar ) + pVar->GetInteger(); + } +} + +RTLFUNC(Unload) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // Diesen Call einfach an das Object weitereichen + SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject(); + if( pObj && pObj->IsA( TYPE( SbxObject ) ) ) + { + SbxVariable* pVar = ((SbxObject*)pObj)-> + Find( String( RTL_CONSTASCII_USTRINGPARAM("Unload") ), SbxCLASS_METHOD ); + if( pVar ) + pVar->GetInteger(); + } +} + +RTLFUNC(LoadPicture) +{ + (void)pBasic; + (void)bWrite; + + if( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aFileURL = getFullPath( rPar.Get(1)->GetString() ); + SvStream* pStream = utl::UcbStreamHelper::CreateStream( aFileURL, STREAM_READ ); + if( pStream != NULL ) + { + Bitmap aBmp; + *pStream >> aBmp; + Graphic aGraphic( aBmp ); + + SbxObjectRef xRef = new SbStdPicture; + ((SbStdPicture*)(SbxObject*)xRef)->SetGraphic( aGraphic ); + rPar.Get(0)->PutObject( xRef ); + } + delete pStream; +} + +RTLFUNC(SavePicture) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if( rPar.Count() != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject(); + if( pObj->IsA( TYPE( SbStdPicture ) ) ) + { + SvFileStream aOStream( rPar.Get(2)->GetString(), STREAM_WRITE | STREAM_TRUNC ); + Graphic aGraphic = ((SbStdPicture*)pObj)->GetGraphic(); + aOStream << aGraphic; + } +} + + +//----------------------------------------------------------------------------------------- + +RTLFUNC(AboutStarBasic) +{ + (void)pBasic; + (void)bWrite; + (void)rPar; +} + +RTLFUNC(MsgBox) +{ + (void)pBasic; + (void)bWrite; + + static const WinBits nStyleMap[] = + { + WB_OK, // MB_OK + WB_OK_CANCEL, // MB_OKCANCEL + WB_ABORT_RETRY_IGNORE, // MB_ABORTRETRYIGNORE + WB_YES_NO_CANCEL, // MB_YESNOCANCEL + WB_YES_NO, // MB_YESNO + WB_RETRY_CANCEL // MB_RETRYCANCEL + }; + static const INT16 nButtonMap[] = + { + 2, // #define RET_CANCEL FALSE + 1, // #define RET_OK TRUE + 6, // #define RET_YES 2 + 7, // #define RET_NO 3 + 4 // #define RET_RETRY 4 + }; + + + USHORT nArgCount = (USHORT)rPar.Count(); + if( nArgCount < 2 || nArgCount > 6 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + WinBits nWinBits; + WinBits nType = 0; // MB_OK + if( nArgCount >= 3 ) + nType = (WinBits)rPar.Get(2)->GetInteger(); + WinBits nStyle = nType; + nStyle &= 15; // Bits 4-16 loeschen + if( nStyle > 5 ) + nStyle = 0; + + nWinBits = nStyleMap[ nStyle ]; + + WinBits nWinDefBits; + nWinDefBits = (WB_DEF_OK | WB_DEF_RETRY | WB_DEF_YES); + if( nType & 256 ) + { + if( nStyle == 5 ) + nWinDefBits = WB_DEF_CANCEL; + else if( nStyle == 2 ) + nWinDefBits = WB_DEF_RETRY; + else + nWinDefBits = (WB_DEF_CANCEL | WB_DEF_RETRY | WB_DEF_NO); + } + else if( nType & 512 ) + { + if( nStyle == 2) + nWinDefBits = WB_DEF_IGNORE; + else + nWinDefBits = WB_DEF_CANCEL; + } + else if( nStyle == 2) + nWinDefBits = WB_DEF_CANCEL; + nWinBits |= nWinDefBits; + + String aMsg = rPar.Get(1)->GetString(); + String aTitle; + if( nArgCount >= 4 ) + aTitle = rPar.Get(3)->GetString(); + else + aTitle = GetpApp()->GetAppName(); + + nType &= (16+32+64); + MessBox* pBox = 0; + Window* pParent = GetpApp()->GetDefDialogParent(); + switch( nType ) + { + case 16: + pBox = new ErrorBox( pParent, nWinBits, aMsg ); + break; + case 32: + pBox = new QueryBox( pParent, nWinBits, aMsg ); + break; + case 48: + pBox = new WarningBox( pParent, nWinBits, aMsg ); + break; + case 64: + pBox = new InfoBox( pParent, aMsg ); + break; + default: + pBox = new MessBox( pParent, nWinBits, aTitle, aMsg ); + } + pBox->SetText( aTitle ); + USHORT nRet = (USHORT)pBox->Execute(); + if( nRet == TRUE ) + nRet = 1; + + INT16 nMappedRet; + if( nStyle == 2 ) + { + nMappedRet = nRet; + if( nMappedRet == 0 ) + nMappedRet = 3; // Abort + } + else + nMappedRet = nButtonMap[ nRet ]; + + rPar.Get(0)->PutInteger( nMappedRet ); + delete pBox; +} + +RTLFUNC(SetAttr) // JSM +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if ( rPar.Count() == 3 ) + { + String aStr = rPar.Get(1)->GetString(); + INT16 nFlags = rPar.Get(2)->GetInteger(); + + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + sal_Bool bReadOnly = (nFlags & 0x0001) != 0; // ATTR_READONLY + xSFI->setReadOnly( aStr, bReadOnly ); + sal_Bool bHidden = (nFlags & 0x0002) != 0; // ATTR_HIDDEN + xSFI->setHidden( aStr, bHidden ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + // #57064 Bei virtuellen URLs den Real-Path extrahieren + DirEntry aEntry( aStr ); + String aFile = aEntry.GetFull(); + #ifdef WIN + int nErr = _dos_setfileattr( aFile.GetStr(),(unsigned ) nFlags ); + if ( nErr ) + { + if (errno == EACCES) + StarBASIC::Error( SbERR_ACCESS_DENIED ); + else + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + } + #endif + ByteString aByteFile( aFile, gsl_getSystemTextEncoding() ); + #ifdef WNT + if (!SetFileAttributes (aByteFile.GetBuffer(),(DWORD)nFlags)) + StarBASIC::Error(SbERR_FILE_NOT_FOUND); + #endif + #ifdef OS2 + FILESTATUS3 aFileStatus; + APIRET rc = DosQueryPathInfo(aByteFile.GetBuffer(),1, + &aFileStatus,sizeof(FILESTATUS3)); + if (!rc) + { + if (aFileStatus.attrFile != nFlags) + { + aFileStatus.attrFile = nFlags; + rc = DosSetPathInfo(aFile.GetStr(),1, + &aFileStatus,sizeof(FILESTATUS3),0); + if (rc) + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + } + } + else + StarBASIC::Error( SbERR_FILE_NOT_FOUND ); + #endif +#else + // Not implemented +#endif + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(Reset) // JSM +{ + (void)pBasic; + (void)bWrite; + (void)rPar; + + SbiIoSystem* pIO = pINST->GetIoSystem(); + if (pIO) + pIO->CloseAll(); +} + +RTLFUNC(DumpAllObjects) +{ + (void)pBasic; + (void)bWrite; + + USHORT nArgCount = (USHORT)rPar.Count(); + if( nArgCount < 2 || nArgCount > 3 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else if( !pBasic ) + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + else + { + SbxObject* p = pBasic; + while( p->GetParent() ) + p = p->GetParent(); + SvFileStream aStrm( rPar.Get( 1 )->GetString(), + STREAM_WRITE | STREAM_TRUNC ); + p->Dump( aStrm, rPar.Get( 2 )->GetBool() ); + aStrm.Close(); + if( aStrm.GetError() != SVSTREAM_OK ) + StarBASIC::Error( SbERR_IO_ERROR ); + } +} + + +RTLFUNC(FileExists) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + String aStr = rPar.Get(1)->GetString(); + BOOL bExists = FALSE; + + // <-- UCB + if( hasUno() ) + { + Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); + if( xSFI.is() ) + { + try + { + bExists = xSFI->exists( aStr ); + } + catch( Exception & ) + { + StarBASIC::Error( ERRCODE_IO_GENERAL ); + } + } + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + DirEntry aEntry( aStr ); + bExists = aEntry.Exists(); +#else + DirectoryItem aItem; + FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem ); + bExists = (nRet == FileBase::E_None); +#endif + } + rPar.Get(0)->PutBool( bExists ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(Partition) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 5 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + INT32 nNumber = rPar.Get(1)->GetLong(); + INT32 nStart = rPar.Get(2)->GetLong(); + INT32 nStop = rPar.Get(3)->GetLong(); + INT32 nInterval = rPar.Get(4)->GetLong(); + + if( nStart < 0 || nStop <= nStart || nInterval < 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // the Partition function inserts leading spaces before lowervalue and uppervalue + // so that they both have the same number of characters as the string + // representation of the value (Stop + 1). This ensures that if you use the output + // of the Partition function with several values of Number, the resulting text + // will be handled properly during any subsequent sort operation. + + // calculate the maximun number of characters before lowervalue and uppervalue + ::rtl::OUString aBeforeStart = ::rtl::OUString::valueOf( nStart - 1 ); + ::rtl::OUString aAfterStop = ::rtl::OUString::valueOf( nStop + 1 ); + INT32 nLen1 = aBeforeStart.getLength(); + INT32 nLen2 = aAfterStop.getLength(); + INT32 nLen = nLen1 >= nLen2 ? nLen1:nLen2; + + ::rtl::OUStringBuffer aRetStr( nLen * 2 + 1); + ::rtl::OUString aLowerValue; + ::rtl::OUString aUpperValue; + if( nNumber < nStart ) + { + aUpperValue = aBeforeStart; + } + else if( nNumber > nStop ) + { + aLowerValue = aAfterStop; + } + else + { + INT32 nLowerValue = nNumber; + INT32 nUpperValue = nLowerValue; + if( nInterval > 1 ) + { + nLowerValue = ((( nNumber - nStart ) / nInterval ) * nInterval ) + nStart; + nUpperValue = nLowerValue + nInterval - 1; + } + + aLowerValue = ::rtl::OUString::valueOf( nLowerValue ); + aUpperValue = ::rtl::OUString::valueOf( nUpperValue ); + } + + nLen1 = aLowerValue.getLength(); + nLen2 = aUpperValue.getLength(); + + if( nLen > nLen1 ) + { + // appending the leading spaces for the lowervalue + for ( INT32 i= (nLen - nLen1) ; i > 0; --i ) + aRetStr.appendAscii(" "); + } + aRetStr.append( aLowerValue ).appendAscii(":"); + if( nLen > nLen2 ) + { + // appending the leading spaces for the uppervalue + for ( INT32 i= (nLen - nLen2) ; i > 0; --i ) + aRetStr.appendAscii(" "); + } + aRetStr.append( aUpperValue ); + rPar.Get(0)->PutString( String(aRetStr.makeStringAndClear()) ); +} diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx new file mode 100644 index 000000000000..dbd66a61575c --- /dev/null +++ b/basic/source/runtime/methods1.cxx @@ -0,0 +1,2610 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: methods1.cxx,v $ + * $Revision: 1.38 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#if defined(WIN) +#include <string.h> +#else +#include <stdlib.h> // getenv +#endif +#include <vcl/svapp.hxx> +#include <vcl/mapmod.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/timer.hxx> +#include <basic/sbxvar.hxx> +#ifndef _SBX_HXX +#include <basic/sbx.hxx> +#endif +#include <svtools/zforlist.hxx> +#include <tools/fsys.hxx> +#include <tools/urlobj.hxx> +#include <osl/file.hxx> + +#ifdef OS2 +#define INCL_DOS +#define INCL_DOSPROCESS +#include <svpm.h> +#endif + +#if defined(WIN) +#include <tools/svwin.h> +#endif + +#ifndef CLK_TCK +#define CLK_TCK CLOCKS_PER_SEC +#endif + +#include <vcl/jobset.hxx> + +#include "sbintern.hxx" +#include "runtime.hxx" +#include "stdobj.hxx" +#include "rtlproto.hxx" +#include "dllmgr.hxx" +#include <iosys.hxx> +#include "sbunoobj.hxx" +#include "propacc.hxx" + + +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/i18n/XCalendar.hpp> + +using namespace comphelper; +using namespace com::sun::star::uno; +using namespace com::sun::star::i18n; + + +static Reference< XCalendar > getLocaleCalendar( void ) +{ + static Reference< XCalendar > xCalendar; + if( !xCalendar.is() ) + { + Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); + if( xSMgr.is() ) + { + xCalendar = Reference< XCalendar >( xSMgr->createInstance + ( ::rtl::OUString::createFromAscii( "com.sun.star.i18n.LocaleCalendar" ) ), UNO_QUERY ); + } + } + + static com::sun::star::lang::Locale aLastLocale; + static bool bNeedsInit = true; + + com::sun::star::lang::Locale aLocale = Application::GetSettings().GetLocale(); + bool bNeedsReload = false; + if( bNeedsInit ) + { + bNeedsInit = false; + bNeedsReload = true; + } + else if( aLocale.Language != aLastLocale.Language || + aLocale.Country != aLastLocale.Country ) + { + bNeedsReload = true; + } + if( bNeedsReload ) + { + aLastLocale = aLocale; + xCalendar->loadDefaultCalendar( aLocale ); + } + return xCalendar; +} + + +RTLFUNC(CBool) // JSM +{ + (void)pBasic; + (void)bWrite; + + BOOL bVal = FALSE; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + bVal = pSbxVariable->GetBool(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutBool(bVal); +} + +RTLFUNC(CByte) // JSM +{ + (void)pBasic; + (void)bWrite; + + BYTE nByte = 0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + nByte = pSbxVariable->GetByte(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutByte(nByte); +} + +RTLFUNC(CCur) // JSM +{ + (void)pBasic; + (void)bWrite; + + SbxINT64 nCur; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + nCur = pSbxVariable->GetCurrency(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutCurrency( nCur ); +} + +RTLFUNC(CDec) // JSM +{ + (void)pBasic; + (void)bWrite; + +#ifdef WNT + SbxDecimal* pDec = NULL; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + pDec = pSbxVariable->GetDecimal(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutDecimal( pDec ); +#else + rPar.Get(0)->PutEmpty(); + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); +#endif +} + +RTLFUNC(CDate) // JSM +{ + (void)pBasic; + (void)bWrite; + + double nVal = 0.0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + nVal = pSbxVariable->GetDate(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutDate(nVal); +} + +RTLFUNC(CDbl) // JSM +{ + (void)pBasic; + (void)bWrite; + + double nVal = 0.0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + if( pSbxVariable->GetType() == SbxSTRING ) + { + // AB #41690 , String holen + String aScanStr = pSbxVariable->GetString(); + SbError Error = SbxValue::ScanNumIntnl( aScanStr, nVal ); + if( Error != SbxERR_OK ) + StarBASIC::Error( Error ); + } + else + { + nVal = pSbxVariable->GetDouble(); + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutDouble(nVal); +} + +RTLFUNC(CInt) // JSM +{ + (void)pBasic; + (void)bWrite; + + INT16 nVal = 0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + nVal = pSbxVariable->GetInteger(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutInteger(nVal); +} + +RTLFUNC(CLng) // JSM +{ + (void)pBasic; + (void)bWrite; + + INT32 nVal = 0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + nVal = pSbxVariable->GetLong(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutLong(nVal); +} + +RTLFUNC(CSng) // JSM +{ + (void)pBasic; + (void)bWrite; + + float nVal = (float)0.0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + if( pSbxVariable->GetType() == SbxSTRING ) + { + // AB #41690 , String holen + double dVal = 0.0; + String aScanStr = pSbxVariable->GetString(); + SbError Error = SbxValue::ScanNumIntnl( aScanStr, dVal, /*bSingle=*/TRUE ); + if( SbxBase::GetError() == SbxERR_OK && Error != SbxERR_OK ) + StarBASIC::Error( Error ); + nVal = (float)dVal; + } + else + { + nVal = pSbxVariable->GetSingle(); + } + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutSingle(nVal); +} + +RTLFUNC(CStr) // JSM +{ + (void)pBasic; + (void)bWrite; + + String aString; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + aString = pSbxVariable->GetString(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutString(aString); +} + +RTLFUNC(CVar) // JSM +{ + (void)pBasic; + (void)bWrite; + + SbxValues aVals( SbxVARIANT ); + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + pSbxVariable->Get( aVals ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->Put( aVals ); +} + +RTLFUNC(CVErr) +{ + (void)pBasic; + (void)bWrite; + + INT16 nErrCode = 0; + if ( rPar.Count() == 2 ) + { + SbxVariable *pSbxVariable = rPar.Get(1); + nErrCode = pSbxVariable->GetInteger(); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + rPar.Get(0)->PutErr( nErrCode ); +} + +RTLFUNC(Iif) // JSM +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 4 ) + { + if (rPar.Get(1)->GetBool()) + *rPar.Get(0) = *rPar.Get(2); + else + *rPar.Get(0) = *rPar.Get(3); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(GetSystemType) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + // Removed for SRC595 + rPar.Get(0)->PutInteger( -1 ); +} + +RTLFUNC(GetGUIType) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // 17.7.2000 Make simple solution for testtool / fat office +#if defined (WNT) + rPar.Get(0)->PutInteger( 1 ); +#elif defined OS2 + rPar.Get(0)->PutInteger( 2 ); +#elif defined UNX + rPar.Get(0)->PutInteger( 4 ); +#else + rPar.Get(0)->PutInteger( -1 ); +#endif + } +} + +RTLFUNC(Red) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + ULONG nRGB = (ULONG)rPar.Get(1)->GetLong(); + nRGB &= 0x00FF0000; + nRGB >>= 16; + rPar.Get(0)->PutInteger( (INT16)nRGB ); + } +} + +RTLFUNC(Green) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + ULONG nRGB = (ULONG)rPar.Get(1)->GetLong(); + nRGB &= 0x0000FF00; + nRGB >>= 8; + rPar.Get(0)->PutInteger( (INT16)nRGB ); + } +} + +RTLFUNC(Blue) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + ULONG nRGB = (ULONG)rPar.Get(1)->GetLong(); + nRGB &= 0x000000FF; + rPar.Get(0)->PutInteger( (INT16)nRGB ); + } +} + + +RTLFUNC(Switch) +{ + (void)pBasic; + (void)bWrite; + + USHORT nCount = rPar.Count(); + if( !(nCount & 0x0001 )) + // Anzahl der Argumente muss ungerade sein + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + USHORT nCurExpr = 1; + while( nCurExpr < (nCount-1) ) + { + if( rPar.Get( nCurExpr )->GetBool()) + { + (*rPar.Get(0)) = *(rPar.Get(nCurExpr+1)); + return; + } + nCurExpr += 2; + } + rPar.Get(0)->PutNull(); +} + +//i#64882# Common wait impl for existing Wait and new WaitUntil +// rtl functions +void Wait_Impl( bool bDurationBased, SbxArray& rPar ) +{ + if( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + long nWait = 0; + if ( bDurationBased ) + { + double dWait = rPar.Get(1)->GetDouble(); + double dNow = Now_Impl(); + double dSecs = (double)( ( dWait - dNow ) * (double)( 24.0*3600.0) ); + nWait = (long)( dSecs * 1000 ); // wait in thousands of sec + } + else + nWait = rPar.Get(1)->GetLong(); + if( nWait < 0 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + Timer aTimer; + aTimer.SetTimeout( nWait ); + aTimer.Start(); + while ( aTimer.IsActive() ) + Application::Yield(); +} + +//i#64882# +RTLFUNC(Wait) +{ + (void)pBasic; + (void)bWrite; + Wait_Impl( false, rPar ); +} + +//i#64882# add new WaitUntil ( for application.wait ) +// share wait_impl with 'normal' oobasic wait +RTLFUNC(WaitUntil) +{ + (void)pBasic; + (void)bWrite; + Wait_Impl( true, rPar ); +} + +RTLFUNC(GetGUIVersion) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + // Removed for SRC595 + rPar.Get(0)->PutLong( -1 ); + } +} + +RTLFUNC(Choose) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + INT16 nIndex = rPar.Get(1)->GetInteger(); + USHORT nCount = rPar.Count(); + nCount--; + if( nCount == 1 || nIndex > (nCount-1) || nIndex < 1 ) + { + rPar.Get(0)->PutNull(); + return; + } + (*rPar.Get(0)) = *(rPar.Get(nIndex+1)); +} + + +RTLFUNC(Trim) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + String aStr( rPar.Get(1)->GetString() ); + aStr.EraseLeadingChars(); + aStr.EraseTrailingChars(); + rPar.Get(0)->PutString( aStr ); + } +} + +RTLFUNC(GetSolarVersion) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutLong( (INT32)SUPD ); +} + +RTLFUNC(TwipsPerPixelX) +{ + (void)pBasic; + (void)bWrite; + + INT32 nResult = 0; + Size aSize( 100,0 ); + MapMode aMap( MAP_TWIP ); + OutputDevice* pDevice = Application::GetDefaultDevice(); + if( pDevice ) + { + aSize = pDevice->PixelToLogic( aSize, aMap ); + nResult = aSize.Width() / 100; + } + rPar.Get(0)->PutLong( nResult ); +} + +RTLFUNC(TwipsPerPixelY) +{ + (void)pBasic; + (void)bWrite; + + INT32 nResult = 0; + Size aSize( 0,100 ); + MapMode aMap( MAP_TWIP ); + OutputDevice* pDevice = Application::GetDefaultDevice(); + if( pDevice ) + { + aSize = pDevice->PixelToLogic( aSize, aMap ); + nResult = aSize.Height() / 100; + } + rPar.Get(0)->PutLong( nResult ); +} + + +RTLFUNC(FreeLibrary) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + ByteString aByteDLLName( rPar.Get(1)->GetString(), gsl_getSystemTextEncoding() ); + pINST->GetDllMgr()->FreeDll( aByteDLLName ); +} +bool IsBaseIndexOne() +{ + bool result = false; + if ( pINST && pINST->pRun ) + { + USHORT res = pINST->pRun->GetBase(); + if ( res ) + result = true; + } + return result; +} + +RTLFUNC(Array) +{ + (void)pBasic; + (void)bWrite; + + SbxDimArray* pArray = new SbxDimArray( SbxVARIANT ); + USHORT nArraySize = rPar.Count() - 1; + + // Option Base zunaechst ignorieren (kennt leider nur der Compiler) + bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() ); + if( nArraySize ) + { + if ( bIncIndex ) + pArray->AddDim( 1, nArraySize ); + else + pArray->AddDim( 0, nArraySize-1 ); + } + else + { + pArray->unoAddDim( 0, -1 ); + } + + // Parameter ins Array uebernehmen + // ATTENTION: Using type USHORT for loop variable is + // mandatory to workaround a problem with the + // Solaris Intel compiler optimizer! See i104354 + for( USHORT i = 0 ; i < nArraySize ; i++ ) + { + SbxVariable* pVar = rPar.Get(i+1); + SbxVariable* pNew = new SbxVariable( *pVar ); + pNew->SetFlag( SBX_WRITE ); + short index = static_cast< short >(i); + if ( bIncIndex ) + ++index; + pArray->Put( pNew, &index ); + } + + // Array zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + USHORT nFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->PutObject( pArray ); + refVar->SetFlags( nFlags ); + refVar->SetParameters( NULL ); +} + + +// Featurewunsch #57868 +// Die Funktion liefert ein Variant-Array, wenn keine Parameter angegeben +// werden, wird ein leeres Array erzeugt (entsprechend dim a(), entspricht +// einer Sequence der Laenge 0 in Uno). +// Wenn Parameter angegeben sind, wird fuer jeden eine Dimension erzeugt +// DimArray( 2, 2, 4 ) entspricht DIM a( 2, 2, 4 ) +// Das Array ist immer vom Typ Variant +RTLFUNC(DimArray) +{ + (void)pBasic; + (void)bWrite; + + SbxDimArray * pArray = new SbxDimArray( SbxVARIANT ); + USHORT nArrayDims = rPar.Count() - 1; + if( nArrayDims > 0 ) + { + for( USHORT i = 0; i < nArrayDims ; i++ ) + { + INT32 ub = rPar.Get(i+1)->GetLong(); + if( ub < 0 ) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + ub = 0; + } + pArray->AddDim32( 0, ub ); + } + } + else + pArray->unoAddDim( 0, -1 ); + + // Array zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + USHORT nFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->PutObject( pArray ); + refVar->SetFlags( nFlags ); + refVar->SetParameters( NULL ); +} + +/* + * FindObject und FindPropertyObject ermoeglichen es, + * Objekte und Properties vom Typ Objekt zur Laufzeit + * ueber ihren Namen als String-Parameter anzusprechen. + * + * Bsp.: + * MyObj.Prop1.Bla = 5 + * + * entspricht: + * dim ObjVar as Object + * dim ObjProp as Object + * ObjName$ = "MyObj" + * ObjVar = FindObject( ObjName$ ) + * PropName$ = "Prop1" + * ObjProp = FindPropertyObject( ObjVar, PropName$ ) + * ObjProp.Bla = 5 + * + * Dabei koennen die Namen zur Laufzeit dynamisch + * erzeugt werden und, so dass z.B. ueber Controls + * "TextEdit1" bis "TextEdit5" in einem Dialog in + * einer Schleife iteriert werden kann. + */ + +// Objekt ueber den Namen ansprechen +// 1. Parameter = Name des Objekts als String +RTLFUNC(FindObject) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen einen Parameter + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // 1. Parameter ist der Name + String aNameStr = rPar.Get(1)->GetString(); + + // Basic-Suchfunktion benutzen + SbxBase* pFind = StarBASIC::FindSBXInCurrentScope( aNameStr ); + SbxObject* pFindObj = NULL; + if( pFind ) + pFindObj = PTR_CAST(SbxObject,pFind); + /* + if( !pFindObj ) + { + StarBASIC::Error( SbERR_VAR_UNDEFINED ); + return; + } + */ + + // Objekt zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( pFindObj ); +} + +// Objekt-Property in einem Objekt ansprechen +// 1. Parameter = Objekt +// 2. Parameter = Name der Property als String +RTLFUNC(FindPropertyObject) +{ + (void)pBasic; + (void)bWrite; + + // Wir brauchen 2 Parameter + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // 1. Parameter holen, muss Objekt sein + SbxBase* pObjVar = (SbxObject*)rPar.Get(1)->GetObject(); + SbxObject* pObj = NULL; + if( pObjVar ) + pObj = PTR_CAST(SbxObject,pObjVar); + if( !pObj && pObjVar && pObjVar->ISA(SbxVariable) ) + { + SbxBase* pObjVarObj = ((SbxVariable*)pObjVar)->GetObject(); + pObj = PTR_CAST(SbxObject,pObjVarObj); + } + /* + if( !pObj ) + { + StarBASIC::Error( SbERR_VAR_UNDEFINED ); + return; + } + */ + + // 2. Parameter ist der Name + String aNameStr = rPar.Get(2)->GetString(); + + // Jetzt muss ein Objekt da sein, sonst Error + SbxObject* pFindObj = NULL; + if( pObj ) + { + // Im Objekt nach Objekt suchen + SbxVariable* pFindVar = pObj->Find( aNameStr, SbxCLASS_OBJECT ); + pFindObj = PTR_CAST(SbxObject,pFindVar); + } + else + StarBASIC::Error( SbERR_BAD_PARAMETER ); + + // Objekt zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( pFindObj ); +} + + + +BOOL lcl_WriteSbxVariable( const SbxVariable& rVar, SvStream* pStrm, + BOOL bBinary, short nBlockLen, BOOL bIsArray ) +{ + ULONG nFPos = pStrm->Tell(); + + BOOL bIsVariant = !rVar.IsFixed(); + SbxDataType eType = rVar.GetType(); + + switch( eType ) + { + case SbxBOOL: + case SbxCHAR: + case SbxBYTE: + if( bIsVariant ) + *pStrm << (USHORT)SbxBYTE; // VarType Id + *pStrm << rVar.GetByte(); + break; + + case SbxEMPTY: + case SbxNULL: + case SbxVOID: + case SbxINTEGER: + case SbxUSHORT: + case SbxINT: + case SbxUINT: + if( bIsVariant ) + *pStrm << (USHORT)SbxINTEGER; // VarType Id + *pStrm << rVar.GetInteger(); + break; + + case SbxLONG: + case SbxULONG: + case SbxLONG64: + case SbxULONG64: + if( bIsVariant ) + *pStrm << (USHORT)SbxLONG; // VarType Id + *pStrm << rVar.GetLong(); + break; + + case SbxSINGLE: + if( bIsVariant ) + *pStrm << (USHORT)eType; // VarType Id + *pStrm << rVar.GetSingle(); + break; + + case SbxDOUBLE: + case SbxCURRENCY: + case SbxDATE: + if( bIsVariant ) + *pStrm << (USHORT)eType; // VarType Id + *pStrm << rVar.GetDouble(); + break; + + case SbxSTRING: + case SbxLPSTR: + { + const String& rStr = rVar.GetString(); + if( !bBinary || bIsArray ) + { + if( bIsVariant ) + *pStrm << (USHORT)SbxSTRING; + pStrm->WriteByteString( rStr, gsl_getSystemTextEncoding() ); + //*pStrm << rStr; + } + else + { + // ohne Laengenangabe! ohne Endekennung! + // What does that mean for Unicode?! Choosing conversion to ByteString... + ByteString aByteStr( rStr, gsl_getSystemTextEncoding() ); + *pStrm << (const char*)aByteStr.GetBuffer(); + //*pStrm << (const char*)rStr.GetStr(); + } + } + break; + + default: + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return FALSE; + } + + if( nBlockLen ) + pStrm->Seek( nFPos + nBlockLen ); + return pStrm->GetErrorCode() ? FALSE : TRUE; +} + +BOOL lcl_ReadSbxVariable( SbxVariable& rVar, SvStream* pStrm, + BOOL bBinary, short nBlockLen, BOOL bIsArray ) +{ + (void)bBinary; + (void)bIsArray; + + double aDouble; + + ULONG nFPos = pStrm->Tell(); + + BOOL bIsVariant = !rVar.IsFixed(); + SbxDataType eVarType = rVar.GetType(); + + SbxDataType eSrcType = eVarType; + if( bIsVariant ) + { + USHORT nTemp; + *pStrm >> nTemp; + eSrcType = (SbxDataType)nTemp; + } + + switch( eSrcType ) + { + case SbxBOOL: + case SbxCHAR: + case SbxBYTE: + { + BYTE aByte; + *pStrm >> aByte; + rVar.PutByte( aByte ); + } + break; + + case SbxEMPTY: + case SbxNULL: + case SbxVOID: + case SbxINTEGER: + case SbxUSHORT: + case SbxINT: + case SbxUINT: + { + INT16 aInt; + *pStrm >> aInt; + rVar.PutInteger( aInt ); + } + break; + + case SbxLONG: + case SbxULONG: + case SbxLONG64: + case SbxULONG64: + { + INT32 aInt; + *pStrm >> aInt; + rVar.PutLong( aInt ); + } + break; + + case SbxSINGLE: + { + float nS; + *pStrm >> nS; + rVar.PutSingle( nS ); + } + break; + + case SbxDOUBLE: + case SbxCURRENCY: + { + *pStrm >> aDouble; + rVar.PutDouble( aDouble ); + } + break; + + case SbxDATE: + { + *pStrm >> aDouble; + rVar.PutDate( aDouble ); + } + break; + + case SbxSTRING: + case SbxLPSTR: + { + String aStr; + pStrm->ReadByteString( aStr, gsl_getSystemTextEncoding() ); + rVar.PutString( aStr ); + } + break; + + default: + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return FALSE; + } + + if( nBlockLen ) + pStrm->Seek( nFPos + nBlockLen ); + return pStrm->GetErrorCode() ? FALSE : TRUE; +} + + +// nCurDim = 1...n +BOOL lcl_WriteReadSbxArray( SbxDimArray& rArr, SvStream* pStrm, + BOOL bBinary, short nCurDim, short* pOtherDims, BOOL bWrite ) +{ + DBG_ASSERT( nCurDim > 0,"Bad Dim"); + short nLower, nUpper; + if( !rArr.GetDim( nCurDim, nLower, nUpper ) ) + return FALSE; + for( short nCur = nLower; nCur <= nUpper; nCur++ ) + { + pOtherDims[ nCurDim-1 ] = nCur; + if( nCurDim != 1 ) + lcl_WriteReadSbxArray(rArr, pStrm, bBinary, nCurDim-1, pOtherDims, bWrite); + else + { + SbxVariable* pVar = rArr.Get( (const short*)pOtherDims ); + BOOL bRet; + if( bWrite ) + bRet = lcl_WriteSbxVariable(*pVar, pStrm, bBinary, 0, TRUE ); + else + bRet = lcl_ReadSbxVariable(*pVar, pStrm, bBinary, 0, TRUE ); + if( !bRet ) + return FALSE; + } + } + return TRUE; +} + +void PutGet( SbxArray& rPar, BOOL bPut ) +{ + // Wir brauchen 3 Parameter + if ( rPar.Count() != 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nFileNo = rPar.Get(1)->GetInteger(); + SbxVariable* pVar2 = rPar.Get(2); + BOOL bHasRecordNo = (BOOL)(pVar2->GetType() != SbxEMPTY); + long nRecordNo = pVar2->GetLong(); + if ( nFileNo < 1 || ( bHasRecordNo && nRecordNo < 1 ) ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + nRecordNo--; // wir moegen's ab 0! + SbiIoSystem* pIO = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nFileNo ); + // das File muss Random (feste Record-Laenge) oder Binary sein + if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_RANDOM)) ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + + SvStream* pStrm = pSbStrm->GetStrm(); + BOOL bRandom = pSbStrm->IsRandom(); + short nBlockLen = bRandom ? pSbStrm->GetBlockLen() : 0; + + if( bPut ) + { + // Datei aufplustern, falls jemand uebers Dateiende hinaus geseekt hat + pSbStrm->ExpandFile(); + } + + // auf die Startposition seeken + if( bHasRecordNo ) + { + ULONG nFilePos = bRandom ? (ULONG)(nBlockLen*nRecordNo) : (ULONG)nRecordNo; + pStrm->Seek( nFilePos ); + } + + SbxDimArray* pArr = 0; + SbxVariable* pVar = rPar.Get(3); + if( pVar->GetType() & SbxARRAY ) + { + SbxBase* pParObj = pVar->GetObject(); + pArr = PTR_CAST(SbxDimArray,pParObj); + } + + BOOL bRet; + + if( pArr ) + { + ULONG nFPos = pStrm->Tell(); + short nDims = pArr->GetDims(); + short* pDims = new short[ nDims ]; + bRet = lcl_WriteReadSbxArray(*pArr,pStrm,!bRandom,nDims,pDims,bPut); + delete [] pDims; + if( nBlockLen ) + pStrm->Seek( nFPos + nBlockLen ); + } + else + { + if( bPut ) + bRet = lcl_WriteSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, FALSE); + else + bRet = lcl_ReadSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, FALSE); + } + if( !bRet || pStrm->GetErrorCode() ) + StarBASIC::Error( SbERR_IO_ERROR ); +} + +RTLFUNC(Put) +{ + (void)pBasic; + (void)bWrite; + + PutGet( rPar, TRUE ); +} + +RTLFUNC(Get) +{ + (void)pBasic; + (void)bWrite; + + PutGet( rPar, FALSE ); +} + +RTLFUNC(Environ) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + String aResult; + // sollte ANSI sein, aber unter Win16 in DLL nicht moeglich +#if defined(WIN) + LPSTR lpszEnv = GetDOSEnvironment(); + String aCompareStr( rPar.Get(1)->GetString() ); + aCompareStr += '='; + const char* pCompare = aCompareStr.GetStr(); + int nCompareLen = aCompareStr.Len(); + while ( *lpszEnv ) + { + // Es werden alle EnvString in der Form ENV=VAL 0-terminiert + // aneinander gehaengt. + + if ( strnicmp( pCompare, lpszEnv, nCompareLen ) == 0 ) + { + aResult = (const char*)(lpszEnv+nCompareLen); + rPar.Get(0)->PutString( aResult ); + return; + } + lpszEnv += lstrlen( lpszEnv ) + 1; // Next Enviroment-String + } +#else + ByteString aByteStr( rPar.Get(1)->GetString(), gsl_getSystemTextEncoding() ); + const char* pEnvStr = getenv( aByteStr.GetBuffer() ); + if ( pEnvStr ) + aResult = String::CreateFromAscii( pEnvStr ); +#endif + rPar.Get(0)->PutString( aResult ); +} + +static double GetDialogZoomFactor( BOOL bX, long nValue ) +{ + OutputDevice* pDevice = Application::GetDefaultDevice(); + double nResult = 0; + if( pDevice ) + { + Size aRefSize( nValue, nValue ); +#ifndef WIN + Fraction aFracX( 1, 26 ); +#else + Fraction aFracX( 1, 23 ); +#endif + Fraction aFracY( 1, 24 ); + MapMode aMap( MAP_APPFONT, Point(), aFracX, aFracY ); + Size aScaledSize = pDevice->LogicToPixel( aRefSize, aMap ); + aRefSize = pDevice->LogicToPixel( aRefSize, MapMode(MAP_TWIP) ); + + double nRef, nScaled; + if( bX ) + { + nRef = aRefSize.Width(); + nScaled = aScaledSize.Width(); + } + else + { + nRef = aRefSize.Height(); + nScaled = aScaledSize.Height(); + } + nResult = nScaled / nRef; + } + return nResult; +} + + +RTLFUNC(GetDialogZoomFactorX) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + rPar.Get(0)->PutDouble( GetDialogZoomFactor( TRUE, rPar.Get(1)->GetLong() )); +} + +RTLFUNC(GetDialogZoomFactorY) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + rPar.Get(0)->PutDouble( GetDialogZoomFactor( FALSE, rPar.Get(1)->GetLong())); +} + + +RTLFUNC(EnableReschedule) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutEmpty(); + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + if( pINST ) + pINST->EnableReschedule( rPar.Get(1)->GetBool() ); +} + +RTLFUNC(GetSystemTicks) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + rPar.Get(0)->PutLong( Time::GetSystemTicks() ); +} + +RTLFUNC(GetPathSeparator) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + rPar.Get(0)->PutString( DirEntry::GetAccessDelimiter() ); +} + +RTLFUNC(ResolvePath) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + String aStr = rPar.Get(1)->GetString(); + DirEntry aEntry( aStr ); + //if( aEntry.IsVirtual() ) + //aStr = aEntry.GetRealPathFromVirtualURL(); + rPar.Get(0)->PutString( aStr ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(TypeLen) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + SbxDataType eType = rPar.Get(1)->GetType(); + INT16 nLen = 0; + switch( eType ) + { + case SbxEMPTY: + case SbxNULL: + case SbxVECTOR: + case SbxARRAY: + case SbxBYREF: + case SbxVOID: + case SbxHRESULT: + case SbxPOINTER: + case SbxDIMARRAY: + case SbxCARRAY: + case SbxUSERDEF: + nLen = 0; + break; + + case SbxINTEGER: + case SbxERROR: + case SbxUSHORT: + case SbxINT: + case SbxUINT: + nLen = 2; + break; + + case SbxLONG: + case SbxSINGLE: + case SbxULONG: + nLen = 4; + break; + + case SbxDOUBLE: + case SbxCURRENCY: + case SbxDATE: + case SbxLONG64: + case SbxULONG64: + nLen = 8; + break; + + case SbxOBJECT: + case SbxVARIANT: + case SbxDATAOBJECT: + nLen = 0; + break; + + case SbxCHAR: + case SbxBYTE: + case SbxBOOL: + nLen = 1; + break; + + case SbxLPSTR: + case SbxLPWSTR: + case SbxCoreSTRING: + case SbxSTRING: + nLen = (INT16)rPar.Get(1)->GetString().Len(); + break; + + default: + nLen = 0; + } + rPar.Get(0)->PutInteger( nLen ); + } +} + + +// Uno-Struct eines beliebigen Typs erzeugen +// 1. Parameter == Klassename, weitere Parameter zur Initialisierung +RTLFUNC(CreateUnoStruct) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_CreateUnoStruct( pBasic, rPar, bWrite ); +} + +// Uno-Service erzeugen +// 1. Parameter == Service-Name +RTLFUNC(CreateUnoService) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_CreateUnoService( pBasic, rPar, bWrite ); +} + +RTLFUNC(CreateUnoServiceWithArguments) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_CreateUnoServiceWithArguments( pBasic, rPar, bWrite ); +} + + +RTLFUNC(CreateUnoValue) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_CreateUnoValue( pBasic, rPar, bWrite ); +} + + +// ServiceManager liefern (keine Parameter) +RTLFUNC(GetProcessServiceManager) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_GetProcessServiceManager( pBasic, rPar, bWrite ); +} + +// PropertySet erzeugen +// 1. Parameter == Sequence<PropertyValue> +RTLFUNC(CreatePropertySet) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_CreatePropertySet( pBasic, rPar, bWrite ); +} + +// Abfragen, ob ein Interface unterstuetzt wird +// Mehrere Interface-Namen als Parameter +RTLFUNC(HasUnoInterfaces) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_HasInterfaces( pBasic, rPar, bWrite ); +} + +// Abfragen, ob ein Basic-Objekt ein Uno-Struct repraesentiert +RTLFUNC(IsUnoStruct) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_IsUnoStruct( pBasic, rPar, bWrite ); +} + +// Abfragen, ob zwei Uno-Objekte identisch sind +RTLFUNC(EqualUnoObjects) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_EqualUnoObjects( pBasic, rPar, bWrite ); +} + +// Instanciate "com.sun.star.awt.UnoControlDialog" on basis +// of a DialogLibrary entry: Convert from XML-ByteSequence +// and attach events. Implemented in classes\eventatt.cxx +void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); + +RTLFUNC(CreateUnoDialog) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_CreateUnoDialog( pBasic, rPar, bWrite ); +} + +// Return the application standard lib as root scope +RTLFUNC(GlobalScope) +{ + (void)pBasic; + (void)bWrite; + + SbxObject* p = pBasic; + while( p->GetParent() ) + p = p->GetParent(); + + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( p ); +} + +// Helper functions to convert Url from/to system paths +RTLFUNC(ConvertToUrl) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + String aStr = rPar.Get(1)->GetString(); + INetURLObject aURLObj( aStr, INET_PROT_FILE ); + ::rtl::OUString aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE ); + if( !aFileURL.getLength() ) + ::osl::File::getFileURLFromSystemPath( aFileURL, aFileURL ); + if( !aFileURL.getLength() ) + aFileURL = aStr; + rPar.Get(0)->PutString( String(aFileURL) ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + +RTLFUNC(ConvertFromUrl) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() == 2 ) + { + String aStr = rPar.Get(1)->GetString(); + ::rtl::OUString aSysPath; + ::osl::File::getSystemPathFromFileURL( aStr, aSysPath ); + if( !aSysPath.getLength() ) + aSysPath = aStr; + rPar.Get(0)->PutString( String(aSysPath) ); + } + else + StarBASIC::Error( SbERR_BAD_ARGUMENT ); +} + + +// Provide DefaultContext +RTLFUNC(GetDefaultContext) +{ + (void)pBasic; + (void)bWrite; + + RTL_Impl_GetDefaultContext( pBasic, rPar, bWrite ); +} + + +RTLFUNC(Join) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if ( nParCount != 3 && nParCount != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + SbxBase* pParObj = rPar.Get(1)->GetObject(); + SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj); + if( pArr ) + { + if( pArr->GetDims() != 1 ) + StarBASIC::Error( SbERR_WRONG_DIMS ); // Syntax Error?! + + String aDelim; + if( nParCount == 3 ) + aDelim = rPar.Get(2)->GetString(); + else + aDelim = String::CreateFromAscii( " " ); + + String aRetStr; + short nLower, nUpper; + pArr->GetDim( 1, nLower, nUpper ); + for( short i = nLower ; i <= nUpper ; ++i ) + { + String aStr = pArr->Get( &i )->GetString(); + aRetStr += aStr; + if( i != nUpper ) + aRetStr += aDelim; + } + rPar.Get(0)->PutString( aRetStr ); + } + else + StarBASIC::Error( SbERR_MUST_HAVE_DIMS ); +} + + +typedef ::std::vector< String > StringVector; + +RTLFUNC(Split) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if ( nParCount < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aExpression = rPar.Get(1)->GetString(); + short nArraySize = 0; + StringVector vRet; + if( aExpression.Len() ) + { + String aDelim; + if( nParCount >= 3 ) + aDelim = rPar.Get(2)->GetString(); + else + aDelim = String::CreateFromAscii( " " ); + + INT32 nCount = -1; + if( nParCount == 4 ) + nCount = rPar.Get(3)->GetLong(); + + xub_StrLen nDelimLen = aDelim.Len(); + if( nDelimLen ) + { + xub_StrLen iSearch = STRING_NOTFOUND; + xub_StrLen iStart = 0; + do + { + bool bBreak = false; + if( nCount >= 0 && nArraySize == nCount - 1 ) + bBreak = true; + + iSearch = aExpression.Search( aDelim, iStart ); + String aSubStr; + if( iSearch != STRING_NOTFOUND && !bBreak ) + { + aSubStr = aExpression.Copy( iStart, iSearch - iStart ); + iStart = iSearch + nDelimLen; + } + else + { + aSubStr = aExpression.Copy( iStart ); + } + vRet.push_back( aSubStr ); + nArraySize++; + + if( bBreak ) + break; + } + while( iSearch != STRING_NOTFOUND ); + } + else + { + vRet.push_back( aExpression ); + nArraySize = 1; + } + } + + SbxDimArray* pArray = new SbxDimArray( SbxVARIANT ); + pArray->unoAddDim( 0, nArraySize-1 ); + + // Parameter ins Array uebernehmen + for( short i = 0 ; i < nArraySize ; i++ ) + { + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + xVar->PutString( vRet[i] ); + pArray->Put( (SbxVariable*)xVar, &i ); + } + + // Array zurueckliefern + SbxVariableRef refVar = rPar.Get(0); + USHORT nFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->PutObject( pArray ); + refVar->SetFlags( nFlags ); + refVar->SetParameters( NULL ); +} + +// MonthName(month[, abbreviate]) +RTLFUNC(MonthName) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if( nParCount != 2 && nParCount != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + Reference< XCalendar > xCalendar = getLocaleCalendar(); + if( !xCalendar.is() ) + { + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + return; + } + Sequence< CalendarItem > aMonthSeq = xCalendar->getMonths(); + sal_Int32 nMonthCount = aMonthSeq.getLength(); + + INT16 nVal = rPar.Get(1)->GetInteger(); + if( nVal < 1 || nVal > nMonthCount ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + BOOL bAbbreviate = false; + if( nParCount == 3 ) + bAbbreviate = rPar.Get(2)->GetBool(); + + const CalendarItem* pCalendarItems = aMonthSeq.getConstArray(); + const CalendarItem& rItem = pCalendarItems[nVal - 1]; + + ::rtl::OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName ); + rPar.Get(0)->PutString( String(aRetStr) ); +} + +// WeekdayName(weekday, abbreviate, firstdayofweek) +RTLFUNC(WeekdayName) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if( nParCount < 2 || nParCount > 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + Reference< XCalendar > xCalendar = getLocaleCalendar(); + if( !xCalendar.is() ) + { + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + return; + } + + Sequence< CalendarItem > aDaySeq = xCalendar->getDays(); + INT16 nDayCount = (INT16)aDaySeq.getLength(); + INT16 nDay = rPar.Get(1)->GetInteger(); + INT16 nFirstDay = 0; + if( nParCount == 4 ) + { + nFirstDay = rPar.Get(3)->GetInteger(); + if( nFirstDay < 0 || nFirstDay > 7 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + } + if( nFirstDay == 0 ) + nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 ); + + nDay = 1 + (nDay + nDayCount + nFirstDay - 2) % nDayCount; + if( nDay < 1 || nDay > nDayCount ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + BOOL bAbbreviate = false; + if( nParCount >= 3 ) + { + SbxVariable* pPar2 = rPar.Get(2); + if( !pPar2->IsErr() ) + bAbbreviate = pPar2->GetBool(); + } + + const CalendarItem* pCalendarItems = aDaySeq.getConstArray(); + const CalendarItem& rItem = pCalendarItems[nDay - 1]; + + ::rtl::OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName ); + rPar.Get(0)->PutString( String(aRetStr) ); +} + +INT16 implGetWeekDay( double aDate, bool bFirstDayParam = false, INT16 nFirstDay = 0 ) +{ + Date aRefDate( 1,1,1900 ); + long nDays = (long) aDate; + nDays -= 2; // normieren: 1.1.1900 => 0 + aRefDate += nDays; + DayOfWeek aDay = aRefDate.GetDayOfWeek(); + INT16 nDay; + if ( aDay != SUNDAY ) + nDay = (INT16)aDay + 2; + else + nDay = 1; // 1==Sonntag + + // #117253 Optional 2. parameter "firstdayofweek" + if( bFirstDayParam ) + { + if( nFirstDay < 0 || nFirstDay > 7 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return 0; + } + if( nFirstDay == 0 ) + { + Reference< XCalendar > xCalendar = getLocaleCalendar(); + if( !xCalendar.is() ) + { + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + return 0; + } + nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 ); + } + nDay = 1 + (nDay + 7 - nFirstDay) % 7; + } + return nDay; +} + +RTLFUNC(Weekday) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if ( nParCount < 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + else + { + double aDate = rPar.Get(1)->GetDate(); + + bool bFirstDay = false; + INT16 nFirstDay = 0; + if ( nParCount > 2 ) + { + nFirstDay = rPar.Get(2)->GetInteger(); + bFirstDay = true; + } + INT16 nDay = implGetWeekDay( aDate, bFirstDay, nFirstDay ); + rPar.Get(0)->PutInteger( nDay ); + } +} + + +enum Interval +{ + INTERVAL_NONE, + INTERVAL_YYYY, + INTERVAL_Q, + INTERVAL_M, + INTERVAL_Y, + INTERVAL_D, + INTERVAL_W, + INTERVAL_WW, + INTERVAL_H, + INTERVAL_N, + INTERVAL_S +}; + +struct IntervalInfo +{ + Interval meInterval; + const char* mpStringCode; + double mdValue; + bool mbSimple; + + IntervalInfo( Interval eInterval, const char* pStringCode, double dValue, bool bSimple ) + : meInterval( eInterval ) + , mpStringCode( pStringCode ) + , mdValue( dValue ) + , mbSimple( bSimple ) + {} +}; + +static IntervalInfo pIntervalTable[] = +{ + IntervalInfo( INTERVAL_YYYY, "yyyy", 0.0, false ), // Year + IntervalInfo( INTERVAL_Q, "q", 0.0, false ), // Quarter + IntervalInfo( INTERVAL_M, "m", 0.0, false ), // Month + IntervalInfo( INTERVAL_Y, "y", 1.0, true ), // Day of year + IntervalInfo( INTERVAL_D, "d", 1.0, true ), // Day + IntervalInfo( INTERVAL_W, "w", 1.0, true ), // Weekday + IntervalInfo( INTERVAL_WW, "ww", 7.0, true ), // Week + IntervalInfo( INTERVAL_H, "h", (1.0 / 24.0), true ), // Hour + IntervalInfo( INTERVAL_N, "n", (1.0 / 1440.0), true), // Minute + IntervalInfo( INTERVAL_S, "s", (1.0 / 86400.0), true ), // Second + IntervalInfo( INTERVAL_NONE, NULL, 0.0, false ) +}; + +IntervalInfo* getIntervalInfo( const String& rStringCode ) +{ + IntervalInfo* pInfo = NULL; + INT16 i = 0; + while( (pInfo = pIntervalTable + i)->mpStringCode != NULL ) + { + if( rStringCode.EqualsIgnoreCaseAscii( pInfo->mpStringCode ) ) + break; + i++; + } + return pInfo; +} + +// From methods.cxx +BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet ); +INT16 implGetDateDay( double aDate ); +INT16 implGetDateMonth( double aDate ); +INT16 implGetDateYear( double aDate ); + +INT16 implGetHour( double dDate ); +INT16 implGetMinute( double dDate ); +INT16 implGetSecond( double dDate ); + + +inline void implGetDayMonthYear( INT16& rnYear, INT16& rnMonth, INT16& rnDay, double dDate ) +{ + rnDay = implGetDateDay( dDate ); + rnMonth = implGetDateMonth( dDate ); + rnYear = implGetDateYear( dDate ); +} + +inline INT16 limitToINT16( INT32 n32 ) +{ + if( n32 > 32767 ) + n32 = 32767; + else if( n32 < -32768 ) + n32 = -32768; + return (INT16)n32; +} + +RTLFUNC(DateAdd) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if( nParCount != 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aStringCode = rPar.Get(1)->GetString(); + IntervalInfo* pInfo = getIntervalInfo( aStringCode ); + if( !pInfo ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + INT32 lNumber = rPar.Get(2)->GetLong(); + double dDate = rPar.Get(3)->GetDate(); + double dNewDate = 0; + if( pInfo->mbSimple ) + { + double dAdd = pInfo->mdValue * lNumber; + dNewDate = dDate + dAdd; + } + else + { + // Keep hours, minutes, seconds + double dHoursMinutesSeconds = dDate - floor( dDate ); + + BOOL bOk = TRUE; + INT16 nYear, nMonth, nDay; + INT16 nTargetYear16 = 0, nTargetMonth = 0; + implGetDayMonthYear( nYear, nMonth, nDay, dDate ); + switch( pInfo->meInterval ) + { + case INTERVAL_YYYY: + { + INT32 nTargetYear = lNumber + nYear; + nTargetYear16 = limitToINT16( nTargetYear ); + nTargetMonth = nMonth; + bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate ); + break; + } + case INTERVAL_Q: + case INTERVAL_M: + { + bool bNeg = (lNumber < 0); + if( bNeg ) + lNumber = -lNumber; + INT32 nYearsAdd; + INT16 nMonthAdd; + if( pInfo->meInterval == INTERVAL_Q ) + { + nYearsAdd = lNumber / 4; + nMonthAdd = (INT16)( 3 * (lNumber % 4) ); + } + else + { + nYearsAdd = lNumber / 12; + nMonthAdd = (INT16)( lNumber % 12 ); + } + + INT32 nTargetYear; + if( bNeg ) + { + nTargetMonth = nMonth - nMonthAdd; + if( nTargetMonth <= 0 ) + { + nTargetMonth += 12; + nYearsAdd++; + } + nTargetYear = (INT32)nYear - nYearsAdd; + } + else + { + nTargetMonth = nMonth + nMonthAdd; + if( nTargetMonth > 12 ) + { + nTargetMonth -= 12; + nYearsAdd++; + } + nTargetYear = (INT32)nYear + nYearsAdd; + } + nTargetYear16 = limitToINT16( nTargetYear ); + bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate ); + break; + } + default: break; + } + + if( bOk ) + { + // Overflow? + INT16 nNewYear, nNewMonth, nNewDay; + implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate ); + if( nNewYear > 9999 || nNewYear < 100 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + INT16 nCorrectionDay = nDay; + while( nNewMonth > nTargetMonth ) + { + nCorrectionDay--; + implDateSerial( nTargetYear16, nTargetMonth, nCorrectionDay, dNewDate ); + implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate ); + } + dNewDate += dHoursMinutesSeconds; + } + } + + rPar.Get(0)->PutDate( dNewDate ); +} + +inline double RoundImpl( double d ) +{ + return ( d >= 0 ) ? floor( d + 0.5 ) : -floor( -d + 0.5 ); +} + +RTLFUNC(DateDiff) +{ + (void)pBasic; + (void)bWrite; + + // DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]]) + + USHORT nParCount = rPar.Count(); + if( nParCount < 4 || nParCount > 6 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aStringCode = rPar.Get(1)->GetString(); + IntervalInfo* pInfo = getIntervalInfo( aStringCode ); + if( !pInfo ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + double dDate1 = rPar.Get(2)->GetDate(); + double dDate2 = rPar.Get(3)->GetDate(); + + double dRet = 0.0; + switch( pInfo->meInterval ) + { + case INTERVAL_YYYY: + { + INT16 nYear1 = implGetDateYear( dDate1 ); + INT16 nYear2 = implGetDateYear( dDate2 ); + dRet = nYear2 - nYear1; + break; + } + case INTERVAL_Q: + { + INT16 nYear1 = implGetDateYear( dDate1 ); + INT16 nYear2 = implGetDateYear( dDate2 ); + INT16 nQ1 = 1 + (implGetDateMonth( dDate1 ) - 1) / 3; + INT16 nQ2 = 1 + (implGetDateMonth( dDate2 ) - 1) / 3; + INT16 nQGes1 = 4 * nYear1 + nQ1; + INT16 nQGes2 = 4 * nYear2 + nQ2; + dRet = nQGes2 - nQGes1; + break; + } + case INTERVAL_M: + { + INT16 nYear1 = implGetDateYear( dDate1 ); + INT16 nYear2 = implGetDateYear( dDate2 ); + INT16 nMonth1 = implGetDateMonth( dDate1 ); + INT16 nMonth2 = implGetDateMonth( dDate2 ); + INT16 nMonthGes1 = 12 * nYear1 + nMonth1; + INT16 nMonthGes2 = 12 * nYear2 + nMonth2; + dRet = nMonthGes2 - nMonthGes1; + break; + } + case INTERVAL_Y: + case INTERVAL_D: + { + double dDays1 = floor( dDate1 ); + double dDays2 = floor( dDate2 ); + dRet = dDays2 - dDays1; + break; + } + case INTERVAL_W: + case INTERVAL_WW: + { + double dDays1 = floor( dDate1 ); + double dDays2 = floor( dDate2 ); + if( pInfo->meInterval == INTERVAL_WW ) + { + INT16 nFirstDay = 1; // Default + if( nParCount >= 5 ) + { + nFirstDay = rPar.Get(4)->GetInteger(); + if( nFirstDay < 0 || nFirstDay > 7 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + if( nFirstDay == 0 ) + { + Reference< XCalendar > xCalendar = getLocaleCalendar(); + if( !xCalendar.is() ) + { + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + return; + } + nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 ); + } + } + INT16 nDay1 = implGetWeekDay( dDate1 ); + INT16 nDay1_Diff = nDay1 - nFirstDay; + if( nDay1_Diff < 0 ) + nDay1_Diff += 7; + dDays1 -= nDay1_Diff; + + INT16 nDay2 = implGetWeekDay( dDate2 ); + INT16 nDay2_Diff = nDay2 - nFirstDay; + if( nDay2_Diff < 0 ) + nDay2_Diff += 7; + dDays2 -= nDay2_Diff; + } + + double dDiff = dDays2 - dDays1; + dRet = ( dDiff >= 0 ) ? floor( dDiff / 7.0 ) : -floor( -dDiff / 7.0 ); + break; + } + case INTERVAL_H: + { + double dFactor = 24.0; + dRet = RoundImpl( dFactor * (dDate2 - dDate1) ); + break; + } + case INTERVAL_N: + { + double dFactor =1440.0; + dRet = RoundImpl( dFactor * (dDate2 - dDate1) ); + break; + } + case INTERVAL_S: + { + double dFactor = 86400.0; + dRet = RoundImpl( dFactor * (dDate2 - dDate1) ); + break; + } + case INTERVAL_NONE: + break; + } + rPar.Get(0)->PutDouble( dRet ); +} + +double implGetDateOfFirstDayInFirstWeek + ( INT16 nYear, INT16& nFirstDay, INT16& nFirstWeek, bool* pbError = NULL ) +{ + SbError nError = 0; + if( nFirstDay < 0 || nFirstDay > 7 ) + nError = SbERR_BAD_ARGUMENT; + + if( nFirstWeek < 0 || nFirstWeek > 3 ) + nError = SbERR_BAD_ARGUMENT; + + Reference< XCalendar > xCalendar; + if( nFirstDay == 0 || nFirstWeek == 0 ) + { + xCalendar = getLocaleCalendar(); + if( !xCalendar.is() ) + nError = SbERR_BAD_ARGUMENT; + } + + if( nError != 0 ) + { + StarBASIC::Error( nError ); + if( pbError ) + *pbError = true; + return 0.0; + } + + if( nFirstDay == 0 ) + nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 ); + + INT16 nFirstWeekMinDays = 0; // Not used for vbFirstJan1 = default + if( nFirstWeek == 0 ) + { + nFirstWeekMinDays = xCalendar->getMinimumNumberOfDaysForFirstWeek(); + if( nFirstWeekMinDays == 1 ) + { + nFirstWeekMinDays = 0; + nFirstWeek = 1; + } + else if( nFirstWeekMinDays == 4 ) + nFirstWeek = 2; + else if( nFirstWeekMinDays == 7 ) + nFirstWeek = 3; + } + else if( nFirstWeek == 2 ) + nFirstWeekMinDays = 4; // vbFirstFourDays + else if( nFirstWeek == 3 ) + nFirstWeekMinDays = 7; // vbFirstFourDays + + double dBaseDate; + implDateSerial( nYear, 1, 1, dBaseDate ); + double dRetDate = dBaseDate; + + INT16 nWeekDay0101 = implGetWeekDay( dBaseDate ); + INT16 nDayDiff = nWeekDay0101 - nFirstDay; + if( nDayDiff < 0 ) + nDayDiff += 7; + + if( nFirstWeekMinDays ) + { + INT16 nThisWeeksDaysInYearCount = 7 - nDayDiff; + if( nThisWeeksDaysInYearCount < nFirstWeekMinDays ) + nDayDiff -= 7; + } + dRetDate = dBaseDate - nDayDiff; + return dRetDate; +} + +RTLFUNC(DatePart) +{ + (void)pBasic; + (void)bWrite; + + // DatePart(interval, date[,firstdayofweek[, firstweekofyear]]) + + USHORT nParCount = rPar.Count(); + if( nParCount < 3 || nParCount > 5 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aStringCode = rPar.Get(1)->GetString(); + IntervalInfo* pInfo = getIntervalInfo( aStringCode ); + if( !pInfo ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + double dDate = rPar.Get(2)->GetDate(); + + INT32 nRet = 0; + switch( pInfo->meInterval ) + { + case INTERVAL_YYYY: + { + nRet = implGetDateYear( dDate ); + break; + } + case INTERVAL_Q: + { + nRet = 1 + (implGetDateMonth( dDate ) - 1) / 3; + break; + } + case INTERVAL_M: + { + nRet = implGetDateMonth( dDate ); + break; + } + case INTERVAL_Y: + { + INT16 nYear = implGetDateYear( dDate ); + double dBaseDate; + implDateSerial( nYear, 1, 1, dBaseDate ); + nRet = 1 + INT32( dDate - dBaseDate ); + break; + } + case INTERVAL_D: + { + nRet = implGetDateDay( dDate ); + break; + } + case INTERVAL_W: + { + bool bFirstDay = false; + INT16 nFirstDay = 1; // Default + if( nParCount >= 4 ) + { + nFirstDay = rPar.Get(3)->GetInteger(); + bFirstDay = true; + } + nRet = implGetWeekDay( dDate, bFirstDay, nFirstDay ); + break; + } + case INTERVAL_WW: + { + INT16 nFirstDay = 1; // Default + if( nParCount >= 4 ) + nFirstDay = rPar.Get(3)->GetInteger(); + + INT16 nFirstWeek = 1; // Default + if( nParCount == 5 ) + nFirstWeek = rPar.Get(4)->GetInteger(); + + INT16 nYear = implGetDateYear( dDate ); + bool bError = false; + double dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear, nFirstDay, nFirstWeek, &bError ); + if( !bError ) + { + if( dYearFirstDay > dDate ) + { + // Date belongs to last year's week + dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear - 1, nFirstDay, nFirstWeek ); + } + else if( nFirstWeek != 1 ) + { + // Check if date belongs to next year + double dNextYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear + 1, nFirstDay, nFirstWeek ); + if( dDate >= dNextYearFirstDay ) + dYearFirstDay = dNextYearFirstDay; + } + + // Calculate week + double dDiff = dDate - dYearFirstDay; + nRet = 1 + INT32( dDiff / 7 ); + } + break; + } + case INTERVAL_H: + { + nRet = implGetHour( dDate ); + break; + } + case INTERVAL_N: + { + nRet = implGetMinute( dDate ); + break; + } + case INTERVAL_S: + { + nRet = implGetSecond( dDate ); + break; + } + case INTERVAL_NONE: + break; + } + rPar.Get(0)->PutLong( nRet ); +} + +// FormatDateTime(Date[,NamedFormat]) +RTLFUNC(FormatDateTime) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if( nParCount < 2 || nParCount > 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + double dDate = rPar.Get(1)->GetDate(); + INT16 nNamedFormat = 0; + if( nParCount > 2 ) + { + nNamedFormat = rPar.Get(2)->GetInteger(); + if( nNamedFormat < 0 || nNamedFormat > 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + } + + Reference< XCalendar > xCalendar = getLocaleCalendar(); + if( !xCalendar.is() ) + { + StarBASIC::Error( SbERR_INTERNAL_ERROR ); + return; + } + + String aRetStr; + SbxVariableRef pSbxVar = new SbxVariable( SbxSTRING ); + switch( nNamedFormat ) + { + // GeneralDate: + // Display a date and/or time. If there is a date part, + // display it as a short date. If there is a time part, + // display it as a long time. If present, both parts are displayed. + + // 12/21/2004 11:24:50 AM + // 21.12.2004 12:13:51 + case 0: + pSbxVar->PutDate( dDate ); + aRetStr = pSbxVar->GetString(); + break; + + // LongDate: Display a date using the long date format specified + // in your computer's regional settings. + // Tuesday, December 21, 2004 + // Dienstag, 21. December 2004 + case 1: + { + SvNumberFormatter* pFormatter = NULL; + if( pINST ) + pFormatter = pINST->GetNumberFormatter(); + else + { + sal_uInt32 n; // Dummy + SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n ); + } + + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + ULONG nIndex = pFormatter->GetFormatIndex( NF_DATE_SYSTEM_LONG, eLangType ); + Color* pCol; + pFormatter->GetOutputString( dDate, nIndex, aRetStr, &pCol ); + + if( !pINST ) + delete pFormatter; + + break; + } + + // ShortDate: Display a date using the short date format specified + // in your computer's regional settings. + // 12/21/2004 + // 21.12.2004 + case 2: + pSbxVar->PutDate( floor(dDate) ); + aRetStr = pSbxVar->GetString(); + break; + + // LongTime: Display a time using the time format specified + // in your computer's regional settings. + // 11:24:50 AM + // 12:13:51 + case 3: + // ShortTime: Display a time using the 24-hour format (hh:mm). + // 11:24 + case 4: + double n; + double dTime = modf( dDate, &n ); + pSbxVar->PutDate( dTime ); + if( nNamedFormat == 3 ) + aRetStr = pSbxVar->GetString(); + else + aRetStr = pSbxVar->GetString().Copy( 0, 5 ); + break; + } + + rPar.Get(0)->PutString( aRetStr ); +} + +RTLFUNC(Round) +{ + (void)pBasic; + (void)bWrite; + + USHORT nParCount = rPar.Count(); + if( nParCount != 2 && nParCount != 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbxVariable *pSbxVariable = rPar.Get(1); + double dVal = pSbxVariable->GetDouble(); + double dRes = 0.0; + if( dVal != 0.0 ) + { + bool bNeg = false; + if( dVal < 0.0 ) + { + bNeg = true; + dVal = -dVal; + } + + INT16 numdecimalplaces = 0; + if( nParCount == 3 ) + { + numdecimalplaces = rPar.Get(2)->GetInteger(); + if( numdecimalplaces < 0 || numdecimalplaces > 22 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + } + + if( numdecimalplaces == 0 ) + { + dRes = floor( dVal + 0.5 ); + } + else + { + double dFactor = pow( 10.0, numdecimalplaces ); + dVal *= dFactor; + dRes = floor( dVal + 0.5 ); + dRes /= dFactor; + } + + if( bNeg ) + dRes = -dRes; + } + rPar.Get(0)->PutDouble( dRes ); +} + +RTLFUNC(StrReverse) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() != 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbxVariable *pSbxVariable = rPar.Get(1); + if( pSbxVariable->IsNull() ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aStr = pSbxVariable->GetString(); + aStr.Reverse(); + rPar.Get(0)->PutString( aStr ); +} + +RTLFUNC(CompatibilityMode) +{ + (void)pBasic; + (void)bWrite; + + bool bEnabled = false; + USHORT nCount = rPar.Count(); + if ( nCount != 1 && nCount != 2 ) + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + + SbiInstance* pInst = pINST; + if( pInst ) + { + if ( nCount == 2 ) + pInst->EnableCompatibility( rPar.Get(1)->GetBool() ); + + bEnabled = pInst->IsCompatibility(); + } + rPar.Get(0)->PutBool( bEnabled ); +} + +RTLFUNC(Input) +{ + (void)pBasic; + (void)bWrite; + + // 2 parameters needed + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + USHORT nByteCount = rPar.Get(1)->GetUShort(); + INT16 nFileNumber = rPar.Get(2)->GetInteger(); + + SbiIoSystem* pIosys = pINST->GetIoSystem(); + SbiStream* pSbStrm = pIosys->GetStream( nFileNumber ); + if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_INPUT)) ) + { + StarBASIC::Error( SbERR_BAD_CHANNEL ); + return; + } + + ByteString aByteBuffer; + SbError err = pSbStrm->Read( aByteBuffer, nByteCount, true ); + if( !err ) + err = pIosys->GetError(); + + if( err ) + { + StarBASIC::Error( err ); + return; + } + rPar.Get(0)->PutString( String( aByteBuffer, gsl_getSystemTextEncoding() ) ); +} + +// #115824 +RTLFUNC(Me) +{ + (void)pBasic; + (void)bWrite; + + SbModule* pActiveModule = pINST->GetActiveModule(); + SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pActiveModule); + if( pClassModuleObject == NULL ) + { + StarBASIC::Error( SbERR_INVALID_USAGE_OBJECT ); + } + else + { + SbxVariableRef refVar = rPar.Get(0); + refVar->PutObject( pClassModuleObject ); + } +} + diff --git a/basic/source/runtime/os2.asm b/basic/source/runtime/os2.asm new file mode 100644 index 000000000000..1dd5a296d6b7 --- /dev/null +++ b/basic/source/runtime/os2.asm @@ -0,0 +1,107 @@ +;************************************************************************* +; +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; Copyright 2008 by Sun Microsystems, Inc. +; +; OpenOffice.org - a multi-platform office productivity suite +; +; $RCSfile: os2.asm,v $ +; +; $Revision: 1.4 $ +; +; This file is part of OpenOffice.org. +; +; OpenOffice.org is free software: you can redistribute it and/or modify +; it under the terms of the GNU Lesser General Public License version 3 +; only, as published by the Free Software Foundation. +; +; OpenOffice.org is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU Lesser General Public License version 3 for more details +; (a copy is included in the LICENSE file that accompanied this code). +; +; You should have received a copy of the GNU Lesser General Public License +; version 3 along with OpenOffice.org. If not, see +; <http://www.openoffice.org/license.html> +; for a copy of the LGPLv3 License. +; +;************************************************************************* + +; Anmerkungen +; Direktaufruf von C- und PASCAL-Routinen, OS/2 +; +; Inhalt: +; type = CallXXX (far *proc, char *stack, short nstack) +; +; Kopie des Basic-Stacks (nstack Bytes) auf den C-Stack +; und Aufruf der Prozedur. + + .386 + .MODEL FLAT + + .CODE + + PUBLIC CallINT + PUBLIC CallLNG + PUBLIC CallSNG + PUBLIC CallDBL + PUBLIC CallSTR + PUBLIC CallFIX + + PUBLIC _CallINT + PUBLIC _CallLNG + PUBLIC _CallSNG + PUBLIC _CallDBL + PUBLIC _CallSTR + PUBLIC _CallFIX + +_CallINT LABEL byte +_CallLNG LABEL byte +_CallSNG LABEL byte +_CallDBL LABEL byte +_CallSTR LABEL byte +_CallFIX LABEL byte + +CallINT LABEL byte +CallLNG LABEL byte +CallSNG LABEL byte +CallDBL LABEL byte +CallSTR LABEL byte +CallFIX PROC + +p EQU [EBP+8] +stk EQU [EBP+12] +n EQU [EBP+16] + + PUSH EBP + MOV EBP,ESP + PUSH ESI + PUSH EDI + MOV DX,DS + MOVZX ECX,word ptr [n] + SUB ESP,ECX + MOV EDI,ESP + MOV AX,SS + MOV ES,AX + MOV ESI,[stk] + SHR ECX,1 + CLD + JCXZ $1 + REP MOVSW ; Stack uebernehmen +$1: MOV DS,DX + CALL LARGE [p] ; 32-bit + MOV ECX,EBP + SUB ECX,8 ; wegen gepushter Register + MOV ESP,ECX + POP EDI + POP ESI + POP EBP +; Bei Borland C++ Calling Convention: +; RET 12 +; CSet System-Calling Convention + RET +CallFIX ENDP + + END diff --git a/basic/source/runtime/props.cxx b/basic/source/runtime/props.cxx new file mode 100644 index 000000000000..dc890029e6f2 --- /dev/null +++ b/basic/source/runtime/props.cxx @@ -0,0 +1,764 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: props.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "runtime.hxx" +#include "stdobj.hxx" +#include "rtlproto.hxx" + + +// Properties und Methoden legen beim Get (bWrite = FALSE) den Returnwert +// im Element 0 des Argv ab; beim Put (bWrite = TRUE) wird der Wert aus +// Element 0 gespeichert. + +RTLFUNC(Erl) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get( 0 )->PutLong( StarBASIC::GetErl() ); +} + +RTLFUNC(Err) +{ + (void)pBasic; + (void)bWrite; + + if( bWrite ) + { + INT32 nVal = rPar.Get( 0 )->GetLong(); + if( nVal <= 65535L ) + StarBASIC::Error( StarBASIC::GetSfxFromVBError( (USHORT) nVal ) ); + } + else + rPar.Get( 0 )->PutLong( StarBASIC::GetVBErrorCode( StarBASIC::GetErrBasic() ) ); +} + +RTLFUNC(False) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutBool( FALSE ); +} + +RTLFUNC(Nothing) +{ + (void)pBasic; + (void)bWrite; + + // liefert eine leere Objekt-Variable. + rPar.Get( 0 )->PutObject( NULL ); +} + +RTLFUNC(Null) +{ + (void)pBasic; + (void)bWrite; + + // liefert eine leere Objekt-Variable. + rPar.Get( 0 )->PutNull(); +} + +RTLFUNC(PI) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get( 0 )->PutDouble( F_PI ); +} + +RTLFUNC(True) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get( 0 )->PutBool( TRUE ); +} + +RTLFUNC(ATTR_NORMAL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(ATTR_READONLY) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(ATTR_HIDDEN) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(ATTR_SYSTEM) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(4); +} +RTLFUNC(ATTR_VOLUME) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(8); +} +RTLFUNC(ATTR_DIRECTORY) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(16); +} +RTLFUNC(ATTR_ARCHIVE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(32); +} + +RTLFUNC(V_EMPTY) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(V_NULL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(V_INTEGER) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(V_LONG) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(3); +} +RTLFUNC(V_SINGLE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(4); +} +RTLFUNC(V_DOUBLE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(5); +} +RTLFUNC(V_CURRENCY) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(6); +} +RTLFUNC(V_DATE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(7); +} +RTLFUNC(V_STRING) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(8); +} + +RTLFUNC(MB_OK) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(MB_OKCANCEL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(MB_ABORTRETRYIGNORE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(MB_YESNOCANCEL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(3); +} +RTLFUNC(MB_YESNO) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(4); +} +RTLFUNC(MB_RETRYCANCEL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(5); +} +RTLFUNC(MB_ICONSTOP) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(16); +} +RTLFUNC(MB_ICONQUESTION) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(32); +} +RTLFUNC(MB_ICONEXCLAMATION) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(48); +} +RTLFUNC(MB_ICONINFORMATION) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(64); +} +RTLFUNC(MB_DEFBUTTON1) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(MB_DEFBUTTON2) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(256); +} +RTLFUNC(MB_DEFBUTTON3) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(512); +} +RTLFUNC(MB_APPLMODAL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(MB_SYSTEMMODAL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(4096); +} + +RTLFUNC(IDOK) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} + +RTLFUNC(IDCANCEL) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(IDABORT) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(3); +} +RTLFUNC(IDRETRY) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(4); +} +RTLFUNC(IDYES) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(6); +} +RTLFUNC(IDNO) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(7); +} + +RTLFUNC(CF_TEXT) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(CF_BITMAP) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(CF_METAFILEPICT) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(3); +} + +RTLFUNC(TYP_AUTHORFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(7); +} +RTLFUNC(TYP_CHAPTERFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(4); +} +RTLFUNC(TYP_CONDTXTFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(27); +} +RTLFUNC(TYP_DATEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(TYP_DBFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(19); +} +RTLFUNC(TYP_DBNAMEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(3); +} +RTLFUNC(TYP_DBNEXTSETFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(24); +} +RTLFUNC(TYP_DBNUMSETFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(25); +} +RTLFUNC(TYP_DBSETNUMBERFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(26); +} +RTLFUNC(TYP_DDEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(14); +} +RTLFUNC(TYP_DOCINFOFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(18); +} +RTLFUNC(TYP_DOCSTATFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(6); +} +RTLFUNC(TYP_EXTUSERFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(30); +} +RTLFUNC(TYP_FILENAMEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(TYP_FIXDATEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(31); +} +RTLFUNC(TYP_FIXTIMEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(32); +} +RTLFUNC(TYP_FORMELFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(10); +} +RTLFUNC(TYP_GETFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(9); +} +RTLFUNC(TYP_GETREFFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(13); +} +RTLFUNC(TYP_HIDDENPARAFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(17); +} +RTLFUNC(TYP_HIDDENTXTFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(11); +} +RTLFUNC(TYP_INPUTFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(16); +} +RTLFUNC(TYP_MACROFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(15); +} +RTLFUNC(TYP_NEXTPAGEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(28); +} +RTLFUNC(TYP_PAGENUMBERFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(5); +} +RTLFUNC(TYP_POSTITFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(21); +} +RTLFUNC(TYP_PREVPAGEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(29); +} +RTLFUNC(TYP_SEQFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(23); +} +RTLFUNC(TYP_SETFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(8); +} +RTLFUNC(TYP_SETINPFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(33); +} +RTLFUNC(TYP_SETREFFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(12); +} +RTLFUNC(TYP_TEMPLNAMEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(22); +} +RTLFUNC(TYP_TIMEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(TYP_USERFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(20); +} +RTLFUNC(TYP_USRINPFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(34); +} +RTLFUNC(TYP_SETREFPAGEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(35); +} +RTLFUNC(TYP_GETREFPAGEFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(36); +} +RTLFUNC(TYP_INTERNETFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(37); +} + +RTLFUNC(SET_ON) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(SET_OFF) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(TOGGLE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} + +RTLFUNC(FRAMEANCHORPAGE) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(FRAMEANCHORPARA) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(14); +} +RTLFUNC(FRAMEANCHORCHAR) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(15); +} + +RTLFUNC(CLEAR_ALLTABS) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(CLEAR_TAB) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(SET_TAB) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} + +RTLFUNC(LINEPROP) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(0); +} +RTLFUNC(LINE_1) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(1); +} +RTLFUNC(LINE_15) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(2); +} +RTLFUNC(LINE_2) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(3); +} + +RTLFUNC(TYP_JUMPEDITFLD) +{ + (void)pBasic; + (void)bWrite; + + rPar.Get(0)->PutInteger(38); +} + + diff --git a/basic/source/runtime/rtlproto.hxx b/basic/source/runtime/rtlproto.hxx new file mode 100644 index 000000000000..2d0092e14eeb --- /dev/null +++ b/basic/source/runtime/rtlproto.hxx @@ -0,0 +1,350 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: rtlproto.hxx,v $ + * $Revision: 1.20 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <basic/sbstar.hxx> + +#define RTLFUNC( name ) void SbRtl_##name( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +#define RTLNAME( name ) &SbRtl_##name + +typedef void( *RtlCall ) ( StarBASIC* p, SbxArray& rArgs, BOOL bWrite ); + +// Properties + +extern RTLFUNC(Date); +extern RTLFUNC(Err); +extern RTLFUNC(Erl); +extern RTLFUNC(False); +extern RTLFUNC(Nothing); +extern RTLFUNC(Null); +extern RTLFUNC(True); + +extern RTLFUNC(ATTR_NORMAL); +extern RTLFUNC(ATTR_READONLY); +extern RTLFUNC(ATTR_HIDDEN); +extern RTLFUNC(ATTR_SYSTEM); +extern RTLFUNC(ATTR_VOLUME); +extern RTLFUNC(ATTR_DIRECTORY); +extern RTLFUNC(ATTR_ARCHIVE); + +extern RTLFUNC(V_EMPTY); +extern RTLFUNC(V_NULL); +extern RTLFUNC(V_INTEGER); +extern RTLFUNC(V_LONG); +extern RTLFUNC(V_SINGLE); +extern RTLFUNC(V_DOUBLE); +extern RTLFUNC(V_CURRENCY); +extern RTLFUNC(V_DATE); +extern RTLFUNC(V_STRING); + +extern RTLFUNC(MB_OK); +extern RTLFUNC(MB_OKCANCEL); +extern RTLFUNC(MB_ABORTRETRYIGNORE); +extern RTLFUNC(MB_YESNOCANCEL); +extern RTLFUNC(MB_YESNO); +extern RTLFUNC(MB_RETRYCANCEL); +extern RTLFUNC(MB_ICONSTOP); +extern RTLFUNC(MB_ICONQUESTION); +extern RTLFUNC(MB_ICONEXCLAMATION); +extern RTLFUNC(MB_ICONINFORMATION); +extern RTLFUNC(MB_DEFBUTTON1); +extern RTLFUNC(MB_DEFBUTTON2); +extern RTLFUNC(MB_DEFBUTTON3); +extern RTLFUNC(MB_APPLMODAL); +extern RTLFUNC(MB_SYSTEMMODAL); + +extern RTLFUNC(IDOK); +extern RTLFUNC(IDCANCEL); +extern RTLFUNC(IDABORT); +extern RTLFUNC(IDRETRY); +extern RTLFUNC(IDYES); +extern RTLFUNC(IDNO); + +extern RTLFUNC(CF_TEXT); +extern RTLFUNC(CF_BITMAP); +extern RTLFUNC(CF_METAFILEPICT); + +extern RTLFUNC(PI); + +extern RTLFUNC(SET_OFF); +extern RTLFUNC(SET_ON); +extern RTLFUNC(TOGGLE); + +extern RTLFUNC(TYP_AUTHORFLD); +extern RTLFUNC(TYP_CHAPTERFLD); +extern RTLFUNC(TYP_CONDTXTFLD); +extern RTLFUNC(TYP_DATEFLD); +extern RTLFUNC(TYP_DBFLD); +extern RTLFUNC(TYP_DBNAMEFLD); +extern RTLFUNC(TYP_DBNEXTSETFLD); +extern RTLFUNC(TYP_DBNUMSETFLD); +extern RTLFUNC(TYP_DBSETNUMBERFLD); +extern RTLFUNC(TYP_DDEFLD); +extern RTLFUNC(TYP_DOCINFOFLD); +extern RTLFUNC(TYP_DOCSTATFLD); +extern RTLFUNC(TYP_EXTUSERFLD); +extern RTLFUNC(TYP_FILENAMEFLD); +extern RTLFUNC(TYP_FIXDATEFLD); +extern RTLFUNC(TYP_FIXTIMEFLD); +extern RTLFUNC(TYP_FORMELFLD); +extern RTLFUNC(TYP_GETFLD); +extern RTLFUNC(TYP_GETREFFLD); +extern RTLFUNC(TYP_HIDDENPARAFLD); +extern RTLFUNC(TYP_HIDDENTXTFLD); +extern RTLFUNC(TYP_INPUTFLD); +extern RTLFUNC(TYP_MACROFLD); +extern RTLFUNC(TYP_NEXTPAGEFLD); +extern RTLFUNC(TYP_PAGENUMBERFLD); +extern RTLFUNC(TYP_POSTITFLD); +extern RTLFUNC(TYP_PREVPAGEFLD); +extern RTLFUNC(TYP_SEQFLD); +extern RTLFUNC(TYP_SETFLD); +extern RTLFUNC(TYP_SETINPFLD); +extern RTLFUNC(TYP_SETREFFLD); +extern RTLFUNC(TYP_TEMPLNAMEFLD); +extern RTLFUNC(TYP_TIMEFLD); +extern RTLFUNC(TYP_USERFLD); +extern RTLFUNC(TYP_USRINPFLD); +extern RTLFUNC(TYP_SETREFPAGEFLD); +extern RTLFUNC(TYP_GETREFPAGEFLD); +extern RTLFUNC(TYP_INTERNETFLD); +extern RTLFUNC(TYP_JUMPEDITFLD); + +extern RTLFUNC(FRAMEANCHORPAGE); +extern RTLFUNC(FRAMEANCHORPARA); +extern RTLFUNC(FRAMEANCHORCHAR); + +extern RTLFUNC(CLEAR_ALLTABS); +extern RTLFUNC(CLEAR_TAB); +extern RTLFUNC(SET_TAB); + +extern RTLFUNC(LINEPROP); +extern RTLFUNC(LINE_1); +extern RTLFUNC(LINE_15); +extern RTLFUNC(LINE_2); + +// Methoden + +extern RTLFUNC(CreateObject); +extern RTLFUNC(Error); +extern RTLFUNC(Sin); +extern RTLFUNC(Abs); +extern RTLFUNC(Asc); +extern RTLFUNC(Atn); +extern RTLFUNC(Chr); +extern RTLFUNC(Cos); +extern RTLFUNC(CurDir); +extern RTLFUNC(ChDir); // JSM +extern RTLFUNC(ChDrive); // JSM +extern RTLFUNC(FileCopy); // JSM +extern RTLFUNC(Kill); // JSM +extern RTLFUNC(MkDir); // JSM +extern RTLFUNC(RmDir); // JSM +extern RTLFUNC(SendKeys); // JSM +extern RTLFUNC(DimArray); +extern RTLFUNC(Dir); +extern RTLFUNC(Exp); +extern RTLFUNC(FileLen); +extern RTLFUNC(Fix); +extern RTLFUNC(Hex); +extern RTLFUNC(Input); +extern RTLFUNC(InStr); +extern RTLFUNC(InStrRev); +extern RTLFUNC(Int); +extern RTLFUNC(Join); +extern RTLFUNC(LCase); +extern RTLFUNC(Left); +extern RTLFUNC(Log); +extern RTLFUNC(LTrim); +extern RTLFUNC(Mid); +extern RTLFUNC(Oct); +extern RTLFUNC(Replace); +extern RTLFUNC(Right); +extern RTLFUNC(RTrim); +extern RTLFUNC(RTL); +extern RTLFUNC(Sgn); +extern RTLFUNC(Space); +extern RTLFUNC(Split); +extern RTLFUNC(Sqr); +extern RTLFUNC(Str); +extern RTLFUNC(StrComp); +extern RTLFUNC(String); +extern RTLFUNC(StrReverse); +extern RTLFUNC(Tan); +extern RTLFUNC(UCase); +extern RTLFUNC(Val); +extern RTLFUNC(Len); +extern RTLFUNC(Spc); +extern RTLFUNC(DateSerial); +extern RTLFUNC(TimeSerial); +extern RTLFUNC(DateValue); +extern RTLFUNC(TimeValue); +extern RTLFUNC(Day); +extern RTLFUNC(Hour); +extern RTLFUNC(Minute); +extern RTLFUNC(Month); +extern RTLFUNC(MonthName); +extern RTLFUNC(Now); +extern RTLFUNC(Second); +extern RTLFUNC(Time); +extern RTLFUNC(Timer); +extern RTLFUNC(Weekday); +extern RTLFUNC(WeekdayName); +extern RTLFUNC(Year); +extern RTLFUNC(Date); +extern RTLFUNC(InputBox); +extern RTLFUNC(Me); +extern RTLFUNC(MsgBox); +extern RTLFUNC(IsArray); +extern RTLFUNC(IsDate); +extern RTLFUNC(IsEmpty); +extern RTLFUNC(IsError); +extern RTLFUNC(IsNull); +extern RTLFUNC(IsNumeric); +extern RTLFUNC(IsObject); +extern RTLFUNC(IsUnoStruct); + +extern RTLFUNC(FileDateTime); +extern RTLFUNC(Format); +extern RTLFUNC(GetAttr); +extern RTLFUNC(Randomize); // JSM +extern RTLFUNC(Round); +extern RTLFUNC(Rnd); +extern RTLFUNC(Shell); +extern RTLFUNC(VarType); +extern RTLFUNC(TypeName); +extern RTLFUNC(TypeLen); + +extern RTLFUNC(EOF); +extern RTLFUNC(FileAttr); +extern RTLFUNC(Loc); +extern RTLFUNC(Lof); +extern RTLFUNC(Seek); +extern RTLFUNC(SetAttr); // JSM +extern RTLFUNC(Reset); // JSM + +extern RTLFUNC(DDEInitiate); +extern RTLFUNC(DDETerminate); +extern RTLFUNC(DDETerminateAll); +extern RTLFUNC(DDERequest); +extern RTLFUNC(DDEExecute); +extern RTLFUNC(DDEPoke); + +extern RTLFUNC(FreeFile); +extern RTLFUNC(IsMissing); +extern RTLFUNC(LBound); +extern RTLFUNC(UBound); +extern RTLFUNC(RGB); +extern RTLFUNC(QBColor); +extern RTLFUNC(StrConv); + +extern RTLFUNC(Beep); + +extern RTLFUNC(Load); +extern RTLFUNC(Unload); +extern RTLFUNC(AboutStarBasic); +extern RTLFUNC(LoadPicture); +extern RTLFUNC(SavePicture); + +extern RTLFUNC(CBool); // JSM +extern RTLFUNC(CByte); // JSM +extern RTLFUNC(CCur); // JSM +extern RTLFUNC(CDate); // JSM +extern RTLFUNC(CDbl); // JSM +extern RTLFUNC(CInt); // JSM +extern RTLFUNC(CLng); // JSM +extern RTLFUNC(CSng); // JSM +extern RTLFUNC(CStr); // JSM +extern RTLFUNC(CVar); // JSM +extern RTLFUNC(CVErr); // JSM + +extern RTLFUNC(Iif); // JSM + +extern RTLFUNC(DumpAllObjects); + +extern RTLFUNC(GetSystemType); +extern RTLFUNC(GetGUIType); +extern RTLFUNC(Red); +extern RTLFUNC(Green); +extern RTLFUNC(Blue); + +extern RTLFUNC(Switch); +extern RTLFUNC(Wait); +//i#64882# add new WaitUntil +extern RTLFUNC(WaitUntil); + +extern RTLFUNC(GetGUIVersion); +extern RTLFUNC(Choose); +extern RTLFUNC(Trim); + +extern RTLFUNC(DateAdd); +extern RTLFUNC(DateDiff); +extern RTLFUNC(DatePart); +extern RTLFUNC(FormatDateTime); +extern RTLFUNC(GetSolarVersion); +extern RTLFUNC(TwipsPerPixelX); +extern RTLFUNC(TwipsPerPixelY); +extern RTLFUNC(FreeLibrary); +extern RTLFUNC(Array); +extern RTLFUNC(FindObject); +extern RTLFUNC(FindPropertyObject); +extern RTLFUNC(EnableReschedule); + +extern RTLFUNC(Put); +extern RTLFUNC(Get); +extern RTLFUNC(Environ); +extern RTLFUNC(GetDialogZoomFactorX); +extern RTLFUNC(GetDialogZoomFactorY); +extern RTLFUNC(GetSystemTicks); +extern RTLFUNC(GetPathSeparator); +extern RTLFUNC(ResolvePath); +extern RTLFUNC(CreateUnoStruct); +extern RTLFUNC(CreateUnoService); +extern RTLFUNC(CreateUnoServiceWithArguments); +extern RTLFUNC(CreateUnoValue); +extern RTLFUNC(GetProcessServiceManager); +extern RTLFUNC(GetDefaultContext); +extern RTLFUNC(CreatePropertySet); +extern RTLFUNC(CreateUnoListener); +extern RTLFUNC(HasUnoInterfaces); +extern RTLFUNC(EqualUnoObjects); +extern RTLFUNC(CreateUnoDialog); +extern RTLFUNC(GlobalScope); +extern RTLFUNC(FileExists); +extern RTLFUNC(ConvertToUrl); +extern RTLFUNC(ConvertFromUrl); +extern RTLFUNC(CDateToIso); +extern RTLFUNC(CDateFromIso); +extern RTLFUNC(CompatibilityMode); +extern RTLFUNC(CDec); + +extern RTLFUNC(Partition); // Fong + +extern double Now_Impl(); +extern void Wait_Impl( bool bDurationBased, SbxArray& rPar ); diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx new file mode 100644 index 000000000000..cc276eea766b --- /dev/null +++ b/basic/source/runtime/runtime.cxx @@ -0,0 +1,1158 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: runtime.cxx,v $ + * $Revision: 1.39 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/fsys.hxx> +#include <vcl/svapp.hxx> +#include <tools/wldcrd.hxx> +#include <svtools/zforlist.hxx> +#include <svtools/syslocale.hxx> +#include "runtime.hxx" +#include "sbintern.hxx" +#include "opcodes.hxx" +#include "codegen.hxx" +#include "iosys.hxx" +#include "image.hxx" +#include "ddectrl.hxx" +#include "dllmgr.hxx" +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include "sbunoobj.hxx" + +bool SbiRuntime::isVBAEnabled() +{ + bool result = false; + SbiInstance* pInst = pINST; + if ( pInst && pINST->pRun ) + result = pInst->pRun->GetImageFlag( SBIMG_VBASUPPORT ); + return result; +} + +// #91147 Global reschedule flag +static BOOL bStaticGlobalEnableReschedule = TRUE; + +void StarBASIC::StaticEnableReschedule( BOOL bReschedule ) +{ + bStaticGlobalEnableReschedule = bReschedule; +} + + +struct SbiArgvStack { // Argv stack: + SbiArgvStack* pNext; // Stack Chain + SbxArrayRef refArgv; // Argv + short nArgc; // Argc +}; + +SbiRuntime::pStep0 SbiRuntime::aStep0[] = { // Alle Opcodes ohne Operanden + &SbiRuntime::StepNOP, + &SbiRuntime::StepEXP, + &SbiRuntime::StepMUL, + &SbiRuntime::StepDIV, + &SbiRuntime::StepMOD, + &SbiRuntime::StepPLUS, + &SbiRuntime::StepMINUS, + &SbiRuntime::StepNEG, + &SbiRuntime::StepEQ, + &SbiRuntime::StepNE, + &SbiRuntime::StepLT, + &SbiRuntime::StepGT, + &SbiRuntime::StepLE, + &SbiRuntime::StepGE, + &SbiRuntime::StepIDIV, + &SbiRuntime::StepAND, + &SbiRuntime::StepOR, + &SbiRuntime::StepXOR, + &SbiRuntime::StepEQV, + &SbiRuntime::StepIMP, + &SbiRuntime::StepNOT, + &SbiRuntime::StepCAT, + + &SbiRuntime::StepLIKE, + &SbiRuntime::StepIS, + // Laden/speichern + &SbiRuntime::StepARGC, // neuen Argv einrichten + &SbiRuntime::StepARGV, // TOS ==> aktueller Argv + &SbiRuntime::StepINPUT, // Input ==> TOS + &SbiRuntime::StepLINPUT, // Line Input ==> TOS + &SbiRuntime::StepGET, // TOS anfassen + &SbiRuntime::StepSET, // Speichern Objekt TOS ==> TOS-1 + &SbiRuntime::StepPUT, // TOS ==> TOS-1 + &SbiRuntime::StepPUTC, // TOS ==> TOS-1, dann ReadOnly + &SbiRuntime::StepDIM, // DIM + &SbiRuntime::StepREDIM, // REDIM + &SbiRuntime::StepREDIMP, // REDIM PRESERVE + &SbiRuntime::StepERASE, // TOS loeschen + // Verzweigen + &SbiRuntime::StepSTOP, // Programmende + &SbiRuntime::StepINITFOR, // FOR-Variable initialisieren + &SbiRuntime::StepNEXT, // FOR-Variable inkrementieren + &SbiRuntime::StepCASE, // Anfang CASE + &SbiRuntime::StepENDCASE, // Ende CASE + &SbiRuntime::StepSTDERROR, // Standard-Fehlerbehandlung + &SbiRuntime::StepNOERROR, // keine Fehlerbehandlung + &SbiRuntime::StepLEAVE, // UP verlassen + // E/A + &SbiRuntime::StepCHANNEL, // TOS = Kanalnummer + &SbiRuntime::StepPRINT, // print TOS + &SbiRuntime::StepPRINTF, // print TOS in field + &SbiRuntime::StepWRITE, // write TOS + &SbiRuntime::StepRENAME, // Rename Tos+1 to Tos + &SbiRuntime::StepPROMPT, // Input Prompt aus TOS definieren + &SbiRuntime::StepRESTART, // Set restart point + &SbiRuntime::StepCHANNEL0, // E/A-Kanal 0 einstellen + &SbiRuntime::StepEMPTY, // Leeren Ausdruck auf Stack + &SbiRuntime::StepERROR, // TOS = Fehlercode + &SbiRuntime::StepLSET, // Speichern Objekt TOS ==> TOS-1 + &SbiRuntime::StepRSET, // Speichern Objekt TOS ==> TOS-1 + &SbiRuntime::StepREDIMP_ERASE,// Copy array object for REDIMP + &SbiRuntime::StepINITFOREACH,// Init for each loop + &SbiRuntime::StepVBASET,// vba-like set statement + &SbiRuntime::StepERASE_CLEAR,// vba-like set statement + &SbiRuntime::StepARRAYACCESS,// access TOS as array +}; + +SbiRuntime::pStep1 SbiRuntime::aStep1[] = { // Alle Opcodes mit einem Operanden + &SbiRuntime::StepLOADNC, // Laden einer numerischen Konstanten (+ID) + &SbiRuntime::StepLOADSC, // Laden einer Stringkonstanten (+ID) + &SbiRuntime::StepLOADI, // Immediate Load (+Wert) + &SbiRuntime::StepARGN, // Speichern eines named Args in Argv (+StringID) + &SbiRuntime::StepPAD, // String auf feste Laenge bringen (+Laenge) + // Verzweigungen + &SbiRuntime::StepJUMP, // Sprung (+Target) + &SbiRuntime::StepJUMPT, // TOS auswerten), bedingter Sprung (+Target) + &SbiRuntime::StepJUMPF, // TOS auswerten), bedingter Sprung (+Target) + &SbiRuntime::StepONJUMP, // TOS auswerten), Sprung in JUMP-Tabelle (+MaxVal) + &SbiRuntime::StepGOSUB, // UP-Aufruf (+Target) + &SbiRuntime::StepRETURN, // UP-Return (+0 oder Target) + &SbiRuntime::StepTESTFOR, // FOR-Variable testen), inkrementieren (+Endlabel) + &SbiRuntime::StepCASETO, // Tos+1 <= Case <= Tos), 2xremove (+Target) + &SbiRuntime::StepERRHDL, // Fehler-Handler (+Offset) + &SbiRuntime::StepRESUME, // Resume nach Fehlern (+0 or 1 or Label) + // E/A + &SbiRuntime::StepCLOSE, // (+Kanal/0) + &SbiRuntime::StepPRCHAR, // (+char) + // Verwaltung + &SbiRuntime::StepSETCLASS, // Set + Klassennamen testen (+StringId) + &SbiRuntime::StepTESTCLASS, // Check TOS class (+StringId) + &SbiRuntime::StepLIB, // Lib fuer Declare-Call (+StringId) + &SbiRuntime::StepBASED, // TOS wird um BASE erhoeht, BASE davor gepusht + &SbiRuntime::StepARGTYP, // Letzten Parameter in Argv konvertieren (+Typ) + &SbiRuntime::StepVBASETCLASS,// vba-like set statement +}; + +SbiRuntime::pStep2 SbiRuntime::aStep2[] = {// Alle Opcodes mit zwei Operanden + &SbiRuntime::StepRTL, // Laden aus RTL (+StringID+Typ) + &SbiRuntime::StepFIND, // Laden (+StringID+Typ) + &SbiRuntime::StepELEM, // Laden Element (+StringID+Typ) + &SbiRuntime::StepPARAM, // Parameter (+Offset+Typ) + // Verzweigen + &SbiRuntime::StepCALL, // Declare-Call (+StringID+Typ) + &SbiRuntime::StepCALLC, // CDecl-Declare-Call (+StringID+Typ) + &SbiRuntime::StepCASEIS, // Case-Test (+Test-Opcode+False-Target) + // Verwaltung + &SbiRuntime::StepSTMNT, // Beginn eines Statements (+Line+Col) + // E/A + &SbiRuntime::StepOPEN, // (+SvStreamFlags+Flags) + // Objekte + &SbiRuntime::StepLOCAL, // Lokale Variable definieren (+StringId+Typ) + &SbiRuntime::StepPUBLIC, // Modulglobale Variable (+StringID+Typ) + &SbiRuntime::StepGLOBAL, // Globale Variable definieren (+StringID+Typ) + &SbiRuntime::StepCREATE, // Objekt kreieren (+StringId+StringId) + &SbiRuntime::StepSTATIC, // Statische Variable (+StringId+StringId) + &SbiRuntime::StepTCREATE, // User Defined Objekte (+StringId+StringId) + &SbiRuntime::StepDCREATE, // Objekt-Array kreieren (+StringID+StringID) + &SbiRuntime::StepGLOBAL_P, // Globale Variable definieren, die beim Neustart + // von Basic nicht ueberschrieben wird (+StringID+Typ) + &SbiRuntime::StepFIND_G, // Sucht globale Variable mit Spezialbehandlung wegen _GLOBAL_P + &SbiRuntime::StepDCREATE_REDIMP, // Objekt-Array redimensionieren (+StringID+StringID) + &SbiRuntime::StepFIND_CM, // Search inside a class module (CM) to enable global search in time + &SbiRuntime::StepPUBLIC_P, // Search inside a class module (CM) to enable global search in time + &SbiRuntime::StepFIND_STATIC, // Search inside a class module (CM) to enable global search in time +}; + + +////////////////////////////////////////////////////////////////////////// +// SbiRTLData // +////////////////////////////////////////////////////////////////////////// + +SbiRTLData::SbiRTLData() +{ + pDir = 0; + nDirFlags = 0; + nCurDirPos = 0; + pWildCard = NULL; +} + +SbiRTLData::~SbiRTLData() +{ + delete pDir; + pDir = 0; + delete pWildCard; +} + +////////////////////////////////////////////////////////////////////////// +// SbiInstance // +////////////////////////////////////////////////////////////////////////// + +// 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out +// Die Entscheidung, ob StepPoint aufgerufen werden soll, wird anhand des +// CallLevels getroffen. Angehalten wird, wenn der aktuelle CallLevel <= +// nBreakCallLvl ist. Der aktuelle CallLevel kann niemals kleiner als 1 +// sein, da er beim Aufruf einer Methode (auch main) inkrementiert wird. +// Daher bedeutet ein BreakCallLvl von 0, dass das Programm gar nicht +// angehalten wird. +// (siehe auch step2.cxx, SbiRuntime::StepSTMNT() ) + +// Hilfsfunktion, um den BreakCallLevel gemaess der der Debug-Flags zu ermitteln +void SbiInstance::CalcBreakCallLevel( USHORT nFlags ) +{ + // Break-Flag wegfiltern + nFlags &= ~((USHORT)SbDEBUG_BREAK); + + USHORT nRet; + switch( nFlags ) + { + case SbDEBUG_STEPINTO: + nRet = nCallLvl + 1; // CallLevel+1 wird auch angehalten + break; + case SbDEBUG_STEPOVER | SbDEBUG_STEPINTO: + nRet = nCallLvl; // Aktueller CallLevel wird angehalten + break; + case SbDEBUG_STEPOUT: + nRet = nCallLvl - 1; // Kleinerer CallLevel wird angehalten + break; + case SbDEBUG_CONTINUE: + // Basic-IDE liefert 0 statt SbDEBUG_CONTINUE, also auch default=continue + default: + nRet = 0; // CallLevel ist immer >0 -> kein StepPoint + } + nBreakCallLvl = nRet; // Ergebnis uebernehmen +} + +SbiInstance::SbiInstance( StarBASIC* p ) +{ + pBasic = p; + pNext = NULL; + pRun = NULL; + pIosys = new SbiIoSystem; + pDdeCtrl = new SbiDdeControl; + pDllMgr = 0; // on demand + pNumberFormatter = 0; // on demand + nCallLvl = 0; + nBreakCallLvl = 0; + nErr = + nErl = 0; + bReschedule = TRUE; + bCompatibility = FALSE; +} + +SbiInstance::~SbiInstance() +{ + while( pRun ) + { + SbiRuntime* p = pRun->pNext; + delete pRun; + pRun = p; + } + delete pIosys; + delete pDdeCtrl; + delete pDllMgr; + delete pNumberFormatter; + + try + { + int nSize = ComponentVector.size(); + if( nSize ) + { + for( int i = nSize - 1 ; i >= 0 ; --i ) + { + Reference< XComponent > xDlgComponent = ComponentVector[i]; + if( xDlgComponent.is() ) + xDlgComponent->dispose(); + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "SbiInstance::~SbiInstance: caught an exception while disposing the components!" ); + } + + ComponentVector.clear(); +} + +SbiDllMgr* SbiInstance::GetDllMgr() +{ + if( !pDllMgr ) + pDllMgr = new SbiDllMgr; + return pDllMgr; +} + +// #39629 NumberFormatter jetzt ueber statische Methode anlegen +SvNumberFormatter* SbiInstance::GetNumberFormatter() +{ + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + SvtSysLocale aSysLocale; + DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat(); + if( pNumberFormatter ) + { + if( eLangType != meFormatterLangType || + eDate != meFormatterDateFormat ) + { + delete pNumberFormatter; + pNumberFormatter = NULL; + } + } + meFormatterLangType = eLangType; + meFormatterDateFormat = eDate; + if( !pNumberFormatter ) + PrepareNumberFormatter( pNumberFormatter, nStdDateIdx, nStdTimeIdx, nStdDateTimeIdx, + &meFormatterLangType, &meFormatterDateFormat ); + return pNumberFormatter; +} + +// #39629 NumberFormatter auch statisch anbieten +void SbiInstance::PrepareNumberFormatter( SvNumberFormatter*& rpNumberFormatter, + sal_uInt32 &rnStdDateIdx, sal_uInt32 &rnStdTimeIdx, sal_uInt32 &rnStdDateTimeIdx, + LanguageType* peFormatterLangType, DateFormat* peFormatterDateFormat ) +{ + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + xFactory = comphelper::getProcessServiceFactory(); + + LanguageType eLangType; + if( peFormatterLangType ) + eLangType = *peFormatterLangType; + else + eLangType = GetpApp()->GetSettings().GetLanguage(); + + DateFormat eDate; + if( peFormatterDateFormat ) + eDate = *peFormatterDateFormat; + else + { + SvtSysLocale aSysLocale; + eDate = aSysLocale.GetLocaleData().getDateFormat(); + } + + rpNumberFormatter = new SvNumberFormatter( xFactory, eLangType ); + + xub_StrLen nCheckPos = 0; short nType; + rnStdTimeIdx = rpNumberFormatter->GetStandardFormat( NUMBERFORMAT_TIME, eLangType ); + + // Standard-Vorlagen des Formatters haben nur zweistellige + // Jahreszahl. Deshalb eigenes Format registrieren + + // HACK, da der Numberformatter in PutandConvertEntry die Platzhalter + // fuer Monat, Tag, Jahr nicht entsprechend der Systemeinstellung + // austauscht. Problem: Print Year(Date) unter engl. BS + // siehe auch svtools\source\sbx\sbxdate.cxx + + String aDateStr; + switch( eDate ) + { + case MDY: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("MM.TT.JJJJ") ); break; + case DMY: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("TT.MM.JJJJ") ); break; + case YMD: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("JJJJ.MM.TT") ); break; + default: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("MM.TT.JJJJ") ); + } + String aStr( aDateStr ); + rpNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType, + rnStdDateIdx, LANGUAGE_GERMAN, eLangType ); + nCheckPos = 0; + String aStrHHMMSS( RTL_CONSTASCII_USTRINGPARAM(" HH:MM:SS") ); + aStr = aDateStr; + aStr += aStrHHMMSS; + rpNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType, + rnStdDateTimeIdx, LANGUAGE_GERMAN, eLangType ); +} + + + +// Engine laufenlassen. Falls Flags == SbDEBUG_CONTINUE, Flags uebernehmen + +void SbiInstance::Stop() +{ + for( SbiRuntime* p = pRun; p; p = p->pNext ) + p->Stop(); +} + +// Allows Basic IDE to set watch mode to suppress errors +static bool bWatchMode = false; + +void setBasicWatchMode( bool bOn ) +{ + bWatchMode = bOn; +} + +void SbiInstance::Error( SbError n ) +{ + Error( n, String() ); +} + +void SbiInstance::Error( SbError n, const String& rMsg ) +{ + if( !bWatchMode ) + { + aErrorMsg = rMsg; + pRun->Error( n ); + } +} + +void SbiInstance::FatalError( SbError n ) +{ + pRun->FatalError( n ); +} + +void SbiInstance::FatalError( SbError _errCode, const String& _details ) +{ + pRun->FatalError( _errCode, _details ); +} + +void SbiInstance::Abort() +{ + // Basic suchen, in dem der Fehler auftrat + StarBASIC* pErrBasic = GetCurrentBasic( pBasic ); + pErrBasic->RTError( nErr, aErrorMsg, pRun->nLine, pRun->nCol1, pRun->nCol2 ); + pBasic->Stop(); +} + +// Hilfsfunktion, um aktives Basic zu finden, kann ungleich pRTBasic sein +StarBASIC* GetCurrentBasic( StarBASIC* pRTBasic ) +{ + StarBASIC* pCurBasic = pRTBasic; + SbModule* pActiveModule = pRTBasic->GetActiveModule(); + if( pActiveModule ) + { + SbxObject* pParent = pActiveModule->GetParent(); + if( pParent && pParent->ISA(StarBASIC) ) + pCurBasic = (StarBASIC*)pParent; + } + return pCurBasic; +} + +SbModule* SbiInstance::GetActiveModule() +{ + if( pRun ) + return pRun->GetModule(); + else + return NULL; +} + +SbMethod* SbiInstance::GetCaller( USHORT nLevel ) +{ + SbiRuntime* p = pRun; + while( nLevel-- && p ) + p = p->pNext; + if( p ) + return p->GetCaller(); + else + return NULL; +} + +SbxArray* SbiInstance::GetLocals( SbMethod* pMeth ) +{ + SbiRuntime* p = pRun; + while( p && p->GetMethod() != pMeth ) + p = p->pNext; + if( p ) + return p->GetLocals(); + else + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +// SbiInstance // +////////////////////////////////////////////////////////////////////////// + +// Achtung: pMeth kann auch NULL sein (beim Aufruf des Init-Codes) + +SbiRuntime::SbiRuntime( SbModule* pm, SbMethod* pe, UINT32 nStart ) + : rBasic( *(StarBASIC*)pm->pParent ), pInst( pINST ), + pMod( pm ), pMeth( pe ), pImg( pMod->pImage ), m_nLastTime(0) +{ + nFlags = pe ? pe->GetDebugFlags() : 0; + pIosys = pInst->pIosys; + pArgvStk = NULL; + pGosubStk = NULL; + pForStk = NULL; + pError = NULL; + pErrCode = + pErrStmnt = + pRestart = NULL; + pNext = NULL; + pCode = + pStmnt = (const BYTE* ) pImg->GetCode() + nStart; + bRun = + bError = TRUE; + bInError = FALSE; + bBlocked = FALSE; + nLine = 0; + nCol1 = 0; + nCol2 = 0; + nExprLvl = 0; + nArgc = 0; + nError = 0; + nGosubLvl = 0; + nForLvl = 0; + nOps = 0; + refExprStk = new SbxArray; +#if defined GCC + SetParameters( pe ? pe->GetParameters() : (class SbxArray *)NULL ); +#else + SetParameters( pe ? pe->GetParameters() : NULL ); +#endif + pRefSaveList = NULL; + pItemStoreList = NULL; + bVBAEnabled = isVBAEnabled(); +} + +SbiRuntime::~SbiRuntime() +{ + ClearGosubStack(); + ClearArgvStack(); + ClearForStack(); + + // #74254 Items zum Sichern temporaere Referenzen freigeben + ClearRefs(); + while( pItemStoreList ) + { + RefSaveItem* pToDeleteItem = pItemStoreList; + pItemStoreList = pToDeleteItem->pNext; + delete pToDeleteItem; + } +} + +// Aufbau der Parameterliste. Alle ByRef-Parameter werden direkt +// uebernommen; von ByVal-Parametern werden Kopien angelegt. Falls +// ein bestimmter Datentyp verlangt wird, wird konvertiert. + +void SbiRuntime::SetParameters( SbxArray* pParams ) +{ + refParams = new SbxArray; + // fuer den Returnwert + refParams->Put( pMeth, 0 ); + + SbxInfo* pInfo = pMeth ? pMeth->GetInfo() : NULL; + USHORT nParamCount = pParams ? pParams->Count() : 1; + if( nParamCount > 1 ) + { + for( USHORT i = 1 ; i < nParamCount ; i++ ) + { + const SbxParamInfo* p = pInfo ? pInfo->GetParam( i ) : NULL; + + // #111897 ParamArray + if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 ) + { + SbxDimArray* pArray = new SbxDimArray( SbxVARIANT ); + USHORT nParamArrayParamCount = nParamCount - i; + pArray->unoAddDim( 0, nParamArrayParamCount - 1 ); + for( USHORT j = i ; j < nParamCount ; j++ ) + { + SbxVariable* v = pParams->Get( j ); + short nDimIndex = j - i; + pArray->Put( v, &nDimIndex ); + } + SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT ); + pArrayVar->SetFlag( SBX_READWRITE ); + pArrayVar->PutObject( pArray ); + refParams->Put( pArrayVar, i ); + + // Block ParamArray for missing parameter + pInfo = NULL; + break; + } + + SbxVariable* v = pParams->Get( i ); + // Methoden sind immer byval! + BOOL bByVal = v->IsA( TYPE(SbxMethod) ); + SbxDataType t = v->GetType(); + if( p ) + { + bByVal |= BOOL( ( p->eType & SbxBYREF ) == 0 ); + t = (SbxDataType) ( p->eType & 0x0FFF ); + + if( !bByVal && t != SbxVARIANT && + (!v->IsFixed() || (SbxDataType)(v->GetType() & 0x0FFF ) != t) ) + bByVal = TRUE; + } + if( bByVal ) + { + SbxVariable* v2 = new SbxVariable( t ); + v2->SetFlag( SBX_READWRITE ); + *v2 = *v; + refParams->Put( v2, i ); + } + else + { + if( t != SbxVARIANT && t != ( v->GetType() & 0x0FFF ) ) + { + // Array konvertieren?? + if( p && (p->eType & SbxARRAY) ) + Error( SbERR_CONVERSION ); + else + v->Convert( t ); + } + refParams->Put( v, i ); + } + if( p ) + refParams->PutAlias( p->aName, i ); + } + } + + // ParamArray for missing parameter + if( pInfo ) + { + // #111897 Check first missing parameter for ParamArray + const SbxParamInfo* p = pInfo->GetParam( nParamCount ); + if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 ) + { + SbxDimArray* pArray = new SbxDimArray( SbxVARIANT ); + pArray->unoAddDim( 0, -1 ); + SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT ); + pArrayVar->SetFlag( SBX_READWRITE ); + pArrayVar->PutObject( pArray ); + refParams->Put( pArrayVar, nParamCount ); + } + } +} + + +// Einen P-Code ausfuehren + +BOOL SbiRuntime::Step() +{ + if( bRun ) + { + // Unbedingt gelegentlich die Kontrolle abgeben! + if( !( ++nOps & 0xF ) && pInst->IsReschedule() && bStaticGlobalEnableReschedule ) + { + sal_uInt32 nTime = osl_getGlobalTimer(); + if (nTime - m_nLastTime > 5 ) // 20 ms + { + Application::Reschedule(); + m_nLastTime = nTime; + } + } + + // #i48868 blocked by next call level? + while( bBlocked ) + { + if( pInst->IsReschedule() && bStaticGlobalEnableReschedule ) + Application::Reschedule(); + } + SbiOpcode eOp = (SbiOpcode ) ( *pCode++ ); + UINT32 nOp1, nOp2; + if( eOp <= SbOP0_END ) + { + (this->*( aStep0[ eOp ] ) )(); + } + else if( eOp >= SbOP1_START && eOp <= SbOP1_END ) + { + nOp1 = *pCode++; nOp1 |= *pCode++ << 8; nOp1 |= *pCode++ << 16; nOp1 |= *pCode++ << 24; + + (this->*( aStep1[ eOp - SbOP1_START ] ) )( nOp1 ); + } + else if( eOp >= SbOP2_START && eOp <= SbOP2_END ) + { + nOp1 = *pCode++; nOp1 |= *pCode++ << 8; nOp1 |= *pCode++ << 16; nOp1 |= *pCode++ << 24; + nOp2 = *pCode++; nOp2 |= *pCode++ << 8; nOp2 |= *pCode++ << 16; nOp2 |= *pCode++ << 24; + (this->*( aStep2[ eOp - SbOP2_START ] ) )( nOp1, nOp2 ); + } + else + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + + // SBX-Fehler aufgetreten? + SbError nSbError = SbxBase::GetError(); + Error( ERRCODE_TOERROR(nSbError) ); // Warnings rausfiltern + + // AB 13.2.1997, neues Error-Handling: + // ACHTUNG: Hier kann nError auch dann gesetzt sein, wenn !nSbError, + // da nError jetzt auch von anderen RT-Instanzen gesetzt werden kann + + if( nError ) + SbxBase::ResetError(); + + // AB,15.3.96: Fehler nur anzeigen, wenn BASIC noch aktiv + // (insbesondere nicht nach Compiler-Fehlern zur Laufzeit) + if( nError && bRun ) + { + SbError err = nError; + ClearExprStack(); + nError = 0; + pInst->nErr = err; + pInst->nErl = nLine; + pErrCode = pCode; + pErrStmnt = pStmnt; + // An error occured in an error handler + // force parent handler ( if there is one ) + // to handle the error + bool bLetParentHandleThis = false; + + // Im Error Handler? Dann Std-Error + if ( !bInError ) + { + bInError = TRUE; + + if( !bError ) // On Error Resume Next + StepRESUME( 1 ); + else if( pError ) // On Error Goto ... + pCode = pError; + else + bLetParentHandleThis = true; + } + else + { + bLetParentHandleThis = true; + pError = NULL; //terminate the handler + } + if ( bLetParentHandleThis ) + { + // AB 13.2.1997, neues Error-Handling: + // Uebergeordnete Error-Handler beruecksichtigen + + // Wir haben keinen Error-Handler -> weiter oben suchen + SbiRuntime* pRtErrHdl = NULL; + SbiRuntime* pRt = this; + while( NULL != (pRt = pRt->pNext) ) + { + // Gibt es einen Error-Handler? + if( pRt->bError == FALSE || pRt->pError != NULL ) + { + pRtErrHdl = pRt; + break; + } + } + + // Error-Hdl gefunden? + if( pRtErrHdl ) + { + // (Neuen) Error-Stack anlegen + SbErrorStack*& rErrStack = GetSbData()->pErrStack; + if( rErrStack ) + delete rErrStack; + rErrStack = new SbErrorStack(); + + // Alle im Call-Stack darunter stehenden RTs manipulieren + pRt = this; + do + { + // Fehler setzen + pRt->nError = err; + if( pRt != pRtErrHdl ) + pRt->bRun = FALSE; + + // In Error-Stack eintragen + SbErrorStackEntry *pEntry = new SbErrorStackEntry + ( pRt->pMeth, pRt->nLine, pRt->nCol1, pRt->nCol2 ); + rErrStack->C40_INSERT(SbErrorStackEntry, pEntry, rErrStack->Count() ); + + // Nach RT mit Error-Handler aufhoeren + if( pRt == pRtErrHdl ) + break; + pRt = pRt->pNext; + } + while( pRt ); + } + // Kein Error-Hdl gefunden -> altes Vorgehen + else + { + pInst->Abort(); + } + + // ALT: Nur + // pInst->Abort(); + } + } + } + return bRun; +} + +void SbiRuntime::Error( SbError n ) +{ + if( n ) + nError = n; +} + +void SbiRuntime::Error( SbError _errCode, const String& _details ) +{ + if ( _errCode ) + { + OSL_ENSURE( pInst->pRun == this, "SbiRuntime::Error: can't propagate the error message details!" ); + if ( pInst->pRun == this ) + { + pInst->Error( _errCode, _details ); + OSL_POSTCOND( nError == _errCode, "SbiRuntime::Error: the instance is expecte to propagate the error code back to me!" ); + } + else + { + nError = _errCode; + } + } +} + +void SbiRuntime::FatalError( SbError n ) +{ + StepSTDERROR(); + Error( n ); +} + +void SbiRuntime::FatalError( SbError _errCode, const String& _details ) +{ + StepSTDERROR(); + Error( _errCode, _details ); +} + +////////////////////////////////////////////////////////////////////////// +// +// Parameter, Locals, Caller +// +////////////////////////////////////////////////////////////////////////// + +SbMethod* SbiRuntime::GetCaller() +{ + return pMeth; +} + +SbxArray* SbiRuntime::GetLocals() +{ + return refLocals; +} + +SbxArray* SbiRuntime::GetParams() +{ + return refParams; +} + +////////////////////////////////////////////////////////////////////////// +// +// Stacks +// +////////////////////////////////////////////////////////////////////////// + +// Der Expression-Stack steht fuer die laufende Auswertung von Expressions +// zur Verfuegung. + +void SbiRuntime::PushVar( SbxVariable* pVar ) +{ + if( pVar ) + refExprStk->Put( pVar, nExprLvl++ ); +} + +SbxVariableRef SbiRuntime::PopVar() +{ +#ifndef PRODUCT + if( !nExprLvl ) + { + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + return new SbxVariable; + } +#endif + SbxVariableRef xVar = refExprStk->Get( --nExprLvl ); +#ifdef DBG_UTIL + if ( xVar->GetName().EqualsAscii( "Cells" ) ) + DBG_TRACE( "" ); +#endif + // Methods halten im 0.Parameter sich selbst, also weghauen + if( xVar->IsA( TYPE(SbxMethod) ) ) + xVar->SetParameters(0); + return xVar; +} + +BOOL SbiRuntime::ClearExprStack() +{ + // Achtung: Clear() reicht nicht, da Methods geloescht werden muessen + while ( nExprLvl ) + { + PopVar(); + } + refExprStk->Clear(); + return FALSE; +} + +// Variable auf dem Expression-Stack holen, ohne sie zu entfernen +// n zaehlt ab 0. + +SbxVariable* SbiRuntime::GetTOS( short n ) +{ + n = nExprLvl - n - 1; +#ifndef PRODUCT + if( n < 0 ) + { + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + return new SbxVariable; + } +#endif + return refExprStk->Get( (USHORT) n ); +} + +// Sicherstellen, dass TOS eine temporaere Variable ist + +void SbiRuntime::TOSMakeTemp() +{ + SbxVariable* p = refExprStk->Get( nExprLvl - 1 ); + if( p->GetRefCount() != 1 ) + { + SbxVariable* pNew = new SbxVariable( *p ); + pNew->SetFlag( SBX_READWRITE ); + refExprStk->Put( pNew, nExprLvl - 1 ); + } +} + +// Der GOSUB-Stack nimmt Returnadressen fuer GOSUBs auf + +void SbiRuntime::PushGosub( const BYTE* pc ) +{ + if( ++nGosubLvl > MAXRECURSION ) + StarBASIC::FatalError( SbERR_STACK_OVERFLOW ); + SbiGosubStack* p = new SbiGosubStack; + p->pCode = pc; + p->pNext = pGosubStk; + p->nStartForLvl = nForLvl; + pGosubStk = p; +} + +void SbiRuntime::PopGosub() +{ + if( !pGosubStk ) + Error( SbERR_NO_GOSUB ); + else + { + SbiGosubStack* p = pGosubStk; + pCode = p->pCode; + pGosubStk = p->pNext; + delete p; + nGosubLvl--; + } +} + +// Entleeren des GOSUB-Stacks + +void SbiRuntime::ClearGosubStack() +{ + SbiGosubStack* p; + while(( p = pGosubStk ) != NULL ) + pGosubStk = p->pNext, delete p; + nGosubLvl = 0; +} + +// Der Argv-Stack nimmt aktuelle Argument-Vektoren auf + +void SbiRuntime::PushArgv() +{ + SbiArgvStack* p = new SbiArgvStack; + p->refArgv = refArgv; + p->nArgc = nArgc; + nArgc = 1; + refArgv.Clear(); + p->pNext = pArgvStk; + pArgvStk = p; +} + +void SbiRuntime::PopArgv() +{ + if( pArgvStk ) + { + SbiArgvStack* p = pArgvStk; + pArgvStk = p->pNext; + refArgv = p->refArgv; + nArgc = p->nArgc; + delete p; + } +} + +// Entleeren des Argv-Stacks + +void SbiRuntime::ClearArgvStack() +{ + while( pArgvStk ) + PopArgv(); +} + +// Push des For-Stacks. Der Stack hat Inkrement, Ende, Beginn und Variable. +// Nach Aufbau des Stack-Elements ist der Stack leer. + +void SbiRuntime::PushFor() +{ + SbiForStack* p = new SbiForStack; + p->eForType = FOR_TO; + p->pNext = pForStk; + pForStk = p; + // Der Stack ist wie folgt aufgebaut: + p->refInc = PopVar(); + p->refEnd = PopVar(); + SbxVariableRef xBgn = PopVar(); + p->refVar = PopVar(); + *(p->refVar) = *xBgn; + nForLvl++; +} + +void SbiRuntime::PushForEach() +{ + SbiForStack* p = new SbiForStack; + p->pNext = pForStk; + pForStk = p; + + SbxVariableRef xObjVar = PopVar(); + SbxBase* pObj = xObjVar.Is() ? xObjVar->GetObject() : NULL; + if( pObj == NULL ) + { + Error( SbERR_NO_OBJECT ); + return; + } + + bool bError_ = false; + BasicCollection* pCollection; + SbxDimArray* pArray; + SbUnoObject* pUnoObj; + if( (pArray = PTR_CAST(SbxDimArray,pObj)) != NULL ) + { + p->eForType = FOR_EACH_ARRAY; + p->refEnd = (SbxVariable*)pArray; + + short nDims = pArray->GetDims(); + p->pArrayLowerBounds = new sal_Int32[nDims]; + p->pArrayUpperBounds = new sal_Int32[nDims]; + p->pArrayCurIndices = new sal_Int32[nDims]; + sal_Int32 lBound, uBound; + for( short i = 0 ; i < nDims ; i++ ) + { + pArray->GetDim32( i+1, lBound, uBound ); + p->pArrayCurIndices[i] = p->pArrayLowerBounds[i] = lBound; + p->pArrayUpperBounds[i] = uBound; + } + } + else if( (pCollection = PTR_CAST(BasicCollection,pObj)) != NULL ) + { + p->eForType = FOR_EACH_COLLECTION; + p->refEnd = pCollection; + p->nCurCollectionIndex = 0; + } + else if( (pUnoObj = PTR_CAST(SbUnoObject,pObj)) != NULL ) + { + // XEnumerationAccess? + Any aAny = pUnoObj->getUnoAny(); + Reference< XEnumerationAccess > xEnumerationAccess; + if( (aAny >>= xEnumerationAccess) ) + { + p->xEnumeration = xEnumerationAccess->createEnumeration(); + p->eForType = FOR_EACH_XENUMERATION; + } + else + { + bError_ = true; + } + } + else + { + bError_ = true; + } + + if( bError_ ) + { + Error( SbERR_CONVERSION ); + return; + } + + // Container variable + p->refVar = PopVar(); + nForLvl++; +} + +// Poppen des FOR-Stacks + +void SbiRuntime::PopFor() +{ + if( pForStk ) + { + SbiForStack* p = pForStk; + pForStk = p->pNext; + delete p; + nForLvl--; + } +} + +// Entleeren des FOR-Stacks + +void SbiRuntime::ClearForStack() +{ + while( pForStk ) + PopFor(); +} + +////////////////////////////////////////////////////////////////////////// +// +// DLL-Aufrufe +// +////////////////////////////////////////////////////////////////////////// + +void SbiRuntime::DllCall + ( const String& aFuncName, // Funktionsname + const String& aDLLName, // Name der DLL + SbxArray* pArgs, // Parameter (ab Index 1, kann NULL sein) + SbxDataType eResType, // Returnwert + BOOL bCDecl ) // TRUE: nach C-Konventionen +{ + // No DllCall for "virtual" portal users + if( needSecurityRestrictions() ) + { + StarBASIC::Error(SbERR_NOT_IMPLEMENTED); + return; + } + + // MUSS NOCH IMPLEMENTIERT WERDEN + /* + String aMsg; + aMsg = "FUNC="; + aMsg += pFunc; + aMsg += " DLL="; + aMsg += pDLL; + MessBox( NULL, WB_OK, String( "DLL-CALL" ), aMsg ).Execute(); + Error( SbERR_NOT_IMPLEMENTED ); + */ + + SbxVariable* pRes = new SbxVariable( eResType ); + SbiDllMgr* pDllMgr = pInst->GetDllMgr(); + ByteString aByteFuncName( aFuncName, gsl_getSystemTextEncoding() ); + ByteString aByteDLLName( aDLLName, gsl_getSystemTextEncoding() ); + SbError nErr = pDllMgr->Call( aByteFuncName.GetBuffer(), aByteDLLName.GetBuffer(), pArgs, *pRes, bCDecl ); + if( nErr ) + Error( nErr ); + PushVar( pRes ); +} +USHORT +SbiRuntime::GetImageFlag( USHORT n ) const +{ + return pImg->GetFlag( n ); +} +USHORT +SbiRuntime::GetBase() +{ + return pImg->GetBase(); +} diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx new file mode 100644 index 000000000000..b9b2bee387a6 --- /dev/null +++ b/basic/source/runtime/stdobj.cxx @@ -0,0 +1,783 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stdobj.cxx,v $ + * $Revision: 1.28 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "runtime.hxx" +#include "stdobj.hxx" +#include <basic/sbstdobj.hxx> +#include "rtlproto.hxx" +#include "sbintern.hxx" + +// Das nArgs-Feld eines Tabelleneintrags ist wie folgt verschluesselt: +// Zur Zeit wird davon ausgegangen, dass Properties keine Parameter +// benoetigen! + +#define _ARGSMASK 0x007F // Bis zu 127 Argumente +#define _COMPTMASK 0x0080 // Only valid in compatibility mode +#define _RWMASK 0x0F00 // Maske fuer R/W-Bits +#define _TYPEMASK 0xF000 // Maske fuer den Typ des Eintrags + +#define _READ 0x0100 // kann gelesen werden +#define _BWRITE 0x0200 // kann as Lvalue verwendet werden +#define _LVALUE _BWRITE // kann as Lvalue verwendet werden +#define _READWRITE 0x0300 // beides +#define _OPT 0x0400 // Parameter ist optional +#define _CONST 0x0800 // Property ist const +#define _METHOD 0x3000 // Masken-Bits fuer eine Methode +#define _PROPERTY 0x4000 // Masken-Bit fuer eine Property +#define _OBJECT 0x8000 // Masken-Bit fuer ein Objekt + // Kombination von oberen Bits: +#define _FUNCTION 0x1100 // Maske fuer Function +#define _LFUNCTION 0x1300 // Maske fuer Function, die auch als Lvalue geht +#define _SUB 0x2100 // Maske fuer Sub +#define _ROPROP 0x4100 // Maske Read Only-Property +#define _WOPROP 0x4200 // Maske Write Only-Property +#define _RWPROP 0x4300 // Maske Read/Write-Property +#define _CPROP 0x4900 // Maske fuer Konstante + +struct Methods { + const char* pName; // Name des Eintrags + SbxDataType eType; // Datentyp + short nArgs; // Argumente und Flags + RtlCall pFunc; // Function Pointer + USHORT nHash; // Hashcode +}; + +static Methods aMethods[] = { + +{ "AboutStarBasic", SbxNULL, 1 | _FUNCTION, RTLNAME(AboutStarBasic),0 }, + { "Name", SbxSTRING, 0,NULL,0 }, +{ "Abs", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Abs),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "Array", SbxOBJECT, _FUNCTION, RTLNAME(Array),0 }, +{ "Asc", SbxLONG, 1 | _FUNCTION, RTLNAME(Asc),0 }, + { "string", SbxSTRING, 0,NULL,0 }, +{ "AscW", SbxLONG, 1 | _FUNCTION | _COMPTMASK, RTLNAME(Asc),0}, + { "string", SbxSTRING, 0,NULL,0 }, +{ "Atn", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Atn),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "ATTR_ARCHIVE", SbxINTEGER, _CPROP, RTLNAME(ATTR_ARCHIVE),0 }, +{ "ATTR_DIRECTORY", SbxINTEGER, _CPROP, RTLNAME(ATTR_DIRECTORY),0 }, +{ "ATTR_HIDDEN", SbxINTEGER, _CPROP, RTLNAME(ATTR_HIDDEN),0 }, +{ "ATTR_NORMAL", SbxINTEGER, _CPROP, RTLNAME(ATTR_NORMAL),0 }, +{ "ATTR_READONLY", SbxINTEGER, _CPROP, RTLNAME(ATTR_READONLY),0 }, +{ "ATTR_SYSTEM", SbxINTEGER, _CPROP, RTLNAME(ATTR_SYSTEM),0 }, +{ "ATTR_VOLUME", SbxINTEGER, _CPROP, RTLNAME(ATTR_VOLUME),0 }, + +{ "Beep", SbxNULL, _FUNCTION, RTLNAME(Beep),0 }, +{ "Blue", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Blue),0 }, + { "RGB-Value", SbxLONG, 0,NULL,0 }, + +{ "CBool", SbxBOOL, 1 | _FUNCTION, RTLNAME(CBool),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CByte", SbxBYTE, 1 | _FUNCTION, RTLNAME(CByte),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CCur", SbxCURRENCY, 1 | _FUNCTION, RTLNAME(CCur),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CDate", SbxDATE, 1 | _FUNCTION, RTLNAME(CDate),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CDateFromIso", SbxDATE, 1 | _FUNCTION, RTLNAME(CDateFromIso),0 }, + { "IsoDate", SbxSTRING, 0,NULL,0 }, +{ "CDateToIso", SbxSTRING, 1 | _FUNCTION, RTLNAME(CDateToIso),0 }, + { "Date", SbxDATE, 0,NULL,0 }, +{ "CDec", SbxDECIMAL, 1 | _FUNCTION, RTLNAME(CDec),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CDbl", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(CDbl),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CF_BITMAP", SbxINTEGER, _CPROP, RTLNAME(CF_BITMAP),0 }, +{ "CF_METAFILEPICT",SbxINTEGER, _CPROP, RTLNAME(CF_METAFILEPICT),0 }, +{ "CF_TEXT", SbxINTEGER, _CPROP, RTLNAME(CF_TEXT),0 }, +{ "ChDir", SbxNULL, 1 | _FUNCTION, RTLNAME(ChDir),0 }, + { "string", SbxSTRING, 0,NULL,0 }, +{ "ChDrive", SbxNULL, 1 | _FUNCTION, RTLNAME(ChDrive),0 }, + { "string", SbxSTRING, 0,NULL,0 }, + +{ "Choose", SbxVARIANT, 2 | _FUNCTION, RTLNAME(Choose),0 }, + { "Index", SbxINTEGER, 0,NULL,0 }, + { "Expression", SbxVARIANT, 0,NULL,0 }, + +{ "Chr", SbxSTRING, 1 | _FUNCTION, RTLNAME(Chr),0 }, + { "string", SbxINTEGER, 0,NULL,0 }, +{ "ChrW", SbxSTRING, 1 | _FUNCTION | _COMPTMASK, RTLNAME(Chr),0}, + { "string", SbxINTEGER, 0,NULL,0 }, + +{ "CInt", SbxINTEGER, 1 | _FUNCTION, RTLNAME(CInt),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CLEAR_ALLTABS", SbxINTEGER, _CPROP, RTLNAME(CLEAR_ALLTABS),0 }, +{ "CLEAR_TAB", SbxINTEGER, _CPROP, RTLNAME(CLEAR_TAB),0 }, +{ "CLng", SbxLONG, 1 | _FUNCTION, RTLNAME(CLng),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CompatibilityMode", SbxBOOL, 1 | _FUNCTION, RTLNAME(CompatibilityMode),0}, + { "bEnable", SbxBOOL, 0,NULL,0 }, +{ "ConvertFromUrl", SbxSTRING, 1 | _FUNCTION, RTLNAME(ConvertFromUrl),0 }, + { "Url", SbxSTRING, 0,NULL,0 }, +{ "ConvertToUrl", SbxSTRING, 1 | _FUNCTION, RTLNAME(ConvertToUrl),0 }, + { "SystemPath", SbxSTRING, 0,NULL,0 }, +{ "Cos", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Cos),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "CreateObject", SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateObject ),0 }, + { "class", SbxSTRING, 0,NULL,0 }, +{ "CreateUnoListener",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoListener ),0 }, + { "prefix", SbxSTRING, 0,NULL,0 }, + { "typename", SbxSTRING, 0,NULL,0 }, +{ "CreateUnoDialog",SbxOBJECT, 2 | _FUNCTION, RTLNAME( CreateUnoDialog ),0 }, + { "dialoglibrary",SbxOBJECT, 0,NULL,0 }, + { "dialogname", SbxSTRING, 0,NULL,0 }, +{ "CreateUnoService",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoService ),0 }, + { "servicename", SbxSTRING, 0,NULL,0 }, +{ "CreateUnoServiceWithArguments",SbxOBJECT, 2 | _FUNCTION, RTLNAME( CreateUnoServiceWithArguments ),0 }, + { "servicename", SbxSTRING, 0,NULL,0 }, + { "arguments", SbxARRAY, 0,NULL,0 }, +{ "CreateUnoStruct",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoStruct ),0 }, + { "classname", SbxSTRING, 0,NULL,0 }, +{ "CreateUnoValue", SbxOBJECT, 2 | _FUNCTION, RTLNAME( CreateUnoValue ),0 }, + { "type", SbxSTRING, 0,NULL,0 }, + { "value", SbxVARIANT, 0,NULL,0 }, +{ "CreatePropertySet",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreatePropertySet ),0 }, + { "values", SbxARRAY, 0,NULL,0 }, +{ "CSng", SbxSINGLE, 1 | _FUNCTION, RTLNAME(CSng),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CStr", SbxSTRING, 1 | _FUNCTION, RTLNAME(CStr),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CurDir", SbxSTRING, 1 | _FUNCTION, RTLNAME(CurDir),0 }, + { "string", SbxSTRING, 0,NULL,0 }, +{ "CVar", SbxVARIANT, 1 | _FUNCTION, RTLNAME(CVar),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, +{ "CVErr", SbxVARIANT, 1 | _FUNCTION, RTLNAME(CVErr),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, + +{ "Date", SbxDATE, _LFUNCTION,RTLNAME(Date),0 }, +{ "DateAdd", SbxDATE, 3 | _FUNCTION, RTLNAME(DateAdd),0 }, + { "Interval", SbxSTRING, 0,NULL,0 }, + { "Number", SbxLONG, 0,NULL,0 }, + { "Date", SbxDATE, 0,NULL,0 }, +{ "DateDiff", SbxDOUBLE, 5 | _FUNCTION, RTLNAME(DateDiff),0 }, + { "Interval", SbxSTRING, 0,NULL,0 }, + { "Date1", SbxDATE, 0,NULL,0 }, + { "Date2", SbxDATE, 0,NULL,0 }, + { "Firstdayofweek" , SbxINTEGER, _OPT,NULL,0 }, + { "Firstweekofyear", SbxINTEGER, _OPT,NULL,0 }, +{ "DatePart", SbxLONG, 4 | _FUNCTION, RTLNAME(DatePart),0 }, + { "Interval", SbxSTRING, 0,NULL,0 }, + { "Date", SbxDATE, 0,NULL,0 }, + { "Firstdayofweek" , SbxINTEGER, _OPT, NULL,0 }, + { "Firstweekofyear", SbxINTEGER, _OPT, NULL,0 }, +{ "DateSerial", SbxDATE, 3 | _FUNCTION, RTLNAME(DateSerial),0 }, + { "Year", SbxINTEGER, 0,NULL,0 }, + { "Month", SbxINTEGER, 0,NULL,0 }, + { "Day", SbxINTEGER, 0,NULL,0 }, +{ "DateValue", SbxDATE, 1 | _FUNCTION, RTLNAME(DateValue),0 }, + { "String", SbxSTRING, 0,NULL,0 }, +{ "Day", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Day),0 }, + { "Date", SbxDATE, 0,NULL,0 }, +{ "Ddeexecute", SbxNULL, 2 | _FUNCTION, RTLNAME(DDEExecute),0 }, + { "Channel", SbxLONG, 0,NULL,0 }, + { "Command", SbxSTRING, 0,NULL,0 }, +{ "Ddeinitiate", SbxINTEGER, 2 | _FUNCTION, RTLNAME(DDEInitiate),0 }, + { "Application", SbxSTRING, 0,NULL,0 }, + { "Topic", SbxSTRING, 0,NULL,0 }, +{ "Ddepoke", SbxNULL, 3 | _FUNCTION, RTLNAME(DDEPoke),0 }, + { "Channel", SbxLONG, 0,NULL,0 }, + { "Item", SbxSTRING, 0,NULL,0 }, + { "Data", SbxSTRING, 0,NULL,0 }, +{ "Dderequest", SbxSTRING, 2 | _FUNCTION, RTLNAME(DDERequest),0 }, + { "Channel", SbxLONG, 0,NULL,0 }, + { "Item", SbxSTRING, 0,NULL,0 }, +{ "Ddeterminate", SbxNULL, 1 | _FUNCTION, RTLNAME(DDETerminate),0 }, + { "Channel", SbxLONG, 0,NULL,0 }, +{ "Ddeterminateall", SbxNULL, _FUNCTION, RTLNAME(DDETerminateAll),0 }, +{ "DimArray", SbxOBJECT, _FUNCTION, RTLNAME(DimArray),0 }, +{ "Dir", SbxSTRING, 2 | _FUNCTION, RTLNAME(Dir),0 }, + { "FileSpec", SbxSTRING, _OPT, NULL,0 }, + { "attrmask", SbxINTEGER, _OPT, NULL,0 }, +{ "DumpAllObjects", SbxEMPTY, 2 | _SUB, RTLNAME(DumpAllObjects),0 }, + { "FileSpec", SbxSTRING, 0,NULL,0 }, + { "DumpAll", SbxINTEGER, _OPT, NULL,0 }, + +{ "EqualUnoObjects",SbxBOOL, 2 | _FUNCTION, RTLNAME(EqualUnoObjects),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "EnableReschedule", SbxNULL, 1 | _FUNCTION, RTLNAME(EnableReschedule),0}, + { "bEnable", SbxBOOL, 0,NULL,0 }, +{ "Environ", SbxSTRING, 1 | _FUNCTION, RTLNAME(Environ),0 }, + { "Environmentstring",SbxSTRING, 0,NULL,0 }, +{ "EOF", SbxBOOL, 1 | _FUNCTION, RTLNAME(EOF),0 }, + { "Channel", SbxINTEGER, 0,NULL,0 }, +{ "Erl", SbxLONG, _ROPROP, RTLNAME( Erl ),0 }, +{ "Err", SbxLONG, _RWPROP, RTLNAME( Err ),0 }, +{ "Error", SbxSTRING, 1 | _FUNCTION, RTLNAME( Error ),0 }, + { "code", SbxLONG, 0,NULL,0 }, +{ "Exp", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Exp),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, + +{ "False", SbxBOOL, _CPROP, RTLNAME(False),0 }, +{ "FileAttr", SbxINTEGER, 2 | _FUNCTION, RTLNAME(FileAttr),0 }, + { "Channel", SbxINTEGER, 0,NULL,0 }, + { "Attributes", SbxINTEGER, 0,NULL,0 }, +{ "FileCopy", SbxNULL, 2 | _FUNCTION, RTLNAME(FileCopy),0 }, + { "Source", SbxSTRING, 0,NULL,0 }, + { "Destination", SbxSTRING, 0,NULL,0 }, +{ "FileDateTime", SbxSTRING, 1 | _FUNCTION, RTLNAME(FileDateTime),0 }, + { "filename", SbxSTRING, 0,NULL,0 }, +{ "FileExists", SbxBOOL, 1 | _FUNCTION, RTLNAME(FileExists),0 }, + { "filename", SbxSTRING, 0,NULL,0 }, +{ "FileLen", SbxLONG, 1 | _FUNCTION, RTLNAME(FileLen),0 }, + { "filename", SbxSTRING, 0,NULL,0 }, +{ "FindObject", SbxOBJECT, 1 | _FUNCTION, RTLNAME(FindObject),0 }, + { "Name", SbxSTRING, 0,NULL,0 }, +{ "FindPropertyObject", SbxOBJECT, 2 | _FUNCTION, RTLNAME(FindPropertyObject),0 }, + { "Object", SbxOBJECT, 0,NULL,0 }, + { "Name", SbxSTRING, 0,NULL,0 }, +{ "Fix", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Fix),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "Format", SbxSTRING, 2 | _FUNCTION, RTLNAME(Format),0 }, + { "expression", SbxVARIANT, 0,NULL,0 }, + { "format", SbxSTRING, _OPT, NULL,0 }, +{ "FormatDateTime", SbxSTRING, 2 | _FUNCTION | _COMPTMASK, RTLNAME(FormatDateTime),0 }, + { "Date", SbxDATE, 0,NULL,0 }, + { "NamedFormat", SbxINTEGER, _OPT, NULL,0 }, +{ "FRAMEANCHORCHAR", SbxINTEGER, _CPROP, RTLNAME(FRAMEANCHORCHAR),0 }, +{ "FRAMEANCHORPAGE", SbxINTEGER, _CPROP, RTLNAME(FRAMEANCHORPAGE),0 }, +{ "FRAMEANCHORPARA", SbxINTEGER, _CPROP, RTLNAME(FRAMEANCHORPARA),0 }, +{ "FreeFile", SbxINTEGER, _FUNCTION, RTLNAME(FreeFile),0 }, +{ "FreeLibrary", SbxNULL, 1 | _FUNCTION, RTLNAME(FreeLibrary),0 }, + { "Modulename", SbxSTRING, 0,NULL,0 }, + +{ "Get", SbxNULL, 3 | _FUNCTION, RTLNAME(Get),0 }, + { "filenumber", SbxINTEGER, 0,NULL,0 }, + { "recordnumber", SbxLONG, 0,NULL,0 }, + { "variablename", SbxVARIANT, 0,NULL,0 }, +{ "GetAttr", SbxINTEGER, 1 | _FUNCTION, RTLNAME(GetAttr),0 }, + { "filename", SbxSTRING, 0,NULL,0 }, +{ "GetDefaultContext", SbxOBJECT, 0 | _FUNCTION, RTLNAME(GetDefaultContext),0 }, +{ "GetDialogZoomFactorX", SbxDOUBLE, _FUNCTION,RTLNAME(GetDialogZoomFactorX),0 }, +{ "GetDialogZoomFactorY", SbxDOUBLE, _FUNCTION,RTLNAME(GetDialogZoomFactorY),0 }, +{ "GetGUIType", SbxINTEGER, _FUNCTION,RTLNAME(GetGUIType),0 }, +{ "GetGUIVersion", SbxLONG, _FUNCTION,RTLNAME(GetGUIVersion),0 }, +{ "GetPathSeparator", SbxSTRING, _FUNCTION,RTLNAME(GetPathSeparator),0 }, +{ "GetProcessServiceManager", SbxOBJECT, 0 | _FUNCTION, RTLNAME(GetProcessServiceManager),0 }, +{ "GetSolarVersion", SbxLONG, _FUNCTION,RTLNAME(GetSolarVersion),0 }, +{ "GetSystemTicks", SbxLONG, _FUNCTION,RTLNAME(GetSystemTicks),0 }, +{ "GetSystemType", SbxINTEGER, _FUNCTION,RTLNAME(GetSystemType),0 }, +{ "GlobalScope", SbxOBJECT, _FUNCTION,RTLNAME(GlobalScope),0 }, +{ "Green", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Green),0 }, + { "RGB-Value", SbxLONG, 0,NULL,0 }, + +{ "HasUnoInterfaces", SbxBOOL, 1 | _FUNCTION, RTLNAME(HasUnoInterfaces),0}, + { "InterfaceName",SbxSTRING, 0,NULL,0 }, +{ "Hex", SbxSTRING, 1 | _FUNCTION, RTLNAME(Hex),0 }, + { "number", SbxLONG, 0,NULL,0 }, +{ "Hour", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Hour),0 }, + { "Date", SbxDATE, 0,NULL,0 }, + +{ "IDABORT", SbxINTEGER, _CPROP, RTLNAME(IDABORT),0 }, +{ "IDCANCEL", SbxINTEGER, _CPROP, RTLNAME(IDCANCEL),0 }, +{ "IDNO", SbxINTEGER, _CPROP, RTLNAME(IDNO),0 }, +{ "IDOK", SbxINTEGER, _CPROP, RTLNAME(IDOK),0 }, +{ "IDRETRY", SbxINTEGER, _CPROP, RTLNAME(IDRETRY),0 }, +{ "IDYES", SbxINTEGER, _CPROP, RTLNAME(IDYES),0 }, + +{ "Iif", SbxVARIANT, 3 | _FUNCTION, RTLNAME(Iif),0 }, + { "Bool", SbxBOOL, 0,NULL,0 }, + { "Variant1", SbxVARIANT, 0,NULL,0 }, + { "Variant2", SbxVARIANT, 0,NULL,0 }, + +{ "Input", SbxSTRING, 2 | _FUNCTION | _COMPTMASK, RTLNAME(Input),0}, + { "Number", SbxLONG, 0,NULL,0 }, + { "FileNumber", SbxLONG, 0,NULL,0 }, +{ "InputBox", SbxSTRING, 5 | _FUNCTION, RTLNAME(InputBox),0 }, + { "Prompt", SbxSTRING, 0,NULL,0 }, + { "Title", SbxSTRING, _OPT, NULL,0 }, + { "Default", SbxSTRING, _OPT, NULL,0 }, + { "XPosTwips", SbxLONG, _OPT, NULL,0 }, + { "YPosTwips", SbxLONG, _OPT, NULL,0 }, +{ "InStr", SbxLONG, 4 | _FUNCTION, RTLNAME(InStr),0 }, + { "Start", SbxSTRING, _OPT, NULL,0 }, + { "String1", SbxSTRING, 0,NULL,0 }, + { "String2", SbxSTRING, 0,NULL,0 }, + { "Compare", SbxINTEGER, _OPT, NULL,0 }, +{ "InStrRev", SbxLONG, 4 | _FUNCTION | _COMPTMASK, RTLNAME(InStrRev),0}, + { "String1", SbxSTRING, 0,NULL,0 }, + { "String2", SbxSTRING, 0,NULL,0 }, + { "Start", SbxSTRING, _OPT, NULL,0 }, + { "Compare", SbxINTEGER, _OPT, NULL,0 }, +{ "Int", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Int),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "IsArray", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsArray),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsDate", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsDate),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsEmpty", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsEmpty),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsError", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsError),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsMissing", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsMissing),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsNull", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsNull),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsNumeric", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsNumeric),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsObject", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsObject),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "IsUnoStruct", SbxBOOL, 1 | _FUNCTION, RTLNAME(IsUnoStruct),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "Join", SbxSTRING, 2 | _FUNCTION, RTLNAME(Join),0 }, + { "list", SbxOBJECT, 0,NULL,0 }, + { "delimiter", SbxSTRING, 0,NULL,0 }, +{ "Kill", SbxNULL, 1 | _FUNCTION, RTLNAME(Kill),0 }, + { "filespec", SbxSTRING, 0,NULL,0 }, +{ "LBound", SbxLONG, 1 | _FUNCTION, RTLNAME(LBound),0 }, + { "Variant", SbxVARIANT, 0,NULL,0 }, +{ "LCase", SbxSTRING, 1 | _FUNCTION, RTLNAME(LCase),0 }, + { "string", SbxSTRING, 0,NULL,0 }, +{ "Left", SbxSTRING, 2 | _FUNCTION, RTLNAME(Left),0 }, + { "String", SbxSTRING, 0,NULL,0 }, + { "Count", SbxLONG, 0,NULL,0 }, +{ "Len", SbxLONG, 1 | _FUNCTION, RTLNAME(Len),0 }, + { "StringOrVariant", SbxVARIANT, 0,NULL,0 }, +{ "Load", SbxNULL, 1 | _FUNCTION, RTLNAME(Load),0 }, + { "object", SbxOBJECT, 0,NULL,0 }, +{ "LoadPicture", SbxOBJECT, 1 | _FUNCTION, RTLNAME(LoadPicture),0 }, + { "string", SbxSTRING, 0,NULL,0 }, +{ "Loc", SbxLONG, 1 | _FUNCTION, RTLNAME(Loc),0 }, + { "Channel", SbxINTEGER, 0,NULL,0 }, +{ "Lof", SbxLONG, 1 | _FUNCTION, RTLNAME(Lof),0 }, + { "Channel", SbxINTEGER, 0,NULL,0 }, +{ "Log", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Log),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "LTrim", SbxSTRING, 1 | _FUNCTION, RTLNAME(LTrim),0 }, + { "string", SbxSTRING, 0,NULL,0 }, + +{ "MB_ABORTRETRYIGNORE", SbxINTEGER, _CPROP, RTLNAME(MB_ABORTRETRYIGNORE),0}, +{ "MB_APPLMODAL", SbxINTEGER, _CPROP, RTLNAME(MB_APPLMODAL),0 }, +{ "MB_DEFBUTTON1", SbxINTEGER, _CPROP, RTLNAME(MB_DEFBUTTON1),0 }, +{ "MB_DEFBUTTON2", SbxINTEGER, _CPROP, RTLNAME(MB_DEFBUTTON2),0 }, +{ "MB_DEFBUTTON3", SbxINTEGER, _CPROP, RTLNAME(MB_DEFBUTTON3),0 }, +{ "MB_ICONEXCLAMATION", SbxINTEGER, _CPROP, RTLNAME(MB_ICONEXCLAMATION),0}, +{ "MB_ICONINFORMATION", SbxINTEGER, _CPROP, RTLNAME(MB_ICONINFORMATION),0}, +{ "MB_ICONQUESTION",SbxINTEGER, _CPROP, RTLNAME(MB_ICONQUESTION),0 }, +{ "MB_ICONSTOP", SbxINTEGER, _CPROP, RTLNAME(MB_ICONSTOP),0 }, +{ "MB_OK", SbxINTEGER, _CPROP, RTLNAME(MB_OK),0 }, +{ "MB_OKCANCEL", SbxINTEGER, _CPROP, RTLNAME(MB_OKCANCEL),0 }, +{ "MB_RETRYCANCEL", SbxINTEGER, _CPROP, RTLNAME(MB_RETRYCANCEL),0 }, +{ "MB_SYSTEMMODAL", SbxINTEGER, _CPROP, RTLNAME(MB_SYSTEMMODAL),0 }, +{ "MB_YESNO", SbxINTEGER, _CPROP, RTLNAME(MB_YESNO),0 }, +{ "MB_YESNOCANCEL", SbxINTEGER, _CPROP, RTLNAME(MB_YESNOCANCEL),0 }, + +{ "Me", SbxOBJECT, 0 | _FUNCTION | _COMPTMASK, RTLNAME(Me),0 }, +{ "Mid", SbxSTRING, 3 | _LFUNCTION,RTLNAME(Mid),0 }, + { "String", SbxSTRING, 0,NULL,0 }, + { "StartPos", SbxLONG, 0,NULL,0 }, + { "Length", SbxLONG, _OPT, NULL,0 }, +{ "Minute", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Minute),0 }, + { "Date", SbxDATE, 0,NULL,0 }, +{ "MkDir", SbxNULL, 1 | _FUNCTION, RTLNAME(MkDir),0 }, + { "pathname", SbxSTRING, 0,NULL,0 }, +{ "Month", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Month),0 }, + { "Date", SbxDATE, 0,NULL,0 }, +{ "MonthName", SbxSTRING, 2 | _FUNCTION | _COMPTMASK, RTLNAME(MonthName),0 }, + { "Month", SbxINTEGER, 0,NULL,0 }, + { "Abbreviate", SbxBOOL, _OPT, NULL,0 }, +{ "MsgBox", SbxINTEGER, 5 | _FUNCTION, RTLNAME(MsgBox),0 }, + { "Prompt", SbxSTRING, 0,NULL,0 }, + { "Buttons", SbxINTEGER, _OPT, NULL,0 }, + { "Title", SbxSTRING, _OPT, NULL,0 }, + { "Helpfile", SbxSTRING, _OPT, NULL,0 }, + { "Context", SbxINTEGER, _OPT, NULL,0 }, + +{ "Nothing", SbxOBJECT, _CPROP, RTLNAME(Nothing),0 }, +{ "Now", SbxDATE, _FUNCTION, RTLNAME(Now),0 }, +{ "Null", SbxNULL, _CPROP, RTLNAME(Null),0 }, + +{ "Oct", SbxSTRING, 1 | _FUNCTION, RTLNAME(Oct),0 }, + { "number", SbxLONG, 0,NULL,0 }, + +{ "Partition", SbxSTRING, 4 | _FUNCTION, RTLNAME(Partition),0 }, + { "number", SbxLONG, 0,NULL,0 }, + { "start", SbxLONG, 0,NULL,0 }, + { "stop", SbxLONG, 0,NULL,0 }, + { "interval", SbxLONG, 0,NULL,0 }, +{ "Pi", SbxDOUBLE, _CPROP, RTLNAME(PI),0 }, +{ "Put", SbxNULL, 3 | _FUNCTION, RTLNAME(Put),0 }, + { "filenumber", SbxINTEGER, 0,NULL,0 }, + { "recordnumber", SbxLONG, 0,NULL,0 }, + { "variablename", SbxVARIANT, 0,NULL,0 }, + +{ "QBColor", SbxLONG, 1 | _FUNCTION, RTLNAME(QBColor),0 }, + { "number", SbxINTEGER, 0,NULL,0 }, + +{ "Randomize", SbxNULL, 1 | _FUNCTION, RTLNAME(Randomize),0 }, + { "Number", SbxDOUBLE, _OPT, NULL,0 }, +{ "Red", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Red),0 }, + { "RGB-Value", SbxLONG, 0,NULL,0 }, +{ "Reset", SbxNULL, 0 | _FUNCTION, RTLNAME(Reset),0 }, +{ "ResolvePath", SbxSTRING, 1 | _FUNCTION, RTLNAME(ResolvePath),0 }, + { "Path", SbxSTRING, 0,NULL,0 }, +{ "RGB", SbxLONG, 3 | _FUNCTION, RTLNAME(RGB),0 }, + { "Red", SbxINTEGER, 0,NULL,0 }, + { "Green", SbxINTEGER, 0,NULL,0 }, + { "Blue", SbxINTEGER, 0,NULL,0 }, +{ "Replace", SbxSTRING, 6 | _FUNCTION, RTLNAME(Replace),0 }, + { "Expression", SbxSTRING, 0,NULL,0 }, + { "Find", SbxSTRING, 0,NULL,0 }, + { "Replace", SbxSTRING, 0,NULL,0 }, + { "Start", SbxINTEGER, _OPT, NULL,0 }, + { "Count", SbxINTEGER, _OPT, NULL,0 }, + { "Compare", SbxINTEGER, _OPT, NULL,0 }, +{ "Right", SbxSTRING, 2 | _FUNCTION, RTLNAME(Right),0 }, + { "String", SbxSTRING, 0,NULL,0 }, + { "Count", SbxLONG, 0,NULL,0 }, +{ "RmDir", SbxNULL, 1 | _FUNCTION, RTLNAME(RmDir),0 }, + { "pathname", SbxSTRING, 0,NULL,0 }, +{ "Round", SbxDOUBLE, 2 | _FUNCTION | _COMPTMASK, RTLNAME(Round),0}, + { "Expression", SbxDOUBLE, 0,NULL,0 }, + { "Numdecimalplaces", SbxINTEGER, _OPT, NULL,0 }, +{ "Rnd", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Rnd),0 }, + { "Number", SbxDOUBLE, _OPT, NULL,0 }, +{ "RTL", SbxOBJECT, 0 | _FUNCTION | _COMPTMASK, RTLNAME(RTL),0}, +{ "RTrim", SbxSTRING, 1 | _FUNCTION, RTLNAME(RTrim),0 }, + { "string", SbxSTRING, 0,NULL,0 }, + +{ "SavePicture", SbxNULL, 2 | _FUNCTION, RTLNAME(SavePicture),0 }, + { "object", SbxOBJECT, 0,NULL,0 }, + { "string", SbxSTRING, 0,NULL,0 }, +{ "Second", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Second),0 }, + { "Date", SbxDATE, 0,NULL,0 }, +{ "Seek", SbxLONG, 1 | _FUNCTION, RTLNAME(Seek),0 }, + { "Channel", SbxINTEGER, 0,NULL,0 }, +{ "SendKeys", SbxNULL, 2 | _FUNCTION, RTLNAME(SendKeys),0 }, + { "String", SbxSTRING, 0,NULL,0 }, + { "Wait", SbxBOOL, _OPT, NULL,0 }, +{ "SetAttr", SbxNULL, 2 | _FUNCTION, RTLNAME(SetAttr),0 }, + { "File" , SbxSTRING, 0,NULL,0 }, + { "Attributes", SbxINTEGER, 0,NULL,0 }, +{ "SET_OFF", SbxINTEGER, _CPROP, RTLNAME(SET_OFF),0 }, +{ "SET_ON", SbxINTEGER, _CPROP, RTLNAME(SET_ON),0 }, +{ "SET_TAB", SbxINTEGER, _CPROP, RTLNAME(SET_TAB),0 }, +{ "Sgn", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Sgn),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "Shell", SbxLONG, 2 | _FUNCTION, RTLNAME(Shell),0 }, + { "Commandstring",SbxSTRING, 0,NULL,0 }, + { "WindowStyle", SbxINTEGER, _OPT, NULL,0 }, +{ "Sin", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Sin),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "Space", SbxSTRING, 1 | _FUNCTION, RTLNAME(Space),0 }, + { "string", SbxLONG, 0,NULL,0 }, +{ "Spc", SbxSTRING, 1 | _FUNCTION, RTLNAME(Spc),0 }, + { "Count", SbxLONG, 0,NULL,0 }, +{ "Split", SbxOBJECT, 3 | _FUNCTION, RTLNAME(Split),0 }, + { "expression", SbxSTRING, 0,NULL,0 }, + { "delimiter", SbxSTRING, 0,NULL,0 }, + { "count", SbxLONG, 0,NULL,0 }, +{ "Sqr", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Sqr),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "Str", SbxSTRING, 1 | _FUNCTION, RTLNAME(Str),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "StrComp", SbxINTEGER, 3 | _FUNCTION, RTLNAME(StrComp),0 }, + { "String1", SbxSTRING, 0,NULL,0 }, + { "String2", SbxSTRING, 0,NULL,0 }, + { "Compare", SbxINTEGER, _OPT, NULL,0 }, +{ "StrConv", SbxOBJECT, 3 | _FUNCTION, RTLNAME(StrConv),0 }, + { "String", SbxSTRING, 0,NULL,0 }, + { "Conversion", SbxSTRING, 0,NULL,0 }, + { "LCID", SbxINTEGER, _OPT,NULL,0 }, +{ "String", SbxSTRING, 2 | _FUNCTION, RTLNAME(String),0 }, + { "Count", SbxLONG, 0,NULL,0 }, + { "Filler", SbxVARIANT, 0,NULL,0 }, +{ "StrReverse", SbxSTRING, 1 | _FUNCTION | _COMPTMASK, RTLNAME(StrReverse),0 }, + { "String1", SbxSTRING, 0,NULL,0 }, +{ "Switch", SbxVARIANT, 2 | _FUNCTION, RTLNAME(Switch),0 }, + { "Expression", SbxVARIANT, 0,NULL,0 }, + { "Value", SbxVARIANT, 0,NULL,0 }, + +{ "Tan", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Tan),0 }, + { "number", SbxDOUBLE, 0,NULL,0 }, +{ "Time", SbxVARIANT, _LFUNCTION,RTLNAME(Time),0 }, +{ "Timer", SbxDATE, _FUNCTION, RTLNAME(Timer),0 }, +{ "TimeSerial", SbxDATE, 3 | _FUNCTION, RTLNAME(TimeSerial),0 }, + { "Hour", SbxLONG, 0,NULL,0 }, + { "Minute", SbxLONG, 0,NULL,0 }, + { "Second", SbxLONG, 0,NULL,0 }, +{ "TimeValue", SbxDATE, 1 | _FUNCTION, RTLNAME(TimeValue),0 }, + { "String", SbxSTRING, 0,NULL,0 }, +{ "TOGGLE", SbxINTEGER, _CPROP, RTLNAME(TOGGLE),0 }, +{ "Trim", SbxSTRING, 1 | _FUNCTION, RTLNAME(Trim),0 }, + { "String", SbxSTRING, 0,NULL,0 }, +{ "True", SbxBOOL, _CPROP, RTLNAME(True),0 }, +{ "TwipsPerPixelX", SbxLONG, _FUNCTION, RTLNAME(TwipsPerPixelX),0 }, +{ "TwipsPerPixelY", SbxLONG, _FUNCTION, RTLNAME(TwipsPerPixelY),0 }, + +{ "TYP_AUTHORFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_AUTHORFLD),0 }, +{ "TYP_CHAPTERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_CHAPTERFLD),0 }, +{ "TYP_CONDTXTFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_CONDTXTFLD),0 }, +{ "TYP_DATEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DATEFLD),0 }, +{ "TYP_DBFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBFLD),0 }, +{ "TYP_DBNAMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBNAMEFLD),0 }, +{ "TYP_DBNEXTSETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBNEXTSETFLD),0 }, +{ "TYP_DBNUMSETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBNUMSETFLD),0 }, +{ "TYP_DBSETNUMBERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DBSETNUMBERFLD),0 }, +{ "TYP_DDEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DDEFLD),0 }, +{ "TYP_DOCINFOFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DOCINFOFLD),0 }, +{ "TYP_DOCSTATFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_DOCSTATFLD),0 }, +{ "TYP_EXTUSERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_EXTUSERFLD),0 }, +{ "TYP_FILENAMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FILENAMEFLD),0 }, +{ "TYP_FIXDATEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FIXDATEFLD),0 }, +{ "TYP_FIXTIMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FIXTIMEFLD),0 }, +{ "TYP_FORMELFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_FORMELFLD),0 }, +{ "TYP_GETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_GETFLD),0 }, +{ "TYP_GETREFFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_GETREFFLD),0 }, +{ "TYP_GETREFPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_GETREFPAGEFLD),0 }, +{ "TYP_HIDDENPARAFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_HIDDENPARAFLD),0 }, +{ "TYP_HIDDENTXTFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_HIDDENTXTFLD),0 }, +{ "TYP_INPUTFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_INPUTFLD),0 }, +{ "TYP_INTERNETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_INTERNETFLD),0 }, +{ "TYP_JUMPEDITFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_JUMPEDITFLD),0 }, +{ "TYP_MACROFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_MACROFLD),0 }, +{ "TYP_NEXTPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_NEXTPAGEFLD),0 }, +{ "TYP_PAGENUMBERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_PAGENUMBERFLD),0 }, +{ "TYP_POSTITFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_POSTITFLD),0 }, +{ "TYP_PREVPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_PREVPAGEFLD),0 }, +{ "TYP_SEQFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SEQFLD),0 }, +{ "TYP_SETFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETFLD),0 }, +{ "TYP_SETINPFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETINPFLD),0 }, +{ "TYP_SETREFFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETREFFLD),0 }, +{ "TYP_SETREFPAGEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_SETREFPAGEFLD),0 }, +{ "TYP_TEMPLNAMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_TEMPLNAMEFLD),0}, +{ "TYP_TIMEFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_TIMEFLD),0 }, +{ "TYP_USERFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_USERFLD),0 }, +{ "TYP_USRINPFLD", SbxINTEGER, _CPROP, RTLNAME(TYP_USRINPFLD),0 }, + +{ "TypeLen", SbxINTEGER, 1 | _FUNCTION, RTLNAME(TypeLen),0 }, + { "Var", SbxVARIANT, 0,NULL,0 }, +{ "TypeName", SbxSTRING, 1 | _FUNCTION, RTLNAME(TypeName),0 }, + { "Var", SbxVARIANT, 0,NULL,0 }, + +{ "UBound", SbxLONG, 1 | _FUNCTION, RTLNAME(UBound),0 }, + { "Var", SbxVARIANT, 0,NULL,0 }, +{ "UCase", SbxSTRING, 1 | _FUNCTION, RTLNAME(UCase),0 }, + { "String", SbxSTRING, 0,NULL,0 }, +{ "Unload", SbxNULL, 1 | _FUNCTION, RTLNAME(Unload),0 }, + { "Dialog", SbxOBJECT, 0,NULL,0 }, + +{ "Val", SbxDOUBLE, 1 | _FUNCTION, RTLNAME(Val),0 }, + { "String", SbxSTRING, 0,NULL,0 }, +{ "VarType", SbxINTEGER, 1 | _FUNCTION, RTLNAME(VarType),0 }, + { "Var", SbxVARIANT, 0,NULL,0 }, +{ "V_EMPTY", SbxINTEGER, _CPROP, RTLNAME(V_EMPTY),0 }, +{ "V_NULL", SbxINTEGER, _CPROP, RTLNAME(V_NULL),0 }, +{ "V_INTEGER", SbxINTEGER, _CPROP, RTLNAME(V_INTEGER),0 }, +{ "V_LONG", SbxINTEGER, _CPROP, RTLNAME(V_LONG),0 }, +{ "V_SINGLE", SbxINTEGER, _CPROP, RTLNAME(V_SINGLE),0 }, +{ "V_DOUBLE", SbxINTEGER, _CPROP, RTLNAME(V_DOUBLE),0 }, +{ "V_CURRENCY", SbxINTEGER, _CPROP, RTLNAME(V_CURRENCY),0 }, +{ "V_DATE", SbxINTEGER, _CPROP, RTLNAME(V_DATE),0 }, +{ "V_STRING", SbxINTEGER, _CPROP, RTLNAME(V_STRING),0 }, + +{ "Wait", SbxNULL, 1 | _FUNCTION, RTLNAME(Wait),0 }, + { "Milliseconds", SbxLONG, 0,NULL,0 }, +//#i64882# +{ "WaitUntil", SbxNULL, 1 | _FUNCTION, RTLNAME(WaitUntil),0 }, + { "Date", SbxDOUBLE, 0,NULL,0 }, +{ "Weekday", SbxINTEGER, 2 | _FUNCTION, RTLNAME(Weekday),0 }, + { "Date", SbxDATE, 0,NULL,0 }, + { "Firstdayofweek", SbxINTEGER, _OPT, NULL,0 }, +{ "WeekdayName", SbxSTRING, 3 | _FUNCTION | _COMPTMASK, RTLNAME(WeekdayName),0 }, + { "Weekday", SbxINTEGER, 0,NULL,0 }, + { "Abbreviate", SbxBOOL, _OPT, NULL,0 }, + { "Firstdayofweek", SbxINTEGER, _OPT, NULL,0 }, +{ "Year", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Year),0 }, + { "Date", SbxDATE, 0,NULL,0 }, + +{ NULL, SbxNULL, -1,NULL,0 }}; // Tabellenende + +SbiStdObject::SbiStdObject( const String& r, StarBASIC* pb ) : SbxObject( r ) +{ + // Muessen wir die Hashcodes initialisieren? + Methods* p = aMethods; + if( !p->nHash ) + while( p->nArgs != -1 ) + { + String aName_ = String::CreateFromAscii( p->pName ); + p->nHash = SbxVariable::MakeHashCode( aName_ ); + p += ( p->nArgs & _ARGSMASK ) + 1; + } + + SetParent( pb ); + + pStdFactory = new SbStdFactory; + SbxBase::AddFactory( pStdFactory ); + + Insert( new SbStdClipboard ); +} + +SbiStdObject::~SbiStdObject() +{ + SbxBase::RemoveFactory( pStdFactory ); + delete pStdFactory; +} + +// Suche nach einem Element: +// Hier wird linear durch die Methodentabelle gegangen, bis eine +// passende Methode gefunden wurde. Auf Grund der Bits im nArgs-Feld +// wird dann die passende Instanz eines SbxObjElement generiert. +// Wenn die Methode/Property nicht gefunden wurde, nur NULL ohne +// Fehlercode zurueckliefern, da so auch eine ganze Chain von +// Objekten nach der Methode/Property befragt werden kann. + +SbxVariable* SbiStdObject::Find( const String& rName, SbxClassType t ) +{ + // Bereits eingetragen? + SbxVariable* pVar = SbxObject::Find( rName, t ); + if( !pVar ) + { + // sonst suchen + USHORT nHash_ = SbxVariable::MakeHashCode( rName ); + Methods* p = aMethods; + BOOL bFound = FALSE; + short nIndex = 0; + USHORT nSrchMask = _TYPEMASK; + switch( t ) + { + case SbxCLASS_METHOD: nSrchMask = _METHOD; break; + case SbxCLASS_PROPERTY: nSrchMask = _PROPERTY; break; + case SbxCLASS_OBJECT: nSrchMask = _OBJECT; break; + default: break; + } + while( p->nArgs != -1 ) + { + if( ( p->nArgs & nSrchMask ) + && ( p->nHash == nHash_ ) + && ( rName.EqualsIgnoreCaseAscii( p->pName ) ) ) + { + bFound = TRUE; + if( p->nArgs & _COMPTMASK ) + { + SbiInstance* pInst = pINST; + if( !pInst || !pInst->IsCompatibility() ) + bFound = FALSE; + } + break; + } + nIndex += ( p->nArgs & _ARGSMASK ) + 1; + p = aMethods + nIndex; + } + + if( bFound ) + { + // Args-Felder isolieren: + short nAccess = ( p->nArgs & _RWMASK ) >> 8; + short nType = ( p->nArgs & _TYPEMASK ); + if( p->nArgs & _CONST ) + nAccess |= SBX_CONST; + String aName_ = String::CreateFromAscii( p->pName ); + SbxClassType eCT = SbxCLASS_OBJECT; + if( nType & _PROPERTY ) + eCT = SbxCLASS_PROPERTY; + else if( nType & _METHOD ) + eCT = SbxCLASS_METHOD; + pVar = Make( aName_, eCT, p->eType ); + pVar->SetUserData( nIndex + 1 ); + pVar->SetFlags( nAccess ); + } + } + return pVar; +} + +// SetModified muß bei der RTL abgklemmt werden +void SbiStdObject::SetModified( BOOL ) +{ +} + +// Aufruf einer Property oder Methode. + +void SbiStdObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) + +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pPar_ = pVar->GetParameters(); + ULONG t = pHint->GetId(); + USHORT nCallId = (USHORT) pVar->GetUserData(); + if( nCallId ) + { + if( t == SBX_HINT_INFOWANTED ) + pVar->SetInfo( GetInfo( (short) pVar->GetUserData() ) ); + else + { + BOOL bWrite = FALSE; + if( t == SBX_HINT_DATACHANGED ) + bWrite = TRUE; + if( t == SBX_HINT_DATAWANTED || bWrite ) + { + RtlCall p = (RtlCall) aMethods[ nCallId-1 ].pFunc; + SbxArrayRef rPar( pPar_ ); + if( !pPar_ ) + { + rPar = pPar_ = new SbxArray; + pPar_->Put( pVar, 0 ); + } + p( (StarBASIC*) GetParent(), *pPar_, bWrite ); + return; + } + } + } + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + +// Zusammenbau der Infostruktur fuer einzelne Elemente +// Falls nIdx = 0, nix erzeugen (sind Std-Props!) + +SbxInfo* SbiStdObject::GetInfo( short nIdx ) +{ + if( !nIdx ) + return NULL; + Methods* p = &aMethods[ --nIdx ]; + // Wenn mal eine Hilfedatei zur Verfuegung steht: + // SbxInfo* pInfo_ = new SbxInfo( Hilfedateiname, p->nHelpId ); + SbxInfo* pInfo_ = new SbxInfo; + short nPar = p->nArgs & _ARGSMASK; + for( short i = 0; i < nPar; i++ ) + { + p++; + String aName_ = String::CreateFromAscii( p->pName ); + USHORT nFlags_ = ( p->nArgs >> 8 ) & 0x03; + if( p->nArgs & _OPT ) + nFlags_ |= SBX_OPTIONAL; + pInfo_->AddParam( aName_, p->eType, nFlags_ ); + } + return pInfo_; +} + diff --git a/basic/source/runtime/stdobj1.cxx b/basic/source/runtime/stdobj1.cxx new file mode 100644 index 000000000000..7e0fef5cccc9 --- /dev/null +++ b/basic/source/runtime/stdobj1.cxx @@ -0,0 +1,554 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stdobj1.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <vcl/wrkwin.hxx> +#include <vcl/svapp.hxx> +#include <svtools/transfer.hxx> +#include "runtime.hxx" +#include <basic/sbstdobj.hxx> + +#define ATTR_IMP_TYPE 1 +#define ATTR_IMP_WIDTH 2 +#define ATTR_IMP_HEIGHT 3 +#define ATTR_IMP_BOLD 4 +#define ATTR_IMP_ITALIC 5 +#define ATTR_IMP_STRIKETHROUGH 6 +#define ATTR_IMP_UNDERLINE 7 +#define ATTR_IMP_WEIGHT 8 +#define ATTR_IMP_SIZE 9 +#define ATTR_IMP_NAME 10 + +#define METH_CLEAR 20 +#define METH_GETDATA 21 +#define METH_GETFORMAT 22 +#define METH_GETTEXT 23 +#define METH_SETDATA 24 +#define METH_SETTEXT 25 + +//------------------------------------------------------------------------------ +SbStdFactory::SbStdFactory() +{ +} + +SbxObject* SbStdFactory::CreateObject( const String& rClassName ) +{ + if( rClassName.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("Picture") ) ) ) + return new SbStdPicture; + else + if( rClassName.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("Font") ) ) ) + return new SbStdFont; + else + return NULL; +} + +//------------------------------------------------------------------------------ + + + +void SbStdPicture::PropType( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + { + StarBASIC::Error( SbERR_PROP_READONLY ); + return; + } + + GraphicType eType = aGraphic.GetType(); + INT16 nType = 0; + + if( eType == GRAPHIC_BITMAP ) + nType = 1; + else + if( eType != GRAPHIC_NONE ) + nType = 2; + + pVar->PutInteger( nType ); +} + + +void SbStdPicture::PropWidth( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + { + StarBASIC::Error( SbERR_PROP_READONLY ); + return; + } + + Size aSize = aGraphic.GetPrefSize(); + aSize = GetpApp()->GetAppWindow()->LogicToPixel( aSize, aGraphic.GetPrefMapMode() ); + aSize = GetpApp()->GetAppWindow()->PixelToLogic( aSize, MapMode( MAP_TWIP ) ); + + pVar->PutInteger( (INT16)aSize.Width() ); +} + +void SbStdPicture::PropHeight( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + { + StarBASIC::Error( SbERR_PROP_READONLY ); + return; + } + + Size aSize = aGraphic.GetPrefSize(); + aSize = GetpApp()->GetAppWindow()->LogicToPixel( aSize, aGraphic.GetPrefMapMode() ); + aSize = GetpApp()->GetAppWindow()->PixelToLogic( aSize, MapMode( MAP_TWIP ) ); + + pVar->PutInteger( (INT16)aSize.Height() ); +} + + +TYPEINIT1( SbStdPicture, SbxObject ); + +SbStdPicture::SbStdPicture() : + SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("Picture") ) ) +{ + // Properties + SbxVariable* p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Type") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READ | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_TYPE ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Width") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READ | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_WIDTH ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Height") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READ | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_HEIGHT ); +} + +SbStdPicture::~SbStdPicture() +{ +} + + +SbxVariable* SbStdPicture::Find( const String& rName, SbxClassType t ) +{ + // Bereits eingetragen? + return SbxObject::Find( rName, t ); +} + + + +void SbStdPicture::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) + +{ + const SbxHint* pHint = PTR_CAST( SbxHint, &rHint ); + + if( pHint ) + { + if( pHint->GetId() == SBX_HINT_INFOWANTED ) + { + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + return; + } + + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pPar_ = pVar->GetParameters(); + USHORT nWhich = (USHORT)pVar->GetUserData(); + BOOL bWrite = pHint->GetId() == SBX_HINT_DATACHANGED; + + // Propteries + switch( nWhich ) + { + case ATTR_IMP_TYPE: PropType( pVar, pPar_, bWrite ); return; + case ATTR_IMP_WIDTH: PropWidth( pVar, pPar_, bWrite ); return; + case ATTR_IMP_HEIGHT: PropHeight( pVar, pPar_, bWrite ); return; + } + + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + +//----------------------------------------------------------------------------- + +void SbStdFont::PropBold( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + SetBold( pVar->GetBool() ); + else + pVar->PutBool( IsBold() ); +} + +void SbStdFont::PropItalic( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + SetItalic( pVar->GetBool() ); + else + pVar->PutBool( IsItalic() ); +} + +void SbStdFont::PropStrikeThrough( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + SetStrikeThrough( pVar->GetBool() ); + else + pVar->PutBool( IsStrikeThrough() ); +} + +void SbStdFont::PropUnderline( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + SetUnderline( pVar->GetBool() ); + else + pVar->PutBool( IsUnderline() ); +} + +void SbStdFont::PropSize( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + SetSize( (USHORT)pVar->GetInteger() ); + else + pVar->PutInteger( (INT16)GetSize() ); +} + +void SbStdFont::PropName( SbxVariable* pVar, SbxArray*, BOOL bWrite ) +{ + if( bWrite ) + SetFontName( pVar->GetString() ); + else + pVar->PutString( GetFontName() ); +} + + +TYPEINIT1( SbStdFont, SbxObject ); + +SbStdFont::SbStdFont() : + SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("Font") ) ) +{ + // Properties + SbxVariable* p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Bold") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READWRITE | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_BOLD ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Italic") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READWRITE | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_ITALIC ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("StrikeThrough") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READWRITE | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_STRIKETHROUGH ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Underline") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READWRITE | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_UNDERLINE ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Size") ), SbxCLASS_PROPERTY, SbxVARIANT ); + p->SetFlags( SBX_READWRITE | SBX_DONTSTORE ); + p->SetUserData( ATTR_IMP_SIZE ); + + // Name Property selbst verarbeiten + p = Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY ); + DBG_ASSERT( p, "Keine Name Property" ); + p->SetUserData( ATTR_IMP_NAME ); +} + +SbStdFont::~SbStdFont() +{ +} + + +SbxVariable* SbStdFont::Find( const String& rName, SbxClassType t ) +{ + // Bereits eingetragen? + return SbxObject::Find( rName, t ); +} + + + +void SbStdFont::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST( SbxHint, &rHint ); + + if( pHint ) + { + if( pHint->GetId() == SBX_HINT_INFOWANTED ) + { + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + return; + } + + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pPar_ = pVar->GetParameters(); + USHORT nWhich = (USHORT)pVar->GetUserData(); + BOOL bWrite = pHint->GetId() == SBX_HINT_DATACHANGED; + + // Propteries + switch( nWhich ) + { + case ATTR_IMP_BOLD: PropBold( pVar, pPar_, bWrite ); return; + case ATTR_IMP_ITALIC: PropItalic( pVar, pPar_, bWrite ); return; + case ATTR_IMP_STRIKETHROUGH:PropStrikeThrough( pVar, pPar_, bWrite ); return; + case ATTR_IMP_UNDERLINE: PropUnderline( pVar, pPar_, bWrite ); return; + case ATTR_IMP_SIZE: PropSize( pVar, pPar_, bWrite ); return; + case ATTR_IMP_NAME: PropName( pVar, pPar_, bWrite ); return; + } + + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + + +//----------------------------------------------------------------------------- + +/* +class TransferableHelperImpl : public TransferableHelper +{ + SotFormatStringId mFormat; + String mString; + Graphic mGraphic; + + virtual void AddSupportedFormats(); + virtual sal_Bool GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ); + +public: + TransferableHelperImpl( void ) { mFormat = 0; } + TransferableHelperImpl( const String& rStr ) + mFormat( FORMAT_STRING ), mString( rStr ) {} + TransferableHelperImpl( const Graphic& rGraphic ); + mFormat( FORMAT_BITMAP ), mGraphic( rGraphic ) {} + +}; + +void TransferableHelperImpl::AddSupportedFormats() +{ +} + +sal_Bool TransferableHelperImpl::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ) +{ + sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); + if( nFormat == FORMAT_STRING ) + { + } + else if( nFormat == FORMAT_BITMAP || + nFormat == FORMAT_GDIMETAFILE ) + { + } +} +*/ + +void SbStdClipboard::MethClear( SbxVariable*, SbxArray* pPar_, BOOL ) +{ + if( pPar_ && (pPar_->Count() > 1) ) + { + StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS ); + return; + } + + //Clipboard::Clear(); +} + +void SbStdClipboard::MethGetData( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + (void)pVar; + + if( !pPar_ || (pPar_->Count() != 2) ) + { + StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS ); + return; + } + + USHORT nFormat = pPar_->Get(1)->GetInteger(); + if( !nFormat || nFormat > 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + /* + if( nFormat == FORMAT_STRING ) + pVar->PutString( Clipboard::PasteString() ); + else + if( (nFormat == FORMAT_BITMAP) || + (nFormat == FORMAT_GDIMETAFILE ) ) + { + SbxObjectRef xPic = new SbStdPicture; + Graphic aGraph; + aGraph.Paste(); + ((SbStdPicture*)(SbxObject*)xPic)->SetGraphic( aGraph ); + pVar->PutObject( xPic ); + } + */ +} + +void SbStdClipboard::MethGetFormat( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + if( !pPar_ || (pPar_->Count() != 2) ) + { + StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS ); + return; + } + + USHORT nFormat = pPar_->Get(1)->GetInteger(); + if( !nFormat || nFormat > 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + pVar->PutBool( FALSE ); + //pVar->PutBool( Clipboard::HasFormat( nFormat ) ); +} + +void SbStdClipboard::MethGetText( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + if( pPar_ && (pPar_->Count() > 1) ) + { + StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS ); + return; + } + + pVar->PutString( String() ); + //pVar->PutString( Clipboard::PasteString() ); +} + +void SbStdClipboard::MethSetData( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + (void)pVar; + + if( !pPar_ || (pPar_->Count() != 3) ) + { + StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS ); + return; + } + + USHORT nFormat = pPar_->Get(2)->GetInteger(); + if( !nFormat || nFormat > 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + /* + if( nFormat == FORMAT_STRING ) + { + Clipboard::CopyString( pPar_->Get(1)->GetString() ); + } + else + if( (nFormat == FORMAT_BITMAP) || + (nFormat == FORMAT_GDIMETAFILE) ) + { + SbxObject* pObj = (SbxObject*)pPar_->Get(1)->GetObject(); + + if( pObj && pObj->IsA( TYPE( SbStdPicture ) ) ) + ((SbStdPicture*)(SbxObject*)pObj)->GetGraphic().Copy(); + } + */ +} + +void SbStdClipboard::MethSetText( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + (void)pVar; + + if( !pPar_ || (pPar_->Count() != 2) ) + { + StarBASIC::Error( SbERR_BAD_NUMBER_OF_ARGS ); + return; + } + + // Clipboard::CopyString( pPar_->Get(1)->GetString() ); +} + + +TYPEINIT1( SbStdClipboard, SbxObject ); + +SbStdClipboard::SbStdClipboard() : + SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("Clipboard") ) ) +{ + // Name Property selbst verarbeiten + SbxVariable* p = Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY ); + DBG_ASSERT( p, "Keine Name Property" ); + p->SetUserData( ATTR_IMP_NAME ); + + //Methoden registrieren + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("Clear") ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p->SetUserData( METH_CLEAR ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("GetData") ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p->SetUserData( METH_GETDATA ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("GetFormat") ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p->SetUserData( METH_GETFORMAT ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("GetText") ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p->SetUserData( METH_GETTEXT ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("SetData") ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p->SetUserData( METH_SETDATA ); + p = Make( String( RTL_CONSTASCII_USTRINGPARAM("SetText") ), SbxCLASS_METHOD, SbxEMPTY ); + p->SetFlag( SBX_DONTSTORE ); + p->SetUserData( METH_SETTEXT ); +} + +SbStdClipboard::~SbStdClipboard() +{ +} + + +SbxVariable* SbStdClipboard::Find( const String& rName, SbxClassType t ) +{ + // Bereits eingetragen? + return SbxObject::Find( rName, t ); +} + + + +void SbStdClipboard::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST( SbxHint, &rHint ); + + if( pHint ) + { + if( pHint->GetId() == SBX_HINT_INFOWANTED ) + { + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + return; + } + + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pPar_ = pVar->GetParameters(); + USHORT nWhich = (USHORT)pVar->GetUserData(); + BOOL bWrite = pHint->GetId() == SBX_HINT_DATACHANGED; + + // Methods + switch( nWhich ) + { + case METH_CLEAR: MethClear( pVar, pPar_, bWrite ); return; + case METH_GETDATA: MethGetData( pVar, pPar_, bWrite ); return; + case METH_GETFORMAT: MethGetFormat( pVar, pPar_, bWrite ); return; + case METH_GETTEXT: MethGetText( pVar, pPar_, bWrite ); return; + case METH_SETDATA: MethSetData( pVar, pPar_, bWrite ); return; + case METH_SETTEXT: MethSetText( pVar, pPar_, bWrite ); return; + } + + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + + diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx new file mode 100644 index 000000000000..6ef6db23798c --- /dev/null +++ b/basic/source/runtime/step0.cxx @@ -0,0 +1,1273 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: step0.cxx,v $ + * $Revision: 1.32 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <vcl/msgbox.hxx> +#include <tools/fsys.hxx> + +#include "runtime.hxx" +#include "sbintern.hxx" +#include "iosys.hxx" +#include <sb.hrc> +#include <basrid.hxx> +#include "sbunoobj.hxx" +#include "image.hxx" +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/util/SearchOptions.hdl> +#include <vcl/svapp.hxx> +#include <unotools/textsearch.hxx> + +#include <algorithm> + +SbxVariable* getDefaultProp( SbxVariable* pRef ); + +void SbiRuntime::StepNOP() +{} + +void SbiRuntime::StepArith( SbxOperator eOp ) +{ + SbxVariableRef p1 = PopVar(); + TOSMakeTemp(); + SbxVariable* p2 = GetTOS(); + + + // This could & should be moved to the MakeTempTOS() method in runtime.cxx + // In the code which this is cut'npaste from there is a check for a ref + // count != 1 based on which the copy of the SbxVariable is done. + // see orig code in MakeTempTOS ( and I'm not sure what the significance, + // of that is ) + // here we alway seem to have a refcount of 1. Also it seems that + // MakeTempTOS is called for other operation, so I hold off for now + // until I have a better idea + if ( bVBAEnabled + && ( p2->GetType() == SbxOBJECT || p2->GetType() == SbxVARIANT ) + ) + { + SbxVariable* pDflt = getDefaultProp( p2 ); + if ( pDflt ) + { + pDflt->Broadcast( SBX_HINT_DATAWANTED ); + // replacing new p2 on stack causes object pointed by + // pDft->pParent to be deleted, when p2->Compute() is + // called below pParent is accessed ( but its deleted ) + // so set it to NULL now + pDflt->SetParent( NULL ); + p2 = new SbxVariable( *pDflt ); + p2->SetFlag( SBX_READWRITE ); + refExprStk->Put( p2, nExprLvl - 1 ); + } + } + + p2->ResetFlag( SBX_FIXED ); + p2->Compute( eOp, *p1 ); + + checkArithmeticOverflow( p2 ); +} + +void SbiRuntime::StepUnary( SbxOperator eOp ) +{ + TOSMakeTemp(); + SbxVariable* p = GetTOS(); + p->Compute( eOp, *p ); +} + +void SbiRuntime::StepCompare( SbxOperator eOp ) +{ + SbxVariableRef p1 = PopVar(); + SbxVariableRef p2 = PopVar(); + + // Make sure objects with default params have + // values ( and type ) set as appropriate + SbxDataType p1Type = p1->GetType(); + SbxDataType p2Type = p2->GetType(); + if ( p1Type == p2Type ) + { + if ( p1Type == SbxEMPTY ) + { + p1->Broadcast( SBX_HINT_DATAWANTED ); + p2->Broadcast( SBX_HINT_DATAWANTED ); + } + // if both sides are an object and have default props + // then we need to use the default props + // we don't need to worry if only one side ( lhs, rhs ) is an + // object ( object side will get coerced to correct type in + // Compare ) + else if ( p1Type == SbxOBJECT ) + { + SbxVariable* pDflt = getDefaultProp( p1 ); + if ( pDflt ) + { + p1 = pDflt; + p1->Broadcast( SBX_HINT_DATAWANTED ); + } + pDflt = getDefaultProp( p2 ); + if ( pDflt ) + { + p2 = pDflt; + p2->Broadcast( SBX_HINT_DATAWANTED ); + } + } + + } +#ifndef WIN + static SbxVariable* pTRUE = NULL; + static SbxVariable* pFALSE = NULL; + + if( p2->Compare( eOp, *p1 ) ) + { + if( !pTRUE ) + { + pTRUE = new SbxVariable; + pTRUE->PutBool( TRUE ); + pTRUE->AddRef(); + } + PushVar( pTRUE ); + } + else + { + if( !pFALSE ) + { + pFALSE = new SbxVariable; + pFALSE->PutBool( FALSE ); + pFALSE->AddRef(); + } + PushVar( pFALSE ); + } +#else + BOOL bRes = p2->Compare( eOp, *p1 ); + SbxVariable* pRes = new SbxVariable; + pRes->PutBool( bRes ); + PushVar( pRes ); +#endif +} + +void SbiRuntime::StepEXP() { StepArith( SbxEXP ); } +void SbiRuntime::StepMUL() { StepArith( SbxMUL ); } +void SbiRuntime::StepDIV() { StepArith( SbxDIV ); } +void SbiRuntime::StepIDIV() { StepArith( SbxIDIV ); } +void SbiRuntime::StepMOD() { StepArith( SbxMOD ); } +void SbiRuntime::StepPLUS() { StepArith( SbxPLUS ); } +void SbiRuntime::StepMINUS() { StepArith( SbxMINUS ); } +void SbiRuntime::StepCAT() { StepArith( SbxCAT ); } +void SbiRuntime::StepAND() { StepArith( SbxAND ); } +void SbiRuntime::StepOR() { StepArith( SbxOR ); } +void SbiRuntime::StepXOR() { StepArith( SbxXOR ); } +void SbiRuntime::StepEQV() { StepArith( SbxEQV ); } +void SbiRuntime::StepIMP() { StepArith( SbxIMP ); } + +void SbiRuntime::StepNEG() { StepUnary( SbxNEG ); } +void SbiRuntime::StepNOT() { StepUnary( SbxNOT ); } + +void SbiRuntime::StepEQ() { StepCompare( SbxEQ ); } +void SbiRuntime::StepNE() { StepCompare( SbxNE ); } +void SbiRuntime::StepLT() { StepCompare( SbxLT ); } +void SbiRuntime::StepGT() { StepCompare( SbxGT ); } +void SbiRuntime::StepLE() { StepCompare( SbxLE ); } +void SbiRuntime::StepGE() { StepCompare( SbxGE ); } + +namespace +{ + bool NeedEsc(sal_Unicode cCode) + { + String sEsc(RTL_CONSTASCII_USTRINGPARAM(".^$+\\|{}()")); + return (STRING_NOTFOUND != sEsc.Search(cCode)); + } + + String VBALikeToRegexp(const String &rIn) + { + String sResult; + const sal_Unicode *start = rIn.GetBuffer(); + const sal_Unicode *end = start + rIn.Len(); + + int seenright = 0; + + sResult.Append('^'); + + while (start < end) + { + switch (*start) + { + case '?': + sResult.Append('.'); + start++; + break; + case '*': + sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM(".*"))); + start++; + break; + case '#': + sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM("[0-9]"))); + start++; + break; + case ']': + sResult.Append('\\'); + sResult.Append(*start++); + break; + case '[': + sResult.Append(*start++); + seenright = 0; + while (start < end && !seenright) + { + switch (*start) + { + case '[': + case '?': + case '*': + sResult.Append('\\'); + sResult.Append(*start); + break; + case ']': + sResult.Append(*start); + seenright = 1; + break; + case '!': + sResult.Append('^'); + break; + default: + if (NeedEsc(*start)) + sResult.Append('\\'); + sResult.Append(*start); + break; + } + start++; + } + break; + default: + if (NeedEsc(*start)) + sResult.Append('\\'); + sResult.Append(*start++); + } + } + + sResult.Append('$'); + + return sResult; + } +} + +void SbiRuntime::StepLIKE() +{ + SbxVariableRef refVar1 = PopVar(); + SbxVariableRef refVar2 = PopVar(); + + String pattern = VBALikeToRegexp(refVar1->GetString()); + String value = refVar2->GetString(); + + com::sun::star::util::SearchOptions aSearchOpt; + + aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP; + + aSearchOpt.Locale = Application::GetSettings().GetLocale(); + aSearchOpt.searchString = pattern; + + int bTextMode(1); + bool bCompatibility = ( pINST && pINST->IsCompatibility() ); + if( bCompatibility ) + bTextMode = GetImageFlag( SBIMG_COMPARETEXT ); + + if( bTextMode ) + aSearchOpt.transliterateFlags |= com::sun::star::i18n::TransliterationModules_IGNORE_CASE; + + SbxVariable* pRes = new SbxVariable; + utl::TextSearch aSearch(aSearchOpt); + xub_StrLen nStart=0, nEnd=value.Len(); + int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd); + pRes->PutBool( bRes != 0 ); + + PushVar( pRes ); +} + +// TOS und TOS-1 sind beides Objektvariable und enthalten den selben Pointer + +void SbiRuntime::StepIS() +{ + SbxVariableRef refVar1 = PopVar(); + SbxVariableRef refVar2 = PopVar(); + BOOL bRes = BOOL( + refVar1->GetType() == SbxOBJECT + && refVar2->GetType() == SbxOBJECT ); + if ( bVBAEnabled && !bRes ) + Error( SbERR_INVALID_USAGE_OBJECT ); + bRes = ( bRes && refVar1->GetObject() == refVar2->GetObject() ); + SbxVariable* pRes = new SbxVariable; + pRes->PutBool( bRes ); + PushVar( pRes ); +} + +// Aktualisieren des Wertes von TOS + +void SbiRuntime::StepGET() +{ + SbxVariable* p = GetTOS(); + p->Broadcast( SBX_HINT_DATAWANTED ); +} + +// #67607 Uno-Structs kopieren +inline void checkUnoStructCopy( SbxVariableRef& refVal, SbxVariableRef& refVar ) +{ + SbxDataType eVarType = refVar->GetType(); + if( eVarType != SbxOBJECT ) + return; + + SbxObjectRef xValObj = (SbxObject*)refVal->GetObject(); + if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) ) + return; + + // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure + if( refVar->ISA(SbProcedureProperty) ) + return; + + SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject(); + SbxDataType eValType = refVal->GetType(); + if( eValType == SbxOBJECT && xVarObj == xValObj ) + { + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)xVarObj); + if( pUnoObj ) + { + Any aAny = pUnoObj->getUnoAny(); + if( aAny.getValueType().getTypeClass() == TypeClass_STRUCT ) + { + SbUnoObject* pNewUnoObj = new SbUnoObject( pUnoObj->GetName(), aAny ); + // #70324: ClassName uebernehmen + pNewUnoObj->SetClassName( pUnoObj->GetClassName() ); + refVar->PutObject( pNewUnoObj ); + } + } + } +} + + +// Ablage von TOS in TOS-1 + +void SbiRuntime::StepPUT() +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + // Store auf die eigene Methode (innerhalb einer Function)? + BOOL bFlagsChanged = FALSE; + USHORT n = 0; + if( (SbxVariable*) refVar == (SbxVariable*) pMeth ) + { + bFlagsChanged = TRUE; + n = refVar->GetFlags(); + refVar->SetFlag( SBX_WRITE ); + } + + // if left side arg is an object or variant and right handside isn't + // either an object or a variant then try and see if a default + // property exists. + // to use e.g. Range{"A1") = 34 + // could equate to Range("A1").Value = 34 + if ( bVBAEnabled ) + { + if ( refVar->GetType() == SbxOBJECT ) + { + SbxVariable* pDflt = getDefaultProp( refVar ); + if ( pDflt ) + refVar = pDflt; + } + if ( refVal->GetType() == SbxOBJECT ) + { + SbxVariable* pDflt = getDefaultProp( refVal ); + if ( pDflt ) + refVal = pDflt; + } + } + + *refVar = *refVal; + // lhs is a property who's value is currently null + if ( !bVBAEnabled || ( bVBAEnabled && refVar->GetType() != SbxEMPTY ) ) + // #67607 Uno-Structs kopieren + checkUnoStructCopy( refVal, refVar ); + if( bFlagsChanged ) + refVar->SetFlags( n ); +} + + +// Speichern Objektvariable +// Nicht-Objekt-Variable fuehren zu Fehlern + +void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp ) +{ + // #67733 Typen mit Array-Flag sind auch ok + SbxDataType eValType = refVal->GetType(); + SbxDataType eVarType = refVar->GetType(); + if( (eValType != SbxOBJECT + && eValType != SbxEMPTY +// seems like when using the default method its possible for objects +// to be empty ( no broadcast has taken place yet ) or the actual value is + + && !bHandleDefaultProp + && !(eValType & SbxARRAY)) || + (eVarType != SbxOBJECT + && eVarType != SbxEMPTY + && !bHandleDefaultProp + && !(eVarType & SbxARRAY) ) ) + { + Error( SbERR_INVALID_USAGE_OBJECT ); + } + else + { + // Getting in here causes problems with objects with default properties + // if they are SbxEMPTY I guess + if ( !bHandleDefaultProp || ( bHandleDefaultProp && refVal->GetType() == SbxOBJECT ) ) + { + // Auf refVal GetObject fuer Collections ausloesen + SbxBase* pObjVarObj = refVal->GetObject(); + if( pObjVarObj ) + { + SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj); + + // #67733 Typen mit Array-Flag sind auch ok + if( refObjVal ) + refVal = refObjVal; + else if( !(eValType & SbxARRAY) ) + refVal = NULL; + } + } + + // #52896 Wenn Uno-Sequences bzw. allgemein Arrays einer als + // Object deklarierten Variable zugewiesen werden, kann hier + // refVal ungueltig sein! + if( !refVal ) + { + Error( SbERR_INVALID_USAGE_OBJECT ); + } + else + { + // Store auf die eigene Methode (innerhalb einer Function)? + BOOL bFlagsChanged = FALSE; + USHORT n = 0; + if( (SbxVariable*) refVar == (SbxVariable*) pMeth ) + { + bFlagsChanged = TRUE; + n = refVar->GetFlags(); + refVar->SetFlag( SBX_WRITE ); + } + SbProcedureProperty* pProcProperty = PTR_CAST(SbProcedureProperty,(SbxVariable*)refVar); + if( pProcProperty ) + pProcProperty->setSet( true ); + + if ( bHandleDefaultProp ) + { + // get default properties for lhs & rhs where necessary + // SbxVariable* defaultProp = NULL; unused variable + bool bLHSHasDefaultProp = false; + // LHS try determine if a default prop exists + if ( refVar->GetType() == SbxOBJECT ) + { + SbxVariable* pDflt = getDefaultProp( refVar ); + if ( pDflt ) + { + refVar = pDflt; + bLHSHasDefaultProp = true; + } + } + // RHS only get a default prop is the rhs has one + if ( refVal->GetType() == SbxOBJECT ) + { + // check if lhs is a null object + // if it is then use the object not the default property + SbxObject* pObj = NULL; + + + pObj = PTR_CAST(SbxObject,(SbxVariable*)refVar); + + // calling GetObject on a SbxEMPTY variable raises + // object not set errors, make sure its an Object + if ( !pObj && refVar->GetType() == SbxOBJECT ) + { + SbxBase* pObjVarObj = refVar->GetObject(); + pObj = PTR_CAST(SbxObject,pObjVarObj); + } + SbxVariable* pDflt = NULL; + if ( pObj || bLHSHasDefaultProp ) + // lhs is either a valid object || or has a defaultProp + pDflt = getDefaultProp( refVal ); + if ( pDflt ) + refVal = pDflt; + } + } + + *refVar = *refVal; + + // lhs is a property who's value is currently (Empty e.g. no broadcast yet) + // in this case if there is a default prop involved the value of the + // default property may infact be void so the type will also be SbxEMPTY + // in this case we do not want to call checkUnoStructCopy 'cause that will + // cause an error also + if ( !bHandleDefaultProp || ( bHandleDefaultProp && ( refVar->GetType() != SbxEMPTY ) ) ) + // #67607 Uno-Structs kopieren + checkUnoStructCopy( refVal, refVar ); + if( bFlagsChanged ) + refVar->SetFlags( n ); + } + } +} + +void SbiRuntime::StepSET() +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + StepSET_Impl( refVal, refVar, bVBAEnabled ); // this is really assigment +} + +void SbiRuntime::StepVBASET() +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + // don't handle default property + StepSET_Impl( refVal, refVar, false ); // set obj = something +} + + +// JSM 07.10.95 +void SbiRuntime::StepLSET() +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + if( refVar->GetType() != SbxSTRING + || refVal->GetType() != SbxSTRING ) + Error( SbERR_INVALID_USAGE_OBJECT ); + else + { + // Store auf die eigene Methode (innerhalb einer Function)? + USHORT n = refVar->GetFlags(); + if( (SbxVariable*) refVar == (SbxVariable*) pMeth ) + refVar->SetFlag( SBX_WRITE ); + String aRefVarString = refVar->GetString(); + String aRefValString = refVal->GetString(); + + USHORT nVarStrLen = aRefVarString.Len(); + USHORT nValStrLen = aRefValString.Len(); + String aNewStr; + if( nVarStrLen > nValStrLen ) + { + aRefVarString.Fill(nVarStrLen,' '); + aNewStr = aRefValString.Copy( 0, nValStrLen ); + aNewStr += aRefVarString.Copy( nValStrLen, nVarStrLen - nValStrLen ); + } + else + { + aNewStr = aRefValString.Copy( 0, nVarStrLen ); + } + + refVar->PutString( aNewStr ); + refVar->SetFlags( n ); + } +} + +// JSM 07.10.95 +void SbiRuntime::StepRSET() +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + if( refVar->GetType() != SbxSTRING + || refVal->GetType() != SbxSTRING ) + Error( SbERR_INVALID_USAGE_OBJECT ); + else + { + // Store auf die eigene Methode (innerhalb einer Function)? + USHORT n = refVar->GetFlags(); + if( (SbxVariable*) refVar == (SbxVariable*) pMeth ) + refVar->SetFlag( SBX_WRITE ); + String aRefVarString = refVar->GetString(); + String aRefValString = refVal->GetString(); + + USHORT nPos = 0; + USHORT nVarStrLen = aRefVarString.Len(); + if( nVarStrLen > aRefValString.Len() ) + { + aRefVarString.Fill(nVarStrLen,' '); + nPos = nVarStrLen - aRefValString.Len(); + } + aRefVarString = aRefVarString.Copy( 0, nPos ); + aRefVarString += aRefValString.Copy( 0, nVarStrLen - nPos ); + refVar->PutString(aRefVarString); + + refVar->SetFlags( n ); + } +} + +// Ablage von TOS in TOS-1, dann ReadOnly-Bit setzen + +void SbiRuntime::StepPUTC() +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + refVar->SetFlag( SBX_WRITE ); + *refVar = *refVal; + refVar->ResetFlag( SBX_WRITE ); + refVar->SetFlag( SBX_CONST ); +} + +// DIM +// TOS = Variable fuer das Array mit Dimensionsangaben als Parameter + +void SbiRuntime::StepDIM() +{ + SbxVariableRef refVar = PopVar(); + DimImpl( refVar ); +} + +// #56204 DIM-Funktionalitaet in Hilfsmethode auslagern (step0.cxx) +void SbiRuntime::DimImpl( SbxVariableRef refVar ) +{ + SbxArray* pDims = refVar->GetParameters(); + // Muss eine gerade Anzahl Argumente haben + // Man denke daran, dass Arg[0] nicht zaehlt! + if( pDims && !( pDims->Count() & 1 ) ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + { + SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT; + SbxDimArray* pArray = new SbxDimArray( eType ); + // AB 2.4.1996, auch Arrays ohne Dimensionsangaben zulassen (VB-komp.) + if( pDims ) + { + for( USHORT i = 1; i < pDims->Count(); ) + { + INT32 lb = pDims->Get( i++ )->GetLong(); + INT32 ub = pDims->Get( i++ )->GetLong(); + if( ub < lb ) + Error( SbERR_OUT_OF_RANGE ), ub = lb; + pArray->AddDim32( lb, ub ); + if ( lb != ub ) + pArray->setHasFixedSize( true ); + } + } + else + { + // #62867 Beim Anlegen eines Arrays der Laenge 0 wie bei + // Uno-Sequences der Laenge 0 eine Dimension anlegen + pArray->unoAddDim( 0, -1 ); + } + USHORT nSavFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->PutObject( pArray ); + refVar->SetFlags( nSavFlags ); + refVar->SetParameters( NULL ); + } +} + +// REDIM +// TOS = Variable fuer das Array +// argv = Dimensionsangaben + +void SbiRuntime::StepREDIM() +{ + // Im Moment ist es nichts anderes als Dim, da doppeltes Dim + // bereits vom Compiler erkannt wird. + StepDIM(); +} + + +// Helper function for StepREDIMP +void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex, + short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) +{ + sal_Int32& ri = pActualIndices[nActualDim]; + for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ ) + { + if( nActualDim < nMaxDimIndex ) + { + implCopyDimArray( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1, + pActualIndices, pLowerBounds, pUpperBounds ); + } + else + { + SbxVariable* pSource = pOldArray->Get32( pActualIndices ); + SbxVariable* pDest = pNewArray->Get32( pActualIndices ); + if( pSource && pDest ) + *pDest = *pSource; + } + } +} + +// REDIM PRESERVE +// TOS = Variable fuer das Array +// argv = Dimensionsangaben + +void SbiRuntime::StepREDIMP() +{ + SbxVariableRef refVar = PopVar(); + DimImpl( refVar ); + + // Now check, if we can copy from the old array + if( refRedimpArray.Is() ) + { + SbxBase* pElemObj = refVar->GetObject(); + SbxDimArray* pNewArray = PTR_CAST(SbxDimArray,pElemObj); + SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray; + if( pNewArray ) + { + short nDimsNew = pNewArray->GetDims(); + short nDimsOld = pOldArray->GetDims(); + short nDims = nDimsNew; + BOOL bRangeError = FALSE; + + // Store dims to use them for copying later + sal_Int32* pLowerBounds = new sal_Int32[nDims]; + sal_Int32* pUpperBounds = new sal_Int32[nDims]; + sal_Int32* pActualIndices = new sal_Int32[nDims]; + + if( nDimsOld != nDimsNew ) + { + bRangeError = TRUE; + } + else + { + // Compare bounds + for( short i = 1 ; i <= nDims ; i++ ) + { + sal_Int32 lBoundNew, uBoundNew; + sal_Int32 lBoundOld, uBoundOld; + pNewArray->GetDim32( i, lBoundNew, uBoundNew ); + pOldArray->GetDim32( i, lBoundOld, uBoundOld ); + + /* #69094 Allow all dimensions to be changed + although Visual Basic is not able to do so. + // All bounds but the last have to be the same + if( i < nDims && ( lBoundNew != lBoundOld || uBoundNew != uBoundOld ) ) + { + bRangeError = TRUE; + break; + } + else + */ + { + // #69094: if( i == nDims ) + { + lBoundNew = std::max( lBoundNew, lBoundOld ); + uBoundNew = std::min( uBoundNew, uBoundOld ); + } + short j = i - 1; + pActualIndices[j] = pLowerBounds[j] = lBoundNew; + pUpperBounds[j] = uBoundNew; + } + } + } + + if( bRangeError ) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + else + { + // Copy data from old array by going recursively through all dimensions + // (It would be faster to work on the flat internal data array of an + // SbyArray but this solution is clearer and easier) + implCopyDimArray( pNewArray, pOldArray, nDims - 1, + 0, pActualIndices, pLowerBounds, pUpperBounds ); + } + + delete[] pUpperBounds; + delete[] pLowerBounds; + delete[] pActualIndices; + refRedimpArray = NULL; + } + } + + //StarBASIC::FatalError( SbERR_NOT_IMPLEMENTED ); +} + +// REDIM_COPY +// TOS = Array-Variable, Reference to array is copied +// Variable is cleared as in ERASE + +void SbiRuntime::StepREDIMP_ERASE() +{ + SbxVariableRef refVar = PopVar(); + SbxDataType eType = refVar->GetType(); + if( eType & SbxARRAY ) + { + SbxBase* pElemObj = refVar->GetObject(); + SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj); + if( pDimArray ) + { + refRedimpArray = pDimArray; + } + + // As in ERASE + USHORT nSavFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->SetType( SbxDataType(eType & 0x0FFF) ); + refVar->SetFlags( nSavFlags ); + refVar->Clear(); + } + else + if( refVar->IsFixed() ) + refVar->Clear(); + else + refVar->SetType( SbxEMPTY ); +} + +void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType ) +{ + USHORT nSavFlags = refVar->GetFlags(); + refVar->ResetFlag( SBX_FIXED ); + refVar->SetType( SbxDataType(eType & 0x0FFF) ); + refVar->SetFlags( nSavFlags ); + refVar->Clear(); +} + +void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled ) +{ + SbxDataType eType = refVar->GetType(); + if( eType & SbxARRAY ) + { + if ( bVBAEnabled ) + { + SbxBase* pElemObj = refVar->GetObject(); + SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj); + bool bClearValues = true; + if( pDimArray ) + { + if ( pDimArray->hasFixedSize() ) + { + // Clear all Value(s) + pDimArray->SbxArray::Clear(); + bClearValues = false; + } + else + pDimArray->Clear(); // clear Dims + } + if ( bClearValues ) + { + SbxArray* pArray = PTR_CAST(SbxArray,pElemObj); + if ( pArray ) + pArray->Clear(); + } + } + else + // AB 2.4.1996 + // Arrays haben bei Erase nach VB ein recht komplexes Verhalten. Hier + // werden zunaechst nur die Typ-Probleme bei REDIM (#26295) beseitigt: + // Typ hart auf den Array-Typ setzen, da eine Variable mit Array + // SbxOBJECT ist. Bei REDIM entsteht dann ein SbxOBJECT-Array und + // der ursruengliche Typ geht verloren -> Laufzeitfehler + lcl_clearImpl( refVar, eType ); + } + else + if( refVar->IsFixed() ) + refVar->Clear(); + else + refVar->SetType( SbxEMPTY ); +} + +// Variable loeschen +// TOS = Variable + +void SbiRuntime::StepERASE() +{ + SbxVariableRef refVar = PopVar(); + lcl_eraseImpl( refVar, bVBAEnabled ); +} + +void SbiRuntime::StepERASE_CLEAR() +{ + SbxVariableRef refVar = PopVar(); + lcl_eraseImpl( refVar, bVBAEnabled ); + SbxDataType eType = refVar->GetType(); + lcl_clearImpl( refVar, eType ); +} + +void SbiRuntime::StepARRAYACCESS() +{ + if( !refArgv ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + SbxVariableRef refVar = PopVar(); + refVar->SetParameters( refArgv ); + PopArgv(); + PushVar( CheckArray( refVar ) ); +} + +// Einrichten eines Argvs +// nOp1 bleibt so -> 1. Element ist Returnwert + +void SbiRuntime::StepARGC() +{ + PushArgv(); + refArgv = new SbxArray; + nArgc = 1; +} + +// Speichern eines Arguments in Argv + +void SbiRuntime::StepARGV() +{ + if( !refArgv ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + { + SbxVariableRef pVal = PopVar(); + + // Before fix of #94916: + // if( pVal->ISA(SbxMethod) || pVal->ISA(SbxProperty) ) + if( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) ) + { + // Methoden und Properties evaluieren! + SbxVariable* pRes = new SbxVariable( *pVal ); + pVal = pRes; + } + refArgv->Put( pVal, nArgc++ ); + } +} + +// Input to Variable. Die Variable ist auf TOS und wird +// anschliessend entfernt. + +void SbiRuntime::StepINPUT() +{ + String s; + char ch = 0; + SbError err; + // Skip whitespace + while( ( err = pIosys->GetError() ) == 0 ) + { + ch = pIosys->Read(); + if( ch != ' ' && ch != '\t' && ch != '\n' ) + break; + } + if( !err ) + { + // Scan until comma or whitespace + char sep = ( ch == '"' ) ? ch : 0; + if( sep ) ch = pIosys->Read(); + while( ( err = pIosys->GetError() ) == 0 ) + { + if( ch == sep ) + { + ch = pIosys->Read(); + if( ch != sep ) + break; + } + else if( !sep && (ch == ',' || ch == '\n') ) + break; + s += ch; + ch = pIosys->Read(); + } + // skip whitespace + if( ch == ' ' || ch == '\t' ) + while( ( err = pIosys->GetError() ) == 0 ) + { + if( ch != ' ' && ch != '\t' && ch != '\n' ) + break; + ch = pIosys->Read(); + } + } + if( !err ) + { + SbxVariableRef pVar = GetTOS(); + // Zuerst versuchen, die Variable mit einem numerischen Wert + // zu fuellen, dann mit einem Stringwert + if( !pVar->IsFixed() || pVar->IsNumeric() ) + { + USHORT nLen = 0; + if( !pVar->Scan( s, &nLen ) ) + { + err = SbxBase::GetError(); + SbxBase::ResetError(); + } + // Der Wert muss komplett eingescant werden + else if( nLen != s.Len() && !pVar->PutString( s ) ) + { + err = SbxBase::GetError(); + SbxBase::ResetError(); + } + else if( nLen != s.Len() && pVar->IsNumeric() ) + { + err = SbxBase::GetError(); + SbxBase::ResetError(); + if( !err ) + err = SbERR_CONVERSION; + } + } + else + { + pVar->PutString( s ); + err = SbxBase::GetError(); + SbxBase::ResetError(); + } + } + if( err == SbERR_USER_ABORT ) + Error( err ); + else if( err ) + { + if( pRestart && !pIosys->GetChannel() ) + { + BasResId aId( IDS_SBERR_START + 4 ); + String aMsg( aId ); + + //****** DONT CHECK IN, TEST ONLY ******* + //****** DONT CHECK IN, TEST ONLY ******* + // ErrorBox( NULL, WB_OK, aMsg ).Execute(); + //****** DONT CHECK IN, TEST ONLY ******* + //****** DONT CHECK IN, TEST ONLY ******* + + pCode = pRestart; + } + else + Error( err ); + } + else + { + // pIosys->ResetChannel(); + PopVar(); + } +} + +// Line Input to Variable. Die Variable ist auf TOS und wird +// anschliessend entfernt. + +void SbiRuntime::StepLINPUT() +{ + ByteString aInput; + pIosys->Read( aInput ); + Error( pIosys->GetError() ); + SbxVariableRef p = PopVar(); + p->PutString( String( aInput, gsl_getSystemTextEncoding() ) ); + // pIosys->ResetChannel(); +} + +// Programmende + +void SbiRuntime::StepSTOP() +{ + pInst->Stop(); +} + +// FOR-Variable initialisieren + +void SbiRuntime::StepINITFOR() +{ + PushFor(); +} + +void SbiRuntime::StepINITFOREACH() +{ + PushForEach(); +} + +// FOR-Variable inkrementieren + +void SbiRuntime::StepNEXT() +{ + if( !pForStk ) + { + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + return; + } + if( pForStk->eForType == FOR_TO ) + pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc ); +} + +// Anfang CASE: TOS in CASE-Stack + +void SbiRuntime::StepCASE() +{ + if( !refCaseStk.Is() ) + refCaseStk = new SbxArray; + SbxVariableRef xVar = PopVar(); + refCaseStk->Put( xVar, refCaseStk->Count() ); +} + +// Ende CASE: Variable freigeben + +void SbiRuntime::StepENDCASE() +{ + if( !refCaseStk || !refCaseStk->Count() ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + refCaseStk->Remove( refCaseStk->Count() - 1 ); +} + +// Standard-Fehlerbehandlung + +void SbiRuntime::StepSTDERROR() +{ + pError = NULL; bError = TRUE; + pInst->aErrorMsg = String(); + pInst->nErr = 0L; + pInst->nErl = 0; + nError = 0L; +} + +void SbiRuntime::StepNOERROR() +{ + pInst->aErrorMsg = String(); + pInst->nErr = 0L; + pInst->nErl = 0; + nError = 0L; + bError = FALSE; +} + +// UP verlassen + +void SbiRuntime::StepLEAVE() +{ + bRun = FALSE; +} + +void SbiRuntime::StepCHANNEL() // TOS = Kanalnummer +{ + SbxVariableRef pChan = PopVar(); + short nChan = pChan->GetInteger(); + pIosys->SetChannel( nChan ); + Error( pIosys->GetError() ); +} + +void SbiRuntime::StepCHANNEL0() +{ + pIosys->ResetChannel(); +} + +void SbiRuntime::StepPRINT() // print TOS +{ + SbxVariableRef p = PopVar(); + String s1 = p->GetString(); + String s; + if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE ) + s = ' '; // ein Blank davor + s += s1; + ByteString aByteStr( s, gsl_getSystemTextEncoding() ); + pIosys->Write( aByteStr ); + Error( pIosys->GetError() ); +} + +void SbiRuntime::StepPRINTF() // print TOS in field +{ + SbxVariableRef p = PopVar(); + String s1 = p->GetString(); + String s; + if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE ) + s = ' '; // ein Blank davor + s += s1; + s.Expand( 14, ' ' ); + ByteString aByteStr( s, gsl_getSystemTextEncoding() ); + pIosys->Write( aByteStr ); + Error( pIosys->GetError() ); +} + +void SbiRuntime::StepWRITE() // write TOS +{ + SbxVariableRef p = PopVar(); + // Muss der String gekapselt werden? + char ch = 0; + switch (p->GetType() ) + { + case SbxSTRING: ch = '"'; break; + case SbxCURRENCY: + case SbxBOOL: + case SbxDATE: ch = '#'; break; + default: break; + } + String s; + if( ch ) + s += ch; + s += p->GetString(); + if( ch ) + s += ch; + ByteString aByteStr( s, gsl_getSystemTextEncoding() ); + pIosys->Write( aByteStr ); + Error( pIosys->GetError() ); +} + +void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos +{ + SbxVariableRef pTos1 = PopVar(); + SbxVariableRef pTos = PopVar(); + String aDest = pTos1->GetString(); + String aSource = pTos->GetString(); + + // <-- UCB + if( hasUno() ) + { + implStepRenameUCB( aSource, aDest ); + } + else + // --> UCB + { +#ifdef _OLD_FILE_IMPL + DirEntry aSourceDirEntry( aSource ); + if( aSourceDirEntry.Exists() ) + { + if( aSourceDirEntry.MoveTo( DirEntry(aDest) ) != FSYS_ERR_OK ) + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); + } + else + StarBASIC::Error( SbERR_PATH_NOT_FOUND ); +#else + implStepRenameOSL( aSource, aDest ); +#endif + } +} + +// TOS = Prompt + +void SbiRuntime::StepPROMPT() +{ + SbxVariableRef p = PopVar(); + ByteString aStr( p->GetString(), gsl_getSystemTextEncoding() ); + pIosys->SetPrompt( aStr ); +} + +// Set Restart point + +void SbiRuntime::StepRESTART() +{ + pRestart = pCode; +} + +// Leerer Ausdruck auf Stack fuer fehlenden Parameter + +void SbiRuntime::StepEMPTY() +{ + // #57915 Die Semantik von StepEMPTY() ist die Repraesentation eines fehlenden + // Arguments. Dies wird in VB durch ein durch den Wert 448 (SbERR_NAMED_NOT_FOUND) + // vom Typ Error repraesentiert. StepEmpty jetzt muesste besser StepMISSING() + // heissen, aber der Name wird der Einfachkeit halber beibehalten. + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + xVar->PutErr( 448 ); + PushVar( xVar ); + // ALT: PushVar( new SbxVariable( SbxEMPTY ) ); +} + +// TOS = Fehlercode + +void SbiRuntime::StepERROR() +{ + SbxVariableRef refCode = PopVar(); + USHORT n = refCode->GetUShort(); + SbError error = StarBASIC::GetSfxFromVBError( n ); + Error( error ); +} + diff --git a/basic/source/runtime/step1.cxx b/basic/source/runtime/step1.cxx new file mode 100644 index 000000000000..938e5f6ad236 --- /dev/null +++ b/basic/source/runtime/step1.cxx @@ -0,0 +1,571 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: step1.cxx,v $ + * $Revision: 1.18 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdlib.h> +#include <rtl/math.hxx> +#include "runtime.hxx" +#include "sbintern.hxx" +#include "iosys.hxx" +#include "image.hxx" +#include "sbunoobj.hxx" + +bool checkUnoObjectType( SbUnoObject* refVal, + const String& aClass ); + +// Laden einer numerischen Konstanten (+ID) + +void SbiRuntime::StepLOADNC( UINT32 nOp1 ) +{ + SbxVariable* p = new SbxVariable( SbxDOUBLE ); + + // #57844 Lokalisierte Funktion benutzen + String aStr = pImg->GetString( static_cast<short>( nOp1 ) ); + // Auch , zulassen !!! + USHORT iComma = aStr.Search( ',' ); + if( iComma != STRING_NOTFOUND ) + { + String aStr1 = aStr.Copy( 0, iComma ); + String aStr2 = aStr.Copy( iComma + 1 ); + aStr = aStr1; + aStr += '.'; + aStr += aStr2; + } + double n = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL ); + + p->PutDouble( n ); + PushVar( p ); +} + +// Laden einer Stringkonstanten (+ID) + +void SbiRuntime::StepLOADSC( UINT32 nOp1 ) +{ + SbxVariable* p = new SbxVariable; + p->PutString( pImg->GetString( static_cast<short>( nOp1 ) ) ); + PushVar( p ); +} + +// Immediate Load (+Wert) + +void SbiRuntime::StepLOADI( UINT32 nOp1 ) +{ + SbxVariable* p = new SbxVariable; + p->PutInteger( static_cast<INT16>( nOp1 ) ); + PushVar( p ); +} + +// Speichern eines named Arguments in Argv (+Arg-Nr ab 1!) + +void SbiRuntime::StepARGN( UINT32 nOp1 ) +{ + if( !refArgv ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + { + String aAlias( pImg->GetString( static_cast<short>( nOp1 ) ) ); + SbxVariableRef pVal = PopVar(); + refArgv->Put( pVal, nArgc ); + refArgv->PutAlias( aAlias, nArgc++ ); + } +} + +// Konvertierung des Typs eines Arguments in Argv fuer DECLARE-Fkt. (+Typ) + +void SbiRuntime::StepARGTYP( UINT32 nOp1 ) +{ + if( !refArgv ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + { + BOOL bByVal = (nOp1 & 0x8000) != 0; // Ist BYVAL verlangt? + SbxDataType t = (SbxDataType) (nOp1 & 0x7FFF); + SbxVariable* pVar = refArgv->Get( refArgv->Count() - 1 ); // letztes Arg + + // BYVAL prüfen + if( pVar->GetRefCount() > 2 ) // 2 ist normal für BYVAL + { + // Parameter ist eine Referenz + if( bByVal ) + { + // Call by Value ist verlangt -> Kopie anlegen + pVar = new SbxVariable( *pVar ); + pVar->SetFlag( SBX_READWRITE ); + refExprStk->Put( pVar, refArgv->Count() - 1 ); + } + else + pVar->SetFlag( SBX_REFERENCE ); // Ref-Flag für DllMgr + } + else + { + // Parameter ist KEINE Referenz + if( bByVal ) + pVar->ResetFlag( SBX_REFERENCE ); // Keine Referenz -> OK + else + Error( SbERR_BAD_PARAMETERS ); // Referenz verlangt + } + + if( pVar->GetType() != t ) + { + // Variant, damit richtige Konvertierung + // Ausserdem Fehler, wenn SbxBYREF + pVar->Convert( SbxVARIANT ); + pVar->Convert( t ); + } + } +} + +// String auf feste Laenge bringen (+Laenge) + +void SbiRuntime::StepPAD( UINT32 nOp1 ) +{ + SbxVariable* p = GetTOS(); + String& s = (String&)(const String&) *p; + if( s.Len() > nOp1 ) + s.Erase( static_cast<xub_StrLen>( nOp1 ) ); + else + s.Expand( static_cast<xub_StrLen>( nOp1 ), ' ' ); +} + +// Sprung (+Target) + +void SbiRuntime::StepJUMP( UINT32 nOp1 ) +{ +#ifndef PRODUCT + // #QUESTION shouln't this be + // if( (BYTE*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() ) + if( nOp1 >= pImg->GetCodeSize() ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); +#endif + pCode = (const BYTE*) pImg->GetCode() + nOp1; +} + +// TOS auswerten, bedingter Sprung (+Target) + +void SbiRuntime::StepJUMPT( UINT32 nOp1 ) +{ + SbxVariableRef p = PopVar(); + if( p->GetBool() ) + StepJUMP( nOp1 ); +} + +// TOS auswerten, bedingter Sprung (+Target) + +void SbiRuntime::StepJUMPF( UINT32 nOp1 ) +{ + SbxVariableRef p = PopVar(); + if( !p->GetBool() ) + StepJUMP( nOp1 ); +} + +// TOS auswerten, Sprung in JUMP-Tabelle (+MaxVal) +// Sieht so aus: +// ONJUMP 2 +// JUMP target1 +// JUMP target2 +// ... +//Falls im Operanden 0x8000 gesetzt ist, Returnadresse pushen (ON..GOSUB) + +void SbiRuntime::StepONJUMP( UINT32 nOp1 ) +{ + SbxVariableRef p = PopVar(); + INT16 n = p->GetInteger(); + if( nOp1 & 0x8000 ) + { + nOp1 &= 0x7FFF; + //PushGosub( pCode + 3 * nOp1 ); + PushGosub( pCode + 5 * nOp1 ); + } + if( n < 1 || static_cast<UINT32>(n) > nOp1 ) + n = static_cast<INT16>( nOp1 + 1 ); + //nOp1 = (UINT32) ( (const char*) pCode - pImg->GetCode() ) + 3 * --n; + nOp1 = (UINT32) ( (const char*) pCode - pImg->GetCode() ) + 5 * --n; + StepJUMP( nOp1 ); +} + +// UP-Aufruf (+Target) + +void SbiRuntime::StepGOSUB( UINT32 nOp1 ) +{ + PushGosub( pCode ); + if( nOp1 >= pImg->GetCodeSize() ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + pCode = (const BYTE*) pImg->GetCode() + nOp1; +} + +// UP-Return (+0 oder Target) + +void SbiRuntime::StepRETURN( UINT32 nOp1 ) +{ + PopGosub(); + if( nOp1 ) + StepJUMP( nOp1 ); +} + +// FOR-Variable testen (+Endlabel) + +void unoToSbxValue( SbxVariable* pVar, const Any& aValue ); + +void SbiRuntime::StepTESTFOR( UINT32 nOp1 ) +{ + if( !pForStk ) + { + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + return; + } + + bool bEndLoop = false; + switch( pForStk->eForType ) + { + case FOR_TO: + { + SbxOperator eOp = ( pForStk->refInc->GetDouble() < 0 ) ? SbxLT : SbxGT; + if( pForStk->refVar->Compare( eOp, *pForStk->refEnd ) ) + bEndLoop = true; + break; + } + case FOR_EACH_ARRAY: + { + SbiForStack* p = pForStk; + if( p->pArrayCurIndices == NULL ) + { + bEndLoop = true; + } + else + { + SbxDimArray* pArray = (SbxDimArray*)(SbxVariable*)p->refEnd; + short nDims = pArray->GetDims(); + + // Empty array? + if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] ) + { + bEndLoop = true; + break; + } + SbxVariable* pVal = pArray->Get32( p->pArrayCurIndices ); + *(p->refVar) = *pVal; + + bool bFoundNext = false; + for( short i = 0 ; i < nDims ; i++ ) + { + if( p->pArrayCurIndices[i] < p->pArrayUpperBounds[i] ) + { + bFoundNext = true; + p->pArrayCurIndices[i]++; + for( short j = i - 1 ; j >= 0 ; j-- ) + p->pArrayCurIndices[j] = p->pArrayLowerBounds[j]; + break; + } + } + if( !bFoundNext ) + { + delete[] p->pArrayCurIndices; + p->pArrayCurIndices = NULL; + } + } + break; + } + case FOR_EACH_COLLECTION: + { + BasicCollection* pCollection = (BasicCollection*)(SbxVariable*)pForStk->refEnd; + SbxArrayRef xItemArray = pCollection->xItemArray; + INT32 nCount = xItemArray->Count32(); + if( pForStk->nCurCollectionIndex < nCount ) + { + SbxVariable* pRes = xItemArray->Get32( pForStk->nCurCollectionIndex ); + pForStk->nCurCollectionIndex++; + (*pForStk->refVar) = *pRes; + } + else + { + bEndLoop = true; + } + break; + } + case FOR_EACH_XENUMERATION: + { + SbiForStack* p = pForStk; + if( p->xEnumeration->hasMoreElements() ) + { + Any aElem = p->xEnumeration->nextElement(); + SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( (SbxVariable*)xVar, aElem ); + (*pForStk->refVar) = *xVar; + } + else + { + bEndLoop = true; + } + break; + } + } + if( bEndLoop ) + { + PopFor(); + StepJUMP( nOp1 ); + } +} + +// Tos+1 <= Tos+2 <= Tos, 2xremove (+Target) + +void SbiRuntime::StepCASETO( UINT32 nOp1 ) +{ + if( !refCaseStk || !refCaseStk->Count() ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + { + SbxVariableRef xTo = PopVar(); + SbxVariableRef xFrom = PopVar(); + SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 ); + if( *xCase >= *xFrom && *xCase <= *xTo ) + StepJUMP( nOp1 ); + } +} + +// Fehler-Handler + +void SbiRuntime::StepERRHDL( UINT32 nOp1 ) +{ + const BYTE* p = pCode; + StepJUMP( nOp1 ); + pError = pCode; + pCode = p; + pInst->aErrorMsg = String(); + pInst->nErr = 0; + pInst->nErl = 0; + nError = 0; +} + +// Resume nach Fehlern (+0=statement, 1=next or Label) + +void SbiRuntime::StepRESUME( UINT32 nOp1 ) +{ + // AB #32714 Resume ohne Error? -> Fehler + if( !bInError ) + { + Error( SbERR_BAD_RESUME ); + return; + } + if( nOp1 ) + { + // Code-Zeiger auf naechstes Statement setzen + USHORT n1, n2; + pCode = pMod->FindNextStmnt( pErrCode, n1, n2, TRUE, pImg ); + } + else + pCode = pErrStmnt; + + if( nOp1 > 1 ) + StepJUMP( nOp1 ); + pInst->aErrorMsg = String(); + pInst->nErr = 0; + pInst->nErl = 0; + nError = 0; + bInError = FALSE; + + // Error-Stack loeschen + SbErrorStack*& rErrStack = GetSbData()->pErrStack; + delete rErrStack; + rErrStack = NULL; +} + +// Kanal schliessen (+Kanal, 0=Alle) +void SbiRuntime::StepCLOSE( UINT32 nOp1 ) +{ + SbError err; + if( !nOp1 ) + pIosys->Shutdown(); + else + { + err = pIosys->GetError(); + if( !err ) + { + pIosys->Close(); + } + } + err = pIosys->GetError(); + Error( err ); +} + +// Zeichen ausgeben (+char) + +void SbiRuntime::StepPRCHAR( UINT32 nOp1 ) +{ + ByteString s( (char) nOp1 ); + pIosys->Write( s ); + Error( pIosys->GetError() ); +} + +// Check, ob TOS eine bestimmte Objektklasse ist (+StringID) + +bool SbiRuntime::implIsClass( SbxObject* pObj, const String& aClass ) +{ + bool bRet = true; + + if( aClass.Len() != 0 ) + { + bRet = pObj->IsClass( aClass ); + if( !bRet ) + bRet = aClass.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("object") ) ); + if( !bRet ) + { + String aObjClass = pObj->GetClassName(); + SbModule* pClassMod = pCLASSFAC->FindClass( aObjClass ); + SbClassData* pClassData; + if( pClassMod && (pClassData=pClassMod->pClassData) != NULL ) + { + SbxVariable* pClassVar = + pClassData->mxIfaces->Find( aClass, SbxCLASS_DONTCARE ); + bRet = (pClassVar != NULL); + } + } + } + return bRet; +} + +bool SbiRuntime::checkClass_Impl( const SbxVariableRef& refVal, + const String& aClass, bool bRaiseErrors ) +{ + bool bOk = true; + + SbxDataType t = refVal->GetType(); + if( t == SbxOBJECT ) + { + SbxObject* pObj; + SbxVariable* pVal = (SbxVariable*)refVal; + if( pVal->IsA( TYPE(SbxObject) ) ) + pObj = (SbxObject*) pVal; + else + { + pObj = (SbxObject*) refVal->GetObject(); + if( pObj && !pObj->IsA( TYPE(SbxObject) ) ) + pObj = NULL; + } + if( pObj ) + { + if( !implIsClass( pObj, aClass ) ) + { + if ( bVBAEnabled && pObj->IsA( TYPE(SbUnoObject) ) ) + { + SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + bOk = checkUnoObjectType( pUnoObj, aClass ); + } + else + bOk = false; + if ( !bOk ) + { + if( bRaiseErrors ) + Error( SbERR_INVALID_USAGE_OBJECT ); + } + } + else + { + SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pObj); + if( pClassModuleObject != NULL ) + pClassModuleObject->triggerInitializeEvent(); + } + } + } + else + { + if ( !bVBAEnabled ) + { + if( bRaiseErrors ) + Error( SbERR_NEEDS_OBJECT ); + bOk = false; + } + } + return bOk; +} + +void SbiRuntime::StepSETCLASS_impl( UINT32 nOp1, bool bHandleDflt ) +{ + SbxVariableRef refVal = PopVar(); + SbxVariableRef refVar = PopVar(); + String aClass( pImg->GetString( static_cast<short>( nOp1 ) ) ); + + bool bOk = checkClass_Impl( refVal, aClass, true ); + if( bOk ) + StepSET_Impl( refVal, refVar, bHandleDflt ); // don't do handle dflt prop for a "proper" set +} + +void SbiRuntime::StepVBASETCLASS( UINT32 nOp1 ) +{ + StepSETCLASS_impl( nOp1, false ); +} + +void SbiRuntime::StepSETCLASS( UINT32 nOp1 ) +{ + StepSETCLASS_impl( nOp1, true ); +} + +void SbiRuntime::StepTESTCLASS( UINT32 nOp1 ) +{ + SbxVariableRef xObjVal = PopVar(); + String aClass( pImg->GetString( static_cast<short>( nOp1 ) ) ); + bool bOk = checkClass_Impl( xObjVal, aClass, false ); + + SbxVariable* pRet = new SbxVariable; + pRet->PutBool( bOk ); + PushVar( pRet ); +} + +// Library fuer anschliessenden Declare-Call definieren + +void SbiRuntime::StepLIB( UINT32 nOp1 ) +{ + aLibName = pImg->GetString( static_cast<short>( nOp1 ) ); +} + +// TOS wird um BASE erhoeht, BASE davor gepusht (+BASE) +// Dieser Opcode wird vor DIM/REDIM-Anweisungen gepusht, +// wenn nur ein Index angegeben wurde. + +void SbiRuntime::StepBASED( UINT32 nOp1 ) +{ + SbxVariable* p1 = new SbxVariable; + SbxVariableRef x2 = PopVar(); + + // #109275 Check compatiblity mode + bool bCompatible = ((nOp1 & 0x8000) != 0); + USHORT uBase = static_cast<USHORT>(nOp1 & 1); // Can only be 0 or 1 + p1->PutInteger( uBase ); + if( !bCompatible ) + x2->Compute( SbxPLUS, *p1 ); + PushVar( x2 ); // erst die Expr + PushVar( p1 ); // dann die Base +} + + + + + diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx new file mode 100644 index 000000000000..fb0b217b76c4 --- /dev/null +++ b/basic/source/runtime/step2.cxx @@ -0,0 +1,1216 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: step2.cxx,v $ + * $Revision: 1.35 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "runtime.hxx" +#ifndef GCC +#endif +#include "iosys.hxx" +#include "image.hxx" +#include "sbintern.hxx" +#include "sbunoobj.hxx" +#include "opcodes.hxx" + +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/script/XDefaultMethod.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <comphelper/processfactory.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::container; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::script; + +using com::sun::star::uno::Reference; + +SbxVariable* getVBAConstant( const String& rName ); + +// Suchen eines Elements +// Die Bits im String-ID: +// 0x8000 - Argv ist belegt + +SbxVariable* SbiRuntime::FindElement + ( SbxObject* pObj, UINT32 nOp1, UINT32 nOp2, SbError nNotFound, BOOL bLocal, BOOL bStatic ) +{ + bool bIsVBAInterOp = SbiRuntime::isVBAEnabled(); + if( bIsVBAInterOp ) + { + StarBASIC* pMSOMacroRuntimeLib = GetSbData()->pMSOMacroRuntimLib; + if( pMSOMacroRuntimeLib != NULL ) + pMSOMacroRuntimeLib->ResetFlag( SBX_EXTSEARCH ); + } + + SbxVariable* pElem = NULL; + if( !pObj ) + { + Error( SbERR_NO_OBJECT ); + pElem = new SbxVariable; + } + else + { + BOOL bFatalError = FALSE; + SbxDataType t = (SbxDataType) nOp2; + String aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) ); + // Hacky capture of Evaluate [] syntax + // this should be tackled I feel at the pcode level + if ( bIsVBAInterOp && aName.Search('[') == 0 ) + { + // emulate pcode here + StepARGC(); + // psuedo StepLOADSC + String sArg = aName.Copy( 1, aName.Len() - 2 ); + SbxVariable* p = new SbxVariable; + p->PutString( sArg ); + PushVar( p ); + // + StepARGV(); + nOp1 = nOp1 | 0x8000; // indicate params are present + aName = String::CreateFromAscii("Evaluate"); + } + if( bLocal ) + { + if ( bStatic ) + { + if ( pMeth ) + pElem = pMeth->GetStatics()->Find( aName, SbxCLASS_DONTCARE ); + } + + if ( !pElem ) + pElem = refLocals->Find( aName, SbxCLASS_DONTCARE ); + } + if( !pElem ) + { + // Die RTL brauchen wir nicht mehr zu durchsuchen! + BOOL bSave = rBasic.bNoRtl; + rBasic.bNoRtl = TRUE; + pElem = pObj->Find( aName, SbxCLASS_DONTCARE ); + + // #110004, #112015: Make private really private + if( bLocal && pElem ) // Local as flag for global search + { + if( pElem->IsSet( SBX_PRIVATE ) ) + { + SbiInstance* pInst_ = pINST; + if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() ) + pElem = NULL; // Found but in wrong module! + + // Interfaces: Use SBX_EXTFOUND + } + } + rBasic.bNoRtl = bSave; + + // Ist es ein globaler Uno-Bezeichner? + if( bLocal && !pElem ) + { + bool bSetName = true; // preserve normal behaviour + + // i#i68894# if VBAInterOp favour searching vba globals + // over searching for uno classess + if ( bVBAEnabled ) + { + // Try Find in VBA symbols space + pElem = rBasic.VBAFind( aName, SbxCLASS_DONTCARE ); + if ( pElem ) + bSetName = false; // don't overwrite uno name + else + pElem = getVBAConstant( aName ); + } + // #72382 VORSICHT! Liefert jetzt wegen unbekannten + // Modulen IMMER ein Ergebnis! + SbUnoClass* pUnoClass = findUnoClass( aName ); + if( pUnoClass ) + { + pElem = new SbxVariable( t ); + SbxValues aRes( SbxOBJECT ); + aRes.pObj = pUnoClass; + pElem->SbxVariable::Put( aRes ); + } + + // #62939 Wenn eine Uno-Klasse gefunden wurde, muss + // das Wrapper-Objekt gehalten werden, da sonst auch + // die Uno-Klasse, z.B. "stardiv" immer wieder neu + // aus der Registry gelesen werden muss + if( pElem ) + { + // #63774 Darf nicht mit gespeichert werden!!! + pElem->SetFlag( SBX_DONTSTORE ); + pElem->SetFlag( SBX_NO_MODIFY); + + // #72382 Lokal speichern, sonst werden alle implizit + // deklarierten Vars automatisch global ! + if ( bSetName ) + pElem->SetName( aName ); + refLocals->Put( pElem, refLocals->Count() ); + } + } + + if( !pElem ) + { + // Nicht da und nicht im Objekt? + // Hat das Ding Parameter, nicht einrichten! + if( nOp1 & 0x8000 ) + bFatalError = TRUE; + // ALT: StarBASIC::FatalError( nNotFound ); + + // Sonst, falls keine Parameter sind, anderen Error Code verwenden + if( !bLocal || pImg->GetFlag( SBIMG_EXPLICIT ) ) + { + // #39108 Bei explizit und als ELEM immer ein Fatal Error + bFatalError = TRUE; + + // Falls keine Parameter sind, anderen Error Code verwenden + if( !( nOp1 & 0x8000 ) && nNotFound == SbERR_PROC_UNDEFINED ) + nNotFound = SbERR_VAR_UNDEFINED; + } + if( bFatalError ) + { + // #39108 Statt FatalError zu setzen, Dummy-Variable liefern + if( !xDummyVar.Is() ) + xDummyVar = new SbxVariable( SbxVARIANT ); + pElem = xDummyVar; + + // Parameter von Hand loeschen + ClearArgvStack(); + + // Normalen Error setzen + Error( nNotFound, aName ); + } + else + { + if ( bStatic ) + pElem = StepSTATIC_Impl( aName, t ); + if ( !pElem ) + { + // Sonst Variable neu anlegen + pElem = new SbxVariable( t ); + if( t != SbxVARIANT ) + pElem->SetFlag( SBX_FIXED ); + pElem->SetName( aName ); + refLocals->Put( pElem, refLocals->Count() ); + } + } + } + } + // #39108 Args koennen schon geloescht sein! + if( !bFatalError ) + SetupArgs( pElem, nOp1 ); + // Ein bestimmter Call-Type wurde gewuenscht, daher muessen + // wir hier den Typ setzen und das Ding anfassen, um den + // korrekten Returnwert zu erhalten! + if( pElem->IsA( TYPE(SbxMethod) ) ) + { + // Soll der Typ konvertiert werden? + SbxDataType t2 = pElem->GetType(); + BOOL bSet = FALSE; + if( !( pElem->GetFlags() & SBX_FIXED ) ) + { + if( t != SbxVARIANT && t != t2 && + t >= SbxINTEGER && t <= SbxSTRING ) + pElem->SetType( t ), bSet = TRUE; + } + // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen + SbxVariableRef refTemp = pElem; + + // Moegliche Reste vom letzten Aufruf der SbxMethod beseitigen + // Vorher Schreiben freigeben, damit kein Error gesetzt wird. + USHORT nSavFlags = pElem->GetFlags(); + pElem->SetFlag( SBX_READWRITE | SBX_NO_BROADCAST ); + pElem->SbxValue::Clear(); + pElem->SetFlags( nSavFlags ); + + // Erst nach dem Setzen anfassen, da z.B. LEFT() + // den Unterschied zwischen Left$() und Left() kennen muss + + // AB 12.8.96: Da in PopVar() die Parameter von Methoden weggehauen + // werden, muessen wir hier explizit eine neue SbxMethod anlegen + SbxVariable* pNew = new SbxMethod( *((SbxMethod*)pElem) ); // das ist der Call! + //ALT: SbxVariable* pNew = new SbxVariable( *pElem ); // das ist der Call! + + pElem->SetParameters(0); // sonst bleibt Ref auf sich selbst + pNew->SetFlag( SBX_READWRITE ); + + // den Datentypen zuruecksetzen? + if( bSet ) + pElem->SetType( t2 ); + pElem = pNew; + } + // Index-Access bei UnoObjekten beruecksichtigen + /* + else if( pElem->ISA(SbUnoProperty) ) + { + // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen + SbxVariableRef refTemp = pElem; + + // Variable kopieren und dabei den Notify aufloesen + SbxVariable* pNew = new SbxVariable( *((SbxVariable*)pElem) ); // das ist der Call! + pElem->SetParameters( NULL ); // sonst bleibt Ref auf sich selbst + pElem = pNew; + } + */ + } + return CheckArray( pElem ); +} + +// Find-Funktion ueber Name fuer aktuellen Scope (z.B. Abfrage aus BASIC-IDE) +SbxBase* SbiRuntime::FindElementExtern( const String& rName ) +{ + // Hinweis zu #35281#: Es darf nicht davon ausgegangen werden, dass + // pMeth != null, da im RunInit noch keine gesetzt ist. + + SbxVariable* pElem = NULL; + if( !pMod || !rName.Len() ) + return NULL; + + // Lokal suchen + if( refLocals ) + pElem = refLocals->Find( rName, SbxCLASS_DONTCARE ); + + // In Statics suchen + if ( !pElem && pMeth ) + { + // Bei Statics, Name der Methode davor setzen + String aMethName = pMeth->GetName(); + aMethName += ':'; + aMethName += rName; + pElem = pMod->Find(aMethName, SbxCLASS_DONTCARE); + } + + // In Parameter-Liste suchen + if( !pElem && pMeth ) + { + SbxInfo* pInfo = pMeth->GetInfo(); + if( pInfo && refParams ) + { + USHORT nParamCount = refParams->Count(); + USHORT j = 1; + const SbxParamInfo* pParam = pInfo->GetParam( j ); + while( pParam ) + { + if( pParam->aName.EqualsIgnoreCaseAscii( rName ) ) + { + if( j >= nParamCount ) + { + // Parameter is missing + pElem = new SbxVariable( SbxSTRING ); + pElem->PutString( String( RTL_CONSTASCII_USTRINGPARAM("<missing parameter>" ) ) ); + } + else + { + pElem = refParams->Get( j ); + } + break; + } + pParam = pInfo->GetParam( ++j ); + } + } + } + + // Im Modul suchen + if( !pElem ) + { + // RTL nicht durchsuchen! + BOOL bSave = rBasic.bNoRtl; + rBasic.bNoRtl = TRUE; + pElem = pMod->Find( rName, SbxCLASS_DONTCARE ); + rBasic.bNoRtl = bSave; + } + return pElem; +} + + +// Argumente eines Elements setzen +// Dabei auch die Argumente umsetzen, falls benannte Parameter +// verwendet wurden + +void SbiRuntime::SetupArgs( SbxVariable* p, UINT32 nOp1 ) +{ + if( nOp1 & 0x8000 ) + { + if( !refArgv ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + BOOL bHasNamed = FALSE; + USHORT i; + USHORT nArgCount = refArgv->Count(); + for( i = 1 ; i < nArgCount ; i++ ) + { + if( refArgv->GetAlias( i ).Len() ) + { + bHasNamed = TRUE; break; + } + } + if( bHasNamed ) + { + // Wir haben mindestens einen benannten Parameter! + // Wir muessen also umsortieren + // Gibt es Parameter-Infos? + SbxInfo* pInfo = p->GetInfo(); + if( !pInfo ) + { + bool bError_ = true; + + SbUnoMethod* pUnoMethod = PTR_CAST(SbUnoMethod,p); + if( pUnoMethod ) + { + SbUnoObject* pParentUnoObj = PTR_CAST( SbUnoObject,p->GetParent() ); + if( pParentUnoObj ) + { + Any aUnoAny = pParentUnoObj->getUnoAny(); + Reference< XInvocation > xInvocation; + aUnoAny >>= xInvocation; + if( xInvocation.is() ) // TODO: if( xOLEAutomation.is() ) + { + bError_ = false; + + USHORT nCurPar = 1; + AutomationNamedArgsSbxArray* pArg = + new AutomationNamedArgsSbxArray( nArgCount ); + ::rtl::OUString* pNames = pArg->getNames().getArray(); + for( i = 1 ; i < nArgCount ; i++ ) + { + SbxVariable* pVar = refArgv->Get( i ); + const String& rName = refArgv->GetAlias( i ); + if( rName.Len() ) + pNames[i] = rName; + pArg->Put( pVar, nCurPar++ ); + } + refArgv = pArg; + } + } + } + if( bError_ ) + Error( SbERR_NO_NAMED_ARGS ); + } + else + { + USHORT nCurPar = 1; + SbxArray* pArg = new SbxArray; + for( i = 1 ; i < nArgCount ; i++ ) + { + SbxVariable* pVar = refArgv->Get( i ); + const String& rName = refArgv->GetAlias( i ); + if( rName.Len() ) + { + // nCurPar wird auf den gefundenen Parameter gesetzt + USHORT j = 1; + const SbxParamInfo* pParam = pInfo->GetParam( j ); + while( pParam ) + { + if( pParam->aName.EqualsIgnoreCaseAscii( rName ) ) + { + nCurPar = j; + break; + } + pParam = pInfo->GetParam( ++j ); + } + if( !pParam ) + { + Error( SbERR_NAMED_NOT_FOUND ); break; + } + } + pArg->Put( pVar, nCurPar++ ); + } + refArgv = pArg; + } + } + // Eigene Var als Parameter 0 + refArgv->Put( p, 0 ); + p->SetParameters( refArgv ); + PopArgv(); + } + else + p->SetParameters( NULL ); +} + +// Holen eines Array-Elements + +SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) +{ + // Falls wir ein Array haben, wollen wir bitte das Array-Element! + SbxArray* pPar; + if( pElem->GetType() & SbxARRAY ) + { + SbxBase* pElemObj = pElem->GetObject(); + SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj); + pPar = pElem->GetParameters(); + if( pDimArray ) + { + // Die Parameter koennen fehlen, wenn ein Array als + // Argument uebergeben wird. + if( pPar ) + pElem = pDimArray->Get( pPar ); + } + else + { + SbxArray* pArray = PTR_CAST(SbxArray,pElemObj); + if( pArray ) + { + if( !pPar ) + { + Error( SbERR_OUT_OF_RANGE ); + pElem = new SbxVariable; + } + else + pElem = pArray->Get( pPar->Get( 1 )->GetInteger() ); + } + } + + // #42940, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt + if( pPar ) + pPar->Put( NULL, 0 ); + } + // Index-Access bei UnoObjekten beruecksichtigen + else if( pElem->GetType() == SbxOBJECT && !pElem->ISA(SbxMethod) ) + { + pPar = pElem->GetParameters(); + if ( pPar ) + { + // Ist es ein Uno-Objekt? + SbxBaseRef pObj = (SbxBase*)pElem->GetObject(); + if( pObj ) + { + if( pObj->ISA(SbUnoObject) ) + { + SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj; + Any aAny = pUnoObj->getUnoAny(); + + if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) + { + Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue(); + Reference< XIndexAccess > xIndexAccess( x, UNO_QUERY ); + if ( !bVBAEnabled ) + { + // Haben wir Index-Access? + if( xIndexAccess.is() ) + { + UINT32 nParamCount = (UINT32)pPar->Count() - 1; + if( nParamCount != 1 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return pElem; + } + + // Index holen + INT32 nIndex = pPar->Get( 1 )->GetLong(); + Reference< XInterface > xRet; + try + { + Any aAny2 = xIndexAccess->getByIndex( nIndex ); + TypeClass eType = aAny2.getValueType().getTypeClass(); + if( eType == TypeClass_INTERFACE ) + xRet = *(Reference< XInterface >*)aAny2.getValue(); + } + catch (IndexOutOfBoundsException&) + { + // Bei Exception erstmal immer von Konvertierungs-Problem ausgehen + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + + // #57847 Immer neue Variable anlegen, sonst Fehler + // durch PutObject(NULL) bei ReadOnly-Properties. + pElem = new SbxVariable( SbxVARIANT ); + if( xRet.is() ) + { + aAny <<= xRet; + + // #67173 Kein Namen angeben, damit echter Klassen-Namen eintragen wird + String aName; + SbxObjectRef xWrapper = (SbxObject*)new SbUnoObject( aName, aAny ); + pElem->PutObject( xWrapper ); + } + else + { + pElem->PutObject( NULL ); + } + } + } + else + { + rtl::OUString sDefaultMethod; + + Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY ); + + if ( xDfltMethod.is() ) + sDefaultMethod = xDfltMethod->getDefaultMethodName(); + else if( xIndexAccess.is() ) + sDefaultMethod = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getByIndex" ) ); + + if ( sDefaultMethod.getLength() ) + { + SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD ); + SbxVariableRef refTemp = meth; + if ( refTemp ) + { + meth->SetParameters( pPar ); + SbxVariable* pNew = new SbxMethod( *(SbxMethod*)meth ); + pElem = pNew; + } + } + } + } + + // #42940, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt + pPar->Put( NULL, 0 ); + } + else if( pObj->ISA(BasicCollection) ) + { + BasicCollection* pCol = (BasicCollection*)(SbxBase*)pObj; + pElem = new SbxVariable( SbxVARIANT ); + pPar->Put( pElem, 0 ); + pCol->CollItem( pPar ); + } + } + } + } + + return pElem; +} + +// Laden eines Elements aus der Runtime-Library (+StringID+Typ) + +void SbiRuntime::StepRTL( UINT32 nOp1, UINT32 nOp2 ) +{ + PushVar( FindElement( rBasic.pRtl, nOp1, nOp2, SbERR_PROC_UNDEFINED, FALSE ) ); +} + +void +SbiRuntime::StepFIND_Impl( SbxObject* pObj, UINT32 nOp1, UINT32 nOp2, SbError nNotFound, BOOL bLocal, BOOL bStatic ) +{ + if( !refLocals ) + refLocals = new SbxArray; + PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, bLocal, bStatic ) ); +} +// Laden einer lokalen/globalen Variablen (+StringID+Typ) + +void SbiRuntime::StepFIND( UINT32 nOp1, UINT32 nOp2 ) +{ + StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, TRUE ); +} + +// Search inside a class module (CM) to enable global search in time +void SbiRuntime::StepFIND_CM( UINT32 nOp1, UINT32 nOp2 ) +{ + + SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pMod); + if( pClassModuleObject ) + pMod->SetFlag( SBX_GBLSEARCH ); + + StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, TRUE ); + + if( pClassModuleObject ) + pMod->ResetFlag( SBX_GBLSEARCH ); +} + +void SbiRuntime::StepFIND_STATIC( UINT32 nOp1, UINT32 nOp2 ) +{ + StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, TRUE, TRUE ); +} + +// Laden eines Objekt-Elements (+StringID+Typ) +// Das Objekt liegt auf TOS + +void SbiRuntime::StepELEM( UINT32 nOp1, UINT32 nOp2 ) +{ + // Liegt auf dem TOS ein Objekt? + SbxVariableRef pObjVar = PopVar(); + + SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pObjVar); + if( !pObj ) + { + SbxBase* pObjVarObj = pObjVar->GetObject(); + pObj = PTR_CAST(SbxObject,pObjVarObj); + } + + // #56368 Bei StepElem Referenz sichern, sonst koennen Objekte + // in Qualifizierungsketten wie ActiveComponent.Selection(0).Text + // zu fueh die Referenz verlieren + // #74254 Jetzt per Liste + if( pObj ) + SaveRef( (SbxVariable*)pObj ); + + PushVar( FindElement( pObj, nOp1, nOp2, SbERR_NO_METHOD, FALSE ) ); +} + +// Laden eines Parameters (+Offset+Typ) +// Wenn der Datentyp nicht stimmen sollte, eine Kopie anlegen +// Der Datentyp SbxEMPTY zeigt an, daa kein Parameter angegeben ist. +// Get( 0 ) darf EMPTY sein + +void SbiRuntime::StepPARAM( UINT32 nOp1, UINT32 nOp2 ) +{ + USHORT i = static_cast<USHORT>( nOp1 & 0x7FFF ); + SbxDataType t = (SbxDataType) nOp2; + SbxVariable* p; + + // #57915 Missing sauberer loesen + USHORT nParamCount = refParams->Count(); + if( i >= nParamCount ) + { + INT16 iLoop = i; + while( iLoop >= nParamCount ) + { + p = new SbxVariable(); + p->PutErr( 448 ); // Wie in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND) + refParams->Put( p, iLoop ); + iLoop--; + } + } + p = refParams->Get( i ); + + if( p->GetType() == SbxERROR && ( i ) ) + //if( p->GetType() == SbxEMPTY && ( i ) ) + { + // Wenn ein Parameter fehlt, kann er OPTIONAL sein + BOOL bOpt = FALSE; + if( pMeth ) + { + SbxInfo* pInfo = pMeth->GetInfo(); + if ( pInfo ) + { + const SbxParamInfo* pParam = pInfo->GetParam( i ); + if( pParam && ( (pParam->nFlags & SBX_OPTIONAL) != 0 ) ) + { + // Default value? + USHORT nDefaultId = sal::static_int_cast< USHORT >( + pParam->nUserData & 0xffff ); + if( nDefaultId > 0 ) + { + String aDefaultStr = pImg->GetString( nDefaultId ); + p = new SbxVariable(); + p->PutString( aDefaultStr ); + refParams->Put( p, i ); + } + bOpt = TRUE; + } + } + } + if( bOpt == FALSE ) + Error( SbERR_NOT_OPTIONAL ); + } + else if( t != SbxVARIANT && (SbxDataType)(p->GetType() & 0x0FFF ) != t ) + { + SbxVariable* q = new SbxVariable( t ); + SaveRef( q ); + *q = *p; + p = q; + } + SetupArgs( p, nOp1 ); + PushVar( CheckArray( p ) ); +} + +// Case-Test (+True-Target+Test-Opcode) + +void SbiRuntime::StepCASEIS( UINT32 nOp1, UINT32 nOp2 ) +{ + if( !refCaseStk || !refCaseStk->Count() ) + StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); + else + { + SbxVariableRef xComp = PopVar(); + SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 ); + if( xCase->Compare( (SbxOperator) nOp2, *xComp ) ) + StepJUMP( nOp1 ); + } +} + +// Aufruf einer DLL-Prozedur (+StringID+Typ) +// Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist + +void SbiRuntime::StepCALL( UINT32 nOp1, UINT32 nOp2 ) +{ + String aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ); + SbxArray* pArgs = NULL; + if( nOp1 & 0x8000 ) + pArgs = refArgv; + DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, FALSE ); + aLibName = String(); + if( nOp1 & 0x8000 ) + PopArgv(); +} + +// Aufruf einer DLL-Prozedur nach CDecl (+StringID+Typ) +// Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist + +void SbiRuntime::StepCALLC( UINT32 nOp1, UINT32 nOp2 ) +{ + String aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ); + SbxArray* pArgs = NULL; + if( nOp1 & 0x8000 ) + pArgs = refArgv; + DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, TRUE ); + aLibName = String(); + if( nOp1 & 0x8000 ) + PopArgv(); +} + + +// Beginn eines Statements (+Line+Col) + +void SbiRuntime::StepSTMNT( UINT32 nOp1, UINT32 nOp2 ) +{ + // Wenn der Expr-Stack am Anfang einen Statements eine Variable enthaelt, + // hat ein Trottel X als Funktion aufgerufen, obwohl es eine Variable ist! + BOOL bFatalExpr = FALSE; + String sUnknownMethodName; + if( nExprLvl > 1 ) + bFatalExpr = TRUE; + else if( nExprLvl ) + { + SbxVariable* p = refExprStk->Get( 0 ); + if( p->GetRefCount() > 1 + && refLocals.Is() && refLocals->Find( p->GetName(), p->GetClass() ) ) + { + sUnknownMethodName = p->GetName(); + bFatalExpr = TRUE; + } + } + // Der Expr-Stack ist nun nicht mehr notwendig + ClearExprStack(); + + // #56368 Kuenstliche Referenz fuer StepElem wieder freigeben, + // damit sie nicht ueber ein Statement hinaus erhalten bleibt + //refSaveObj = NULL; + // #74254 Jetzt per Liste + ClearRefs(); + + // Wir muessen hier hart abbrechen, da sonst Zeile und Spalte nicht mehr + // stimmen! + if( bFatalExpr) + { + StarBASIC::FatalError( SbERR_NO_METHOD, sUnknownMethodName ); + return; + } + pStmnt = pCode - 9; + USHORT nOld = nLine; + nLine = static_cast<short>( nOp1 ); + + // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern + nCol1 = static_cast<short>( nOp2 & 0xFF ); + + // Suchen des naechsten STMNT-Befehls, + // um die End-Spalte dieses Statements zu setzen + // Searches of the next STMNT instruction, + // around the final column of this statement to set + + nCol2 = 0xffff; + USHORT n1, n2; + const BYTE* p = pMod->FindNextStmnt( pCode, n1, n2 ); + if( p ) + { + if( n1 == nOp1 ) + { + // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern + nCol2 = (n2 & 0xFF) - 1; + } + } + + // #29955 for-Schleifen-Ebene korrigieren, #67452 NICHT im Error-Handler sonst Chaos + if( !bInError ) + { + // (Bei Sprüngen aus Schleifen tritt hier eine Differenz auf) + USHORT nExspectedForLevel = static_cast<USHORT>( nOp2 / 0x100 ); + if( pGosubStk ) + nExspectedForLevel = nExspectedForLevel + pGosubStk->nStartForLvl; + + // Wenn der tatsaechliche For-Level zu klein ist, wurde aus + // einer Schleife heraus gesprungen -> korrigieren + while( nForLvl > nExspectedForLevel ) + PopFor(); + } + + // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out + // Erklärung siehe bei _ImplGetBreakCallLevel. + if( pInst->nCallLvl <= pInst->nBreakCallLvl ) + //if( nFlags & SbDEBUG_STEPINTO ) + { + StarBASIC* pStepBasic = GetCurrentBasic( &rBasic ); + USHORT nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 ); + + // Neuen BreakCallLevel ermitteln + pInst->CalcBreakCallLevel( nNewFlags ); + } + + // Breakpoints nur bei STMNT-Befehlen in neuer Zeile! + else if( ( nOp1 != nOld ) + && ( nFlags & SbDEBUG_BREAK ) + && pMod->IsBP( static_cast<USHORT>( nOp1 ) ) ) + { + StarBASIC* pBreakBasic = GetCurrentBasic( &rBasic ); + USHORT nNewFlags = pBreakBasic->BreakPoint( nLine, nCol1, nCol2 ); + + // Neuen BreakCallLevel ermitteln + pInst->CalcBreakCallLevel( nNewFlags ); + //16.10.96, ALT: + //if( nNewFlags != SbDEBUG_CONTINUE ) + // nFlags = nNewFlags; + } +} + +// (+SvStreamFlags+Flags) +// Stack: Blocklaenge +// Kanalnummer +// Dateiname + +void SbiRuntime::StepOPEN( UINT32 nOp1, UINT32 nOp2 ) +{ + SbxVariableRef pName = PopVar(); + SbxVariableRef pChan = PopVar(); + SbxVariableRef pLen = PopVar(); + short nBlkLen = pLen->GetInteger(); + short nChan = pChan->GetInteger(); + ByteString aName( pName->GetString(), gsl_getSystemTextEncoding() ); + pIosys->Open( nChan, aName, static_cast<short>( nOp1 ), + static_cast<short>( nOp2 ), nBlkLen ); + Error( pIosys->GetError() ); +} + +// Objekt kreieren (+StringID+StringID) + +void SbiRuntime::StepCREATE( UINT32 nOp1, UINT32 nOp2 ) +{ + String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + SbxObject *pObj = SbxBase::CreateObject( aClass ); + if( !pObj ) + Error( SbERR_INVALID_OBJECT ); + else + { + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + pObj->SetName( aName ); + // Das Objekt muss BASIC rufen koennen + pObj->SetParent( &rBasic ); + SbxVariable* pNew = new SbxVariable; + pNew->PutObject( pObj ); + PushVar( pNew ); + } +} + +void SbiRuntime::StepDCREATE( UINT32 nOp1, UINT32 nOp2 ) +{ + StepDCREATE_IMPL( nOp1, nOp2 ); +} + +void SbiRuntime::StepDCREATE_REDIMP( UINT32 nOp1, UINT32 nOp2 ) +{ + StepDCREATE_IMPL( nOp1, nOp2 ); +} + + +// Helper function for StepDCREATE_IMPL / bRedimp = true +void implCopyDimArray_DCREATE( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex, + short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) +{ + sal_Int32& ri = pActualIndices[nActualDim]; + for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ ) + { + if( nActualDim < nMaxDimIndex ) + { + implCopyDimArray_DCREATE( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1, + pActualIndices, pLowerBounds, pUpperBounds ); + } + else + { + SbxVariable* pSource = pOldArray->Get32( pActualIndices ); + pNewArray->Put32( pSource, pActualIndices ); + } + } +} + +// #56204 Objekt-Array kreieren (+StringID+StringID), DCREATE == Dim-Create +void SbiRuntime::StepDCREATE_IMPL( UINT32 nOp1, UINT32 nOp2 ) +{ + SbxVariableRef refVar = PopVar(); + + DimImpl( refVar ); + + // Das Array mit Instanzen der geforderten Klasse fuellen + SbxBaseRef xObj = (SbxBase*)refVar->GetObject(); + if( !xObj ) + { + StarBASIC::Error( SbERR_INVALID_OBJECT ); + return; + } + + SbxDimArray* pArray = 0; + if( xObj->ISA(SbxDimArray) ) + { + SbxBase* pObj = (SbxBase*)xObj; + pArray = (SbxDimArray*)pObj; + + // Dimensionen auswerten + short nDims = pArray->GetDims(); + INT32 nTotalSize = 0; + + // es muss ein eindimensionales Array sein + INT32 nLower, nUpper, nSize; + INT32 i; + for( i = 0 ; i < nDims ; i++ ) + { + pArray->GetDim32( i+1, nLower, nUpper ); + nSize = nUpper - nLower + 1; + if( i == 0 ) + nTotalSize = nSize; + else + nTotalSize *= nSize; + } + + // Objekte anlegen und ins Array eintragen + String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + for( i = 0 ; i < nTotalSize ; i++ ) + { + SbxObject *pClassObj = SbxBase::CreateObject( aClass ); + if( !pClassObj ) + { + Error( SbERR_INVALID_OBJECT ); + break; + } + else + { + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + pClassObj->SetName( aName ); + // Das Objekt muss BASIC rufen koennen + pClassObj->SetParent( &rBasic ); + pArray->SbxArray::Put32( pClassObj, i ); + } + } + } + + SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray; + if( pArray && pOldArray ) + { + short nDimsNew = pArray->GetDims(); + short nDimsOld = pOldArray->GetDims(); + short nDims = nDimsNew; + BOOL bRangeError = FALSE; + + // Store dims to use them for copying later + sal_Int32* pLowerBounds = new sal_Int32[nDims]; + sal_Int32* pUpperBounds = new sal_Int32[nDims]; + sal_Int32* pActualIndices = new sal_Int32[nDims]; + if( nDimsOld != nDimsNew ) + { + bRangeError = TRUE; + } + else + { + // Compare bounds + for( short i = 1 ; i <= nDims ; i++ ) + { + sal_Int32 lBoundNew, uBoundNew; + sal_Int32 lBoundOld, uBoundOld; + pArray->GetDim32( i, lBoundNew, uBoundNew ); + pOldArray->GetDim32( i, lBoundOld, uBoundOld ); + + lBoundNew = std::max( lBoundNew, lBoundOld ); + uBoundNew = std::min( uBoundNew, uBoundOld ); + short j = i - 1; + pActualIndices[j] = pLowerBounds[j] = lBoundNew; + pUpperBounds[j] = uBoundNew; + } + } + + if( bRangeError ) + { + StarBASIC::Error( SbERR_OUT_OF_RANGE ); + } + else + { + // Copy data from old array by going recursively through all dimensions + // (It would be faster to work on the flat internal data array of an + // SbyArray but this solution is clearer and easier) + implCopyDimArray_DCREATE( pArray, pOldArray, nDims - 1, + 0, pActualIndices, pLowerBounds, pUpperBounds ); + } + delete [] pUpperBounds; + delete [] pLowerBounds; + delete [] pActualIndices; + refRedimpArray = NULL; + } +} + +// Objekt aus User-Type kreieren (+StringID+StringID) + +SbxObject* createUserTypeImpl( const String& rClassName ); // sb.cxx + +void SbiRuntime::StepTCREATE( UINT32 nOp1, UINT32 nOp2 ) +{ + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + + SbxObject* pCopyObj = createUserTypeImpl( aClass ); + if( pCopyObj ) + pCopyObj->SetName( aName ); + SbxVariable* pNew = new SbxVariable; + pNew->PutObject( pCopyObj ); + PushVar( pNew ); +} + + +// Einrichten einer lokalen Variablen (+StringID+Typ) + +void SbiRuntime::StepLOCAL( UINT32 nOp1, UINT32 nOp2 ) +{ + if( !refLocals.Is() ) + refLocals = new SbxArray; + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + if( refLocals->Find( aName, SbxCLASS_DONTCARE ) == NULL ) + { + SbxDataType t = (SbxDataType) nOp2; + SbxVariable* p = new SbxVariable( t ); + p->SetName( aName ); + refLocals->Put( p, refLocals->Count() ); + } +} + +// Einrichten einer modulglobalen Variablen (+StringID+Typ) + +void SbiRuntime::StepPUBLIC_Impl( UINT32 nOp1, UINT32 nOp2, bool bUsedForClassModule ) +{ + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + SbxDataType t = (SbxDataType) nOp2; + BOOL bFlag = pMod->IsSet( SBX_NO_MODIFY ); + pMod->SetFlag( SBX_NO_MODIFY ); + SbxVariableRef p = pMod->Find( aName, SbxCLASS_PROPERTY ); + if( p.Is() ) + pMod->Remove (p); + SbProperty* pProp = pMod->GetProperty( aName, t ); + if( !bUsedForClassModule ) + pProp->SetFlag( SBX_PRIVATE ); + if( !bFlag ) + pMod->ResetFlag( SBX_NO_MODIFY ); + if( pProp ) + { + pProp->SetFlag( SBX_DONTSTORE ); + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + pProp->SetFlag( SBX_NO_MODIFY); + } +} + +void SbiRuntime::StepPUBLIC( UINT32 nOp1, UINT32 nOp2 ) +{ + StepPUBLIC_Impl( nOp1, nOp2, false ); +} + +void SbiRuntime::StepPUBLIC_P( UINT32 nOp1, UINT32 nOp2 ) +{ + // Creates module variable that isn't reinitialised when + // between invocations ( for VBASupport & document basic only ) + if( pMod->pImage->bFirstInit ) + StepPUBLIC( nOp1, nOp2 ); +} + +// Einrichten einer globalen Variablen (+StringID+Typ) + +void SbiRuntime::StepGLOBAL( UINT32 nOp1, UINT32 nOp2 ) +{ + if( pImg->GetFlag( SBIMG_CLASSMODULE ) ) + StepPUBLIC_Impl( nOp1, nOp2, true ); + + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + SbxDataType t = (SbxDataType) nOp2; + BOOL bFlag = rBasic.IsSet( SBX_NO_MODIFY ); + rBasic.SetFlag( SBX_NO_MODIFY ); + SbxVariableRef p = rBasic.Find( aName, SbxCLASS_PROPERTY ); + if( p.Is() ) + rBasic.Remove (p); + p = rBasic.Make( aName, SbxCLASS_PROPERTY, t ); + if( !bFlag ) + rBasic.ResetFlag( SBX_NO_MODIFY ); + if( p ) + { + p->SetFlag( SBX_DONTSTORE ); + // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' + p->SetFlag( SBX_NO_MODIFY); + } +} + + +// Creates global variable that isn't reinitialised when +// basic is restarted, P=PERSIST (+StringID+Typ) + +void SbiRuntime::StepGLOBAL_P( UINT32 nOp1, UINT32 nOp2 ) +{ + if( pMod->pImage->bFirstInit ) + { + StepGLOBAL( nOp1, nOp2 ); + } +} + + +// Searches for global variable, behavior depends on the fact +// if the variable is initialised for the first time + +void SbiRuntime::StepFIND_G( UINT32 nOp1, UINT32 nOp2 ) +{ + if( pMod->pImage->bFirstInit ) + { + // Behave like always during first init + StepFIND( nOp1, nOp2 ); + } + else + { + // Return dummy variable + SbxDataType t = (SbxDataType) nOp2; + String aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) ); + + SbxVariable* pDummyVar = new SbxVariable( t ); + pDummyVar->SetName( aName ); + PushVar( pDummyVar ); + } +} + + +SbxVariable* SbiRuntime::StepSTATIC_Impl( String& aName, SbxDataType& t ) +{ + SbxVariable* p = NULL; + if ( pMeth ) + { + SbxArray* pStatics = pMeth->GetStatics(); + if( pStatics && ( pStatics->Find( aName, SbxCLASS_DONTCARE ) == NULL ) ) + { + p = new SbxVariable( t ); + if( t != SbxVARIANT ) + p->SetFlag( SBX_FIXED ); + p->SetName( aName ); + pStatics->Put( p, pStatics->Count() ); + } + } + return p; +} +// Einrichten einer statischen Variablen (+StringID+Typ) +void SbiRuntime::StepSTATIC( UINT32 nOp1, UINT32 nOp2 ) +{ + String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + SbxDataType t = (SbxDataType) nOp2; + StepSTATIC_Impl( aName, t ); +} + diff --git a/basic/source/runtime/win.asm b/basic/source/runtime/win.asm new file mode 100644 index 000000000000..252bb43b5dcf --- /dev/null +++ b/basic/source/runtime/win.asm @@ -0,0 +1,84 @@ +;************************************************************************* +; +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; Copyright 2008 by Sun Microsystems, Inc. +; +; OpenOffice.org - a multi-platform office productivity suite +; +; $RCSfile: win.asm,v $ +; +; $Revision: 1.4 $ +; +; This file is part of OpenOffice.org. +; +; OpenOffice.org is free software: you can redistribute it and/or modify +; it under the terms of the GNU Lesser General Public License version 3 +; only, as published by the Free Software Foundation. +; +; OpenOffice.org is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU Lesser General Public License version 3 for more details +; (a copy is included in the LICENSE file that accompanied this code). +; +; You should have received a copy of the GNU Lesser General Public License +; version 3 along with OpenOffice.org. If not, see +; <http://www.openoffice.org/license.html> +; for a copy of the LGPLv3 License. +; +;************************************************************************* + +; Anmerkungen +; Direktaufruf von C- und PASCAL-Routinen, Windows und OS/2 +; +; Inhalt: +; type = CallXXX (far *proc, char *stack, short nstack) +; +; Kopie des Basic-Stacks (nstack Bytes) auf den C-Stack +; und Aufruf der Prozedur. + + .MODEL LARGE,C + + .CODE + + PUBLIC CallINT + PUBLIC CallLNG + PUBLIC CallSNG + PUBLIC CallDBL + PUBLIC CallSTR + PUBLIC CallFIX + +CallINT LABEL byte +CallLNG LABEL byte +CallSNG LABEL byte +CallDBL LABEL byte +CallSTR LABEL byte +CallFIX PROC p:PTR,stk:PTR,n:WORD + + PUSH SI + PUSH DI + MOV DX,DS + SUB SP,[n] + MOV DI,SP + MOV AX,SS + MOV ES,AX + LDS SI,[stk] + MOV CX,[n] + SHR CX,1 + CLD + JCXZ $1 + REP MOVSW ; Stack uebernehmen +$1: MOV DS,DX + CALL [p] ; Aufruf der Prozedur + CLI + MOV SP,BP + SUB SP,4 ; wegen gepushter Register + STI + POP DI + POP SI + RET + +CallFIX ENDP + + END diff --git a/basic/source/runtime/wnt-mingw.s b/basic/source/runtime/wnt-mingw.s new file mode 100644 index 000000000000..b42c5278c7e0 --- /dev/null +++ b/basic/source/runtime/wnt-mingw.s @@ -0,0 +1,97 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: wnt.asm,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY# without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# Anmerkungen +# Direktaufruf von C- und PASCAL-Routinen, Windows und OS/2 +# +# Inhalt: +# type = CallXXX (far *pProc, char *pStack, short nStack) +# +# Kopie des Basic-Stacks (nStack Bytes) auf den C-Stack +# und Aufruf der Prozedur. + + .intel_syntax + #.386 + +#_TEXT SEGMENT DWORD PUBLIC 'CODE' USE32 + + #ASSUME CS:_TEXT + +.globl _CallINT +.globl _CallLNG +.globl _CallDBL +.globl _CallSTR +.globl _CallFIX + +_CallINT: +_CallLNG: +_CallDBL: +_CallSTR: + +_CallFIX: PUSH EBP + MOV EBP,ESP + PUSH ESI + PUSH EDI + + PUSH ECX + PUSH EDX + + MOV DX,DS + MOVZX EAX,WORD PTR [EBP+16] # EAX == nStack + SUB ESP,EAX # Stack um nStack Bytes vergroessern + MOV EDI,ESP + MOV AX,SS + MOV ES,AX # ES:EDI = Startadresse des fuer + # Parameter reservierten Stackbereichs + MOV ESI,[EBP+12] # DS:ESI == pStack + + MOVZX ECX,WORD PTR [EBP+16] # ECX == nStack + SHR ECX,1 + CLD + JCXZ $1 + REP MOVSW # Stack uebernehmen +$1: MOV DS,DX + CALL DWORD PTR [EBP+8] # Aufruf der Prozedur + # CLI # unter NT nicht erlaubt (privileged instruction) + MOV ESP,EBP + SUB ESP,16 # wegen gepushter Register + # (ESI, EDI) + # STI + POP EDX + POP ECX + POP EDI + POP ESI + POP EBP + RET 12 + +#_TEXT ENDS + + #END diff --git a/basic/source/runtime/wnt.asm b/basic/source/runtime/wnt.asm new file mode 100644 index 000000000000..b4d1bd15d2ed --- /dev/null +++ b/basic/source/runtime/wnt.asm @@ -0,0 +1,96 @@ +;************************************************************************* +; +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; Copyright 2008 by Sun Microsystems, Inc. +; +; OpenOffice.org - a multi-platform office productivity suite +; +; $RCSfile: wnt.asm,v $ +; +; $Revision: 1.4 $ +; +; This file is part of OpenOffice.org. +; +; OpenOffice.org is free software: you can redistribute it and/or modify +; it under the terms of the GNU Lesser General Public License version 3 +; only, as published by the Free Software Foundation. +; +; OpenOffice.org is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU Lesser General Public License version 3 for more details +; (a copy is included in the LICENSE file that accompanied this code). +; +; You should have received a copy of the GNU Lesser General Public License +; version 3 along with OpenOffice.org. If not, see +; <http://www.openoffice.org/license.html> +; for a copy of the LGPLv3 License. +; +;************************************************************************* + +; Anmerkungen +; Direktaufruf von C- und PASCAL-Routinen, Windows und OS/2 +; +; Inhalt: +; type = CallXXX (far *pProc, char *pStack, short nStack) +; +; Kopie des Basic-Stacks (nStack Bytes) auf den C-Stack +; und Aufruf der Prozedur. + + .386 + +_TEXT SEGMENT DWORD PUBLIC 'CODE' USE32 + + ASSUME CS:_TEXT + + PUBLIC _CallINT@12 + PUBLIC _CallLNG@12 + PUBLIC _CallDBL@12 + PUBLIC _CallSTR@12 + PUBLIC _CallFIX@12 + +_CallINT@12 LABEL byte +_CallLNG@12 LABEL byte +_CallDBL@12 LABEL byte +_CallSTR@12 LABEL byte + +_CallFIX@12: PUSH EBP + MOV EBP,ESP + PUSH ESI + PUSH EDI + + PUSH ECX + PUSH EDX + + MOV DX,DS + MOVZX EAX,WORD PTR [EBP+16] ; EAX == nStack + SUB ESP,EAX ; Stack um nStack Bytes vergroessern + MOV EDI,ESP + MOV AX,SS + MOV ES,AX ; ES:EDI = Startadresse des fuer + ; Parameter reservierten Stackbereichs + MOV ESI,[EBP+12] ; DS:ESI == pStack + + MOVZX ECX,WORD PTR [EBP+16] ; ECX == nStack + SHR ECX,1 + CLD + JCXZ $1 + REP MOVSW ; Stack uebernehmen +$1: MOV DS,DX + CALL DWORD PTR [EBP+8] ; Aufruf der Prozedur + ; CLI ; unter NT nicht erlaubt (privileged instruction) + MOV ESP,EBP + SUB ESP,16 ; wegen gepushter Register + ; (ESI, EDI) + ; STI + POP EDX + POP ECX + POP EDI + POP ESI + POP EBP + RET 12 + +_TEXT ENDS + + END diff --git a/basic/source/sample/collelem.cxx b/basic/source/sample/collelem.cxx new file mode 100644 index 000000000000..36d09480af8b --- /dev/null +++ b/basic/source/sample/collelem.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: collelem.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <vcl/msgbox.hxx> +#include <basic/sbx.hxx> +#include "collelem.hxx" + +// Das Sample-Element ist ein kleines Objekt, das die Properties +// Name und Value enth„lt sowie die Methode Say, die den bergebenen +// Text mit dem eigenen Namen verkoppelt und ausgibt. + +SampleElement::SampleElement( const String& r ) : SbxObject( r ) +{ + // Methode Say mit einem String-Parameter + SbxVariable* pMeth = Make( String( RTL_CONSTASCII_USTRINGPARAM("Say") ), SbxCLASS_METHOD, SbxEMPTY ); + pMeth->SetUserData( 0x12345678 ); + pMeth->ResetFlag( SBX_FIXED ); + SbxInfo* pInfo_ = new SbxInfo; + pInfo_->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("text") ), SbxSTRING, SBX_READ ); + pMeth->SetInfo( pInfo_ ); +} + +void SampleElement::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pPar_ = pVar->GetParameters(); + ULONG t = pHint->GetId(); + if( t == SBX_HINT_DATAWANTED && pVar->GetUserData() == 0x12345678 ) + { + // Die Say-Methode: + // 1 Parameter + Returnwert + if( !pPar_ || pPar_->Count() != 2 ) + SetError( SbxERR_WRONG_ARGS ); + else + { + String s( GetName() ); + s.AppendAscii( " says: " ); + s += pPar_->Get( 1 )->GetString(); + pPar_->Get( 0 )->SetType(SbxSTRING); + pPar_->Get( 0 )->PutString( s ); + InfoBox( NULL, s ).Execute(); + } + return; + } + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + diff --git a/basic/source/sample/makefile.mk b/basic/source/sample/makefile.mk new file mode 100644 index 000000000000..f1802b0e75dc --- /dev/null +++ b/basic/source/sample/makefile.mk @@ -0,0 +1,62 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=sample + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +# --- Allgemein ------------------------------------------------------------ + +CXXFILES = \ + object.cxx \ + collelem.cxx + + +OBJFILES = \ + $(OBJ)$/object.obj \ + $(OBJ)$/collelem.obj + + +LIBTARGET = NO + +LIB1TARGET=$(LB)$/sample.lib +LIB1ARCHIV=$(LB)$/libsample.a + +LIB1OBJFILES = $(OBJFILES) + +# --- Targets ------------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/basic/source/sample/object.cxx b/basic/source/sample/object.cxx new file mode 100644 index 000000000000..55c804f9a6ba --- /dev/null +++ b/basic/source/sample/object.cxx @@ -0,0 +1,281 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: object.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbxobj.hxx> +#include <basic/sbx.hxx> +#ifndef __SBX_SBXVARIABLE_HXX //autogen +#include <basic/sbxvar.hxx> +#endif +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif + +#include "object.hxx" +#include "collelem.hxx" + +// Das Sample-Objekt hat folgende Elemente: +// 1) Properties: +// Name der Name +// Value ein double-Wert, beide bereits als Default drin +// 2) Methoden: +// Create Erzeugen eines neuen Unterelements +// Display Ausgabe eines Textes +// Square Argument * Argument +// Event Aufruf eines Basic-Eventhandlers +// 3) Unterobjekte: +// Per Create() kann ein neues Unterelement eingerichtet werden, +// das indiziert werden kann, falls mehrere Objekte gleichen Namens +// existieren. +// Diese Implementation ist ein Beispiel fuer eine tabellengesteuerte +// Version, die sehr viele Elemente enthalten kann. Die Elemente werden +// je nach Bedarf aus der Tabelle in das Objekt uebernommen. +// Die Collection findet sich in COLLECTN.*, die in der Collection +// enthaltenen Objekte in COLLELEM.* + +// Das Sample-Objekt wird in ..\app\mybasic.cxx wie folgt in StarBASIC +// eingebaut: + +// MyBasic::MyBasic() : StarBASIC() +// { +// AddFactory( new SampleObjectFac() ); +// } + +// Das nArgs-Feld eines Tabelleneintrags ist wie folgt verschluesselt: + +#define _ARGSMASK 0x00FF // Bis zu 255 Argumente +#define _RWMASK 0x0F00 // Maske fuer R/W-Bits +#define _TYPEMASK 0xF000 // Maske fuer den Typ des Eintrags + +#define _READ 0x0100 // kann gelesen werden +#define _BWRITE 0x0200 // kann as Lvalue verwendet werden +#define _LVALUE _BWRITE // kann as Lvalue verwendet werden +#define _READWRITE 0x0300 // beides +#define _OPT 0x0400 // TRUE: optionaler Parameter +#define _METHOD 0x1000 // Masken-Bit fuer eine Methode +#define _PROPERTY 0x2000 // Masken-Bit fuer eine Property +#define _COLL 0x4000 // Masken-Bit fuer eine Collection + // Kombination von oberen Bits: +#define _FUNCTION 0x1100 // Maske fuer Function +#define _LFUNCTION 0x1300 // Maske fuer Function, die auch als Lvalue geht +#define _ROPROP 0x2100 // Maske Read Only-Property +#define _WOPROP 0x2200 // Maske Write Only-Property +#define _RWPROP 0x2300 // Maske Read/Write-Property +#define _COLLPROP 0x4100 // Maske Read-Collection-Element + +#define COLLNAME "Elements" // Name der Collection, hier mal hart verdrahtet + +SampleObject::Methods SampleObject::aMethods[] = { +// Eine Sample-Methode (der Returnwert ist SbxNULL) +{ "Display", SbxEMPTY, &SampleObject::Display, 1 | _FUNCTION }, + // Ein Named Parameter + { "message", SbxSTRING, NULL, 0 }, +// Eine Sample-Funktion +{ "Square", SbxDOUBLE, &SampleObject::Square, 1 | _FUNCTION }, + // Ein Named Parameter + { "value", SbxDOUBLE, NULL, 0 }, +// Basic-Callback +{ "Event", SbxEMPTY, &SampleObject::Event, 1 | _FUNCTION }, + // Ein Named Parameter + { "event", SbxSTRING, NULL, 0 }, +// Element erzeugen +{ "Create", SbxEMPTY, &SampleObject::Create, 1 | _FUNCTION }, + // Ein Named Parameter + { "name", SbxSTRING, NULL, 0 }, + +{ NULL, SbxNULL, NULL, -1 }}; // Tabellenende + +SampleObject::SampleObject( const String& rClass ) : SbxObject( rClass ) +{ + SetName( String( RTL_CONSTASCII_USTRINGPARAM("Sample") ) ); + PutDouble( 1.0 ); // Startwert fuer Value +} + +// Suche nach einem Element: +// Hier wird linear durch die Methodentabelle gegangen, bis eine +// passende Methode gefunden wurde. +// Wenn die Methode/Property nicht gefunden wurde, nur NULL ohne +// Fehlercode zurueckliefern, da so auch eine ganze Chain von +// Objekten nach der Methode/Property befragt werden kann. + +SbxVariable* SampleObject::Find( const String& rName, SbxClassType t ) +{ + // Ist das Element bereits vorhanden? + SbxVariable* pRes = SbxObject::Find( rName, t ); + if( !pRes && t != SbxCLASS_OBJECT ) + { + // sonst suchen + Methods* p = aMethods; + short nIndex = 0; + BOOL bFound = FALSE; + while( p->nArgs != -1 ) + { + if( rName.EqualsIgnoreCaseAscii( p->pName ) ) + { + bFound = TRUE; break; + } + nIndex += ( p->nArgs & _ARGSMASK ) + 1; + p = aMethods + nIndex; + } + if( bFound ) + { + // Args-Felder isolieren: + short nAccess = ( p->nArgs & _RWMASK ) >> 8; + short nType = ( p->nArgs & _TYPEMASK ); + String aName_ = String::CreateFromAscii( p->pName ); + SbxClassType eCT = SbxCLASS_OBJECT; + if( nType & _PROPERTY ) + eCT = SbxCLASS_PROPERTY; + else if( nType & _METHOD ) + eCT = SbxCLASS_METHOD; + pRes = Make( aName_, eCT, p->eType ); + // Wir setzen den Array-Index + 1, da ja noch andere + // Standard-Properties existieren, die auch aktiviert + // werden muessen. + pRes->SetUserData( nIndex + 1 ); + pRes->SetFlags( nAccess ); + } + } + return pRes; +} + +// Aktivierung eines Elements oder Anfordern eines Infoblocks + +void SampleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCT, + const SfxHint& rHint, const TypeId& rHT ) +{ + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbxArray* pPar_ = pVar->GetParameters(); + USHORT nIndex = (USHORT) pVar->GetUserData(); + // kein Index: weiterreichen! + if( nIndex ) + { + ULONG t = pHint->GetId(); + if( t == SBX_HINT_INFOWANTED ) + pVar->SetInfo( GetInfo( (short) pVar->GetUserData() ) ); + else + { + BOOL bWrite = FALSE; + if( t == SBX_HINT_DATACHANGED ) + bWrite = TRUE; + if( t == SBX_HINT_DATAWANTED || bWrite ) + { + // Parameter-Test fuer Methoden: + USHORT nPar = aMethods[ --nIndex ].nArgs & 0x00FF; + // Element 0 ist der Returnwert + if( ( !pPar_ && nPar ) + || ( pPar_->Count() != nPar+1 ) ) + SetError( SbxERR_WRONG_ARGS ); + // Alles klar, man kann den Call ausfuehren + else + { + (this->*(aMethods[ nIndex ].pFunc))( pVar, pPar_, bWrite ); + } + } + } + } + SbxObject::SFX_NOTIFY( rBC, rBCT, rHint, rHT ); + } +} + +// Zusammenbau der Infostruktur fuer einzelne Elemente + +SbxInfo* SampleObject::GetInfo( short nIdx ) +{ + Methods* p = &aMethods[ nIdx ]; + // Wenn mal eine Hilfedatei zur Verfuegung steht: + // SbxInfo* pInfo_ = new SbxInfo( Hilfedateiname, p->nHelpId ); + SbxInfo* pInfo_ = new SbxInfo; + short nPar = p->nArgs & _ARGSMASK; + for( short i = 0; i < nPar; i++ ) + { + p++; + String aName_ = String::CreateFromAscii( p->pName ); + USHORT nFlags_ = ( p->nArgs >> 8 ) & 0x03; + if( p->nArgs & _OPT ) + nFlags_ |= SBX_OPTIONAL; + pInfo_->AddParam( aName_, p->eType, nFlags_ ); + } + return pInfo_; +} + +//////////////////////////////////////////////////////////////////////////// + +// Properties und Methoden legen beim Get (bPut = FALSE) den Returnwert +// im Element 0 des Argv ab; beim Put (bPut = TRUE) wird der Wert aus +// Element 0 gespeichert. + +// Die Methoden: + +void SampleObject::Display( SbxVariable*, SbxArray* pPar_, BOOL ) +{ + // GetString() loest u.U. auch einen Error aus! + String s( pPar_->Get( 1 )->GetString() ); + if( !IsError() ) + InfoBox( NULL, s ).Execute(); +} + +void SampleObject::Square( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + double n = pPar_->Get( 1 )->GetDouble(); + pVar->PutDouble( n * n ); +} + +// Callback nach BASIC: + +void SampleObject::Event( SbxVariable*, SbxArray* pPar_, BOOL ) +{ + Call( pPar_->Get( 1 )->GetString(), NULL ); +} + +// Neues Element anlegen + +void SampleObject::Create( SbxVariable* pVar, SbxArray* pPar_, BOOL ) +{ + pVar->PutObject( + MakeObject( pPar_->Get( 1 )->GetString(), String( RTL_CONSTASCII_USTRINGPARAM("SampleElement") ) ) ); +} + +// Die Factory legt unsere beiden Objekte an. + +SbxObject* SampleObjectFac::CreateObject( const String& rClass ) +{ + if( rClass.EqualsIgnoreCaseAscii( "SampleObject" ) ) + return new SampleObject( rClass ); + if( rClass.EqualsIgnoreCaseAscii( "SampleElement" ) ) + return new SampleElement( rClass ); + return NULL; +} + diff --git a/basic/source/sample/sample.bas b/basic/source/sample/sample.bas new file mode 100644 index 000000000000..d0e416871af0 --- /dev/null +++ b/basic/source/sample/sample.bas @@ -0,0 +1,39 @@ +' Sample-Programm fuer Sample-Objekte + +Sub Main + Dim Sample As SampleObject + Dim Element1 As Object, Element2 As Object + Set Element1 = Sample!Create "Objekt" + Set Element2 = Sample.Create "Objekt" + Element1 = "Element 1" + Element2 = "Element 2" + For i = 0 to 1 + Print Sample.Objekt( i ) + Next + 'Test der Event-Methode im Sample-Objekt + Sample.Event "Bang" +End Sub + +Sub Bang + print "Sample-Callback: BANG!" +End Sub + + + + + + + + + + + + + + + + + + + + diff --git a/basic/source/sbx/format.src b/basic/source/sbx/format.src new file mode 100644 index 000000000000..8609bbc875b3 --- /dev/null +++ b/basic/source/sbx/format.src @@ -0,0 +1,88 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: format.src,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "svtools/svtools.hrc" + +String STR_BASICKEY_FORMAT_ON +{ + Text [ en-US ] = "On" ; +}; +String STR_BASICKEY_FORMAT_OFF +{ + Text [ en-US ] = "Off" ; +}; +String STR_BASICKEY_FORMAT_TRUE +{ + Text [ en-US ] = "True" ; +}; +String STR_BASICKEY_FORMAT_FALSE +{ + Text [ en-US ] = "False" ; +}; +String STR_BASICKEY_FORMAT_YES +{ + Text [ en-US ] = "Yes" ; +}; +String STR_BASICKEY_FORMAT_NO +{ + Text [ en-US ] = "No" ; +}; +String STR_BASICKEY_FORMAT_CURRENCY +{ + Text [ en-US ] = "@0.00 $;@(0.00 $)" ; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/basic/source/sbx/makefile.mk b/basic/source/sbx/makefile.mk new file mode 100644 index 000000000000..357ce64df6ec --- /dev/null +++ b/basic/source/sbx/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=sbx + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + + +# --- Allgemein ----------------------------------------------------------- + +SRS1NAME=$(TARGET) +SRC1FILES= format.src + +SLOFILES= \ + $(SLO)$/sbxbase.obj \ + $(SLO)$/sbxres.obj \ + $(SLO)$/sbxvalue.obj \ + $(SLO)$/sbxvals.obj \ + $(SLO)$/sbxvar.obj \ + $(SLO)$/sbxarray.obj \ + $(SLO)$/sbxobj.obj \ + $(SLO)$/sbxcoll.obj \ + $(SLO)$/sbxexec.obj \ + $(SLO)$/sbxint.obj \ + $(SLO)$/sbxlng.obj \ + $(SLO)$/sbxsng.obj \ + $(SLO)$/sbxmstrm.obj \ + $(SLO)$/sbxdbl.obj \ + $(SLO)$/sbxcurr.obj \ + $(SLO)$/sbxdate.obj \ + $(SLO)$/sbxstr.obj \ + $(SLO)$/sbxbool.obj \ + $(SLO)$/sbxchar.obj \ + $(SLO)$/sbxbyte.obj \ + $(SLO)$/sbxuint.obj \ + $(SLO)$/sbxulng.obj \ + $(SLO)$/sbxform.obj \ + $(SLO)$/sbxscan.obj \ + $(SLO)$/sbxdec.obj + + +EXCEPTIONSFILES=$(SLO)$/sbxarray.obj + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + + diff --git a/basic/source/sbx/sbxarray.cxx b/basic/source/sbx/sbxarray.cxx new file mode 100644 index 000000000000..9b3a87348d5b --- /dev/null +++ b/basic/source/sbx/sbxarray.cxx @@ -0,0 +1,860 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxarray.cxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <basic/sbx.hxx> +#include "runtime.hxx" +#include <vector> +using namespace std; + +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]; + const SbxVariable* pSrc_ = *pSrcRef; + if( !pSrc_ ) + continue; + SbxVarEntryPtr pDstRef = new SbxVarEntry; + *((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef); + if( pSrcRef->pAlias ) + pDstRef->pAlias = new XubString( *pSrcRef->pAlias ); + 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 ); +#ifdef DBG_UTIL + else + DBG_CHKOBJ( rRef, SbxBase, 0 ); +#endif + + 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 ); +#ifdef DBG_UTIL + else + DBG_CHKOBJ( rRef, SbxBase, 0 ); +#endif + + 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 ); + } + } +} + +const XubString& SbxArray::GetAlias( USHORT nIdx ) +{ + if( !CanRead() ) + { + SetError( SbxERR_PROP_WRITEONLY ); + return String::EmptyString(); + } + SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx ); + + if ( !rRef.pAlias ) + return String::EmptyString(); +#ifdef DBG_UTIL + else + DBG_CHKOBJ( rRef, SbxBase, 0 ); +#endif + + return *rRef.pAlias; +} + +void SbxArray::PutAlias( const XubString& rAlias, USHORT nIdx ) +{ + if( !CanWrite() ) + SetError( SbxERR_PROP_READONLY ); + else + { + SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx ); + if( !rRef.pAlias ) + rRef.pAlias = new XubString( rAlias ); + else + *rRef.pAlias = rAlias; + } +} + +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 ), mbHasFixedSize( false ) +{ + 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; + } + this->mbHasFixedSize = rArray.mbHasFixedSize; + } + 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; +} + +SbxVariableRef& SbxDimArray::GetRef( const short* pIdx ) +{ + return SbxArray::GetRef( Offset( pIdx ) ); +} + +SbxVariable* SbxDimArray::Get( const short* pIdx ) +{ + return SbxArray::Get( Offset( pIdx ) ); +} + +void SbxDimArray::Put( SbxVariable* p, const short* pIdx ) +{ + SbxArray::Put( p, Offset( pIdx ) ); +} + +SbxVariableRef& SbxDimArray::GetRef32( const INT32* pIdx ) +{ + return SbxArray::GetRef32( Offset32( 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 || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) ) + { + 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; +} + +USHORT SbxDimArray::Offset( SbxArray* pPar ) +{ + UINT32 nPos = Offset32( pPar ); + if( nPos > (long) SBX_MAXINDEX ) + { + SetError( SbxERR_BOUNDS ); nPos = 0; + } + return (USHORT) nPos; +} + +SbxVariableRef& SbxDimArray::GetRef( SbxArray* pPar ) +{ + return SbxArray::GetRef32( Offset32( pPar ) ); +} + +SbxVariable* SbxDimArray::Get( SbxArray* pPar ) +{ + return SbxArray::Get32( Offset32( pPar ) ); +} + +void SbxDimArray::Put( SbxVariable* p, SbxArray* pPar ) +{ + SbxArray::Put32( p, 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 ); +} + diff --git a/basic/source/sbx/sbxbase.cxx b/basic/source/sbx/sbxbase.cxx new file mode 100644 index 000000000000..2000e2d02f3e --- /dev/null +++ b/basic/source/sbx/sbxbase.cxx @@ -0,0 +1,465 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxbase.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include <tools/shl.hxx> +#include <tools/stream.hxx> + +#include <basic/sbx.hxx> +#include <basic/sbxfac.hxx> +#include <basic/sbxbase.hxx> + +// 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() +{ +#ifndef DOS + SbxAppData** ppData = (SbxAppData**) ::GetAppData( SHL_SBX ); + SbxAppData* p = *ppData; + if( !p ) + p = *ppData = new SbxAppData; + return p; +#else + SbxAppData** ppData; + SbxAppData* p; + p = *ppData = new SbxAppData; + return p; +#endif +} + +SbxAppData::~SbxAppData() +{ + if( pBasicFormater ) + delete pBasicFormater; +} + + +//////////////////////////////// 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() +void SbxBase::StaticEnableBroadcasting( BOOL bEnable ) +{ + bStaticEnableBroadcasting = bEnable; +} + +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() ); +} + +void SbxInfo::AddParam( const SbxParamInfo& r ) +{ + const SbxParamInfo* p = new SbxParamInfo + ( r.aName, r.eType, r.nFlags, r.aTypeRef ); + aParams.Insert( p, aParams.Count() ); +} + +const SbxParamInfo* SbxInfo::GetParam( USHORT n ) const +{ + if( n < 1 || n > aParams.Count() ) + return NULL; + else + return aParams.GetObject( n-1 ); +} + +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; +} + diff --git a/basic/source/sbx/sbxbool.cxx b/basic/source/sbx/sbxbool.cxx new file mode 100644 index 000000000000..f0ee0e2b3966 --- /dev/null +++ b/basic/source/sbx/sbxbool.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxbool.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" +#include "sbxres.hxx" + +// AB 29.10.99 Unicode +#ifndef _USE_NO_NAMESPACE +using namespace rtl; +#endif + +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 ); + } +} + diff --git a/basic/source/sbx/sbxbyte.cxx b/basic/source/sbx/sbxbyte.cxx new file mode 100644 index 000000000000..fe7a6308d49d --- /dev/null +++ b/basic/source/sbx/sbxbyte.cxx @@ -0,0 +1,332 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxbyte.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +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 ); + } +} + diff --git a/basic/source/sbx/sbxchar.cxx b/basic/source/sbx/sbxchar.cxx new file mode 100644 index 000000000000..974062de25b1 --- /dev/null +++ b/basic/source/sbx/sbxchar.cxx @@ -0,0 +1,328 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxchar.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +// AB 29.10.99 Unicode +#ifndef _USE_NO_NAMESPACE +using namespace rtl; +#endif + +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 ); + } +} + + diff --git a/basic/source/sbx/sbxcoll.cxx b/basic/source/sbx/sbxcoll.cxx new file mode 100644 index 000000000000..2f7f0dc52f83 --- /dev/null +++ b/basic/source/sbx/sbxcoll.cxx @@ -0,0 +1,304 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxcoll.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include <tools/stream.hxx> + +#include <basic/sbx.hxx> +#include "sbxres.hxx" + +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; +} + diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx new file mode 100644 index 000000000000..55eaa8c96054 --- /dev/null +++ b/basic/source/sbx/sbxconv.hxx @@ -0,0 +1,154 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxconv.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SBXCONV_HXX +#define _SBXCONV_HXX + +#include "sbxdec.hxx" + +class SbxArray; + +// 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 ); + +// mit erweiterter Auswertung (International, "TRUE"/"FALSE") +extern BOOL ImpConvStringExt( String& rSrc, SbxDataType eTargetType ); + +// 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 ); + +// ByteArry <--> String +SbxArray* StringToByteArray(const String& rStr); +String ByteArrayToString(SbxArray* pArr); + +#endif diff --git a/basic/source/sbx/sbxcurr.cxx b/basic/source/sbx/sbxcurr.cxx new file mode 100644 index 000000000000..eeba9ced2849 --- /dev/null +++ b/basic/source/sbx/sbxcurr.cxx @@ -0,0 +1,398 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxcurr.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <basic/sbx.hxx> +#include <tools/errcode.hxx> + +#define _TLBIGINT_INT64 +#include <tools/bigint.hxx> + +#include <basic/sbxvar.hxx> +#include "sbxconv.hxx" + +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( 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; + aBig.INT64( &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; +} + diff --git a/basic/source/sbx/sbxdate.cxx b/basic/source/sbx/sbxdate.cxx new file mode 100644 index 000000000000..c6862a88a56c --- /dev/null +++ b/basic/source/sbx/sbxdate.cxx @@ -0,0 +1,415 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxdate.cxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <vcl/svapp.hxx> +#include <svtools/zforlist.hxx> +#include <tools/errcode.hxx> +#include <tools/color.hxx> +#include <i18npool/lang.h> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" +#include "math.h" +#include <comphelper/processfactory.hxx> + + +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 ); + } +} + diff --git a/basic/source/sbx/sbxdbl.cxx b/basic/source/sbx/sbxdbl.cxx new file mode 100644 index 000000000000..f7fdb3f0b33f --- /dev/null +++ b/basic/source/sbx/sbxdbl.cxx @@ -0,0 +1,309 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxdbl.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" +#include "runtime.hxx" + +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; + if ( SbiRuntime::isVBAEnabled() )// VBA only behaviour + SbxBase::SetError( SbxERR_CONVERSION ); + } + else + { + double d; + SbxDataType t; + if( ImpScan( *p->pString, d, t, NULL ) != SbxERR_OK ) + { + nRes = 0; + if ( SbiRuntime::isVBAEnabled() )// VBA only behaviour + SbxBase::SetError( SbxERR_CONVERSION ); + } + 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 ); + } +} + diff --git a/basic/source/sbx/sbxdec.cxx b/basic/source/sbx/sbxdec.cxx new file mode 100644 index 000000000000..f61051397ab8 --- /dev/null +++ b/basic/source/sbx/sbxdec.cxx @@ -0,0 +1,800 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxdec.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> + +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +#include <com/sun/star/bridge/oleautomation/Decimal.hpp> + + +// int GnDecCounter = 0; + +// Implementation SbxDecimal +SbxDecimal::SbxDecimal( void ) +{ + setInt( 0 ); + mnRefCount = 0; + // GnDecCounter++; +} + +SbxDecimal::SbxDecimal( const SbxDecimal& rDec ) +{ +#ifdef WIN32 + maDec = rDec.maDec; +#else + (void)rDec; +#endif + mnRefCount = 0; + // GnDecCounter++; +} + +SbxDecimal::SbxDecimal + ( const com::sun::star::bridge::oleautomation::Decimal& rAutomationDec ) +{ +#ifdef WIN32 + maDec.scale = rAutomationDec.Scale; + maDec.sign = rAutomationDec.Sign; + maDec.Lo32 = rAutomationDec.LowValue; + maDec.Mid32 = rAutomationDec.MiddleValue; + maDec.Hi32 = rAutomationDec.HighValue; +#else + (void)rAutomationDec; +#endif + mnRefCount = 0; + // GnDecCounter++; +} + +void SbxDecimal::fillAutomationDecimal + ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec ) +{ +#ifdef WIN32 + rAutomationDec.Scale = maDec.scale; + rAutomationDec.Sign = maDec.sign; + rAutomationDec.LowValue = maDec.Lo32; + rAutomationDec.MiddleValue = maDec.Mid32; + rAutomationDec.HighValue = maDec.Hi32; +#else + (void)rAutomationDec; +#endif +} + +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::getByte( BYTE& rVal ) +{ + bool bRet = ( VarUI1FromDec( &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::getInt( int& rVal ) +{ + INT32 TmpVal; + bool bRet = getLong( TmpVal ); + rVal = TmpVal; + 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::setShort( INT16 val ) { (void)val; } +void SbxDecimal::setLong( INT32 val ) { (void)val; } +void SbxDecimal::setUShort( UINT16 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::setString( String* pString ) { (void)pString; return false; } + +bool SbxDecimal::getChar( sal_Unicode& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getByte( BYTE& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getShort( INT16& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getLong( INT32& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getUShort( UINT16& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getULong( UINT32& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getSingle( float& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getDouble( double& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getInt( int& rVal ) { (void)rVal; return false; } +bool SbxDecimal::getUInt( unsigned int& rVal ) { (void)rVal; return false; } + +#endif + +bool SbxDecimal::getString( String& rString ) +{ +#ifdef WIN32 + 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; +#else + (void)rString; + return false; +#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 +} + diff --git a/basic/source/sbx/sbxdec.hxx b/basic/source/sbx/sbxdec.hxx new file mode 100644 index 000000000000..3570830cdf70 --- /dev/null +++ b/basic/source/sbx/sbxdec.hxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxdec.hxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef __SBX_SBX_DEC_HXX +#define __SBX_SBX_DEC_HXX + +#ifdef WIN32 + +#undef WB_LEFT +#undef WB_RIGHT +#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 <basic/sbx.hxx> + +#include <com/sun/star/bridge/oleautomation/Decimal.hpp> + + +// Decimal support +// Implementation only for windows + +class SbxDecimal +{ + friend void releaseDecimalPtr( SbxDecimal*& rpDecimal ); + +#ifdef WIN32 + DECIMAL maDec; +#endif + INT32 mnRefCount; + +public: + SbxDecimal( void ); + SbxDecimal( const SbxDecimal& rDec ); + SbxDecimal( const com::sun::star::bridge::oleautomation::Decimal& rAutomationDec ); + + ~SbxDecimal(); + + void addRef( void ) + { mnRefCount++; } + + void fillAutomationDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec ); + + void setChar( sal_Unicode val ); + void setByte( BYTE val ); + void setShort( INT16 val ); + void setLong( INT32 val ); + void setUShort( UINT16 val ); + void setULong( UINT32 val ); + bool setSingle( float val ); + bool setDouble( double val ); + void setInt( int val ); + void setUInt( unsigned int val ); + bool setString( String* pString ); + void setDecimal( SbxDecimal* pDecimal ) + { +#ifdef WIN32 + if( pDecimal ) + maDec = pDecimal->maDec; +#else + (void)pDecimal; +#endif + } + + bool getChar( sal_Unicode& rVal ); + bool getByte( BYTE& rVal ); + bool getShort( INT16& rVal ); + bool getLong( INT32& rVal ); + bool getUShort( UINT16& rVal ); + bool getULong( UINT32& rVal ); + bool getSingle( float& rVal ); + bool getDouble( double& rVal ); + bool getInt( int& rVal ); + bool getUInt( unsigned int& rVal ); + bool getString( String& rString ); + + 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 ); +}; + diff --git a/basic/source/sbx/sbxexec.cxx b/basic/source/sbx/sbxexec.cxx new file mode 100644 index 000000000000..5a5ba02d6da1 --- /dev/null +++ b/basic/source/sbx/sbxexec.cxx @@ -0,0 +1,404 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxexec.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#ifndef _APP_HXX //autogen +#include <vcl/svapp.hxx> +#endif +#include <basic/sbx.hxx> + + +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; +} + diff --git a/basic/source/sbx/sbxform.cxx b/basic/source/sbx/sbxform.cxx new file mode 100644 index 000000000000..9df7e0430719 --- /dev/null +++ b/basic/source/sbx/sbxform.cxx @@ -0,0 +1,1171 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxform.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include <stdlib.h> + +#include <basic/sbxform.hxx> + +/* +TODO: gibt es noch irgend welche Star-Basic Besonderheiten ? + + was bedeutet: * als Platzhalter + +BEMERKUNG: Visual-Basic behandelt folgende (ung"ultige) Format-Strings + wie angezeigt: + + ##0##.##0## --> ##000.000## + + (diese Klasse verh"alt sich genau so). +*/ + +#include <stdio.h> // f"ur: sprintf() +#include <float.h> // f"ur: DBL_DIG, DBL_EPSILON +#include <math.h> // f"ur: floor(), fabs(), log10(), pow() + +//================================================================= +//=========================== DEFINES ============================= +//================================================================= + +#define _NO_DIGIT -1 + +#define MAX_NO_OF_EXP_DIGITS 5 + // +4 wegen dem Wertebereich: zwischen -308 und +308 + // +1 f"ur abschliessende 0 +#define MAX_NO_OF_DIGITS DBL_DIG +#define MAX_DOUBLE_BUFFER_LENGTH MAX_NO_OF_DIGITS + 9 + // +1 f"ur Vorzeichen + // +1 f"ur Ziffer vor dem Dezimal-Punkt + // +1 f"ur Dezimal-Punkt + // +2 f"ur Exponent E und Exp. Vorzeichen + // +3 f"ur den Wert des Exponenten + // +1 f"ur abschliessende 0 + +// Defines f"ur die Ziffern: +#define ASCII_0 '0' // 48 +#define ASCII_9 '9' // 57 + +#define CREATE_1000SEP_CHAR '@' + +#define FORMAT_SEPARATOR ';' + +// vordefinierte Formate f"ur den Format$()-Befehl: +#define BASICFORMAT_GENERALNUMBER "General Number" +#define BASICFORMAT_CURRENCY "Currency" +#define BASICFORMAT_FIXED "Fixed" +#define BASICFORMAT_STANDARD "Standard" +#define BASICFORMAT_PERCENT "Percent" +#define BASICFORMAT_SCIENTIFIC "Scientific" +#define BASICFORMAT_YESNO "Yes/No" +#define BASICFORMAT_TRUEFALSE "True/False" +#define BASICFORMAT_ONOFF "On/Off" + +#define EMPTYFORMATSTRING "" + +// Bem.: Visual-Basic hat bei Floating-Point-Zahlen maximal 12 Stellen +// nach dem Dezimal-Punkt. +// Alle Format-Strings sind kompatibel zu Visual-Basic: +#define GENERALNUMBER_FORMAT "0.############" + // max. 12 Stellen in Visual-Basic ! +#define CURRENCY_FORMAT "@$0.00;@($0.00)" +#define FIXED_FORMAT "0.00" +#define STANDARD_FORMAT "@0.00" +#define PERCENT_FORMAT "0.00%" +#define SCIENTIFIC_FORMAT "#.00E+00" +// BEMERKUNG: das Zeichen @ bedeutet, das Tausender-Separatoren erzeugt +// weden sollen. Dies ist eine StarBasic 'Erweiterung'. + +//================================================================= + +// zur Bestimmung der Anzahl Stellen in dNumber +double get_number_of_digits( double dNumber ) +//double floor_log10_fabs( double dNumber ) +{ + if( dNumber==0.0 ) + // 0 hat zumindest auch eine Stelle ! + return 0.0; //ehemals 1.0, jetzt 0.0 wegen #40025; + else + return floor( log10( fabs( dNumber ) ) ); +} + +//================================================================= +//======================= IMPLEMENTATION ========================== +//================================================================= + +SbxBasicFormater::SbxBasicFormater( sal_Unicode _cDecPoint, sal_Unicode _cThousandSep, + String _sOnStrg, + String _sOffStrg, + String _sYesStrg, + String _sNoStrg, + String _sTrueStrg, + String _sFalseStrg, + String _sCurrencyStrg, + String _sCurrencyFormatStrg ) +{ + cDecPoint = _cDecPoint; + cThousandSep = _cThousandSep; + sOnStrg = _sOnStrg; + sOffStrg = _sOffStrg; + sYesStrg = _sYesStrg; + sNoStrg = _sNoStrg; + sTrueStrg = _sTrueStrg; + sFalseStrg = _sFalseStrg; + sCurrencyStrg = _sCurrencyStrg; + sCurrencyFormatStrg = _sCurrencyFormatStrg; +} + +// Funktion zur Ausgabe eines Fehler-Textes (zum Debuggen) +/* +void SbxBasicFormater::ShowError( char * sErrMsg ) +{ +// cout << "ERROR in Format$(): " << sErrMsg << endl; +} +*/ +// verschiebt alle Zeichen des Strings, angefangen von der nStartPos, +// um eine Position zu gr"osseren Indizes, d.h. es wird Platz f"ur +// ein neues (einzuf"ugendes) Zeichen geschafft. +// ACHTUNG: der String MUSS gross genug sein ! +inline void SbxBasicFormater::ShiftString( String& sStrg, USHORT nStartPos ) +{ + sStrg.Erase( nStartPos,1 ); +} + +// Funktion um ein Zeichen an einen String anzuh"angen +inline void SbxBasicFormater::StrAppendChar( String& sStrg, sal_Unicode ch ) +{ + sStrg.Insert( ch ); +} + +// h"angt die "ubergebene Ziffer nDigit an den "ubergebenen String sStrg +// an, dabei wird "uberpr"uft ob nDigit eine g"ultige Ziffer ist, +// falls dies nicht der Fall ist, wird nichts gemacht. +void SbxBasicFormater::AppendDigit( String& sStrg, short nDigit ) +{ + if( nDigit>=0 && nDigit<=9 ) + StrAppendChar( sStrg, (sal_Unicode)(nDigit+ASCII_0) ); +} + +// verschiebt den Dezimal-Punkt um eine Stelle nach links +void SbxBasicFormater::LeftShiftDecimalPoint( String& sStrg ) +{ + USHORT nPos = sStrg.Search( cDecPoint ); + + if( nPos!=STRING_NOTFOUND ) + { + // vertausche Dezimal-Punkt + sStrg.SetChar( nPos, sStrg.GetChar( nPos - 1 ) ); + sStrg.SetChar( nPos-1, cDecPoint ); + } +} + +// rundet in einem String die Ziffer an der angegebenen Stelle, +// es wird ein Flag zur"uckgeliefert, falls ein Overflow auftrat, +// d.h. 99.99 --> 100.00, d.h. ein Gr"ossenordung ge"andert wurde +// (geschieht beim Runden einer 9). +void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos, BOOL& bOverflow ) +{ + // wurde ggf ein falscher Index uebergeben --> Aufruf ignorieren + if( nPos<0 ) + return; + + bOverflow = FALSE; + // "uberspringe den Dezimalpunkt und Tausender-Trennzeichen + sal_Unicode c = sStrg.GetChar( nPos ); + if( nPos>0 && (c == cDecPoint || c == cThousandSep) ) + { + StrRoundDigit( sStrg,nPos-1,bOverflow ); + // AENDERUNG ab 9.3.1997: nach rekursivem Call die Methode SOFORT beenden ! + return; + } + // "uberspringe alle nicht-Ziffern: + // BEMERKUNG: + // in einem g"ultigen Format-String sollte die Ausgabe + // der Zahl an einem St"uck geschen, d.h. Sonderzeichen sollten + // NUR vor ODER nach der Zahl stehen und nicht mitten in der + // Format-Angabe f"ur die Zahl + while( nPos>=0 && (sStrg.GetChar( nPos )<ASCII_0 || sStrg.GetChar( nPos )>ASCII_9) ) + nPos--; + // muss ggf. noch Platz f"ur eine weitere (f"uhrende) Ziffer + // geschaffen werden ? + if( nPos==-1 ) + { + ShiftString( sStrg,0 ); + // f"uhrende 1 einf"ugen: z.B. 99.99 f"ur 0.0 + sStrg.SetChar( 0, '1' ); + bOverflow = TRUE; + } + else + { + // ist die zu rundende Position eine Ziffer ? + sal_Unicode c2 = sStrg.GetChar( nPos ); + if( c2 >= ASCII_0 && c2 <= ASCII_9 ) + { + // muss eine 9 gerundet werden? Falls: Ja --> rekursiver Aufruf + if( c2 == ASCII_9 ) + { + sStrg.SetChar( nPos, '0' ); + StrRoundDigit( sStrg,nPos-1,bOverflow ); + } + else + sStrg.SetChar( nPos, c2+1 ); + } + else + { + // --> Nein, d.h. Platz f"ur Ziffer schaffen: z.B. -99.99 f"ur #0.0 + // da gerundet wird MUSS es immer eine g"ultige Position + // nPos+1 geben ! + ShiftString( sStrg,nPos+1 ); + // f"uhrende 1 einf"ugen + sStrg.SetChar( nPos+1, '1' ); + bOverflow = TRUE; + } + } +} + +// rundet in einem String die Ziffer an der angegebenen Stelle +void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos ) +{ + BOOL bOverflow; + + StrRoundDigit( sStrg,nPos,bOverflow ); +} + +// parse den Formatstring von der "ubergebenen Position zur"uck +// und l"osche ggf. "uberf"ussige 0en, z.B. 4.50 in 0.0# +void SbxBasicFormater::ParseBack( String& sStrg, const String& sFormatStrg, + short nFormatPos ) +{ + // WICHTIG: nFormatPos kann auch negativ sein, in diesem Fall Aufruf ignorieren + for( short i=nFormatPos; + i>0 && sFormatStrg.GetChar( i ) == '#' && sStrg.GetChar( (sStrg.Len()-1) ) == '0'; + i-- ) + { sStrg.Erase( sStrg.Len()-1 ); } +} + +#ifdef _with_sprintf + +/* + Bemerkung: + Zahl wird mit maximaler (sinnvollen) Genauigkeit in einen String + umgewandelt (mit sprintf()), dieser String wird dann im Schleifen- + Durchlauf nach der entsprechenden Ziffer durchsucht. +*/ +// initialisiert die Daten der Klasse um einen Scan-Durchlauf durchzuf"uhren +void SbxBasicFormater::InitScan( double _dNum ) +{ + char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ]; + + dNum = _dNum; + InitExp( get_number_of_digits( dNum ) ); + // maximal 15 Nachkomma-Stellen, Format-Beispiel: -1.234000000000000E-001 + /*int nCount =*/ sprintf( sBuffer,"%+22.15lE",dNum ); + sSciNumStrg.AssignAscii( sBuffer ); +} + +void SbxBasicFormater::InitExp( double _dNewExp ) +{ + char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ]; + // bestimme den Exponenten (kann immer GENAU durch int dargestellt werden) + nNumExp = (short)_dNewExp; + // und dessen String + /*int nCount =*/ sprintf( sBuffer,"%+i",nNumExp ); + sNumExpStrg.AssignAscii( sBuffer ); + // bestimme die Anzahl der Stellen im Exponenten + nExpExp = (short)get_number_of_digits( (double)nNumExp ); +} + +// bestimmt die Ziffer an der angegebenen Stelle (gedacht zur Anwendung im +// Scan-Durchlauf) +short SbxBasicFormater::GetDigitAtPosScan( short nPos, BOOL& bFoundFirstDigit ) +{ + // Versuch eine gr"ossere Ziffer zu lesen, + // z.B. Stelle 4 in 1.234, + // oder eine Ziffer ausserhalb der Aufl"osung der + // Zahl (double) zu lesen (z.B. max. 15 Stellen). + if( nPos>nNumExp || abs(nNumExp-nPos)>MAX_NO_OF_DIGITS ) + return _NO_DIGIT; + // bestimme den Index der Stelle in dem Number-String: + // "uberlese das Vorzeichen + USHORT no = 1; + // falls notwendig den Dezimal-Punkt "uberlesen: + if( nPos<nNumExp ) + no++; + no += nNumExp-nPos; + // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen + if( nPos==nNumExp ) + bFoundFirstDigit = TRUE; + return (short)(sSciNumStrg.GetChar( no ) - ASCII_0); +} + +short SbxBasicFormater::GetDigitAtPosExpScan( short nPos, BOOL& bFoundFirstDigit ) +{ + // ist die abgefragte Stelle zu gross f"ur den Exponenten ? + if( nPos>nExpExp ) + return -1; + + // bestimme den Index der Stelle in dem Number-String: + // "uberlese das Vorzeichen + USHORT no = 1; + no += nExpExp-nPos; + // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen + if( nPos==nExpExp ) + bFoundFirstDigit = TRUE; + return (short)(sNumExpStrg.GetChar( no ) - ASCII_0); +} + +// es kann ein Wert f"ur den Exponent angegeben werden, da ggf. die +// Zahl ggf. NICHT normiert (z.B. 1.2345e-03) dargestellt werden soll, +// sondern eventuell 123.345e-3 ! +short SbxBasicFormater::GetDigitAtPosExpScan( double dNewExponent, short nPos, + BOOL& bFoundFirstDigit ) +{ + // neuer Exponent wurde "ubergeben, aktualisiere + // die tempor"aren Klassen-Variablen + InitExp( dNewExponent ); + // und jetzt die Stelle bestimmen + return GetDigitAtPosExpScan( nPos,bFoundFirstDigit ); +} + +#else + +/* Probleme mit der folgenden Methode: + +TODO: ggf einen 'intelligenten' Peek-Parser um Rundungsfehler bei + double-Zahlen herauszufinden ? z.B. f"ur 0.00115 #.#e-000 + + Problem mit: format( 0.3345 , "0.000" ) + Problem mit: format( 0.00115 , "0.0000" ) + +*/ +// liefert die Ziffer an der angegebenen '10er System'-Position, +// d.h. positive nPos f"ur Stellen vor dem Komma und negative +// f"ur Stellen nach dem Komma. +// nPos==0 bedeutet erste Stelle vor dem Komma, also 10^0. +// liefert 0..9 f"ur g"ultige Ziffern und -1 f"ur nicht vorhanden, +// d.h. falls die "ubergebene Zahl zu klein ist +// (z.B. Stelle 5 bei dNumber=123). +// Weiter wird in dNextNumber die um die f"uhrenden Stellen +// (bis nPos) gek"urzte Zahl zur"uckgeliefert, z.B. +// GetDigitAtPos( 3434.565 , 2 , dNewNumber ) --> dNewNumber = 434.565 +// dies kann f"ur Schleifenabarbeitung g"unstiger sein, d.h. +// die Zahlen immer von der gr"ossten Stelle abarbeiten/scanen. +// In bFoundFirstDigit wird ggf. ein Flag gesetzt wenn eine Ziffer +// gefunden wurde, dies wird dazu verwendet um 'Fehler' beim Parsen 202 +// zu vermeiden, die +// +// ACHTUNG: anscheinend gibt es manchmal noch Probleme mit Rundungs-Fehlern! +short SbxBasicFormater::GetDigitAtPos( double dNumber, short nPos, + double& dNextNumber, BOOL& bFoundFirstDigit ) +// ACHTUNG: nPos kann auch negativ werden, f"ur Stellen nach dem Dezimal-Punkt +{ + double dTemp = dNumber; + double dDigit,dPos; + short nMaxDigit; + + // erst mal aus der Zahl eine positive Zahl machen: + dNumber = fabs( dNumber ); + dPos = (double)nPos; + + // "uberpr"ufe ob Zahl zu klein f"ur angegebene Stelle ist + nMaxDigit = (short)get_number_of_digits( dNumber ); + // f"uhrende Ziffern 'l"oschen' + // Bem.: Fehler nur bei Zahlen gr"osser 0, d.h. bei Ziffern vor dem + // Dezimal-Punkt + if( nMaxDigit<nPos && !bFoundFirstDigit && nPos>=0 ) + return _NO_DIGIT; + // Ziffer gefunden, setze Flag: + bFoundFirstDigit = TRUE; + for( short i=nMaxDigit; i>=nPos; i-- ) + { + double dI = (double)i; + double dTemp1 = pow( 10.0,dI ); + // pr"apariere nun die gesuchte Ziffer: + dDigit = floor( pow( 10.0,log10( fabs( dNumber ) )-dI ) ); + dNumber -= dTemp1 * dDigit; + } + // Zuweisung f"ur optimierte Schleifen-Durchl"aufe + dNextNumber = dNumber; + // und zum Schluss noch die float-Rundungsungenauigkeiten heraus filtern + return RoundDigit( dDigit ); +} + +// rundet eine double-Zahl zwischen 0 und 9 auf die genaue +// Integer-Zahl, z.B. 2.8 -> 3 und 2.2 -> 2 +short SbxBasicFormater::RoundDigit( double dNumber ) +{ + // ist der Wertebereich g"ultig ? + if( dNumber<0.0 || dNumber>10.0 ) + return -1; + short nTempHigh = (short)(dNumber+0.5); // ggf. floor( ) + return nTempHigh; +} + +#endif + +// kopiert den entsprechenden Teil des Format-Strings, falls vorhanden, +// und liefert diesen zur"uck. +// Somit wird ein neuer String erzeugt, der vom Aufrufer wieder freigegeben +// werden muss +String SbxBasicFormater::GetPosFormatString( const String& sFormatStrg, BOOL & bFound ) +{ + bFound = FALSE; // default... + USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); + + if( nPos!=STRING_NOTFOUND ) + { + bFound = TRUE; + // der Format-String f"ur die positiven Zahlen ist alles + // vor dem ersten ';' + return sFormatStrg.Copy( 0,nPos ); + } + // kein ; gefunden, liefere Leerstring + String aRetStr; + aRetStr.AssignAscii( EMPTYFORMATSTRING ); + return aRetStr; +} + +// siehe auch GetPosFormatString() +String SbxBasicFormater::GetNegFormatString( const String& sFormatStrg, BOOL & bFound ) +{ + bFound = FALSE; // default... + USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); + + if( nPos!=STRING_NOTFOUND ) + { + // der Format-String f"ur die negative Zahlen ist alles + // zwischen dem ersten und dem zweiten ';'. + // Daher: hole erst mal alles nach dem ersten ';' + String sTempStrg = sFormatStrg.Copy( nPos+1 ); + // und suche darin ggf. ein weiteres ';' + nPos = sTempStrg.Search( FORMAT_SEPARATOR ); + bFound = TRUE; + if( nPos==STRING_NOTFOUND ) + // keins gefunden, liefere alles... + return sTempStrg; + else + // ansonsten den String zwischen den beiden ';' liefern + return sTempStrg.Copy( 0,nPos ); + } + String aRetStr; + aRetStr.AssignAscii( EMPTYFORMATSTRING ); + return aRetStr; +} + +// siehe auch GetPosFormatString() +String SbxBasicFormater::Get0FormatString( const String& sFormatStrg, BOOL & bFound ) +{ + bFound = FALSE; // default... + USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); + + if( nPos!=STRING_NOTFOUND ) + { + // der Format-String f"ur die Null ist alles + // was nach dem zweiten ';' kommt. + // Daher: hole erst mal alles nach dem ersten ';' + String sTempStrg = sFormatStrg.Copy( nPos+1 ); + // und suche darin ggf. ein weiteres ';' + nPos = sTempStrg.Search( FORMAT_SEPARATOR ); + if( nPos!=STRING_NOTFOUND ) + { + bFound = TRUE; + sTempStrg = sTempStrg.Copy( nPos+1 ); + nPos = sTempStrg.Search( FORMAT_SEPARATOR ); + if( nPos==STRING_NOTFOUND ) + // keins gefunden, liefere alles... + return sTempStrg; + else + return sTempStrg.Copy( 0,nPos ); + } + } + // kein ; gefunden, liefere Leerstring + String aRetStr; + aRetStr.AssignAscii( EMPTYFORMATSTRING ); + return aRetStr; +} + +// siehe auch GetPosFormatString() +String SbxBasicFormater::GetNullFormatString( const String& sFormatStrg, BOOL & bFound ) +{ + bFound = FALSE; // default... + USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR ); + + if( nPos!=STRING_NOTFOUND ) + { + // der Format-String f"ur die Null ist alles + // was nach dem dritten ';' kommt. + // Daher: hole erst mal alles nach dem ersten ';' + String sTempStrg = sFormatStrg.Copy( nPos+1 ); + // und suche darin ggf. ein weiteres ';' + nPos = sTempStrg.Search( FORMAT_SEPARATOR ); + if( nPos!=STRING_NOTFOUND ) + { + // und suche nun nach dem dritten ';' + sTempStrg = sTempStrg.Copy( nPos+1 ); + nPos = sTempStrg.Search( FORMAT_SEPARATOR ); + if( nPos!=STRING_NOTFOUND ) + { + bFound = TRUE; + return sTempStrg.Copy( nPos+1 ); + } + } + } + // kein ; gefunden, liefere Leerstring + String aRetStr; + aRetStr.AssignAscii( EMPTYFORMATSTRING ); + return aRetStr; +} + +// analysiert den Format-String, liefert Wert <> 0 falls ein Fehler +// aufgetreten ist +short SbxBasicFormater::AnalyseFormatString( const String& sFormatStrg, + short& nNoOfDigitsLeft, short& nNoOfDigitsRight, + short& nNoOfOptionalDigitsLeft, + short& nNoOfExponentDigits, short& nNoOfOptionalExponentDigits, + BOOL& bPercent, BOOL& bCurrency, BOOL& bScientific, + BOOL& bGenerateThousandSeparator, + short& nMultipleThousandSeparators ) +{ + USHORT nLen; + short nState = 0; + + nLen = sFormatStrg.Len(); + // initialisiere alle Z"ahler und Flags + nNoOfDigitsLeft = 0; + nNoOfDigitsRight = 0; + nNoOfOptionalDigitsLeft = 0; + nNoOfExponentDigits = 0; + nNoOfOptionalExponentDigits = 0; + bPercent = FALSE; + bCurrency = FALSE; + bScientific = FALSE; + // ab 11.7.97: sobald ein Komma in dem Format String gefunden wird, + // werden alle 3 Zehnerpotenzen markiert (d.h. tausender, milionen, ...) + // bisher wurde nur an den gesetzten Position ein Tausender-Separator + // ausgegeben oder wenn ein @ im Format-String stand. + // Dies war ein Missverstaendnis der VB Kompatiblitaet. + bGenerateThousandSeparator = sFormatStrg.Search( ',' ) != STRING_NOTFOUND; + nMultipleThousandSeparators = 0; + // und untersuche den Format-String nach den gew"unschten Informationen + for( USHORT i=0; i<nLen; i++ ) + { + sal_Unicode c = sFormatStrg.GetChar( i ); + switch( c ) { + case '#': + case '0': + if( nState==0 ) + { + nNoOfDigitsLeft++; +// TODO hier ggf. bessere Fehler-"Uberpr"ufung der Mantisse auf g"ultige Syntax (siehe Grammatik) + // ACHTUNG: 'undefiniertes' Verhalten falls # und 0 + // gemischt werden !!! + // BEMERKUNG: eigentlich sind #-Platzhalter bei Scientific + // Darstellung vor dem Dezimal-Punkt sinnlos ! + if( c=='#' ) + nNoOfOptionalDigitsLeft++; + } + else if( nState==1 ) + nNoOfDigitsRight++; + else if( nState==-1 ) // suche 0 im Exponent + { + if( c=='#' ) // # schaltet den Zustand weiter + { + nNoOfOptionalExponentDigits++; + nState = -2; + } + nNoOfExponentDigits++; + } + else if( nState==-2 ) // suche # im Exponent + { + if( c=='0' ) + // ERROR: 0 nach # im Exponent ist NICHT erlaubt !! + return -4; + nNoOfOptionalExponentDigits++; + nNoOfExponentDigits++; + } + break; + case '.': + nState++; + if( nState>1 ) + return -1; // ERROR: zu viele Dezimal-Punkte + break; + case '%': + bPercent = TRUE; + /* old: + bPercent++; + if( bPercent>1 ) + return -2; // ERROR: zu viele Prozent-Zeichen + */ + break; + case '(': + bCurrency = TRUE; + break; + case ',': + { + sal_Unicode ch = sFormatStrg.GetChar( i+1 ); + // vorl"aufig wird NUR auf zwei aufeinanderfolgede + // Zeichen gepr"uft + if( ch!=0 && (ch==',' || ch=='.') ) + nMultipleThousandSeparators++; + } break; + case 'e': + case 'E': + // #i13821 not when no digits before + if( nNoOfDigitsLeft > 0 || nNoOfDigitsRight > 0 ) + { + nState = -1; // breche jetzt das Z"ahlen der Stellen ab + bScientific = TRUE; + } + /* old: + bScientific++; + if( bScientific>1 ) + return -3; // ERROR: zu viele Exponent-Zeichen + */ + break; + // EIGENES Kommando-Zeichen, das die Erzeugung der + // Tausender-Trennzeichen einschaltet + case '\\': + // Ignore next char + i++; + break; + case CREATE_1000SEP_CHAR: + bGenerateThousandSeparator = TRUE; + break; + } + } + return 0; +} + +// das Flag bCreateSign zeigt an, dass bei der Mantisse ein Vorzeichen +// erzeugt werden soll +void SbxBasicFormater::ScanFormatString( double dNumber, + const String& sFormatStrg, String& sReturnStrg, + BOOL bCreateSign ) +{ + short /*nErr,*/nNoOfDigitsLeft,nNoOfDigitsRight,nNoOfOptionalDigitsLeft, + nNoOfExponentDigits,nNoOfOptionalExponentDigits, + nMultipleThousandSeparators; + BOOL bPercent,bCurrency,bScientific,bGenerateThousandSeparator; + + // Initialisiere den Return-String + sReturnStrg = String(); + + // analysiere den Format-String, d.h. bestimme folgende Werte: + /* + - Anzahl der Ziffern vor dem Komma + - Anzahl der Ziffern nach dem Komma + - optionale Ziffern vor dem Komma + - Anzahl der Ziffern im Exponent + - optionale Ziffern im Exponent + - Prozent-Zeichen gefunden ? + - () f"ur negatives Vorzeichen ? + - Exponetial-Schreibweise ? + - sollen Tausender-Separatoren erzeugt werden ? + - wird ein Prozent-Zeichen gefunden ? --> dNumber *= 100.0; + - gibt es aufeinanderfolgende Tausender-Trennzeichen ? + ,, oder ,. --> dNumber /= 1000.0; + - sonstige Fehler ? mehrfache Dezimalpunkte, E's, etc. + --> Fehler werden zur Zeit einfach ignoriert + */ + /*nErr =*/ AnalyseFormatString( sFormatStrg,nNoOfDigitsLeft,nNoOfDigitsRight, + nNoOfOptionalDigitsLeft,nNoOfExponentDigits, + nNoOfOptionalExponentDigits, + bPercent,bCurrency,bScientific,bGenerateThousandSeparator, + nMultipleThousandSeparators ); + /* es werden alle Fehler ignoriert, wie in Visual-Basic + if( nErr!=0 ) + { + char sBuffer[512]; + + //sprintf( sBuffer,"bad format-string >%s< err=%i",sFormatStrg,nErr ); + strcpy( sBuffer,"bad format-string" ); + ShowError( sBuffer ); + } + else + */ + { + // Spezialbehandlung f"ur Spezialzeichen + if( bPercent ) + dNumber *= 100.0; +// TODO: diese Vorgabe (,, oder ,.) ist NICHT Visual-Basic kompatibel ! + // Frage: soll das hier stehen bleiben (Anforderungen) ? + if( nMultipleThousandSeparators ) + dNumber /= 1000.0; + + // einige Arbeits-Variablen + double dExponent; + short i,nLen; + short nState,nDigitPos,nExponentPos,nMaxDigit,nMaxExponentDigit; + BOOL bFirstDigit,bFirstExponentDigit,bFoundFirstDigit, + bIsNegative,bZeroSpaceOn, bSignHappend,bDigitPosNegative; + + // Initialisierung der Arbeits-Variablen + bSignHappend = FALSE; + bFoundFirstDigit = FALSE; + bIsNegative = dNumber<0.0; + nLen = sFormatStrg.Len(); + dExponent = get_number_of_digits( dNumber ); + nExponentPos = 0; + nMaxExponentDigit = 0; + nMaxDigit = (short)dExponent; + bDigitPosNegative = false; + if( bScientific ) + { + //if( nNoOfOptionalDigitsLeft>0 ) + // ShowError( "# in scientific-format in front of the decimal-point has no effect" ); + // beim Exponent ggf. "uberz"ahlige Stellen vor dem Komma abziehen + dExponent = dExponent - (double)(nNoOfDigitsLeft-1); + nDigitPos = nMaxDigit; + nMaxExponentDigit = (short)get_number_of_digits( dExponent ); + nExponentPos = nNoOfExponentDigits-1 - nNoOfOptionalExponentDigits; + } + else + { + nDigitPos = nNoOfDigitsLeft-1; // Z"ahlweise f"angt bei 0 an, 10^0 + // hier ben"otigt man keine Exponent-Daten ! + bDigitPosNegative = (nDigitPos < 0); + } + bFirstDigit = TRUE; + bFirstExponentDigit = TRUE; + nState = 0; // 0 --> Mantisse; 1 --> Exponent + bZeroSpaceOn = 0; + + +#ifdef _with_sprintf + InitScan( dNumber ); +#endif + // scanne jetzt den Format-String: + sal_Unicode cForce = 0; + for( i=0; i<nLen; i++ ) + { + sal_Unicode c; + if( cForce ) + { + c = cForce; + cForce = 0; + } + else + { + c = sFormatStrg.GetChar( i ); + } + switch( c ) { + case '0': + case '#': + if( nState==0 ) + { + // Behandlung der Mantisse + if( bFirstDigit ) + { + //org:bFirstDigit = FALSE; + // ggf. Vorzeichen erzeugen + // Bem.: bei bCurrency soll das negative + // Vorzeichen durch () angezeigt werden + if( bIsNegative && !bCreateSign/*!bCurrency*/ && !bSignHappend ) + { + // nur einmal ein Vorzeichen ausgeben + bSignHappend = TRUE; + StrAppendChar( sReturnStrg,'-' ); + } + // hier jetzt "uberz"ahlige Stellen ausgeben, + // d.h. vom Format-String nicht erfasste Stellen + if( nMaxDigit>nDigitPos ) + { + for( short j=nMaxDigit; j>nDigitPos; j-- ) + { + short nTempDigit; +#ifdef _with_sprintf + AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( j,bFoundFirstDigit ) ); +#else + AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,j,dNumber,bFoundFirstDigit ) ); +#endif + // wurde wirklich eine Ziffer eingefuegt ? + if( nTempDigit!=_NO_DIGIT ) + // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen + bFirstDigit = FALSE; + // muss ggf. ein Tausender-Trennzeichen erzeugt werden? + if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && j>0 && (j % 3 == 0) ) + StrAppendChar( sReturnStrg,cThousandSep ); + } + } + } + // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ? + if( nMaxDigit<nDigitPos && ( c=='0' || bZeroSpaceOn ) ) + { + AppendDigit( sReturnStrg,0 ); // Ja + // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen + bFirstDigit = FALSE; + bZeroSpaceOn = 1; + // BEM.: bei Visual-Basic schaltet die erste 0 f"ur alle + // nachfolgenden # (bis zum Dezimal-Punkt) die 0 ein, + // dieses Verhalten wird hier mit dem Flag simmuliert. + // muss ggf. ein Tausender-Trennzeichen erzeugt werden? + if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) ) + StrAppendChar( sReturnStrg,cThousandSep ); + } + else + { + short nTempDigit; +#ifdef _with_sprintf + AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ) ); +#else + AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ) ); +#endif + // wurde wirklich eine Ziffer eingefuegt ? + if( nTempDigit!=_NO_DIGIT ) + // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen + bFirstDigit = FALSE; + // muss ggf. ein Tausender-Trennzeichen erzeugt werden? + if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) ) + StrAppendChar( sReturnStrg,cThousandSep ); + } + // und Position aktualisieren + nDigitPos--; + } + else + { + // Behandlung des Exponenten + if( bFirstExponentDigit ) + { + // Vorzeichen wurde schon bei e/E ausgegeben + bFirstExponentDigit = FALSE; + if( nMaxExponentDigit>nExponentPos ) + // hier jetzt "uberz"ahlige Stellen ausgeben, + // d.h. vom Format-String nicht erfasste Stellen + { + for( short j=nMaxExponentDigit; j>nExponentPos; j-- ) + { +#ifdef _with_sprintf + AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,j,bFoundFirstDigit ) ); +#else + AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,j,dExponent,bFoundFirstDigit ) ); +#endif + } + } + } + // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ? + if( nMaxExponentDigit<nExponentPos && c=='0' ) + AppendDigit( sReturnStrg,0 ); // Ja + else +#ifdef _with_sprintf + AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,nExponentPos,bFoundFirstDigit ) ); +#else + AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,nExponentPos,dExponent,bFoundFirstDigit ) ); +#endif + nExponentPos--; + } + break; + case '.': + if( bDigitPosNegative ) // #i13821: If no digits before . + { + bDigitPosNegative = false; + nDigitPos = 0; + cForce = '#'; + i-=2; + break; + } + // gebe Komma aus + StrAppendChar( sReturnStrg,cDecPoint ); + break; + case '%': + // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 + ParseBack( sReturnStrg,sFormatStrg,i-1 ); + // gebe Prozent-Zeichen aus + sReturnStrg.Insert('%'); + break; + case 'e': + case 'E': + // muss Mantisse noch gerundet werden, bevor der Exponent angezeigt wird ? + { + // gibt es ueberhaupt eine Mantisse ? + if( bFirstDigit ) + { + // anscheinend nicht, d.h. ungueltiger Format String, z.B. E000.00 + // d.h. ignoriere diese e bzw. E Zeichen + // ggf. einen Fehler (wie Visual Basic) ausgeben ? + + // #i13821: VB 6 behaviour + StrAppendChar( sReturnStrg,c ); + break; + } + + BOOL bOverflow = FALSE; +#ifdef _with_sprintf + short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ); +#else + short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ); +#endif + if( nNextDigit>=5 ) + StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1,bOverflow ); + if( bOverflow ) + { + // es wurde eine f"uhrende 9 gerundet, d.h. + // verschiebe den Dezimal-Punkt um eine Stelle nach links + LeftShiftDecimalPoint( sReturnStrg ); + // und l"osche die letzte Ziffer, diese wird + // duch die f"uhrende 1 ersetzt: + sReturnStrg.SetChar( sReturnStrg.Len()-1 , 0 ); + // der Exponent muss um 1 erh"oht werden, + // da der Dezimalpunkt verschoben wurde + dExponent += 1.0; + } + // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 + ParseBack( sReturnStrg,sFormatStrg,i-1 ); + } + // "andere Zustand des Scanners + nState++; + // gebe Exponent-Zeichen aus + StrAppendChar( sReturnStrg,c ); + // i++; // MANIPULATION der Schleifen-Variable ! + c = sFormatStrg.GetChar( ++i ); + // und gebe Vorzeichen / Exponent aus + if( c!=0 ) + { + if( c=='-' ) + { + // falls Exponent < 0 gebe - aus + if( dExponent<0.0 ) + StrAppendChar( sReturnStrg,'-' ); + } + else if( c=='+' ) + { + // gebe auf jeden Fall das Vorzeichen des Exponenten aus ! + if( dExponent<0.0 ) + StrAppendChar( sReturnStrg,'-' ); + else + StrAppendChar( sReturnStrg,'+' ); + } + //else + // ShowError( "operator e/E did not find + or -" ); + } + //else + // ShowError( "operator e/E ended with 0" ); + break; + case ',': + // ACHTUNG: nur falls Zahl bisher ausgegeben wurde + // das Zeichen ausgeben + ////--> Siehe Kommentar vom 11.7. in AnalyseFormatString() + ////if( !bFirstDigit ) + //// // gebe Tausender-Trennzeichen aus + //// StrAppendChar( sReturnStrg,cThousandSep ); + break; + case ';': + break; + case '(': + case ')': + // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 + ParseBack( sReturnStrg,sFormatStrg,i-1 ); + if( bIsNegative ) + StrAppendChar( sReturnStrg,c ); + break; + case '$': + // den String fuer die Waehrung dranhengen: + sReturnStrg += sCurrencyStrg; + break; + case ' ': + case '-': + case '+': + // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 + ParseBack( sReturnStrg,sFormatStrg,i-1 ); + // gebe das jeweilige Zeichen direkt aus + StrAppendChar( sReturnStrg,c ); + break; + case '\\': + // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00 + // falls Sonderzeichen am Ende oder mitten in + // Format-String vorkommen + ParseBack( sReturnStrg,sFormatStrg,i-1 ); + // Sonderzeichen gefunden, gebe N"ACHSTES + // Zeichen direkt aus (falls es existiert) + // i++; + c = sFormatStrg.GetChar( ++i ); + if( c!=0 ) + StrAppendChar( sReturnStrg,c ); + //else + // ShowError( "operator \\ ended with 0" ); + break; + case CREATE_1000SEP_CHAR: + // hier ignorieren, Aktion wurde schon in + // AnalyseFormatString durchgef"uhrt + break; + default: + // auch die Zeichen und Ziffern ausgeben (wie in Visual-Basic) + if( ( c>='a' && c<='z' ) || + ( c>='A' && c<='Z' ) || + ( c>='1' && c<='9' ) ) + StrAppendChar( sReturnStrg,c ); + // else + // ignorieren ! + // ehemals: ShowError( "bad character in format-string" ); + } + } + // Format-String wurde vollst"andig gescanned, + // muss die letzte Stelle nun gerundet werden ? + // Dies hier ist jedoch NUR notwendig, falls das + // Zahlenformat NICHT Scientific-Format ist ! + if( !bScientific ) + { +#ifdef _with_sprintf + short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ); +#else + short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ); +#endif + if( nNextDigit>=5 ) + StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1 ); + } + // und ganz zum Schluss: + // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00#, + // ABER nur Stellen nach dem Dezimal-Punkt k"onnen gel"oscht werden + if( nNoOfDigitsRight>0 ) + ParseBack( sReturnStrg,sFormatStrg,sFormatStrg.Len()-1 ); + } +} + +String SbxBasicFormater::BasicFormatNull( String sFormatStrg ) +{ + BOOL bNullFormatFound; + String sNullFormatStrg = GetNullFormatString( sFormatStrg,bNullFormatFound ); + + if( bNullFormatFound ) + return sNullFormatStrg; + String aRetStr; + aRetStr.AssignAscii( "null" ); + return aRetStr; +} + +String SbxBasicFormater::BasicFormat( double dNumber, String sFormatStrg ) +{ + BOOL bPosFormatFound,bNegFormatFound,b0FormatFound; + + // analysiere Format-String auf vordefinierte Formate: + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) ) + sFormatStrg.AssignAscii( GENERALNUMBER_FORMAT ); + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) ) + sFormatStrg = sCurrencyFormatStrg; // old: CURRENCY_FORMAT; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) ) + sFormatStrg.AssignAscii( FIXED_FORMAT ); + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) ) + sFormatStrg.AssignAscii( STANDARD_FORMAT ); + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) ) + sFormatStrg.AssignAscii( PERCENT_FORMAT ); + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) ) + sFormatStrg.AssignAscii( SCIENTIFIC_FORMAT ); + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) ) + return ( dNumber==0.0 ) ? sNoStrg : sYesStrg ; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) ) + return ( dNumber==0.0 ) ? sFalseStrg : sTrueStrg ; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) ) + return ( dNumber==0.0 ) ? sOffStrg : sOnStrg ; + + // analysiere Format-String auf ';', d.h. Format-Strings f"ur + // positive-, negative- und 0-Werte + String sPosFormatStrg = GetPosFormatString( sFormatStrg, bPosFormatFound ); + String sNegFormatStrg = GetNegFormatString( sFormatStrg, bNegFormatFound ); + String s0FormatStrg = Get0FormatString( sFormatStrg, b0FormatFound ); + //String sNullFormatStrg = GetNullFormatString( sFormatStrg, bNullFormatFound ); + + String sReturnStrg; + String sTempStrg; + + if( dNumber==0.0 ) + { + sTempStrg = sFormatStrg; + if( b0FormatFound ) + { + // wurde ggf. Leer-String uebergeben ? + if( s0FormatStrg.Len() == 0 && bPosFormatFound ) + // --> Ja, dann verwende String fuer positive Werte + sTempStrg = sPosFormatStrg; + else + sTempStrg = s0FormatStrg; + } + else if( bPosFormatFound ) + { + // verwende String fuer positive Werte + sTempStrg = sPosFormatStrg; + } + ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/FALSE ); + } + else + { + if( dNumber<0.0 ) + { + if( bNegFormatFound ) + { + // wurde ggf. Leer-String uebergeben ? + if( sNegFormatStrg.Len() == 0 && bPosFormatFound ) + { + // --> Ja, dann verwende String fuer positive Werte + // und setzte Minus-Zeichen davor ! + sTempStrg = String::CreateFromAscii("-"); + sTempStrg += sPosFormatStrg; + } + else + sTempStrg = sNegFormatStrg; + } + else + sTempStrg = sFormatStrg; + // falls KEIN Format-String speziell f"ur negative Werte angegeben + // wurde, so soll das Vorzeichen ausgegeben werden + ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/bNegFormatFound/*sNegFormatStrg!=EMPTYFORMATSTRING*/ ); + } + else // if( dNumber>0.0 ) + { + ScanFormatString( dNumber, + (/*sPosFormatStrg!=EMPTYFORMATSTRING*/bPosFormatFound ? sPosFormatStrg : sFormatStrg), + sReturnStrg,/*bCreateSign=*/FALSE ); + } + } + return sReturnStrg; +} + +BOOL SbxBasicFormater::isBasicFormat( String sFormatStrg ) +{ + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) ) + return TRUE; + if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) ) + return TRUE; + return FALSE; +} + diff --git a/basic/source/sbx/sbxint.cxx b/basic/source/sbx/sbxint.cxx new file mode 100644 index 000000000000..648ea17283c1 --- /dev/null +++ b/basic/source/sbx/sbxint.cxx @@ -0,0 +1,970 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxint.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +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 ); + } +} + + diff --git a/basic/source/sbx/sbxlng.cxx b/basic/source/sbx/sbxlng.cxx new file mode 100644 index 000000000000..f5d4d5aa273c --- /dev/null +++ b/basic/source/sbx/sbxlng.cxx @@ -0,0 +1,344 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxlng.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +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 ); + } +} + diff --git a/basic/source/sbx/sbxmstrm.cxx b/basic/source/sbx/sbxmstrm.cxx new file mode 100644 index 000000000000..9fa3f7d240f1 --- /dev/null +++ b/basic/source/sbx/sbxmstrm.cxx @@ -0,0 +1,42 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxmstrm.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <basic/sbxmstrm.hxx> + +SbxDataType SbxMemoryStream::GetType() const +{ + return SbxMEMORYSTREAM; +} + +SbxMemoryStream::~SbxMemoryStream() +{ +} diff --git a/basic/source/sbx/sbxobj.cxx b/basic/source/sbx/sbxobj.cxx new file mode 100644 index 000000000000..3f747f27c5bd --- /dev/null +++ b/basic/source/sbx/sbxobj.cxx @@ -0,0 +1,1148 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxobj.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <vcl/sound.hxx> +#include <basic/sbx.hxx> +#include <basic/sbxbase.hxx> +#include "sbxres.hxx" +#include <svtools/brdcst.hxx> + +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; +} +void SbxObject::SetDfltProperty( const XubString& rName ) +{ + if ( rName != aDfltPropName ) + pDfltProp = NULL; + aDfltPropName = rName; + SetModified( TRUE ); +} + +void SbxObject::SetDfltProperty( SbxProperty* p ) +{ + if( p ) + { + USHORT n; + SbxArray* pArray = FindVar( p, n ); + pArray->Put( p, n ); + if( p->GetParent() != this ) + p->SetParent( this ); + Broadcast( SBX_HINT_OBJECTCHANGED ); + } + pDfltProp = p; + SetModified( TRUE ); +} + +// 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 + } +} + +// AB 23.3.1997, Spezial-Methode, gleichnamige Controls zulassen +void SbxObject::VCPtrInsert( 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 ); + Broadcast( SBX_HINT_OBJECTCHANGED ); + } +} + +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 ); + } +} + +// AB 23.3.1997, Loeschen per Pointer fuer Controls (doppelte Namen!) +void SbxObject::VCPtrRemove( SbxVariable* pVar ) +{ + USHORT nIdx; + // Neu FindVar-Methode, sonst identisch mit normaler Methode + SbxArray* pArray = VCPtrFindVar( pVar, nIdx ); + if( pArray && nIdx < pArray->Count() ) + { + SbxVariableRef xVar = pArray->Get( nIdx ); + if( xVar->IsBroadcaster() ) + EndListening( xVar->GetBroadcaster(), TRUE ); + if( (SbxVariable*) xVar == pDfltProp ) + pDfltProp = NULL; + pArray->Remove( nIdx ); + if( xVar->GetParent() == this ) + xVar->SetParent( NULL ); + SetModified( TRUE ); + Broadcast( SBX_HINT_OBJECTCHANGED ); + } +} + +// AB 23.3.1997, Zugehoerige Spezial-Methode, nur ueber Pointer suchen +SbxArray* SbxObject::VCPtrFindVar( 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(); + for( USHORT i = 0; i < pArray->Count(); i++ ) + { + SbxVariableRef& rRef = pArray->GetRef( i ); + if( (SbxVariable*) rRef == pVar ) + { + nArrayIdx = i; break; + } + } + } + return pArray; +} + + + +void SbxObject::SetPos( SbxVariable* pVar, USHORT nPos ) +{ + USHORT nIdx; + SbxArray* pArray = FindVar( pVar, nIdx ); + if( pArray ) + { + if( nPos >= pArray->Count() ) + nPos = pArray->Count() - 1; + if( nIdx < ( pArray->Count() - 1 ) ) + { + SbxVariableRef refVar = pArray->Get( nIdx ); + pArray->Remove( nIdx ); + pArray->Insert( refVar, nPos ); + } + } +// 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; +} + +BOOL SbxMethod::Run( SbxValues* pValues ) +{ + SbxValues aRes; + if( !pValues ) + pValues = &aRes; + pValues->eType = SbxVARIANT; + return Get( *pValues ); +} + +SbxClassType SbxMethod::GetClass() const +{ + return SbxCLASS_METHOD; +} + +SbxClassType SbxProperty::GetClass() const +{ + return SbxCLASS_PROPERTY; +} + +void SbxObject::GarbageCollection( ULONG nObjects ) + +/* [Beschreibung] + + Diese statische Methode durchsucht die n"achsten 'nObjects' der zur Zeit + existierenden <SbxObject>-Instanzen nach zyklischen Referenzen, die sich + nur noch selbst am Leben erhalten. Ist 'nObjects==0', dann werden + alle existierenden durchsucht. + + zur Zeit nur implementiert: Object -> Parent-Property -> Parent -> Object +*/ + +{ + (void)nObjects; + + static BOOL bInGarbageCollection = FALSE; + if ( bInGarbageCollection ) + return; + bInGarbageCollection = TRUE; + +#if 0 + // erstes Object dieser Runde anspringen + BOOL bAll = !nObjects; + if ( bAll ) + rObjects.First(); + SbxObject *pObj = rObjects.GetCurObject(); + if ( !pObj ) + pObj = rObjects.First(); + + while ( pObj && 0 != nObjects-- ) + { + // hat der Parent nur noch 1 Ref-Count? + SbxObject *pParent = PTR_CAST( SbxObject, pObj->GetParent() ); + if ( pParent && 1 == pParent->GetRefCount() ) + { + // dann alle Properies des Objects durchsuchen + SbxArray *pProps = pObj->GetProperties(); + for ( USHORT n = 0; n < pProps->Count(); ++n ) + { + // verweist die Property auf den Parent des Object? + SbxVariable *pProp = pProps->Get(n); + const SbxValues &rValues = pProp->GetValues_Impl(); + if ( SbxOBJECT == rValues.eType && + pParent == rValues.pObj ) + { +#ifdef DBG_UTIL + DbgOutf( "SBX: %s.%s with Object %s was garbage", + pObj->GetName().GetStr(), + pProp->GetName().GetStr(), + pParent->GetName().GetStr() ); +#endif + // dann freigeben + pProp->SbxValue::Clear(); + Sound::Beep(); + break; + } + } + } + + // zum n"achsten + pObj = rObjects.Next(); + if ( !bAll && !pObj ) + pObj = rObjects.First(); + } +#endif + +// AB 28.10. Zur 507a vorerst raus, da SfxBroadcaster::Enable() wegfaellt +#if 0 +#ifdef DBG_UTIL + SbxVarList_Impl &rVars = GetSbxData_Impl()->aVars; + DbgOutf( "SBX: garbage collector done, %lu objects remainding", + rVars.Count() ); + if ( rVars.Count() > 200 && rVars.Count() < 210 ) + { + SvFileStream aStream( "d:\\tmp\\dump.sbx", STREAM_STD_WRITE ); + SfxBroadcaster::Enable(FALSE); + for ( ULONG n = 0; n < rVars.Count(); ++n ) + { + SbxVariable *pVar = rVars.GetObject(n); + SbxObject *pObj = PTR_CAST(SbxObject, pVar); + USHORT nFlags = pVar->GetFlags(); + pVar->SetFlag(SBX_NO_BROADCAST); + if ( pObj ) + pObj->Dump(aStream); + else if ( !pVar->GetParent() || !pVar->GetParent()->ISA(SbxObject) ) + pVar->Dump(aStream); + pVar->SetFlags(nFlags); + } + SfxBroadcaster::Enable(TRUE); + } +#endif +#endif + bInGarbageCollection = FALSE; +} + diff --git a/basic/source/sbx/sbxres.cxx b/basic/source/sbx/sbxres.cxx new file mode 100644 index 000000000000..7dd61462a2e2 --- /dev/null +++ b/basic/source/sbx/sbxres.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxres.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#include "sbxres.hxx" + +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 ) ) ) +{} + diff --git a/basic/source/sbx/sbxres.hxx b/basic/source/sbx/sbxres.hxx new file mode 100644 index 000000000000..8971657f05a5 --- /dev/null +++ b/basic/source/sbx/sbxres.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxres.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _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 + +class SbxRes : public String +{ +public: + SbxRes( USHORT ); +}; + +const char* GetSbxRes( USHORT ); + + +#endif diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx new file mode 100644 index 000000000000..acc5d91c4e2e --- /dev/null +++ b/basic/source/sbx/sbxscan.cxx @@ -0,0 +1,966 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxscan.cxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +#include "svtools/syslocale.hxx" + +#if defined ( UNX ) +#include <stdlib.h> +#endif + +#ifndef _APP_HXX //autogen +#include <vcl/svapp.hxx> +#endif +#include <math.h> +#include <string.h> +#include <ctype.h> + +#include "sbxres.hxx" +#include <basic/sbxbase.hxx> +#include <basic/sbxform.hxx> +#include <svtools/svtools.hrc> + +#include "basrid.hxx" +#include "runtime.hxx" + +#include <svtools/zforlist.hxx> +#include <comphelper/processfactory.hxx> + + +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; + } + else if ( SbiRuntime::isVBAEnabled() ) + { + OSL_TRACE("Reporting error converting"); + return SbxERR_CONVERSION; + } + if( pLen ) + *pLen = (USHORT) ( p - pStart ); + if( !bRes ) + return SbxERR_CONVERSION; + if( bMinus ) + nVal = -nVal; + rType = eScanType; + return SbxERR_OK; +} + +// Schnittstelle fuer CDbl im Basic +SbxError SbxValue::ScanNumIntnl( const String& rSrc, double& nVal, BOOL bSingle ) +{ + SbxDataType t; + USHORT nLen = 0; + SbxError nRetError = ImpScan( rSrc, nVal, t, &nLen, + /*bAllowIntntl*/FALSE, /*bOnlyIntntl*/TRUE ); + // Komplett gelesen? + if( nRetError == SbxERR_OK && nLen != rSrc.Len() ) + nRetError = SbxERR_CONVERSION; + + if( bSingle ) + { + SbxValues aValues( nVal ); + nVal = (double)ImpGetSingle( &aValues ); // Hier Error bei Overflow + } + return nRetError; +} + +//////////////////////////////////////////////////////////////////////////// + +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 + +BOOL ImpConvStringExt( XubString& rSrc, SbxDataType eTargetType ) +{ + // Merken, ob ueberhaupt was geaendert wurde + BOOL bChanged = FALSE; + String aNewString; + + // Nur Spezial-Fälle behandeln, als Default tun wir nichts + switch( eTargetType ) + { + // Bei Fliesskomma International beruecksichtigen + case SbxSINGLE: + case SbxDOUBLE: + case SbxCURRENCY: + { + ByteString aBStr( rSrc, RTL_TEXTENCODING_ASCII_US ); + + // Komma besorgen + sal_Unicode cDecimalSep, cThousandSep; + ImpGetIntntlSep( cDecimalSep, cThousandSep ); + aNewString = rSrc; + + // Ersetzen, wenn DecimalSep kein '.' (nur den ersten) + if( cDecimalSep != (sal_Unicode)'.' ) + { + USHORT nPos = aNewString.Search( cDecimalSep ); + if( nPos != STRING_NOTFOUND ) + { + aNewString.SetChar( nPos, '.' ); + bChanged = TRUE; + } + } + break; + } + + // Bei BOOL TRUE und FALSE als String pruefen + case SbxBOOL: + { + if( rSrc.EqualsIgnoreCaseAscii( "true" ) ) + { + aNewString = String::CreateFromInt32(SbxTRUE); + bChanged = TRUE; + } + else + if( rSrc.EqualsIgnoreCaseAscii( "false" ) ) + { + aNewString = String::CreateFromInt32(SbxFALSE); + bChanged = TRUE; + } + break; + } + default: break; + } + // String bei Aenderung uebernehmen + if( bChanged ) + rSrc = aNewString; + return bChanged; +} + + +// 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_ + +static USHORT printfmtstr( const XubString& rStr, XubString& rRes, const XubString& rFmt ) +{ + const xub_Unicode* pStr = rStr.GetBuffer(); + const xub_Unicode* pFmtStart = rFmt.GetBuffer(); + const xub_Unicode* pFmt = pFmtStart; + rRes.Erase(); + switch( *pFmt ) + { + case '!': + rRes += *pStr++; pFmt++; break; + case '\\': + do + { + rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' '); + pFmt++; + } while( *pFmt != '\\' ); + rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' '); + pFmt++; break; + case '&': + rRes = rStr; + pFmt++; break; + default: + rRes = rStr; + break; + } + return (USHORT) ( pFmt - pFmtStart ); +} + +///////////////////////////////////////////////////////////////////////// + +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; +} + + +ResMgr* implGetResMgr( void ) +{ + static ResMgr* pResMgr = NULL; + if( !pResMgr ) + { + ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); + pResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(sb), aLocale ); + } + return pResMgr; +} + +class SbxValueFormatResId : public ResId +{ +public: + SbxValueFormatResId( USHORT nId ) + : ResId( nId, *implGetResMgr() ) + {} +}; + + +enum VbaFormatType +{ + VBA_FORMAT_TYPE_OFFSET, // standard number format + VBA_FORMAT_TYPE_USERDEFINED, // user defined number format + VBA_FORMAT_TYPE_NULL +}; + +struct VbaFormatInfo +{ + VbaFormatType meType; + const char* mpVbaFormat; // Format string in vba + NfIndexTableOffset meOffset; // SvNumberFormatter format index, if meType = VBA_FORMAT_TYPE_OFFSET + const char* mpOOoFormat; // if meType = VBA_FORMAT_TYPE_USERDEFINED +}; + +#define VBA_FORMAT_OFFSET( pcUtf8, eOffset ) \ + { VBA_FORMAT_TYPE_OFFSET, pcUtf8, eOffset, 0 } + +#define VBA_FORMAT_USERDEFINED( pcUtf8, pcDefinedUtf8 ) \ + { VBA_FORMAT_TYPE_USERDEFINED, pcUtf8, NF_NUMBER_STANDARD, pcDefinedUtf8 } + +static VbaFormatInfo pFormatInfoTable[] = +{ + VBA_FORMAT_OFFSET( "Long Date", NF_DATE_SYSTEM_LONG ), + VBA_FORMAT_USERDEFINED( "Medium Date", "DD-MMM-YY" ), + VBA_FORMAT_OFFSET( "Short Date", NF_DATE_SYSTEM_SHORT ), + VBA_FORMAT_USERDEFINED( "Long Time", "H:MM:SS AM/PM" ), + VBA_FORMAT_OFFSET( "Medium Time", NF_TIME_HHMMAMPM ), + VBA_FORMAT_OFFSET( "Short Time", NF_TIME_HHMM ), + VBA_FORMAT_OFFSET( "ddddd", NF_DATE_SYSTEM_SHORT ), + VBA_FORMAT_OFFSET( "dddddd", NF_DATE_SYSTEM_LONG ), + VBA_FORMAT_USERDEFINED( "ttttt", "H:MM:SS AM/PM" ), + VBA_FORMAT_OFFSET( "ww", NF_DATE_WW ), + { VBA_FORMAT_TYPE_NULL, 0, NF_INDEX_TABLE_ENTRIES, 0 } +}; + +VbaFormatInfo* getFormatInfo( const String& rFmt ) +{ + VbaFormatInfo* pInfo = NULL; + INT16 i = 0; + while( (pInfo = pFormatInfoTable + i )->mpVbaFormat != NULL ) + { + if( rFmt.EqualsIgnoreCaseAscii( pInfo->mpVbaFormat ) ) + break; + i++; + } + return pInfo; +} + +#define VBAFORMAT_GENERALDATE "General Date" +#define VBAFORMAT_C "c" +#define VBAFORMAT_N "n" +#define VBAFORMAT_NN "nn" +#define VBAFORMAT_W "w" +#define VBAFORMAT_Y "y" +#define VBAFORMAT_LOWERCASE "<" +#define VBAFORMAT_UPPERCASE ">" + +// From methods1.cxx +INT16 implGetWeekDay( double aDate, bool bFirstDayParam = false, INT16 nFirstDay = 0 ); +// from methods.cxx +INT16 implGetMinute( double dDate ); +INT16 implGetDateYear( double aDate ); +BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet ); + +void SbxValue::Format( XubString& rRes, const XubString* pFmt ) const +{ + short nComma = 0; + double d = 0; + + // pflin, It is better to use SvNumberFormatter to handle the date/time/number format. + // the SvNumberFormatter output is mostly compatible with + // VBA output besides the OOo-basic output + if( pFmt && !SbxBasicFormater::isBasicFormat( *pFmt ) ) + { + String aStr = GetString(); + + if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_LOWERCASE ) ) + { + rRes = aStr.ToLowerAscii(); + return; + } + if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_UPPERCASE ) ) + { + rRes = aStr.ToUpperAscii(); + return; + } + + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + xFactory = comphelper::getProcessServiceFactory(); + SvNumberFormatter aFormatter( xFactory, eLangType ); + + sal_uInt32 nIndex; + xub_StrLen nCheckPos = 0; + short nType; + double nNumber; + Color* pCol; + + BOOL bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, nNumber ); + + // number format, use SvNumberFormatter to handle it. + if( bSuccess ) + { + String aFmtStr = *pFmt; + VbaFormatInfo* pInfo = getFormatInfo( aFmtStr ); + if( pInfo && pInfo->meType != VBA_FORMAT_TYPE_NULL ) + { + if( pInfo->meType == VBA_FORMAT_TYPE_OFFSET ) + { + nIndex = aFormatter.GetFormatIndex( pInfo->meOffset, eLangType ); + } + else + { + aFmtStr.AssignAscii( pInfo->mpOOoFormat ); + aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); + } + aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); + } + else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_GENERALDATE ) + || aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_C )) + { + if( nNumber <=-1.0 || nNumber >= 1.0 ) + { + // short date + nIndex = aFormatter.GetFormatIndex( NF_DATE_SYSTEM_SHORT, eLangType ); + aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); + + // long time + if( floor( nNumber ) != nNumber ) + { + aFmtStr.AssignAscii( "H:MM:SS AM/PM" ); + aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); + String aTime; + aFormatter.GetOutputString( nNumber, nIndex, aTime, &pCol ); + rRes.AppendAscii(" "); + rRes += aTime; + } + } + else + { + // long time only + aFmtStr.AssignAscii( "H:MM:SS AM/PM" ); + aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); + aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); + } + } + else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_N ) + || aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN )) + { + INT32 nMin = implGetMinute( nNumber ); + if( nMin < 10 && aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN ) ) + { + // Minute in two digits + sal_Unicode* p = rRes.AllocBuffer( 2 ); + *p++ = '0'; + *p = sal_Unicode( '0' + nMin ); + } + else + { + rRes = String::CreateFromInt32( nMin ); + } + } + else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_W )) + { + INT32 nWeekDay = implGetWeekDay( nNumber ); + rRes = String::CreateFromInt32( nWeekDay ); + } + else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_Y )) + { + INT16 nYear = implGetDateYear( nNumber ); + double dBaseDate; + implDateSerial( nYear, 1, 1, dBaseDate ); + INT32 nYear32 = 1 + INT32( nNumber - dBaseDate ); + rRes = String::CreateFromInt32( nYear32 ); + } + else + { + aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType ); + aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol ); + } + + return; + } + } + + SbxDataType eType = GetType(); + switch( eType ) + { + case SbxCHAR: + case SbxBYTE: + case SbxINTEGER: + case SbxUSHORT: + case SbxLONG: + case SbxULONG: + case SbxINT: + case SbxUINT: + case SbxNULL: // #45929 NULL mit durchschummeln + nComma = 0; goto cvt; + case SbxSINGLE: + nComma = 6; goto cvt; + case SbxDOUBLE: + nComma = 14; + + cvt: + if( eType != SbxNULL ) + d = GetDouble(); + + // #45355 weiterer Einsprungpunkt fuer isnumeric-String + cvt2: + if( pFmt ) + { + // hole die 'statischen' Daten f"ur Sbx + SbxAppData* pData = GetSbxData_Impl(); + + LanguageType eLangType = GetpApp()->GetSettings().GetLanguage(); + if( pData->pBasicFormater ) + { + if( pData->eBasicFormaterLangType != eLangType ) + { + delete pData->pBasicFormater; + pData->pBasicFormater = NULL; + } + } + pData->eBasicFormaterLangType = eLangType; + + // falls bisher noch kein BasicFormater-Objekt + // existiert, so erzeuge dieses + if( !pData->pBasicFormater ) + { + SvtSysLocale aSysLocale; + const LocaleDataWrapper& rData = aSysLocale.GetLocaleData(); + sal_Unicode cComma = rData.getNumDecimalSep().GetBuffer()[0]; + sal_Unicode c1000 = rData.getNumThousandSep().GetBuffer()[0]; + String aCurrencyStrg = rData.getCurrSymbol(); + + // Initialisierung des Basic-Formater-Hilfsobjekts: + // hole die Resourcen f"ur die vordefinierten Ausgaben + // des Format()-Befehls, z.B. f"ur "On/Off". + String aOnStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_ON ) ); + String aOffStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_OFF) ); + String aYesStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_YES) ); + String aNoStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_NO) ); + String aTrueStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_TRUE) ); + String aFalseStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_FALSE) ); + String aCurrencyFormatStrg = String( SbxValueFormatResId( + STR_BASICKEY_FORMAT_CURRENCY) ); + // erzeuge das Basic-Formater-Objekt + pData->pBasicFormater + = new SbxBasicFormater( cComma,c1000,aOnStrg,aOffStrg, + aYesStrg,aNoStrg,aTrueStrg,aFalseStrg, + aCurrencyStrg,aCurrencyFormatStrg ); + } + // Bem.: Aus Performance-Gr"unden wird nur EIN BasicFormater- + // Objekt erzeugt und 'gespeichert', dadurch erspart man + // sich das teure Resourcen-Laden (f"ur landesspezifische + // vordefinierte Ausgaben, z.B. "On/Off") und die st"andige + // String-Erzeugungs Operationen. + // ABER: dadurch ist dieser Code NICHT multithreading f"ahig ! + + // hier gibt es Probleme mit ;;;Null, da diese Methode nur aufgerufen + // wird, wenn der SbxValue eine Zahl ist !!! + // dazu koennte: pData->pBasicFormater->BasicFormatNull( *pFmt ); aufgerufen werden ! + if( eType != SbxNULL ) + { + rRes = pData->pBasicFormater->BasicFormat( d ,*pFmt ); + } + else + { + rRes = pData->pBasicFormater->BasicFormatNull( *pFmt ); + } + + // Die alte Implementierung: + //old: printfmtnum( GetDouble(), rRes, *pFmt ); + } + else + ImpCvtNum( GetDouble(), nComma, rRes ); + break; + case SbxSTRING: + if( pFmt ) + { + // #45355 wenn es numerisch ist, muss gewandelt werden + if( IsNumericRTL() ) + { + ScanNumIntnl( GetString(), d, /*bSingle*/FALSE ); + goto cvt2; + } + else + { + // Sonst String-Formatierung + printfmtstr( GetString(), rRes, *pFmt ); + } + } + else + rRes = GetString(); + break; + default: + rRes = GetString(); + } +} + + diff --git a/basic/source/sbx/sbxsng.cxx b/basic/source/sbx/sbxsng.cxx new file mode 100644 index 000000000000..71cefc252660 --- /dev/null +++ b/basic/source/sbx/sbxsng.cxx @@ -0,0 +1,362 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxsng.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +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 ); + } +} + diff --git a/basic/source/sbx/sbxstr.cxx b/basic/source/sbx/sbxstr.cxx new file mode 100644 index 000000000000..8fb2a58a4895 --- /dev/null +++ b/basic/source/sbx/sbxstr.cxx @@ -0,0 +1,324 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxstr.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" +#include "sbxres.hxx" +#include "runtime.hxx" +#ifndef _RTL_USTRBUF_HXX_ +#include <rtl/ustrbuf.hxx> +#endif +// AB 29.10.99 Unicode +#ifndef _USE_NO_NAMESPACE +using namespace rtl; +#endif + + +// 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 if( p->pObj && p->pObj->IsFixed() + && (p->pObj->GetType() == (SbxARRAY | SbxBYTE )) ) + { + // convert byte array to string + SbxArray* pArr = PTR_CAST(SbxArray, p->pObj); + if( pArr ) + aRes = ByteArrayToString( pArr ); + } + 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; +} + +// Convert string to an array of bytes, preserving unicode (2bytes per character) +SbxArray* StringToByteArray(const String& rStr) +{ + USHORT nArraySize = rStr.Len() * 2; + const sal_Unicode* pSrc = rStr.GetBuffer(); + SbxDimArray* pArray = new SbxDimArray(SbxBYTE); + bool bIncIndex = ( IsBaseIndexOne() && SbiRuntime::isVBAEnabled() ); + if( nArraySize ) + { + if( bIncIndex ) + pArray->AddDim( 1, nArraySize ); + else + pArray->AddDim( 0, nArraySize-1 ); + } + else + { + pArray->unoAddDim( 0, -1 ); + } + + for( USHORT i=0; i< nArraySize; i++) + { + SbxVariable* pNew = new SbxVariable( SbxBYTE ); + BYTE aByte = static_cast< BYTE >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff ); + pNew->PutByte( aByte ); + pNew->SetFlag( SBX_WRITE ); + pArray->Put( pNew, i ); + if( i%2 ) + pSrc++; + } + return pArray; +} + +// Convert an array of bytes to string (2bytes per character) +String ByteArrayToString(SbxArray* pArr) +{ + USHORT nCount = pArr->Count(); + OUStringBuffer aStrBuf; + sal_Unicode aChar = 0; + for( USHORT i = 0 ; i < nCount ; i++ ) + { + sal_Unicode aTempChar = pArr->Get(i)->GetByte(); + if( i%2 ) + { + aChar = (aTempChar << 8 ) | aChar; + aStrBuf.append(aChar); + aChar = 0; + } + else + { + aChar = aTempChar; + } + } + + if( nCount%2 ) + { + aStrBuf.append(aChar); + } + + String aStr(aStrBuf.makeStringAndClear()); + + return aStr; +} diff --git a/basic/source/sbx/sbxuint.cxx b/basic/source/sbx/sbxuint.cxx new file mode 100644 index 000000000000..6f1e91fc583a --- /dev/null +++ b/basic/source/sbx/sbxuint.cxx @@ -0,0 +1,334 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxuint.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +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 ); + } +} + diff --git a/basic/source/sbx/sbxulng.cxx b/basic/source/sbx/sbxulng.cxx new file mode 100644 index 000000000000..d42e78805314 --- /dev/null +++ b/basic/source/sbx/sbxulng.cxx @@ -0,0 +1,324 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxulng.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/errcode.hxx> +#include <basic/sbx.hxx> +#include "sbxconv.hxx" + +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 ); + } +} + diff --git a/basic/source/sbx/sbxvals.cxx b/basic/source/sbx/sbxvals.cxx new file mode 100644 index 000000000000..b9e59aa5308e --- /dev/null +++ b/basic/source/sbx/sbxvals.cxx @@ -0,0 +1,112 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxvals.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#define _TLBIGINT_INT64 +#include <tools/bigint.hxx> +#include <basic/sbx.hxx> + +///////////////////////////// BigInt/Currency ////////////////////////////// + +SbxValues::SbxValues( const BigInt &rBig ) : eType(SbxCURRENCY) +{ + rBig.INT64( &nLong64 ); +} + +//TODO: BigInt is TOOLS_DLLPUBLIC, and its four member functions only declared +// and defined within basic (#define _TLBIGINT_INT64) are a bad hack that causes +// "warning C4273: 'function' : inconsistent dll linkage" on MSC; this whole +// mess should be cleaned up properly (e.g., by completely removing Sbx[U]INT64 +// and using sal_[u]Int64 instead): +#if defined _MSC_VER +#pragma warning(disable: 4273) +#endif + +BOOL BigInt::INT64( SbxINT64 *p ) const +{ + if( bIsBig ) { + if( nLen > 4 || (nNum[3] & 0x8000) ) + return FALSE; + + p->nLow = ((UINT32)nNum[1] << 16) | (UINT32)nNum[0]; + p->nHigh = ((UINT32)nNum[3] << 16) | (UINT32)nNum[2]; + if( bIsNeg ) + p->CHS(); + } + else + p->Set( (INT32)nVal ); + + return TRUE; +} + +BigInt::BigInt( const SbxINT64 &r ) +{ + BigInt a10000 = 0x10000; + + *this = r.nHigh; + if( r.nHigh ) + *this *= a10000; + *this += (USHORT)(r.nLow >> 16); + *this *= a10000; + *this += (USHORT)r.nLow; +} + +BOOL BigInt::UINT64( SbxUINT64 *p ) const +{ + if( bIsBig ) { + if( bIsNeg || nLen > 4 ) + return FALSE; + + p->nLow = ((UINT32)nNum[1] << 16) | (UINT32)nNum[0]; + p->nHigh = ((UINT32)nNum[3] << 16) | (UINT32)nNum[2]; + } + else { + if( nVal < 0 ) + return FALSE; + + p->Set( (UINT32)nVal ); + } + + return TRUE; +} + +BigInt::BigInt( const SbxUINT64 &r ) +{ + BigInt a10000 = 0x10000; + + *this = BigInt(r.nHigh); + if( r.nHigh ) + *this *= a10000; + *this += (USHORT)(r.nLow >> 16); + *this *= a10000; + *this += (USHORT)r.nLow; +} diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx new file mode 100644 index 000000000000..ca21908ece78 --- /dev/null +++ b/basic/source/sbx/sbxvalue.cxx @@ -0,0 +1,1854 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxvalue.cxx,v $ + * $Revision: 1.14 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + +#define _TLBIGINT_INT64 +#include <tools/bigint.hxx> +#include <tools/stream.hxx> + +#include <basic/sbx.hxx> +#include "sbxconv.hxx" +#include <math.h> +#include "runtime.hxx" +// AB 29.10.99 Unicode +#ifndef _USE_NO_NAMESPACE +using namespace rtl; +#endif + + +TYPEINIT1(SbxValue,SbxBase) + +/////////////////////////// SbxINT64 ///////////////////////////////////// +SbxINT64 &SbxINT64::operator -= ( const SbxINT64 &r ) +{ + BigInt b( *this ); + b -= BigInt( r ); + b.INT64( this ); + return *this; +} +SbxINT64 &SbxINT64::operator += ( const SbxINT64 &r ) +{ + BigInt b( *this ); + b += BigInt( r ); + b.INT64( this ); + return *this; +} +SbxINT64 &SbxINT64::operator *= ( const SbxINT64 &r ) +{ + BigInt b( *this ); + b *= BigInt( r ); + b.INT64( this ); + return *this; +} +SbxINT64 &SbxINT64::operator %= ( const SbxINT64 &r ) +{ + BigInt b( *this ); + b %= BigInt( r ); + b.INT64( this ); + return *this; +} +SbxINT64 &SbxINT64::operator /= ( const SbxINT64 &r ) +{ + BigInt b( *this ); + b /= BigInt( r ); + b.INT64( 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( *this ); + b %= BigInt( r ); + b.UINT64( this ); + return *this; +} +SbxUINT64 &SbxUINT64::operator /= ( const SbxUINT64 &r ) +{ + BigInt b( *this ); + b /= BigInt( r ); + b.UINT64( 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 + { + // string -> byte array + if( IsFixed() && (aData.eType == SbxOBJECT) + && aData.pObj && ( aData.pObj->GetType() == (SbxARRAY | SbxBYTE) ) + && (r.aData.eType == SbxSTRING) ) + { + String aStr = r.GetString(); + SbxArray* pArr = StringToByteArray(aStr); + PutObject(pArr); + return *this; + } + // byte array -> string + if( r.IsFixed() && (r.aData.eType == SbxOBJECT) + && r.aData.pObj && ( r.aData.pObj->GetType() == (SbxARRAY | SbxBYTE) ) + && (aData.eType == SbxSTRING) ) + { + SbxBase* pObj = r.GetObject(); + SbxArray* pArr = PTR_CAST(SbxArray, pObj); + if( pArr ) + { + String aStr = ByteArrayToString( pArr ); + PutString(aStr); + return *this; + } + } + // 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; +} + +BOOL SbxValue::GetNoBroadcast( SbxValues& rRes ) +{ + USHORT nFlags_ = GetFlags(); + SetFlag( SBX_NO_BROADCAST ); + BOOL bRes = Get( rRes ); + SetFlags( nFlags_ ); + 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::HasObject() const +{ + ErrCode eErr = GetError(); + SbxValues aRes; + aRes.eType = SbxOBJECT; + Get( aRes ); + SetError( eErr ); + return 0 != aRes.pObj; +} + +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( GetData, SbxDATAOBJECT, void*, pData ) +GET( GetDouble, SbxDOUBLE, double, nDouble ) +GET( GetErr, SbxERROR, UINT16, nUShort ) +GET( GetInt, SbxINT, int, nInt ) +GET( GetInteger, SbxINTEGER, INT16, nInteger ) +GET( GetLong, SbxLONG, INT32, nLong ) +GET( GetLong64, SbxLONG64, SbxINT64, nLong64 ) +GET( GetObject, SbxOBJECT, SbxBase*, pObj ) +GET( GetSingle, SbxSINGLE, float, nSingle ) +GET( GetULong, SbxULONG, UINT32, nULong ) +GET( GetULong64, SbxULONG64, SbxUINT64, nULong64 ) +GET( GetUShort, SbxUSHORT, UINT16, nUShort ) +GET( GetInt64, SbxSALINT64, sal_Int64, nInt64 ) +GET( GetUInt64, SbxSALUINT64, sal_uInt64, uInt64 ) +GET( GetDecimal, SbxDECIMAL, SbxDecimal*, pDecimal ) + + +//////////////////////////// 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; +} + +// AB, 28.3.96: +// Methode, um bei speziellen Typen eine Vorbehandlung des Strings +// durchzufuehren. Insbesondere erforderlich fuer BASIC-IDE, damit +// die Ausgaben im Watch-Fenster mit PutStringExt zurueckgeschrieben +// werden koennen, wenn Floats mit ',' als Dezimaltrenner oder BOOLs +// explizit mit "TRUE" oder "FALSE" angegeben werden. +// Implementierung in ImpConvStringExt (SBXSCAN.CXX) +BOOL SbxValue::PutStringExt( const XubString& r ) +{ + // Kopieren, bei Unicode gleich konvertieren + String aStr( r ); + + // Eigenen Typ bestimmen (nicht wie in Put() mit TheRealValue(), + // Objekte werden sowieso nicht behandelt) + SbxDataType eTargetType = SbxDataType( aData.eType & 0x0FFF ); + + // Source-Value basteln + SbxValues aRes; + aRes.eType = SbxSTRING; + + // Nur, wenn wirklich was konvertiert wurde, Kopie nehmen, + // sonst Original (Unicode bleibt erhalten) + BOOL bRet; + if( ImpConvStringExt( aStr, eTargetType ) ) + aRes.pString = (XubString*)&aStr; + else + aRes.pString = (XubString*)&r; + + // #34939: Bei Strings. die eine Zahl enthalten und wenn this einen + // Num-Typ hat, Fixed-Flag setzen, damit der Typ nicht veraendert wird + USHORT nFlags_ = GetFlags(); + if( ( eTargetType >= SbxINTEGER && eTargetType <= SbxCURRENCY ) || + ( eTargetType >= SbxCHAR && eTargetType <= SbxUINT ) || + eTargetType == SbxBOOL ) + { + SbxValue aVal; + aVal.Put( aRes ); + if( aVal.IsNumeric() ) + SetFlag( SBX_FIXED ); + } + + Put( aRes ); + bRet = BOOL( !IsError() ); + + // Falls das mit dem FIXED einen Error gegeben hat, zuruecksetzen + // (UI-Aktion sollte keinen Error ergeben, sondern nur scheitern) + if( !bRet ) + ResetError(); + + SetFlags( nFlags_ ); + return bRet; +} + +BOOL SbxValue::PutString( const xub_Unicode* p ) +{ + XubString aVal( p ); + SbxValues aRes; + aRes.eType = SbxSTRING; + aRes.pString = &aVal; + Put( aRes ); + return BOOL( !IsError() ); +} + +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::PutNull() +{ + BOOL bRet = SetType( SbxNULL ); + if( bRet ) + SetModified( TRUE ); + return bRet; +} + + +// Special decimal methods +BOOL SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec ) +{ + SbxValue::Clear(); + aData.pDecimal = new SbxDecimal( rAutomationDec ); + aData.pDecimal->addRef(); + aData.eType = SbxDECIMAL; + return TRUE; +} + +BOOL SbxValue::fillAutomationDecimal + ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec ) +{ + SbxDecimal* pDecimal = GetDecimal(); + if( pDecimal != NULL ) + { + pDecimal->fillAutomationDecimal( rAutomationDec ); + return TRUE; + } + return FALSE; +} + + +BOOL SbxValue::PutpChar( const xub_Unicode* p ) +{ + XubString aVal( p ); + SbxValues aRes; + aRes.eType = SbxLPSTR; + aRes.pString = &aVal; + Put( aRes ); + return BOOL( !IsError() ); +} + +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( PutData, SbxDATAOBJECT, void*, pData ) +PUT( PutDouble, SbxDOUBLE, double, nDouble ) +PUT( PutErr, SbxERROR, UINT16, nUShort ) +PUT( PutInt, SbxINT, int, nInt ) +PUT( PutInteger, SbxINTEGER, INT16, nInteger ) +PUT( PutLong, SbxLONG, INT32, nLong ) +PUT( PutLong64, SbxLONG64, const SbxINT64&, nLong64 ) +PUT( PutObject, SbxOBJECT, SbxBase*, pObj ) +PUT( PutSingle, SbxSINGLE, float, nSingle ) +PUT( PutULong, SbxULONG, UINT32, nULong ) +PUT( PutULong64, SbxULONG64, const SbxUINT64&, nULong64 ) +PUT( PutUShort, SbxUSHORT, UINT16, nUShort ) +PUT( PutInt64, SbxSALINT64, sal_Int64, nInt64 ) +PUT( PutUInt64, SbxSALUINT64, sal_uInt64, uInt64 ) +PUT( PutDecimal, SbxDECIMAL, SbxDecimal*, pDecimal ) + + +////////////////////////// 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::IsNumericRTL() const +{ + return ImpIsNumeric( /*bOnlyIntntl*/TRUE ); +} + +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 ) +{ + bool bVBAInterop = SbiRuntime::isVBAEnabled(); + + 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 + && !bVBAInterop + ) + *this = rOp; + // 13.2.96: Nicht schon vor Get auf SbxEMPTY pruefen + else + { + SbxValues aL, aR; + bool bDecimal = false; + if( bVBAInterop && ( ( eThisType == SbxSTRING && eOpType != SbxSTRING ) || + ( eThisType != SbxSTRING && eOpType == SbxSTRING ) ) && + ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS ) ) + { + goto Lbl_OpIsDouble; + } + else if( eThisType == SbxSTRING || eOp == SbxCAT || ( bVBAInterop && ( eOpType == SbxSTRING ) && ( eOp == SbxPLUS ) ) ) + { + 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 ) + { + if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNOT ) ) ) + 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( aL.nLong64 ); + BigInt b2( aR.nLong64 ); + b1 *= b2; + b1 /= n10K; + double d = double( b1 ) / 10000.0; + if( d > SbxMAXCURR || d < SbxMINCURR ) + SetError( SbxERR_OVERFLOW ); + else + b1.INT64( &aL.nLong64 ); + break; + } + case SbxDIV: + if( !aR.nLong64 ) + { + SetError( SbxERR_ZERODIV ); + } + else + { + // #i20704 Implement directly + BigInt b1( aL.nLong64 ); + BigInt b2( aR.nLong64 ); + b1 *= n10K; + b1 /= b2; + double d = double( b1 ) / 10000.0; + if( d > SbxMAXCURR || d < SbxMINCURR ) + SetError( SbxERR_OVERFLOW ); + else + b1.INT64( &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 +Lbl_OpIsDouble: + { // Andere Operatoren + aL.eType = aR.eType = SbxDOUBLE; + if( rOp.Get( aR ) ) + { + if( rOp.GetType() == SbxEMPTY ) + { + if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNEG ) ) ) + 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 bVBAInterop = SbiRuntime::isVBAEnabled(); + + 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 && !bVBAInterop ) + { + bRes = TRUE; + } + else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY ) + bRes = !bVBAInterop ? TRUE : ( eOp == SbxEQ ? TRUE : FALSE ); + // 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() ) && !bVBAInterop + ) + bRes = BOOL( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE ); + else if( !IsFixed() && !rOp.IsFixed() + && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() ) +&& !bVBAInterop + ) + 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 ) ) + bool bGetL = Get( aL );
+ bool bGetR = rOp.Get( aR );
+ if( bGetL && bGetR )
+ 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 ); + } + // at least one value was got
+ // if this is VBA then a conversion error for one
+ // side will yield a false result of an equality test
+ else if ( bGetR || bGetL )
+ {
+ if ( bVBAInterop && eOp == SbxEQ && GetError() == SbxERR_CONVERSION )
+ {
+ ResetError();
+ bRes = FALSE;
+ }
+ }
+ } + } + 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; +} + diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx new file mode 100644 index 000000000000..66c56adc731a --- /dev/null +++ b/basic/source/sbx/sbxvar.cxx @@ -0,0 +1,588 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbxvar.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" + + +#include <tools/stream.hxx> +#include "svtools/brdcst.hxx" + +#include <basic/sbx.hxx> +#include <basic/sbxbase.hxx> +#include "sbxres.hxx" +#include "sbxconv.hxx" +#include <math.h> +#include <ctype.h> + +///////////////////////////// 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::SetInfo( SbxInfo* p ) +{ + pInfo = p; +} + +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 ); + UINT32 nTemp; + rStrm >> nTemp; + nUserData = nTemp; + } + else + { + rStrm.SeekRel( -1L ); + rStrm >> nType; + rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US ); + UINT32 nTemp; + rStrm >> nTemp; + nUserData = nTemp; + // 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 << (UINT32)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() +{} + +SbxInfo::SbxInfo( const String& r, UINT32 n ) + : aHelpFile( r ), nHelpId( n ), aParams() +{} + +////////////////////////////// SbxAlias ////////////////////////////////// + +SbxAlias::SbxAlias( const XubString& rName, SbxVariable* p ) + : SbxVariable(), xAlias( p ) +{ + SetName( rName ); + SetFlags( p->GetFlags() ); + SetFlag( SBX_DONTSTORE ); + aData.eType = p->GetType(); + StartListening( p->GetBroadcaster() ); +} + +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; +} + diff --git a/basic/source/uno/dlgcont.cxx b/basic/source/uno/dlgcont.cxx new file mode 100644 index 000000000000..f7e5f9a842e4 --- /dev/null +++ b/basic/source/uno/dlgcont.cxx @@ -0,0 +1,658 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dlgcont.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include "com/sun/star/resource/XStringResourceWithStorage.hpp" +#include "com/sun/star/resource/XStringResourceWithLocation.hpp" +#include "dlgcont.hxx" +#include "sbmodule.hxx" +#include <comphelper/processfactory.hxx> +#include <unotools/streamwrap.hxx> +#include <osl/mutex.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <svtools/pathoptions.hxx> +#include <xmlscript/xmldlg_imexp.hxx> +#include <cppuhelper/factory.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> + + +namespace basic +{ + +using namespace com::sun::star::document; +using namespace com::sun::star::container; +using namespace com::sun::star::io; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::lang; +using namespace com::sun::star::script; +using namespace com::sun::star::xml::sax; +using namespace com::sun::star; +using namespace cppu; +using namespace rtl; +using namespace osl; + +using com::sun::star::uno::Reference; + +//============================================================================ +// Implementation class SfxDialogLibraryContainer + +const sal_Char* SAL_CALL SfxDialogLibraryContainer::getInfoFileName() const { return "dialog"; } +const sal_Char* SAL_CALL SfxDialogLibraryContainer::getOldInfoFileName() const { return "dialogs"; } +const sal_Char* SAL_CALL SfxDialogLibraryContainer::getLibElementFileExtension() const { return "xdl"; } +const sal_Char* SAL_CALL SfxDialogLibraryContainer::getLibrariesDir() const { return "Dialogs"; } + +// Ctor for service +SfxDialogLibraryContainer::SfxDialogLibraryContainer( void ) +{ + // all initialisation has to be done + // by calling XInitialization::initialize +} + +SfxDialogLibraryContainer::SfxDialogLibraryContainer( const uno::Reference< embed::XStorage >& xStorage ) +{ + init( OUString(), xStorage ); +} + +// Methods to get library instances of the correct type +SfxLibrary* SfxDialogLibraryContainer::implCreateLibrary( const ::rtl::OUString& aName ) +{ + SfxLibrary* pRet = new SfxDialogLibrary( maModifiable, aName, mxMSF, mxSFI, this ); + return pRet; +} + +SfxLibrary* SfxDialogLibraryContainer::implCreateLibraryLink + ( const ::rtl::OUString& aName, const OUString& aLibInfoFileURL, + const OUString& StorageURL, sal_Bool ReadOnly ) +{ + SfxLibrary* pRet = new SfxDialogLibrary + ( maModifiable, aName, mxMSF, mxSFI, aLibInfoFileURL, StorageURL, ReadOnly, this ); + return pRet; +} + +Any SAL_CALL SfxDialogLibraryContainer::createEmptyLibraryElement( void ) +{ + Reference< XInputStreamProvider > xISP; + Any aRetAny; + aRetAny <<= xISP; + return aRetAny; +} + +bool SAL_CALL SfxDialogLibraryContainer::isLibraryElementValid( Any aElement ) const +{ + return SfxDialogLibrary::containsValidDialog( aElement ); +} + +bool writeOasis2OOoLibraryElement( + Reference< XInputStream > xInput, Reference< XOutputStream > xOutput ) +{ + Reference< XMultiServiceFactory > xMSF( + comphelper::getProcessServiceFactory() ); + + Reference< XComponentContext > xContext; + Reference< beans::XPropertySet > xProps( xMSF, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + OSL_VERIFY( xProps->getPropertyValue( + OUString::createFromAscii(("DefaultContext")) ) >>= xContext ); + + Reference< lang::XMultiComponentFactory > xSMgr( + xContext->getServiceManager() ); + + if (! xSMgr.is()) + { + return FALSE; + } + + Reference< xml::sax::XParser > xParser( + xSMgr->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.sax.Parser" ) ), + xContext ), + UNO_QUERY ); + + Reference< xml::sax::XExtendedDocumentHandler > xWriter( + xSMgr->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.sax.Writer" ) ), + xContext ), + UNO_QUERY ); + + Reference< io::XActiveDataSource > xSource( xWriter, UNO_QUERY ); + xSource->setOutputStream( xOutput ); + + if ( !xParser.is() || !xWriter.is() ) + { + return FALSE; + } + + Sequence<Any> aArgs( 1 ); + aArgs[0] <<= xWriter; + + Reference< xml::sax::XDocumentHandler > xHandler( + xSMgr->createInstanceWithArgumentsAndContext( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Oasis2OOoTransformer" ) ), + aArgs, xContext ), + UNO_QUERY ); + + xParser->setDocumentHandler( xHandler ); + + xml::sax::InputSource source; + source.aInputStream = xInput; + source.sSystemId = OUString::createFromAscii( "virtual file" ); + + xParser->parseStream( source ); + + return TRUE; +} + +void SAL_CALL SfxDialogLibraryContainer::writeLibraryElement +( + Any aElement, + const OUString& /*aElementName*/, + Reference< XOutputStream > xOutput +) + throw(Exception) +{ + Reference< XInputStreamProvider > xISP; + aElement >>= xISP; + if( !xISP.is() ) + return; + + Reference< XInputStream > xInput( xISP->createInputStream() ); + + bool bComplete = FALSE; + if ( mbOasis2OOoFormat ) + { + bComplete = writeOasis2OOoLibraryElement( xInput, xOutput ); + } + + if ( bComplete == FALSE ) + { + Sequence< sal_Int8 > bytes; + sal_Int32 nRead = xInput->readBytes( bytes, xInput->available() ); + for (;;) + { + if( nRead ) + xOutput->writeBytes( bytes ); + + nRead = xInput->readBytes( bytes, 1024 ); + if (! nRead) + break; + } + } + xInput->closeInput(); +} + +void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference< embed::XStorage >& xStorage ) throw ( RuntimeException ) +{ + LibraryContainerMethodGuard aGuard( *this ); + mbOasis2OOoFormat = sal_False; + + if ( mxStorage.is() && xStorage.is() ) + { + try + { + long nSource = SotStorage::GetVersion( mxStorage ); + long nTarget = SotStorage::GetVersion( xStorage ); + + if ( nSource == SOFFICE_FILEFORMAT_CURRENT && + nTarget != SOFFICE_FILEFORMAT_CURRENT ) + { + mbOasis2OOoFormat = sal_True; + } + } + catch ( Exception& ) + { + // if we cannot get the version then the + // Oasis2OOoTransformer will not be used + OSL_ASSERT(FALSE); + } + } + + SfxLibraryContainer::storeLibrariesToStorage( xStorage ); + + mbOasis2OOoFormat = sal_False; +} + + +Any SAL_CALL SfxDialogLibraryContainer::importLibraryElement + ( const OUString& aFile, const uno::Reference< io::XInputStream >& xElementStream ) +{ + Any aRetAny; + + // TODO: Member because later it will be a component + //Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() ); + //if( !xMSF.is() ) + //{ + // OSL_ENSURE( 0, "### couln't get ProcessServiceFactory\n" ); + // return aRetAny; + //} + + Reference< XParser > xParser( mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY ); + if( !xParser.is() ) + { + OSL_ENSURE( 0, "### couln't create sax parser component\n" ); + return aRetAny; + } + + Reference< XNameContainer > xDialogModel( mxMSF->createInstance + ( OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ) ), UNO_QUERY ); + if( !xDialogModel.is() ) + { + OSL_ENSURE( 0, "### couln't create com.sun.star.awt.UnoControlDialogModel component\n" ); + return aRetAny; + } + + // Read from storage? + sal_Bool bStorage = xElementStream.is(); + Reference< XInputStream > xInput; + + if( bStorage ) + { + xInput = xElementStream; + } + else + { + try + { + xInput = mxSFI->openFileRead( aFile ); + } + catch( Exception& ) + //catch( Exception& e ) + { + // TODO: + //throw WrappedTargetException( e ); + } + } + if( !xInput.is() ) + return aRetAny; + + Reference< XComponentContext > xContext; + Reference< beans::XPropertySet > xProps( mxMSF, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + OSL_VERIFY( xProps->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext ); + + InputSource source; + source.aInputStream = xInput; + source.sSystemId = aFile; + + try { + // start parsing + xParser->setDocumentHandler( ::xmlscript::importDialogModel( xDialogModel, xContext ) ); + xParser->parseStream( source ); + } + catch( Exception& ) + { + OSL_ENSURE( 0, "Parsing error\n" ); + SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + return aRetAny; + } + + // Create InputStream, TODO: Implement own InputStreamProvider + // to avoid creating the DialogModel here! + Reference< XInputStreamProvider > xISP = ::xmlscript::exportDialogModel( xDialogModel, xContext ); + aRetAny <<= xISP; + return aRetAny; +} + +void SAL_CALL SfxDialogLibraryContainer::importFromOldStorage( const OUString& ) +{ + // Nothing to do here, old dialogs cannot be imported +} + +SfxLibraryContainer* SfxDialogLibraryContainer::createInstanceImpl( void ) +{ + return new SfxDialogLibraryContainer(); +} + + +static OUString aResourceFileNameBase = OUString::createFromAscii( "DialogStrings" ); +static OUString aResourceFileCommentBase = OUString::createFromAscii( "# Strings for Dialog Library " ); + +// Resource handling +Reference< ::com::sun::star::resource::XStringResourcePersistence > + SfxDialogLibraryContainer::implCreateStringResource( SfxDialogLibrary* pDialogLibrary ) +{ + Reference< resource::XStringResourcePersistence > xRet; + OUString aLibName = pDialogLibrary->getName(); + bool bReadOnly = pDialogLibrary->mbReadOnly; + + // get ui locale + ::com::sun ::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); + + OUString aComment = aResourceFileCommentBase; + aComment += aLibName; + + sal_Bool bStorage = mxStorage.is(); + if( bStorage ) + { + Sequence<Any> aArgs( 5 ); + aArgs[1] <<= bReadOnly; + aArgs[2] <<= aLocale; + aArgs[3] <<= aResourceFileNameBase; + aArgs[4] <<= aComment; + + // TODO: Ctor + xRet = Reference< resource::XStringResourcePersistence >( mxMSF->createInstance + ( OUString::createFromAscii( "com.sun.star.resource.StringResourceWithStorage" ) ), UNO_QUERY ); + + uno::Reference< embed::XStorage > xLibrariesStor; + uno::Reference< embed::XStorage > xLibraryStor; + try { + xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); + // TODO: Should be READWRITE with new storage concept using store() instead of storeTo() + if ( !xLibrariesStor.is() ) + throw uno::RuntimeException(); + + xLibraryStor = xLibrariesStor->openStorageElement( aLibName, embed::ElementModes::READ ); + // TODO: Should be READWRITE with new storage concept using store() instead of storeTo() + if ( !xLibraryStor.is() ) + throw uno::RuntimeException(); + + aArgs[0] <<= xLibraryStor; + } + catch( uno::Exception& ) + { + // TODO: Error handling? + return xRet; + } + + // TODO: Ctor + if( xRet.is() ) + { + Reference< XInitialization > xInit( xRet, UNO_QUERY ); + if( xInit.is() ) + xInit->initialize( aArgs ); + } + } + else + { + Sequence<Any> aArgs( 6 ); + + OUString aLocation = createAppLibraryFolder( pDialogLibrary, aLibName ); + aArgs[0] <<= aLocation; + aArgs[1] <<= bReadOnly; + aArgs[2] <<= aLocale; + aArgs[3] <<= aResourceFileNameBase; + aArgs[4] <<= aComment; + + // TODO: Real handler? + Reference< task::XInteractionHandler > xDummyHandler; + aArgs[5] <<= xDummyHandler; + + // TODO: Ctor + xRet = Reference< resource::XStringResourcePersistence >( mxMSF->createInstance + ( OUString::createFromAscii( "com.sun.star.resource.StringResourceWithLocation" ) ), UNO_QUERY ); + + // TODO: Ctor + if( xRet.is() ) + { + Reference< XInitialization > xInit( xRet, UNO_QUERY ); + if( xInit.is() ) + xInit->initialize( aArgs ); + } + } + + return xRet; +} + +void SfxDialogLibraryContainer::onNewRootStorage() +{ + // the library container is not modified, go through the libraries and check whether they are modified + Sequence< OUString > aNames = maNameContainer.getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nNameCount = aNames.getLength(); + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aName = pNames[ i ]; + SfxDialogLibrary* pDialogLibrary = static_cast<SfxDialogLibrary*>( getImplLib( aName ) ); + + Reference< resource::XStringResourcePersistence > xStringResourcePersistence = + pDialogLibrary->getStringResourcePersistence(); + + if( xStringResourcePersistence.is() ) + { + Reference< embed::XStorage > xLibrariesStor; + Reference< embed::XStorage > xLibraryStor; + try { + xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READWRITE ); + if ( !xLibrariesStor.is() ) + throw uno::RuntimeException(); + + OUString aLibName = pDialogLibrary->getName(); + xLibraryStor = xLibrariesStor->openStorageElement( aLibName, embed::ElementModes::READWRITE ); + if ( !xLibraryStor.is() ) + throw uno::RuntimeException(); + + Reference< resource::XStringResourceWithStorage > + xStringResourceWithStorage( xStringResourcePersistence, UNO_QUERY ); + if( xStringResourceWithStorage.is() ) + xStringResourceWithStorage->setStorage( xLibraryStor ); + } + catch( uno::Exception& ) + { + // TODO: Error handling? + } + } + } +} + + +//============================================================================ +// Service + +void createRegistryInfo_SfxDialogLibraryContainer() +{ + static OAutoRegistration< SfxDialogLibraryContainer > aAutoRegistration; +} + +::rtl::OUString SAL_CALL SfxDialogLibraryContainer::getImplementationName( ) throw (RuntimeException) +{ + return getImplementationName_static(); +} + +Sequence< ::rtl::OUString > SAL_CALL SfxDialogLibraryContainer::getSupportedServiceNames( ) throw (RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +Sequence< OUString > SfxDialogLibraryContainer::getSupportedServiceNames_static() +{ + Sequence< OUString > aServiceNames( 2 ); + aServiceNames[0] = OUString::createFromAscii( "com.sun.star.script.DocumentDialogLibraryContainer" ); + // plus, for compatibility: + aServiceNames[1] = OUString::createFromAscii( "com.sun.star.script.DialogLibraryContainer" ); + return aServiceNames; +} + +OUString SfxDialogLibraryContainer::getImplementationName_static() +{ + static OUString aImplName; + static sal_Bool bNeedsInit = sal_True; + + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if( bNeedsInit ) + { + aImplName = OUString::createFromAscii( "com.sun.star.comp.sfx2.DialogLibraryContainer" ); + bNeedsInit = sal_False; + } + return aImplName; +} + +Reference< XInterface > SAL_CALL SfxDialogLibraryContainer::Create( const Reference< XComponentContext >& ) throw( Exception ) +{ + Reference< XInterface > xRet = + static_cast< XInterface* >( static_cast< OWeakObject* >(new SfxDialogLibraryContainer()) ); + return xRet; +} + + +//============================================================================ +// Implementation class SfxDialogLibrary + +// Ctor +SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper& _rModifiable, + const ::rtl::OUString& aName, + const Reference< XMultiServiceFactory >& xMSF, + const Reference< XSimpleFileAccess >& xSFI, + SfxDialogLibraryContainer* pParent ) + : SfxLibrary( _rModifiable, getCppuType( (const Reference< XInputStreamProvider > *)0 ), xMSF, xSFI ) + , m_pParent( pParent ) + , m_aName( aName ) +{ +} + +SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper& _rModifiable, + const ::rtl::OUString& aName, + const Reference< XMultiServiceFactory >& xMSF, + const Reference< XSimpleFileAccess >& xSFI, + const OUString& aLibInfoFileURL, + const OUString& aStorageURL, + sal_Bool ReadOnly, + SfxDialogLibraryContainer* pParent ) + : SfxLibrary( _rModifiable, getCppuType( (const Reference< XInputStreamProvider > *)0 ), + xMSF, xSFI, aLibInfoFileURL, aStorageURL, ReadOnly) + , m_pParent( pParent ) + , m_aName( aName ) +{ +} + +IMPLEMENT_FORWARD_XINTERFACE2( SfxDialogLibrary, SfxLibrary, SfxDialogLibrary_BASE ); +IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxDialogLibrary, SfxLibrary, SfxDialogLibrary_BASE ); + +// Provide modify state including resources +sal_Bool SfxDialogLibrary::isModified( void ) +{ + sal_Bool bRet = implIsModified(); + + if( !bRet && m_xStringResourcePersistence.is() ) + bRet = m_xStringResourcePersistence->isModified(); + // else: Resources not accessed so far -> not modified + + return bRet; +} + +void SfxDialogLibrary::storeResources( void ) +{ + if( m_xStringResourcePersistence.is() ) + m_xStringResourcePersistence->store(); +} + +void SfxDialogLibrary::storeResourcesAsURL + ( const ::rtl::OUString& URL, const ::rtl::OUString& NewName ) +{ + OUString aComment = aResourceFileCommentBase; + m_aName = NewName; + aComment += m_aName; + + if( m_xStringResourcePersistence.is() ) + { + m_xStringResourcePersistence->setComment( aComment ); + + Reference< resource::XStringResourceWithLocation > + xStringResourceWithLocation( m_xStringResourcePersistence, UNO_QUERY ); + if( xStringResourceWithLocation.is() ) + xStringResourceWithLocation->storeAsURL( URL ); + } +} + +void SfxDialogLibrary::storeResourcesToURL( const OUString& URL, + const Reference< task::XInteractionHandler >& xHandler ) +{ + OUString aComment = aResourceFileCommentBase; + aComment += m_aName; + + if( m_xStringResourcePersistence.is() ) + { + m_xStringResourcePersistence->storeToURL + ( URL, aResourceFileNameBase, aComment, xHandler ); + } +} + +void SfxDialogLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference + < ::com::sun::star::embed::XStorage >& xStorage ) +{ + OUString aComment = aResourceFileCommentBase; + aComment += m_aName; + + if( m_xStringResourcePersistence.is() ) + { + m_xStringResourcePersistence->storeToStorage + ( xStorage, aResourceFileNameBase, aComment ); + } +} + + +// XStringResourceSupplier +Reference< resource::XStringResourceResolver > + SAL_CALL SfxDialogLibrary::getStringResource( ) throw (RuntimeException) +{ + if( !m_xStringResourcePersistence.is() ) + m_xStringResourcePersistence = m_pParent->implCreateStringResource( this ); + + Reference< resource::XStringResourceResolver > xRet( m_xStringResourcePersistence, UNO_QUERY ); + return xRet; +} + +bool SfxDialogLibrary::containsValidDialog( const ::com::sun::star::uno::Any& aElement ) +{ + Reference< XInputStreamProvider > xISP; + aElement >>= xISP; + return xISP.is(); +} + +bool SAL_CALL SfxDialogLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const +{ + return SfxDialogLibrary::containsValidDialog( aElement ); +} + +} +//============================================================================ + diff --git a/basic/source/uno/makefile.mk b/basic/source/uno/makefile.mk new file mode 100644 index 000000000000..c77ad7a2d5e6 --- /dev/null +++ b/basic/source/uno/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=basic +TARGET=uno + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +SLOFILES= \ + $(SLO)$/namecont.obj \ + $(SLO)$/scriptcont.obj \ + $(SLO)$/dlgcont.obj \ + $(SLO)$/sbmodule.obj \ + $(SLO)$/sbservices.obj \ + $(SLO)$/modsizeexceeded.obj + +# --- Targets -------------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/basic/source/uno/modsizeexceeded.cxx b/basic/source/uno/modsizeexceeded.cxx new file mode 100644 index 000000000000..4e324a4702ef --- /dev/null +++ b/basic/source/uno/modsizeexceeded.cxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: modsizeexceeded.cxx,v $ + * $Revision: 1.3 $ + * + * 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 "modsizeexceeded.hxx" + +#include <framework/interaction.hxx> +#include <com/sun/star/script/ModuleSizeExceededRequest.hpp> + +using namespace com::sun::star; +using namespace cppu; +using namespace rtl; +using namespace osl; + +ModuleSizeExceeded::ModuleSizeExceeded( const uno::Sequence< ::rtl::OUString >& sModules ) +{ + script::ModuleSizeExceededRequest aReq; + aReq.Names = sModules; + + m_aRequest <<= aReq; + + m_xAbort.set( uno::Reference< task::XInteractionAbort >(new framework::ContinuationAbort), uno::UNO_QUERY ); + m_xApprove.set( uno::Reference< task::XInteractionApprove >(new framework::ContinuationApprove ), uno::UNO_QUERY ); + m_lContinuations.realloc( 2 ); + m_lContinuations[0] = m_xApprove; + m_lContinuations[1] = m_xAbort; +} + +sal_Bool +ModuleSizeExceeded::isAbort() const +{ + framework::ContinuationAbort* pBase = static_cast< framework::ContinuationAbort* >( m_xAbort.get() ); + return pBase->isSelected(); +} + +sal_Bool +ModuleSizeExceeded::isApprove() const +{ + framework::ContinuationApprove* pBase = static_cast< framework::ContinuationApprove* >( m_xApprove.get() ); + return pBase->isSelected(); +} + + diff --git a/basic/source/uno/namecont.cxx b/basic/source/uno/namecont.cxx new file mode 100644 index 000000000000..c397e402fac4 --- /dev/null +++ b/basic/source/uno/namecont.cxx @@ -0,0 +1,3328 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: namecont.cxx,v $ + * $Revision: 1.18 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#ifndef __RSC //autogen +#include <tools/errinf.hxx> +#endif +#include <osl/mutex.hxx> +#include <vos/diagnose.hxx> +#include <rtl/uri.hxx> +#include <rtl/strbuf.hxx> +#include <comphelper/processfactory.hxx> +#ifndef INCLUDED_COMPHELPER_ANYTOSTRING_HXX +#include <comphelper/anytostring.hxx> +#endif + +#include "namecont.hxx" +#include <basic/basicmanagerrepository.hxx> +#include <tools/diagnose_ex.h> +#include <tools/urlobj.hxx> +#include <unotools/streamwrap.hxx> +#include <svtools/pathoptions.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> +#include <basic/basmgr.hxx> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uno/DeploymentException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/script/LibraryNotLoadedException.hpp> +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include <comphelper/storagehelper.hxx> +#ifndef _RTL_USTRING_HXX_ +#include <comphelper/anytostring.hxx> +#endif +#include <cppuhelper/exc_hlp.hxx> +#include <basic/sbmod.hxx> + + +namespace basic +{ + +using namespace com::sun::star::document; +using namespace com::sun::star::container; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::io; +using namespace com::sun::star::ucb; +using namespace com::sun::star::script; +using namespace com::sun::star::beans; +using namespace com::sun::star::xml::sax; +using namespace com::sun::star::util; +using namespace com::sun::star::task; +using namespace com::sun::star::embed; +using namespace com::sun::star::frame; +using namespace com::sun::star::deployment; +using namespace com::sun::star; +using namespace cppu; +using namespace rtl; +using namespace osl; + +using com::sun::star::uno::Reference; + +// #i34411: Flag for error handling during migration +static bool GbMigrationSuppressErrors = false; + +//============================================================================ +// Implementation class NameContainer + +// Methods XElementAccess +Type NameContainer::getElementType() + throw(RuntimeException) +{ + return mType; +} + +sal_Bool NameContainer::hasElements() + throw(RuntimeException) +{ + sal_Bool bRet = (mnElementCount > 0); + return bRet; +} + +// Methods XNameAccess +Any NameContainer::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + NameContainerNameMap::iterator aIt = mHashMap.find( aName ); + if( aIt == mHashMap.end() ) + { + throw NoSuchElementException(); + } + sal_Int32 iHashResult = (*aIt).second; + Any aRetAny = mValues.getConstArray()[ iHashResult ]; + return aRetAny; +} + +Sequence< OUString > NameContainer::getElementNames() + throw(RuntimeException) +{ + return mNames; +} + +sal_Bool NameContainer::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + NameContainerNameMap::iterator aIt = mHashMap.find( aName ); + sal_Bool bRet = ( aIt != mHashMap.end() ); + return bRet; +} + + +// Methods XNameReplace +void NameContainer::replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + Type aAnyType = aElement.getValueType(); + if( mType != aAnyType ) + throw IllegalArgumentException(); + + NameContainerNameMap::iterator aIt = mHashMap.find( aName ); + if( aIt == mHashMap.end() ) + { + throw NoSuchElementException(); + } + sal_Int32 iHashResult = (*aIt).second; + Any aOldElement = mValues.getConstArray()[ iHashResult ]; + mValues.getArray()[ iHashResult ] = aElement; + + + // Fire event + ContainerEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Accessor <<= aName; + aEvent.Element = aElement; + aEvent.ReplacedElement = aOldElement; + + OInterfaceIteratorHelper aIterator( maListenerContainer ); + while( aIterator.hasMoreElements() ) + { + Reference< XInterface > xIface = aIterator.next(); + Reference< XContainerListener > xListener( xIface, UNO_QUERY ); + try + { + xListener->elementReplaced( aEvent ); + } + catch(RuntimeException&) + { + aIterator.remove(); + } + } +} + + +// Methods XNameContainer +void NameContainer::insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + Type aAnyType = aElement.getValueType(); + if( mType != aAnyType ) + throw IllegalArgumentException(); + + NameContainerNameMap::iterator aIt = mHashMap.find( aName ); + if( aIt != mHashMap.end() ) + { + throw ElementExistException(); + } + + sal_Int32 nCount = mNames.getLength(); + mNames.realloc( nCount + 1 ); + mValues.realloc( nCount + 1 ); + mNames.getArray()[ nCount ] = aName; + mValues.getArray()[ nCount ] = aElement; + + mHashMap[ aName ] = nCount; + mnElementCount++; + + + // Fire event + ContainerEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Accessor <<= aName; + aEvent.Element = aElement; + + OInterfaceIteratorHelper aIterator( maListenerContainer ); + while( aIterator.hasMoreElements() ) + { + Reference< XInterface > xIface = aIterator.next(); + Reference< XContainerListener > xListener( xIface, UNO_QUERY ); + try + { + xListener->elementInserted( aEvent ); + } + catch(RuntimeException&) + { + aIterator.remove(); + } + } +} + +void NameContainer::removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + NameContainerNameMap::iterator aIt = mHashMap.find( Name ); + if( aIt == mHashMap.end() ) + { + throw NoSuchElementException(); + } + + sal_Int32 iHashResult = (*aIt).second; + Any aOldElement = mValues.getConstArray()[ iHashResult ]; + mHashMap.erase( aIt ); + sal_Int32 iLast = mNames.getLength() - 1; + if( iLast != iHashResult ) + { + OUString* pNames = mNames.getArray(); + Any* pValues = mValues.getArray(); + pNames[ iHashResult ] = pNames[ iLast ]; + pValues[ iHashResult ] = pValues[ iLast ]; + mHashMap[ pNames[ iHashResult ] ] = iHashResult; + } + mNames.realloc( iLast ); + mValues.realloc( iLast ); + mnElementCount--; + + + // Fire event + ContainerEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Accessor <<= Name; + aEvent.Element = aOldElement; + + OInterfaceIteratorHelper aIterator( maListenerContainer ); + while( aIterator.hasMoreElements() ) + { + Reference< XInterface > xIface = aIterator.next(); + Reference< XContainerListener > xListener( xIface, UNO_QUERY ); + try + { + xListener->elementRemoved( aEvent ); + } + catch(RuntimeException&) + { + aIterator.remove(); + } + } +} + + +// Methods XContainer +void SAL_CALL NameContainer::addContainerListener( const Reference< XContainerListener >& xListener ) + throw (RuntimeException) +{ + if( !xListener.is() ) + throw RuntimeException(); + Reference< XInterface > xIface( xListener, UNO_QUERY ); + maListenerContainer.addInterface( xIface ); +} + +void SAL_CALL NameContainer::removeContainerListener( const Reference< XContainerListener >& xListener ) + throw (RuntimeException) +{ + if( !xListener.is() ) + throw RuntimeException(); + Reference< XInterface > xIface( xListener, UNO_QUERY ); + maListenerContainer.removeInterface( xIface ); +} + +//============================================================================ +// ModifiableHelper + +void ModifiableHelper::setModified( sal_Bool _bModified ) +{ + if ( _bModified == mbModified ) + return; + mbModified = _bModified; + + if ( m_aModifyListeners.getLength() == 0 ) + return; + + EventObject aModifyEvent( m_rEventSource ); + m_aModifyListeners.notifyEach( &XModifyListener::modified, aModifyEvent ); +} + +//============================================================================ + +// Implementation class SfxLibraryContainer +DBG_NAME( SfxLibraryContainer ) + +// Ctor +SfxLibraryContainer::SfxLibraryContainer( void ) + : LibraryContainerHelper( maMutex ) + , maModifiable( *this, maMutex ) + , maNameContainer( getCppuType( (Reference< XNameAccess >*) NULL ) ) + , mbOldInfoFormat( sal_False ) + , mbOasis2OOoFormat( sal_False ) + , mpBasMgr( NULL ) + , mbOwnBasMgr( sal_False ) +{ + DBG_CTOR( SfxLibraryContainer, NULL ); + + mxMSF = comphelper::getProcessServiceFactory(); + if( !mxMSF.is() ) + { + OSL_ENSURE( 0, "### couln't get ProcessServiceFactory\n" ); + } + + mxSFI = Reference< XSimpleFileAccess >( mxMSF->createInstance + ( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); + if( !mxSFI.is() ) + { + OSL_ENSURE( 0, "### couln't create SimpleFileAccess component\n" ); + } + + mxStringSubstitution = Reference< XStringSubstitution >( mxMSF->createInstance + ( OUString::createFromAscii( "com.sun.star.util.PathSubstitution" ) ), UNO_QUERY ); + if( !mxStringSubstitution.is() ) + { + OSL_ENSURE( 0, "### couln't create PathSubstitution component\n" ); + } +} + +SfxLibraryContainer::~SfxLibraryContainer() +{ + if( mbOwnBasMgr ) + BasicManager::LegacyDeleteBasicManager( mpBasMgr ); + DBG_DTOR( SfxLibraryContainer, NULL ); +} + +void SfxLibraryContainer::checkDisposed() const +{ + if ( isDisposed() ) + throw DisposedException( ::rtl::OUString(), *const_cast< SfxLibraryContainer* >( this ) ); +} + +void SfxLibraryContainer::enterMethod() +{ + maMutex.acquire(); + checkDisposed(); +} + +void SfxLibraryContainer::leaveMethod() +{ + maMutex.release(); +} + +BasicManager* SfxLibraryContainer::getBasicManager( void ) +{ + if ( mpBasMgr ) + return mpBasMgr; + + Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY ); + OSL_ENSURE( xDocument.is(), "SfxLibraryContainer::getBasicManager: cannot obtain a BasicManager without document!" ); + if ( xDocument.is() ) + mpBasMgr = BasicManagerRepository::getDocumentBasicManager( xDocument ); + + return mpBasMgr; +} + +// Methods XStorageBasedLibraryContainer +Reference< XStorage > SAL_CALL SfxLibraryContainer::getRootStorage() throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return mxStorage; +} + +void SAL_CALL SfxLibraryContainer::setRootStorage( const Reference< XStorage >& _rxRootStorage ) throw (IllegalArgumentException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + if ( !_rxRootStorage.is() ) + throw IllegalArgumentException(); + + mxStorage = _rxRootStorage; + onNewRootStorage(); +} + +void SAL_CALL SfxLibraryContainer::storeLibrariesToStorage( const Reference< XStorage >& _rxRootStorage ) throw (IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + if ( !_rxRootStorage.is() ) + throw IllegalArgumentException(); + + try + { + storeLibraries_Impl( _rxRootStorage, sal_True ); + } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } +} + + +// Methods XModifiable +sal_Bool SfxLibraryContainer::isModified() throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + if ( maModifiable.isModified() ) + return sal_True; + + // the library container is not modified, go through the libraries and check whether they are modified + Sequence< OUString > aNames = maNameContainer.getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nNameCount = aNames.getLength(); + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aName = pNames[ i ]; + SfxLibrary* pImplLib = getImplLib( aName ); + if( pImplLib->isModified() ) + { + if ( aName.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") ) ) ) + { + // this is a workaround that has to be implemented because + // empty standard library should stay marked as modified + // but should not be treated as modified while it is empty + if ( pImplLib->hasElements() ) + return sal_True; + } + else + return sal_True; + } + } + + return sal_False; +} + +void SAL_CALL SfxLibraryContainer::setModified( sal_Bool _bModified ) throw (PropertyVetoException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + maModifiable.setModified( _bModified ); +} + +void SAL_CALL SfxLibraryContainer::addModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + maModifiable.addModifyListener( _rxListener ); +} + +void SAL_CALL SfxLibraryContainer::removeModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + maModifiable.removeModifyListener( _rxListener ); +} + +// Methods XPersistentLibraryContainer +Any SAL_CALL SfxLibraryContainer::getRootLocation() throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return makeAny( getRootStorage() ); +} + +::rtl::OUString SAL_CALL SfxLibraryContainer::getContainerLocationName() throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return maLibrariesDir; +} + +void SAL_CALL SfxLibraryContainer::storeLibraries( ) throw (WrappedTargetException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + try + { + storeLibraries_Impl( mxStorage, mxStorage.is() ); + // we need to store *all* libraries if and only if we are based on a storage: + // in this case, storeLibraries_Impl will remove the source storage, after loading + // all libraries, so we need to force them to be stored, again + } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } +} + +static void checkAndCopyFileImpl( const INetURLObject& rSourceFolderInetObj, + const INetURLObject& rTargetFolderInetObj, + const OUString& rCheckFileName, + const OUString& rCheckExtension, + Reference< XSimpleFileAccess > xSFI ) +{ + INetURLObject aTargetFolderInetObj( rTargetFolderInetObj ); + aTargetFolderInetObj.insertName( rCheckFileName, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + aTargetFolderInetObj.setExtension( rCheckExtension ); + OUString aTargetFile = aTargetFolderInetObj.GetMainURL( INetURLObject::NO_DECODE ); + if( !xSFI->exists( aTargetFile ) ) + { + INetURLObject aSourceFolderInetObj( rSourceFolderInetObj ); + aSourceFolderInetObj.insertName( rCheckFileName, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + aSourceFolderInetObj.setExtension( rCheckExtension ); + OUString aSourceFile = aSourceFolderInetObj.GetMainURL( INetURLObject::NO_DECODE ); + xSFI->copy( aSourceFile, aTargetFile ); + } +} + +static void createVariableURL( OUString& rStr, const OUString& rLibName, + const OUString& rInfoFileName, bool bUser ) +{ + if( bUser ) + rStr = OUString::createFromAscii( "$(USER)/basic/" ); + else + rStr = OUString::createFromAscii( "$(INST)/share/basic/" ); + + rStr += rLibName; + rStr += OUString::createFromAscii( "/" ); + rStr += rInfoFileName; + rStr += OUString::createFromAscii( ".xlb/" ); +} + +sal_Bool SfxLibraryContainer::init( const OUString& rInitialDocumentURL, const uno::Reference< embed::XStorage >& rxInitialStorage ) +{ + // this might be called from within the ctor, and the impl_init might (indirectly) create + // an UNO reference to ourself. + // Ensure that we're not destroyed while we're in here + osl_incrementInterlockedCount( &m_refCount ); + sal_Bool bSuccess = init_Impl( rInitialDocumentURL, rxInitialStorage ); + osl_decrementInterlockedCount( &m_refCount ); + + return bSuccess; +} + +sal_Bool SfxLibraryContainer::init_Impl( + const OUString& rInitialDocumentURL, const uno::Reference< embed::XStorage >& rxInitialStorage ) +{ + uno::Reference< embed::XStorage > xStorage = rxInitialStorage; + + maInitialDocumentURL = rInitialDocumentURL; + maInfoFileName = OUString::createFromAscii( getInfoFileName() ); + maOldInfoFileName = OUString::createFromAscii( getOldInfoFileName() ); + maLibElementFileExtension = OUString::createFromAscii( getLibElementFileExtension() ); + maLibrariesDir = OUString::createFromAscii( getLibrariesDir() ); + + meInitMode = DEFAULT; + INetURLObject aInitUrlInetObj( maInitialDocumentURL ); + OUString aInitFileName = aInitUrlInetObj.GetMainURL( INetURLObject::NO_DECODE ); + if( aInitFileName.getLength() ) + { + // We need a BasicManager to avoid problems + StarBASIC* pBas = new StarBASIC(); + mpBasMgr = new BasicManager( pBas ); + mbOwnBasMgr = sal_True; + + OUString aExtension = aInitUrlInetObj.getExtension(); + if( aExtension.compareToAscii( "xlc" ) == COMPARE_EQUAL ) + { + meInitMode = CONTAINER_INIT_FILE; + INetURLObject aLibPathInetObj( aInitUrlInetObj ); + aLibPathInetObj.removeSegment(); + maLibraryPath = aLibPathInetObj.GetMainURL( INetURLObject::NO_DECODE ); + } + else if( aExtension.compareToAscii( "xlb" ) == COMPARE_EQUAL ) + { + meInitMode = LIBRARY_INIT_FILE; + uno::Reference< embed::XStorage > xDummyStor; + ::xmlscript::LibDescriptor aLibDesc; + sal_Bool bReadIndexFile = implLoadLibraryIndexFile( NULL, aLibDesc, xDummyStor, aInitFileName ); + return bReadIndexFile; + } + else + { + // Decide between old and new document + sal_Bool bOldStorage = SotStorage::IsOLEStorage( aInitFileName ); + if ( bOldStorage ) + { + meInitMode = OLD_BASIC_STORAGE; + importFromOldStorage( aInitFileName ); + return sal_True; + } + else + { + meInitMode = OFFICE_DOCUMENT; + try + { + xStorage = ::comphelper::OStorageHelper::GetStorageFromURL( aInitFileName, embed::ElementModes::READ ); + } + catch ( uno::Exception& ) + { + // TODO: error handling + } + } + } + } + else + { + // Default pathes + maLibraryPath = SvtPathOptions().GetBasicPath(); + } + + Reference< XParser > xParser( mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY ); + if( !xParser.is() ) + { + OSL_ENSURE( 0, "### couln't create sax parser component\n" ); + return sal_False; + } + + uno::Reference< io::XInputStream > xInput; + + mxStorage = xStorage; + sal_Bool bStorage = mxStorage.is(); + + + // #110009: Scope to force the StorageRefs to be destructed and + // so the streams to be closed before the preload operation + { + // #110009 + + uno::Reference< embed::XStorage > xLibrariesStor; + String aFileName; + + int nPassCount = 1; + if( !bStorage && meInitMode == DEFAULT ) + nPassCount = 2; + for( int nPass = 0 ; nPass < nPassCount ; nPass++ ) + { + if( bStorage ) + { + OSL_ENSURE( meInitMode == DEFAULT || meInitMode == OFFICE_DOCUMENT, + "### Wrong InitMode for document\n" ); + try + { + uno::Reference< io::XStream > xStream; + xLibrariesStor = xStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); + //if ( !xLibrariesStor.is() ) + // TODO: the method must either return a storage or throw an exception + //throw uno::RuntimeException(); + + if ( xLibrariesStor.is() ) + { + aFileName = maInfoFileName; + aFileName += String( RTL_CONSTASCII_USTRINGPARAM("-lc.xml") ); + + try + { + xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ ); + } + catch( uno::Exception& ) + {} + + if( !xStream.is() ) + { + mbOldInfoFormat = true; + + // Check old version + aFileName = maOldInfoFileName; + aFileName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") ); + + try + { + xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ ); + } + catch( uno::Exception& ) + {} + + if( !xStream.is() ) + { + // Check for EA2 document version with wrong extensions + aFileName = maOldInfoFileName; + aFileName += String( RTL_CONSTASCII_USTRINGPARAM(".xli") ); + xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ ); + } + } + } + + if ( xStream.is() ) + xInput = xStream->getInputStream(); + } + catch( uno::Exception& ) + { + // TODO: error handling? + } + } + else + { + INetURLObject* pLibInfoInetObj = NULL; + if( meInitMode == CONTAINER_INIT_FILE ) + { + aFileName = aInitFileName; + } + else + { + if( nPass == 1 ) + pLibInfoInetObj = new INetURLObject( String(maLibraryPath).GetToken(0) ); + else + pLibInfoInetObj = new INetURLObject( String(maLibraryPath).GetToken(1) ); + pLibInfoInetObj->insertName( maInfoFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + pLibInfoInetObj->setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xlc") ) ); + aFileName = pLibInfoInetObj->GetMainURL( INetURLObject::NO_DECODE ); + } + + try + { + xInput = mxSFI->openFileRead( aFileName ); + } + catch( Exception& ) + { + xInput.clear(); + if( nPass == 0 ) + { + SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFileName ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + } + + // Old variant? + if( !xInput.is() && nPass == 0 ) + { + INetURLObject aLibInfoInetObj( String(maLibraryPath).GetToken(1) ); + aLibInfoInetObj.insertName( maOldInfoFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aLibInfoInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xli") ) ); + aFileName = aLibInfoInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + try + { + xInput = mxSFI->openFileRead( aFileName ); + mbOldInfoFormat = true; + } + catch( Exception& ) + { + xInput.clear(); + SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFileName ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + } + + delete pLibInfoInetObj; + } + + if( xInput.is() ) + { + InputSource source; + source.aInputStream = xInput; + source.sSystemId = aFileName; + + // start parsing + ::xmlscript::LibDescriptorArray* pLibArray = new ::xmlscript::LibDescriptorArray(); + + try + { + xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( pLibArray ) ); + xParser->parseStream( source ); + } + catch ( xml::sax::SAXException& e ) + { + (void) e; // avoid warning + OSL_ENSURE( 0, OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + return sal_False; + } + catch ( io::IOException& e ) + { + (void) e; // avoid warning + OSL_ENSURE( 0, OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + return sal_False; + } + + sal_Int32 nLibCount = pLibArray->mnLibCount; + for( sal_Int32 i = 0 ; i < nLibCount ; i++ ) + { + ::xmlscript::LibDescriptor& rLib = pLibArray->mpLibs[i]; + + // Check storage URL + OUString aStorageURL = rLib.aStorageURL; + if( !bStorage && !aStorageURL.getLength() && nPass == 0 ) + { + String aLibraryPath; + if( meInitMode == CONTAINER_INIT_FILE ) + aLibraryPath = maLibraryPath; + else + aLibraryPath = String(maLibraryPath).GetToken(1); + INetURLObject aInetObj( aLibraryPath ); + + aInetObj.insertName( rLib.aName, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + if( mxSFI->isFolder( aLibDirPath ) ) + { + createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, true ); + maModifiable.setModified( sal_True ); + } + else if( rLib.bLink ) + { + // Check "share" path + INetURLObject aShareInetObj( String(maLibraryPath).GetToken(0) ); + aShareInetObj.insertName( rLib.aName, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + OUString aShareLibDirPath = aShareInetObj.GetMainURL( INetURLObject::NO_DECODE ); + if( mxSFI->isFolder( aShareLibDirPath ) ) + { + createVariableURL( rLib.aStorageURL, rLib.aName, maInfoFileName, false ); + maModifiable.setModified( sal_True ); + } + else + { + // #i25537: Ignore lib if library folder does not really exist + continue; + } + } + } + + OUString aLibName = rLib.aName; + + // If the same library name is used by the shared and the + // user lib container index files the user file wins + if( nPass == 1 && hasByName( aLibName ) ) + continue; + + SfxLibrary* pImplLib; + if( rLib.bLink ) + { + Reference< XNameAccess > xLib = + createLibraryLink( aLibName, rLib.aStorageURL, rLib.bReadOnly ); + pImplLib = static_cast< SfxLibrary* >( xLib.get() ); + } + else + { + Reference< XNameContainer > xLib = createLibrary( aLibName ); + pImplLib = static_cast< SfxLibrary* >( xLib.get() ); + pImplLib->mbLoaded = sal_False; + pImplLib->mbReadOnly = rLib.bReadOnly; + if( !bStorage ) + checkStorageURL( rLib.aStorageURL, pImplLib->maLibInfoFileURL, + pImplLib->maStorageURL, pImplLib->maUnexpandedStorageURL ); + } + maModifiable.setModified( sal_False ); + + // Read library info files + if( !mbOldInfoFormat ) + { + uno::Reference< embed::XStorage > xLibraryStor; + if( !pImplLib->mbInitialised && bStorage ) + { + try { + xLibraryStor = xLibrariesStor->openStorageElement( rLib.aName, + embed::ElementModes::READ ); + } + catch( uno::Exception& ) + { + #if OSL_DEBUG_LEVEL > 0 + Any aError( ::cppu::getCaughtException() ); + ::rtl::OStringBuffer aMessage; + aMessage.append( "couln't open sub storage for library '" ); + aMessage.append( ::rtl::OUStringToOString( rLib.aName, osl_getThreadTextEncoding() ) ); + aMessage.append( "'.\n\nException:" ); + aMessage.append( ::rtl::OUStringToOString( ::comphelper::anyToString( aError ), osl_getThreadTextEncoding() ) ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + } + } + + // Link is already initialised in createLibraryLink() + if( !pImplLib->mbInitialised && (!bStorage || xLibraryStor.is()) ) + { + OUString aIndexFileName; + sal_Bool bLoaded = implLoadLibraryIndexFile( pImplLib, rLib, xLibraryStor, aIndexFileName ); + if( bLoaded && aLibName != rLib.aName ) + { + OSL_ENSURE( 0, "Different library names in library" + " container and library info files!\n" ); + } + if( GbMigrationSuppressErrors && !bLoaded ) + removeLibrary( aLibName ); + } + } + else if( !bStorage ) + { + // Write new index file immediately because otherwise + // the library elements will be lost when storing into + // the new info format + uno::Reference< embed::XStorage > xTmpStorage; + implStoreLibraryIndexFile( pImplLib, rLib, xTmpStorage ); + } + + implImportLibDescriptor( pImplLib, rLib ); + + if( nPass == 1 ) + { + pImplLib->mbSharedIndexFile = sal_True; + pImplLib->mbReadOnly = sal_True; + } + } + + // Keep flag for documents to force writing the new index files + if( !bStorage ) + mbOldInfoFormat = sal_False; + + delete pLibArray; + } + // Only in the first pass it's an error when no index file is found + else if( nPass == 0 ) + { + return sal_False; + } + } + + // #110009: END Scope to force the StorageRefs to be destructed + } + // #110009 + + if( !bStorage && meInitMode == DEFAULT ) + implScanExtensions(); + + // #110009 Preload? + { + Sequence< OUString > aNames = maNameContainer.getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nNameCount = aNames.getLength(); + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aName = pNames[ i ]; + SfxLibrary* pImplLib = getImplLib( aName ); + if( pImplLib->mbPreload ) + loadLibrary( aName ); + } + } + + // #118803# upgrade installation 7.0 -> 8.0 + if( meInitMode == DEFAULT ) + { + INetURLObject aUserBasicInetObj( String(maLibraryPath).GetToken(1) ); + OUString aStandardStr( RTL_CONSTASCII_USTRINGPARAM("Standard") ); + + static char strPrevFolderName_1[] = "__basic_80"; + static char strPrevFolderName_2[] = "__basic_80_2"; + INetURLObject aPrevUserBasicInetObj_1( aUserBasicInetObj ); + aPrevUserBasicInetObj_1.removeSegment(); + INetURLObject aPrevUserBasicInetObj_2 = aPrevUserBasicInetObj_1; + aPrevUserBasicInetObj_1.Append( strPrevFolderName_1 ); + aPrevUserBasicInetObj_2.Append( strPrevFolderName_2 ); + + // #i93163 + bool bCleanUp = false; + try + { + INetURLObject aPrevUserBasicInetObj = aPrevUserBasicInetObj_1; + String aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::NO_DECODE ); + bool bSecondTime = false; + if( mxSFI->isFolder( aPrevFolder ) ) + { + // #110101 Check if Standard folder exists and is complete + INetURLObject aUserBasicStandardInetObj( aUserBasicInetObj ); + aUserBasicStandardInetObj.insertName( aStandardStr, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + INetURLObject aPrevUserBasicStandardInetObj( aPrevUserBasicInetObj ); + aPrevUserBasicStandardInetObj.insertName( aStandardStr, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + OUString aPrevStandardFolder = aPrevUserBasicStandardInetObj.GetMainURL( INetURLObject::NO_DECODE ); + if( mxSFI->isFolder( aPrevStandardFolder ) ) + { + OUString aXlbExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xlb") ) ); + OUString aCheckFileName; + + // Check if script.xlb exists + aCheckFileName = OUString( RTL_CONSTASCII_USTRINGPARAM("script") ); + checkAndCopyFileImpl( aUserBasicStandardInetObj, + aPrevUserBasicStandardInetObj, + aCheckFileName, aXlbExtension, mxSFI ); + + // Check if dialog.xlb exists + aCheckFileName = OUString( RTL_CONSTASCII_USTRINGPARAM("dialog") ); + checkAndCopyFileImpl( aUserBasicStandardInetObj, + aPrevUserBasicStandardInetObj, + aCheckFileName, aXlbExtension, mxSFI ); + + // Check if module1.xba exists + OUString aXbaExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xba") ) ); + aCheckFileName = OUString( RTL_CONSTASCII_USTRINGPARAM("Module1") ); + checkAndCopyFileImpl( aUserBasicStandardInetObj, + aPrevUserBasicStandardInetObj, + aCheckFileName, aXbaExtension, mxSFI ); + } + else + { + String aStandardFolder = aUserBasicStandardInetObj.GetMainURL( INetURLObject::NO_DECODE ); + mxSFI->copy( aStandardFolder, aPrevStandardFolder ); + } + + String aPrevCopyToFolder = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::NO_DECODE ); + mxSFI->copy( aPrevFolder, aPrevCopyToFolder ); + } + else + { + bSecondTime = true; + aPrevUserBasicInetObj = aPrevUserBasicInetObj_2; + aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::NO_DECODE ); + } + if( mxSFI->isFolder( aPrevFolder ) ) + { + SfxLibraryContainer* pPrevCont = createInstanceImpl(); + Reference< XInterface > xRef = static_cast< XInterface* >( static_cast< OWeakObject* >(pPrevCont) ); + + // Rename previous basic folder to make storage URLs correct during initialisation + String aFolderUserBasic = aUserBasicInetObj.GetMainURL( INetURLObject::NO_DECODE ); + INetURLObject aUserBasicTmpInetObj( aUserBasicInetObj ); + aUserBasicTmpInetObj.removeSegment(); + aUserBasicTmpInetObj.Append( "__basic_tmp" ); + String aFolderTmp = aUserBasicTmpInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + mxSFI->move( aFolderUserBasic, aFolderTmp ); + try + { + mxSFI->move( aPrevFolder, aFolderUserBasic ); + } + catch( Exception& ) + { + // Move back user/basic folder + try + { + mxSFI->kill( aFolderUserBasic ); + } + catch( Exception& ) + {} + mxSFI->move( aFolderTmp, aFolderUserBasic ); + throw; + } + + INetURLObject aPrevUserBasicLibInfoInetObj( aUserBasicInetObj ); + aPrevUserBasicLibInfoInetObj.insertName( maInfoFileName, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + aPrevUserBasicLibInfoInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xlc") ) ); + OUString aLibInfoFileName = aPrevUserBasicLibInfoInetObj.GetMainURL( INetURLObject::NO_DECODE ); + Sequence<Any> aInitSeq( 1 ); + aInitSeq.getArray()[0] <<= aLibInfoFileName; + GbMigrationSuppressErrors = true; + pPrevCont->initialize( aInitSeq ); + GbMigrationSuppressErrors = false; + + // Rename folders back + mxSFI->move( aFolderUserBasic, aPrevFolder ); + mxSFI->move( aFolderTmp, aFolderUserBasic ); + + OUString aUserSearchStr = OUString::createFromAscii( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ); + OUString aSharedSearchStr = OUString::createFromAscii( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ); + OUString aInstSearchStr = OUString::createFromAscii( "$(INST)" ); + + Sequence< OUString > aNames = pPrevCont->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + sal_Int32 nNameCount = aNames.getLength(); + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aLibName = pNames[ i ]; + if( hasByName( aLibName ) ) + { + if( aLibName == aStandardStr ) + { + SfxLibrary* pImplLib = getImplLib( aStandardStr ); + INetURLObject aStandardFolderInetObj( pImplLib->maStorageURL ); + String aStandardFolder = pImplLib->maStorageURL; + mxSFI->kill( aStandardFolder ); + } + else + { + continue; + } + } + + SfxLibrary* pImplLib = pPrevCont->getImplLib( aLibName ); + if( pImplLib->mbLink ) + { + OUString aStorageURL = pImplLib->maUnexpandedStorageURL; + bool bCreateLink = true; + if( aStorageURL.indexOf( aUserSearchStr ) != -1 || + aStorageURL.indexOf( aSharedSearchStr ) != -1 || + aStorageURL.indexOf( aInstSearchStr ) != -1 ) + { + bCreateLink = false; + } + if( bCreateLink ) + createLibraryLink( aLibName, pImplLib->maStorageURL, pImplLib->mbReadOnly ); + } + else + { + // Move folder if not already done + INetURLObject aUserBasicLibFolderInetObj( aUserBasicInetObj ); + aUserBasicLibFolderInetObj.Append( aLibName ); + String aLibFolder = aUserBasicLibFolderInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + INetURLObject aPrevUserBasicLibFolderInetObj( aPrevUserBasicInetObj ); + aPrevUserBasicLibFolderInetObj.Append( aLibName ); + String aPrevLibFolder = aPrevUserBasicLibFolderInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + if( mxSFI->isFolder( aPrevLibFolder ) && !mxSFI->isFolder( aLibFolder ) ) + mxSFI->move( aPrevLibFolder, aLibFolder ); + + if( aLibName == aStandardStr ) + maNameContainer.removeByName( aLibName ); + + // Create library + Reference< XNameContainer > xLib = createLibrary( aLibName ); + SfxLibrary* pNewLib = static_cast< SfxLibrary* >( xLib.get() ); + pNewLib->mbLoaded = false; + pNewLib->implSetModified( sal_False ); + checkStorageURL( aLibFolder, pNewLib->maLibInfoFileURL, + pNewLib->maStorageURL, pNewLib->maUnexpandedStorageURL ); + + uno::Reference< embed::XStorage > xDummyStor; + ::xmlscript::LibDescriptor aLibDesc; + /*sal_Bool bReadIndexFile =*/ implLoadLibraryIndexFile + ( pNewLib, aLibDesc, xDummyStor, pNewLib->maLibInfoFileURL ); + implImportLibDescriptor( pNewLib, aLibDesc ); + } + } + mxSFI->kill( aPrevFolder ); + } + } + catch( Exception& ) + { + bCleanUp = true; + } + + // #i93163 + if( bCleanUp ) + { + DBG_ERROR( "Upgrade of Basic installation failed somehow" ); + + static char strErrorSavFolderName[] = "__basic_80_err"; + INetURLObject aPrevUserBasicInetObj_Err( aUserBasicInetObj ); + aPrevUserBasicInetObj_Err.removeSegment(); + aPrevUserBasicInetObj_Err.Append( strErrorSavFolderName ); + String aPrevFolder_Err = aPrevUserBasicInetObj_Err.GetMainURL( INetURLObject::NO_DECODE ); + + bool bSaved = false; + try + { + String aPrevFolder_1 = aPrevUserBasicInetObj_1.GetMainURL( INetURLObject::NO_DECODE ); + if( mxSFI->isFolder( aPrevFolder_1 ) ) + { + mxSFI->move( aPrevFolder_1, aPrevFolder_Err ); + bSaved = true; + } + } + catch( Exception& ) + {} + try + { + String aPrevFolder_2 = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::NO_DECODE ); + if( !bSaved && mxSFI->isFolder( aPrevFolder_2 ) ) + mxSFI->move( aPrevFolder_2, aPrevFolder_Err ); + else + mxSFI->kill( aPrevFolder_2 ); + } + catch( Exception& ) + {} + } + } + + return sal_True; +} + +void SfxLibraryContainer::implScanExtensions( void ) +{ + ScriptExtensionIterator aScriptIt; + rtl::OUString aLibURL; + + bool bPureDialogLib = false; + while( (aLibURL = aScriptIt.nextBasicOrDialogLibrary( bPureDialogLib )).getLength() > 0 ) + { + if( bPureDialogLib && maInfoFileName.equalsAscii( "script" ) ) + continue; + + // Extract lib name + sal_Int32 nLen = aLibURL.getLength(); + sal_Int32 indexLastSlash = aLibURL.lastIndexOf( '/' ); + sal_Int32 nReduceCopy = 0; + if( indexLastSlash == nLen - 1 ) + { + nReduceCopy = 1; + indexLastSlash = aLibURL.lastIndexOf( '/', nLen - 1 ); + } + + OUString aLibName = aLibURL.copy( indexLastSlash + 1, nLen - indexLastSlash - nReduceCopy - 1 ); + + // If a library of the same exists the existing library wins + if( hasByName( aLibName ) ) + continue; + + // Add index file to URL + OUString aIndexFileURL = aLibURL; + if( nReduceCopy == 0 ) + aIndexFileURL += OUString::createFromAscii( "/" ); + aIndexFileURL += maInfoFileName; + aIndexFileURL += OUString::createFromAscii( ".xlb" ); + + // Create link + const bool bReadOnly = false; + Reference< XNameAccess > xLib = + createLibraryLink( aLibName, aIndexFileURL, bReadOnly ); + } +} + +// Handle maLibInfoFileURL and maStorageURL correctly +void SfxLibraryContainer::checkStorageURL( const OUString& aSourceURL, + OUString& aLibInfoFileURL, OUString& aStorageURL, OUString& aUnexpandedStorageURL ) +{ + OUString aExpandedSourceURL = expand_url( aSourceURL ); + if( aExpandedSourceURL != aSourceURL ) + aUnexpandedStorageURL = aSourceURL; + + INetURLObject aInetObj( aExpandedSourceURL ); + OUString aExtension = aInetObj.getExtension(); + if( aExtension.compareToAscii( "xlb" ) == COMPARE_EQUAL ) + { + // URL to xlb file + aLibInfoFileURL = aExpandedSourceURL; + aInetObj.removeSegment(); + aStorageURL = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + } + else + { + // URL to library folder + aStorageURL = aExpandedSourceURL; + aInetObj.insertName( maInfoFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xlb") ) ); + aLibInfoFileURL = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + } +} + +SfxLibrary* SfxLibraryContainer::getImplLib( const String& rLibraryName ) +{ + Any aLibAny = maNameContainer.getByName( rLibraryName ) ; + Reference< XNameAccess > xNameAccess; + aLibAny >>= xNameAccess; + SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); + return pImplLib; +} + + +// Storing with password encryption + +// Empty implementation, avoids unneccesary implementation in dlgcont.cxx +sal_Bool SfxLibraryContainer::implStorePasswordLibrary( + SfxLibrary*, + const OUString&, + const uno::Reference< embed::XStorage >&, const uno::Reference< task::XInteractionHandler >& ) +{ + return sal_False; +} + +sal_Bool SfxLibraryContainer::implStorePasswordLibrary( + SfxLibrary* /*pLib*/, + const ::rtl::OUString& /*aName*/, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& /*xStorage*/, + const ::rtl::OUString& /*aTargetURL*/, + const Reference< XSimpleFileAccess > /*xToUseSFI*/, + const uno::Reference< task::XInteractionHandler >& ) +{ + return sal_False; +} + +sal_Bool SfxLibraryContainer::implLoadPasswordLibrary( + SfxLibrary* /*pLib*/, + const OUString& /*Name*/, + sal_Bool /*bVerifyPasswordOnly*/ ) +throw(WrappedTargetException, RuntimeException) +{ + return sal_True; +} + + + +#define EXPAND_PROTOCOL "vnd.sun.star.expand" +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +OUString SfxLibraryContainer::createAppLibraryFolder + ( SfxLibrary* pLib, const OUString& aName ) +{ + OUString aLibDirPath = pLib->maStorageURL; + if( !aLibDirPath.getLength() ) + { + INetURLObject aInetObj( String(maLibraryPath).GetToken(1) ); + aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + checkStorageURL( aInetObj.GetMainURL( INetURLObject::NO_DECODE ), pLib->maLibInfoFileURL, + pLib->maStorageURL, pLib->maUnexpandedStorageURL ); + aLibDirPath = pLib->maStorageURL; + } + + if( !mxSFI->isFolder( aLibDirPath ) ) + { + try + { + mxSFI->createFolder( aLibDirPath ); + } + catch( Exception& ) + {} + } + + return aLibDirPath; +} + +// Storing +void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib, + const OUString& aName, const uno::Reference< embed::XStorage >& xStorage ) +{ + OUString aDummyLocation; + Reference< XSimpleFileAccess > xDummySFA; + Reference< XInteractionHandler > xDummyHandler; + implStoreLibrary( pLib, aName, xStorage, aDummyLocation, xDummySFA, xDummyHandler ); +} + +// New variant for library export +void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib, + const OUString& aName, const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, Reference< XSimpleFileAccess > xToUseSFI, + const Reference< XInteractionHandler >& xHandler ) +{ + sal_Bool bLink = pLib->mbLink; + sal_Bool bStorage = xStorage.is() && !bLink; + + Sequence< OUString > aElementNames = pLib->getElementNames(); + sal_Int32 nNameCount = aElementNames.getLength(); + const OUString* pNames = aElementNames.getConstArray(); + + if( bStorage ) + { + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + OUString aStreamName = aElementName; + aStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") ); + + Any aElement = pLib->getByName( aElementName ); + if( !isLibraryElementValid( aElement ) ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OStringBuffer aMessage; + aMessage.append( "invalid library element '" ); + aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) ); + aMessage.append( "'." ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + continue; + } + try { + uno::Reference< io::XStream > xElementStream = xStorage->openStreamElement( + aStreamName, + embed::ElementModes::READWRITE ); + //if ( !xElementStream.is() ) + // throw uno::RuntimeException(); // TODO: method must either return the stream or throw an exception + + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + + uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY ); + OSL_ENSURE( xProps.is(), "The StorageStream must implement XPropertySet interface!\n" ); + //if ( !xProps.is() ) //TODO + // throw uno::RuntimeException(); + + if ( xProps.is() ) + { + xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); + + // #87671 Allow encryption +//REMOVE aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("Encrypted") ); + aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "UseCommonStoragePasswordEncryption" ) ); + xProps->setPropertyValue( aPropName, uno::makeAny( sal_True ) ); + + Reference< XOutputStream > xOutput = xElementStream->getOutputStream(); + writeLibraryElement( aElement, aElementName, xOutput ); + // writeLibraryElement closes the stream + // xOutput->closeOutput(); + } + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Problem during storing of library!\n" ); + // TODO: error handling? + } + } + + pLib->storeResourcesToStorage( xStorage ); + } + else + { + // Export? + bool bExport = aTargetURL.getLength(); + try + { + Reference< XSimpleFileAccess > xSFI = mxSFI; + if( xToUseSFI.is() ) + xSFI = xToUseSFI; + + OUString aLibDirPath; + if( bExport ) + { + INetURLObject aInetObj( aTargetURL ); + aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + if( !xSFI->isFolder( aLibDirPath ) ) + xSFI->createFolder( aLibDirPath ); + + pLib->storeResourcesToURL( aLibDirPath, xHandler ); + } + else + { + aLibDirPath = createAppLibraryFolder( pLib, aName ); + pLib->storeResources(); + } + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + INetURLObject aElementInetObj( aLibDirPath ); + aElementInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementInetObj.setExtension( maLibElementFileExtension ); + String aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + Any aElement = pLib->getByName( aElementName ); + if( !isLibraryElementValid( aElement ) ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OStringBuffer aMessage; + aMessage.append( "invalid library element '" ); + aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) ); + aMessage.append( "'." ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + continue; + } + + // TODO: Check modified + try + { + if( xSFI->exists( aElementPath ) ) + xSFI->kill( aElementPath ); + Reference< XOutputStream > xOutput = xSFI->openFileWrite( aElementPath ); + writeLibraryElement( aElement, aElementName, xOutput ); + xOutput->closeOutput(); + } + catch( Exception& ) + { + if( bExport ) + throw; + + SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aElementPath ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + } + } + catch( Exception& ) + { + if( bExport ) + throw; + } + } +} + +void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib, + const ::xmlscript::LibDescriptor& rLib, const uno::Reference< embed::XStorage >& xStorage ) +{ + OUString aDummyLocation; + Reference< XSimpleFileAccess > xDummySFA; + implStoreLibraryIndexFile( pLib, rLib, xStorage, aDummyLocation, xDummySFA ); +} + +// New variant for library export +void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib, + const ::xmlscript::LibDescriptor& rLib, const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, Reference< XSimpleFileAccess > xToUseSFI ) +{ + // Create sax writer + Reference< XExtendedDocumentHandler > xHandler( + mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") ) ), UNO_QUERY ); + if( !xHandler.is() ) + { + OSL_ENSURE( 0, "### couln't create sax-writer component\n" ); + return; + } + + sal_Bool bLink = pLib->mbLink; + sal_Bool bStorage = xStorage.is() && !bLink; + + // Write info file + uno::Reference< io::XOutputStream > xOut; + uno::Reference< io::XStream > xInfoStream; + if( bStorage ) + { + OUString aStreamName( maInfoFileName ); + aStreamName += String( RTL_CONSTASCII_USTRINGPARAM("-lb.xml") ); + + try { + xInfoStream = xStorage->openStreamElement( aStreamName, embed::ElementModes::READWRITE ); + OSL_ENSURE( xInfoStream.is(), "No stream!\n" ); + uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY ); + //if ( !xProps.is() ) + // throw uno::RuntimeException(); // TODO + + if ( xProps.is() ) + { + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); + + // #87671 Allow encryption +//REMOVE aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("Encrypted") ); + aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "UseCommonStoragePasswordEncryption" ) ); + xProps->setPropertyValue( aPropName, uno::makeAny( sal_True ) ); + + xOut = xInfoStream->getOutputStream(); + } + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Problem during storing of library index file!\n" ); + // TODO: error handling? + } + } + else + { + // Export? + bool bExport = aTargetURL.getLength(); + Reference< XSimpleFileAccess > xSFI = mxSFI; + if( xToUseSFI.is() ) + xSFI = xToUseSFI; + + OUString aLibInfoPath; + if( bExport ) + { + INetURLObject aInetObj( aTargetURL ); + aInetObj.insertName( rLib.aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + if( !xSFI->isFolder( aLibDirPath ) ) + xSFI->createFolder( aLibDirPath ); + + aInetObj.insertName( maInfoFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xlb") ) ); + aLibInfoPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + } + else + { + createAppLibraryFolder( pLib, rLib.aName ); + aLibInfoPath = pLib->maLibInfoFileURL; + } + + try + { + if( xSFI->exists( aLibInfoPath ) ) + xSFI->kill( aLibInfoPath ); + xOut = xSFI->openFileWrite( aLibInfoPath ); + } + catch( Exception& ) + { + if( bExport ) + throw; + + SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + } + if( !xOut.is() ) + { + OSL_ENSURE( 0, "### couln't open output stream\n" ); + return; + } + + Reference< XActiveDataSource > xSource( xHandler, UNO_QUERY ); + xSource->setOutputStream( xOut ); + + xmlscript::exportLibrary( xHandler, rLib ); +} + + +sal_Bool SfxLibraryContainer::implLoadLibraryIndexFile( SfxLibrary* pLib, + ::xmlscript::LibDescriptor& rLib, const uno::Reference< embed::XStorage >& xStorage, const OUString& aIndexFileName ) +{ + Reference< XParser > xParser( mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY ); + if( !xParser.is() ) + { + OSL_ENSURE( 0, "### couln't create sax parser component\n" ); + return sal_False; + } + + sal_Bool bLink = sal_False; + sal_Bool bStorage = sal_False; + if( pLib ) + { + bLink = pLib->mbLink; + bStorage = xStorage.is() && !bLink; + } + + // Read info file + uno::Reference< io::XInputStream > xInput; + String aLibInfoPath; + if( bStorage ) + { + aLibInfoPath = maInfoFileName; + aLibInfoPath += String( RTL_CONSTASCII_USTRINGPARAM("-lb.xml") ); + + try { + uno::Reference< io::XStream > xInfoStream = + xStorage->openStreamElement( aLibInfoPath, embed::ElementModes::READ ); + xInput = xInfoStream->getInputStream(); + } + catch( uno::Exception& ) + {} + } + else + { + // Create Input stream + //String aLibInfoPath; // attention: THIS PROBLEM MUST BE REVIEWED BY SCRIPTING OWNER!!! + + if( pLib ) + { + createAppLibraryFolder( pLib, rLib.aName ); + aLibInfoPath = pLib->maLibInfoFileURL; + } + else + aLibInfoPath = aIndexFileName; + + try + { + xInput = mxSFI->openFileRead( aLibInfoPath ); + } + catch( Exception& ) + { + xInput.clear(); + if( !GbMigrationSuppressErrors ) + { + SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + } + } + if( !xInput.is() ) + { + // OSL_ENSURE( 0, "### couln't open input stream\n" ); + return sal_False; + } + + InputSource source; + source.aInputStream = xInput; + source.sSystemId = aLibInfoPath; + + // start parsing + try { + xParser->setDocumentHandler( ::xmlscript::importLibrary( rLib ) ); + xParser->parseStream( source ); + } + catch( Exception& ) + { + // throw WrappedTargetException( OUString::createFromAscii( "parsing error!\n" ), + // Reference< XInterface >(), + // makeAny( e ) ); + OSL_ENSURE( 0, "Parsing error\n" ); + SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + return sal_False; + } + + if( !pLib ) + { + Reference< XNameContainer > xLib = createLibrary( rLib.aName ); + pLib = static_cast< SfxLibrary* >( xLib.get() ); + pLib->mbLoaded = sal_False; + rLib.aStorageURL = aIndexFileName; + checkStorageURL( rLib.aStorageURL, pLib->maLibInfoFileURL, pLib->maStorageURL, + pLib->maUnexpandedStorageURL ); + + implImportLibDescriptor( pLib, rLib ); + } + + return sal_True; +} + +void SfxLibraryContainer::implImportLibDescriptor + ( SfxLibrary* pLib, ::xmlscript::LibDescriptor& rLib ) +{ + if( !pLib->mbInitialised ) + { + sal_Int32 nElementCount = rLib.aElementNames.getLength(); + const OUString* pElementNames = rLib.aElementNames.getConstArray(); + Any aDummyElement = createEmptyLibraryElement(); + for( sal_Int32 i = 0 ; i < nElementCount ; i++ ) + { + pLib->maNameContainer.insertByName( pElementNames[i], aDummyElement ); + } + pLib->mbPasswordProtected = rLib.bPasswordProtected; + pLib->mbReadOnly = rLib.bReadOnly; + pLib->mbPreload = rLib.bPreload; + pLib->implSetModified( sal_False ); + + pLib->mbInitialised = sal_True; + } +} + + +// Methods of new XLibraryStorage interface? +void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference< embed::XStorage >& xStorage, sal_Bool bComplete ) +{ + const Sequence< OUString > aNames = maNameContainer.getElementNames(); + sal_Int32 nNameCount = aNames.getLength(); + const OUString* pName = aNames.getConstArray(); + const OUString* pNamesEnd = aNames.getConstArray() + nNameCount; + + // Don't count libs from shared index file + sal_Int32 nLibsToSave = nNameCount; + for( ; pName != pNamesEnd; ++pName ) + { + SfxLibrary* pImplLib = getImplLib( *pName ); + if( pImplLib->mbSharedIndexFile || pImplLib->mbExtension ) + nLibsToSave--; + } + if( !nLibsToSave ) + return; + + ::xmlscript::LibDescriptorArray* pLibArray = new ::xmlscript::LibDescriptorArray( nLibsToSave ); + + // Write to storage? + sal_Bool bStorage = xStorage.is(); + uno::Reference< embed::XStorage > xLibrariesStor; + uno::Reference< embed::XStorage > xSourceLibrariesStor; + if( bStorage ) + { + // when we save to our root storage, ensure the libs are all loaded. Else the below cleaning + // of the target storage will loose them. + if ( xStorage == mxStorage ) + { + pName = aNames.getConstArray(); + for ( ; pName != pNamesEnd; ++pName ) + { + if ( !isLibraryLoaded( *pName ) ) + loadLibrary( *pName ); + } + } + + // first of all, clean the target library storage, since the storing procedure must do overwrite + try + { + if ( xStorage->hasByName( maLibrariesDir ) ) + xStorage->removeElement( maLibrariesDir ); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + // Don't write if only empty standard lib exists + if ( ( nNameCount == 1 ) && ( aNames[0].equalsAscii( "Standard" ) ) ) + { + Any aLibAny = maNameContainer.getByName( aNames[0] ); + Reference< XNameAccess > xNameAccess; + aLibAny >>= xNameAccess; + if ( !xNameAccess->hasElements() ) + return; + } + + try { + xLibrariesStor.set( xStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READWRITE ), UNO_QUERY_THROW ); + } + catch( uno::Exception& ) + { + #if OSL_DEBUG_LEVEL > 0 + Any aError( ::cppu::getCaughtException() ); + ::rtl::OStringBuffer aMessage; + aMessage.append( "couln't open source library storage.\n\nException:" ); + aMessage.append( ::rtl::OUStringToOString( ::comphelper::anyToString( aError ), osl_getThreadTextEncoding() ) ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + return; + } + + try + { + if ( ( mxStorage != xStorage ) && ( mxStorage->hasByName( maLibrariesDir ) ) ) + xSourceLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + int iArray = 0; + pName = aNames.getConstArray(); + ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs; + for( ; pName != pNamesEnd; ++pName ) + { + SfxLibrary* pImplLib = getImplLib( *pName ); + if( pImplLib->mbSharedIndexFile ) + continue; + bool bExtensionLib = pImplLib->mbExtension; + ::xmlscript::LibDescriptor& rLib = bExtensionLib ? + aLibDescriptorForExtensionLibs : pLibArray->mpLibs[iArray]; + if( !bExtensionLib ) + iArray++; + rLib.aName = *pName; + + rLib.bLink = pImplLib->mbLink; + if( !bStorage || pImplLib->mbLink ) + { + rLib.aStorageURL = ( pImplLib->maUnexpandedStorageURL.getLength() ) ? + pImplLib->maUnexpandedStorageURL : pImplLib->maLibInfoFileURL; + } + rLib.bReadOnly = pImplLib->mbReadOnly; + rLib.bPreload = pImplLib->mbPreload; + rLib.bPasswordProtected = pImplLib->mbPasswordProtected; + rLib.aElementNames = pImplLib->getElementNames(); + + if( pImplLib->implIsModified() || bComplete ) + { + // Can we copy the storage? + if( !mbOldInfoFormat && !pImplLib->implIsModified() && !mbOasis2OOoFormat && xSourceLibrariesStor.is() ) + { + try { + xSourceLibrariesStor->copyElementTo( rLib.aName, xLibrariesStor, rLib.aName ); + } catch( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + // TODO: error handling? + } + } + else + { + uno::Reference< embed::XStorage > xLibraryStor; + if( bStorage ) + { + try + { + xLibraryStor = xLibrariesStor->openStorageElement( + rLib.aName, + embed::ElementModes::READWRITE ); + } + catch( uno::Exception& ) + { + #if OSL_DEBUG_LEVEL > 0 + Any aError( ::cppu::getCaughtException() ); + ::rtl::OStringBuffer aMessage; + aMessage.append( "couln't create sub storage for library '" ); + aMessage.append( ::rtl::OUStringToOString( rLib.aName, osl_getThreadTextEncoding() ) ); + aMessage.append( "'.\n\nException:" ); + aMessage.append( ::rtl::OUStringToOString( ::comphelper::anyToString( aError ), osl_getThreadTextEncoding() ) ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + return; + } + } + + // Maybe lib is not loaded?! + if( bComplete ) + loadLibrary( rLib.aName ); + + if( pImplLib->mbPasswordProtected ) + implStorePasswordLibrary( pImplLib, rLib.aName, xLibraryStor, uno::Reference< task::XInteractionHandler >() ); + // TODO: Check return value + else + implStoreLibrary( pImplLib, rLib.aName, xLibraryStor ); + + implStoreLibraryIndexFile( pImplLib, rLib, xLibraryStor ); + if( bStorage ) + { + try { + uno::Reference< embed::XTransactedObject > xTransact( xLibraryStor, uno::UNO_QUERY_THROW ); + xTransact->commit(); + } + catch( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + // TODO: error handling + } + } + } + + maModifiable.setModified( sal_True ); + pImplLib->implSetModified( sal_False ); + } + + // For container info ReadOnly refers to mbReadOnlyLink + rLib.bReadOnly = pImplLib->mbReadOnlyLink; + } + + if( !mbOldInfoFormat && !maModifiable.isModified() ) + return; + maModifiable.setModified( sal_False ); + mbOldInfoFormat = sal_False; + + // Write library container info + // Create sax writer + Reference< XExtendedDocumentHandler > xHandler( + mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") ) ), UNO_QUERY ); + if( !xHandler.is() ) + { + OSL_ENSURE( 0, "### couln't create sax-writer component\n" ); + return; + } + + // Write info file + uno::Reference< io::XOutputStream > xOut; + uno::Reference< io::XStream > xInfoStream; + if( bStorage ) + { + OUString aStreamName( maInfoFileName ); + aStreamName += String( RTL_CONSTASCII_USTRINGPARAM("-lc.xml") ); + + try { + xInfoStream = xLibrariesStor->openStreamElement( aStreamName, embed::ElementModes::READWRITE ); + uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY ); + OSL_ENSURE ( xProps.is(), "The stream must implement XPropertySet!\n" ); + if ( !xProps.is() ) + throw uno::RuntimeException(); + + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); + + // #87671 Allow encryption + aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("UseCommonStoragePasswordEncryption") ); + xProps->setPropertyValue( aPropName, uno::makeAny( sal_True ) ); + + xOut = xInfoStream->getOutputStream(); + } + catch( uno::Exception& ) + { + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + } + else + { + // Create Output stream + INetURLObject aLibInfoInetObj( String(maLibraryPath).GetToken(1) ); + aLibInfoInetObj.insertName( maInfoFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aLibInfoInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("xlc") ) ); + String aLibInfoPath( aLibInfoInetObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + try + { + if( mxSFI->exists( aLibInfoPath ) ) + mxSFI->kill( aLibInfoPath ); + xOut = mxSFI->openFileWrite( aLibInfoPath ); + } + catch( Exception& ) + { + xOut.clear(); + SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + + } + if( !xOut.is() ) + { + OSL_ENSURE( 0, "### couln't open output stream\n" ); + return; + } + + Reference< XActiveDataSource > xSource( xHandler, UNO_QUERY ); + xSource->setOutputStream( xOut ); + + try + { + xmlscript::exportLibraryContainer( xHandler, pLibArray ); + if ( bStorage ) + { + uno::Reference< embed::XTransactedObject > xTransact( xLibrariesStor, uno::UNO_QUERY ); + OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" ); + if ( !xTransact.is() ) + throw uno::RuntimeException(); + + xTransact->commit(); + } + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Problem during storing of libraries!\n" ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + + delete pLibArray; +} + + +// Methods XElementAccess +Type SAL_CALL SfxLibraryContainer::getElementType() + throw(RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return maNameContainer.getElementType(); +} + +sal_Bool SfxLibraryContainer::hasElements() + throw(RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + sal_Bool bRet = maNameContainer.hasElements(); + return bRet; +} + +// Methods XNameAccess +Any SfxLibraryContainer::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + Any aRetAny = maNameContainer.getByName( aName ) ; + return aRetAny; +} + +Sequence< OUString > SfxLibraryContainer::getElementNames() + throw(RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return maNameContainer.getElementNames(); +} + +sal_Bool SfxLibraryContainer::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return maNameContainer.hasByName( aName ) ; +} + +// Methods XLibraryContainer +Reference< XNameContainer > SAL_CALL SfxLibraryContainer::createLibrary( const OUString& Name ) + throw(IllegalArgumentException, ElementExistException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pNewLib = implCreateLibrary( Name ); + pNewLib->maLibElementFileExtension = maLibElementFileExtension; + + createVariableURL( pNewLib->maUnexpandedStorageURL, Name, maInfoFileName, true ); + + Reference< XNameAccess > xNameAccess = static_cast< XNameAccess* >( pNewLib ); + Any aElement; + aElement <<= xNameAccess; + maNameContainer.insertByName( Name, aElement ); + maModifiable.setModified( sal_True ); + Reference< XNameContainer > xRet( xNameAccess, UNO_QUERY ); + return xRet; +} + +Reference< XNameAccess > SAL_CALL SfxLibraryContainer::createLibraryLink + ( const OUString& Name, const OUString& StorageURL, sal_Bool ReadOnly ) + throw(IllegalArgumentException, ElementExistException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + // TODO: Check other reasons to force ReadOnly status + //if( !ReadOnly ) + //{ + //} + + OUString aLibInfoFileURL; + OUString aLibDirURL; + OUString aUnexpandedStorageURL; + checkStorageURL( StorageURL, aLibInfoFileURL, aLibDirURL, aUnexpandedStorageURL ); + + + SfxLibrary* pNewLib = implCreateLibraryLink( Name, aLibInfoFileURL, aLibDirURL, ReadOnly ); + pNewLib->maLibElementFileExtension = maLibElementFileExtension; + pNewLib->maUnexpandedStorageURL = aUnexpandedStorageURL; + + OUString aInitFileName; + uno::Reference< embed::XStorage > xDummyStor; + ::xmlscript::LibDescriptor aLibDesc; + /*sal_Bool bReadIndexFile = */implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, aInitFileName ); + implImportLibDescriptor( pNewLib, aLibDesc ); + + Reference< XNameAccess > xRet = static_cast< XNameAccess* >( pNewLib ); + Any aElement; + aElement <<= xRet; + maNameContainer.insertByName( Name, aElement ); + maModifiable.setModified( sal_True ); + + OUString aUserSearchStr = OUString::createFromAscii( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ); + OUString aSharedSearchStr = OUString::createFromAscii( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ); + if( StorageURL.indexOf( aUserSearchStr ) != -1 ) + { + pNewLib->mbExtension = sal_True; + } + else if( StorageURL.indexOf( aSharedSearchStr ) != -1 ) + { + pNewLib->mbExtension = sal_True; + pNewLib->mbReadOnly = sal_True; + } + + return xRet; +} + +void SAL_CALL SfxLibraryContainer::removeLibrary( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + // Get and hold library before removing + Any aLibAny = maNameContainer.getByName( Name ) ; + Reference< XNameAccess > xNameAccess; + aLibAny >>= xNameAccess; + SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); + if( pImplLib->mbReadOnly && !pImplLib->mbLink ) + throw IllegalArgumentException(); + + // Remove from container + maNameContainer.removeByName( Name ); + maModifiable.setModified( sal_True ); + + // Delete library files, but not for linked libraries + if( !pImplLib->mbLink ) + { + if( mxStorage.is() ) + return; + if( xNameAccess->hasElements() ) + { + Sequence< OUString > aNames = pImplLib->getElementNames(); + sal_Int32 nNameCount = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + for( sal_Int32 i = 0 ; i < nNameCount ; ++i, ++pNames ) + { + pImplLib->removeElementWithoutChecks( *pNames, SfxLibrary::LibraryContainerAccess() ); + } + } + + // Delete index file + createAppLibraryFolder( pImplLib, Name ); + String aLibInfoPath = pImplLib->maLibInfoFileURL; + try + { + if( mxSFI->exists( aLibInfoPath ) ) + mxSFI->kill( aLibInfoPath ); + } + catch( Exception& ) {} + + // Delete folder if empty + INetURLObject aInetObj( String(maLibraryPath).GetToken(1) ); + aInetObj.insertName( Name, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + try + { + if( mxSFI->isFolder( aLibDirPath ) ) + { + Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true ); + sal_Int32 nCount = aContentSeq.getLength(); + if( !nCount ) + mxSFI->kill( aLibDirPath ); + } + } + catch( Exception& ) + { + } + } +} + +sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLoaded( const OUString& Name ) + throw(NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + sal_Bool bRet = pImplLib->mbLoaded; + return bRet; +} + + +void SAL_CALL SfxLibraryContainer::loadLibrary( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + Any aLibAny = maNameContainer.getByName( Name ) ; + Reference< XNameAccess > xNameAccess; + aLibAny >>= xNameAccess; + SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); + + sal_Bool bLoaded = pImplLib->mbLoaded; + pImplLib->mbLoaded = sal_True; + if( !bLoaded && xNameAccess->hasElements() ) + { + if( pImplLib->mbPasswordProtected ) + { + implLoadPasswordLibrary( pImplLib, Name ); + return; + } + + sal_Bool bLink = pImplLib->mbLink; + sal_Bool bStorage = mxStorage.is() && !bLink; + + uno::Reference< embed::XStorage > xLibrariesStor; + uno::Reference< embed::XStorage > xLibraryStor; + if( bStorage ) + { + try { + xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); + OSL_ENSURE( xLibrariesStor.is(), "The method must either throw exception or return a storage!\n" ); + if ( !xLibrariesStor.is() ) + throw uno::RuntimeException(); + + xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ ); + OSL_ENSURE( xLibraryStor.is(), "The method must either throw exception or return a storage!\n" ); + if ( !xLibrariesStor.is() ) + throw uno::RuntimeException(); + } + catch( uno::Exception& ) + { + #if OSL_DEBUG_LEVEL > 0 + Any aError( ::cppu::getCaughtException() ); + ::rtl::OStringBuffer aMessage; + aMessage.append( "couln't open sub storage for library '" ); + aMessage.append( ::rtl::OUStringToOString( Name, osl_getThreadTextEncoding() ) ); + aMessage.append( "'.\n\nException:" ); + aMessage.append( ::rtl::OUStringToOString( ::comphelper::anyToString( aError ), osl_getThreadTextEncoding() ) ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + return; + } + } + + Sequence< OUString > aNames = pImplLib->getElementNames(); + sal_Int32 nNameCount = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + OUString aFile; + uno::Reference< io::XInputStream > xInStream; + + if( bStorage ) + { + uno::Reference< io::XStream > xElementStream; + + aFile = aElementName; + aFile += String( RTL_CONSTASCII_USTRINGPARAM(".xml") ); + + try { + xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ ); + } catch( uno::Exception& ) + {} + + if( !xElementStream.is() ) + { + // Check for EA2 document version with wrong extensions + aFile = aElementName; + aFile += String( RTL_CONSTASCII_USTRINGPARAM(".") ); + aFile += maLibElementFileExtension; + try { + xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ ); + } catch( uno::Exception& ) + {} + } + + if ( xElementStream.is() ) + xInStream = xElementStream->getInputStream(); + + if ( !xInStream.is() ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OStringBuffer aMessage; + aMessage.append( "couln't open library element stream - attempted to open library '" ); + aMessage.append( ::rtl::OUStringToOString( Name, osl_getThreadTextEncoding() ) ); + aMessage.append( "'." ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + return; + } + } + else + { + String aLibDirPath = pImplLib->maStorageURL; + INetURLObject aElementInetObj( aLibDirPath ); + aElementInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementInetObj.setExtension( maLibElementFileExtension ); + aFile = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ); + } + + Any aAny = importLibraryElement( aFile, xInStream ); + if( pImplLib->hasByName( aElementName ) ) + { + if( aAny.hasValue() ) + pImplLib->maNameContainer.replaceByName( aElementName, aAny ); + } + else + { + pImplLib->maNameContainer.insertByName( aElementName, aAny ); + } + } + + pImplLib->implSetModified( sal_False ); + } +} + +// Methods XLibraryContainer2 +sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLink( const OUString& Name ) + throw (NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + sal_Bool bRet = pImplLib->mbLink; + return bRet; +} + +OUString SAL_CALL SfxLibraryContainer::getLibraryLinkURL( const OUString& Name ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + sal_Bool bLink = pImplLib->mbLink; + if( !bLink ) + throw IllegalArgumentException(); + OUString aRetStr = pImplLib->maLibInfoFileURL; + return aRetStr; +} + +sal_Bool SAL_CALL SfxLibraryContainer::isLibraryReadOnly( const OUString& Name ) + throw (NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + sal_Bool bRet = pImplLib->mbReadOnly || (pImplLib->mbLink && pImplLib->mbReadOnlyLink); + return bRet; +} + +void SAL_CALL SfxLibraryContainer::setLibraryReadOnly( const OUString& Name, sal_Bool bReadOnly ) + throw (NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + if( pImplLib->mbLink ) + { + if( pImplLib->mbReadOnlyLink != bReadOnly ) + { + pImplLib->mbReadOnlyLink = bReadOnly; + pImplLib->implSetModified( sal_True ); + maModifiable.setModified( sal_True ); + } + } + else + { + if( pImplLib->mbReadOnly != bReadOnly ) + { + pImplLib->mbReadOnly = bReadOnly; + pImplLib->implSetModified( sal_True ); + } + } +} + +void SAL_CALL SfxLibraryContainer::renameLibrary( const OUString& Name, const OUString& NewName ) + throw (NoSuchElementException, ElementExistException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + if( maNameContainer.hasByName( NewName ) ) + throw ElementExistException(); + + // Get and hold library before removing + Any aLibAny = maNameContainer.getByName( Name ) ; + + // #i24094 Maybe lib is not loaded! + Reference< XNameAccess > xNameAccess; + aLibAny >>= xNameAccess; + SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() ); + if( pImplLib->mbPasswordProtected && !pImplLib->mbPasswordVerified ) + return; // Lib with unverified password cannot be renamed + loadLibrary( Name ); + + // Remove from container + maNameContainer.removeByName( Name ); + maModifiable.setModified( sal_True ); + + // Rename library folder, but not for linked libraries + bool bMovedSuccessful = true; + + // Rename files + sal_Bool bStorage = mxStorage.is(); + if( !bStorage && !pImplLib->mbLink ) + { + bMovedSuccessful = false; + + OUString aLibDirPath = pImplLib->maStorageURL; + + INetURLObject aDestInetObj( String(maLibraryPath).GetToken(1) ); + aDestInetObj.insertName( NewName, sal_True, INetURLObject::LAST_SEGMENT, + sal_True, INetURLObject::ENCODE_ALL ); + OUString aDestDirPath = aDestInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + // Store new URL + OUString aLibInfoFileURL = pImplLib->maLibInfoFileURL; + checkStorageURL( aDestDirPath, pImplLib->maLibInfoFileURL, pImplLib->maStorageURL, + pImplLib->maUnexpandedStorageURL ); + + try + { + if( mxSFI->isFolder( aLibDirPath ) ) + { + if( !mxSFI->isFolder( aDestDirPath ) ) + mxSFI->createFolder( aDestDirPath ); + + // Move index file + try + { + if( mxSFI->exists( pImplLib->maLibInfoFileURL ) ) + mxSFI->kill( pImplLib->maLibInfoFileURL ); + mxSFI->move( aLibInfoFileURL, pImplLib->maLibInfoFileURL ); + } + catch( Exception& ) + { + } + + Sequence< OUString > aElementNames = xNameAccess->getElementNames(); + sal_Int32 nNameCount = aElementNames.getLength(); + const OUString* pNames = aElementNames.getConstArray(); + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + INetURLObject aElementInetObj( aLibDirPath ); + aElementInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementInetObj.setExtension( maLibElementFileExtension ); + String aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + INetURLObject aElementDestInetObj( aDestDirPath ); + aElementDestInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementDestInetObj.setExtension( maLibElementFileExtension ); + String aDestElementPath( aElementDestInetObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + try + { + if( mxSFI->exists( aDestElementPath ) ) + mxSFI->kill( aDestElementPath ); + mxSFI->move( aElementPath, aDestElementPath ); + } + catch( Exception& ) + { + } + } + pImplLib->storeResourcesAsURL( aDestDirPath, NewName ); + + // Delete folder if empty + Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true ); + sal_Int32 nCount = aContentSeq.getLength(); + if( !nCount ) + { + mxSFI->kill( aLibDirPath ); + } + + bMovedSuccessful = true; + pImplLib->implSetModified( sal_True ); + } + } + catch( Exception& ) + { + // Restore old library + maNameContainer.insertByName( Name, aLibAny ) ; + } + } + + if( bStorage && !pImplLib->mbLink ) + pImplLib->implSetModified( sal_True ); + + if( bMovedSuccessful ) + maNameContainer.insertByName( NewName, aLibAny ) ; + +} + + +// Methods XInitialization +void SAL_CALL SfxLibraryContainer::initialize( const Sequence< Any >& _rArguments ) + throw (Exception, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + sal_Int32 nArgCount = _rArguments.getLength(); + if ( nArgCount == 1 ) + { + OUString sInitialDocumentURL; + Reference< XStorageBasedDocument > xDocument; + if ( _rArguments[0] >>= sInitialDocumentURL ) + { + initializeFromDocumentURL( sInitialDocumentURL ); + return; + } + + if ( _rArguments[0] >>= xDocument ) + { + initializeFromDocument( xDocument ); + return; + } + } + + throw IllegalArgumentException(); +} + +void SAL_CALL SfxLibraryContainer::initializeFromDocumentURL( const ::rtl::OUString& _rInitialDocumentURL ) +{ + init( _rInitialDocumentURL, NULL ); +} + +void SAL_CALL SfxLibraryContainer::initializeFromDocument( const Reference< XStorageBasedDocument >& _rxDocument ) +{ + // check whether this is a valid OfficeDocument, and obtain the document's root storage + Reference< XStorage > xDocStorage; + try + { + Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY_THROW ); + if ( xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.OfficeDocument" ) ) ) ) + xDocStorage.set( _rxDocument->getDocumentStorage(), UNO_QUERY_THROW ); + + Reference< XModel > xDocument( _rxDocument, UNO_QUERY_THROW ); + Reference< XComponent > xDocComponent( _rxDocument, UNO_QUERY_THROW ); + + mxOwnerDocument = xDocument; + startComponentListening( xDocComponent ); + } + catch( const Exception& ) { } + + if ( !xDocStorage.is() ) + throw IllegalArgumentException(); + + init( OUString(), xDocStorage ); +} + +// OEventListenerAdapter +void SfxLibraryContainer::_disposing( const EventObject& _rSource ) +{ +#if OSL_DEBUG_LEVEL > 0 + Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY ); + OSL_ENSURE( ( xDocument == _rSource.Source ) && xDocument.is(), "SfxLibraryContainer::_disposing: where does this come from?" ); +#else + (void)_rSource; +#endif + dispose(); +} + +// OComponentHelper +void SAL_CALL SfxLibraryContainer::disposing() +{ + stopAllComponentListening(); + mxOwnerDocument = WeakReference< XModel >(); +} + +// Methods XLibraryContainerPassword +sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordProtected( const OUString& ) + throw (NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return sal_False; +} + +sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordVerified( const OUString& ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + throw IllegalArgumentException(); +} + +sal_Bool SAL_CALL SfxLibraryContainer::verifyLibraryPassword + ( const OUString&, const OUString& ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + throw IllegalArgumentException(); +} + +void SAL_CALL SfxLibraryContainer::changeLibraryPassword( + const OUString&, const OUString&, const OUString& ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + throw IllegalArgumentException(); +} + +// Methods XContainer +void SAL_CALL SfxLibraryContainer::addContainerListener( const Reference< XContainerListener >& xListener ) + throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + maNameContainer.setEventSource( static_cast< XInterface* >( (OWeakObject*)this ) ); + maNameContainer.addContainerListener( xListener ); +} + +void SAL_CALL SfxLibraryContainer::removeContainerListener( const Reference< XContainerListener >& xListener ) + throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + maNameContainer.removeContainerListener( xListener ); +} + +// Methods XLibraryContainerExport +void SAL_CALL SfxLibraryContainer::exportLibrary( const OUString& Name, const OUString& URL, + const Reference< XInteractionHandler >& Handler ) + throw ( uno::Exception, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + + Reference< XSimpleFileAccess > xToUseSFI; + if( Handler.is() ) + { + xToUseSFI = Reference< XSimpleFileAccess >( mxMSF->createInstance + ( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); + if( xToUseSFI.is() ) + xToUseSFI->setInteractionHandler( Handler ); + } + + // Maybe lib is not loaded?! + loadLibrary( Name ); + + uno::Reference< ::com::sun::star::embed::XStorage > xDummyStor; + if( pImplLib->mbPasswordProtected ) + implStorePasswordLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler ); + else + implStoreLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler ); + + ::xmlscript::LibDescriptor aLibDesc; + aLibDesc.aName = Name; + aLibDesc.bLink = false; // Link status gets lost? + aLibDesc.bReadOnly = pImplLib->mbReadOnly; + aLibDesc.bPreload = false; // Preload status gets lost? + aLibDesc.bPasswordProtected = pImplLib->mbPasswordProtected; + aLibDesc.aElementNames = pImplLib->getElementNames(); + + implStoreLibraryIndexFile( pImplLib, aLibDesc, xDummyStor, URL, xToUseSFI ); +} + +OUString SfxLibraryContainer::expand_url( const OUString& url ) + throw(::com::sun::star::uno::RuntimeException) +{ + if (0 == url.compareToAscii( RTL_CONSTASCII_STRINGPARAM(EXPAND_PROTOCOL ":") )) + { + if( !mxMacroExpander.is() ) + { + Reference< XPropertySet > xProps( mxMSF, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if( xProps.is() ) + { + Reference< XComponentContext > xContext; + xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; + OSL_ASSERT( xContext.is() ); + if( xContext.is() ) + { + Reference< util::XMacroExpander > xExpander; + xContext->getValueByName( + OUSTR("/singletons/com.sun.star.util.theMacroExpander") ) >>= xExpander; + if(! xExpander.is()) + { + throw uno::DeploymentException( + OUSTR("no macro expander singleton available!"), Reference< XInterface >() ); + } + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !mxMacroExpander.is() ) + { + mxMacroExpander = xExpander; + } + } + } + } + + if( !mxMacroExpander.is() ) + return url; + + // cut protocol + OUString macro( url.copy( sizeof (EXPAND_PROTOCOL ":") -1 ) ); + // decode uric class chars + macro = Uri::decode( macro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string + OUString ret( mxMacroExpander->expandMacros( macro ) ); + return ret; + } + else if( mxStringSubstitution.is() ) + { + OUString ret( mxStringSubstitution->substituteVariables( url, false ) ); + return ret; + } + else + { + return url; + } +} + +// Methods XServiceInfo +::sal_Bool SAL_CALL SfxLibraryContainer::supportsService( const ::rtl::OUString& _rServiceName ) + throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + Sequence< OUString > aSupportedServices( getSupportedServiceNames() ); + const OUString* pSupportedServices = aSupportedServices.getConstArray(); + for ( sal_Int32 i=0; i<aSupportedServices.getLength(); ++i, ++pSupportedServices ) + if ( *pSupportedServices == _rServiceName ) + return sal_True; + return sal_False; +} + +//============================================================================ + +// Implementation class SfxLibrary + +// Ctor +SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType, + const Reference< XMultiServiceFactory >& xMSF, const Reference< XSimpleFileAccess >& xSFI ) + : OComponentHelper( m_aMutex ) + , mxMSF( xMSF ) + , mxSFI( xSFI ) + , mrModifiable( _rModifiable ) + , maNameContainer( aType ) + , mbLoaded( sal_True ) + , mbIsModified( sal_True ) + , mbInitialised( sal_False ) + , mbLink( sal_False ) + , mbReadOnly( sal_False ) + , mbReadOnlyLink( sal_False ) + , mbPreload( sal_False ) + , mbPasswordProtected( sal_False ) + , mbPasswordVerified( sal_False ) + , mbDoc50Password( sal_False ) + , mbSharedIndexFile( sal_False ) + , mbExtension( sal_False ) +{ +} + +SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType, + const Reference< XMultiServiceFactory >& xMSF, const Reference< XSimpleFileAccess >& xSFI, + const OUString& aLibInfoFileURL, const OUString& aStorageURL, sal_Bool ReadOnly ) + : OComponentHelper( m_aMutex ) + , mxMSF( xMSF ) + , mxSFI( xSFI ) + , mrModifiable( _rModifiable ) + , maNameContainer( aType ) + , mbLoaded( sal_False ) + , mbIsModified( sal_True ) + , mbInitialised( sal_False ) + , maLibInfoFileURL( aLibInfoFileURL ) + , maStorageURL( aStorageURL ) + , mbLink( sal_True ) + , mbReadOnly( sal_False ) + , mbReadOnlyLink( ReadOnly ) + , mbPreload( sal_False ) + , mbPasswordProtected( sal_False ) + , mbPasswordVerified( sal_False ) + , mbDoc50Password( sal_False ) + , mbSharedIndexFile( sal_False ) + , mbExtension( sal_False ) +{ +} + +void SfxLibrary::implSetModified( sal_Bool _bIsModified ) +{ + if ( mbIsModified == _bIsModified ) + return; + mbIsModified = _bIsModified; + if ( mbIsModified ) + mrModifiable.setModified( sal_True ); +} + +// Methods XInterface +Any SAL_CALL SfxLibrary::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet; + + /* + if( mbReadOnly ) + { + aRet = Any( ::cppu::queryInterface( rType, + static_cast< XContainer * >( this ), + static_cast< XNameAccess * >( this ) ) ); + } + else + { + */ + aRet = Any( ::cppu::queryInterface( rType, + static_cast< XContainer * >( this ), + static_cast< XNameContainer * >( this ), + static_cast< XNameAccess * >( this ) ) ); + //} + if( !aRet.hasValue() ) + aRet = OComponentHelper::queryInterface( rType ); + return aRet; +} + +// Methods XElementAccess +Type SfxLibrary::getElementType() + throw(RuntimeException) +{ + return maNameContainer.getElementType(); +} + +sal_Bool SfxLibrary::hasElements() + throw(RuntimeException) +{ + sal_Bool bRet = maNameContainer.hasElements(); + return bRet; +} + +// Methods XNameAccess +Any SfxLibrary::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + impl_checkLoaded(); + + Any aRetAny = maNameContainer.getByName( aName ) ; + return aRetAny; +} + +Sequence< OUString > SfxLibrary::getElementNames() + throw(RuntimeException) +{ + return maNameContainer.getElementNames(); +} + +sal_Bool SfxLibrary::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + sal_Bool bRet = maNameContainer.hasByName( aName ); + return bRet; +} + +void SfxLibrary::impl_checkReadOnly() +{ + if( mbReadOnly || (mbLink && mbReadOnlyLink) ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Library is readonly." ) ), + // TODO: resource + *this, 0 + ); +} + +void SfxLibrary::impl_checkLoaded() +{ + if ( !mbLoaded ) + throw WrappedTargetException( + ::rtl::OUString(), + *this, + makeAny( LibraryNotLoadedException( + ::rtl::OUString(), + *this + ) ) + ); +} + +// Methods XNameReplace +void SfxLibrary::replaceByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + impl_checkReadOnly(); + impl_checkLoaded(); + + OSL_ENSURE( isLibraryElementValid( aElement ), "SfxLibrary::replaceByName: replacing element is invalid!" ); + + maNameContainer.replaceByName( aName, aElement ); + implSetModified( sal_True ); +} + + +// Methods XNameContainer +void SfxLibrary::insertByName( const OUString& aName, const Any& aElement ) + throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + impl_checkReadOnly(); + impl_checkLoaded(); + + OSL_ENSURE( isLibraryElementValid( aElement ), "SfxLibrary::insertByName: to-be-inserted element is invalid!" ); + + maNameContainer.insertByName( aName, aElement ); + implSetModified( sal_True ); +} + +void SfxLibrary::impl_removeWithoutChecks( const ::rtl::OUString& _rElementName ) +{ + maNameContainer.removeByName( _rElementName ); + implSetModified( sal_True ); + + // Remove element file + if( maStorageURL.getLength() ) + { + INetURLObject aElementInetObj( maStorageURL ); + aElementInetObj.insertName( _rElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementInetObj.setExtension( maLibElementFileExtension ); + OUString aFile = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + try + { + if( mxSFI->exists( aFile ) ) + mxSFI->kill( aFile ); + } + catch( Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +void SfxLibrary::removeByName( const OUString& Name ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + impl_checkReadOnly(); + impl_checkLoaded(); + impl_removeWithoutChecks( Name ); +} + +// XTypeProvider +Sequence< Type > SfxLibrary::getTypes() + throw( RuntimeException ) +{ + static OTypeCollection * s_pTypes_NameContainer = 0; + { + if( !s_pTypes_NameContainer ) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if( !s_pTypes_NameContainer ) + { + static OTypeCollection s_aTypes_NameContainer( + ::getCppuType( (const Reference< XNameContainer > *)0 ), + ::getCppuType( (const Reference< XContainer > *)0 ), + OComponentHelper::getTypes() ); + s_pTypes_NameContainer = &s_aTypes_NameContainer; + } + } + return s_pTypes_NameContainer->getTypes(); + } +} + + +Sequence< sal_Int8 > SfxLibrary::getImplementationId() + throw( RuntimeException ) +{ + static OImplementationId * s_pId_NameContainer = 0; + { + if( !s_pId_NameContainer ) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if( !s_pId_NameContainer ) + { + static OImplementationId s_aId_NameContainer; + s_pId_NameContainer = &s_aId_NameContainer; + } + } + return s_pId_NameContainer->getImplementationId(); + } +} + + +//============================================================================ + +// Methods XContainer +void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener ) + throw (RuntimeException) +{ + maNameContainer.setEventSource( static_cast< XInterface* >( (OWeakObject*)this ) ); + maNameContainer.addContainerListener( xListener ); +} + +void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerListener >& xListener ) + throw (RuntimeException) +{ + maNameContainer.removeContainerListener( xListener ); +} + + +//============================================================================ +// Implementation class ScriptExtensionIterator + +static rtl::OUString aBasicLibMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.basic-library" ) ); +static rtl::OUString aDialogLibMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.dialog-library" ) ); + +ScriptExtensionIterator::ScriptExtensionIterator( void ) + : m_eState( USER_EXTENSIONS ) + , m_bUserPackagesLoaded( false ) + , m_bSharedPackagesLoaded( false ) + , m_iUserPackage( 0 ) + , m_iSharedPackage( 0 ) + , m_pScriptSubPackageIterator( NULL ) +{ + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + xProps->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext; + OSL_ASSERT( m_xContext.is() ); + } + if( !m_xContext.is() ) + { + throw RuntimeException( + ::rtl::OUString::createFromAscii( "ScriptExtensionIterator::init(), no XComponentContext" ), + Reference< XInterface >() ); + } +} + +rtl::OUString ScriptExtensionIterator::nextBasicOrDialogLibrary( bool& rbPureDialogLib ) +{ + rtl::OUString aRetLib; + + while( !aRetLib.getLength() && m_eState != END_REACHED ) + { + switch( m_eState ) + { + case USER_EXTENSIONS: + { + Reference< deployment::XPackage > xScriptPackage = + implGetNextUserScriptPackage( rbPureDialogLib ); + if( !xScriptPackage.is() ) + break; + + aRetLib = xScriptPackage->getURL(); + break; + } + + case SHARED_EXTENSIONS: + { + Reference< deployment::XPackage > xScriptPackage = + implGetNextSharedScriptPackage( rbPureDialogLib ); + if( !xScriptPackage.is() ) + break; + + aRetLib = xScriptPackage->getURL(); + break; + } + case END_REACHED: + VOS_ENSURE( false, "ScriptExtensionIterator::nextBasicOrDialogLibrary(): Invalid case END_REACHED" ); + break; + } + } + + return aRetLib; +} + +ScriptSubPackageIterator::ScriptSubPackageIterator( Reference< deployment::XPackage > xMainPackage ) + : m_xMainPackage( xMainPackage ) + , m_bIsValid( false ) + , m_bIsBundle( false ) + , m_nSubPkgCount( 0 ) + , m_iNextSubPkg( 0 ) +{ + Reference< deployment::XPackage > xScriptPackage; + if( !m_xMainPackage.is() ) + return; + + // Check if parent package is registered + beans::Optional< beans::Ambiguous<sal_Bool> > option( m_xMainPackage->isRegistered + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); + bool bRegistered = false; + if( option.IsPresent ) + { + beans::Ambiguous<sal_Bool> const & reg = option.Value; + if( !reg.IsAmbiguous && reg.Value ) + bRegistered = true; + } + if( bRegistered ) + { + m_bIsValid = true; + if( m_xMainPackage->isBundle() ) + { + m_bIsBundle = true; + m_aSubPkgSeq = m_xMainPackage->getBundle + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ); + m_nSubPkgCount = m_aSubPkgSeq.getLength(); + } + } +} + +Reference< deployment::XPackage > ScriptSubPackageIterator::getNextScriptSubPackage + ( bool& rbPureDialogLib ) +{ + rbPureDialogLib = false; + + Reference< deployment::XPackage > xScriptPackage; + if( !m_bIsValid ) + return xScriptPackage; + + if( m_bIsBundle ) + { + const Reference< deployment::XPackage >* pSeq = m_aSubPkgSeq.getConstArray(); + sal_Int32 iPkg; + for( iPkg = m_iNextSubPkg ; iPkg < m_nSubPkgCount ; ++iPkg ) + { + const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; + xScriptPackage = implDetectScriptPackage( xSubPkg, rbPureDialogLib ); + if( xScriptPackage.is() ) + break; + } + m_iNextSubPkg = iPkg + 1; + } + else + { + xScriptPackage = implDetectScriptPackage( m_xMainPackage, rbPureDialogLib ); + m_bIsValid = false; // No more script packages + } + + return xScriptPackage; +} + +Reference< deployment::XPackage > ScriptSubPackageIterator::implDetectScriptPackage + ( const Reference< deployment::XPackage > xPackage, bool& rbPureDialogLib ) +{ + Reference< deployment::XPackage > xScriptPackage; + + if( xPackage.is() ) + { + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aBasicLibMediaType ) ) + { + xScriptPackage = xPackage; + } + else if( aMediaType.equals( aDialogLibMediaType ) ) + { + rbPureDialogLib = true; + xScriptPackage = xPackage; + } + } + + return xScriptPackage; +} + +Reference< deployment::XPackage > ScriptExtensionIterator::implGetScriptPackageFromPackage + ( const Reference< deployment::XPackage > xPackage, bool& rbPureDialogLib ) +{ + rbPureDialogLib = false; + + Reference< deployment::XPackage > xScriptPackage; + if( !xPackage.is() ) + return xScriptPackage; + + // Check if parent package is registered + beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); + bool bRegistered = false; + if( option.IsPresent ) + { + beans::Ambiguous<sal_Bool> const & reg = option.Value; + if( !reg.IsAmbiguous && reg.Value ) + bRegistered = true; + } + if( bRegistered ) + { + if( xPackage->isBundle() ) + { + Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ); + sal_Int32 nPkgCount = aPkgSeq.getLength(); + const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray(); + for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg ) + { + const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aBasicLibMediaType ) ) + { + xScriptPackage = xSubPkg; + break; + } + else if( aMediaType.equals( aDialogLibMediaType ) ) + { + rbPureDialogLib = true; + xScriptPackage = xSubPkg; + break; + } + } + } + else + { + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aBasicLibMediaType ) ) + { + xScriptPackage = xPackage; + } + else if( aMediaType.equals( aDialogLibMediaType ) ) + { + rbPureDialogLib = true; + xScriptPackage = xPackage; + } + } + } + + return xScriptPackage; +} + +Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextUserScriptPackage + ( bool& rbPureDialogLib ) +{ + Reference< deployment::XPackage > xScriptPackage; + + if( !m_bUserPackagesLoaded ) + { + try + { + Reference< XPackageManager > xUserManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") ); + m_aUserPackagesSeq = xUserManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + } + catch( com::sun::star::uno::DeploymentException& ) + { + // Special Office installations may not contain deployment code + m_eState = END_REACHED; + return xScriptPackage; + } + + m_bUserPackagesLoaded = true; + } + + if( m_iUserPackage == m_aUserPackagesSeq.getLength() ) + { + m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE + } + else + { + if( m_pScriptSubPackageIterator == NULL ) + { + const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage ]; + VOS_ENSURE( xPackage.is(), "ScriptExtensionIterator::implGetNextUserScriptPackage(): Invalid package" ); + m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage ); + } + + if( m_pScriptSubPackageIterator != NULL ) + { + xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib ); + if( !xScriptPackage.is() ) + { + delete m_pScriptSubPackageIterator; + m_pScriptSubPackageIterator = NULL; + m_iUserPackage++; + } + } + } + + return xScriptPackage; +} + +Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextSharedScriptPackage + ( bool& rbPureDialogLib ) +{ + Reference< deployment::XPackage > xScriptPackage; + + if( !m_bSharedPackagesLoaded ) + { + try + { + Reference< XPackageManager > xSharedManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") ); + m_aSharedPackagesSeq = xSharedManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + } + catch( com::sun::star::uno::DeploymentException& ) + { + // Special Office installations may not contain deployment code + return xScriptPackage; + } + + m_bSharedPackagesLoaded = true; + } + + if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() ) + { + m_eState = END_REACHED; + } + else + { + if( m_pScriptSubPackageIterator == NULL ) + { + const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage ]; + VOS_ENSURE( xPackage.is(), "ScriptExtensionIterator::implGetNextSharedScriptPackage(): Invalid package" ); + m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage ); + } + + if( m_pScriptSubPackageIterator != NULL ) + { + xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib ); + if( !xScriptPackage.is() ) + { + delete m_pScriptSubPackageIterator; + m_pScriptSubPackageIterator = NULL; + m_iSharedPackage++; + } + } + } + + return xScriptPackage; +} + +} // namespace basic diff --git a/basic/source/uno/sbmodule.cxx b/basic/source/uno/sbmodule.cxx new file mode 100644 index 000000000000..8509a9312153 --- /dev/null +++ b/basic/source/uno/sbmodule.cxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbmodule.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include "sbmodule.hxx" +#include <rtl/instance.hxx> + +//........................................................................ +namespace basic +{ +//........................................................................ + + IMPLEMENT_COMPONENT_MODULE( BasicModule ); + +//........................................................................ +} // namespace basic +//........................................................................ + + diff --git a/basic/source/uno/sbmodule.hxx b/basic/source/uno/sbmodule.hxx new file mode 100644 index 000000000000..b6c102dd5294 --- /dev/null +++ b/basic/source/uno/sbmodule.hxx @@ -0,0 +1,48 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbmodule.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SBMODULE_HXX +#define SBMODULE_HXX + +#include <comphelper/componentmodule.hxx> + +//........................................................................ +namespace basic +{ +//........................................................................ + + DECLARE_COMPONENT_MODULE( BasicModule, BasicModuleClient ) + +//........................................................................ +} // namespace basic +//........................................................................ + +#endif // SBMODULE_HXX + diff --git a/basic/source/uno/sbservices.cxx b/basic/source/uno/sbservices.cxx new file mode 100644 index 000000000000..ea539e686815 --- /dev/null +++ b/basic/source/uno/sbservices.cxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sbservices.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include "sbmodule.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace basic +{ +//........................................................................ + + //-------------------------------------------------------------------- + extern void createRegistryInfo_SfxDialogLibraryContainer(); + extern void createRegistryInfo_SfxScriptLibraryContainer(); + + static void initializeModule() + { + static bool bInitialized( false ); + if ( !bInitialized ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !bInitialized ) + { + createRegistryInfo_SfxDialogLibraryContainer(); + createRegistryInfo_SfxScriptLibraryContainer(); + } + } + } + +//........................................................................ +} // namespace basic +//........................................................................ + +IMPLEMENT_COMPONENT_LIBRARY_API( ::basic::BasicModule, ::basic::initializeModule ) + diff --git a/basic/source/uno/scriptcont.cxx b/basic/source/uno/scriptcont.cxx new file mode 100644 index 000000000000..aad4815872c0 --- /dev/null +++ b/basic/source/uno/scriptcont.cxx @@ -0,0 +1,1174 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scriptcont.cxx,v $ + * $Revision: 1.11 $ + * + * 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 "scriptcont.hxx" +#include "sbmodule.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XEncryptionProtectedSource.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/task/ErrorCodeIOException.hpp> +#include <comphelper/processfactory.hxx> +#ifndef _COMPHELPER_STORAGEHELPER_HXX_ +#include <comphelper/storagehelper.hxx> +#endif +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <osl/mutex.hxx> +#include <rtl/digest.h> +#include <rtl/strbuf.hxx> + +// For password functionality +#include <tools/urlobj.hxx> + + +#include <svtools/pathoptions.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbmod.hxx> +#include "modsizeexceeded.hxx" +#include <xmlscript/xmlmod_imexp.hxx> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/util/VetoException.hpp> + +namespace basic +{ + +using namespace com::sun::star::document; +using namespace com::sun::star::container; +using namespace com::sun::star::io; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::lang; +using namespace com::sun::star::script; +using namespace com::sun::star::xml::sax; +using namespace com::sun::star; +using namespace cppu; +using namespace rtl; +using namespace osl; + +using com::sun::star::uno::Reference; + +//============================================================================ +// Implementation class SfxScriptLibraryContainer + +const sal_Char* SAL_CALL SfxScriptLibraryContainer::getInfoFileName() const { return "script"; } +const sal_Char* SAL_CALL SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; } +const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; } +const sal_Char* SAL_CALL SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; } + +// OldBasicPassword interface +void SfxScriptLibraryContainer::setLibraryPassword + ( const String& rLibraryName, const String& rPassword ) +{ + try + { + SfxLibrary* pImplLib = getImplLib( rLibraryName ); + if( rPassword.Len() ) + { + pImplLib->mbDoc50Password = sal_True; + pImplLib->mbPasswordProtected = sal_True; + pImplLib->maPassword = rPassword; + } + } + catch( NoSuchElementException& ) {} +} + +String SfxScriptLibraryContainer::getLibraryPassword( const String& rLibraryName ) +{ + SfxLibrary* pImplLib = getImplLib( rLibraryName ); + String aPassword; + if( pImplLib->mbPasswordVerified ) + aPassword = pImplLib->maPassword; + return aPassword; +} + +void SfxScriptLibraryContainer::clearLibraryPassword( const String& rLibraryName ) +{ + try + { + SfxLibrary* pImplLib = getImplLib( rLibraryName ); + pImplLib->mbDoc50Password = sal_False; + pImplLib->mbPasswordProtected = sal_False; + pImplLib->maPassword = OUString(); + } + catch( NoSuchElementException& ) {} +} + +sal_Bool SfxScriptLibraryContainer::hasLibraryPassword( const String& rLibraryName ) +{ + SfxLibrary* pImplLib = getImplLib( rLibraryName ); + return pImplLib->mbPasswordProtected; +} + + +// Ctor for service +SfxScriptLibraryContainer::SfxScriptLibraryContainer( void ) + :maScriptLanguage( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) ) +{ + // all initialisation has to be done + // by calling XInitialization::initialize +} + +SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference< embed::XStorage >& xStorage ) + :maScriptLanguage( RTL_CONSTASCII_USTRINGPARAM( "StarBasic" ) ) +{ + init( OUString(), xStorage ); +} + +// Methods to get library instances of the correct type +SfxLibrary* SfxScriptLibraryContainer::implCreateLibrary( const OUString& aName ) +{ + (void)aName; // Only needed for SfxDialogLibrary + SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxMSF, mxSFI ); + return pRet; +} + +SfxLibrary* SfxScriptLibraryContainer::implCreateLibraryLink + ( const OUString& aName, const OUString& aLibInfoFileURL, + const OUString& StorageURL, sal_Bool ReadOnly ) +{ + (void)aName; // Only needed for SfxDialogLibrary + SfxLibrary* pRet = + new SfxScriptLibrary + ( maModifiable, mxMSF, mxSFI, aLibInfoFileURL, StorageURL, ReadOnly ); + return pRet; +} + +Any SAL_CALL SfxScriptLibraryContainer::createEmptyLibraryElement( void ) +{ + OUString aMod; + Any aRetAny; + aRetAny <<= aMod; + return aRetAny; +} + +bool SAL_CALL SfxScriptLibraryContainer::isLibraryElementValid( Any aElement ) const +{ + return SfxScriptLibrary::containsValidModule( aElement ); +} + +void SAL_CALL SfxScriptLibraryContainer::writeLibraryElement +( + Any aElement, + const OUString& aElementName, + Reference< XOutputStream > xOutput +) + throw(Exception) +{ + // Create sax writer + Reference< XExtendedDocumentHandler > xHandler( + mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") ) ), UNO_QUERY ); + if( !xHandler.is() ) + { + OSL_ENSURE( 0, "### couln't create sax-writer component\n" ); + return; + } + + Reference< XTruncate > xTruncate( xOutput, UNO_QUERY ); + OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" ); + if ( xTruncate.is() ) + xTruncate->truncate(); + + Reference< XActiveDataSource > xSource( xHandler, UNO_QUERY ); + xSource->setOutputStream( xOutput ); + + xmlscript::ModuleDescriptor aMod; + aMod.aName = aElementName; + aMod.aLanguage = maScriptLanguage; + aElement >>= aMod.aCode; + xmlscript::exportScriptModule( xHandler, aMod ); +} + + +Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement + ( const OUString& aFile, const uno::Reference< io::XInputStream >& xInStream ) +{ + Any aRetAny; + + Reference< XParser > xParser( mxMSF->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser") ) ), UNO_QUERY ); + if( !xParser.is() ) + { + OSL_ENSURE( 0, "### couln't create sax parser component\n" ); + return aRetAny; + } + + + // Read from storage? + sal_Bool bStorage = xInStream.is(); + Reference< XInputStream > xInput; + + if( bStorage ) + { + xInput = xInStream; + } + else + { + try + { + xInput = mxSFI->openFileRead( aFile ); + } + catch( Exception& ) + //catch( Exception& e ) + { + // TODO: + //throw WrappedTargetException( e ); + } + } + + if( !xInput.is() ) + return aRetAny; + + InputSource source; + source.aInputStream = xInput; + source.sSystemId = aFile; + + // start parsing + xmlscript::ModuleDescriptor aMod; + + try + { + xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) ); + xParser->parseStream( source ); + } + catch( Exception& ) + { + SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile ); + ULONG nErrorCode = ERRCODE_IO_GENERAL; + ErrorHandler::HandleError( nErrorCode ); + } + + aRetAny <<= aMod.aCode; + + // TODO: Check language + // aMod.aLanguage + // aMod.aName ignored + + return aRetAny; +} + +SfxLibraryContainer* SfxScriptLibraryContainer::createInstanceImpl( void ) +{ + return new SfxScriptLibraryContainer(); +} + +void SAL_CALL SfxScriptLibraryContainer::importFromOldStorage( const ::rtl::OUString& aFile ) +{ + // TODO: move loading from old storage to binary filters? + SotStorageRef xStorage = new SotStorage( sal_False, aFile ); + if( xStorage.Is() && xStorage->GetError() == ERRCODE_NONE ) + { + // We need a BasicManager to avoid problems + // StarBASIC* pBas = new StarBASIC(); + BasicManager* pBasicManager = new BasicManager( *(SotStorage*)xStorage, aFile ); + + // Set info + LibraryContainerInfo aInfo( this, NULL, static_cast< OldBasicPassword* >( this ) ); + pBasicManager->SetLibraryContainerInfo( aInfo ); + + // Now the libraries should be copied to this SfxScriptLibraryContainer + BasicManager::LegacyDeleteBasicManager( pBasicManager ); + } +} + + +// Storing with password encryption + +// Methods XLibraryContainerPassword +sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString& Name ) + throw (NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + sal_Bool bRet = pImplLib->mbPasswordProtected; + return bRet; +} + +sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString& Name ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + if( !pImplLib->mbPasswordProtected ) + throw IllegalArgumentException(); + sal_Bool bRet = pImplLib->mbPasswordVerified; + return bRet; +} + +sal_Bool SAL_CALL SfxScriptLibraryContainer::verifyLibraryPassword + ( const OUString& Name, const OUString& Password ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified ) + throw IllegalArgumentException(); + + // Test password + sal_Bool bSuccess = sal_False; + if( pImplLib->mbDoc50Password ) + { + bSuccess = ( Password == pImplLib->maPassword ); + if( bSuccess ) + pImplLib->mbPasswordVerified = sal_True; + } + else + { + pImplLib->maPassword = Password; + bSuccess = implLoadPasswordLibrary( pImplLib, Name, sal_True ); + if( bSuccess ) + { + // The library gets modified by verifiying the password, because other- + // wise for saving the storage would be copied and that doesn't work + // with mtg's storages when the password is verified + pImplLib->implSetModified( sal_True ); + pImplLib->mbPasswordVerified = sal_True; + + // Reload library to get source + if( pImplLib->mbLoaded ) + implLoadPasswordLibrary( pImplLib, Name ); + } + } + return bSuccess; +} + +void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name, + const OUString& OldPassword, const OUString& NewPassword ) + throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + SfxLibrary* pImplLib = getImplLib( Name ); + if( OldPassword == NewPassword ) + return; + + sal_Bool bOldPassword = ( OldPassword.getLength() > 0 ); + sal_Bool bNewPassword = ( NewPassword.getLength() > 0 ); + sal_Bool bStorage = mxStorage.is() && !pImplLib->mbLink; + + if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) ) + throw IllegalArgumentException(); + + // Library must be loaded + loadLibrary( Name ); + + sal_Bool bKillCryptedFiles = sal_False; + sal_Bool bKillUncryptedFiles = sal_False; + + // Remove or change password? + if( bOldPassword ) + { + if( isLibraryPasswordVerified( Name ) ) + { + if( pImplLib->maPassword != OldPassword ) + throw IllegalArgumentException(); + } + else + { + if( !verifyLibraryPassword( Name, OldPassword ) ) + throw IllegalArgumentException(); + + // Reload library to get source + // Should be done in verifyLibraryPassword loadLibrary( Name ); + } + + if( !bNewPassword ) + { + pImplLib->mbPasswordProtected = sal_False; + pImplLib->mbPasswordVerified = sal_False; + pImplLib->maPassword = OUString(); + + maModifiable.setModified( sal_True ); + pImplLib->implSetModified( sal_True ); + + if( !bStorage && !pImplLib->mbDoc50Password ) + { + // Store application basic uncrypted + uno::Reference< embed::XStorage > xStorage; + storeLibraries_Impl( xStorage, sal_False ); + bKillCryptedFiles = sal_True; + } + } + } + + // Set new password? + if( bNewPassword ) + { + pImplLib->mbPasswordProtected = sal_True; + pImplLib->mbPasswordVerified = sal_True; + pImplLib->maPassword = NewPassword; + + maModifiable.setModified( sal_True ); + pImplLib->implSetModified( sal_True ); + + if( !bStorage && !pImplLib->mbDoc50Password ) + { + // Store applictaion basic crypted + uno::Reference< embed::XStorage > xStorage; + storeLibraries_Impl( xStorage, sal_False ); + bKillUncryptedFiles = sal_True; + } + } + + if( bKillCryptedFiles || bKillUncryptedFiles ) + { + Sequence< OUString > aElementNames = pImplLib->getElementNames(); + sal_Int32 nNameCount = aElementNames.getLength(); + const OUString* pNames = aElementNames.getConstArray(); + OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name ); + try + { + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + INetURLObject aElementInetObj( aLibDirPath ); + aElementInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + if( bKillUncryptedFiles ) + aElementInetObj.setExtension( maLibElementFileExtension ); + else + aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) ); + String aElementPath( aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + if( mxSFI->exists( aElementPath ) ) + mxSFI->kill( aElementPath ); + } + } + catch( Exception& ) {} + } +} + + +void setStreamKey( uno::Reference< io::XStream > xStream, const ::rtl::OUString& aPass ) +{ + uno::Reference< embed::XEncryptionProtectedSource > xEncrStream( xStream, uno::UNO_QUERY ); + if ( xEncrStream.is() ) + xEncrStream->setEncryptionPassword( aPass ); +} + + +// Impl methods +sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, + const ::rtl::OUString& aName, const uno::Reference< embed::XStorage >& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ) +{ + OUString aDummyLocation; + Reference< XSimpleFileAccess > xDummySFA; + return implStorePasswordLibrary( pLib, aName, xStorage, aDummyLocation, xDummySFA, xHandler ); +} + +sal_Bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + const ::rtl::OUString& aTargetURL, const Reference< XSimpleFileAccess > xToUseSFI, const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ) +{ + bool bExport = aTargetURL.getLength(); + + BasicManager* pBasicMgr = getBasicManager(); + OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" ); + if ( !pBasicMgr ) + return sal_False; + + // Only need to handle the export case here, + // save/saveas etc are handled in sfxbasemodel::storeSelf & + // sfxbasemodel::impl_store + uno::Sequence<rtl::OUString> aNames; + if ( bExport && pBasicMgr->LegacyPsswdBinaryLimitExceeded(aNames) ) + { + if ( xHandler.is() ) + { + ModuleSizeExceeded* pReq = new ModuleSizeExceeded( aNames ); + uno::Reference< task::XInteractionRequest > xReq( pReq ); + xHandler->handle( xReq ); + if ( pReq->isAbort() ) + throw util::VetoException(); + } + } + + StarBASIC* pBasicLib = pBasicMgr->GetLib( aName ); + if( !pBasicLib ) + return sal_False; + + Sequence< OUString > aElementNames = pLib->getElementNames(); + sal_Int32 nNameCount = aElementNames.getLength(); + const OUString* pNames = aElementNames.getConstArray(); + + sal_Bool bLink = pLib->mbLink; + sal_Bool bStorage = xStorage.is() && !bLink; + if( bStorage ) + { + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + // Write binary image stream + SbModule* pMod = pBasicLib->FindModule( aElementName ); + if( pMod ) + { + //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") ); + OUString aCodeStreamName = aElementName; + aCodeStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".bin") ); + + try { + uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement( + aCodeStreamName, + embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); + + if ( !xCodeStream.is() ) + throw uno::RuntimeException(); + + SvMemoryStream aMemStream; + /*BOOL bStore = */pMod->StoreBinaryData( aMemStream ); + + sal_Int32 nSize = (sal_Int32)aMemStream.Tell(); + Sequence< sal_Int8 > aBinSeq( nSize ); + sal_Int8* pData = aBinSeq.getArray(); + ::rtl_copyMemory( pData, aMemStream.GetData(), nSize ); + + Reference< XOutputStream > xOut = xCodeStream->getOutputStream(); + if ( !xOut.is() ) + throw io::IOException(); // access denied because the stream is readonly + + xOut->writeBytes( aBinSeq ); + xOut->closeOutput(); + } + catch( uno::Exception& ) + { + // TODO: handle error + } + } + + if( pLib->mbPasswordVerified || pLib->mbDoc50Password ) + { + Any aElement = pLib->getByName( aElementName ); + if( !isLibraryElementValid( aElement ) ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OStringBuffer aMessage; + aMessage.append( "invalid library element '" ); + aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) ); + aMessage.append( "'." ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + continue; + } + + OUString aSourceStreamName = aElementName; + aSourceStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") ); + + try { + uno::Reference< io::XStream > xSourceStream = xStorage->openStreamElement( + aSourceStreamName, + embed::ElementModes::READWRITE ); + uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY ); + if ( !xProps.is() ) + throw uno::RuntimeException(); + + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); + + // Set encryption key + setStreamKey( xSourceStream, pLib->maPassword ); + + Reference< XOutputStream > xOutput = xSourceStream->getOutputStream(); + writeLibraryElement( aElement, aElementName, xOutput ); + // writeLibraryElement should have the stream already closed + // xOutput->closeOutput(); + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Problem on storing of password library!\n" ); + // TODO: error handling + } + } + else // !mbPasswordVerified + { + // TODO + // What to do if not verified?! In any case it's already loaded here + } + } + + } + // Application libraries have only to be saved if the password + // is verified because otherwise they can't be modified + else if( pLib->mbPasswordVerified || bExport ) + { + try + { + Reference< XSimpleFileAccess > xSFI = mxSFI; + if( xToUseSFI.is() ) + xSFI = xToUseSFI; + + OUString aLibDirPath; + if( bExport ) + { + INetURLObject aInetObj( aTargetURL ); + aInetObj.insertName( aName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aLibDirPath = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + if( !xSFI->isFolder( aLibDirPath ) ) + xSFI->createFolder( aLibDirPath ); + } + else + { + aLibDirPath = createAppLibraryFolder( pLib, aName ); + } + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + INetURLObject aElementInetObj( aLibDirPath ); + aElementInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) ); + String aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + Any aElement = pLib->getByName( aElementName ); + if( !isLibraryElementValid( aElement ) ) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OStringBuffer aMessage; + aMessage.append( "invalid library element '" ); + aMessage.append( ::rtl::OUStringToOString( aElementName, osl_getThreadTextEncoding() ) ); + aMessage.append( "'." ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); + #endif + continue; + } + + try + { + uno::Reference< embed::XStorage > xElementRootStorage = + ::comphelper::OStorageHelper::GetStorageFromURL( + aElementPath, + embed::ElementModes::READWRITE ); + if ( !xElementRootStorage.is() ) + throw uno::RuntimeException(); + + // Write binary image stream + SbModule* pMod = pBasicLib->FindModule( aElementName ); + if( pMod ) + { + OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") ); + + uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement( + aCodeStreamName, + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); + + SvMemoryStream aMemStream; + /*BOOL bStore = */pMod->StoreBinaryData( aMemStream ); + + sal_Int32 nSize = (sal_Int32)aMemStream.Tell(); + Sequence< sal_Int8 > aBinSeq( nSize ); + sal_Int8* pData = aBinSeq.getArray(); + ::rtl_copyMemory( pData, aMemStream.GetData(), nSize ); + + Reference< XOutputStream > xOut = xCodeStream->getOutputStream(); + if ( xOut.is() ) + { + xOut->writeBytes( aBinSeq ); + xOut->closeOutput(); + } + } + + // Write encrypted source stream + OUString aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") ); + + uno::Reference< io::XStream > xSourceStream; + try + { + xSourceStream = xElementRootStorage->openStreamElement( + aSourceStreamName, + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); + + // #87671 Allow encryption + uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY ); + OSL_ENSURE( xEncr.is(), + "StorageStream opened for writing must implement XEncryptionProtectedSource!\n" ); + if ( !xEncr.is() ) + throw uno::RuntimeException(); + xEncr->setEncryptionPassword( pLib->maPassword ); + } + catch( ::com::sun::star::packages::WrongPasswordException& ) + { + xSourceStream = xElementRootStorage->openEncryptedStreamElement( + aSourceStreamName, + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, + pLib->maPassword ); + } + + uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY ); + if ( !xProps.is() ) + throw uno::RuntimeException(); + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); + + Reference< XOutputStream > xOut = xSourceStream->getOutputStream(); + writeLibraryElement( aElement, aElementName, xOut ); + // i50568: sax writer already closes stream + // xOut->closeOutput(); + + uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY ); + OSL_ENSURE( xTransact.is(), "The storage must implement XTransactedObject!\n" ); + if ( !xTransact.is() ) + throw uno::RuntimeException(); + + xTransact->commit(); + } + catch( uno::Exception& ) + { + // TODO: handle error + } + + // Storage Dtor commits too, that makes problems + // xElementRootStorage->Commit(); + } + } + catch( Exception& ) + { + //throw e; + } + } + return sal_True; +} + +sal_Bool SfxScriptLibraryContainer::implLoadPasswordLibrary + ( SfxLibrary* pLib, const OUString& Name, sal_Bool bVerifyPasswordOnly ) + throw(WrappedTargetException, RuntimeException) +{ + sal_Bool bRet = sal_True; + + sal_Bool bLink = pLib->mbLink; + sal_Bool bStorage = mxStorage.is() && !bLink; + + // Already loaded? Then only verifiedPassword can change something + SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib ); + if( pScriptLib->mbLoaded ) + { + if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && + (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) ) + return sal_False; + } + + StarBASIC* pBasicLib = NULL; + sal_Bool bLoadBinary = sal_False; + if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified ) + { + BasicManager* pBasicMgr = getBasicManager(); + OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" ); + sal_Bool bLoaded = pScriptLib->mbLoaded; + pScriptLib->mbLoaded = sal_True; // Necessary to get lib + pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : NULL; + pScriptLib->mbLoaded = bLoaded; // Restore flag + if( !pBasicLib ) + return sal_False; + + bLoadBinary = sal_True; + pScriptLib->mbLoadedBinary = sal_True; + } + + sal_Bool bLoadSource = sal_False; + if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly ) + { + bLoadSource = sal_True; + pScriptLib->mbLoadedSource = sal_True; + } + + Sequence< OUString > aElementNames = pLib->getElementNames(); + sal_Int32 nNameCount = aElementNames.getLength(); + const OUString* pNames = aElementNames.getConstArray(); + + if( bStorage ) + { + uno::Reference< embed::XStorage > xLibrariesStor; + uno::Reference< embed::XStorage > xLibraryStor; + if( bStorage ) + { + try { + xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); + if ( !xLibrariesStor.is() ) + throw uno::RuntimeException(); + + xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ ); + if ( !xLibraryStor.is() ) + throw uno::RuntimeException(); + } + catch( uno::Exception& ) + { + OSL_ENSURE( 0, "### couln't open sub storage for library\n" ); + return sal_False; + } + } + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + // Load binary + if( bLoadBinary ) + { + SbModule* pMod = pBasicLib->FindModule( aElementName ); + if( !pMod ) + { + pMod = pBasicLib->MakeModule( aElementName, String() ); + pBasicLib->SetModified( FALSE ); + } + + //OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") ); + OUString aCodeStreamName= aElementName; + aCodeStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".bin") ); + + try { + uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement( + aCodeStreamName, + embed::ElementModes::READ ); + if ( !xCodeStream.is() ) + throw uno::RuntimeException(); + + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream ); + if ( !pStream || pStream->GetError() ) + { + sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL; + delete pStream; + throw task::ErrorCodeIOException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), nError ); + } + + /*BOOL bRet = */pMod->LoadBinaryData( *pStream ); + // TODO: Check return value + + delete pStream; + } + catch( uno::Exception& ) + { + // TODO: error handling + } + } + + // Load source + if( bLoadSource || bVerifyPasswordOnly ) + { + // Access encrypted source stream + OUString aSourceStreamName = aElementName; + aSourceStreamName += String( RTL_CONSTASCII_USTRINGPARAM(".xml") ); + + try { + uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement( + aSourceStreamName, + embed::ElementModes::READ, + pLib->maPassword ); + if ( !xSourceStream.is() ) + throw uno::RuntimeException(); + + // if this point is reached then the password is correct + if ( !bVerifyPasswordOnly ) + { + uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream(); + if ( !xInStream.is() ) + throw io::IOException(); // read access denied, seems to be impossible + + Any aAny = importLibraryElement( aSourceStreamName, xInStream ); + if( pLib->hasByName( aElementName ) ) + { + if( aAny.hasValue() ) + pLib->maNameContainer.replaceByName( aElementName, aAny ); + } + else + { + pLib->maNameContainer.insertByName( aElementName, aAny ); + } + } + } + catch( uno::Exception& ) + { + bRet = sal_False; + } + } + } + } + else + { + try + { + OUString aLibDirPath = createAppLibraryFolder( pLib, Name ); + + for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) + { + OUString aElementName = pNames[ i ]; + + INetURLObject aElementInetObj( aLibDirPath ); + aElementInetObj.insertName( aElementName, sal_False, + INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); + aElementInetObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM("pba") ) ); + String aElementPath = aElementInetObj.GetMainURL( INetURLObject::NO_DECODE ); + + uno::Reference< embed::XStorage > xElementRootStorage; + try { + xElementRootStorage = ::comphelper::OStorageHelper::GetStorageFromURL( + aElementPath, + embed::ElementModes::READWRITE ); + } catch( uno::Exception& ) + { + // TODO: error handling + } + + if ( xElementRootStorage.is() ) + { + // Load binary + if( bLoadBinary ) + { + SbModule* pMod = pBasicLib->FindModule( aElementName ); + if( !pMod ) + { + pMod = pBasicLib->MakeModule( aElementName, String() ); + pBasicLib->SetModified( FALSE ); + } + + try { + OUString aCodeStreamName( RTL_CONSTASCII_USTRINGPARAM("code.bin") ); + uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement( + aCodeStreamName, + embed::ElementModes::READ ); + + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xCodeStream ); + if ( !pStream || pStream->GetError() ) + { + sal_Int32 nError = pStream ? pStream->GetError() : ERRCODE_IO_GENERAL; + delete pStream; + throw task::ErrorCodeIOException( ::rtl::OUString(), + uno::Reference< uno::XInterface >(), + nError ); + } + + /*BOOL bRet = */pMod->LoadBinaryData( *pStream ); + // TODO: Check return value + + delete pStream; + } + catch( uno::Exception& ) + { + // TODO: error handling + } + } + + // Load source + if( bLoadSource || bVerifyPasswordOnly ) + { + // Access encrypted source stream + OUString aSourceStreamName( RTL_CONSTASCII_USTRINGPARAM("source.xml") ); + try { + uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement( + aSourceStreamName, + embed::ElementModes::READ, + pLib->maPassword ); + if ( !xSourceStream.is() ) + throw uno::RuntimeException(); + + if ( !bVerifyPasswordOnly ) + { + uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream(); + if ( !xInStream.is() ) + throw io::IOException(); // read access denied, seems to be impossible + + Any aAny = importLibraryElement( aSourceStreamName, xInStream ); + if( pLib->hasByName( aElementName ) ) + { + if( aAny.hasValue() ) + pLib->maNameContainer.replaceByName( aElementName, aAny ); + } + else + { + pLib->maNameContainer.insertByName( aElementName, aAny ); + } + } + } + catch ( uno::Exception& ) + { + bRet = sal_False; + } + } + } + } + + } + catch( Exception& ) + { + // TODO + //throw e; + } + } + +//REMOVE // If the password is verified the library must remain modified, because +//REMOVE // otherwise for saving the storage would be copied and that doesn't work +//REMOVE // with mtg's storages when the password is verified +//REMOVE if( !pLib->mbPasswordVerified ) +//REMOVE pLib->mbModified = sal_False; + return bRet; +} + + +void SfxScriptLibraryContainer::onNewRootStorage() +{ +} + +//============================================================================ +// Service +void createRegistryInfo_SfxScriptLibraryContainer() +{ + static OAutoRegistration< SfxScriptLibraryContainer > aAutoRegistration; +} + +::rtl::OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( ) throw (RuntimeException) +{ + return getImplementationName_static(); +} + +Sequence< ::rtl::OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( ) throw (RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +Sequence< OUString > SfxScriptLibraryContainer::getSupportedServiceNames_static() +{ + Sequence< OUString > aServiceNames( 2 ); + aServiceNames[0] = OUString::createFromAscii( "com.sun.star.script.DocumentScriptLibraryContainer" ); + // plus, for compatibility: + aServiceNames[1] = OUString::createFromAscii( "com.sun.star.script.ScriptLibraryContainer" ); + return aServiceNames; +} + +OUString SfxScriptLibraryContainer::getImplementationName_static() +{ + static OUString aImplName; + static sal_Bool bNeedsInit = sal_True; + + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if( bNeedsInit ) + { + aImplName = OUString::createFromAscii( "com.sun.star.comp.sfx2.ScriptLibraryContainer" ); + bNeedsInit = sal_False; + } + return aImplName; +} + +Reference< XInterface > SAL_CALL SfxScriptLibraryContainer::Create + ( const Reference< XComponentContext >& ) + throw( Exception ) +{ + Reference< XInterface > xRet = + static_cast< XInterface* >( static_cast< OWeakObject* >(new SfxScriptLibraryContainer()) ); + return xRet; +} + +//============================================================================ +// Implementation class SfxScriptLibrary + +// Ctor +SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable, + const Reference< XMultiServiceFactory >& xMSF, + const Reference< XSimpleFileAccess >& xSFI ) + : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI ) + , mbLoadedSource( sal_False ) + , mbLoadedBinary( sal_False ) +{ +} + +SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable, + const Reference< XMultiServiceFactory >& xMSF, + const Reference< XSimpleFileAccess >& xSFI, + const OUString& aLibInfoFileURL, + const OUString& aStorageURL, + sal_Bool ReadOnly ) + : SfxLibrary( _rModifiable, getCppuType( (const OUString *)0 ), xMSF, xSFI, + aLibInfoFileURL, aStorageURL, ReadOnly) + , mbLoadedSource( sal_False ) + , mbLoadedBinary( sal_False ) +{ +} + +// Provide modify state including resources +sal_Bool SfxScriptLibrary::isModified( void ) +{ + return implIsModified(); // No resources +} + +void SfxScriptLibrary::storeResources( void ) +{ + // No resources +} + +void SfxScriptLibrary::storeResourcesToURL( const ::rtl::OUString& URL, + const Reference< task::XInteractionHandler >& Handler ) +{ + (void)URL; + (void)Handler; +} + +void SfxScriptLibrary::storeResourcesAsURL + ( const ::rtl::OUString& URL, const ::rtl::OUString& NewName ) +{ + (void)URL; + (void)NewName; +} + +void SfxScriptLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference + < ::com::sun::star::embed::XStorage >& xStorage ) +{ + // No resources + (void)xStorage; +} + +bool SfxScriptLibrary::containsValidModule( const Any& aElement ) +{ + OUString sModuleText; + aElement >>= sModuleText; + return ( sModuleText.getLength() > 0 ); +} + +bool SAL_CALL SfxScriptLibrary::isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const +{ + return SfxScriptLibrary::containsValidModule( aElement ); +} + +//============================================================================ + +} // namespace basic |