The STLport was only built for the benefit of old extensions on platforms that
once used it themselves (Linux x86, Solaris x86 and SPARC, Windows). We
deliberately break such old extensions for LO 4.0 by no longer shipping that
backwards-compatiblity cludge.
Keeps STLport listed in readlicense_oo/ because of
o3tl/inc/o3tl/compat_functionality.hxx.
Also removes GXX_INCLUDE_PATH, as that was only used by STLport (if at all?).
Removes a spurious #define MOVEFILE_REPLACE_EXISTING 0x01 from
l10ntools/inc/helpmerge.hxx that was once added with
8548125848
"INTEGRATION: CWS extensionl10nfix01
(1.11.6); FILE MERGED: 2008/06/26 13:56:03 ihi 1.11.6.1: #i90987# windows rename
-> MoveFileEx" but now starts to cause trouble on Windows. Also disables
warning C4005 about redefinition of WB_LEFT/RIGHT macros (defined in both
tools/wintypes.hxx and the Windows API) in a number of places that include
windows.h -- however the old STLport caused those warnings to not show.
Change-Id: Ie138a219fbbc86fb5aaa7ea0b88cf349935d9829
4795 lines
121 KiB
C++
4795 lines
121 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* 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 .
|
|
*/
|
|
|
|
#include <tools/date.hxx>
|
|
#include <basic/sbxvar.hxx>
|
|
#include <osl/process.h>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/settings.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 <rtl/strbuf.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 <comphelper/string.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/SimpleFileAccess.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;
|
|
|
|
#include <comphelper/string.hxx>
|
|
|
|
#include "date.hxx"
|
|
#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
|
|
#if defined _MSC_VER
|
|
#pragma warning (push, 1)
|
|
#pragma warning (disable: 4005)
|
|
#endif
|
|
#include <windows.h>
|
|
#if defined _MSC_VER
|
|
#pragma warning (pop)
|
|
#endif
|
|
#include <io.h>
|
|
#undef GetObject
|
|
#undef GradientSyle_RECT
|
|
#endif
|
|
|
|
#ifndef DISABLE_SCRIPTING
|
|
|
|
// from source/classes/sbxmod.cxx
|
|
uno::Reference< frame::XModel > getDocumentModel( StarBASIC* );
|
|
|
|
static void FilterWhiteSpace( OUString& rStr )
|
|
{
|
|
if (rStr.isEmpty())
|
|
{
|
|
return;
|
|
}
|
|
rtl::OUStringBuffer aRet;
|
|
|
|
for (sal_Int32 i = 0; i < rStr.getLength(); ++i)
|
|
{
|
|
sal_Unicode cChar = rStr[i];
|
|
if ((cChar != ' ') && (cChar != '\t') &&
|
|
(cChar != '\n') && (cChar != '\r'))
|
|
{
|
|
aRet.append(cChar);
|
|
}
|
|
}
|
|
|
|
rStr = aRet.makeStringAndClear();
|
|
}
|
|
|
|
static long GetDayDiff( const Date& rDate );
|
|
|
|
static const CharClass& GetCharClass( void )
|
|
{
|
|
static bool bNeedsInit = true;
|
|
static LanguageTag aLanguageTag( LANGUAGE_SYSTEM);
|
|
if( bNeedsInit )
|
|
{
|
|
bNeedsInit = false;
|
|
aLanguageTag = Application::GetSettings().GetLanguageTag();
|
|
}
|
|
static CharClass aCharClass( aLanguageTag );
|
|
return aCharClass;
|
|
}
|
|
|
|
static inline bool isFolder( FileStatus::Type aType )
|
|
{
|
|
return ( aType == FileStatus::Directory || aType == FileStatus::Volume );
|
|
}
|
|
|
|
|
|
//*** UCB file access ***
|
|
|
|
// Converts possibly relative paths to absolute paths
|
|
// according to the setting done by ChDir/ChDrive
|
|
OUString getFullPath( const OUString& aRelPath )
|
|
{
|
|
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;
|
|
}
|
|
|
|
// TODO: -> SbiGlobals
|
|
static uno::Reference< ucb::XSimpleFileAccess3 > getFileAccess( void )
|
|
{
|
|
static uno::Reference< ucb::XSimpleFileAccess3 > xSFI;
|
|
if( !xSFI.is() )
|
|
{
|
|
xSFI = ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
|
|
}
|
|
return xSFI;
|
|
}
|
|
|
|
|
|
|
|
// Properties and methods lie down the return value at the Get (bPut = sal_False) in the
|
|
// element 0 of the Argv; the value of element 0 is saved at Put (bPut = sal_True)
|
|
|
|
// CreateObject( class )
|
|
|
|
RTLFUNC(CreateObject)
|
|
{
|
|
(void)bWrite;
|
|
|
|
OUString aClass( rPar.Get( 1 )->GetOUString() );
|
|
SbxObjectRef p = SbxBase::CreateObject( aClass );
|
|
if( !p )
|
|
StarBASIC::Error( SbERR_CANNOT_LOAD );
|
|
else
|
|
{
|
|
// Convenience: enter BASIC as parent
|
|
p->SetParent( pBasic );
|
|
rPar.Get( 0 )->PutObject( p );
|
|
}
|
|
}
|
|
|
|
// Error( n )
|
|
|
|
RTLFUNC(Error)
|
|
{
|
|
(void)bWrite;
|
|
|
|
if( !pBasic )
|
|
StarBASIC::Error( SbERR_INTERNAL_ERROR );
|
|
else
|
|
{
|
|
OUString 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();
|
|
OUString tmpErrMsg;
|
|
if( bVBA && !aErrorMsg.isEmpty())
|
|
{
|
|
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 )
|
|
{
|
|
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() ) );
|
|
}
|
|
}
|
|
|
|
|
|
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() ) );
|
|
}
|
|
}
|
|
|
|
|
|
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 );
|
|
OUString aStr( pArg->GetOUString() );
|
|
if ( aStr.isEmpty())
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
rPar.Get(0)->PutEmpty();
|
|
}
|
|
else
|
|
{
|
|
sal_Unicode aCh = aStr[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 );
|
|
|
|
OUString aStr;
|
|
if( !bChrW && SbiRuntime::isVBAEnabled() )
|
|
{
|
|
sal_Char c = static_cast<sal_Char>(pArg->GetByte());
|
|
aStr = rtl::OUString(&c, 1, osl_getThreadTextEncoding());
|
|
}
|
|
else
|
|
{
|
|
sal_Unicode aCh = static_cast<sal_Unicode>(pArg->GetUShort());
|
|
aStr = OUString(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 Although this function doesn't work with DirEntry, it isn't touched
|
|
// by the adjustment to virtual URLs, as, using the DirEntry-functionality,
|
|
// there's no possibility to detect the current one in a way that a virtual URL
|
|
// could be delivered.
|
|
|
|
#if defined (WNT)
|
|
int nCurDir = 0; // Current dir // JSM
|
|
if ( rPar.Count() == 2 )
|
|
{
|
|
OUString aDrive = rPar.Get(1)->GetOUString();
|
|
if ( aDrive.getLength() != 1 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
nCurDir = (int)aDrive[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( rtl::OUString::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( rtl::OUString::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)->GetOUString() );
|
|
}
|
|
}
|
|
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 OUString& aSource, const OUString& aDest )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
OUString aSourceFullPath = getFullPath( aSource );
|
|
if( !xSFI->exists( aSourceFullPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
return;
|
|
}
|
|
|
|
OUString aDestFullPath = getFullPath( aDest );
|
|
if( xSFI->exists( aDestFullPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_EXISTS );
|
|
}
|
|
else
|
|
{
|
|
xSFI->move( aSourceFullPath, aDestFullPath );
|
|
}
|
|
}
|
|
catch(const Exception & )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Implementation of StepRENAME with OSL
|
|
void implStepRenameOSL( const OUString& aSource, const OUString& 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)
|
|
{
|
|
OUString aSource = rPar.Get(1)->GetOUString();
|
|
OUString aDest = rPar.Get(2)->GetOUString();
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) );
|
|
}
|
|
catch(const 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)
|
|
{
|
|
OUString aFileSpec = rPar.Get(1)->GetOUString();
|
|
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
OUString aFullPath = getFullPath( aFileSpec );
|
|
if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_FILE_NOT_FOUND );
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
xSFI->kill( aFullPath );
|
|
}
|
|
catch(const 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)
|
|
{
|
|
OUString aPath = rPar.Get(1)->GetOUString();
|
|
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
xSFI->createFolder( getFullPath( aPath ) );
|
|
}
|
|
catch(const 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 OUString& aDirPath )
|
|
{
|
|
DirectoryItem aItem;
|
|
FileBase::RC nRet = DirectoryItem::get( aDirPath, aItem );
|
|
bool bExists = (nRet == FileBase::E_None);
|
|
|
|
FileStatus aFileStatus( osl_FileStatus_Mask_Type );
|
|
nRet = aItem.getFileStatus( aFileStatus );
|
|
FileStatus::Type aType = aFileStatus.getFileType();
|
|
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 );
|
|
OUString aPath = aFileStatus2.getFileURL();
|
|
|
|
// Directory?
|
|
FileStatus::Type aType2 = aFileStatus2.getFileType();
|
|
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)
|
|
{
|
|
OUString aPath = rPar.Get(1)->GetOUString();
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
if( !xSFI->isFolder( aPath ) )
|
|
{
|
|
StarBASIC::Error( SbERR_PATH_NOT_FOUND );
|
|
return;
|
|
}
|
|
SbiInstance* pInst = GetSbData()->pInst;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
if( bCompatibility )
|
|
{
|
|
Sequence< 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(const 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 );
|
|
OUString aStr( pArg->GetOUString() );
|
|
sal_Int32 nLen = 0;
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
nLen = xSFI->getSize( getFullPath( aStr ) );
|
|
}
|
|
catch(const 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
|
|
{
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
// converting value to unsigned and limit to 2 or 4 byte representation
|
|
sal_uInt32 nVal = pArg->IsInteger() ?
|
|
static_cast<sal_uInt16>(pArg->GetInteger()) :
|
|
static_cast<sal_uInt32>(pArg->GetLong());
|
|
rPar.Get(0)->PutString( rtl::OUString::valueOf( sal_Int64(nVal), 16 ) );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(FuncCaller)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
if ( SbiRuntime::isVBAEnabled() && GetSbData()->pInst && GetSbData()->pInst->pRun )
|
|
{
|
|
if ( GetSbData()->pInst->pRun->GetExternalCaller() )
|
|
*rPar.Get(0) = *GetSbData()->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_Int32 nStartPos = 1;
|
|
sal_Int32 nFirstStringPos = 1;
|
|
|
|
if ( nArgCount >= 3 )
|
|
{
|
|
nStartPos = rPar.Get(1)->GetLong();
|
|
if( nStartPos <= 0 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
nStartPos = 1;
|
|
}
|
|
nFirstStringPos++;
|
|
}
|
|
|
|
SbiInstance* pInst = GetSbData()->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_Int32 nPos;
|
|
const OUString& rToken = rPar.Get(nFirstStringPos+1)->GetOUString();
|
|
|
|
// #97545 Always find empty string
|
|
if( rToken.isEmpty() )
|
|
{
|
|
nPos = nStartPos;
|
|
}
|
|
else
|
|
{
|
|
if( !bTextMode )
|
|
{
|
|
const OUString& rStr1 = rPar.Get(nFirstStringPos)->GetOUString();
|
|
nPos = rStr1.indexOf( rToken, nStartPos - 1 ) + 1;
|
|
}
|
|
else
|
|
{
|
|
OUString aStr1 = rPar.Get(nFirstStringPos)->GetOUString();
|
|
OUString aToken = rToken;
|
|
|
|
aStr1 = aStr1.toAsciiUpperCase();
|
|
aToken = aToken.toAsciiUpperCase();
|
|
|
|
nPos = aStr1.indexOf( aToken, nStartPos-1 ) + 1;
|
|
}
|
|
}
|
|
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
|
|
{
|
|
OUString aStr1 = rPar.Get(1)->GetOUString();
|
|
OUString aToken = rPar.Get(2)->GetOUString();
|
|
|
|
sal_Int32 nStartPos = -1;
|
|
if ( nArgCount >= 3 )
|
|
{
|
|
nStartPos = rPar.Get(3)->GetLong();
|
|
if( (nStartPos <= 0 && nStartPos != -1))
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
nStartPos = -1;
|
|
}
|
|
}
|
|
|
|
SbiInstance* pInst = GetSbData()->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_Int32 nStrLen = aStr1.getLength();
|
|
if( nStartPos == -1 )
|
|
{
|
|
nStartPos = nStrLen;
|
|
}
|
|
|
|
sal_Int32 nPos = 0;
|
|
if( nStartPos <= nStrLen )
|
|
{
|
|
sal_Int32 nTokenLen = aToken.getLength();
|
|
if( !nTokenLen )
|
|
{
|
|
// Always find empty string
|
|
nPos = nStartPos;
|
|
}
|
|
else if( nStrLen > 0 )
|
|
{
|
|
if( !bTextMode )
|
|
{
|
|
nPos = aStr1.lastIndexOf( aToken, nStartPos ) + 1;
|
|
}
|
|
else
|
|
{
|
|
aStr1 = aStr1.toAsciiUpperCase();
|
|
aToken = aToken.toAsciiUpperCase();
|
|
|
|
nPos = aStr1.lastIndexOf( aToken, nStartPos ) + 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
|
|
{
|
|
const CharClass& rCharClass = GetCharClass();
|
|
OUString aStr( rPar.Get(1)->GetOUString() );
|
|
aStr = rCharClass.lowercase(aStr);
|
|
rPar.Get(0)->PutString( aStr );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Left)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
OUString aStr( rPar.Get(1)->GetOUString() );
|
|
sal_Int32 nResultLen = rPar.Get(2)->GetLong();
|
|
if( nResultLen < 0 )
|
|
{
|
|
nResultLen = 0;
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else if(nResultLen > aStr.getLength())
|
|
{
|
|
nResultLen = aStr.getLength();
|
|
}
|
|
aStr = aStr.copy(0, nResultLen );
|
|
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
|
|
{
|
|
OUString aStr(comphelper::string::stripStart(rPar.Get(1)->GetOUString(), ' '));
|
|
rPar.Get(0)->PutString(aStr);
|
|
}
|
|
}
|
|
|
|
|
|
// Mid( String, nStart, nLength )
|
|
|
|
RTLFUNC(Mid)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
int nArgCount = rPar.Count()-1;
|
|
if ( nArgCount < 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
// #23178: replicate the functionality of Mid$ as a command
|
|
// by adding a replacement-string as a fourth parameter.
|
|
// In contrast to the original the third parameter (nLength)
|
|
// can't be left out here. That's considered in bWrite already.
|
|
if( nArgCount == 4 )
|
|
{
|
|
bWrite = sal_True;
|
|
}
|
|
OUString aArgStr = rPar.Get(1)->GetOUString();
|
|
sal_Int32 nStartPos = rPar.Get(2)->GetLong();
|
|
if ( nStartPos == 0 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
nStartPos--;
|
|
sal_Int32 nLen = -1;
|
|
bool bWriteNoLenParam = false;
|
|
if ( nArgCount == 3 || bWrite )
|
|
{
|
|
sal_Int32 n = rPar.Get(3)->GetLong();
|
|
if( bWrite && n == -1 )
|
|
{
|
|
bWriteNoLenParam = true;
|
|
}
|
|
nLen = n;
|
|
}
|
|
if ( bWrite )
|
|
{
|
|
OUStringBuffer aResultStr;
|
|
SbiInstance* pInst = GetSbData()->pInst;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
if( bCompatibility )
|
|
{
|
|
sal_Int32 nArgLen = aArgStr.getLength();
|
|
if( nStartPos + 1 > nArgLen )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
OUString aReplaceStr = rPar.Get(4)->GetOUString();
|
|
sal_Int32 nReplaceStrLen = aReplaceStr.getLength();
|
|
sal_Int32 nReplaceLen;
|
|
if( bWriteNoLenParam )
|
|
{
|
|
nReplaceLen = nReplaceStrLen;
|
|
}
|
|
else
|
|
{
|
|
nReplaceLen = nLen;
|
|
if( nReplaceLen < 0 || nReplaceLen > nReplaceStrLen )
|
|
{
|
|
nReplaceLen = nReplaceStrLen;
|
|
}
|
|
}
|
|
|
|
sal_Int32 nReplaceEndPos = nStartPos + nReplaceLen;
|
|
if( nReplaceEndPos > nArgLen )
|
|
{
|
|
nReplaceLen -= (nReplaceEndPos - nArgLen);
|
|
}
|
|
aResultStr = aArgStr;
|
|
sal_Int32 nErase = nReplaceLen;
|
|
aResultStr.remove( nStartPos, nErase );
|
|
aResultStr.insert( nStartPos, aReplaceStr.getStr(), nReplaceLen);
|
|
}
|
|
else
|
|
{
|
|
aResultStr = aArgStr;
|
|
aResultStr.remove( nStartPos, nLen );
|
|
aResultStr.insert( nStartPos, rPar.Get(4)->GetOUString().getStr(), nLen);
|
|
}
|
|
|
|
rPar.Get(1)->PutString( aResultStr.makeStringAndClear() );
|
|
}
|
|
else
|
|
{
|
|
OUString aResultStr;
|
|
if(nLen < 0)
|
|
{
|
|
aResultStr = aArgStr.copy( nStartPos);
|
|
}
|
|
else
|
|
{
|
|
if(nStartPos + nLen > aArgStr.getLength())
|
|
{
|
|
nLen = aArgStr.getLength() - nStartPos;
|
|
}
|
|
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( rtl::OUString::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
|
|
{
|
|
OUString aExpStr = rPar.Get(1)->GetOUString();
|
|
OUString aFindStr = rPar.Get(2)->GetOUString();
|
|
OUString aReplaceStr = rPar.Get(3)->GetOUString();
|
|
|
|
sal_Int32 lStartPos = 1;
|
|
if ( nArgCount >= 4 )
|
|
{
|
|
if( rPar.Get(4)->GetType() != SbxEMPTY )
|
|
{
|
|
lStartPos = rPar.Get(4)->GetLong();
|
|
}
|
|
if( lStartPos < 1)
|
|
{
|
|
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)
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
lCount = -1;
|
|
}
|
|
}
|
|
|
|
SbiInstance* pInst = GetSbData()->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_Int32 nExpStrLen = aExpStr.getLength();
|
|
sal_Int32 nFindStrLen = aFindStr.getLength();
|
|
sal_Int32 nReplaceStrLen = aReplaceStr.getLength();
|
|
|
|
if( lStartPos <= nExpStrLen )
|
|
{
|
|
sal_Int32 nPos = lStartPos - 1;
|
|
sal_Int32 nCounts = 0;
|
|
while( lCount == -1 || lCount > nCounts )
|
|
{
|
|
OUString aSrcStr( aExpStr );
|
|
if( bTextMode )
|
|
{
|
|
aSrcStr = aSrcStr.toAsciiUpperCase();
|
|
aFindStr = aFindStr.toAsciiUpperCase();
|
|
}
|
|
nPos = aSrcStr.indexOf( aFindStr, nPos );
|
|
if( nPos >= 0 )
|
|
{
|
|
aExpStr = aExpStr.replaceAt( nPos, nFindStrLen, aReplaceStr );
|
|
nPos = nPos - nFindStrLen + nReplaceStrLen + 1;
|
|
nCounts++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
rPar.Get(0)->PutString( aExpStr.copy( lStartPos - 1 ) );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Right)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
const OUString& rStr = rPar.Get(1)->GetOUString();
|
|
int nResultLen = rPar.Get(2)->GetLong();
|
|
if( nResultLen < 0 )
|
|
{
|
|
nResultLen = 0;
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
int nStrLen = rStr.getLength();
|
|
if ( nResultLen > nStrLen )
|
|
{
|
|
nResultLen = nStrLen;
|
|
}
|
|
OUString 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
|
|
{
|
|
OUString aStr(comphelper::string::stripEnd(rPar.Get(1)->GetOUString(), ' '));
|
|
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
|
|
{
|
|
OUStringBuffer aBuf;
|
|
string::padToLength(aBuf, rPar.Get(1)->GetLong(), ' ');
|
|
rPar.Get(0)->PutString(aBuf.makeStringAndClear());
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Spc)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
OUStringBuffer aBuf;
|
|
string::padToLength(aBuf, rPar.Get(1)->GetLong(), ' ');
|
|
rPar.Get(0)->PutString(aBuf.makeStringAndClear());
|
|
}
|
|
}
|
|
|
|
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
|
|
{
|
|
OUString aStr;
|
|
OUString aStrNew("");
|
|
SbxVariableRef pArg = rPar.Get( 1 );
|
|
pArg->Format( aStr );
|
|
|
|
// Numbers start with a space
|
|
if( pArg->IsNumericRTL() )
|
|
{
|
|
// replace commas by points so that it's symmetric to Val!
|
|
aStr = aStr.replaceFirst( ",", "." );
|
|
|
|
SbiInstance* pInst = GetSbData()->pInst;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
if( bCompatibility )
|
|
{
|
|
sal_Int32 nLen = aStr.getLength();
|
|
|
|
const sal_Unicode* pBuf = aStr.getStr();
|
|
|
|
bool bNeg = ( pBuf[0] == '-' );
|
|
sal_Int32 iZeroSearch = 0;
|
|
if( bNeg )
|
|
{
|
|
aStrNew += "-";
|
|
iZeroSearch++;
|
|
}
|
|
else
|
|
{
|
|
if( pBuf[0] != ' ' )
|
|
{
|
|
aStrNew += " ";
|
|
}
|
|
}
|
|
sal_Int32 iNext = iZeroSearch + 1;
|
|
if( pBuf[iZeroSearch] == '0' && nLen > iNext && pBuf[iNext] == '.' )
|
|
{
|
|
iZeroSearch += 1;
|
|
}
|
|
aStrNew += aStr.copy(iZeroSearch);
|
|
}
|
|
else
|
|
{
|
|
aStrNew = " " + aStr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aStrNew = aStr;
|
|
}
|
|
rPar.Get(0)->PutString( aStrNew );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(StrComp)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
rPar.Get(0)->PutEmpty();
|
|
return;
|
|
}
|
|
const OUString& rStr1 = rPar.Get(1)->GetOUString();
|
|
const OUString& rStr2 = rPar.Get(2)->GetOUString();
|
|
|
|
SbiInstance* pInst = GetSbData()->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;
|
|
}
|
|
sal_Int32 nRetValue = 0;
|
|
if( nTextCompare )
|
|
{
|
|
::utl::TransliterationWrapper* pTransliterationWrapper = GetSbData()->pTransliterationWrapper;
|
|
if( !pTransliterationWrapper )
|
|
{
|
|
uno::Reference< uno::XComponentContext > xContext = getProcessComponentContext();
|
|
pTransliterationWrapper = GetSbData()->pTransliterationWrapper =
|
|
new ::utl::TransliterationWrapper( xContext,
|
|
i18n::TransliterationModules_IGNORE_CASE |
|
|
i18n::TransliterationModules_IGNORE_KANA |
|
|
i18n::TransliterationModules_IGNORE_WIDTH );
|
|
}
|
|
|
|
LanguageType eLangType = GetpApp()->GetSettings().GetLanguageTag().getLanguageType();
|
|
pTransliterationWrapper->loadModuleIfNeeded( eLangType );
|
|
nRetValue = pTransliterationWrapper->compareString( rStr1, rStr2 );
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 aResult;
|
|
aResult = rStr1.compareTo( rStr2 );
|
|
if ( aResult < 0 )
|
|
{
|
|
nRetValue = -1;
|
|
}
|
|
else if ( aResult > 0)
|
|
{
|
|
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
|
|
{
|
|
sal_Unicode aFiller;
|
|
sal_Int32 lCount = rPar.Get(1)->GetLong();
|
|
if( lCount < 0 || lCount > 0xffff )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
if( rPar.Get(2)->GetType() == SbxINTEGER )
|
|
{
|
|
aFiller = (sal_Unicode)rPar.Get(2)->GetInteger();
|
|
}
|
|
else
|
|
{
|
|
const OUString& rStr = rPar.Get(2)->GetOUString();
|
|
aFiller = rStr[0];
|
|
}
|
|
OUStringBuffer aBuf(lCount);
|
|
string::padToLength(aBuf, lCount, aFiller);
|
|
rPar.Get(0)->PutString(aBuf.makeStringAndClear());
|
|
}
|
|
}
|
|
|
|
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
|
|
{
|
|
const CharClass& rCharClass = GetCharClass();
|
|
OUString aStr( rPar.Get(1)->GetOUString() );
|
|
aStr = rCharClass.uppercase( 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;
|
|
|
|
OUString aStr( rPar.Get(1)->GetOUString() );
|
|
|
|
FilterWhiteSpace( aStr );
|
|
if ( aStr[0] == '&' && aStr.getLength() > 1 )
|
|
{
|
|
int nRadix = 10;
|
|
char aChar = (char)aStr[1];
|
|
if ( aChar == 'h' || aChar == 'H' )
|
|
{
|
|
nRadix = 16;
|
|
}
|
|
else if ( aChar == 'o' || aChar == 'O' )
|
|
{
|
|
nRadix = 8;
|
|
}
|
|
if ( nRadix != 10 )
|
|
{
|
|
OString aByteStr(rtl::OUStringToOString(aStr, osl_getThreadTextEncoding()));
|
|
sal_Int16 nlResult = (sal_Int16)strtol( aByteStr.getStr()+2, &pEndPtr, nRadix);
|
|
nResult = (double)nlResult;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// #57844 use localized function
|
|
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; // standardize: 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; // standardize: 1.1.1900 => 0.0
|
|
aRefDate += nDays;
|
|
sal_Int16 nRet = (sal_Int16)( aRefDate.GetMonth() );
|
|
return nRet;
|
|
}
|
|
|
|
// 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 ) );
|
|
OUString aRetStr = rtl::OUString::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 )
|
|
{
|
|
OUString aStr = rPar.Get(1)->GetOUString();
|
|
sal_Int16 iMonthStart = aStr.getLength() - 4;
|
|
OUString aYearStr = aStr.copy( 0, iMonthStart );
|
|
OUString aMonthStr = aStr.copy( iMonthStart, 2 );
|
|
OUString 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; // because of UNO DateTimes, which go till 24 o'clock
|
|
}
|
|
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 check GetSbData()->pInst, can be called from the URL line
|
|
SvNumberFormatter* pFormatter = NULL;
|
|
if( GetSbData()->pInst )
|
|
{
|
|
pFormatter = GetSbData()->pInst->GetNumberFormatter();
|
|
}
|
|
else
|
|
{
|
|
sal_uInt32 n; // Dummy
|
|
SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
|
|
}
|
|
|
|
sal_uInt32 nIndex;
|
|
double fResult;
|
|
OUString aStr( rPar.Get(1)->GetOUString() );
|
|
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().GetLanguageTag().getLanguageType();
|
|
if( !bSuccess && ( eLangType != LANGUAGE_ENGLISH_US ) )
|
|
{
|
|
// Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value;
|
|
uno::Reference< 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 )
|
|
{
|
|
// cut time
|
|
if ( fResult > 0.0 )
|
|
{
|
|
fResult = floor( fResult );
|
|
}
|
|
else
|
|
{
|
|
fResult = ceil( fResult );
|
|
}
|
|
}
|
|
rPar.Get(0)->PutDate( fResult );
|
|
}
|
|
else
|
|
{
|
|
StarBASIC::Error( SbERR_CONVERSION );
|
|
}
|
|
// #39629 pFormatter can be requested itself
|
|
if( !GetSbData()->pInst )
|
|
{
|
|
delete pFormatter;
|
|
}
|
|
}
|
|
}
|
|
|
|
RTLFUNC(TimeValue)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
SvNumberFormatter* pFormatter = NULL;
|
|
if( GetSbData()->pInst )
|
|
pFormatter = GetSbData()->pInst->GetNumberFormatter();
|
|
else
|
|
{
|
|
sal_uInt32 n;
|
|
SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
|
|
}
|
|
|
|
sal_uInt32 nIndex;
|
|
double fResult;
|
|
sal_Bool bSuccess = pFormatter->IsNumberFormat( rPar.Get(1)->GetOUString(),
|
|
nIndex, fResult );
|
|
short nType = pFormatter->GetType(nIndex);
|
|
if(bSuccess && (nType==NUMBERFORMAT_TIME||nType==NUMBERFORMAT_DATETIME))
|
|
{
|
|
if ( nType == NUMBERFORMAT_DATETIME )
|
|
{
|
|
// cut days
|
|
fResult = fmod( fResult, 1 );
|
|
}
|
|
rPar.Get(0)->PutDate( fResult );
|
|
}
|
|
else
|
|
{
|
|
StarBASIC::Error( SbERR_CONVERSION );
|
|
}
|
|
if( !GetSbData()->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 );
|
|
}
|
|
}
|
|
|
|
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( Date::SYSTEM );
|
|
Time aTime( Time::SYSTEM );
|
|
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( Time::SYSTEM );
|
|
SbxVariable* pMeth = rPar.Get( 0 );
|
|
OUString 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 = rtl::OUString::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;
|
|
|
|
SvNumberFormatter* pFormatter = NULL;
|
|
sal_uInt32 nIndex;
|
|
if( GetSbData()->pInst )
|
|
{
|
|
pFormatter = GetSbData()->pInst->GetNumberFormatter();
|
|
nIndex = GetSbData()->pInst->GetStdTimeIdx();
|
|
}
|
|
else
|
|
{
|
|
sal_uInt32 n; // Dummy
|
|
SbiInstance::PrepareNumberFormatter( pFormatter, n, nIndex, n );
|
|
}
|
|
|
|
pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
|
|
|
|
if( !GetSbData()->pInst )
|
|
{
|
|
delete pFormatter;
|
|
}
|
|
}
|
|
pMeth->PutString( aRes );
|
|
}
|
|
else
|
|
{
|
|
StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Timer)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
Time aTime( Time::SYSTEM );
|
|
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( Date::SYSTEM );
|
|
double nDays = (double)GetDayDiff( aToday );
|
|
SbxVariable* pMeth = rPar.Get( 0 );
|
|
if( pMeth->IsString() )
|
|
{
|
|
OUString aRes;
|
|
Color* pCol;
|
|
|
|
SvNumberFormatter* pFormatter = NULL;
|
|
sal_uInt32 nIndex;
|
|
if( GetSbData()->pInst )
|
|
{
|
|
pFormatter = GetSbData()->pInst->GetNumberFormatter();
|
|
nIndex = GetSbData()->pInst->GetStdDateIdx();
|
|
}
|
|
else
|
|
{
|
|
sal_uInt32 n;
|
|
SbiInstance::PrepareNumberFormatter( pFormatter, nIndex, n, n );
|
|
}
|
|
|
|
pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
|
|
pMeth->PutString( aRes );
|
|
|
|
if( !GetSbData()->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 only string is converted, all other types result in 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 )
|
|
{
|
|
SbxError nPrevError = SbxBase::GetError();
|
|
SbxBase::ResetError();
|
|
|
|
// force conversion of the parameter to SbxDATE
|
|
xArg->SbxValue::GetDate();
|
|
|
|
bDate = !SbxBase::IsError();
|
|
|
|
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 );
|
|
}
|
|
}
|
|
uno::Reference< script::XErrorQuery > xError;
|
|
if ( pObj )
|
|
{
|
|
xError.set( pObj->getUnoAny(), uno::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 because of Uno-objects return true
|
|
// even if the pObj value is NULL
|
|
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() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
RTLFUNC(IsMissing)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() < 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
// #57915 Missing is reported by an error
|
|
rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
|
|
}
|
|
}
|
|
|
|
// Function looks for wildcards, removes them and always returns the pure path
|
|
OUString implSetupWildcard( const OUString& rFileParam, SbiRTLData* pRTLData )
|
|
{
|
|
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 = OUString();
|
|
|
|
OUString aFileParam = rFileParam;
|
|
sal_Int32 nLastWild = aFileParam.lastIndexOf( cWild1 );
|
|
if( nLastWild < 0 )
|
|
{
|
|
nLastWild = aFileParam.lastIndexOf( cWild2 );
|
|
}
|
|
bool bHasWildcards = ( nLastWild >= 0 );
|
|
|
|
|
|
sal_Int32 nLastDelim = aFileParam.lastIndexOf( cDelim1 );
|
|
if( nLastDelim < 0 )
|
|
{
|
|
nLastDelim = aFileParam.lastIndexOf( cDelim2 );
|
|
}
|
|
if( bHasWildcards )
|
|
{
|
|
// Wildcards in path?
|
|
if( nLastDelim >= 0 && nLastDelim > nLastWild )
|
|
{
|
|
return aFileParam;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OUString aPathStr = getFullPath( aFileParam );
|
|
if( nLastDelim != aFileParam.getLength() - 1 )
|
|
{
|
|
pRTLData->sFullNameToBeChecked = aPathStr;
|
|
}
|
|
return aPathStr;
|
|
}
|
|
|
|
OUString aPureFileName;
|
|
if( nLastDelim < 0 )
|
|
{
|
|
aPureFileName = aFileParam;
|
|
aFileParam = OUString();
|
|
}
|
|
else
|
|
{
|
|
aPureFileName = aFileParam.copy( nLastDelim + 1 );
|
|
aFileParam = aFileParam.copy( 0, nLastDelim );
|
|
}
|
|
|
|
// Try again to get a valid URL/UNC-path with only the path
|
|
OUString aPathStr = getFullPath( aFileParam );
|
|
|
|
// Is there a pure file name left? Otherwise the path is
|
|
// invalid anyway because it was not accepted by OSL before
|
|
if (string::equals(aPureFileName, '*'))
|
|
{
|
|
pRTLData->pWildCard = new WildCard( aPureFileName );
|
|
}
|
|
return aPathStr;
|
|
}
|
|
|
|
inline sal_Bool implCheckWildcard( const OUString& rName, SbiRTLData* pRTLData )
|
|
{
|
|
sal_Bool bMatch = sal_True;
|
|
|
|
if( pRTLData->pWildCard )
|
|
{
|
|
bMatch = pRTLData->pWildCard->Matches( rName );
|
|
}
|
|
return bMatch;
|
|
}
|
|
|
|
|
|
bool isRootDir( OUString aDirURLStr )
|
|
{
|
|
INetURLObject aDirURLObj( aDirURLStr );
|
|
bool bRoot = false;
|
|
|
|
// Check if it's a root directory
|
|
sal_Int32 nCount = aDirURLObj.getSegmentCount();
|
|
|
|
// No segment means Unix root directory "file:///"
|
|
if( nCount == 0 )
|
|
{
|
|
bRoot = true;
|
|
}
|
|
// Exactly one segment needs further checking, because it
|
|
// can be Unix "file:///foo/" -> no root
|
|
// or Windows "file:///c:/" -> root
|
|
else if( nCount == 1 )
|
|
{
|
|
OUString aSeg1 = aDirURLObj.getName( 0, sal_True,
|
|
INetURLObject::DECODE_WITH_CHARSET );
|
|
if( aSeg1[1] == (sal_Unicode)':' )
|
|
{
|
|
bRoot = true;
|
|
}
|
|
}
|
|
// More than one segments can never be root
|
|
// so bRoot remains false
|
|
|
|
return bRoot;
|
|
}
|
|
|
|
RTLFUNC(Dir)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
OUString aPath;
|
|
|
|
sal_uInt16 nParCount = rPar.Count();
|
|
if( nParCount > 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
SbiRTLData* pRTLData = GetSbData()->pInst->GetRTLData();
|
|
|
|
// #34645: can also be called from the URL line via 'macro: Dir'
|
|
// there's no pRTLDate existing in that case and the method must be left
|
|
if( !pRTLData )
|
|
{
|
|
return;
|
|
}
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
if ( nParCount >= 2 )
|
|
{
|
|
OUString aFileParam = rPar.Get(1)->GetOUString();
|
|
|
|
OUString aFileURLStr = implSetupWildcard( aFileParam, pRTLData );
|
|
if( !pRTLData->sFullNameToBeChecked.isEmpty())
|
|
{
|
|
sal_Bool bExists = sal_False;
|
|
try { bExists = xSFI->exists( aFileURLStr ); }
|
|
catch(const Exception & ) {}
|
|
|
|
OUString aNameOnlyStr;
|
|
if( bExists )
|
|
{
|
|
INetURLObject aFileURL( aFileURLStr );
|
|
aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT,
|
|
true, INetURLObject::DECODE_WITH_CHARSET );
|
|
}
|
|
rPar.Get(0)->PutString( aNameOnlyStr );
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
OUString aDirURLStr;
|
|
sal_Bool bFolder = xSFI->isFolder( aFileURLStr );
|
|
|
|
if( bFolder )
|
|
{
|
|
aDirURLStr = aFileURLStr;
|
|
}
|
|
else
|
|
{
|
|
OUString 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 )
|
|
{
|
|
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(const Exception & )
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
if( pRTLData->aDirSeq.getLength() > 0 )
|
|
{
|
|
bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
|
|
|
|
SbiInstance* pInst = GetSbData()->pInst;
|
|
bool bCompatibility = ( pInst && pInst->IsCompatibility() );
|
|
for( ;; )
|
|
{
|
|
if( pRTLData->nCurDirPos < 0 )
|
|
{
|
|
if( pRTLData->nCurDirPos == -2 )
|
|
{
|
|
aPath = ::rtl::OUString("." );
|
|
}
|
|
else if( pRTLData->nCurDirPos == -1 )
|
|
{
|
|
aPath = ::rtl::OUString(".." );
|
|
}
|
|
pRTLData->nCurDirPos++;
|
|
}
|
|
else if( pRTLData->nCurDirPos >= pRTLData->aDirSeq.getLength() )
|
|
{
|
|
pRTLData->aDirSeq.realloc( 0 );
|
|
aPath = "";
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
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 )
|
|
{
|
|
OUString aFileParam = rPar.Get(1)->GetOUString();
|
|
|
|
OUString aDirURL = implSetupWildcard( aFileParam, pRTLData );
|
|
|
|
sal_uInt16 nFlags = 0;
|
|
if ( nParCount > 2 )
|
|
{
|
|
pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
|
|
}
|
|
else
|
|
{
|
|
pRTLData->nDirFlags = 0;
|
|
}
|
|
|
|
// Read directory
|
|
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( OUString() );
|
|
return;
|
|
}
|
|
|
|
// #86950 Add "." and ".." directories for VB compatibility
|
|
pRTLData->nCurDirPos = 0;
|
|
if( bIncludeFolders )
|
|
{
|
|
bool bRoot = isRootDir( aDirURL );
|
|
|
|
// If it's no root directory we flag the need for
|
|
// the "." and ".." directories by the value -2
|
|
// for the actual position. Later for -2 will be
|
|
// returned "." and for -1 ".."
|
|
if( !bRoot )
|
|
{
|
|
pRTLData->nCurDirPos = -2;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if( pRTLData->pDir )
|
|
{
|
|
bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
|
|
for( ;; )
|
|
{
|
|
if( pRTLData->nCurDirPos < 0 )
|
|
{
|
|
if( pRTLData->nCurDirPos == -2 )
|
|
{
|
|
aPath = ::rtl::OUString("." );
|
|
}
|
|
else if( pRTLData->nCurDirPos == -1 )
|
|
{
|
|
aPath = ::rtl::OUString(".." );
|
|
}
|
|
pRTLData->nCurDirPos++;
|
|
}
|
|
else
|
|
{
|
|
DirectoryItem aItem;
|
|
FileBase::RC nRet = pRTLData->pDir->getNextItem( aItem );
|
|
if( nRet != FileBase::E_None )
|
|
{
|
|
delete pRTLData->pDir;
|
|
pRTLData->pDir = NULL;
|
|
aPath = "";
|
|
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();
|
|
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)->GetOUString() );
|
|
aEntry.ToAbs();
|
|
|
|
// #57064 extract the real-path for virtual URLs
|
|
OString aByteStrFullPath(rtl::OUStringToOString(aEntry.GetFull(),
|
|
osl_getThreadTextEncoding()));
|
|
DWORD nRealFlags = GetFileAttributes (aByteStrFullPath.getStr());
|
|
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() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
OUString aPath = getFullPath( rPar.Get(1)->GetOUString() );
|
|
sal_Bool bExists = sal_False;
|
|
try { bExists = xSFI->exists( aPath ); }
|
|
catch(const 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 |= Sb_ATTR_READONLY;
|
|
}
|
|
if( bHidden )
|
|
{
|
|
nFlags |= Sb_ATTR_HIDDEN;
|
|
}
|
|
if( bDirectory )
|
|
{
|
|
nFlags |= Sb_ATTR_DIRECTORY;
|
|
}
|
|
}
|
|
catch(const Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DirectoryItem aItem;
|
|
DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetOUString() ), aItem );
|
|
FileStatus aFileStatus( osl_FileStatus_Mask_Attributes | osl_FileStatus_Mask_Type );
|
|
aItem.getFileStatus( aFileStatus );
|
|
sal_uInt64 nAttributes = aFileStatus.getAttributes();
|
|
bool bReadOnly = (nAttributes & osl_File_Attribute_ReadOnly) != 0;
|
|
|
|
FileStatus::Type aType = aFileStatus.getFileType();
|
|
bool bDirectory = isFolder( aType );
|
|
if( bReadOnly )
|
|
{
|
|
nFlags |= Sb_ATTR_READONLY;
|
|
}
|
|
if( bDirectory )
|
|
{
|
|
nFlags |= Sb_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
|
|
{
|
|
OUString aPath = rPar.Get(1)->GetOUString();
|
|
Time aTime( Time::EMPTY );
|
|
Date aDate( Date::EMPTY );
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
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(const 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;
|
|
|
|
SvNumberFormatter* pFormatter = NULL;
|
|
sal_uInt32 nIndex;
|
|
if( GetSbData()->pInst )
|
|
{
|
|
pFormatter = GetSbData()->pInst->GetNumberFormatter();
|
|
nIndex = GetSbData()->pInst->GetStdDateTimeIdx();
|
|
}
|
|
else
|
|
{
|
|
sal_uInt32 n;
|
|
SbiInstance::PrepareNumberFormatter( pFormatter, n, n, nIndex );
|
|
}
|
|
|
|
OUString aRes;
|
|
pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol );
|
|
rPar.Get(0)->PutString( aRes );
|
|
|
|
if( !GetSbData()->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 = GetSbData()->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; // can we read another character?
|
|
bIsEof = pSvStrm->IsEof();
|
|
if ( !bIsEof )
|
|
{
|
|
pSvStrm->SeekRel( -1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bIsEof = pSvStrm->IsEof(); // for binary data!
|
|
}
|
|
rPar.Get(0)->PutBool( bIsEof );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(FileAttr)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
// No changes for UCB
|
|
// #57064 Although this function doesn't operate with DirEntry, it is
|
|
// not touched by the adjustment to virtual URLs, as it only works on
|
|
// already opened files and the name doesn't matter there.
|
|
|
|
if ( rPar.Count() != 3 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
sal_Int16 nChannel = rPar.Get(1)->GetInteger();
|
|
SbiIoSystem* pIO = GetSbData()->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 = GetSbData()->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++; // block positions starting at 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 = GetSbData()->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 = GetSbData()->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 counts from 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 counts from 1, SvStreams count from 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
|
|
{
|
|
OUString aResult;
|
|
if( nArgCount == 2 )
|
|
{
|
|
rPar.Get(1)->Format( aResult );
|
|
}
|
|
else
|
|
{
|
|
OUString aFmt( rPar.Get(2)->GetOUString() );
|
|
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 (text mode applications OS/2, WIN95, WNT)
|
|
// HACK: The WindowStyle will be passed to
|
|
// Application::StartApp in Creator. 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;
|
|
|
|
OUString aCmdLine = rPar.Get(1)->GetOUString();
|
|
// attach additional parameters - everything must be parsed anyway
|
|
if( nArgCount >= 4 )
|
|
{
|
|
aCmdLine += " ";
|
|
aCmdLine += rPar.Get(3)->GetOUString();
|
|
}
|
|
else if( aCmdLine.isEmpty() )
|
|
{
|
|
// avaoid special treatment (empty list)
|
|
aCmdLine += " ";
|
|
}
|
|
sal_Int32 nLen = aCmdLine.getLength();
|
|
|
|
// #55735 if there are parameters, they have to be seperated
|
|
// #72471 also seperate the single parameters
|
|
std::list<String> aTokenList;
|
|
OUString aToken;
|
|
sal_Int32 i = 0;
|
|
sal_Unicode c;
|
|
while( i < nLen )
|
|
{
|
|
for ( ;; ++i )
|
|
{
|
|
c = aCmdLine[ i ];
|
|
if ( c != ' ' && c != '\t' )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( c == '\"' || c == '\'' )
|
|
{
|
|
sal_Int32 iFoundPos = aCmdLine.indexOf( c, i + 1 );
|
|
|
|
if( iFoundPos < 0 )
|
|
{
|
|
aToken = aCmdLine.copy( i);
|
|
i = nLen;
|
|
}
|
|
else
|
|
{
|
|
aToken = aCmdLine.copy( i + 1, (iFoundPos - i - 1) );
|
|
i = iFoundPos + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 iFoundSpacePos = aCmdLine.indexOf( ' ', i );
|
|
sal_Int32 iFoundTabPos = aCmdLine.indexOf( '\t', i );
|
|
sal_Int32 iFoundPos = iFoundSpacePos >= 0 ? iFoundTabPos >= 0 ? Min( iFoundSpacePos, iFoundTabPos ) : iFoundSpacePos : -1;
|
|
|
|
if( iFoundPos < 0 )
|
|
{
|
|
aToken = aCmdLine.copy( i );
|
|
i = nLen;
|
|
}
|
|
else
|
|
{
|
|
aToken = aCmdLine.copy( i, (iFoundPos - i) );
|
|
i = iFoundPos;
|
|
}
|
|
}
|
|
|
|
// insert into the list
|
|
aTokenList.push_back( aToken );
|
|
}
|
|
// #55735 / #72471 end
|
|
|
|
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 work parameter(s) up
|
|
std::list<String>::const_iterator iter = aTokenList.begin();
|
|
const OUString& rStr = *iter;
|
|
OUString aOUStrProg( rStr.getStr(), rStr.getLength() );
|
|
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 OUString& rParamStr = (*iter);
|
|
const OUString aTempStr( rParamStr.getStr(), rParamStr.getLength());
|
|
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;
|
|
}
|
|
|
|
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
|
|
OUString 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;
|
|
}
|
|
return rtl::OUString::createFromAscii(pTypeNames[nPos]);
|
|
}
|
|
|
|
String getObjectTypeName( SbxVariable* pVar )
|
|
{
|
|
OUString sRet( "Object" );
|
|
if ( pVar )
|
|
{
|
|
SbxBase* pObj = pVar->GetObject();
|
|
if( !pObj )
|
|
{
|
|
sRet = OUString("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
|
|
uno::Reference< XServiceInfo > xServInfo( aObj, uno::UNO_QUERY );
|
|
if ( xServInfo.is() )
|
|
{
|
|
// is this a VBA object ?
|
|
uno::Reference< ooo::vba::XHelperInterface > xVBA( aObj, uno::UNO_QUERY );
|
|
Sequence< rtl::OUString > sServices = xServInfo->getSupportedServiceNames();
|
|
if ( sServices.getLength() )
|
|
{
|
|
sRet = sServices[ 0 ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uno::Reference< bridge::oleautomation::XAutomationObject > xAutoMation( aObj, uno::UNO_QUERY );
|
|
if ( xAutoMation.is() )
|
|
{
|
|
uno::Reference< script::XInvocation > xInv( aObj, uno::UNO_QUERY );
|
|
if ( xInv.is() )
|
|
{
|
|
try
|
|
{
|
|
xInv->getValue( rtl::OUString( "$GetTypeName" ) ) >>= sRet;
|
|
}
|
|
catch(const 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();
|
|
bool bIsArray = ( ( eType & SbxARRAY ) != 0 );
|
|
|
|
OUString aRetStr;
|
|
if ( SbiRuntime::isVBAEnabled() && eType == SbxOBJECT )
|
|
{
|
|
aRetStr = getObjectTypeName( rPar.Get(1) );
|
|
}
|
|
else
|
|
{
|
|
aRetStr = getBasicTypeName( eType );
|
|
}
|
|
if( bIsArray )
|
|
{
|
|
aRetStr += "()";
|
|
}
|
|
rPar.Get(0)->PutString( aRetStr );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Len)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if ( rPar.Count() != 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
const OUString& rStr = rPar.Get(1)->GetOUString();
|
|
rPar.Get(0)->PutLong( rStr.getLength() );
|
|
}
|
|
}
|
|
|
|
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 OUString& rApp = rPar.Get(1)->GetOUString();
|
|
const OUString& rTopic = rPar.Get(2)->GetOUString();
|
|
|
|
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
|
|
size_t nChannel;
|
|
SbError nDdeErr = pDDE->Initiate( rApp, rTopic, nChannel );
|
|
if( nDdeErr )
|
|
{
|
|
StarBASIC::Error( nDdeErr );
|
|
}
|
|
else
|
|
{
|
|
rPar.Get(0)->PutInteger( (int)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;
|
|
}
|
|
size_t nChannel = rPar.Get(1)->GetInteger();
|
|
SbiDdeControl* pDDE = GetSbData()->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 = GetSbData()->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;
|
|
}
|
|
size_t nChannel = rPar.Get(1)->GetInteger();
|
|
const OUString& rItem = rPar.Get(2)->GetOUString();
|
|
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
|
|
OUString 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;
|
|
}
|
|
size_t nChannel = rPar.Get(1)->GetInteger();
|
|
const OUString& rCommand = rPar.Get(2)->GetOUString();
|
|
SbiDdeControl* pDDE = GetSbData()->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;
|
|
}
|
|
size_t nChannel = rPar.Get(1)->GetInteger();
|
|
const OUString& rItem = rPar.Get(2)->GetOUString();
|
|
const OUString& rData = rPar.Get(3)->GetOUString();
|
|
SbiDdeControl* pDDE = GetSbData()->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 = GetSbData()->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 = GetSbData()->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;
|
|
}
|
|
|
|
OUString aOldStr = rPar.Get(1)->GetOUString();
|
|
sal_Int32 nConversion = rPar.Get(2)->GetLong();
|
|
|
|
sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
|
|
|
|
sal_Int32 nOldLen = aOldStr.getLength();
|
|
if( nOldLen == 0 )
|
|
{
|
|
// null string,return
|
|
rPar.Get(0)->PutString(aOldStr);
|
|
return;
|
|
}
|
|
|
|
sal_Int32 nType = 0;
|
|
if ( (nConversion & 0x03) == 3 ) // vbProperCase
|
|
{
|
|
const CharClass& rCharClass = GetCharClass();
|
|
aOldStr = rCharClass.titlecase( aOldStr.toAsciiLowerCase(), 0, nOldLen );
|
|
}
|
|
else if ( (nConversion & 0x01) == 1 ) // vbUpperCase
|
|
{
|
|
nType |= i18n::TransliterationModules_LOWERCASE_UPPERCASE;
|
|
}
|
|
else if ( (nConversion & 0x02) == 2 ) // vbLowerCase
|
|
{
|
|
nType |= i18n::TransliterationModules_UPPERCASE_LOWERCASE;
|
|
}
|
|
if ( (nConversion & 0x04) == 4 ) // vbWide
|
|
{
|
|
nType |= i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
|
|
}
|
|
else if ( (nConversion & 0x08) == 8 ) // vbNarrow
|
|
{
|
|
nType |= i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
|
|
}
|
|
if ( (nConversion & 0x10) == 16) // vbKatakana
|
|
{
|
|
nType |= i18n::TransliterationModules_HIRAGANA_KATAKANA;
|
|
}
|
|
else if ( (nConversion & 0x20) == 32 ) // vbHiragana
|
|
{
|
|
nType |= i18n::TransliterationModules_KATAKANA_HIRAGANA;
|
|
}
|
|
OUString aNewStr( aOldStr );
|
|
if( nType != 0 )
|
|
{
|
|
uno::Reference< uno::XComponentContext > xContext = getProcessComponentContext();
|
|
::utl::TransliterationWrapper aTransliterationWrapper( xContext, nType );
|
|
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_Int32 nSize = aNewStr.getLength()*2;
|
|
const sal_Unicode* pSrc = aNewStr.getStr();
|
|
sal_Char* pChar = new sal_Char[nSize+1];
|
|
for( sal_Int32 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
|
|
OUString aOUStr = ::rtl::OStringToOUString(aOStr, osl_getThreadTextEncoding());
|
|
rPar.Get(0)->PutString( aOUStr );
|
|
return;
|
|
}
|
|
else if ( (nConversion & 0x80) == 128 ) // vbFromUnicode
|
|
{
|
|
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_Int32 nArraySize = 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_Int32 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;
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Load)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if( rPar.Count() != 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
|
|
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( OUString("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;
|
|
}
|
|
|
|
|
|
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( OUString("Unload"), SbxCLASS_METHOD );
|
|
if( pVar )
|
|
{
|
|
pVar->GetInteger();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RTLFUNC(LoadPicture)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
|
|
if( rPar.Count() != 2 )
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
return;
|
|
}
|
|
|
|
OUString aFileURL = getFullPath( rPar.Get(1)->GetOUString() );
|
|
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)->GetOUString(), 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; // delete bits 4-16
|
|
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;
|
|
|
|
OUString aMsg = rPar.Get(1)->GetOUString();
|
|
OUString aTitle;
|
|
if( nArgCount >= 4 )
|
|
{
|
|
aTitle = rPar.Get(3)->GetOUString();
|
|
}
|
|
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 )
|
|
{
|
|
OUString aStr = rPar.Get(1)->GetOUString();
|
|
sal_Int16 nFlags = rPar.Get(2)->GetInteger();
|
|
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
sal_Bool bReadOnly = (nFlags & Sb_ATTR_READONLY) != 0;
|
|
xSFI->setReadOnly( aStr, bReadOnly );
|
|
sal_Bool bHidden = (nFlags & Sb_ATTR_HIDDEN) != 0;
|
|
xSFI->setHidden( aStr, bHidden );
|
|
}
|
|
catch(const Exception & )
|
|
{
|
|
StarBASIC::Error( ERRCODE_IO_GENERAL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
}
|
|
}
|
|
|
|
RTLFUNC(Reset)
|
|
{
|
|
(void)pBasic;
|
|
(void)bWrite;
|
|
(void)rPar;
|
|
|
|
SbiIoSystem* pIO = GetSbData()->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 )->GetOUString(),
|
|
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 )
|
|
{
|
|
OUString aStr = rPar.Get(1)->GetOUString();
|
|
sal_Bool bExists = sal_False;
|
|
|
|
if( hasUno() )
|
|
{
|
|
uno::Reference< ucb::XSimpleFileAccess3 > xSFI = getFileAccess();
|
|
if( xSFI.is() )
|
|
{
|
|
try
|
|
{
|
|
bExists = xSFI->exists( aStr );
|
|
}
|
|
catch(const 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
|
|
OUString aBeforeStart = ::rtl::OUString::valueOf( nStart - 1 );
|
|
OUString aAfterStop = ::rtl::OUString::valueOf( nStop + 1 );
|
|
sal_Int32 nLen1 = aBeforeStart.getLength();
|
|
sal_Int32 nLen2 = aAfterStop.getLength();
|
|
sal_Int32 nLen = nLen1 >= nLen2 ? nLen1:nLen2;
|
|
|
|
OUStringBuffer aRetStr( nLen * 2 + 1);
|
|
OUString aLowerValue;
|
|
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( aRetStr.makeStringAndClear());
|
|
}
|
|
|
|
#endif
|
|
|
|
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; // adjustment VisualBasic: 1.Jan.1900 == 2
|
|
return nDiffDays;
|
|
}
|
|
|
|
sal_Int16 implGetDateYear( double aDate )
|
|
{
|
|
Date aRefDate( 1,1,1900 );
|
|
long nDays = (long) aDate;
|
|
nDays -= 2; // standardize: 1.1.1900 => 0.0
|
|
aRefDate += nDays;
|
|
sal_Int16 nRet = (sal_Int16)( aRefDate.GetYear() );
|
|
return nRet;
|
|
}
|
|
|
|
bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, double& rdRet )
|
|
{
|
|
#ifndef DISABLE_SCRIPTING
|
|
if ( nYear < 30 && SbiRuntime::isVBAEnabled() )
|
|
{
|
|
nYear += 2000;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if ( nYear < 100 )
|
|
{
|
|
nYear += 1900;
|
|
}
|
|
}
|
|
Date aCurDate( nDay, nMonth, nYear );
|
|
if ((nYear < 100 || nYear > 9999) )
|
|
{
|
|
#ifndef DISABLE_SCRIPTING
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifndef DISABLE_SCRIPTING
|
|
if ( !SbiRuntime::isVBAEnabled() )
|
|
#endif
|
|
{
|
|
if ( (nMonth < 1 || nMonth > 12 )||
|
|
(nDay < 1 || nDay > 31 ) )
|
|
{
|
|
#ifndef DISABLE_SCRIPTING
|
|
StarBASIC::Error( SbERR_BAD_ARGUMENT );
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
#ifndef DISABLE_SCRIPTING
|
|
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 );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
long nDiffDays = GetDayDiff( aCurDate );
|
|
rdRet = (double)nDiffDays;
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|