4436 lines
120 KiB
C++
4436 lines
120 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_basic.hxx"
|
|
|
|
|
|
#include <tools/date.hxx>
|
|
#include <basic/sbxvar.hxx>
|
|
#include <osl/process.h>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <vcl/sound.hxx>
|
|
#include <tools/wintypes.hxx>
|
|
#include <vcl/msgbox.hxx>
|
|
#include <basic/sbx.hxx>
|
|
#include <svl/zforlist.hxx>
|
|
#include <rtl/math.hxx>
|
|
#include <tools/urlobj.hxx>
|
|
#include <osl/time.h>
|
|
#include <unotools/charclass.hxx>
|
|
#include <unotools/ucbstreamhelper.hxx>
|
|
#include <tools/wldcrd.hxx>
|
|
#include <i18npool/lang.h>
|
|
#include <rtl/string.hxx>
|
|
|
|
#include "runtime.hxx"
|
|
#include "sbunoobj.hxx"
|
|
#ifdef WNT
|
|
#include <tools/fsys.hxx>
|
|
#else
|
|
#include <osl/file.hxx>
|
|
#endif
|
|
#include "errobject.hxx"
|
|
|
|
#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>
|
|
#include <com/sun/star/script/XErrorQuery.hpp>
|
|
#include <ooo/vba/XHelperInterface.hpp>
|
|
#include <com/sun/star/bridge/oleautomation/XAutomationObject.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::script;
|
|
using namespace com::sun::star::frame;
|
|
|
|
#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 <basic/vbahelper.hxx>
|
|
|
|
#include <list>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
SbxVariable* getDefaultProp( SbxVariable* pRef );
|
|
|
|
#if defined (WNT)
|
|
#include <direct.h> // _getdcwd get current work directory, _chdrive
|
|
#endif
|
|
|
|
#ifdef UNX
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <basic/sbobjmod.hxx>
|
|
|
|
#ifdef WNT
|
|
#define GradientStyle_RECT BLA_GradientStyle_RECT
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
#undef GetObject
|
|
#undef GradientSyle_RECT
|
|
#endif
|
|
|
|
// from source/classes/sbxmod.cxx
|
|
Reference< XModel > getDocumentModel( StarBASIC* );
|
|
|
|
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 sal_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;
|
|
}
|
|
|
|
// TODO: -> SbiGlobals
|
|
static com::sun::star::uno::Reference< XSimpleFileAccess3 > getFileAccess( void )
|
|
{
|
|
static com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI;
|
|
if( !xSFI.is() )
|
|
{
|
|
com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
|
|
if( xSMgr.is() )
|
|
{
|
|
xSFI = com::sun::star::uno::Reference< XSimpleFileAccess3 >( xSMgr->createInstance
|
|
( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" )) ), UNO_QUERY );
|
|
}
|
|
}
|
|
return xSFI;
|
|
}
|
|
|
|
|
|
|
|
// Properties und Methoden legen beim Get (bPut = sal_False) den Returnwert
|
|
// im Element 0 des Argv ab; beim Put (bPut = sal_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;
|
|
sal_Int32 nCode = 0;
|
|
if( rPar.Count() == 1 )
|
|
{
|
|
nErr = StarBASIC::GetErrBasic();
|
|
aErrorMsg = StarBASIC::GetErrorMsg();
|
|
}
|
|
else
|
|
{
|
|
nCode = rPar.Get( 1 )->GetLong();
|
|
if( nCode > 65535L )
|
|
StarBASIC::Error( SbERR_CONVERSION );
|
|
else
|
|
nErr = StarBASIC::GetSfxFromVBError( (sal_uInt16)nCode );
|
|
}
|
|
|
|
bool bVBA = SbiRuntime::isVBAEnabled();
|
|
String tmpErrMsg;
|
|
if( bVBA && aErrorMsg.Len() > 0 )
|
|
{
|
|
tmpErrMsg = aErrorMsg;
|
|
}
|
|
else
|
|
{
|
|
pBasic->MakeErrorText( nErr, aErrorMsg );
|
|
tmpErrMsg = pBasic->GetErrorText();
|
|
}
|
|
// If this rtlfunc 'Error' passed a errcode the same as the active Err Objects's
|
|
// current err then return the description for the error message if it is set
|
|
// ( complicated isn't it ? )
|
|
if ( bVBA && rPar.Count() > 1 )
|
|
{
|
|
com::sun::star::uno::Reference< ooo::vba::XErrObject > xErrObj( SbxErrObject::getUnoErrObject() );
|
|
if ( xErrObj.is() && xErrObj->getNumber() == nCode && xErrObj->getDescription().getLength() )
|
|
tmpErrMsg = xErrObj->getDescription();
|
|
}
|
|
rPar.Get( 0 )->PutString( tmpErrMsg );
|
|
}
|
|
}
|
|
|
|
// Sinus
|
|
|
|
RTLFUNC(Sin)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
rPar.Get( 0 )->PutDouble( sin( pArg->GetDouble() ) );
|
|
}
|
|
}
|
|
|
|
// Cosinus
|
|
|
|
RTLFUNC(Cos)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
rPar.Get( 0 )->PutDouble( cos( pArg->GetDouble() ) );
|
|
}
|
|
}
|
|
|
|
// Atn
|
|
|
|
RTLFUNC(Atn)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
rPar.Get( 0 )->PutDouble( atan( pArg->GetDouble() ) );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
RTLFUNC(Abs)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
rPar.Get( 0 )->PutDouble( fabs( pArg->GetDouble() ) );
|
|
}
|
|
}
|
|
|
|
|
|
RTLFUNC(Asc)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
String aStr( pArg->GetString() );
|
|
if ( aStr.Len() == 0 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
rPar.Get(0)->PutEmpty();
|
|
}
|
|
else
|
|
{
|
|
sal_Unicode aCh = aStr.GetBuffer()[0];
|
|
rPar.Get(0)->PutLong( aCh );
|
|
}
|
|
}
|
|
}
|
|
|
|
void implChr( SbxArray& rPar, bool bChrW )
|
|
{
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
|
|
String aStr;
|
|
if( !bChrW && SbiRuntime::isVBAEnabled() )
|
|
{
|
|
sal_Char c = (sal_Char)pArg->GetByte();
|
|
ByteString s( c );
|
|
aStr = String( s, gsl_getSystemTextEncoding() );
|
|
}
|
|
else
|
|
{
|
|
sal_Unicode aCh = (sal_Unicode)pArg->GetUShort();
|
|
aStr = String( aCh );
|
|
}
|
|
rPar.Get(0)->PutString( aStr );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Chr)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
bool bChrW = false;
|
|
implChr( rPar, bChrW );
|
|
}
|
|
|
|
RTLFUNC(ChrW)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
bool bChrW = true;
|
|
implChr( rPar, bChrW );
|
|
}
|
|
|
|
|
|
#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.
|
|
|
|
#if defined (WNT)
|
|
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 ];
|
|
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( sal_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)
|
|
{
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if (rPar.Count() == 2)
|
|
{
|
|
// VBA: track current directory per document type (separately for Writer, Calc, Impress, etc.)
|
|
if( SbiRuntime::isVBAEnabled() )
|
|
::basic::vba::registerCurrentDirectory( getDocumentModel( pBasic ), rPar.Get(1)->GetString() );
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
RTLFUNC(ChDrive)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if (rPar.Count() != 2)
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
|
|
// Implementation of StepRENAME with UCB
|
|
void implStepRenameUCB( const String& aSource, const String& aDest )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
String aSourceFullPath = getFullPath( aSource );
|
|
if( !xSFI->exists( aSourceFullPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
return;
|
|
}
|
|
|
|
String aDestFullPath = getFullPath( aDest );
|
|
if( xSFI->exists( aDestFullPath ) )
|
|
StarBASIC::Error( SbERR_FILE_EXISTS );
|
|
else
|
|
xSFI->move( aSourceFullPath, aDestFullPath );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Implementation of StepRENAME with OSL
|
|
void implStepRenameOSL( const String& aSource, const String& aDest )
|
|
{
|
|
FileBase::RC nRet = File::move( getFullPathUNC( aSource ), getFullPathUNC( aDest ) );
|
|
if( nRet != FileBase::E_None )
|
|
{
|
|
StarBASIC::Error( SbERR_PATH_NOT_FOUND );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(FileCopy)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if (rPar.Count() == 3)
|
|
{
|
|
String aSource = rPar.Get(1)->GetString();
|
|
String aDest = rPar.Get(2)->GetString();
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( SbERR_PATH_NOT_FOUND );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FileBase::RC nRet = File::copy( getFullPathUNC( aSource ), getFullPathUNC( aDest ) );
|
|
if( nRet != FileBase::E_None )
|
|
{
|
|
StarBASIC::Error( SbERR_PATH_NOT_FOUND );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
RTLFUNC(Kill)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if (rPar.Count() == 2)
|
|
{
|
|
String aFileSpec = rPar.Get(1)->GetString();
|
|
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
String aFullPath = getFullPath( aFileSpec );
|
|
if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
xSFI->kill( aFullPath );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
File::remove( getFullPathUNC( aFileSpec ) );
|
|
}
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
RTLFUNC(MkDir)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if (rPar.Count() == 2)
|
|
{
|
|
String aPath = rPar.Get(1)->GetString();
|
|
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
if ( SbiRuntime::isVBAEnabled() )
|
|
{
|
|
// If aPath is the folder name, not a path, then create the folder under current directory.
|
|
INetURLObject aTryPathURL( aPath );
|
|
::rtl::OUString sPathURL = aTryPathURL.GetMainURL( INetURLObject::NO_DECODE );
|
|
if ( !sPathURL.getLength() )
|
|
{
|
|
File::getFileURLFromSystemPath( aPath, sPathURL );
|
|
}
|
|
INetURLObject aPathURL( sPathURL );
|
|
if ( !aPathURL.GetPath().getLength() )
|
|
{
|
|
::rtl::OUString sCurDirURL;
|
|
SbxArrayRef pPar = new SbxArray;
|
|
SbxVariableRef pVar = new SbxVariable();
|
|
pPar->Put( pVar, 0 );
|
|
SbRtl_CurDir( pBasic, *pPar, sal_False );
|
|
String aCurPath = pPar->Get(0)->GetString();
|
|
|
|
File::getFileURLFromSystemPath( aCurPath, sCurDirURL );
|
|
INetURLObject aDirURL( sCurDirURL );
|
|
aDirURL.Append( aPath );
|
|
::rtl::OUString aTmpPath = aDirURL.GetMainURL( INetURLObject::NO_DECODE );
|
|
if ( aTmpPath.getLength() > 0 )
|
|
{
|
|
aPath = aTmpPath;
|
|
}
|
|
}
|
|
}
|
|
|
|
xSFI->createFolder( getFullPath( aPath ) );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Directory::create( getFullPathUNC( aPath ) );
|
|
}
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
|
|
// 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( osl_FileStatus_Mask_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( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_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 );
|
|
}
|
|
|
|
|
|
RTLFUNC(RmDir)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if (rPar.Count() == 2)
|
|
{
|
|
String aPath = rPar.Get(1)->GetString();
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
if( !xSFI->isFolder( aPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_PATH_NOT_FOUND );
|
|
return;
|
|
}
|
|
SbiInstance* pInst = pINST;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
if( bCompatibility )
|
|
{
|
|
Sequence< ::rtl::OUString > aContent = xSFI->getFolderContents( aPath, true );
|
|
sal_Int32 nCount = aContent.getLength();
|
|
if( nCount > 0 )
|
|
{
|
|
StarBASIC::Error( SbERR_ACCESS_ERROR );
|
|
return;
|
|
}
|
|
}
|
|
|
|
xSFI->kill( getFullPath( aPath ) );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
implRemoveDirRecursive( getFullPathUNC( aPath ) );
|
|
}
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
RTLFUNC(SendKeys)
|
|
{
|
|
(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() );
|
|
sal_Int32 nLen = 0;
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
nLen = xSFI->getSize( getFullPath( aStr ) );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DirectoryItem aItem;
|
|
DirectoryItem::get( getFullPathUNC( aStr ), aItem );
|
|
FileStatus aFileStatus( osl_FileStatus_Mask_FileSize );
|
|
aItem.getFileStatus( aFileStatus );
|
|
nLen = (sal_Int32)aFileStatus.getFileSize();
|
|
}
|
|
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 ) );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(FuncCaller)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
if ( SbiRuntime::isVBAEnabled() && pINST && pINST->pRun )
|
|
{
|
|
if ( pINST->pRun->GetExternalCaller() )
|
|
*rPar.Get(0) = *pINST->pRun->GetExternalCaller();
|
|
else
|
|
{
|
|
SbxVariableRef pVar = new SbxVariable(SbxVARIANT);
|
|
*rPar.Get(0) = *pVar;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
|
|
}
|
|
|
|
}
|
|
// InStr( [start],string,string,[compare] )
|
|
|
|
RTLFUNC(InStr)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
sal_uIntPtr nArgCount = rPar.Count()-1;
|
|
if ( nArgCount < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
sal_uInt16 nStartPos = 1;
|
|
|
|
sal_uInt16 nFirstStringPos = 1;
|
|
if ( nArgCount >= 3 )
|
|
{
|
|
sal_Int32 lStartPos = rPar.Get(1)->GetLong();
|
|
if( lStartPos <= 0 || lStartPos > 0xffff )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
lStartPos = 1;
|
|
}
|
|
nStartPos = (sal_uInt16)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 ) : sal_False;
|
|
}
|
|
else
|
|
{
|
|
bTextMode = 1;;
|
|
}
|
|
if ( nArgCount == 4 )
|
|
bTextMode = rPar.Get(4)->GetInteger();
|
|
|
|
sal_uInt16 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;
|
|
|
|
sal_uIntPtr 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();
|
|
|
|
sal_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 ) : sal_False;
|
|
}
|
|
else
|
|
{
|
|
bTextMode = 1;;
|
|
}
|
|
if ( nArgCount == 4 )
|
|
bTextMode = rPar.Get(4)->GetInteger();
|
|
|
|
sal_uInt16 nStrLen = aStr1.Len();
|
|
sal_uInt16 nStartPos = lStartPos == -1 ? nStrLen : (sal_uInt16)lStartPos;
|
|
|
|
sal_uInt16 nPos = 0;
|
|
if( nStartPos <= nStrLen )
|
|
{
|
|
sal_uInt16 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 = (sal_uInt16)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 = (sal_uInt16)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() );
|
|
sal_Int32 lResultLen = rPar.Get(2)->GetLong();
|
|
if( lResultLen > 0xffff )
|
|
{
|
|
lResultLen = 0xffff;
|
|
}
|
|
else if( lResultLen < 0 )
|
|
{
|
|
lResultLen = 0;
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
aStr.Erase( (sal_uInt16)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;
|
|
|
|
sal_uIntPtr 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 = sal_True;
|
|
|
|
String aArgStr = rPar.Get(1)->GetString();
|
|
sal_uInt16 nStartPos = (sal_uInt16)(rPar.Get(2)->GetLong() );
|
|
if ( nStartPos == 0 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
nStartPos--;
|
|
sal_uInt16 nLen = 0xffff;
|
|
bool bWriteNoLenParam = false;
|
|
if ( nArgCount == 3 || bWrite )
|
|
{
|
|
sal_Int32 n = rPar.Get(3)->GetLong();
|
|
if( bWrite && n == -1 )
|
|
bWriteNoLenParam = true;
|
|
nLen = (sal_uInt16)n;
|
|
}
|
|
String aResultStr;
|
|
if ( bWrite )
|
|
{
|
|
SbiInstance* pInst = pINST;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
if( bCompatibility )
|
|
{
|
|
sal_uInt16 nArgLen = aArgStr.Len();
|
|
if( nStartPos + 1 > nArgLen )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
String aReplaceStr = rPar.Get(4)->GetString();
|
|
sal_uInt16 nReplaceStrLen = aReplaceStr.Len();
|
|
sal_uInt16 nReplaceLen;
|
|
if( bWriteNoLenParam )
|
|
{
|
|
nReplaceLen = nReplaceStrLen;
|
|
}
|
|
else
|
|
{
|
|
nReplaceLen = nLen;
|
|
if( nReplaceLen > nReplaceStrLen )
|
|
nReplaceLen = nReplaceStrLen;
|
|
}
|
|
|
|
sal_uInt16 nReplaceEndPos = nStartPos + nReplaceLen;
|
|
if( nReplaceEndPos > nArgLen )
|
|
nReplaceLen -= (nReplaceEndPos - nArgLen);
|
|
|
|
aResultStr = aArgStr;
|
|
sal_uInt16 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;
|
|
|
|
sal_uIntPtr 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();
|
|
|
|
sal_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;
|
|
}
|
|
}
|
|
|
|
sal_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 ) : sal_False;
|
|
}
|
|
else
|
|
{
|
|
bTextMode = 1;
|
|
}
|
|
if ( nArgCount == 6 )
|
|
bTextMode = rPar.Get(6)->GetInteger();
|
|
|
|
sal_uInt16 nExpStrLen = aExpStr.Len();
|
|
sal_uInt16 nFindStrLen = aFindStr.Len();
|
|
sal_uInt16 nReplaceStrLen = aReplaceStr.Len();
|
|
|
|
if( lStartPos <= nExpStrLen )
|
|
{
|
|
sal_uInt16 nPos = static_cast<sal_uInt16>( lStartPos - 1 );
|
|
sal_uInt16 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<sal_uInt16>(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();
|
|
sal_Int32 lResultLen = rPar.Get(2)->GetLong();
|
|
if( lResultLen > 0xffff )
|
|
{
|
|
lResultLen = 0xffff;
|
|
}
|
|
else if( lResultLen < 0 )
|
|
{
|
|
lResultLen = 0;
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
sal_uInt16 nResultLen = (sal_uInt16)lResultLen;
|
|
sal_uInt16 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();
|
|
sal_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( (sal_uInt16)(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( (sal_uInt16)(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] == '-' );
|
|
sal_uInt16 iZeroSearch = 0;
|
|
if( bNeg )
|
|
iZeroSearch++;
|
|
|
|
sal_uInt16 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;
|
|
sal_Int16 nTextCompare;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
if( bCompatibility )
|
|
{
|
|
SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
|
|
nTextCompare = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : sal_False;
|
|
}
|
|
else
|
|
{
|
|
nTextCompare = sal_True;
|
|
}
|
|
if ( rPar.Count() == 4 )
|
|
nTextCompare = rPar.Get(3)->GetInteger();
|
|
|
|
if( !bCompatibility )
|
|
nTextCompare = !nTextCompare;
|
|
|
|
StringCompare aResult;
|
|
sal_Int32 nRetValue = 0;
|
|
if( nTextCompare )
|
|
{
|
|
::utl::TransliterationWrapper* pTransliterationWrapper = GetSbData()->pTransliterationWrapper;
|
|
if( !pTransliterationWrapper )
|
|
{
|
|
com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
|
|
pTransliterationWrapper = GetSbData()->pTransliterationWrapper =
|
|
new ::utl::TransliterationWrapper( xSMgr,
|
|
::com::sun::star::i18n::TransliterationModules_IGNORE_CASE |
|
|
::com::sun::star::i18n::TransliterationModules_IGNORE_KANA |
|
|
::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH );
|
|
}
|
|
|
|
LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
|
|
pTransliterationWrapper->loadModuleIfNeeded( eLangType );
|
|
nRetValue = pTransliterationWrapper->compareString( rStr1, rStr2 );
|
|
}
|
|
else
|
|
{
|
|
aResult = rStr1.CompareTo( rStr2 );
|
|
if ( aResult == COMPARE_LESS )
|
|
nRetValue = -1;
|
|
else if ( aResult == COMPARE_GREATER )
|
|
nRetValue = 1;
|
|
}
|
|
|
|
rPar.Get(0)->PutInteger( sal::static_int_cast< sal_Int16 >( nRetValue ) );
|
|
}
|
|
|
|
RTLFUNC(String)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
String aStr;
|
|
sal_Unicode aFiller;
|
|
sal_Int32 lCount = rPar.Get(1)->GetLong();
|
|
if( lCount < 0 || lCount > 0xffff )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
sal_uInt16 nCount = (sal_uInt16)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() );
|
|
|
|
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() );
|
|
sal_Int16 nlResult = (sal_Int16)strtol( aByteStr.GetBuffer()+2, &pEndPtr, nRadix);
|
|
nResult = (double)nlResult;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// #57844 Lokalisierte Funktion benutzen
|
|
nResult = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
|
|
checkArithmeticOverflow( nResult );
|
|
}
|
|
|
|
rPar.Get(0)->PutDouble( nResult );
|
|
}
|
|
}
|
|
|
|
|
|
// Helper functions for date conversion
|
|
sal_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 += (sal_uIntPtr)aDate;
|
|
}
|
|
else
|
|
{
|
|
aDate = ceil( aDate );
|
|
aRefDate -= (sal_uIntPtr)(-1.0 * aDate);
|
|
}
|
|
|
|
sal_Int16 nRet = (sal_Int16)( aRefDate.GetDay() );
|
|
return nRet;
|
|
}
|
|
|
|
sal_Int16 implGetDateMonth( double aDate )
|
|
{
|
|
Date aRefDate( 1,1,1900 );
|
|
long nDays = (long)aDate;
|
|
nDays -= 2; // normieren: 1.1.1900 => 0.0
|
|
aRefDate += nDays;
|
|
sal_Int16 nRet = (sal_Int16)( aRefDate.GetMonth() );
|
|
return nRet;
|
|
}
|
|
|
|
sal_Int16 implGetDateYear( double aDate )
|
|
{
|
|
Date aRefDate( 1,1,1900 );
|
|
long nDays = (long) aDate;
|
|
nDays -= 2; // normieren: 1.1.1900 => 0.0
|
|
aRefDate += nDays;
|
|
sal_Int16 nRet = (sal_Int16)( aRefDate.GetYear() );
|
|
return nRet;
|
|
}
|
|
|
|
sal_Bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_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 sal_False;
|
|
}
|
|
if ( !SbiRuntime::isVBAEnabled() )
|
|
{
|
|
if ( (nMonth < 1 || nMonth > 12 )||
|
|
(nDay < 1 || nDay > 31 ) )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return sal_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
|
|
sal_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 sal_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();
|
|
sal_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( (sal_Int16)aYearStr.ToInt32(),
|
|
(sal_Int16)aMonthStr.ToInt32(), (sal_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;
|
|
}
|
|
sal_Int16 nYear = rPar.Get(1)->GetInteger();
|
|
sal_Int16 nMonth = rPar.Get(2)->GetInteger();
|
|
sal_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;
|
|
}
|
|
sal_Int16 nHour = rPar.Get(1)->GetInteger();
|
|
if ( nHour == 24 )
|
|
nHour = 0; // Wegen UNO DateTimes, die bis 24 Uhr gehen
|
|
sal_Int16 nMinute = rPar.Get(2)->GetInteger();
|
|
sal_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;
|
|
}
|
|
|
|
sal_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() );
|
|
sal_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 );
|
|
}
|
|
rPar.Get(0)->PutDate( fResult );
|
|
}
|
|
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;
|
|
sal_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 );
|
|
}
|
|
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();
|
|
|
|
sal_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
|
|
{
|
|
sal_Int16 nYear = implGetDateYear( rPar.Get(1)->GetDate() );
|
|
rPar.Get(0)->PutInteger( nYear );
|
|
}
|
|
}
|
|
|
|
sal_Int16 implGetHour( double dDate )
|
|
{
|
|
if( dDate < 0.0 )
|
|
dDate *= -1.0;
|
|
double nFrac = dDate - floor( dDate );
|
|
nFrac *= 86400.0;
|
|
sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
|
|
sal_Int16 nHour = (sal_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();
|
|
sal_Int16 nHour = implGetHour( nArg );
|
|
rPar.Get(0)->PutInteger( nHour );
|
|
}
|
|
}
|
|
|
|
sal_Int16 implGetMinute( double dDate )
|
|
{
|
|
if( dDate < 0.0 )
|
|
dDate *= -1.0;
|
|
double nFrac = dDate - floor( dDate );
|
|
nFrac *= 86400.0;
|
|
sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
|
|
sal_Int16 nTemp = (sal_Int16)(nSeconds % 3600);
|
|
sal_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();
|
|
sal_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
|
|
{
|
|
sal_Int16 nMonth = implGetDateMonth( rPar.Get(1)->GetDate() );
|
|
rPar.Get(0)->PutInteger( nMonth );
|
|
}
|
|
}
|
|
|
|
sal_Int16 implGetSecond( double dDate )
|
|
{
|
|
if( dDate < 0.0 )
|
|
dDate *= -1.0;
|
|
double nFrac = dDate - floor( dDate );
|
|
nFrac *= 86400.0;
|
|
sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
|
|
sal_Int16 nTemp = (sal_Int16)(nSeconds / 3600);
|
|
nSeconds -= nTemp * 3600;
|
|
nTemp = (sal_Int16)(nSeconds / 60);
|
|
nSeconds -= nTemp * 60;
|
|
|
|
sal_Int16 nRet = (sal_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();
|
|
sal_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) ? sal_True : sal_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;
|
|
sal_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 sal_False
|
|
SbxVariableRef xArg = rPar.Get( 1 );
|
|
SbxDataType eType = xArg->GetType();
|
|
sal_Bool bDate = sal_False;
|
|
|
|
if( eType == SbxDATE )
|
|
{
|
|
bDate = sal_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
|
|
{
|
|
SbxVariable* pVar = NULL;
|
|
if( SbiRuntime::isVBAEnabled() )
|
|
pVar = getDefaultProp( rPar.Get(1) );
|
|
if ( pVar )
|
|
{
|
|
pVar->Broadcast( SBX_HINT_DATAWANTED );
|
|
rPar.Get( 0 )->PutBool( pVar->IsEmpty() );
|
|
}
|
|
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
|
|
{
|
|
SbxVariable* pVar =rPar.Get( 1 );
|
|
SbUnoObject* pObj = PTR_CAST(SbUnoObject,pVar );
|
|
if ( !pObj )
|
|
{
|
|
if ( SbxBase* pBaseObj = pVar->GetObject() )
|
|
pObj = PTR_CAST(SbUnoObject, pBaseObj );
|
|
}
|
|
Reference< XErrorQuery > xError;
|
|
if ( pObj )
|
|
xError.set( pObj->getUnoAny(), UNO_QUERY );
|
|
if ( xError.is() )
|
|
rPar.Get( 0 )->PutBool( xError->hasError() );
|
|
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 );
|
|
sal_Bool bNull = rPar.Get(1)->IsNull();
|
|
if( !bNull && pArg->GetType() == SbxOBJECT )
|
|
{
|
|
SbxBase* pObj = pArg->GetObject();
|
|
if( !pObj )
|
|
bNull = sal_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() );
|
|
}
|
|
|
|
// 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 );
|
|
sal_Bool bRoot = sal_False;
|
|
|
|
// Check if it's a root directory
|
|
sal_Int32 nCount = aDirURLObj.getSegmentCount();
|
|
|
|
// No segment means Unix root directory "file:///"
|
|
if( nCount == 0 )
|
|
{
|
|
bRoot = sal_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, sal_True,
|
|
INetURLObject::DECODE_WITH_CHARSET );
|
|
if( aSeg1.getStr()[1] == (sal_Unicode)':' )
|
|
{
|
|
bRoot = sal_True;
|
|
}
|
|
}
|
|
// More than one segments can never be root
|
|
// so bRoot remains sal_False
|
|
|
|
return bRoot;
|
|
}
|
|
|
|
RTLFUNC(Dir)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
String aPath;
|
|
|
|
sal_uInt16 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;
|
|
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
if ( nParCount >= 2 )
|
|
{
|
|
String aFileParam = rPar.Get(1)->GetString();
|
|
|
|
String aFileURLStr = implSetupWildcard( aFileParam, pRTLData );
|
|
if( pRTLData->sFullNameToBeChecked.Len() > 0 )
|
|
{
|
|
sal_Bool bExists = sal_False;
|
|
try { bExists = xSFI->exists( aFileURLStr ); }
|
|
catch( Exception & ) {}
|
|
|
|
String aNameOnlyStr;
|
|
if( bExists )
|
|
{
|
|
INetURLObject aFileURL( aFileURLStr );
|
|
aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT,
|
|
true, INetURLObject::DECODE_WITH_CHARSET );
|
|
}
|
|
rPar.Get(0)->PutString( aNameOnlyStr );
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
String aDirURLStr;
|
|
sal_Bool bFolder = xSFI->isFolder( aFileURLStr );
|
|
|
|
if( bFolder )
|
|
{
|
|
aDirURLStr = aFileURLStr;
|
|
}
|
|
else
|
|
{
|
|
String aEmptyStr;
|
|
rPar.Get(0)->PutString( aEmptyStr );
|
|
}
|
|
|
|
sal_uInt16 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 )
|
|
{
|
|
sal_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 & )
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
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(RTL_CONSTASCII_USTRINGPARAM( "." ));
|
|
}
|
|
else if( pRTLData->nCurDirPos == -1 )
|
|
{
|
|
aPath = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ".." ));
|
|
}
|
|
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, sal_True,
|
|
INetURLObject::DECODE_WITH_CHARSET );
|
|
}
|
|
|
|
sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
|
|
if( !bMatch )
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
}
|
|
rPar.Get(0)->PutString( aPath );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// TODO: OSL
|
|
if ( nParCount >= 2 )
|
|
{
|
|
String aFileParam = rPar.Get(1)->GetString();
|
|
|
|
String aDirURL = implSetupWildcard( aFileParam, pRTLData );
|
|
|
|
sal_uInt16 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 )
|
|
{
|
|
sal_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(RTL_CONSTASCII_USTRINGPARAM( "." ));
|
|
}
|
|
else if( pRTLData->nCurDirPos == -1 )
|
|
{
|
|
aPath = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ".." ));
|
|
}
|
|
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( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_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 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
RTLFUNC(GetAttr)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() == 2 )
|
|
{
|
|
sal_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 = (sal_Int16) (nRealFlags);
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
|
|
rPar.Get(0)->PutInteger( nFlags );
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
String aPath = getFullPath( rPar.Get(1)->GetString() );
|
|
sal_Bool bExists = sal_False;
|
|
try { bExists = xSFI->exists( aPath ); }
|
|
catch( Exception & ) {}
|
|
if( !bExists )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
return;
|
|
}
|
|
|
|
sal_Bool bReadOnly = xSFI->isReadOnly( aPath );
|
|
sal_Bool bHidden = xSFI->isHidden( aPath );
|
|
sal_Bool bDirectory = xSFI->isFolder( aPath );
|
|
if( bReadOnly )
|
|
nFlags |= 0x0001; // ATTR_READONLY
|
|
if( bHidden )
|
|
nFlags |= 0x0002; // ATTR_HIDDEN
|
|
if( bDirectory )
|
|
nFlags |= 0x0010; // ATTR_DIRECTORY
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DirectoryItem aItem;
|
|
DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetString() ), aItem );
|
|
FileStatus aFileStatus( osl_FileStatus_Mask_Attributes | osl_FileStatus_Mask_Type );
|
|
aItem.getFileStatus( aFileStatus );
|
|
sal_uInt64 nAttributes = aFileStatus.getAttributes();
|
|
sal_Bool bReadOnly = (nAttributes & osl_File_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
|
|
{
|
|
String aPath = rPar.Get(1)->GetString();
|
|
Time aTime;
|
|
Date aDate;
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
com::sun::star::util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath );
|
|
aTime = Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds );
|
|
aDate = Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DirectoryItem aItem;
|
|
DirectoryItem::get( getFullPathUNC( aPath ), aItem );
|
|
FileStatus aFileStatus( osl_FileStatus_Mask_ModifyTime );
|
|
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 );
|
|
}
|
|
|
|
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;
|
|
|
|
// No changes for UCB
|
|
if ( rPar.Count() != 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
sal_Int16 nChannel = rPar.Get(1)->GetInteger();
|
|
SbiIoSystem* pIO = pINST->GetIoSystem();
|
|
SbiStream* pSbStrm = pIO->GetStream( nChannel );
|
|
if ( !pSbStrm )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_CHANNEL );
|
|
return;
|
|
}
|
|
sal_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;
|
|
|
|
// 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
|
|
{
|
|
sal_Int16 nChannel = rPar.Get(1)->GetInteger();
|
|
SbiIoSystem* pIO = pINST->GetIoSystem();
|
|
SbiStream* pSbStrm = pIO->GetStream( nChannel );
|
|
if ( !pSbStrm )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_CHANNEL );
|
|
return;
|
|
}
|
|
sal_Int16 nRet;
|
|
if ( rPar.Get(2)->GetInteger() == 1 )
|
|
nRet = (sal_Int16)(pSbStrm->GetMode());
|
|
else
|
|
nRet = 0; // System file handle not supported
|
|
|
|
rPar.Get(0)->PutInteger( nRet );
|
|
}
|
|
}
|
|
RTLFUNC(Loc)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
// No changes for UCB
|
|
if ( rPar.Count() != 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
sal_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();
|
|
sal_uIntPtr 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( (sal_Int32)nPos );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Lof)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
// No changes for UCB
|
|
if ( rPar.Count() != 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
sal_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();
|
|
sal_uIntPtr nOldPos = pSvStrm->Tell();
|
|
sal_uIntPtr nLen = pSvStrm->Seek( STREAM_SEEK_TO_END );
|
|
pSvStrm->Seek( nOldPos );
|
|
rPar.Get(0)->PutLong( (sal_Int32)nLen );
|
|
}
|
|
}
|
|
|
|
|
|
RTLFUNC(Seek)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
// No changes for UCB
|
|
int nArgs = (int)rPar.Count();
|
|
if ( nArgs < 2 || nArgs > 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
sal_Int16 nChannel = rPar.Get(1)->GetInteger();
|
|
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
|
|
{
|
|
sal_uIntPtr nPos = pStrm->Tell();
|
|
if( pSbStrm->IsRandom() )
|
|
nPos = nPos / pSbStrm->GetBlockLen();
|
|
nPos++; // Basic zaehlt ab 1
|
|
rPar.Get(0)->PutLong( (sal_Int32)nPos );
|
|
}
|
|
else // Seek-Statement
|
|
{
|
|
sal_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( (sal_uIntPtr)nPos );
|
|
pSbStrm->SetExpandOnWriteTo( nPos );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Format)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
sal_uInt16 nArgCount = (sal_uInt16)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 );
|
|
sal_Int16 nSeed;
|
|
if( rPar.Count() == 2 )
|
|
nSeed = (sal_Int16)rPar.Get(1)->GetInteger();
|
|
else
|
|
nSeed = (sal_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 + 1.0));
|
|
rPar.Get(0)->PutDouble( nRand );
|
|
}
|
|
}
|
|
|
|
|
|
// Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = sal_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;
|
|
}
|
|
|
|
sal_uIntPtr nArgCount = rPar.Count();
|
|
if ( nArgCount < 2 || nArgCount > 5 )
|
|
{
|
|
rPar.Get(0)->PutLong(0);
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
oslProcessOption nOptions = osl_Process_SEARCHPATH | osl_Process_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( " " );
|
|
}
|
|
sal_uInt16 nLen = aCmdLine.Len();
|
|
|
|
// #55735 Wenn Parameter dabei sind, muessen die abgetrennt werden
|
|
// #72471 Auch die einzelnen Parameter trennen
|
|
std::list<String> aTokenList;
|
|
String aToken;
|
|
sal_uInt16 i = 0;
|
|
sal_Unicode c;
|
|
while( i < nLen )
|
|
{
|
|
// Spaces weg
|
|
for ( ;; ++i )
|
|
{
|
|
c = aCmdLine.GetBuffer()[ i ];
|
|
if ( c != ' ' && c != '\t' )
|
|
break;
|
|
}
|
|
|
|
if( c == '\"' || c == '\'' )
|
|
{
|
|
sal_uInt16 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
|
|
{
|
|
sal_uInt16 iFoundSpacePos = aCmdLine.Search( ' ', i );
|
|
sal_uInt16 iFoundTabPos = aCmdLine.Search( '\t', i );
|
|
sal_uInt16 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
|
|
|
|
sal_Int16 nWinStyle = 0;
|
|
if( nArgCount >= 3 )
|
|
{
|
|
nWinStyle = rPar.Get(2)->GetInteger();
|
|
switch( nWinStyle )
|
|
{
|
|
case 2:
|
|
nOptions |= osl_Process_MINIMIZED;
|
|
break;
|
|
case 3:
|
|
nOptions |= osl_Process_MAXIMIZED;
|
|
break;
|
|
case 10:
|
|
nOptions |= osl_Process_FULLSCREEN;
|
|
break;
|
|
}
|
|
|
|
sal_Bool bSync = sal_False;
|
|
if( nArgCount >= 5 )
|
|
bSync = rPar.Get(4)->GetBool();
|
|
if( bSync )
|
|
nOptions |= osl_Process_WAIT;
|
|
}
|
|
|
|
// #72471 Parameter aufbereiten
|
|
std::list<String>::const_iterator iter = aTokenList.begin();
|
|
const String& rStr = *iter;
|
|
::rtl::OUString aOUStrProg( rStr.GetBuffer(), rStr.Len() );
|
|
::rtl::OUString aOUStrProgUNC = getFullPathUNC( aOUStrProg );
|
|
|
|
++iter;
|
|
|
|
sal_uInt16 nParamCount = sal::static_int_cast< sal_uInt16 >(
|
|
aTokenList.size() - 1 );
|
|
rtl_uString** pParamList = NULL;
|
|
if( nParamCount )
|
|
{
|
|
pParamList = new rtl_uString*[nParamCount];
|
|
for(int iList = 0; iter != aTokenList.end(); ++iList, ++iter)
|
|
{
|
|
const String& rParamStr = (*iter);
|
|
const ::rtl::OUString aTempStr( rParamStr.GetBuffer(), rParamStr.Len());
|
|
pParamList[iList] = NULL;
|
|
rtl_uString_assign(&(pParamList[iList]), aTempStr.pData);
|
|
}
|
|
}
|
|
|
|
oslProcess pApp;
|
|
sal_Bool bSucc = osl_executeProcess(
|
|
aOUStrProgUNC.pData,
|
|
pParamList,
|
|
nParamCount,
|
|
nOptions,
|
|
NULL,
|
|
NULL,
|
|
NULL, 0,
|
|
&pApp ) == osl_Process_E_None;
|
|
|
|
osl_freeProcessHandle( pApp );
|
|
|
|
for(int j = 0; i < nParamCount; i++)
|
|
{
|
|
rtl_uString_release(pParamList[j]);
|
|
pParamList[j] = NULL;
|
|
}
|
|
|
|
long nResult = 0;
|
|
// We should return the identifier of the executing process when is running VBA, because method Shell(...) returns it in Excel.
|
|
if ( bSucc && SbiRuntime::isVBAEnabled())
|
|
{
|
|
oslProcessInfo aInfo;
|
|
aInfo.Size = sizeof(oslProcessInfo);
|
|
osl_getProcessInfo( pApp, osl_Process_IDENTIFIER, &aInfo );
|
|
nResult = aInfo.Ident;
|
|
}
|
|
|
|
if( !bSucc )
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
else
|
|
rPar.Get(0)->PutLong( nResult );
|
|
}
|
|
}
|
|
|
|
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( (sal_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;
|
|
sal_uInt16 nTypeNameCount = sizeof( pTypeNames ) / sizeof( char* );
|
|
if ( nPos < 0 || nPos >= nTypeNameCount )
|
|
nPos = nTypeNameCount - 1;
|
|
String aRetStr = String::CreateFromAscii( pTypeNames[nPos] );
|
|
return aRetStr;
|
|
}
|
|
|
|
String getObjectTypeName( SbxVariable* pVar )
|
|
{
|
|
rtl::OUString sRet( RTL_CONSTASCII_USTRINGPARAM("Object") );
|
|
if ( pVar )
|
|
{
|
|
SbxBase* pObj = pVar->GetObject();
|
|
if( !pObj )
|
|
sRet = String( RTL_CONSTASCII_USTRINGPARAM("Nothing") );
|
|
else
|
|
{
|
|
SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pVar );
|
|
if ( !pUnoObj )
|
|
{
|
|
if ( SbxBase* pBaseObj = pVar->GetObject() )
|
|
pUnoObj = PTR_CAST(SbUnoObject, pBaseObj );
|
|
}
|
|
if ( pUnoObj )
|
|
{
|
|
Any aObj = pUnoObj->getUnoAny();
|
|
// For upstreaming unless we start to build oovbaapi by default
|
|
// we need to get detect the vba-ness of the object in some
|
|
// other way
|
|
// note: Automation objects do not support XServiceInfo
|
|
Reference< XServiceInfo > xServInfo( aObj, UNO_QUERY );
|
|
if ( xServInfo.is() )
|
|
{
|
|
// is this a VBA object ?
|
|
Reference< ooo::vba::XHelperInterface > xVBA( aObj, UNO_QUERY );
|
|
Sequence< rtl::OUString > sServices = xServInfo->getSupportedServiceNames();
|
|
if ( sServices.getLength() )
|
|
sRet = sServices[ 0 ];
|
|
}
|
|
else
|
|
{
|
|
Reference< com::sun::star::bridge::oleautomation::XAutomationObject > xAutoMation( aObj, UNO_QUERY );
|
|
if ( xAutoMation.is() )
|
|
{
|
|
Reference< XInvocation > xInv( aObj, UNO_QUERY );
|
|
if ( xInv.is() )
|
|
{
|
|
try
|
|
{
|
|
xInv->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("$GetTypeName") ) ) >>= sRet;
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sal_Int32 nDot = sRet.lastIndexOf( '.' );
|
|
if ( nDot != -1 && nDot < sRet.getLength() )
|
|
sRet = sRet.copy( nDot + 1 );
|
|
}
|
|
}
|
|
}
|
|
return sRet;
|
|
}
|
|
|
|
RTLFUNC(TypeName)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() != 2 )
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
else
|
|
{
|
|
SbxDataType eType = rPar.Get(1)->GetType();
|
|
sal_Bool bIsArray = ( ( eType & SbxARRAY ) != 0 );
|
|
|
|
String aRetStr;
|
|
if ( SbiRuntime::isVBAEnabled() && eType == SbxOBJECT )
|
|
aRetStr = getObjectTypeName( rPar.Get(1) );
|
|
else
|
|
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( (sal_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();
|
|
sal_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;
|
|
}
|
|
sal_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;
|
|
}
|
|
sal_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;
|
|
}
|
|
sal_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;
|
|
}
|
|
sal_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;
|
|
|
|
sal_uInt16 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 )
|
|
{
|
|
sal_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;
|
|
|
|
sal_uInt16 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 )
|
|
{
|
|
sal_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;
|
|
}
|
|
|
|
sal_uIntPtr nRed = rPar.Get(1)->GetInteger() & 0xFF;
|
|
sal_uIntPtr nGreen = rPar.Get(2)->GetInteger() & 0xFF;
|
|
sal_uIntPtr nBlue = rPar.Get(3)->GetInteger() & 0xFF;
|
|
sal_uIntPtr 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 sal_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;
|
|
}
|
|
|
|
sal_Int16 nCol = rPar.Get(1)->GetInteger();
|
|
if( nCol < 0 || nCol > 15 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
sal_Int32 nRGB = pRGB[ nCol ];
|
|
rPar.Get(0)->PutLong( nRGB );
|
|
}
|
|
|
|
// StrConv(string, conversion, LCID)
|
|
RTLFUNC(StrConv)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
sal_uIntPtr nArgCount = rPar.Count()-1;
|
|
if( nArgCount < 2 || nArgCount > 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
String aOldStr = rPar.Get(1)->GetString();
|
|
sal_Int32 nConversion = rPar.Get(2)->GetLong();
|
|
|
|
sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
|
|
|
|
sal_uInt16 nOldLen = aOldStr.Len();
|
|
if( nOldLen == 0 )
|
|
{
|
|
// null string,return
|
|
rPar.Get(0)->PutString(aOldStr);
|
|
return;
|
|
}
|
|
|
|
sal_Int32 nType = 0;
|
|
if ( (nConversion & 0x03) == 3 ) // vbProperCase
|
|
{
|
|
CharClass& rCharClass = GetCharClass();
|
|
aOldStr = rCharClass.toTitle( aOldStr.ToLowerAscii(), 0, nOldLen );
|
|
}
|
|
else if ( (nConversion & 0x01) == 1 ) // vbUpperCase
|
|
nType |= ::com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE;
|
|
else if ( (nConversion & 0x02) == 2 ) // vbLowerCase
|
|
nType |= ::com::sun::star::i18n::TransliterationModules_UPPERCASE_LOWERCASE;
|
|
|
|
if ( (nConversion & 0x04) == 4 ) // vbWide
|
|
nType |= ::com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
|
|
else if ( (nConversion & 0x08) == 8 ) // vbNarrow
|
|
nType |= ::com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
|
|
|
|
if ( (nConversion & 0x10) == 16) // vbKatakana
|
|
nType |= ::com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
|
|
else if ( (nConversion & 0x20) == 32 ) // vbHiragana
|
|
nType |= ::com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA;
|
|
|
|
String aNewStr( aOldStr );
|
|
if( nType != 0 )
|
|
{
|
|
com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
|
|
::utl::TransliterationWrapper aTransliterationWrapper( xSMgr,nType );
|
|
com::sun::star::uno::Sequence<sal_Int32> aOffsets;
|
|
aTransliterationWrapper.loadModuleIfNeeded( nLanguage );
|
|
aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
|
|
}
|
|
|
|
if ( (nConversion & 0x40) == 64 ) // vbUnicode
|
|
{
|
|
// convert the string to byte string, preserving unicode (2 bytes per character)
|
|
sal_uInt16 nSize = aNewStr.Len()*2;
|
|
const sal_Unicode* pSrc = aNewStr.GetBuffer();
|
|
sal_Char* pChar = new sal_Char[nSize+1];
|
|
for( sal_uInt16 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);
|
|
delete[] 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();
|
|
sal_uInt16 nArraySize = static_cast< sal_uInt16 >( 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( sal_uInt16 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);
|
|
sal_uInt16 nFlags = refVar->GetFlags();
|
|
refVar->ResetFlag( SBX_FIXED );
|
|
refVar->PutObject( pArray );
|
|
refVar->SetFlags( nFlags );
|
|
refVar->SetParameters( NULL );
|
|
return;
|
|
}
|
|
|
|
rPar.Get(0)->PutString(aNewStr);
|
|
}
|
|
|
|
|
|
RTLFUNC(Beep)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() != 1 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
Sound::Beep();
|
|
}
|
|
|
|
RTLFUNC(Load)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if( rPar.Count() != 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
// Diesen Call einfach an das Object weiterreichen
|
|
SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
|
|
if ( pObj )
|
|
{
|
|
if( pObj->IsA( TYPE( SbUserFormModule ) ) )
|
|
{
|
|
((SbUserFormModule*)pObj)->Load();
|
|
}
|
|
else if( pObj->IsA( TYPE( SbxObject ) ) )
|
|
{
|
|
SbxVariable* pVar = ((SbxObject*)pObj)->
|
|
Find( String( RTL_CONSTASCII_USTRINGPARAM("Load") ), SbxCLASS_METHOD );
|
|
if( pVar )
|
|
pVar->GetInteger();
|
|
}
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Unload)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if( rPar.Count() != 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
// Diesen Call einfach an das Object weitereichen
|
|
SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
|
|
if ( pObj )
|
|
{
|
|
if( pObj->IsA( TYPE( SbUserFormModule ) ) )
|
|
{
|
|
SbUserFormModule* pFormModule = ( SbUserFormModule* )pObj;
|
|
pFormModule->Unload();
|
|
}
|
|
else if( pObj->IsA( TYPE( SbxObject ) ) )
|
|
{
|
|
SbxVariable* pVar = ((SbxObject*)pObj)->
|
|
Find( String( RTL_CONSTASCII_USTRINGPARAM("Unload") ), SbxCLASS_METHOD );
|
|
if( pVar )
|
|
pVar->GetInteger();
|
|
}
|
|
}
|
|
}
|
|
|
|
RTLFUNC(LoadPicture)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if( rPar.Count() != 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
String aFileURL = getFullPath( rPar.Get(1)->GetString() );
|
|
SvStream* pStream = utl::UcbStreamHelper::CreateStream( aFileURL, STREAM_READ );
|
|
if( pStream != NULL )
|
|
{
|
|
Bitmap aBmp;
|
|
*pStream >> aBmp;
|
|
Graphic aGraphic( aBmp );
|
|
|
|
SbxObjectRef xRef = new SbStdPicture;
|
|
((SbStdPicture*)(SbxObject*)xRef)->SetGraphic( aGraphic );
|
|
rPar.Get(0)->PutObject( xRef );
|
|
}
|
|
delete pStream;
|
|
}
|
|
|
|
RTLFUNC(SavePicture)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if( rPar.Count() != 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
|
|
if( pObj->IsA( TYPE( SbStdPicture ) ) )
|
|
{
|
|
SvFileStream aOStream( rPar.Get(2)->GetString(), STREAM_WRITE | STREAM_TRUNC );
|
|
Graphic aGraphic = ((SbStdPicture*)pObj)->GetGraphic();
|
|
aOStream << aGraphic;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------------------
|
|
|
|
RTLFUNC(AboutStarBasic)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
(void)rPar;
|
|
}
|
|
|
|
RTLFUNC(MsgBox)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
static const WinBits nStyleMap[] =
|
|
{
|
|
WB_OK, // MB_OK
|
|
WB_OK_CANCEL, // MB_OKCANCEL
|
|
WB_ABORT_RETRY_IGNORE, // MB_ABORTRETRYIGNORE
|
|
WB_YES_NO_CANCEL, // MB_YESNOCANCEL
|
|
WB_YES_NO, // MB_YESNO
|
|
WB_RETRY_CANCEL // MB_RETRYCANCEL
|
|
};
|
|
static const sal_Int16 nButtonMap[] =
|
|
{
|
|
2, // #define RET_CANCEL sal_False
|
|
1, // #define RET_OK sal_True
|
|
6, // #define RET_YES 2
|
|
7, // #define RET_NO 3
|
|
4 // #define RET_RETRY 4
|
|
};
|
|
|
|
|
|
sal_uInt16 nArgCount = (sal_uInt16)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 );
|
|
sal_uInt16 nRet = (sal_uInt16)pBox->Execute();
|
|
if( nRet == sal_True )
|
|
nRet = 1;
|
|
|
|
sal_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)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
rPar.Get(0)->PutEmpty();
|
|
if ( rPar.Count() == 3 )
|
|
{
|
|
String aStr = rPar.Get(1)->GetString();
|
|
sal_Int16 nFlags = rPar.Get(2)->GetInteger();
|
|
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
sal_Bool bReadOnly = (nFlags & 0x0001) != 0; // ATTR_READONLY
|
|
xSFI->setReadOnly( aStr, bReadOnly );
|
|
sal_Bool bHidden = (nFlags & 0x0002) != 0; // ATTR_HIDDEN
|
|
xSFI->setHidden( aStr, bHidden );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
|
|
RTLFUNC(Reset)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
(void)rPar;
|
|
|
|
SbiIoSystem* pIO = pINST->GetIoSystem();
|
|
if (pIO)
|
|
pIO->CloseAll();
|
|
}
|
|
|
|
RTLFUNC(DumpAllObjects)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
sal_uInt16 nArgCount = (sal_uInt16)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();
|
|
sal_Bool bExists = sal_False;
|
|
|
|
if( hasUno() )
|
|
{
|
|
com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
bExists = xSFI->exists( aStr );
|
|
}
|
|
catch( Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DirectoryItem aItem;
|
|
FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem );
|
|
bExists = (nRet == FileBase::E_None);
|
|
}
|
|
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;
|
|
}
|
|
|
|
sal_Int32 nNumber = rPar.Get(1)->GetLong();
|
|
sal_Int32 nStart = rPar.Get(2)->GetLong();
|
|
sal_Int32 nStop = rPar.Get(3)->GetLong();
|
|
sal_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 );
|
|
sal_Int32 nLen1 = aBeforeStart.getLength();
|
|
sal_Int32 nLen2 = aAfterStop.getLength();
|
|
sal_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
|
|
{
|
|
sal_Int32 nLowerValue = nNumber;
|
|
sal_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 ( sal_Int32 i= (nLen - nLen1) ; i > 0; --i )
|
|
aRetStr.appendAscii(" ");
|
|
}
|
|
aRetStr.append( aLowerValue ).appendAscii(":");
|
|
if( nLen > nLen2 )
|
|
{
|
|
// appending the leading spaces for the uppervalue
|
|
for ( sal_Int32 i= (nLen - nLen2) ; i > 0; --i )
|
|
aRetStr.appendAscii(" ");
|
|
}
|
|
aRetStr.append( aUpperValue );
|
|
rPar.Get(0)->PutString( String(aRetStr.makeStringAndClear()) );
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|