/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_basic.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "runtime.hxx" #include "sbunoobj.hxx" #ifdef WNT #include #include "winbase.h" #include #ifndef _FSYS_HXX //autogen #include #endif #else #include #endif #include "errobject.hxx" #ifdef _USE_UNO #include #include #include #include #include #include #include #include #include #include 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::frame; #endif /* _USE_UNO */ //#define _ENABLE_CUR_DIR #include "stdobj.hxx" #include #include "rtlproto.hxx" #include "basrid.hxx" #include "image.hxx" #include "sb.hrc" #include "iosys.hxx" #include "ddectrl.hxx" #include #include #include #include #include #include #include #if defined (WNT) || defined (OS2) #include // _getdcwd get current work directory, _chdrive #endif #ifdef UNX #include #include #endif #ifdef WNT #include #endif #include // 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.isEmpty() ) { File::getFileURLFromSystemPath( aRelPath, aFileURL ); } return aFileURL; } // Sets (virtual) current path for UCB file access void implChDir( const String& aDir ) { (void)aDir; // TODO } // Sets (virtual) current drive for UCB file access void implChDrive( const String& aDrive ) { (void)aDrive; // TODO } // Returns (virtual) current path for UCB file access String implGetCurDir( void ) { String aRetStr; return aRetStr; } // TODO: -> SbiGlobals static com::sun::star::uno::Reference< XSimpleFileAccess3 > getFileAccess( void ) { static com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI; if( !xSFI.is() ) { com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); if( xSMgr.is() ) { xSFI = com::sun::star::uno::Reference< XSimpleFileAccess3 >( xSMgr->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); } } return xSFI; } // Properties und Methoden legen beim Get (bPut = 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().isEmpty() ) 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. // rPar.Get(0)->PutEmpty(); #if defined (WNT) || defined (OS2) int nCurDir = 0; // Current dir // JSM if ( rPar.Count() == 2 ) { String aDrive = rPar.Get(1)->GetString(); if ( aDrive.Len() != 1 ) { StarBASIC::Error( SbERR_BAD_ARGUMENT ); return; } else { nCurDir = (int)aDrive.GetBuffer()[0]; if ( !isalpha( nCurDir ) ) { StarBASIC::Error( SbERR_BAD_ARGUMENT ); return; } else nCurDir -= ( 'A' - 1 ); } } char* pBuffer = new char[ _MAX_PATH ]; #ifdef OS2 if( !nCurDir ) nCurDir = _getdrive(); #endif if ( _getdcwd( nCurDir, pBuffer, _MAX_PATH ) != 0 ) rPar.Get(0)->PutString( String::CreateFromAscii( pBuffer ) ); else StarBASIC::Error( SbERR_NO_DEVICE ); delete [] pBuffer; #elif defined( UNX ) int nSize = _PATH_INCR; char* pMem; while( 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) // JSM { (void)bWrite; rPar.Get(0)->PutEmpty(); if (rPar.Count() == 2) { #ifdef _ENABLE_CUR_DIR String aPath = rPar.Get(1)->GetString(); sal_Bool bError = sal_False; #ifdef WNT // #55997 Laut MI hilft es bei File-URLs einen DirEntry zwischenzuschalten // #40996 Harmoniert bei Verwendung der WIN32-Funktion nicht mit getdir DirEntry aEntry( aPath ); ByteString aFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() ); if( chdir( aFullPath.GetBuffer()) ) bError = sal_True; #else if (!DirEntry(aPath).SetCWD()) bError = sal_True; #endif if( bError ) StarBASIC::Error( SbERR_PATH_NOT_FOUND ); #endif // 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) // JSM { (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); if (rPar.Count() == 2) { #ifdef _ENABLE_CUR_DIR // Keine Laufwerke in Unix #ifndef UNX String aPar1 = rPar.Get(1)->GetString(); #if defined (WNT) || defined (OS2) if (aPar1.Len() > 0) { int nCurDrive = (int)aPar1.GetBuffer()[0]; ; if ( !isalpha( nCurDrive ) ) { StarBASIC::Error( SbERR_BAD_ARGUMENT ); return; } else nCurDrive -= ( 'A' - 1 ); if (_chdrive(nCurDrive)) StarBASIC::Error( SbERR_NO_DEVICE ); } #endif #endif // #ifndef UNX #endif } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } // Implementation of StepRENAME with UCB void implStepRenameUCB( const String& aSource, const String& aDest ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { String aSourceFullPath = getFullPath( aSource ); if( !xSFI->exists( aSourceFullPath ) ) { StarBASIC::Error( SbERR_FILE_NOT_FOUND ); return; } String aDestFullPath = getFullPath( aDest ); if( xSFI->exists( aDestFullPath ) ) StarBASIC::Error( SbERR_FILE_EXISTS ); else xSFI->move( aSourceFullPath, aDestFullPath ); } catch( Exception & ) { StarBASIC::Error( SbERR_FILE_NOT_FOUND ); } } } // Implementation of StepRENAME with OSL void implStepRenameOSL( const String& aSource, const String& aDest ) { FileBase::RC nRet = File::move( getFullPathUNC( aSource ), getFullPathUNC( aDest ) ); if( nRet != FileBase::E_None ) { StarBASIC::Error( SbERR_PATH_NOT_FOUND ); } } RTLFUNC(FileCopy) // JSM { (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); if (rPar.Count() == 3) { String aSource = rPar.Get(1)->GetString(); String aDest = rPar.Get(2)->GetString(); // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) ); } catch( Exception & ) { StarBASIC::Error( SbERR_PATH_NOT_FOUND ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL DirEntry aSourceDirEntry(aSource); if (aSourceDirEntry.Exists()) { if (aSourceDirEntry.CopyTo(DirEntry(aDest),FSYS_ACTION_COPYFILE) != FSYS_ERR_OK) StarBASIC::Error( SbERR_PATH_NOT_FOUND ); } else StarBASIC::Error( SbERR_PATH_NOT_FOUND ); #else FileBase::RC nRet = File::copy( getFullPathUNC( aSource ), getFullPathUNC( aDest ) ); if( nRet != FileBase::E_None ) { StarBASIC::Error( SbERR_PATH_NOT_FOUND ); } #endif } } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } RTLFUNC(Kill) // JSM { (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); if (rPar.Count() == 2) { String aFileSpec = rPar.Get(1)->GetString(); // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { String aFullPath = getFullPath( aFileSpec ); if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) ) { StarBASIC::Error( SbERR_FILE_NOT_FOUND ); return; } try { xSFI->kill( aFullPath ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL if(DirEntry(aFileSpec).Kill() != FSYS_ERR_OK) StarBASIC::Error( SbERR_PATH_NOT_FOUND ); #else File::remove( getFullPathUNC( aFileSpec ) ); #endif } } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } RTLFUNC(MkDir) // JSM { (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); if (rPar.Count() == 2) { String aPath = rPar.Get(1)->GetString(); // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { xSFI->createFolder( getFullPath( aPath ) ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL if (!DirEntry(aPath).MakeDir()) StarBASIC::Error( SbERR_PATH_NOT_FOUND ); #else Directory::create( getFullPathUNC( aPath ) ); #endif } } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } #ifndef _OLD_FILE_IMPL // In OSL only empty directories can be deleted // so we have to delete all files recursively void implRemoveDirRecursive( const String& aDirPath ) { DirectoryItem aItem; FileBase::RC nRet = DirectoryItem::get( aDirPath, aItem ); sal_Bool bExists = (nRet == FileBase::E_None); FileStatus aFileStatus( FileStatusMask_Type ); nRet = aItem.getFileStatus( aFileStatus ); FileStatus::Type aType = aFileStatus.getFileType(); sal_Bool bFolder = isFolder( aType ); if( !bExists || !bFolder ) { StarBASIC::Error( SbERR_PATH_NOT_FOUND ); return; } Directory aDir( aDirPath ); nRet = aDir.open(); if( nRet != FileBase::E_None ) { StarBASIC::Error( SbERR_PATH_NOT_FOUND ); return; } for( ;; ) { DirectoryItem aItem2; nRet = aDir.getNextItem( aItem2 ); if( nRet != FileBase::E_None ) break; // Handle flags FileStatus aFileStatus2( FileStatusMask_Type | FileStatusMask_FileURL ); nRet = aItem2.getFileStatus( aFileStatus2 ); ::rtl::OUString aPath = aFileStatus2.getFileURL(); // Directory? FileStatus::Type aType2 = aFileStatus2.getFileType(); sal_Bool bFolder2 = isFolder( aType2 ); if( bFolder2 ) { implRemoveDirRecursive( aPath ); } else { File::remove( aPath ); } } nRet = aDir.close(); nRet = Directory::remove( aDirPath ); } #endif RTLFUNC(RmDir) // JSM { (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); if (rPar.Count() == 2) { String aPath = rPar.Get(1)->GetString(); // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { if( !xSFI->isFolder( aPath ) ) { StarBASIC::Error( SbERR_PATH_NOT_FOUND ); return; } SbiInstance* pInst = pINST; bool bCompatibility = ( pInst && pInst->IsCompatibility() ); if( bCompatibility ) { Sequence< ::rtl::OUString > aContent = xSFI->getFolderContents( aPath, true ); sal_Int32 nCount = aContent.getLength(); if( nCount > 0 ) { StarBASIC::Error( SbERR_ACCESS_ERROR ); return; } } xSFI->kill( getFullPath( aPath ) ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL DirEntry aDirEntry(aPath); if (aDirEntry.Kill() != FSYS_ERR_OK) StarBASIC::Error( SbERR_PATH_NOT_FOUND ); #else implRemoveDirRecursive( getFullPathUNC( aPath ) ); #endif } } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } RTLFUNC(SendKeys) // JSM { (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); StarBASIC::Error(SbERR_NOT_IMPLEMENTED); } RTLFUNC(Exp) { (void)pBasic; (void)bWrite; if( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { double aDouble = rPar.Get( 1 )->GetDouble(); aDouble = exp( aDouble ); checkArithmeticOverflow( aDouble ); rPar.Get( 0 )->PutDouble( aDouble ); } } RTLFUNC(FileLen) { (void)pBasic; (void)bWrite; if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { SbxVariableRef pArg = rPar.Get( 1 ); String aStr( pArg->GetString() ); sal_Int32 nLen = 0; // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { nLen = xSFI->getSize( getFullPath( aStr ) ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL FileStat aStat = DirEntry( aStr ); nLen = aStat.GetSize(); #else DirectoryItem aItem; FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem ); FileStatus aFileStatus( FileStatusMask_FileSize ); nRet = aItem.getFileStatus( aFileStatus ); nLen = (sal_Int32)aFileStatus.getFileSize(); #endif } rPar.Get(0)->PutLong( (long)nLen ); } } RTLFUNC(Hex) { (void)pBasic; (void)bWrite; if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { char aBuffer[16]; SbxVariableRef pArg = rPar.Get( 1 ); if ( pArg->IsInteger() ) snprintf( aBuffer, sizeof(aBuffer), "%X", pArg->GetInteger() ); else snprintf( aBuffer, sizeof(aBuffer), "%lX", static_cast(pArg->GetLong()) ); rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) ); } } // 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(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( 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 + nReplaceStrLen; nCounts++; } else { break; } } } rPar.Get(0)->PutString( aExpStr.Copy() ); } } 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() ); // lt. Mikkysoft bei Kommas abbrechen! // for( sal_uInt16 n=0; n < aStr.Len(); n++ ) // if( aStr[n] == ',' ) aStr[n] = '.'; FilterWhiteSpace( aStr ); if ( aStr.GetBuffer()[0] == '&' && aStr.Len() > 1 ) { int nRadix = 10; char aChar = (char)aStr.GetBuffer()[1]; if ( aChar == 'h' || aChar == 'H' ) nRadix = 16; else if ( aChar == 'o' || aChar == 'O' ) nRadix = 8; if ( nRadix != 10 ) { ByteString aByteStr( aStr, gsl_getSystemTextEncoding() ); 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 ); // ATL: nResult = strtod( aStr.GetStr(), &pEndPtr ); } 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 ); } // fResult += 2.0; // Anpassung StarCalcFormatter rPar.Get(0)->PutDate( fResult ); // JSM } else StarBASIC::Error( SbERR_CONVERSION ); // #39629 pFormatter kann selbst angefordert sein if( !pINST ) delete pFormatter; } } RTLFUNC(TimeValue) { (void)pBasic; (void)bWrite; if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden SvNumberFormatter* pFormatter = NULL; if( pINST ) pFormatter = pINST->GetNumberFormatter(); else { sal_uInt32 n; // Dummy SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n ); } sal_uInt32 nIndex; double fResult; 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 ); // JSM } else StarBASIC::Error( SbERR_CONVERSION ); // #39629 pFormatter kann selbst angefordert sein if( !pINST ) delete pFormatter; } } RTLFUNC(Day) { (void)pBasic; (void)bWrite; if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { SbxVariableRef pArg = rPar.Get( 1 ); double aDate = pArg->GetDate(); 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 rPar.Get( 0 )->PutBool( rPar.Get(1)->IsEmpty() ); } RTLFUNC(IsError) { (void)pBasic; (void)bWrite; if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() ); } RTLFUNC(IsNull) { (void)pBasic; (void)bWrite; if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { // #51475 Wegen Uno-Objekten auch true liefern, // wenn der pObj-Wert NULL ist SbxVariableRef pArg = rPar.Get( 1 ); 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() ); } // Dir( [Maske] [,Attrs] ) // ToDo: Library-globaler Datenbereich fuer Dir-Objekt und Flags String getDirectoryPath( String aPathStr ) { String aRetStr; DirectoryItem aItem; FileBase::RC nRet = DirectoryItem::get( aPathStr, aItem ); if( nRet == FileBase::E_None ) { FileStatus aFileStatus( FileStatusMask_Type ); nRet = aItem.getFileStatus( aFileStatus ); if( nRet == FileBase::E_None ) { FileStatus::Type aType = aFileStatus.getFileType(); if( isFolder( aType ) ) { aRetStr = aPathStr; } else if( aType == FileStatus::Link ) { FileStatus aFileStatus2( FileStatusMask_LinkTargetURL ); nRet = aItem.getFileStatus( aFileStatus2 ); if( nRet == FileBase::E_None ) aRetStr = getDirectoryPath( aFileStatus2.getLinkTargetURL() ); } } } return aRetStr; } // Function looks for wildcards, removes them and always returns the pure path String implSetupWildcard( const String& rFileParam, SbiRTLData* pRTLData ) { static String aAsterisk = String::CreateFromAscii( "*" ); static sal_Char cDelim1 = (sal_Char)'/'; static sal_Char cDelim2 = (sal_Char)'\\'; static sal_Char cWild1 = '*'; static sal_Char cWild2 = '?'; delete pRTLData->pWildCard; pRTLData->pWildCard = NULL; pRTLData->sFullNameToBeChecked = String(); String aFileParam = rFileParam; xub_StrLen nLastWild = aFileParam.SearchBackward( cWild1 ); if( nLastWild == STRING_NOTFOUND ) nLastWild = aFileParam.SearchBackward( cWild2 ); sal_Bool bHasWildcards = ( nLastWild != STRING_NOTFOUND ); xub_StrLen nLastDelim = aFileParam.SearchBackward( cDelim1 ); if( nLastDelim == STRING_NOTFOUND ) nLastDelim = aFileParam.SearchBackward( cDelim2 ); if( bHasWildcards ) { // Wildcards in path? if( nLastDelim != STRING_NOTFOUND && nLastDelim > nLastWild ) return aFileParam; } else { String aPathStr = getFullPath( aFileParam ); if( nLastDelim != aFileParam.Len() - 1 ) pRTLData->sFullNameToBeChecked = aPathStr; return aPathStr; } String aPureFileName; if( nLastDelim == STRING_NOTFOUND ) { aPureFileName = aFileParam; aFileParam = String(); } else { aPureFileName = aFileParam.Copy( nLastDelim + 1 ); aFileParam = aFileParam.Copy( 0, nLastDelim ); } // Try again to get a valid URL/UNC-path with only the path String aPathStr = getFullPath( aFileParam ); xub_StrLen nPureLen = aPureFileName.Len(); // Is there a pure file name left? Otherwise the path is // invalid anyway because it was not accepted by OSL before if( nPureLen && aPureFileName != aAsterisk ) { pRTLData->pWildCard = new WildCard( aPureFileName ); } return aPathStr; } inline sal_Bool implCheckWildcard( const String& rName, SbiRTLData* pRTLData ) { sal_Bool bMatch = sal_True; if( pRTLData->pWildCard ) bMatch = pRTLData->pWildCard->Matches( rName ); return bMatch; } bool isRootDir( String aDirURLStr ) { INetURLObject aDirURLObj( aDirURLStr ); 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; // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { if ( nParCount >= 2 ) { String aFileParam = rPar.Get(1)->GetString(); String aFileURLStr = implSetupWildcard( aFileParam, pRTLData ); if( pRTLData->sFullNameToBeChecked.Len() > 0 ) { sal_Bool bExists = sal_False; try { bExists = xSFI->exists( aFileURLStr ); } catch( Exception & ) {} String aNameOnlyStr; if( bExists ) { INetURLObject aFileURL( aFileURLStr ); aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); } rPar.Get(0)->PutString( aNameOnlyStr ); return; } try { String aDirURLStr; sal_Bool bFolder = xSFI->isFolder( aFileURLStr ); if( bFolder ) { aDirURLStr = aFileURLStr; } else { String aEmptyStr; rPar.Get(0)->PutString( aEmptyStr ); } 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 & ) { //StarBASIC::Error( ERRCODE_IO_GENERAL ); } } if( pRTLData->aDirSeq.getLength() > 0 ) { sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0); SbiInstance* pInst = pINST; bool bCompatibility = ( pInst && pInst->IsCompatibility() ); for( ;; ) { if( pRTLData->nCurDirPos < 0 ) { if( pRTLData->nCurDirPos == -2 ) { aPath = ::rtl::OUString::createFromAscii( "." ); } else if( pRTLData->nCurDirPos == -1 ) { aPath = ::rtl::OUString::createFromAscii( ".." ); } pRTLData->nCurDirPos++; } else if( pRTLData->nCurDirPos >= pRTLData->aDirSeq.getLength() ) { pRTLData->aDirSeq.realloc( 0 ); aPath.Erase(); break; } else { ::rtl::OUString aFile = pRTLData->aDirSeq.getConstArray()[pRTLData->nCurDirPos++]; if( bCompatibility ) { if( !bFolderFlag ) { sal_Bool bFolder = xSFI->isFolder( aFile ); if( bFolder ) continue; } } else { // Only directories if( bFolderFlag ) { sal_Bool bFolder = xSFI->isFolder( aFile ); if( !bFolder ) continue; } } INetURLObject aURL( aFile ); aPath = aURL.getName( INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET ); } sal_Bool bMatch = implCheckWildcard( aPath, pRTLData ); if( !bMatch ) continue; break; } } rPar.Get(0)->PutString( aPath ); } } else // --> UCB { #ifdef _OLD_FILE_IMPL if ( nParCount >= 2 ) { delete pRTLData->pDir; pRTLData->pDir = 0; // wg. Sonderbehandlung Sb_ATTR_VOLUME DirEntry aEntry( rPar.Get(1)->GetString() ); FileStat aStat( aEntry ); if(!aStat.GetError() && (aStat.GetKind() & FSYS_KIND_FILE)) { // ah ja, ist nur ein dateiname // Pfad abschneiden (wg. VB4) rPar.Get(0)->PutString( aEntry.GetName() ); return; } sal_uInt16 nFlags = 0; if ( nParCount > 2 ) pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger(); else pRTLData->nDirFlags = 0; // Sb_ATTR_VOLUME wird getrennt gehandelt if( pRTLData->nDirFlags & Sb_ATTR_VOLUME ) aPath = aEntry.GetVolume(); else { // Die richtige Auswahl treffen sal_uInt16 nMode = FSYS_KIND_FILE; if( nFlags & Sb_ATTR_DIRECTORY ) nMode |= FSYS_KIND_DIR; if( nFlags == Sb_ATTR_DIRECTORY ) nMode = FSYS_KIND_DIR; pRTLData->pDir = new Dir( aEntry, (DirEntryKind) nMode ); pRTLData->nCurDirPos = 0; } } if( pRTLData->pDir ) { for( ;; ) { if( pRTLData->nCurDirPos >= pRTLData->pDir->Count() ) { delete pRTLData->pDir; pRTLData->pDir = 0; aPath.Erase(); break; } DirEntry aNextEntry=(*(pRTLData->pDir))[pRTLData->nCurDirPos++]; aPath = aNextEntry.GetName(); //Full(); 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::createFromAscii( "." ); } else if( pRTLData->nCurDirPos == -1 ) { aPath = ::rtl::OUString::createFromAscii( ".." ); } pRTLData->nCurDirPos++; } else { DirectoryItem aItem; FileBase::RC nRet = pRTLData->pDir->getNextItem( aItem ); if( nRet != FileBase::E_None ) { delete pRTLData->pDir; pRTLData->pDir = NULL; aPath.Erase(); break; } // Handle flags FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileName ); nRet = aItem.getFileStatus( aFileStatus ); // Only directories? if( bFolderFlag ) { FileStatus::Type aType = aFileStatus.getFileType(); sal_Bool bFolder = isFolder( aType ); if( !bFolder ) continue; } aPath = aFileStatus.getFileName(); } sal_Bool bMatch = implCheckWildcard( aPath, pRTLData ); if( !bMatch ) continue; break; } } rPar.Get(0)->PutString( aPath ); #endif } } } RTLFUNC(GetAttr) { (void)pBasic; (void)bWrite; if ( rPar.Count() == 2 ) { 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 // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { String aPath = getFullPath( rPar.Get(1)->GetString() ); sal_Bool bExists = sal_False; try { bExists = xSFI->exists( aPath ); } catch( Exception & ) {} if( !bExists ) { StarBASIC::Error( SbERR_FILE_NOT_FOUND ); return; } sal_Bool bReadOnly = xSFI->isReadOnly( aPath ); sal_Bool bHidden = xSFI->isHidden( aPath ); sal_Bool bDirectory = xSFI->isFolder( aPath ); if( bReadOnly ) nFlags |= 0x0001; // ATTR_READONLY if( bHidden ) nFlags |= 0x0002; // ATTR_HIDDEN if( bDirectory ) nFlags |= 0x0010; // ATTR_DIRECTORY } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { DirectoryItem aItem; FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetString() ), aItem ); FileStatus aFileStatus( FileStatusMask_Attributes | FileStatusMask_Type ); nRet = aItem.getFileStatus( aFileStatus ); sal_uInt64 nAttributes = aFileStatus.getAttributes(); sal_Bool bReadOnly = (nAttributes & Attribute_ReadOnly) != 0; FileStatus::Type aType = aFileStatus.getFileType(); sal_Bool bDirectory = isFolder( aType ); if( bReadOnly ) nFlags |= 0x0001; // ATTR_READONLY if( bDirectory ) nFlags |= 0x0010; // ATTR_DIRECTORY } rPar.Get(0)->PutInteger( nFlags ); } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } RTLFUNC(FileDateTime) { (void)pBasic; (void)bWrite; if ( rPar.Count() != 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { // <-- UCB String aPath = rPar.Get(1)->GetString(); Time aTime; Date aDate; if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { com::sun::star::util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath ); aTime = Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds ); aDate = Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL DirEntry aEntry( aPath ); FileStat aStat( aEntry ); aTime = Time( aStat.TimeModified() ); aDate = Date( aStat.DateModified() ); #else DirectoryItem aItem; FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aPath ), aItem ); FileStatus aFileStatus( FileStatusMask_ModifyTime ); nRet = aItem.getFileStatus( aFileStatus ); TimeValue aTimeVal = aFileStatus.getModifyTime(); oslDateTime aDT; osl_getDateTimeFromTimeValue( &aTimeVal, &aDT ); aTime = Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 10000000*aDT.NanoSeconds ); aDate = Date( aDT.Day, aDT.Month, aDT.Year ); #endif } double fSerial = (double)GetDayDiff( aDate ); long nSeconds = aTime.GetHour(); nSeconds *= 3600; nSeconds += aTime.GetMin() * 60; nSeconds += aTime.GetSec(); double nDays = ((double)nSeconds) / (double)(24.0*3600.0); fSerial += nDays; Color* pCol; // #39629 pINST pruefen, kann aus URL-Zeile gerufen werden SvNumberFormatter* pFormatter = NULL; sal_uInt32 nIndex; if( pINST ) { pFormatter = pINST->GetNumberFormatter(); nIndex = pINST->GetStdDateTimeIdx(); } else { sal_uInt32 n; // Dummy SbiInstance::PrepareNumberFormatter( pFormatter, n, n, nIndex ); } String aRes; pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol ); rPar.Get(0)->PutString( aRes ); // #39629 pFormatter kann selbst angefordert sein if( !pINST ) delete pFormatter; } } RTLFUNC(EOF) { (void)pBasic; (void)bWrite; // AB 08/16/2000: No changes for UCB if ( rPar.Count() != 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { sal_Int16 nChannel = rPar.Get(1)->GetInteger(); // nChannel--; // macht MD beim Oeffnen auch nicht SbiIoSystem* pIO = pINST->GetIoSystem(); SbiStream* pSbStrm = pIO->GetStream( nChannel ); if ( !pSbStrm ) { StarBASIC::Error( SbERR_BAD_CHANNEL ); return; } 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; // AB 08/16/2000: No changes for UCB // #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von // der Anpassung an virtuelle URLs nich betroffen, da sie nur auf bereits // geoeffneten Dateien arbeitet und der Name hier keine Rolle spielt. if ( rPar.Count() != 3 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { sal_Int16 nChannel = rPar.Get(1)->GetInteger(); // nChannel--; 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; // AB 08/16/2000: 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; // AB 08/16/2000: 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; // AB 08/16/2000: 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(); // nChannel--; SbiIoSystem* pIO = pINST->GetIoSystem(); SbiStream* pSbStrm = pIO->GetStream( nChannel ); if ( !pSbStrm ) { StarBASIC::Error( SbERR_BAD_CHANNEL ); return; } SvStream* pStrm = pSbStrm->GetStrm(); if ( nArgs == 2 ) // Seek-Function { 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 ); 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 { sal_uInt16 nOptions = vos::OProcess::TOption_SearchPath| vos::OProcess::TOption_Detached; String aCmdLine = rPar.Get(1)->GetString(); // Zusaetzliche Parameter anhaengen, es muss eh alles geparsed werden if( nArgCount >= 4 ) { aCmdLine.AppendAscii( " " ); aCmdLine += rPar.Get(3)->GetString(); } else if( !aCmdLine.Len() ) { // Spezial-Behandlung (leere Liste) vermeiden aCmdLine.AppendAscii( " " ); } sal_uInt16 nLen = aCmdLine.Len(); // #55735 Wenn Parameter dabei sind, muessen die abgetrennt werden // #72471 Auch die einzelnen Parameter trennen std::list 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 |= vos::OProcess::TOption_Minimized; break; case 3: nOptions |= vos::OProcess::TOption_Maximized; break; case 10: nOptions |= vos::OProcess::TOption_FullScreen; break; } sal_Bool bSync = sal_False; if( nArgCount >= 5 ) bSync = rPar.Get(4)->GetBool(); if( bSync ) nOptions |= vos::OProcess::TOption_Wait; } vos::OProcess::TProcessOption eOptions = (vos::OProcess::TProcessOption)nOptions; // #72471 Parameter aufbereiten std::list::const_iterator iter = aTokenList.begin(); const String& rStr = *iter; ::rtl::OUString aOUStrProg( rStr.GetBuffer(), rStr.Len() ); String aOUStrProgUNC = getFullPathUNC( aOUStrProg ); iter++; sal_uInt16 nParamCount = sal::static_int_cast< sal_uInt16 >( aTokenList.size() - 1 ); ::rtl::OUString* pArgumentList = NULL; //const char** pParamList = NULL; if( nParamCount ) { pArgumentList = new ::rtl::OUString[ nParamCount ]; //pParamList = new const char*[ nParamCount ]; sal_uInt16 iList = 0; while( iter != aTokenList.end() ) { const String& rParamStr = (*iter); pArgumentList[iList++] = ::rtl::OUString( rParamStr.GetBuffer(), rParamStr.Len() ); //pParamList[iList++] = (*iter).GetStr(); iter++; } } //const char* pParams = aParams.Len() ? aParams.GetStr() : 0; vos::OProcess* pApp; pApp = new vos::OProcess( aOUStrProgUNC ); sal_Bool bSucc; if( nParamCount == 0 ) { bSucc = pApp->execute( eOptions ) == vos::OProcess::E_None; } else { vos::OArgumentList aArgList( pArgumentList, nParamCount ); bSucc = pApp->execute( eOptions, aArgList ) == vos::OProcess::E_None; } /* if( nParamCount == 0 ) pApp = new vos::OProcess( pProg ); else pApp = new vos::OProcess( pProg, pParamList, nParamCount ); sal_Bool bSucc = pApp->execute( eOptions ) == vos::OProcess::E_None; */ delete pApp; delete[] pArgumentList; if( !bSucc ) StarBASIC::Error( SbERR_FILE_NOT_FOUND ); else rPar.Get(0)->PutLong( 0 ); } } RTLFUNC(VarType) { (void)pBasic; (void)bWrite; if ( rPar.Count() != 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { SbxDataType eType = rPar.Get(1)->GetType(); rPar.Get(0)->PutInteger( (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; } 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 = 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; if( nArgCount == 3 ) { // LCID not supported now //nLanguage = rPar.Get(3)->GetInteger(); } 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 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); // 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; ReadDIB(aBmp, *pStream, true); 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, nWinBits, 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) // JSM { (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(); // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { sal_Bool bReadOnly = (nFlags & 0x0001) != 0; // ATTR_READONLY xSFI->setReadOnly( aStr, bReadOnly ); sal_Bool bHidden = (nFlags & 0x0002) != 0; // ATTR_HIDDEN xSFI->setHidden( aStr, bHidden ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL // #57064 Bei virtuellen URLs den Real-Path extrahieren DirEntry aEntry( aStr ); String aFile = aEntry.GetFull(); ByteString aByteFile( aFile, gsl_getSystemTextEncoding() ); #ifdef WNT if (!SetFileAttributes (aByteFile.GetBuffer(),(DWORD)nFlags)) StarBASIC::Error(SbERR_FILE_NOT_FOUND); #endif #ifdef OS2 FILESTATUS3 aFileStatus; APIRET rc = DosQueryPathInfo(aByteFile.GetBuffer(),1, &aFileStatus,sizeof(FILESTATUS3)); if (!rc) { if (aFileStatus.attrFile != nFlags) { aFileStatus.attrFile = nFlags; rc = DosSetPathInfo(aFile.GetStr(),1, &aFileStatus,sizeof(FILESTATUS3),0); if (rc) StarBASIC::Error( SbERR_FILE_NOT_FOUND ); } } else StarBASIC::Error( SbERR_FILE_NOT_FOUND ); #endif #else // Not implemented #endif } } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } RTLFUNC(Reset) // JSM { (void)pBasic; (void)bWrite; (void)rPar; SbiIoSystem* pIO = pINST->GetIoSystem(); if (pIO) pIO->CloseAll(); } RTLFUNC(DumpAllObjects) { (void)pBasic; (void)bWrite; 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; // <-- UCB if( hasUno() ) { com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess(); if( xSFI.is() ) { try { bExists = xSFI->exists( aStr ); } catch( Exception & ) { StarBASIC::Error( ERRCODE_IO_GENERAL ); } } } else // --> UCB { #ifdef _OLD_FILE_IMPL DirEntry aEntry( aStr ); bExists = aEntry.Exists(); #else DirectoryItem aItem; FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem ); bExists = (nRet == FileBase::E_None); #endif } rPar.Get(0)->PutBool( bExists ); } else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } RTLFUNC(Partition) { (void)pBasic; (void)bWrite; if ( rPar.Count() != 5 ) { StarBASIC::Error( SbERR_BAD_ARGUMENT ); return; } 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()) ); }