summaryrefslogtreecommitdiff
path: root/basic/source/runtime/methods.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/runtime/methods.cxx')
-rw-r--r--basic/source/runtime/methods.cxx2787
1 files changed, 1249 insertions, 1538 deletions
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index 7e9a1adcccd7..679414e10a14 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -24,11 +24,10 @@
#include <basic/sbuno.hxx>
#include <osl/process.h>
#include <vcl/dibtools.hxx>
-#include <vcl/window.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <vcl/sound.hxx>
-#include <tools/wintypes.hxx>
+#include <vcl/wintypes.hxx>
#include <vcl/stdtext.hxx>
#include <vcl/weld.hxx>
#include <basic/sbx.hxx>
@@ -45,6 +44,7 @@
#include <rtl/string.hxx>
#include <sal/log.hxx>
#include <comphelper/DirectoryHelper.hxx>
+#include <comphelper/lok.hxx>
#include <runtime.hxx>
#include <sbunoobj.hxx>
@@ -60,6 +60,7 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
#include <com/sun/star/script/XErrorQuery.hpp>
+#include <ooo/vba/VbStrConv.hpp>
#include <ooo/vba/VbTriState.hpp>
#include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
#include <memory>
@@ -68,20 +69,12 @@
#include <o3tl/char16_t2wchar_t.hxx>
// include search util
-#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/i18n/Transliteration.hpp>
#include <com/sun/star/util/SearchAlgorithms2.hpp>
#include <i18nutil/searchopt.hxx>
#include <unotools/textsearch.hxx>
#include <svl/numformat.hxx>
-
-
-using namespace comphelper;
-using namespace osl;
-using namespace com::sun::star;
-using namespace com::sun::star::lang;
-using namespace com::sun::star::uno;
-
#include <date.hxx>
#include <sbstdobj.hxx>
#include <rtlproto.hxx>
@@ -109,12 +102,24 @@ using namespace com::sun::star::uno;
#include <unistd.h>
#endif
-#include <com/sun/star/i18n/XCharacterClassification.hpp>
-#include <vcl/unohelp.hxx>
#include <vcl/TypeSerializer.hxx>
+using namespace comphelper;
+using namespace osl;
+using namespace com::sun::star;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+
+static sal_Int32 GetDayDiff(const Date& rDate) { return rDate - Date(1899'12'30); }
+
#if HAVE_FEATURE_SCRIPTING
+static sal_Int32 nanoSecToMilliSec(sal_Int64 nNanoSeconds)
+{
+ // Rounding nanoseconds to milliseconds precision to avoid comparison inaccuracies
+ return o3tl::convert(nNanoSeconds, 1, tools::Time::nanoPerMilli);
+}
+
static void FilterWhiteSpace( OUString& rStr )
{
if (rStr.isEmpty())
@@ -136,8 +141,6 @@ static void FilterWhiteSpace( OUString& rStr )
rStr = aRet.makeStringAndClear();
}
-static tools::Long GetDayDiff( const Date& rDate );
-
static const CharClass& GetCharClass()
{
static CharClass aCharClass( Application::GetSettings().GetLanguageTag() );
@@ -185,16 +188,17 @@ static uno::Reference< ucb::XSimpleFileAccess3 > const & getFileAccess()
void SbRtl_CreateObject(StarBASIC * pBasic, SbxArray & rPar, bool)
{
+ if( rPar.Count() < 2 )
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
OUString aClass(rPar.Get(1)->GetOUString());
SbxObjectRef p = SbxBase::CreateObject( aClass );
if( !p.is() )
- StarBASIC::Error( ERRCODE_BASIC_CANNOT_LOAD );
- else
- {
- // Convenience: enter BASIC as parent
- p->SetParent( pBasic );
- rPar.Get(0)->PutObject(p.get());
- }
+ return StarBASIC::Error( ERRCODE_BASIC_CANNOT_LOAD );
+
+ // Convenience: enter BASIC as parent
+ p->SetParent( pBasic );
+ rPar.Get(0)->PutObject(p.get());
}
// Error( n )
@@ -202,54 +206,51 @@ void SbRtl_CreateObject(StarBASIC * pBasic, SbxArray & rPar, bool)
void SbRtl_Error(StarBASIC * pBasic, SbxArray & rPar, bool)
{
if( !pBasic )
- StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR );
+ return StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR );
+
+ OUString aErrorMsg;
+ ErrCode nErr = ERRCODE_NONE;
+ sal_Int32 nCode = 0;
+ if (rPar.Count() == 1)
+ {
+ nErr = StarBASIC::GetErrBasic();
+ aErrorMsg = StarBASIC::GetErrorMsg();
+ }
else
{
- OUString aErrorMsg;
- ErrCode nErr = ERRCODE_NONE;
- sal_Int32 nCode = 0;
- if (rPar.Count() == 1)
+ nCode = rPar.Get(1)->GetLong();
+ if( nCode > 65535 )
{
- nErr = StarBASIC::GetErrBasic();
- aErrorMsg = StarBASIC::GetErrorMsg();
- }
- else
- {
- nCode = rPar.Get(1)->GetLong();
- if( nCode > 65535 )
- {
- StarBASIC::Error( ERRCODE_BASIC_CONVERSION );
- }
- else
- {
- nErr = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(nCode) );
- }
- }
-
- bool bVBA = SbiRuntime::isVBAEnabled();
- OUString tmpErrMsg;
- if( bVBA && !aErrorMsg.isEmpty())
- {
- tmpErrMsg = aErrorMsg;
+ StarBASIC::Error( ERRCODE_BASIC_CONVERSION );
}
else
{
- StarBASIC::MakeErrorText( nErr, aErrorMsg );
- tmpErrMsg = StarBASIC::GetErrorText();
+ nErr = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(nCode) );
}
- // If this rtlfunc 'Error' passed an 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)
+ }
+ bool bVBA = SbiRuntime::isVBAEnabled();
+ OUString tmpErrMsg;
+ if( bVBA && !aErrorMsg.isEmpty())
+ {
+ tmpErrMsg = aErrorMsg;
+ }
+ else
+ {
+ StarBASIC::MakeErrorText( nErr, aErrorMsg );
+ tmpErrMsg = StarBASIC::GetErrorText();
+ }
+ // If this rtlfunc 'Error' passed an 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() )
{
- uno::Reference< ooo::vba::XErrObject > xErrObj( SbxErrObject::getUnoErrObject() );
- if ( xErrObj.is() && xErrObj->getNumber() == nCode && !xErrObj->getDescription().isEmpty() )
- {
- tmpErrMsg = xErrObj->getDescription();
- }
+ tmpErrMsg = xErrObj->getDescription();
}
- rPar.Get(0)->PutString(tmpErrMsg);
}
+ rPar.Get(0)->PutString(tmpErrMsg);
}
// Sinus
@@ -257,106 +258,87 @@ void SbRtl_Error(StarBASIC * pBasic, SbxArray & rPar, bool)
void SbRtl_Sin(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- rPar.Get(0)->PutDouble(sin(pArg->GetDouble()));
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+ rPar.Get(0)->PutDouble(sin(pArg->GetDouble()));
}
void SbRtl_Cos(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- rPar.Get(0)->PutDouble(cos(pArg->GetDouble()));
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+ rPar.Get(0)->PutDouble(cos(pArg->GetDouble()));
}
void SbRtl_Atn(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- rPar.Get(0)->PutDouble(atan(pArg->GetDouble()));
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+ rPar.Get(0)->PutDouble(atan(pArg->GetDouble()));
}
void SbRtl_Abs(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- rPar.Get(0)->PutDouble(fabs(pArg->GetDouble()));
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+ rPar.Get(0)->PutDouble(fabs(pArg->GetDouble()));
}
void SbRtl_Asc(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+ OUString aStr( pArg->GetOUString() );
+ if ( aStr.isEmpty())
{
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ rPar.Get(0)->PutEmpty();
+ return;
}
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- OUString aStr( pArg->GetOUString() );
- if ( aStr.isEmpty())
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- rPar.Get(0)->PutEmpty();
- }
- else
- {
- sal_Unicode aCh = aStr[0];
- rPar.Get(0)->PutLong(aCh);
- }
- }
+ sal_Unicode aCh = aStr[0];
+ rPar.Get(0)->PutLong(aCh);
}
static void implChr( SbxArray& rPar, bool bChrW )
{
if (rPar.Count() < 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+
+ OUString aStr;
+ if( !bChrW && SbiRuntime::isVBAEnabled() )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ char c = static_cast<char>(pArg->GetByte());
+ aStr = OUString(&c, 1, osl_getThreadTextEncoding());
}
else
{
- SbxVariableRef pArg = rPar.Get(1);
-
- OUString aStr;
- if( !bChrW && SbiRuntime::isVBAEnabled() )
- {
- char c = static_cast<char>(pArg->GetByte());
- aStr = OUString(&c, 1, osl_getThreadTextEncoding());
- }
- else
+ // Map negative 16-bit values to large positive ones, so that code like Chr(&H8000)
+ // still works after the fix for tdf#62326 changed those four-digit hex notations to
+ // produce negative values:
+ sal_Int32 aCh = pArg->GetLong();
+ if (aCh < -0x8000 || aCh > 0xFFFF)
{
- // Map negative 16-bit values to large positive ones, so that code like Chr(&H8000)
- // still works after the fix for tdf#62326 changed those four-digit hex notations to
- // produce negative values:
- sal_Int32 aCh = pArg->GetLong();
- if (aCh < -0x8000 || aCh > 0xFFFF) {
- StarBASIC::Error(ERRCODE_BASIC_MATH_OVERFLOW);
- aCh = 0;
- }
- aStr = OUString(static_cast<sal_Unicode>(aCh));
+ StarBASIC::Error(ERRCODE_BASIC_MATH_OVERFLOW);
+ aCh = 0;
}
- rPar.Get(0)->PutString(aStr);
+ aStr = OUString(static_cast<sal_Unicode>(aCh));
}
+ rPar.Get(0)->PutString(aStr);
}
void SbRtl_Chr(StarBASIC *, SbxArray & rPar, bool)
@@ -396,22 +378,21 @@ void SbRtl_CurDir(StarBASIC *, SbxArray & rPar, bool)
// there's no possibility to detect the current one in a way that a virtual URL
// could be delivered.
+ if (rPar.Count() > 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
#if defined(_WIN32)
int nCurDir = 0; // Current dir // JSM
if (rPar.Count() == 2)
{
OUString aDrive = rPar.Get(1)->GetOUString();
if ( aDrive.getLength() != 1 )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
auto c = rtl::toAsciiUpperCase(aDrive[0]);
if ( !rtl::isAsciiUpperCase( c ) )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
nCurDir = c - 'A' + 1;
}
wchar_t pBuffer[ _MAX_PATH ];
@@ -421,14 +402,10 @@ void SbRtl_CurDir(StarBASIC *, SbxArray & rPar, bool)
auto const handler = _set_thread_local_invalid_parameter_handler(&invalidParameterHandler);
auto const ok = _wgetdcwd( nCurDir, pBuffer, _MAX_PATH ) != nullptr;
_set_thread_local_invalid_parameter_handler(handler);
- if ( ok )
- {
- rPar.Get(0)->PutString(OUString(o3tl::toU(pBuffer)));
- }
- else
- {
- StarBASIC::Error( ERRCODE_BASIC_NO_DEVICE );
- }
+ if ( !ok )
+ return StarBASIC::Error( ERRCODE_BASIC_NO_DEVICE );
+
+ rPar.Get(0)->PutString(OUString(o3tl::toU(pBuffer)));
#else
@@ -440,20 +417,16 @@ void SbRtl_CurDir(StarBASIC *, SbxArray & rPar, bool)
{
pMem.reset(new char[nSize]);
if( !pMem )
- {
- StarBASIC::Error( ERRCODE_BASIC_NO_MEMORY );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_NO_MEMORY );
+
if( getcwd( pMem.get(), nSize-1 ) != nullptr )
{
rPar.Get(0)->PutString(OUString::createFromAscii(pMem.get()));
return;
}
if( errno != ERANGE )
- {
- StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR );
+
nSize += PATH_INCR;
};
@@ -463,18 +436,14 @@ void SbRtl_CurDir(StarBASIC *, SbxArray & rPar, bool)
void SbRtl_ChDir(StarBASIC * pBasic, SbxArray & rPar, bool)
{
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
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ // VBA: track current directory per document type (separately for Writer, Calc, Impress, etc.)
+ if( SbiRuntime::isVBAEnabled() )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ ::basic::vba::registerCurrentDirectory(getDocumentModel(pBasic),
+ rPar.Get(1)->GetOUString());
}
}
@@ -482,9 +451,7 @@ void SbRtl_ChDrive(StarBASIC *, SbxArray & rPar, bool)
{
rPar.Get(0)->PutEmpty();
if (rPar.Count() != 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
@@ -533,129 +500,119 @@ void implStepRenameOSL( const OUString& aSource, const OUString& aDest )
void SbRtl_FileCopy(StarBASIC *, SbxArray & rPar, bool)
{
rPar.Get(0)->PutEmpty();
- if (rPar.Count() == 3)
+ if (rPar.Count() != 3)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ OUString aSource = rPar.Get(1)->GetOUString();
+ OUString aDest = rPar.Get(2)->GetOUString();
+ if( hasUno() )
{
- OUString aSource = rPar.Get(1)->GetOUString();
- OUString aDest = rPar.Get(2)->GetOUString();
- if( hasUno() )
+ const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
+ if( xSFI.is() )
{
- const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
- if( xSFI.is() )
+ try
{
- try
- {
- xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) );
- }
- catch(const Exception & )
- {
- StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
- }
+ xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) );
}
- }
- else
- {
- FileBase::RC nRet = File::copy( getFullPath( aSource ), getFullPath( aDest ) );
- if( nRet != FileBase::E_None )
+ catch(const Exception & )
{
StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
}
}
}
else
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ {
+ FileBase::RC nRet = File::copy( getFullPath( aSource ), getFullPath( aDest ) );
+ if( nRet != FileBase::E_None )
+ {
+ StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
+ }
+ }
}
void SbRtl_Kill(StarBASIC *, SbxArray & rPar, bool)
{
rPar.Get(0)->PutEmpty();
- if (rPar.Count() == 2)
- {
- OUString aFileSpec = rPar.Get(1)->GetOUString();
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- if( hasUno() )
+ OUString aFileSpec = rPar.Get(1)->GetOUString();
+
+ if( hasUno() )
+ {
+ const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
+ if( xSFI.is() )
{
- const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
- if( xSFI.is() )
+ OUString aFullPath = getFullPath( aFileSpec );
+ if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) )
{
- OUString aFullPath = getFullPath( aFileSpec );
- if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) )
- {
- StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
- return;
- }
- try
- {
- xSFI->kill( aFullPath );
- }
- catch(const Exception & )
- {
- StarBASIC::Error( ERRCODE_IO_GENERAL );
- }
+ StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
+ return;
+ }
+ try
+ {
+ xSFI->kill( aFullPath );
+ }
+ catch(const Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
}
- }
- else
- {
- File::remove( getFullPath( aFileSpec ) );
}
}
else
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ File::remove( getFullPath( aFileSpec ) );
}
}
void SbRtl_MkDir(StarBASIC * pBasic, SbxArray & rPar, bool bWrite)
{
rPar.Get(0)->PutEmpty();
- if (rPar.Count() == 2)
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ OUString aPath = rPar.Get(1)->GetOUString();
+ if ( SbiRuntime::isVBAEnabled() )
{
- OUString aPath = rPar.Get(1)->GetOUString();
- if ( SbiRuntime::isVBAEnabled() )
+ // In vba if the full path is not specified then
+ // folder is created relative to the curdir
+ INetURLObject aURLObj( getFullPath( aPath ) );
+ if ( aURLObj.GetProtocol() != INetProtocol::File )
{
- // In vba if the full path is not specified then
- // folder is created relative to the curdir
- INetURLObject aURLObj( getFullPath( aPath ) );
- if ( aURLObj.GetProtocol() != INetProtocol::File )
- {
- SbxArrayRef pPar = new SbxArray();
- SbxVariableRef pResult = new SbxVariable();
- SbxVariableRef pParam = new SbxVariable();
- pPar->Insert(pResult.get(), pPar->Count());
- pPar->Insert(pParam.get(), pPar->Count());
- SbRtl_CurDir( pBasic, *pPar, bWrite );
-
- OUString sCurPathURL;
- File::getFileURLFromSystemPath(pPar->Get(0)->GetOUString(), sCurPathURL);
-
- aURLObj.SetURL( sCurPathURL );
- aURLObj.Append( aPath );
- File::getSystemPathFromFileURL(aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ),aPath ) ;
- }
+ SbxArrayRef pPar = new SbxArray();
+ SbxVariableRef pResult = new SbxVariable();
+ SbxVariableRef pParam = new SbxVariable();
+ pPar->Insert(pResult.get(), pPar->Count());
+ pPar->Insert(pParam.get(), pPar->Count());
+ SbRtl_CurDir( pBasic, *pPar, bWrite );
+
+ OUString sCurPathURL;
+ File::getFileURLFromSystemPath(pPar->Get(0)->GetOUString(), sCurPathURL);
+
+ aURLObj.SetURL( sCurPathURL );
+ aURLObj.Append( aPath );
+ File::getSystemPathFromFileURL(aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ),aPath ) ;
}
+ }
- if( hasUno() )
+ if( hasUno() )
+ {
+ const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
+ if( xSFI.is() )
{
- const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
- if( xSFI.is() )
+ try
{
- try
- {
- xSFI->createFolder( getFullPath( aPath ) );
- }
- catch(const Exception & )
- {
- StarBASIC::Error( ERRCODE_IO_GENERAL );
- }
+ xSFI->createFolder( getFullPath( aPath ) );
+ }
+ catch(const Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
}
- }
- else
- {
- Directory::create( getFullPath( aPath ) );
}
}
else
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ Directory::create( getFullPath( aPath ) );
}
}
@@ -673,16 +630,14 @@ static void implRemoveDirRecursive( const OUString& aDirPath )
if( !bExists || !bFolder )
{
- StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
}
Directory aDir( aDirPath );
nRet = aDir.open();
if( nRet != FileBase::E_None )
{
- StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
}
aDir.close();
@@ -693,49 +648,43 @@ static void implRemoveDirRecursive( const OUString& aDirPath )
void SbRtl_RmDir(StarBASIC *, SbxArray & rPar, bool)
{
rPar.Get(0)->PutEmpty();
- if (rPar.Count() == 2)
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ OUString aPath = rPar.Get(1)->GetOUString();
+ if( hasUno() )
{
- OUString aPath = rPar.Get(1)->GetOUString();
- if( hasUno() )
+ const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
+ if( xSFI.is() )
{
- const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
- if( xSFI.is() )
+ try
{
- try
+ if( !xSFI->isFolder( aPath ) )
{
- if( !xSFI->isFolder( aPath ) )
- {
- StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
- return;
- }
- SbiInstance* pInst = GetSbData()->pInst;
- bool bCompatibility = ( pInst && pInst->IsCompatibility() );
- if( bCompatibility )
- {
- Sequence< OUString > aContent = xSFI->getFolderContents( aPath, true );
- if( aContent.hasElements() )
- {
- StarBASIC::Error( ERRCODE_BASIC_ACCESS_ERROR );
- return;
- }
- }
-
- xSFI->kill( getFullPath( aPath ) );
+ return StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND );
}
- catch(const Exception & )
+ SbiInstance* pInst = GetSbData()->pInst;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
{
- StarBASIC::Error( ERRCODE_IO_GENERAL );
+ Sequence< OUString > aContent = xSFI->getFolderContents( aPath, true );
+ if( aContent.hasElements() )
+ {
+ return StarBASIC::Error( ERRCODE_BASIC_ACCESS_ERROR );
+ }
}
+
+ xSFI->kill( getFullPath( aPath ) );
+ }
+ catch(const Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
}
- }
- else
- {
- implRemoveDirRecursive( getFullPath( aPath ) );
}
}
else
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ implRemoveDirRecursive( getFullPath( aPath ) );
}
}
@@ -748,91 +697,79 @@ void SbRtl_SendKeys(StarBASIC *, SbxArray & rPar, bool)
void SbRtl_Exp(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- else
- {
- double aDouble = rPar.Get(1)->GetDouble();
- aDouble = exp( aDouble );
- checkArithmeticOverflow( aDouble );
- rPar.Get(0)->PutDouble(aDouble);
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ double aDouble = rPar.Get(1)->GetDouble();
+ aDouble = exp( aDouble );
+ checkArithmeticOverflow( aDouble );
+ rPar.Get(0)->PutDouble(aDouble);
}
void SbRtl_FileLen(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- else
+
+ SbxVariableRef pArg = rPar.Get(1);
+ OUString aStr( pArg->GetOUString() );
+ sal_Int32 nLen = 0;
+ if( hasUno() )
{
- SbxVariableRef pArg = rPar.Get(1);
- OUString aStr( pArg->GetOUString() );
- sal_Int32 nLen = 0;
- if( hasUno() )
+ const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
+ if( xSFI.is() )
{
- const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = getFileAccess();
- if( xSFI.is() )
+ try
{
- try
- {
- nLen = xSFI->getSize( getFullPath( aStr ) );
- }
- catch(const Exception & )
- {
- StarBASIC::Error( ERRCODE_IO_GENERAL );
- }
+ nLen = xSFI->getSize( getFullPath( aStr ) );
+ }
+ catch(const Exception & )
+ {
+ StarBASIC::Error( ERRCODE_IO_GENERAL );
}
}
- else
- {
- DirectoryItem aItem;
- (void)DirectoryItem::get( getFullPath( aStr ), aItem );
- FileStatus aFileStatus( osl_FileStatus_Mask_FileSize );
- (void)aItem.getFileStatus( aFileStatus );
- nLen = static_cast<sal_Int32>(aFileStatus.getFileSize());
- }
- rPar.Get(0)->PutLong(static_cast<tools::Long>(nLen));
}
+ else
+ {
+ DirectoryItem aItem;
+ (void)DirectoryItem::get( getFullPath( aStr ), aItem );
+ FileStatus aFileStatus( osl_FileStatus_Mask_FileSize );
+ (void)aItem.getFileStatus( aFileStatus );
+ nLen = static_cast<sal_Int32>(aFileStatus.getFileSize());
+ }
+ rPar.Get(0)->PutLong(nLen);
}
+
void SbRtl_Hex(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_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());
- OUString aStr(OUString::number( nVal, 16 ));
- aStr = aStr.toAsciiUpperCase();
- rPar.Get(0)->PutString(aStr);
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
+
+ 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(OUString::number(nVal, 16).toAsciiUpperCase());
}
void SbRtl_FuncCaller(StarBASIC *, SbxArray & rPar, bool)
{
- 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;
- }
- }
+ if (!SbiRuntime::isVBAEnabled() || GetSbData()->pInst == nullptr || GetSbData()->pInst->pRun == nullptr)
+ return StarBASIC::Error(ERRCODE_BASIC_NOT_IMPLEMENTED);
+
+ if ( GetSbData()->pInst->pRun->GetExternalCaller() )
+ *rPar.Get(0) = *GetSbData()->pInst->pRun->GetExternalCaller();
else
{
- StarBASIC::Error( ERRCODE_BASIC_NOT_IMPLEMENTED );
+ SbxVariableRef pVar = new SbxVariable(SbxVARIANT);
+ *rPar.Get(0) = *pVar;
}
-
}
// InStr( [start],string,string,[compare] )
@@ -840,79 +777,77 @@ void SbRtl_InStr(StarBASIC *, SbxArray & rPar, bool)
{
const sal_uInt32 nArgCount = rPar.Count() - 1;
if ( nArgCount < 2 )
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- else
- {
- sal_Int32 nStartPos = 1;
- sal_Int32 nFirstStringPos = 1;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- if ( nArgCount >= 3 )
- {
- nStartPos = rPar.Get(1)->GetLong();
- if( nStartPos <= 0 )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- nStartPos = 1;
- }
- nFirstStringPos++;
- }
+ sal_Int32 nStartPos = 1;
+ sal_Int32 nFirstStringPos = 1;
- SbiInstance* pInst = GetSbData()->pInst;
- bool bTextMode;
- bool bCompatibility = ( pInst && pInst->IsCompatibility() );
- if( bCompatibility )
- {
- SbiRuntime* pRT = pInst->pRun;
- bTextMode = pRT && pRT->IsImageFlag( SbiImageFlags::COMPARETEXT );
- }
- else
- {
- bTextMode = true;
- }
- if ( nArgCount == 4 )
+ if ( nArgCount >= 3 )
+ {
+ nStartPos = rPar.Get(1)->GetLong();
+ if( nStartPos <= 0 )
{
- bTextMode = rPar.Get(4)->GetInteger();
+ StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ nStartPos = 1;
}
- sal_Int32 nPos;
- const OUString& rToken = rPar.Get(nFirstStringPos + 1)->GetOUString();
+ nFirstStringPos++;
+ }
- // #97545 Always find empty string
- if( rToken.isEmpty() )
+ SbiInstance* pInst = GetSbData()->pInst;
+ bool bTextMode;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ SbiRuntime* pRT = pInst->pRun;
+ bTextMode = pRT && pRT->IsImageFlag( SbiImageFlags::COMPARETEXT );
+ }
+ else
+ {
+ bTextMode = true;
+ }
+ if ( nArgCount == 4 )
+ {
+ bTextMode = rPar.Get(4)->GetInteger();
+ }
+ sal_Int32 nPos;
+ const OUString aToken = rPar.Get(nFirstStringPos + 1)->GetOUString();
+
+ // #97545 Always find empty string
+ if( aToken.isEmpty() )
+ {
+ nPos = nStartPos;
+ }
+ else
+ {
+ const OUString aStr1 = rPar.Get(nFirstStringPos)->GetOUString();
+ const sal_Int32 nrStr1Len = aStr1.getLength();
+ if (nStartPos > nrStr1Len)
{
- nPos = nStartPos;
+ // Start position is greater than the string being searched
+ nPos = 0;
}
else
{
- const OUString& rStr1 = rPar.Get(nFirstStringPos)->GetOUString();
- const sal_Int32 nrStr1Len = rStr1.getLength();
- if (nStartPos > nrStr1Len)
+ if( !bTextMode )
{
- // Start position is greater than the string being searched
- nPos = 0;
+ nPos = aStr1.indexOf( aToken, nStartPos - 1 ) + 1;
}
else
{
- if( !bTextMode )
- {
- nPos = rStr1.indexOf( rToken, nStartPos - 1 ) + 1;
- }
- else
- {
- // tdf#139840 - case-insensitive operation for non-ASCII characters
- i18nutil::SearchOptions2 aSearchOptions;
- aSearchOptions.searchString = rToken;
- aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
- aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
- utl::TextSearch textSearch(aSearchOptions);
-
- sal_Int32 nStart = nStartPos - 1;
- sal_Int32 nEnd = nrStr1Len;
- nPos = textSearch.SearchForward(rStr1, &nStart, &nEnd) ? nStart + 1 : 0;
- }
+ // tdf#139840 - case-insensitive operation for non-ASCII characters
+ i18nutil::SearchOptions2 aSearchOptions;
+ aSearchOptions.searchString = aToken;
+ aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
+ aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+ utl::TextSearch textSearch(aSearchOptions);
+
+ sal_Int32 nStart = nStartPos - 1;
+ sal_Int32 nEnd = nrStr1Len;
+ nPos = textSearch.SearchForward(aStr1, &nStart, &nEnd) ? nStart + 1 : 0;
}
}
- rPar.Get(0)->PutLong(nPos);
}
+ rPar.Get(0)->PutLong(nPos);
}
@@ -923,78 +858,76 @@ void SbRtl_InStrRev(StarBASIC *, SbxArray & rPar, bool)
const sal_uInt32 nArgCount = rPar.Count() - 1;
if ( nArgCount < 2 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- else
- {
- const OUString aStr1 = rPar.Get(1)->GetOUString();
- const 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( ERRCODE_BASIC_BAD_ARGUMENT );
- nStartPos = -1;
- }
- }
+ const OUString aStr1 = rPar.Get(1)->GetOUString();
+ const OUString aToken = rPar.Get(2)->GetOUString();
- SbiInstance* pInst = GetSbData()->pInst;
- bool bTextMode;
- bool bCompatibility = ( pInst && pInst->IsCompatibility() );
- if( bCompatibility )
- {
- SbiRuntime* pRT = pInst->pRun;
- bTextMode = pRT && pRT->IsImageFlag( SbiImageFlags::COMPARETEXT );
- }
- else
- {
- bTextMode = true;
- }
- if ( nArgCount == 4 )
+ sal_Int32 nStartPos = -1;
+ if ( nArgCount >= 3 )
+ {
+ nStartPos = rPar.Get(3)->GetLong();
+ if( nStartPos <= 0 && nStartPos != -1 )
{
- bTextMode = rPar.Get(4)->GetInteger();
+ StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ nStartPos = -1;
}
- const sal_Int32 nStrLen = aStr1.getLength();
- if( nStartPos == -1 )
+ }
+
+ SbiInstance* pInst = GetSbData()->pInst;
+ bool bTextMode;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
+ {
+ SbiRuntime* pRT = pInst->pRun;
+ bTextMode = pRT && pRT->IsImageFlag( SbiImageFlags::COMPARETEXT );
+ }
+ else
+ {
+ bTextMode = true;
+ }
+ if ( nArgCount == 4 )
+ {
+ bTextMode = rPar.Get(4)->GetInteger();
+ }
+ const sal_Int32 nStrLen = aStr1.getLength();
+ if( nStartPos == -1 )
+ {
+ nStartPos = nStrLen;
+ }
+
+ sal_Int32 nPos = 0;
+ if( nStartPos <= nStrLen )
+ {
+ sal_Int32 nTokenLen = aToken.getLength();
+ if( !nTokenLen )
{
- nStartPos = nStrLen;
+ // Always find empty string
+ nPos = nStartPos;
}
-
- sal_Int32 nPos = 0;
- if( nStartPos <= nStrLen )
+ else if( nStrLen > 0 )
{
- sal_Int32 nTokenLen = aToken.getLength();
- if( !nTokenLen )
+ if( !bTextMode )
{
- // Always find empty string
- nPos = nStartPos;
+ nPos = aStr1.lastIndexOf( aToken, nStartPos ) + 1;
}
- else if( nStrLen > 0 )
+ else
{
- if( !bTextMode )
- {
- nPos = aStr1.lastIndexOf( aToken, nStartPos ) + 1;
- }
- else
- {
- // tdf#143332 - case-insensitive operation for non-ASCII characters
- i18nutil::SearchOptions2 aSearchOptions;
- aSearchOptions.searchString = aToken;
- aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
- aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
- utl::TextSearch textSearch(aSearchOptions);
-
- sal_Int32 nStart = 0;
- sal_Int32 nEnd = nStartPos;
- nPos = textSearch.SearchBackward(aStr1, &nEnd, &nStart) ? nStart : 0;
- }
+ // tdf#143332 - case-insensitive operation for non-ASCII characters
+ i18nutil::SearchOptions2 aSearchOptions;
+ aSearchOptions.searchString = aToken;
+ aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
+ aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+ utl::TextSearch textSearch(aSearchOptions);
+
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd = nStartPos;
+ nPos = textSearch.SearchBackward(aStr1, &nEnd, &nStart) ? nStart : 0;
}
}
- rPar.Get(0)->PutLong(nPos);
}
+ rPar.Get(0)->PutLong(nPos);
}
@@ -1008,110 +941,86 @@ void SbRtl_InStrRev(StarBASIC *, SbxArray & rPar, bool)
void SbRtl_Int(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_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);
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ 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);
}
void SbRtl_Fix(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariableRef pArg = rPar.Get(1);
+ double aDouble = pArg->GetDouble();
+ if ( aDouble >= 0.0 )
+ aDouble = floor( aDouble );
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);
- }
+ aDouble = ceil( aDouble );
+ rPar.Get(0)->PutDouble(aDouble);
}
void SbRtl_LCase(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- const CharClass& rCharClass = GetCharClass();
- OUString aStr(rPar.Get(1)->GetOUString());
- aStr = rCharClass.lowercase(aStr);
- rPar.Get(0)->PutString(aStr);
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ const CharClass& rCharClass = GetCharClass();
+ OUString aStr(rPar.Get(1)->GetOUString());
+ aStr = rCharClass.lowercase(aStr);
+ rPar.Get(0)->PutString(aStr);
}
void SbRtl_Left(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 3)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ OUString aStr(rPar.Get(1)->GetOUString());
+ sal_Int32 nResultLen = rPar.Get(2)->GetLong();
+ if( nResultLen < 0 )
{
+ nResultLen = 0;
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- else
+ else if(nResultLen > aStr.getLength())
{
- OUString aStr(rPar.Get(1)->GetOUString());
- sal_Int32 nResultLen = rPar.Get(2)->GetLong();
- if( nResultLen < 0 )
- {
- nResultLen = 0;
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else if(nResultLen > aStr.getLength())
- {
- nResultLen = aStr.getLength();
- }
- aStr = aStr.copy(0, nResultLen );
- rPar.Get(0)->PutString(aStr);
+ nResultLen = aStr.getLength();
}
+ aStr = aStr.copy(0, nResultLen );
+ rPar.Get(0)->PutString(aStr);
}
void SbRtl_Log(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_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( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ double aArg = rPar.Get(1)->GetDouble();
+ if ( aArg <= 0 )
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ double d = log( aArg );
+ checkArithmeticOverflow( d );
+ rPar.Get(0)->PutDouble(d);
}
void SbRtl_LTrim(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- OUString aStr(comphelper::string::stripStart(rPar.Get(1)->GetOUString(), ' '));
- rPar.Get(0)->PutString(aStr);
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ OUString aStr(comphelper::string::stripStart(rPar.Get(1)->GetOUString(), ' '));
+ rPar.Get(0)->PutString(aStr);
}
@@ -1122,137 +1031,119 @@ void SbRtl_Mid(StarBASIC *, SbxArray & rPar, bool bWrite)
int nArgCount = rPar.Count() - 1;
if ( nArgCount < 2 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error(ERRCODE_BASIC_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 )
{
- // #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 = true;
- }
- OUString aArgStr = rPar.Get(1)->GetOUString();
- sal_Int32 nStartPos = rPar.Get(2)->GetLong();
- if ( nStartPos < 1 )
+ bWrite = true;
+ }
+ OUString aArgStr = rPar.Get(1)->GetOUString();
+ sal_Int32 nStartPos = rPar.Get(2)->GetLong();
+ if ( nStartPos < 1 )
+ {
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ }
+
+ nStartPos--;
+ sal_Int32 nLen = -1;
+ bool bWriteNoLenParam = false;
+ if ( nArgCount == 3 || bWrite )
+ {
+ sal_Int32 n = rPar.Get(3)->GetLong();
+ if( bWrite && n == -1 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ bWriteNoLenParam = true;
}
- else
+ nLen = n;
+ }
+ if ( bWrite )
+ {
+ sal_Int32 nArgLen = aArgStr.getLength();
+ if( nStartPos > nArgLen )
{
- nStartPos--;
- sal_Int32 nLen = -1;
- bool bWriteNoLenParam = false;
- if ( nArgCount == 3 || bWrite )
+ SbiInstance* pInst = GetSbData()->pInst;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
{
- sal_Int32 n = rPar.Get(3)->GetLong();
- if( bWrite && n == -1 )
- {
- bWriteNoLenParam = true;
- }
- nLen = n;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- if ( bWrite )
- {
- sal_Int32 nArgLen = aArgStr.getLength();
- if( nStartPos > nArgLen )
- {
- SbiInstance* pInst = GetSbData()->pInst;
- bool bCompatibility = ( pInst && pInst->IsCompatibility() );
- if( bCompatibility )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
- nStartPos = nArgLen;
- }
-
- OUString aReplaceStr = rPar.Get(4)->GetOUString();
- sal_Int32 nReplaceStrLen = aReplaceStr.getLength();
- sal_Int32 nReplaceLen;
- if( bWriteNoLenParam )
- {
- nReplaceLen = nArgLen - nStartPos;
- }
- else
- {
- nReplaceLen = nLen;
- if( nReplaceLen < 0 || nReplaceLen > nArgLen - nStartPos )
- {
- nReplaceLen = nArgLen - nStartPos;
- }
- }
-
- OUStringBuffer aResultStr(aArgStr);
- sal_Int32 nErase = nReplaceLen;
- aResultStr.remove( nStartPos, nErase );
- aResultStr.insert(
- nStartPos, aReplaceStr.getStr(), std::min(nReplaceLen, nReplaceStrLen));
+ nStartPos = nArgLen;
+ }
- rPar.Get(1)->PutString(aResultStr.makeStringAndClear());
- }
- else
+ OUString aReplaceStr = rPar.Get(4)->GetOUString();
+ sal_Int32 nReplaceStrLen = aReplaceStr.getLength();
+ sal_Int32 nReplaceLen;
+ if( bWriteNoLenParam )
+ {
+ nReplaceLen = nArgLen - nStartPos;
+ }
+ else
+ {
+ nReplaceLen = nLen;
+ if( nReplaceLen < 0 || nReplaceLen > nArgLen - nStartPos )
{
- OUString aResultStr;
- if (nStartPos > aArgStr.getLength())
- {
- // do nothing
- }
- else if(nArgCount == 2)
- {
- aResultStr = aArgStr.copy( nStartPos);
- }
- else
- {
- if (nLen < 0)
- nLen = 0;
- if(nStartPos + nLen > aArgStr.getLength())
- {
- nLen = aArgStr.getLength() - nStartPos;
- }
- if (nLen > 0)
- aResultStr = aArgStr.copy( nStartPos, nLen );
- }
- rPar.Get(0)->PutString(aResultStr);
+ nReplaceLen = nArgLen - nStartPos;
}
}
- }
-}
-void SbRtl_Oct(StarBASIC *, SbxArray & rPar, bool)
-{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ OUStringBuffer aResultStr(aArgStr);
+ sal_Int32 nErase = nReplaceLen;
+ aResultStr.remove( nStartPos, nErase );
+ aResultStr.insert(
+ nStartPos, aReplaceStr.getStr(), std::min(nReplaceLen, nReplaceStrLen));
+
+ rPar.Get(1)->PutString(aResultStr.makeStringAndClear());
}
else
{
- char aBuffer[16];
- SbxVariableRef pArg = rPar.Get(1);
- if ( pArg->IsInteger() )
+ OUString aResultStr;
+ if (nStartPos > aArgStr.getLength())
+ {
+ // do nothing
+ }
+ else if(nArgCount == 2)
{
- snprintf( aBuffer, sizeof(aBuffer), "%o", pArg->GetInteger() );
+ aResultStr = aArgStr.copy( nStartPos);
}
else
{
- snprintf( aBuffer, sizeof(aBuffer), "%lo", static_cast<long unsigned int>(pArg->GetLong()) );
+ if (nLen < 0)
+ nLen = 0;
+ if(nStartPos + nLen > aArgStr.getLength())
+ {
+ nLen = aArgStr.getLength() - nStartPos;
+ }
+ if (nLen > 0)
+ aResultStr = aArgStr.copy( nStartPos, nLen );
}
- rPar.Get(0)->PutString(OUString::createFromAscii(aBuffer));
+ rPar.Get(0)->PutString(aResultStr);
}
}
+void SbRtl_Oct(StarBASIC *, SbxArray & rPar, bool)
+{
+ if (rPar.Count() < 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ 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(OUString::number(nVal, 8));
+}
+
// Replace(expression, find, replace[, start[, count[, compare]]])
void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
{
const sal_uInt32 nArgCount = rPar.Count() - 1;
if ( nArgCount < 3 || nArgCount > 6 )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
sal_Int32 lStartPos = 1;
if (nArgCount >= 4)
@@ -1263,10 +1154,10 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
}
if (lStartPos < 1)
{
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
}
+ --lStartPos; // Make it 0-based
sal_Int32 lCount = -1;
if (nArgCount >= 5)
@@ -1277,8 +1168,7 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
}
if (lCount < -1)
{
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
}
@@ -1302,66 +1192,74 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
}
const OUString aExpStr = rPar.Get(1)->GetOUString();
- const OUString aFindStr = rPar.Get(2)->GetOUString();
+ OUString aFindStr = rPar.Get(2)->GetOUString();
const OUString aReplaceStr = rPar.Get(3)->GetOUString();
- const sal_Int32 nExpStrLen = aExpStr.getLength();
- const sal_Int32 nFindStrLen = aFindStr.getLength();
- // tdf#142487 - use utl::TextSearch in order to implement the replace algorithm
- i18nutil::SearchOptions2 aSearchOptions;
- aSearchOptions.searchString = aFindStr;
- aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
+ OUString aSrcStr(aExpStr);
+ sal_Int32 nPrevPos = std::min(lStartPos, aSrcStr.getLength());
+ css::uno::Sequence<sal_Int32> aOffset;
if (bCaseInsensitive)
- aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
- utl::TextSearch textSearch(aSearchOptions);
+ {
+ // tdf#132389: case-insensitive operation for non-ASCII characters
+ // tdf#142487: use css::i18n::Transliteration to correctly handle ß -> ss expansion
+ // tdf#132388: We can't use utl::TextSearch (css::i18n::XTextSearch), because each call to
+ // css::i18n::XTextSearch::SearchForward transliterates input string, making
+ // performance of repeated calls unacceptable
+ auto xTrans = css::i18n::Transliteration::create(comphelper::getProcessComponentContext());
+ xTrans->loadModule(css::i18n::TransliterationModules_IGNORE_CASE, {});
+ aFindStr = xTrans->transliterate(aFindStr, 0, aFindStr.getLength(), aOffset);
+ aSrcStr = xTrans->transliterate(aSrcStr, nPrevPos, aSrcStr.getLength() - nPrevPos, aOffset);
+ nPrevPos = std::distance(aOffset.begin(),
+ std::lower_bound(aOffset.begin(), aOffset.end(), nPrevPos));
+ }
+
+ auto getExpStrPos = [aOffset, nExpLen = aExpStr.getLength()](sal_Int32 nSrcStrPos) -> sal_Int32
+ {
+ assert(!aOffset.hasElements() || aOffset.getLength() >= nSrcStrPos);
+ if (!aOffset.hasElements())
+ return nSrcStrPos;
+ return aOffset.getLength() > nSrcStrPos ? aOffset[nSrcStrPos] : nExpLen;
+ };
// Note: the result starts from lStartPos, removing everything to the left. See i#94895.
- sal_Int32 nPrevPos = std::min(lStartPos - 1, nExpStrLen);
- OUStringBuffer sResult(nExpStrLen - nPrevPos);
+ OUStringBuffer sResult(aSrcStr.getLength() - nPrevPos);
sal_Int32 nCounts = 0;
while (lCount == -1 || lCount > nCounts)
{
- sal_Int32 nStartPos = nPrevPos;
- sal_Int32 aEndPos = aExpStr.getLength();
- if (textSearch.SearchForward(aExpStr, &nStartPos, &aEndPos))
- {
- sResult.append(aExpStr.getStr() + nPrevPos, nStartPos - nPrevPos);
- sResult.append(aReplaceStr);
- nPrevPos = nStartPos + nFindStrLen;
- nCounts++;
- }
- else
- {
+ sal_Int32 nPos = aSrcStr.indexOf(aFindStr, nPrevPos);
+ if (nPos < 0)
break;
- }
+
+ lStartPos = getExpStrPos(nPrevPos);
+ sResult.append(aExpStr.getStr() + lStartPos, getExpStrPos(nPos) - lStartPos);
+ sResult.append(aReplaceStr);
+ nPrevPos = nPos + aFindStr.getLength();
+ nCounts++;
}
- sResult.append(aExpStr.getStr() + nPrevPos, nExpStrLen - nPrevPos);
+ lStartPos = getExpStrPos(nPrevPos);
+ sResult.append(aExpStr.getStr() + lStartPos, aExpStr.getLength() - lStartPos);
rPar.Get(0)->PutString(sResult.makeStringAndClear());
}
void SbRtl_Right(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 3)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ const OUString aStr = rPar.Get(1)->GetOUString();
+ int nResultLen = rPar.Get(2)->GetLong();
+ if( nResultLen < 0 )
{
+ nResultLen = 0;
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- else
+ int nStrLen = aStr.getLength();
+ if ( nResultLen > nStrLen )
{
- const OUString& rStr = rPar.Get(1)->GetOUString();
- int nResultLen = rPar.Get(2)->GetLong();
- if( nResultLen < 0 )
- {
- nResultLen = 0;
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- int nStrLen = rStr.getLength();
- if ( nResultLen > nStrLen )
- {
- nResultLen = nStrLen;
- }
- OUString aResultStr = rStr.copy( nStrLen - nResultLen );
- rPar.Get(0)->PutString(aResultStr);
+ nResultLen = nStrLen;
}
+ OUString aResultStr = aStr.copy( nStrLen - nResultLen );
+ rPar.Get(0)->PutString(aResultStr);
}
void SbRtl_RTL(StarBASIC * pBasic, SbxArray & rPar, bool)
@@ -1372,145 +1270,115 @@ void SbRtl_RTL(StarBASIC * pBasic, SbxArray & rPar, bool)
void SbRtl_RTrim(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- OUString aStr(comphelper::string::stripEnd(rPar.Get(1)->GetOUString(), ' '));
- rPar.Get(0)->PutString(aStr);
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ OUString aStr(comphelper::string::stripEnd(rPar.Get(1)->GetOUString(), ' '));
+ rPar.Get(0)->PutString(aStr);
}
void SbRtl_Sgn(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ double aDouble = rPar.Get(1)->GetDouble();
+ sal_Int16 nResult = 0;
+ if ( aDouble > 0 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ nResult = 1;
}
- else
+ else if ( aDouble < 0 )
{
- 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);
+ nResult = -1;
}
+ rPar.Get(0)->PutInteger(nResult);
}
void SbRtl_Space(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- OUStringBuffer aBuf;
- string::padToLength(aBuf, rPar.Get(1)->GetLong(), ' ');
- rPar.Get(0)->PutString(aBuf.makeStringAndClear());
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
-}
-void SbRtl_Spc(StarBASIC *, SbxArray & rPar, bool)
-{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- OUStringBuffer aBuf;
- string::padToLength(aBuf, rPar.Get(1)->GetLong(), ' ');
- rPar.Get(0)->PutString(aBuf.makeStringAndClear());
- }
+ const sal_Int32 nCount = rPar.Get(1)->GetLong();
+ OUStringBuffer aBuf(nCount);
+ string::padToLength(aBuf, nCount, ' ');
+ rPar.Get(0)->PutString(aBuf.makeStringAndClear());
}
void SbRtl_Sqr(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
- else
+
+ double aDouble = rPar.Get(1)->GetDouble();
+ if ( aDouble < 0 )
{
- double aDouble = rPar.Get(1)->GetDouble();
- if ( aDouble >= 0 )
- {
- rPar.Get(0)->PutDouble(sqrt(aDouble));
- }
- else
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
+ rPar.Get(0)->PutDouble(sqrt(aDouble));
}
void SbRtl_Str(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
- else
+
+ OUString aStr;
+ OUString aStrNew(u""_ustr);
+ SbxVariableRef pArg = rPar.Get(1);
+ pArg->Format( aStr );
+
+ // Numbers start with a space
+ if (pArg->GetType() != SbxBOOL && pArg->IsNumericRTL())
{
- OUString aStr;
- OUString aStrNew("");
- SbxVariableRef pArg = rPar.Get(1);
- pArg->Format( aStr );
+ // replace commas by points so that it's symmetric to Val!
+ aStr = aStr.replaceFirst( ",", "." );
- // Numbers start with a space
- if( pArg->IsNumericRTL() )
+ SbiInstance* pInst = GetSbData()->pInst;
+ bool bCompatibility = ( pInst && pInst->IsCompatibility() );
+ if( bCompatibility )
{
- // 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();
+ sal_Int32 nLen = aStr.getLength();
- const sal_Unicode* pBuf = aStr.getStr();
+ 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] == '.' )
+ bool bNeg = ( pBuf[0] == '-' );
+ sal_Int32 iZeroSearch = 0;
+ if( bNeg )
+ {
+ aStrNew += "-";
+ iZeroSearch++;
+ }
+ else
+ {
+ if( pBuf[0] != ' ' )
{
- iZeroSearch += 1;
+ aStrNew += " ";
}
- aStrNew += aStr.subView(iZeroSearch);
}
- else
+ sal_Int32 iNext = iZeroSearch + 1;
+ if( pBuf[iZeroSearch] == '0' && nLen > iNext && pBuf[iNext] == '.' )
{
- aStrNew = " " + aStr;
+ iZeroSearch += 1;
}
+ aStrNew += aStr.subView(iZeroSearch);
}
else
{
- aStrNew = aStr;
+ aStrNew = " " + aStr;
}
- rPar.Get(0)->PutString(aStrNew);
}
+ else
+ {
+ aStrNew = aStr;
+ }
+ rPar.Get(0)->PutString(aStrNew);
}
void SbRtl_StrComp(StarBASIC *, SbxArray & rPar, bool)
@@ -1521,8 +1389,8 @@ void SbRtl_StrComp(StarBASIC *, SbxArray & rPar, bool)
rPar.Get(0)->PutEmpty();
return;
}
- const OUString& rStr1 = rPar.Get(1)->GetOUString();
- const OUString& rStr2 = rPar.Get(2)->GetOUString();
+ const OUString aStr1 = rPar.Get(1)->GetOUString();
+ const OUString aStr2 = rPar.Get(2)->GetOUString();
SbiInstance* pInst = GetSbData()->pInst;
bool bTextCompare;
@@ -1549,7 +1417,7 @@ void SbRtl_StrComp(StarBASIC *, SbxArray & rPar, bool)
::utl::TransliterationWrapper* pTransliterationWrapper = GetSbData()->pTransliterationWrapper.get();
if( !pTransliterationWrapper )
{
- uno::Reference< uno::XComponentContext > xContext = getProcessComponentContext();
+ const uno::Reference< uno::XComponentContext >& xContext = getProcessComponentContext();
GetSbData()->pTransliterationWrapper.reset(
new ::utl::TransliterationWrapper( xContext,
TransliterationFlags::IGNORE_CASE |
@@ -1560,12 +1428,12 @@ void SbRtl_StrComp(StarBASIC *, SbxArray & rPar, bool)
LanguageType eLangType = Application::GetSettings().GetLanguageTag().getLanguageType();
pTransliterationWrapper->loadModuleIfNeeded( eLangType );
- nRetValue = pTransliterationWrapper->compareString( rStr1, rStr2 );
+ nRetValue = pTransliterationWrapper->compareString( aStr1, aStr2 );
}
else
{
sal_Int32 aResult;
- aResult = rStr1.compareTo( rStr2 );
+ aResult = aStr1.compareTo( aStr2 );
if ( aResult < 0 )
{
nRetValue = -1;
@@ -1582,69 +1450,64 @@ void SbRtl_String(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
+ }
+
+ sal_Unicode aFiller;
+ sal_Int32 lCount = rPar.Get(1)->GetLong();
+ if( lCount < 0 || lCount > 0xffff )
+ {
StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
+ if (rPar.Get(2)->GetType() == SbxINTEGER)
+ {
+ aFiller = static_cast<sal_Unicode>(rPar.Get(2)->GetInteger());
+ }
else
{
- sal_Unicode aFiller;
- sal_Int32 lCount = rPar.Get(1)->GetLong();
- if( lCount < 0 || lCount > 0xffff )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- if (rPar.Get(2)->GetType() == SbxINTEGER)
- {
- aFiller = static_cast<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());
+ const OUString aStr = rPar.Get(2)->GetOUString();
+ aFiller = aStr[0];
}
+ OUStringBuffer aBuf(lCount);
+ string::padToLength(aBuf, lCount, aFiller);
+ rPar.Get(0)->PutString(aBuf.makeStringAndClear());
}
void SbRtl_Tab(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- else
{
- OUStringBuffer aStr;
- comphelper::string::padToLength(aStr, rPar.Get(1)->GetLong(), '\t');
- rPar.Get(0)->PutString(aStr.makeStringAndClear());
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
+
+ const sal_Int32 nCount = std::max(rPar.Get(1)->GetLong(), sal_Int32(0));
+ OUStringBuffer aStr(nCount);
+ comphelper::string::padToLength(aStr, nCount, '\t');
+ rPar.Get(0)->PutString(aStr.makeStringAndClear());
}
void SbRtl_Tan(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- rPar.Get(0)->PutDouble(tan(pArg->GetDouble()));
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
+
+ SbxVariableRef pArg = rPar.Get(1);
+ rPar.Get(0)->PutDouble(tan(pArg->GetDouble()));
}
void SbRtl_UCase(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- const CharClass& rCharClass = GetCharClass();
- OUString aStr(rPar.Get(1)->GetOUString());
- aStr = rCharClass.uppercase( aStr );
- rPar.Get(0)->PutString(aStr);
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
+
+ const CharClass& rCharClass = GetCharClass();
+ OUString aStr(rPar.Get(1)->GetOUString());
+ aStr = rCharClass.uppercase( aStr );
+ rPar.Get(0)->PutString(aStr);
}
@@ -1652,64 +1515,52 @@ void SbRtl_Val(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
- else
- {
- double nResult = 0.0;
- char* pEndPtr;
+ double nResult = 0.0;
- OUString aStr(rPar.Get(1)->GetOUString());
+ OUString aStr(rPar.Get(1)->GetOUString());
- FilterWhiteSpace( aStr );
- if ( aStr.getLength() > 1 && aStr[0] == '&' )
+ FilterWhiteSpace( aStr );
+ if ( aStr.getLength() > 1 && aStr[0] == '&' )
+ {
+ sal_Unicode aChar = aStr[1];
+ if ( aChar == 'h' || aChar == 'H' )
{
- int nRadix = 10;
- char aChar = static_cast<char>(aStr[1]);
- if ( aChar == 'h' || aChar == 'H' )
- {
- nRadix = 16;
- }
- else if ( aChar == 'o' || aChar == 'O' )
- {
- nRadix = 8;
- }
- if ( nRadix != 10 )
- {
- OString aByteStr(OUStringToOString(aStr, osl_getThreadTextEncoding()));
- sal_Int16 nlResult = static_cast<sal_Int16>(strtol( aByteStr.getStr()+2, &pEndPtr, nRadix));
- nResult = static_cast<double>(nlResult);
- }
+ nResult = static_cast<sal_Int16>(o3tl::toInt64(aStr.subView(2), 16));
}
- else
+ else if ( aChar == 'o' || aChar == 'O' )
{
- rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
- sal_Int32 nParseEnd = 0;
- nResult = ::rtl::math::stringToDouble( aStr, '.', ',', &eStatus, &nParseEnd );
- if ( eStatus != rtl_math_ConversionStatus_Ok )
- StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );
- /* TODO: we should check whether all characters were parsed here,
- * but earlier code silently ignored trailing nonsense such as "1x"
- * resulting in 1 with the side effect that any alpha-only-string
- * like "x" resulted in 0. Not changing that now (2013-03-22) as
- * user macros may rely on it. */
+ nResult = static_cast<sal_Int16>(o3tl::toInt64(aStr.subView(2), 8));
+ }
+ }
+ else
+ {
+ rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
+ sal_Int32 nParseEnd = 0;
+ nResult = ::rtl::math::stringToDouble( aStr, '.', ',', &eStatus, &nParseEnd );
+ if ( eStatus != rtl_math_ConversionStatus_Ok )
+ StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );
+ /* TODO: we should check whether all characters were parsed here,
+ * but earlier code silently ignored trailing nonsense such as "1x"
+ * resulting in 1 with the side effect that any alpha-only-string
+ * like "x" resulted in 0. Not changing that now (2013-03-22) as
+ * user macros may rely on it. */
#if 0
- else if ( nParseEnd != aStr.getLength() )
- StarBASIC::Error( ERRCODE_BASIC_CONVERSION );
+ else if ( nParseEnd != aStr.getLength() )
+ StarBASIC::Error( ERRCODE_BASIC_CONVERSION );
#endif
- }
-
- rPar.Get(0)->PutDouble(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
aDate = floor( aDate );
- Date aRefDate( 1, 1, 1900 );
+ Date aRefDate(1899'12'30);
aRefDate.AddDays( aDate );
sal_Int16 nRet = static_cast<sal_Int16>( aRefDate.GetDay() );
@@ -1718,9 +1569,8 @@ sal_Int16 implGetDateDay( double aDate )
sal_Int16 implGetDateMonth( double aDate )
{
- Date aRefDate( 1,1,1900 );
+ Date aRefDate(1899'12'30);
sal_Int32 nDays = static_cast<sal_Int32>(aDate);
- nDays -= 2; // standardize: 1.1.1900 => 0.0
aRefDate.AddDays( nDays );
sal_Int16 nRet = static_cast<sal_Int16>( aRefDate.GetMonth() );
return nRet;
@@ -1752,8 +1602,7 @@ void SbRtl_CDateToUnoDate(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
unoToSbxValue(rPar.Get(0), Any(SbxDateToUNODate(rPar.Get(1))));
@@ -1764,8 +1613,7 @@ void SbRtl_CDateFromUnoDate(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2 || rPar.Get(1)->GetType() != SbxOBJECT)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
Any aAny(sbxToUnoValue(rPar.Get(1), cppu::UnoType<css::util::Date>::get()));
@@ -1784,14 +1632,15 @@ css::util::Time SbxDateToUNOTime( const SbxValue* const pVal )
aUnoTime.Hours = implGetHour ( aDate );
aUnoTime.Minutes = implGetMinute ( aDate );
aUnoTime.Seconds = implGetSecond ( aDate );
- aUnoTime.NanoSeconds = 0;
+ aUnoTime.NanoSeconds = implGetNanoSecond( aDate );
return aUnoTime;
}
void SbxDateFromUNOTime( SbxValue *pVal, const css::util::Time& aUnoTime)
{
- pVal->PutDate( implTimeSerial(aUnoTime.Hours, aUnoTime.Minutes, aUnoTime.Seconds) );
+ pVal->PutDate(implTimeSerial(aUnoTime.Hours, aUnoTime.Minutes, aUnoTime.Seconds,
+ nanoSecToMilliSec(aUnoTime.NanoSeconds)));
}
// Function to convert date to UNO time (com.sun.star.util.Time)
@@ -1799,8 +1648,7 @@ void SbRtl_CDateToUnoTime(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
unoToSbxValue(rPar.Get(0), Any(SbxDateToUNOTime(rPar.Get(1))));
@@ -1811,8 +1659,7 @@ void SbRtl_CDateFromUnoTime(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2 || rPar.Get(1)->GetType() != SbxOBJECT)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
Any aAny(sbxToUnoValue(rPar.Get(1), cppu::UnoType<css::util::Time>::get()));
@@ -1834,7 +1681,7 @@ css::util::DateTime SbxDateToUNODateTime( const SbxValue* const pVal )
aUnoDT.Hours = implGetHour ( aDate );
aUnoDT.Minutes = implGetMinute ( aDate );
aUnoDT.Seconds = implGetSecond ( aDate );
- aUnoDT.NanoSeconds = 0;
+ aUnoDT.NanoSeconds = implGetNanoSecond( aDate );
return aUnoDT;
}
@@ -1842,9 +1689,8 @@ css::util::DateTime SbxDateToUNODateTime( const SbxValue* const pVal )
void SbxDateFromUNODateTime( SbxValue *pVal, const css::util::DateTime& aUnoDT)
{
double dDate(0.0);
- if( implDateTimeSerial( aUnoDT.Year, aUnoDT.Month, aUnoDT.Day,
- aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds,
- dDate ) )
+ if (implDateTimeSerial(aUnoDT.Year, aUnoDT.Month, aUnoDT.Day, aUnoDT.Hours, aUnoDT.Minutes,
+ aUnoDT.Seconds, nanoSecToMilliSec(aUnoDT.NanoSeconds), dDate))
{
pVal->PutDate( dDate );
}
@@ -1855,8 +1701,7 @@ void SbRtl_CDateToUnoDateTime(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
unoToSbxValue(rPar.Get(0), Any(SbxDateToUNODateTime(rPar.Get(1))));
@@ -1867,8 +1712,7 @@ void SbRtl_CDateFromUnoDateTime(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2 || rPar.Get(1)->GetType() != SbxOBJECT)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
Any aAny(sbxToUnoValue(rPar.Get(1), cppu::UnoType<css::util::DateTime>::get()));
@@ -1882,24 +1726,19 @@ void SbRtl_CDateFromUnoDateTime(StarBASIC *, SbxArray & rPar, bool)
// Function to convert date to ISO 8601 date format YYYYMMDD
void SbRtl_CDateToIso(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() == 2)
- {
- double aDate = rPar.Get(1)->GetDate();
+ if (rPar.Count() != 2)
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- // Date may actually even be -YYYYYMMDD
- char Buffer[11];
- sal_Int16 nYear = implGetDateYear( aDate );
- snprintf( Buffer, sizeof( Buffer ), (nYear < 0 ? "%05d%02d%02d" : "%04d%02d%02d"),
- static_cast<int>(nYear),
- static_cast<int>(implGetDateMonth( aDate )),
- static_cast<int>(implGetDateDay( aDate )) );
- OUString aRetStr = OUString::createFromAscii( Buffer );
- rPar.Get(0)->PutString(aRetStr);
- }
- else
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
+ double aDate = rPar.Get(1)->GetDate();
+
+ // Date may actually even be -YYYYYMMDD
+ char Buffer[11];
+ sal_Int16 nYear = implGetDateYear(aDate);
+ snprintf(Buffer, sizeof(Buffer), (nYear < 0 ? "%05d%02d%02d" : "%04d%02d%02d"),
+ static_cast<int>(nYear), static_cast<int>(implGetDateMonth(aDate)),
+ static_cast<int>(implGetDateDay(aDate)));
+ OUString aRetStr = OUString::createFromAscii(Buffer);
+ rPar.Get(0)->PutString(aRetStr);
}
// Function to convert date from ISO 8601 date format YYYYMMDD or YYYY-MM-DD
@@ -1937,7 +1776,7 @@ void SbRtl_CDateFromIso(StarBASIC *, SbxArray & rPar, bool)
break;
bool bUseTwoDigitYear = false;
- OUString aYearStr, aMonthStr, aDayStr;
+ std::u16string_view aYearStr, aMonthStr, aDayStr;
if (nLen == 6 || nLen == 8 || nLen == 9)
{
// ((Y)YY)YYMMDD
@@ -1947,9 +1786,9 @@ void SbRtl_CDateFromIso(StarBASIC *, SbxArray & rPar, bool)
const sal_Int32 nMonthPos = (nLen == 8 ? 4 : (nLen == 6 ? 2 : 5));
if (nMonthPos == 2)
bUseTwoDigitYear = true;
- aYearStr = aStr.copy( 0, nMonthPos );
- aMonthStr = aStr.copy( nMonthPos, 2 );
- aDayStr = aStr.copy( nMonthPos + 2, 2 );
+ aYearStr = aStr.subView( 0, nMonthPos );
+ aMonthStr = aStr.subView( nMonthPos, 2 );
+ aDayStr = aStr.subView( nMonthPos + 2, 2 );
}
else
{
@@ -1960,9 +1799,9 @@ void SbRtl_CDateFromIso(StarBASIC *, SbxArray & rPar, bool)
if (aStr.indexOf('-', nMonthSep + 1) != nMonthSep + 3)
break;
- aYearStr = aStr.copy( 0, nMonthSep );
- aMonthStr = aStr.copy( nMonthSep + 1, 2 );
- aDayStr = aStr.copy( nMonthSep + 4, 2 );
+ aYearStr = aStr.subView( 0, nMonthSep );
+ aMonthStr = aStr.subView( nMonthSep + 1, 2 );
+ aDayStr = aStr.subView( nMonthSep + 4, 2 );
if ( !comphelper::string::isdigitAsciiString(aYearStr) ||
!comphelper::string::isdigitAsciiString(aMonthStr) ||
!comphelper::string::isdigitAsciiString(aDayStr))
@@ -1970,8 +1809,8 @@ void SbRtl_CDateFromIso(StarBASIC *, SbxArray & rPar, bool)
}
double dDate;
- if (!implDateSerial( static_cast<sal_Int16>(nSign * aYearStr.toInt32()),
- static_cast<sal_Int16>(aMonthStr.toInt32()), static_cast<sal_Int16>(aDayStr.toInt32()),
+ if (!implDateSerial( static_cast<sal_Int16>(nSign * o3tl::toInt32(aYearStr)),
+ static_cast<sal_Int16>(o3tl::toInt32(aMonthStr)), static_cast<sal_Int16>(o3tl::toInt32(aDayStr)),
bUseTwoDigitYear, SbDateCorrection::None, dDate ))
break;
@@ -1993,8 +1832,7 @@ void SbRtl_DateSerial(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 4)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
sal_Int16 nYear = rPar.Get(1)->GetInteger();
sal_Int16 nMonth = rPar.Get(2)->GetInteger();
@@ -2011,8 +1849,7 @@ void SbRtl_TimeSerial(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() < 4)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
sal_Int16 nHour = rPar.Get(1)->GetInteger();
if ( nHour == 24 )
@@ -2025,11 +1862,10 @@ void SbRtl_TimeSerial(StarBASIC *, SbxArray & rPar, bool)
(nMinute < 0 || nMinute > 59 ) ||
(nSecond < 0 || nSecond > 59 ))
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- rPar.Get(0)->PutDate(implTimeSerial(nHour, nMinute, nSecond)); // JSM
+ rPar.Get(0)->PutDate(implTimeSerial(nHour, nMinute, nSecond, 0)); // JSM
}
void SbRtl_DateValue(StarBASIC *, SbxArray & rPar, bool)
@@ -2133,127 +1969,101 @@ void SbRtl_TimeValue(StarBASIC *, SbxArray & rPar, bool)
void SbRtl_Day(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- SbxVariableRef pArg = rPar.Get(1);
- double aDate = pArg->GetDate();
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ SbxVariableRef pArg = rPar.Get(1);
+ double aDate = pArg->GetDate();
- sal_Int16 nDay = implGetDateDay( aDate );
- rPar.Get(0)->PutInteger(nDay);
- }
+ sal_Int16 nDay = implGetDateDay( aDate );
+ rPar.Get(0)->PutInteger(nDay);
}
void SbRtl_Year(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- sal_Int16 nYear = implGetDateYear(rPar.Get(1)->GetDate());
- rPar.Get(0)->PutInteger(nYear);
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ sal_Int16 nYear = implGetDateYear(rPar.Get(1)->GetDate());
+ rPar.Get(0)->PutInteger(nYear);
}
sal_Int16 implGetHour( double dDate )
{
- double nFrac = dDate - floor( dDate );
- nFrac *= 86400.0;
- sal_Int32 nSeconds = static_cast<sal_Int32>(nFrac + 0.5);
- sal_Int16 nHour = static_cast<sal_Int16>(nSeconds / 3600);
- return nHour;
+ double nFrac = (dDate - floor(dDate)) * ::tools::Time::milliSecPerDay;
+ sal_uInt64 nMilliSeconds = static_cast<sal_uInt64>(nFrac + 0.5);
+ return static_cast<sal_Int16>((nMilliSeconds / ::tools::Time::milliSecPerHour)
+ % ::tools::Time::hourPerDay);
}
void SbRtl_Hour(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- double nArg = rPar.Get(1)->GetDate();
- sal_Int16 nHour = implGetHour( nArg );
- rPar.Get(0)->PutInteger(nHour);
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ double nArg = rPar.Get(1)->GetDate();
+ sal_Int16 nHour = implGetHour( nArg );
+ rPar.Get(0)->PutInteger(nHour);
}
void SbRtl_Minute(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- double nArg = rPar.Get(1)->GetDate();
- sal_Int16 nMin = implGetMinute( nArg );
- rPar.Get(0)->PutInteger(nMin);
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ double nArg = rPar.Get(1)->GetDate();
+ sal_Int16 nMin = implGetMinute( nArg );
+ rPar.Get(0)->PutInteger(nMin);
}
void SbRtl_Month(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- sal_Int16 nMonth = implGetDateMonth(rPar.Get(1)->GetDate());
- rPar.Get(0)->PutInteger(nMonth);
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ sal_Int16 nMonth = implGetDateMonth(rPar.Get(1)->GetDate());
+ rPar.Get(0)->PutInteger(nMonth);
}
sal_Int16 implGetSecond( double dDate )
{
- double nFrac = dDate - floor( dDate );
- nFrac *= 86400.0;
- sal_Int32 nSeconds = static_cast<sal_Int32>(nFrac + 0.5);
- sal_Int16 nTemp = static_cast<sal_Int16>(nSeconds / 3600);
- nSeconds -= nTemp * 3600;
- nTemp = static_cast<sal_Int16>(nSeconds / 60);
- nSeconds -= nTemp * 60;
+ double nFrac = (dDate - floor(dDate)) * ::tools::Time::milliSecPerDay;
+ sal_uInt64 nMilliSeconds = static_cast<sal_uInt64>(nFrac + 0.5);
+ return static_cast<sal_Int16>((nMilliSeconds / ::tools::Time::milliSecPerSec)
+ % ::tools::Time::secondPerMinute);
+}
- sal_Int16 nRet = static_cast<sal_Int16>(nSeconds);
- return nRet;
+sal_Int32 implGetNanoSecond(double dDate)
+{
+ double nFrac = (dDate - floor(dDate)) * ::tools::Time::milliSecPerDay;
+ sal_uInt64 nMilliSeconds = static_cast<sal_uInt64>(nFrac + 0.5);
+ nMilliSeconds %= ::tools::Time::milliSecPerSec;
+
+ return static_cast<sal_Int32>(nMilliSeconds * ::tools::Time ::nanoPerMilli);
}
void SbRtl_Second(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- double nArg = rPar.Get(1)->GetDate();
- sal_Int16 nSecond = implGetSecond( nArg );
- rPar.Get(0)->PutInteger(nSecond);
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ double nArg = rPar.Get(1)->GetDate();
+ sal_Int16 nSecond = implGetSecond( nArg );
+ rPar.Get(0)->PutInteger(nSecond);
}
double Now_Impl()
{
- DateTime aDateTime( DateTime::SYSTEM );
- double aSerial = static_cast<double>(GetDayDiff( aDateTime ));
- tools::Long nSeconds = aDateTime.GetHour();
- nSeconds *= 3600;
- nSeconds += aDateTime.GetMin() * 60;
- nSeconds += aDateTime.GetSec();
- double nDays = static_cast<double>(nSeconds) / (24.0*3600.0);
- aSerial += nDays;
- return aSerial;
+ // tdf#161469 - align implementation with the now function in calc, i.e., include subseconds
+ DateTime aActTime(DateTime::SYSTEM);
+ return static_cast<double>(GetDayDiff(aActTime))
+ + implTimeSerial(aActTime.GetHour(), aActTime.GetMin(), aActTime.GetSec(),
+ nanoSecToMilliSec(aActTime.GetNanoSec()));
}
// Date Now()
-void SbRtl_Now(StarBASIC*, SbxArray& rPar, bool) { rPar.Get(0)->PutDate(Now_Impl()); }
+void SbRtl_Now(StarBASIC*, SbxArray& rPar, bool)
+{
+ if (rPar.Count() != 1)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutDate(Now_Impl());
+}
// Date Time()
@@ -2263,6 +2073,11 @@ void SbRtl_Time(StarBASIC *, SbxArray & rPar, bool bWrite)
{
tools::Time aTime( tools::Time::SYSTEM );
SbxVariable* pMeth = rPar.Get(0);
+ if (!pMeth->IsString())
+ {
+ pMeth->PutDate(aTime.GetTimeInDays());
+ return;
+ }
OUString aRes;
if( pMeth->IsFixed() )
{
@@ -2357,176 +2172,144 @@ void SbRtl_Date(StarBASIC *, SbxArray & rPar, bool bWrite)
void SbRtl_IsArray(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- rPar.Get(0)->PutBool((rPar.Get(1)->GetType() & SbxARRAY) != 0);
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutBool((rPar.Get(1)->GetType() & SbxARRAY) != 0);
}
void SbRtl_IsObject(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- SbxVariable* pVar = rPar.Get(1);
- bool bObject = pVar->IsObject();
- SbxBase* pObj = (bObject ? pVar->GetObject() : nullptr);
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- if( auto pUnoClass = dynamic_cast<SbUnoClass*>( pObj) )
- {
- bObject = pUnoClass->getUnoClass().is();
- }
- rPar.Get(0)->PutBool(bObject);
+ SbxVariable* pVar = rPar.Get(1);
+ bool bObject = pVar->IsObject();
+ SbxBase* pObj = (bObject ? pVar->GetObject() : nullptr);
+
+ if( auto pUnoClass = dynamic_cast<SbUnoClass*>( pObj) )
+ {
+ bObject = pUnoClass->getUnoClass().is();
}
+ rPar.Get(0)->PutBool(bObject);
}
void SbRtl_IsDate(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ // #46134 only string is converted, all other types result in sal_False
+ SbxVariableRef xArg = rPar.Get(1);
+ SbxDataType eType = xArg->GetType();
+ bool bDate = false;
+
+ if( eType == SbxDATE )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ bDate = true;
}
- else
+ else if( eType == SbxSTRING )
{
- // #46134 only string is converted, all other types result in sal_False
- SbxVariableRef xArg = rPar.Get(1);
- SbxDataType eType = xArg->GetType();
- bool bDate = false;
-
- if( eType == SbxDATE )
- {
- bDate = true;
- }
- else if( eType == SbxSTRING )
- {
- ErrCode nPrevError = SbxBase::GetError();
- SbxBase::ResetError();
+ ErrCode nPrevError = SbxBase::GetError();
+ SbxBase::ResetError();
- // force conversion of the parameter to SbxDATE
- xArg->SbxValue::GetDate();
+ // force conversion of the parameter to SbxDATE
+ xArg->SbxValue::GetDate();
- bDate = !SbxBase::IsError();
+ bDate = !SbxBase::IsError();
- SbxBase::ResetError();
- SbxBase::SetError( nPrevError );
- }
- rPar.Get(0)->PutBool(bDate);
+ SbxBase::ResetError();
+ SbxBase::SetError( nPrevError );
}
+ rPar.Get(0)->PutBool(bDate);
}
void SbRtl_IsEmpty(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariable* pVar = nullptr;
+ if( SbiRuntime::isVBAEnabled() )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ pVar = getDefaultProp(rPar.Get(1));
+ }
+ if ( pVar )
+ {
+ pVar->Broadcast( SfxHintId::BasicDataWanted );
+ rPar.Get(0)->PutBool(pVar->IsEmpty());
}
else
{
- SbxVariable* pVar = nullptr;
- if( SbiRuntime::isVBAEnabled() )
- {
- pVar = getDefaultProp(rPar.Get(1));
- }
- if ( pVar )
- {
- pVar->Broadcast( SfxHintId::BasicDataWanted );
- rPar.Get(0)->PutBool(pVar->IsEmpty());
- }
- else
- {
- rPar.Get(0)->PutBool(rPar.Get(1)->IsEmpty());
- }
+ rPar.Get(0)->PutBool(rPar.Get(1)->IsEmpty());
}
}
void SbRtl_IsError(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ SbxVariable* pVar = rPar.Get(1);
+ SbUnoObject* pObj = dynamic_cast<SbUnoObject*>( pVar );
+ if ( !pObj )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ if ( SbxBase* pBaseObj = (pVar->IsObject() ? pVar->GetObject() : nullptr) )
+ {
+ pObj = dynamic_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
{
- SbxVariable* pVar = rPar.Get(1);
- SbUnoObject* pObj = dynamic_cast<SbUnoObject*>( pVar );
- if ( !pObj )
- {
- if ( SbxBase* pBaseObj = (pVar->IsObject() ? pVar->GetObject() : nullptr) )
- {
- pObj = dynamic_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());
- }
+ rPar.Get(0)->PutBool(rPar.Get(1)->IsErr());
}
}
void SbRtl_IsNull(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ // #51475 because of Uno-objects return true
+ // even if the pObj value is NULL
+ SbxVariableRef pArg = rPar.Get(1);
+ bool bNull = rPar.Get(1)->IsNull();
+ if( !bNull && pArg->GetType() == SbxOBJECT )
{
- // #51475 because of Uno-objects return true
- // even if the pObj value is NULL
- SbxVariableRef pArg = rPar.Get(1);
- bool bNull = rPar.Get(1)->IsNull();
- if( !bNull && pArg->GetType() == SbxOBJECT )
+ SbxBase* pObj = pArg->GetObject();
+ if( !pObj )
{
- SbxBase* pObj = pArg->GetObject();
- if( !pObj )
- {
- bNull = true;
- }
+ bNull = true;
}
- rPar.Get(0)->PutBool(bNull);
}
+ rPar.Get(0)->PutBool(bNull);
}
void SbRtl_IsNumeric(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- rPar.Get(0)->PutBool(rPar.Get(1)->IsNumericRTL());
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ rPar.Get(0)->PutBool(rPar.Get(1)->IsNumericRTL());
}
void SbRtl_IsMissing(StarBASIC *, SbxArray & rPar, bool)
{
- if (rPar.Count() < 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- // #57915 Missing is reported by an error
- rPar.Get(0)->PutBool(rPar.Get(1)->IsErr());
- }
+ if (rPar.Count() != 2)
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
+ // #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
@@ -2537,7 +2320,7 @@ static OUString implSetupWildcard(const OUString& rFileParam, SbiRTLData& rRTLDa
static const char cWild1 = '*';
static const char cWild2 = '?';
- rRTLData.pWildCard.reset();
+ rRTLData.moWildCard.reset();
rRTLData.sFullNameToBeChecked.clear();
OUString aFileParam = rFileParam;
@@ -2591,7 +2374,7 @@ static OUString implSetupWildcard(const OUString& rFileParam, SbiRTLData& rRTLDa
// invalid anyway because it was not accepted by OSL before
if (aPureFileName != "*")
{
- rRTLData.pWildCard = std::make_unique<WildCard>(aPureFileName);
+ rRTLData.moWildCard.emplace(aPureFileName);
}
return aPathStr;
}
@@ -2600,15 +2383,15 @@ static bool implCheckWildcard(std::u16string_view rName, SbiRTLData const& rRTLD
{
bool bMatch = true;
- if (rRTLData.pWildCard)
+ if (rRTLData.moWildCard)
{
- bMatch = rRTLData.pWildCard->Matches(rName);
+ bMatch = rRTLData.moWildCard->Matches(rName);
}
return bMatch;
}
-static bool isRootDir( const OUString& aDirURLStr )
+static bool isRootDir( std::u16string_view aDirURLStr )
{
INetURLObject aDirURLObj( aDirURLStr );
bool bRoot = false;
@@ -2690,18 +2473,17 @@ void SbRtl_Dir(StarBASIC *, SbxArray & rPar, bool)
}
else
{
- rPar.Get(0)->PutString("");
+ rPar.Get(0)->PutString(u""_ustr);
}
- SbAttributes nFlags = SbAttributes::NONE;
+ sal_Int16 nFlags = SbAttributes::NORMAL;
if ( nParCount > 2 )
{
- rRTLData.nDirFlags = nFlags
- = static_cast<SbAttributes>(rPar.Get(2)->GetInteger());
+ rRTLData.nDirFlags = nFlags = rPar.Get(2)->GetInteger();
}
else
{
- rRTLData.nDirFlags = SbAttributes::NONE;
+ rRTLData.nDirFlags = SbAttributes::NORMAL;
}
// Read directory
bool bIncludeFolders = bool(nFlags & SbAttributes::DIRECTORY);
@@ -2809,15 +2591,14 @@ void SbRtl_Dir(StarBASIC *, SbxArray & rPar, bool)
OUString aDirURL = implSetupWildcard(aFileParam, rRTLData);
- SbAttributes nFlags = SbAttributes::NONE;
+ sal_Int16 nFlags = SbAttributes::NORMAL;
if ( nParCount > 2 )
{
- rRTLData.nDirFlags = nFlags
- = static_cast<SbAttributes>(rPar.Get(2)->GetInteger());
+ rRTLData.nDirFlags = nFlags = rPar.Get(2)->GetInteger();
}
else
{
- rRTLData.nDirFlags = SbAttributes::NONE;
+ rRTLData.nDirFlags = SbAttributes::NORMAL;
}
// Read directory
@@ -2918,7 +2699,7 @@ void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() == 2)
{
- sal_Int16 nFlags = 0;
+ sal_Int16 nFlags = SbAttributes::NORMAL;
// In Windows, we want to use Windows API to get the file attributes
// for VBA interoperability.
@@ -2960,8 +2741,7 @@ void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool)
catch(const Exception & ) {}
if( !bExists )
{
- StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
}
bool bReadOnly = xSFI->isReadOnly( aPath );
@@ -2969,15 +2749,15 @@ void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool)
bool bDirectory = xSFI->isFolder( aPath );
if( bReadOnly )
{
- nFlags |= sal_uInt16(SbAttributes::READONLY);
+ nFlags |= SbAttributes::READONLY;
}
if( bHidden )
{
- nFlags |= sal_uInt16(SbAttributes::HIDDEN);
+ nFlags |= SbAttributes::HIDDEN;
}
if( bDirectory )
{
- nFlags |= sal_uInt16(SbAttributes::DIRECTORY);
+ nFlags |= SbAttributes::DIRECTORY;
}
}
catch(const Exception & )
@@ -2999,11 +2779,11 @@ void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool)
bool bDirectory = isFolder( aType );
if( bReadOnly )
{
- nFlags |= sal_uInt16(SbAttributes::READONLY);
+ nFlags |= SbAttributes::READONLY;
}
if( bDirectory )
{
- nFlags |= sal_uInt16(SbAttributes::DIRECTORY);
+ nFlags |= SbAttributes::DIRECTORY;
}
}
rPar.Get(0)->PutInteger(nFlags);
@@ -3128,8 +2908,7 @@ void SbRtl_EOF(StarBASIC *, SbxArray & rPar, bool)
SbiStream* pSbStrm = pIO->GetStream( nChannel );
if ( !pSbStrm )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
}
bool beof;
SvStream* pSvStrm = pSbStrm->GetStrm();
@@ -3169,8 +2948,7 @@ void SbRtl_FileAttr(StarBASIC *, SbxArray & rPar, bool)
SbiStream* pSbStrm = pIO->GetStream( nChannel );
if ( !pSbStrm )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
}
sal_Int16 nRet;
if (rPar.Get(2)->GetInteger() == 1)
@@ -3198,8 +2976,7 @@ void SbRtl_Loc(StarBASIC *, SbxArray & rPar, bool)
SbiStream* pSbStrm = pIO->GetStream( nChannel );
if ( !pSbStrm )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
}
SvStream* pSvStrm = pSbStrm->GetStrm();
std::size_t nPos;
@@ -3243,8 +3020,7 @@ void SbRtl_Lof(StarBASIC *, SbxArray & rPar, bool)
SbiStream* pSbStrm = pIO->GetStream( nChannel );
if ( !pSbStrm )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
}
SvStream* pSvStrm = pSbStrm->GetStrm();
sal_uInt64 const nLen = pSvStrm->TellEnd();
@@ -3259,16 +3035,14 @@ void SbRtl_Seek(StarBASIC *, SbxArray & rPar, bool)
int nArgs = static_cast<int>(rPar.Count());
if ( nArgs < 2 || nArgs > 3 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
sal_Int16 nChannel = rPar.Get(1)->GetInteger();
SbiIoSystem* pIO = GetSbData()->pInst->GetIoSystem();
SbiStream* pSbStrm = pIO->GetStream( nChannel );
if ( !pSbStrm )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL );
}
SvStream* pStrm = pSbStrm->GetStrm();
@@ -3287,8 +3061,7 @@ void SbRtl_Seek(StarBASIC *, SbxArray & rPar, bool)
sal_Int32 nPos = rPar.Get(2)->GetLong();
if ( nPos < 1 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
nPos--; // Basic counts from 1, SvStreams count from 0
pSbStrm->SetExpandOnWriteTo( 0 );
@@ -3324,14 +3097,34 @@ void SbRtl_Format(StarBASIC *, SbxArray & rPar, bool)
}
}
-// https://msdn.microsoft.com/en-us/vba/language-reference-vba/articles/formatnumber-function
-void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool)
+static bool IsMissing(SbxArray& rPar, const sal_uInt32 i)
+{
+ const sal_uInt32 nArgCount = rPar.Count();
+ if (nArgCount <= i)
+ return true;
+
+ SbxVariable* aPar = rPar.Get(i);
+ return (aPar->GetType() == SbxERROR && SbiRuntime::IsMissing(aPar, 1));
+}
+
+static sal_Int16 GetOptionalIntegerParamOrDefault(SbxArray& rPar, const sal_uInt32 i,
+ const sal_Int16 defaultValue)
+{
+ return IsMissing(rPar, i) ? defaultValue : rPar.Get(i)->GetInteger();
+}
+
+static OUString GetOptionalOUStringParamOrDefault(SbxArray& rPar, const sal_uInt32 i,
+ const OUString& defaultValue)
+{
+ return IsMissing(rPar, i) ? defaultValue : rPar.Get(i)->GetOUString();
+}
+
+static void lcl_FormatNumberPercent(SbxArray& rPar, bool isPercent)
{
const sal_uInt32 nArgCount = rPar.Count();
if (nArgCount < 2 || nArgCount > 6)
{
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
// The UI locale never changes -> we can use static value here
@@ -3342,8 +3135,7 @@ void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool)
nNumDigitsAfterDecimal = rPar.Get(2)->GetInteger();
if (nNumDigitsAfterDecimal < -1)
{
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
else if (nNumDigitsAfterDecimal > 255)
nNumDigitsAfterDecimal %= 256;
@@ -3366,8 +3158,7 @@ void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool)
// do nothing;
break;
default:
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
}
@@ -3384,8 +3175,7 @@ void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool)
bUseParensForNegativeNumbers = true;
break;
default:
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
}
@@ -3402,53 +3192,59 @@ void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool)
bGroupDigits = true;
break;
default:
- StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
- return;
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
}
}
double fVal = rPar.Get(1)->GetDouble();
+ if (isPercent)
+ fVal *= 100;
const bool bNegative = fVal < 0;
if (bNegative)
fVal = fabs(fVal); // Always work with non-negatives, to easily handle leading zero
static const sal_Unicode decSep = localeData.getNumDecimalSep().toChar();
- OUString aResult = rtl::math::doubleToUString(
+ OUStringBuffer aResult;
+ rtl::math::doubleToUStringBuffer(aResult,
fVal, rtl_math_StringFormat_F, nNumDigitsAfterDecimal, decSep,
bGroupDigits ? localeData.getDigitGrouping().getConstArray() : nullptr,
localeData.getNumThousandSep().toChar());
- if (!bIncludeLeadingDigit && aResult.getLength() > 1 && aResult.startsWith("0"))
- aResult = aResult.copy(1);
+ if (!bIncludeLeadingDigit && aResult.getLength() > 1)
+ aResult.stripStart('0');
if (nNumDigitsAfterDecimal > 0)
{
- sal_Int32 nActualDigits;
const sal_Int32 nSepPos = aResult.indexOf(decSep);
- if (nSepPos == -1)
- nActualDigits = 0;
- else
- nActualDigits = aResult.getLength() - nSepPos - 1;
// VBA allows up to 255 digits; rtl::math::doubleToUString outputs up to 15 digits
// for ~small numbers, so pad them as appropriate.
- if (nActualDigits < nNumDigitsAfterDecimal)
- {
- OUStringBuffer sBuf;
- comphelper::string::padToLength(sBuf, nNumDigitsAfterDecimal - nActualDigits, '0');
- aResult += sBuf;
- }
+ if (nSepPos >= 0)
+ comphelper::string::padToLength(aResult, nSepPos + nNumDigitsAfterDecimal + 1, '0');
}
if (bNegative)
{
if (bUseParensForNegativeNumbers)
- aResult = "(" + aResult + ")";
+ aResult.insert(0, '(').append(')');
else
- aResult = "-" + aResult;
+ aResult.insert(0, '-');
}
+ if (isPercent)
+ aResult.append('%');
+ rPar.Get(0)->PutString(aResult.makeStringAndClear());
+}
- rPar.Get(0)->PutString(aResult);
+// https://docs.microsoft.com/en-us/office/vba/Language/Reference/User-Interface-Help/formatnumber-function
+void SbRtl_FormatNumber(StarBASIC*, SbxArray& rPar, bool)
+{
+ return lcl_FormatNumberPercent(rPar, false);
+}
+
+// https://docs.microsoft.com/en-us/office/vba/Language/Reference/User-Interface-Help/formatpercent-function
+void SbRtl_FormatPercent(StarBASIC*, SbxArray& rPar, bool)
+{
+ return lcl_FormatNumberPercent(rPar, true);
}
namespace {
@@ -3479,7 +3275,11 @@ struct RandomNumberGenerator
}
};
-class theRandomNumberGenerator : public rtl::Static<RandomNumberGenerator, theRandomNumberGenerator> {};
+RandomNumberGenerator& theRandomNumberGenerator()
+{
+ static RandomNumberGenerator theGenerator;
+ return theGenerator;
+}
}
@@ -3492,7 +3292,7 @@ void SbRtl_Randomize(StarBASIC *, SbxArray & rPar, bool)
if (rPar.Count() == 2)
{
int nSeed = static_cast<int>(rPar.Get(1)->GetInteger());
- theRandomNumberGenerator::get().global_rng.seed(nSeed);
+ theRandomNumberGenerator().global_rng.seed(nSeed);
}
// without parameter, no need to do anything - RNG is seeded at first use
}
@@ -3506,7 +3306,7 @@ void SbRtl_Rnd(StarBASIC *, SbxArray & rPar, bool)
else
{
std::uniform_real_distribution<double> dist(0.0, 1.0);
- double const tmp(dist(theRandomNumberGenerator::get().global_rng));
+ double const tmp(dist(theRandomNumberGenerator().global_rng));
rPar.Get(0)->PutDouble(tmp);
}
}
@@ -3531,6 +3331,13 @@ void SbRtl_Shell(StarBASIC *, SbxArray & rPar, bool)
}
else
{
+ // Just go straight to error in this case
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ StarBASIC::Error(ERRCODE_BASIC_FILE_NOT_FOUND);
+ return;
+ }
+
oslProcessOption nOptions = osl_Process_SEARCHPATH | osl_Process_DETACHED;
OUString aCmdLine = rPar.Get(1)->GetOUString();
@@ -3543,30 +3350,21 @@ void SbRtl_Shell(StarBASIC *, SbxArray & rPar, bool)
aCmdLine += " " + tmp;
}
}
- else if( aCmdLine.isEmpty() )
- {
- // avoid special treatment (empty list)
- aCmdLine += " ";
- }
sal_Int32 nLen = aCmdLine.getLength();
// #55735 if there are parameters, they have to be separated
// #72471 also separate the single parameters
std::vector<OUString> aTokenVector;
- OUString aToken;
- sal_Int32 i = 0;
- sal_Unicode c;
- while( i < nLen )
+ for (sal_Int32 i = 0; i < nLen;)
{
- for ( ;; ++i )
+ sal_Unicode c = aCmdLine[i];
+ if (c == ' ' || c == '\t')
{
- c = aCmdLine[ i ];
- if ( c != ' ' && c != '\t' )
- {
- break;
- }
+ ++i;
+ continue;
}
+ OUString aToken;
if( c == '\"' || c == '\'' )
{
sal_Int32 iFoundPos = aCmdLine.indexOf( c, i + 1 );
@@ -3605,6 +3403,9 @@ void SbRtl_Shell(StarBASIC *, SbxArray & rPar, bool)
}
// #55735 / #72471 end
+ if (aTokenVector.empty())
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
+
sal_Int16 nWinStyle = 0;
if( nArgCount >= 3 )
{
@@ -3699,62 +3500,62 @@ void SbRtl_VarType(StarBASIC *, SbxArray & rPar, bool)
}
// 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
+const OUString & getBasicTypeName( SbxDataType eType )
+{
+ static constexpr OUString pTypeNames[] =
+ {
+ u"Empty"_ustr, // SbxEMPTY
+ u"Null"_ustr, // SbxNULL
+ u"Integer"_ustr, // SbxINTEGER
+ u"Long"_ustr, // SbxLONG
+ u"Single"_ustr, // SbxSINGLE
+ u"Double"_ustr, // SbxDOUBLE
+ u"Currency"_ustr, // SbxCURRENCY
+ u"Date"_ustr, // SbxDATE
+ u"String"_ustr, // SbxSTRING
+ u"Object"_ustr, // SbxOBJECT
+ u"Error"_ustr, // SbxERROR
+ u"Boolean"_ustr, // SbxBOOL
+ u"Variant"_ustr, // SbxVARIANT
+ u"DataObject"_ustr, // SbxDATAOBJECT
+ u"Unknown Type"_ustr,
+ u"Unknown Type"_ustr,
+ u"Char"_ustr, // SbxCHAR
+ u"Byte"_ustr, // SbxBYTE
+ u"UShort"_ustr, // SbxUSHORT
+ u"ULong"_ustr, // SbxULONG
+ u"Long64"_ustr, // SbxLONG64
+ u"ULong64"_ustr, // SbxULONG64
+ u"Int"_ustr, // SbxINT
+ u"UInt"_ustr, // SbxUINT
+ u"Void"_ustr, // SbxVOID
+ u"HResult"_ustr, // SbxHRESULT
+ u"Pointer"_ustr, // SbxPOINTER
+ u"DimArray"_ustr, // SbxDIMARRAY
+ u"CArray"_ustr, // SbxCARRAY
+ u"Userdef"_ustr, // SbxUSERDEF
+ u"Lpstr"_ustr, // SbxLPSTR
+ u"Lpwstr"_ustr, // SbxLPWSTR
+ u"Unknown Type"_ustr, // SbxCoreSTRING
+ u"WString"_ustr, // SbxWSTRING
+ u"WChar"_ustr, // SbxWCHAR
+ u"Int64"_ustr, // SbxSALINT64
+ u"UInt64"_ustr, // SbxSALUINT64
+ u"Decimal"_ustr, // SbxDECIMAL
};
size_t nPos = static_cast<size_t>(eType) & 0x0FFF;
- const size_t nTypeNameCount = SAL_N_ELEMENTS( pTypeNames );
+ const size_t nTypeNameCount = std::size( pTypeNames );
if ( nPos >= nTypeNameCount )
{
nPos = nTypeNameCount - 1;
}
- return OUString::createFromAscii(pTypeNames[nPos]);
+ return pTypeNames[nPos];
}
static OUString getObjectTypeName( SbxVariable* pVar )
{
- OUString sRet( "Object" );
+ OUString sRet( u"Object"_ustr );
if ( pVar )
{
SbxBase* pBaseObj = pVar->GetObject();
@@ -3796,7 +3597,7 @@ static OUString getObjectTypeName( SbxVariable* pVar )
{
try
{
- xInv->getValue( "$GetTypeName" ) >>= sRet;
+ xInv->getValue( u"$GetTypeName"_ustr ) >>= sRet;
}
catch(const Exception& )
{
@@ -3846,14 +3647,9 @@ void SbRtl_TypeName(StarBASIC *, SbxArray & rPar, bool)
void SbRtl_Len(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- }
- else
- {
- const OUString& rStr = rPar.Get(1)->GetOUString();
- rPar.Get(0)->PutLong(rStr.getLength());
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+ const OUString aStr = rPar.Get(1)->GetOUString();
+ rPar.Get(0)->PutLong(aStr.getLength());
}
void SbRtl_DDEInitiate(StarBASIC *, SbxArray & rPar, bool)
@@ -3861,15 +3657,14 @@ void SbRtl_DDEInitiate(StarBASIC *, SbxArray & rPar, bool)
int nArgs = static_cast<int>(rPar.Count());
if ( nArgs != 3 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- const OUString& rApp = rPar.Get(1)->GetOUString();
- const OUString& rTopic = rPar.Get(2)->GetOUString();
+ const OUString aApp = rPar.Get(1)->GetOUString();
+ const OUString aTopic = rPar.Get(2)->GetOUString();
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
size_t nChannel;
- ErrCode nDdeErr = pDDE->Initiate( rApp, rTopic, nChannel );
+ ErrCode nDdeErr = pDDE->Initiate( aApp, aTopic, nChannel );
if( nDdeErr )
{
StarBASIC::Error( nDdeErr );
@@ -3904,8 +3699,7 @@ void SbRtl_DDETerminateAll(StarBASIC *, SbxArray & rPar, bool)
int nArgs = static_cast<int>(rPar.Count());
if ( nArgs != 1 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
@@ -3921,14 +3715,13 @@ void SbRtl_DDERequest(StarBASIC *, SbxArray & rPar, bool)
int nArgs = static_cast<int>(rPar.Count());
if ( nArgs != 3 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
size_t nChannel = rPar.Get(1)->GetInteger();
- const OUString& rItem = rPar.Get(2)->GetOUString();
+ const OUString aItem = rPar.Get(2)->GetOUString();
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
OUString aResult;
- ErrCode nDdeErr = pDDE->Request( nChannel, rItem, aResult );
+ ErrCode nDdeErr = pDDE->Request( nChannel, aItem, aResult );
if( nDdeErr )
{
StarBASIC::Error( nDdeErr );
@@ -3945,13 +3738,12 @@ void SbRtl_DDEExecute(StarBASIC *, SbxArray & rPar, bool)
int nArgs = static_cast<int>(rPar.Count());
if ( nArgs != 3 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
size_t nChannel = rPar.Get(1)->GetInteger();
- const OUString& rCommand = rPar.Get(2)->GetOUString();
+ const OUString aCommand = rPar.Get(2)->GetOUString();
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
- ErrCode nDdeErr = pDDE->Execute( nChannel, rCommand );
+ ErrCode nDdeErr = pDDE->Execute( nChannel, aCommand );
if( nDdeErr )
{
StarBASIC::Error( nDdeErr );
@@ -3964,14 +3756,13 @@ void SbRtl_DDEPoke(StarBASIC *, SbxArray & rPar, bool)
int nArgs = static_cast<int>(rPar.Count());
if ( nArgs != 4 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
size_t nChannel = rPar.Get(1)->GetInteger();
- const OUString& rItem = rPar.Get(2)->GetOUString();
- const OUString& rData = rPar.Get(3)->GetOUString();
+ const OUString aItem = rPar.Get(2)->GetOUString();
+ const OUString aData = rPar.Get(3)->GetOUString();
SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl();
- ErrCode nDdeErr = pDDE->Poke( nChannel, rItem, rData );
+ ErrCode nDdeErr = pDDE->Poke( nChannel, aItem, aData );
if( nDdeErr )
{
StarBASIC::Error( nDdeErr );
@@ -3983,8 +3774,7 @@ void SbRtl_FreeFile(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 1)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
SbiIoSystem* pIO = GetSbData()->pInst->GetIoSystem();
short nChannel = 1;
@@ -4005,56 +3795,42 @@ void SbRtl_LBound(StarBASIC *, SbxArray & rPar, bool)
{
const sal_uInt32 nParCount = rPar.Count();
if ( nParCount != 3 && nParCount != 2 )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+
SbxBase* pParObj = rPar.Get(1)->GetObject();
SbxDimArray* pArr = dynamic_cast<SbxDimArray*>( pParObj );
- if( pArr )
- {
- sal_Int32 nLower, nUpper;
- short nDim = (nParCount == 3) ? static_cast<short>(rPar.Get(2)->GetInteger()) : 1;
- if (!pArr->GetDim(nDim, nLower, nUpper))
- StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE );
- else
- rPar.Get(0)->PutLong(nLower);
- }
- else
- StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS );
+ if( !pArr )
+ return StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS );
+
+ sal_Int32 nLower, nUpper;
+ short nDim = (nParCount == 3) ? static_cast<short>(rPar.Get(2)->GetInteger()) : 1;
+ if (!pArr->GetDim(nDim, nLower, nUpper))
+ return StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE );
+ rPar.Get(0)->PutLong(nLower);
}
void SbRtl_UBound(StarBASIC *, SbxArray & rPar, bool)
{
const sal_uInt32 nParCount = rPar.Count();
if ( nParCount != 3 && nParCount != 2 )
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
SbxBase* pParObj = rPar.Get(1)->GetObject();
SbxDimArray* pArr = dynamic_cast<SbxDimArray*>( pParObj );
- if( pArr )
- {
- sal_Int32 nLower, nUpper;
- short nDim = (nParCount == 3) ? static_cast<short>(rPar.Get(2)->GetInteger()) : 1;
- if (!pArr->GetDim(nDim, nLower, nUpper))
- StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE );
- else
- rPar.Get(0)->PutLong(nUpper);
- }
- else
- StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS );
+ if( !pArr )
+ return StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS );
+
+ sal_Int32 nLower, nUpper;
+ short nDim = (nParCount == 3) ? static_cast<short>(rPar.Get(2)->GetInteger()) : 1;
+ if (!pArr->GetDim(nDim, nLower, nUpper))
+ return StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE );
+ rPar.Get(0)->PutLong(nUpper);
}
void SbRtl_RGB(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 4)
- {
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
- }
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
sal_Int32 nRed = rPar.Get(1)->GetInteger() & 0xFF;
sal_Int32 nGreen = rPar.Get(2)->GetInteger() & 0xFF;
@@ -4103,31 +3879,61 @@ void SbRtl_QBColor(StarBASIC *, SbxArray & rPar, bool)
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
sal_Int16 nCol = rPar.Get(1)->GetInteger();
if( nCol < 0 || nCol > 15 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
sal_Int32 nRGB = pRGB[ nCol ];
rPar.Get(0)->PutLong(nRGB);
}
+static std::vector<sal_uInt8> byteArray2Vec(SbxArray* pArr)
+{
+ std::vector<sal_uInt8> result;
+ if (pArr)
+ {
+ const sal_uInt32 nCount = pArr->Count();
+ result.reserve(nCount + 1); // to avoid reallocation when padding in vbFromUnicode
+ for (sal_uInt32 i = 0; i < nCount; i++)
+ result.push_back(pArr->Get(i)->GetByte());
+ }
+ return result;
+}
+
+// Makes sure to get the byte array if passed, or the string converted to the bytes using
+// StringToByteArray in basic/source/sbx/sbxstr.cxx
+static std::vector<sal_uInt8> getByteArray(const SbxValue& val)
+{
+ if (val.GetFullType() == SbxOBJECT)
+ if (auto pObj = val.GetObject())
+ if (pObj->GetType() == (SbxARRAY | SbxBYTE))
+ if (auto pArr = dynamic_cast<SbxArray*>(pObj))
+ return byteArray2Vec(pArr);
+
+ // Convert to string
+ tools::SvRef<SbxValue> pStringValue(new SbxValue(SbxSTRING));
+ *pStringValue = val;
+
+ // Convert string to byte array
+ tools::SvRef<SbxValue> pValue(new SbxValue(SbxOBJECT));
+ pValue->PutObject(new SbxArray(SbxBYTE));
+ *pValue = *pStringValue; // Does the magic of conversion of strings to byte arrays
+ return byteArray2Vec(dynamic_cast<SbxArray*>(pValue->GetObject()));
+}
+
// StrConv(string, conversion, LCID)
void SbRtl_StrConv(StarBASIC *, SbxArray & rPar, bool)
{
const sal_uInt32 nArgCount = rPar.Count() - 1;
if( nArgCount < 2 || nArgCount > 3 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- OUString aOldStr = rPar.Get(1)->GetOUString();
sal_Int32 nConversion = rPar.Get(2)->GetLong();
LanguageType nLanguage = LANGUAGE_SYSTEM;
if (nArgCount == 3)
@@ -4135,127 +3941,101 @@ void SbRtl_StrConv(StarBASIC *, SbxArray & rPar, bool)
sal_Int32 lcid = rPar.Get(3)->GetLong();
nLanguage = LanguageType(lcid);
}
- OUString sLanguage = LanguageTag(nLanguage).getLanguage();
- rtl_TextEncoding encodingVal = utl_getWinTextEncodingFromLangStr(sLanguage);
- sal_Int32 nOldLen = aOldStr.getLength();
- if( nOldLen == 0 )
+ if (nConversion == ooo::vba::VbStrConv::vbUnicode) // This mode does not combine
{
- // null string,return
- rPar.Get(0)->PutString(aOldStr);
+ // Assume that the passed byte array is encoded in the defined encoding, convert to
+ // UTF-16 and store as string. Passed strings are converted to byte array first.
+ auto inArray = getByteArray(*rPar.Get(1));
+ std::string_view s(reinterpret_cast<char*>(inArray.data()), inArray.size() / sizeof(char));
+ const auto encoding = utl_getWinTextEncodingFromLangStr(LanguageTag(nLanguage).getBcp47());
+ OUString aOUStr = OStringToOUString(s, encoding);
+ rPar.Get(0)->PutString(aOUStr);
return;
}
- TransliterationFlags nType = TransliterationFlags::NONE;
- if ( (nConversion & 0x03) == 3 ) // vbProperCase
- {
- const CharClass& rCharClass = GetCharClass();
- aOldStr = rCharClass.titlecase( aOldStr.toAsciiLowerCase(), 0, nOldLen );
- }
- else if ( (nConversion & 0x01) == 1 ) // vbUpperCase
- {
- nType |= TransliterationFlags::LOWERCASE_UPPERCASE;
- }
- else if ( (nConversion & 0x02) == 2 ) // vbLowerCase
- {
- nType |= TransliterationFlags::UPPERCASE_LOWERCASE;
- }
- if ( (nConversion & 0x04) == 4 ) // vbWide
- {
- nType |= TransliterationFlags::HALFWIDTH_FULLWIDTH;
- }
- else if ( (nConversion & 0x08) == 8 ) // vbNarrow
- {
- nType |= TransliterationFlags::FULLWIDTH_HALFWIDTH;
- }
- if ( (nConversion & 0x10) == 16) // vbKatakana
- {
- nType |= TransliterationFlags::HIRAGANA_KATAKANA;
- }
- else if ( (nConversion & 0x20) == 32 ) // vbHiragana
- {
- nType |= TransliterationFlags::KATAKANA_HIRAGANA;
- }
- OUString aNewStr( aOldStr );
- if( nType != TransliterationFlags::NONE )
+ if (nConversion == ooo::vba::VbStrConv::vbFromUnicode) // This mode does not combine
{
- 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 );
- }
+ // Assume that the passed byte array is UTF-16-encoded (system-endian), convert to specified
+ // encoding and store as byte array. Passed strings are converted to byte array first.
+ auto inArray = getByteArray(*rPar.Get(1));
+ while (inArray.size() % sizeof(sal_Unicode))
+ inArray.push_back('\0');
+ std::u16string_view s(reinterpret_cast<sal_Unicode*>(inArray.data()),
+ inArray.size() / sizeof(sal_Unicode));
+ const auto encoding = utl_getWinTextEncodingFromLangStr(LanguageTag(nLanguage).getBcp47());
+ OString aOStr = OUStringToOString(s, encoding);
+ const sal_Int32 lb = IsBaseIndexOne() ? 1 : 0;
+ const sal_Int32 ub = lb + aOStr.getLength() - 1;
+ SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
+ pArray->unoAddDim(lb, ub);
- 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();
- std::unique_ptr<char[]> pChar(new char[nSize+1]);
- for( sal_Int32 i=0; i < nSize; i++ )
+ for (sal_Int32 i = 0; i < aOStr.getLength(); ++i)
{
- pChar[i] = static_cast< char >( (i%2) ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
- if( i%2 )
- {
- pSrc++;
- }
+ SbxVariable* pNew = new SbxVariable(SbxBYTE);
+ pNew->PutByte(aOStr[i]);
+ pArray->Put(pNew, i);
}
- pChar[nSize] = '\0';
- OString aOStr(pChar.get());
- // there is no concept about default codepage in unix. so it is incorrectly in unix
- OUString aOUStr = OStringToOUString(aOStr, encodingVal);
- rPar.Get(0)->PutString(aOUStr);
+ SbxVariable* retVar = rPar.Get(0);
+ SbxFlagBits nFlags = retVar->GetFlags();
+ retVar->ResetFlag(SbxFlagBits::Fixed);
+ retVar->PutObject(pArray);
+ retVar->SetFlags(nFlags);
+ retVar->SetParameters(nullptr);
return;
}
- else if ( (nConversion & 0x80) == 128 ) // vbFromUnicode
+
+ std::vector<TransliterationFlags> aTranslitSet;
+ auto check = [&nConversion, &aTranslitSet](sal_Int32 conv, TransliterationFlags flag)
{
- // there is no concept about default codepage in unix. so it is incorrectly in unix
- OString aOStr = OUStringToOString(aNewStr, encodingVal);
- const char* pChar = aOStr.getStr();
- sal_Int32 nArraySize = aOStr.getLength();
- SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
- bool bIncIndex = IsBaseIndexOne();
- if(nArraySize)
+ if ((nConversion & conv) != conv)
+ return false;
+
+ aTranslitSet.push_back(flag);
+ nConversion &= ~conv;
+ return true;
+ };
+
+ // Check mutually exclusive bits together
+
+ if (!check(ooo::vba::VbStrConv::vbProperCase, TransliterationFlags::TITLE_CASE))
+ if (!check(ooo::vba::VbStrConv::vbUpperCase, TransliterationFlags::LOWERCASE_UPPERCASE))
+ check(ooo::vba::VbStrConv::vbLowerCase, TransliterationFlags::UPPERCASE_LOWERCASE);
+
+ if (!check(ooo::vba::VbStrConv::vbWide, TransliterationFlags::HALFWIDTH_FULLWIDTH))
+ check(ooo::vba::VbStrConv::vbNarrow, TransliterationFlags::FULLWIDTH_HALFWIDTH);
+
+ if (!check(ooo::vba::VbStrConv::vbKatakana, TransliterationFlags::HIRAGANA_KATAKANA))
+ check(ooo::vba::VbStrConv::vbHiragana, TransliterationFlags::KATAKANA_HIRAGANA);
+
+ if (nConversion) // unknown / incorrectly combined bits
+ return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
+
+ OUString aStr = rPar.Get(1)->GetOUString();
+ if (!aStr.isEmpty() && !aTranslitSet.empty())
+ {
+ const uno::Reference< uno::XComponentContext >& xContext = getProcessComponentContext();
+
+ for (auto transliterationFlag : aTranslitSet)
{
- if( bIncIndex )
+ if (transliterationFlag == TransliterationFlags::TITLE_CASE)
{
- pArray->AddDim(1, nArraySize);
+ // TransliterationWrapper only handles the first character of the passed string
+ // when handling TITLE_CASE; see Transliteration_titlecase::transliterateImpl in
+ // i18npool/source/transliteration/transliteration_body.cxx
+ CharClass aCharClass{ xContext, LanguageTag(nLanguage) };
+ aStr = aCharClass.titlecase(aCharClass.lowercase(aStr));
}
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( SbxFlagBits::Write );
- sal_Int32 aIdx[1];
- aIdx[0] = i;
- if( bIncIndex )
- {
- ++aIdx[0];
+ utl::TransliterationWrapper aWrapper(xContext, transliterationFlag);
+ aStr = aWrapper.transliterate(aStr, nLanguage, 0, aStr.getLength(), nullptr);
}
- pArray->Put(pNew, aIdx);
}
-
- SbxVariableRef refVar = rPar.Get(0);
- SbxFlagBits nFlags = refVar->GetFlags();
- refVar->ResetFlag( SbxFlagBits::Fixed );
- refVar->PutObject( pArray );
- refVar->SetFlags( nFlags );
- refVar->SetParameters( nullptr );
- return;
}
- rPar.Get(0)->PutString(aNewStr);
+
+ rPar.Get(0)->PutString(aStr);
}
@@ -4263,8 +4043,7 @@ void SbRtl_Beep(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 1)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
Sound::Beep();
}
@@ -4273,8 +4052,7 @@ void SbRtl_Load(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
@@ -4288,7 +4066,7 @@ void SbRtl_Load(StarBASIC *, SbxArray & rPar, bool)
}
else if (SbxObject* pSbxObj = dynamic_cast<SbxObject*>(pObj))
{
- SbxVariable* pVar = pSbxObj->Find("Load", SbxClassType::Method);
+ SbxVariable* pVar = pSbxObj->Find(u"Load"_ustr, SbxClassType::Method);
if( pVar )
{
pVar->GetInteger();
@@ -4301,8 +4079,7 @@ void SbRtl_Unload(StarBASIC *, SbxArray & rPar, bool)
rPar.Get(0)->PutEmpty();
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
@@ -4316,7 +4093,7 @@ void SbRtl_Unload(StarBASIC *, SbxArray & rPar, bool)
}
else if (SbxObject *pSbxObj = dynamic_cast<SbxObject*>(pObj))
{
- SbxVariable* pVar = pSbxObj->Find("Unload", SbxClassType::Method);
+ SbxVariable* pVar = pSbxObj->Find(u"Unload"_ustr, SbxClassType::Method);
if( pVar )
{
pVar->GetInteger();
@@ -4328,8 +4105,7 @@ void SbRtl_LoadPicture(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 2)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
OUString aFileURL = getFullPath(rPar.Get(1)->GetOUString());
@@ -4352,8 +4128,7 @@ void SbRtl_SavePicture(StarBASIC *, SbxArray & rPar, bool)
rPar.Get(0)->PutEmpty();
if (rPar.Count() != 3)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
SbxBase* pObj = rPar.Get(1)->GetObject();
@@ -4371,40 +4146,23 @@ void SbRtl_MsgBox(StarBASIC *, SbxArray & rPar, bool)
const sal_uInt32 nArgCount = rPar.Count();
if( nArgCount < 2 || nArgCount > 6 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
- WinBits nType = 0; // MB_OK
- if( nArgCount >= 3 )
- nType = static_cast<WinBits>(rPar.Get(2)->GetInteger());
- WinBits nStyle = nType;
- nStyle &= 15; // delete bits 4-16
- if (nStyle > 5)
- nStyle = 0;
-
- enum BasicResponse
- {
- Ok = 1,
- Cancel = 2,
- Abort = 3,
- Retry = 4,
- Ignore = 5,
- Yes = 6,
- No = 7
- };
- OUString aMsg = rPar.Get(1)->GetOUString();
- OUString aTitle;
- if( nArgCount >= 4 )
+ // tdf#147529 - check for missing parameters
+ if (IsMissing(rPar, 1))
{
- aTitle = rPar.Get(3)->GetOUString();
- }
- else
- {
- aTitle = Application::GetDisplayName();
+ return StarBASIC::Error(ERRCODE_BASIC_NOT_OPTIONAL);
}
- WinBits nDialogType = nType & (16+32+64);
+ // tdf#151012 - initialize optional parameters with their default values (number of buttons)
+ sal_Int16 nType = GetOptionalIntegerParamOrDefault(rPar, 2, SbMB::OK);
+
+ OUString aMsg = rPar.Get(1)->GetOUString();
+ // tdf#151012 - initialize optional parameters with their default values (title of dialog box)
+ OUString aTitle = GetOptionalOUStringParamOrDefault(rPar, 3, Application::GetDisplayName());
+
+ sal_Int16 nDialogType = nType & (SbMB::ICONSTOP | SbMB::ICONQUESTION | SbMB::ICONINFORMATION);
SolarMutexGuard aSolarGuard;
weld::Widget* pParent = Application::GetDefDialogParent();
@@ -4413,85 +4171,64 @@ void SbRtl_MsgBox(StarBASIC *, SbxArray & rPar, bool)
switch (nDialogType)
{
- case 16:
+ case SbMB::ICONSTOP:
eType = VclMessageType::Error;
break;
- case 32:
+ case SbMB::ICONQUESTION:
eType = VclMessageType::Question;
break;
- case 48:
+ case SbMB::ICONEXCLAMATION:
eType = VclMessageType::Warning;
break;
- case 64:
+ case SbMB::ICONINFORMATION:
eType = VclMessageType::Info;
break;
}
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
- eType, VclButtonsType::NONE, aMsg));
+ eType, VclButtonsType::NONE, aMsg, GetpApp()));
- switch (nStyle)
+ std::vector<std::pair<StandardButtonType, sal_Int16>> buttons;
+ switch (nType & 0x0F) // delete bits 4-16
{
- case 0: // MB_OK
+ case SbMB::OK:
default:
- xBox->add_button(GetStandardText(StandardButtonType::OK), BasicResponse::Ok);
+ buttons.emplace_back(StandardButtonType::OK, SbMB::Response::OK);
break;
- case 1: // MB_OKCANCEL
- xBox->add_button(GetStandardText(StandardButtonType::OK), BasicResponse::Ok);
- xBox->add_button(GetStandardText(StandardButtonType::Cancel), BasicResponse::Cancel);
-
- if (nType & 256 || nType & 512)
- xBox->set_default_response(BasicResponse::Cancel);
- else
- xBox->set_default_response(BasicResponse::Ok);
-
+ case SbMB::OKCANCEL:
+ buttons.emplace_back(StandardButtonType::OK, SbMB::Response::OK);
+ buttons.emplace_back(StandardButtonType::Cancel, SbMB::Response::CANCEL);
break;
- case 2: // MB_ABORTRETRYIGNORE
- xBox->add_button(GetStandardText(StandardButtonType::Abort), BasicResponse::Abort);
- xBox->add_button(GetStandardText(StandardButtonType::Retry), BasicResponse::Retry);
- xBox->add_button(GetStandardText(StandardButtonType::Ignore), BasicResponse::Ignore);
-
- if (nType & 256)
- xBox->set_default_response(BasicResponse::Retry);
- else if (nType & 512)
- xBox->set_default_response(BasicResponse::Ignore);
- else
- xBox->set_default_response(BasicResponse::Cancel);
-
+ case SbMB::ABORTRETRYIGNORE:
+ buttons.emplace_back(StandardButtonType::Abort, SbMB::Response::ABORT);
+ buttons.emplace_back(StandardButtonType::Retry, SbMB::Response::RETRY);
+ buttons.emplace_back(StandardButtonType::Ignore, SbMB::Response::IGNORE);
break;
- case 3: // MB_YESNOCANCEL
- xBox->add_button(GetStandardText(StandardButtonType::Yes), BasicResponse::Yes);
- xBox->add_button(GetStandardText(StandardButtonType::No), BasicResponse::No);
- xBox->add_button(GetStandardText(StandardButtonType::Cancel), BasicResponse::Cancel);
-
- if (nType & 256 || nType & 512)
- xBox->set_default_response(BasicResponse::Cancel);
- else
- xBox->set_default_response(BasicResponse::Yes);
-
+ case SbMB::YESNOCANCEL:
+ buttons.emplace_back(StandardButtonType::Yes, SbMB::Response::YES);
+ buttons.emplace_back(StandardButtonType::No, SbMB::Response::NO);
+ buttons.emplace_back(StandardButtonType::Cancel, SbMB::Response::CANCEL);
break;
- case 4: // MB_YESNO
- xBox->add_button(GetStandardText(StandardButtonType::Yes), BasicResponse::Yes);
- xBox->add_button(GetStandardText(StandardButtonType::No), BasicResponse::No);
-
- if (nType & 256 || nType & 512)
- xBox->set_default_response(BasicResponse::No);
- else
- xBox->set_default_response(BasicResponse::Yes);
-
+ case SbMB::YESNO:
+ buttons.emplace_back(StandardButtonType::Yes, SbMB::Response::YES);
+ buttons.emplace_back(StandardButtonType::No, SbMB::Response::NO);
break;
- case 5: // MB_RETRYCANCEL
- xBox->add_button(GetStandardText(StandardButtonType::Retry), BasicResponse::Retry);
- xBox->add_button(GetStandardText(StandardButtonType::Cancel), BasicResponse::Cancel);
-
- if (nType & 256 || nType & 512)
- xBox->set_default_response(BasicResponse::Cancel);
- else
- xBox->set_default_response(BasicResponse::Retry);
-
+ case SbMB::RETRYCANCEL:
+ buttons.emplace_back(StandardButtonType::Retry, SbMB::Response::RETRY);
+ buttons.emplace_back(StandardButtonType::Cancel, SbMB::Response::CANCEL);
break;
}
+ for (auto [buttonType, buttonResponse] : buttons)
+ xBox->add_button(GetStandardText(buttonType), buttonResponse);
+
+ std::size_t default_button = 0;
+ if (nType & SbMB::DEFBUTTON2)
+ default_button = 1;
+ else if (nType & SbMB::DEFBUTTON3)
+ default_button = 2;
+ xBox->set_default_response(buttons[std::min(default_button, buttons.size() - 1)].second);
+
xBox->set_title(aTitle);
sal_Int16 nRet = xBox->run();
rPar.Get(0)->PutInteger(nRet);
@@ -4503,7 +4240,7 @@ void SbRtl_SetAttr(StarBASIC *, SbxArray & rPar, bool)
if (rPar.Count() == 3)
{
OUString aStr = rPar.Get(1)->GetOUString();
- SbAttributes nFlags = static_cast<SbAttributes>(rPar.Get(2)->GetInteger());
+ sal_Int16 nFlags = rPar.Get(2)->GetInteger();
if( hasUno() )
{
@@ -4514,7 +4251,7 @@ void SbRtl_SetAttr(StarBASIC *, SbxArray & rPar, bool)
{
bool bReadOnly = bool(nFlags & SbAttributes::READONLY);
xSFI->setReadOnly( aStr, bReadOnly );
- bool bHidden = bool(nFlags & SbAttributes::HIDDEN);
+ bool bHidden = bool(nFlags & SbAttributes::HIDDEN);
xSFI->setHidden( aStr, bHidden );
}
catch(const Exception & )
@@ -4609,8 +4346,7 @@ void SbRtl_Partition(StarBASIC *, SbxArray & rPar, bool)
{
if (rPar.Count() != 5)
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
sal_Int32 nNumber = rPar.Get(1)->GetLong();
@@ -4620,8 +4356,7 @@ void SbRtl_Partition(StarBASIC *, SbxArray & rPar, bool)
if( nStart < 0 || nStop <= nStart || nInterval < 1 )
{
- StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
- return;
+ return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
}
// the Partition function inserts leading spaces before lowervalue and uppervalue
@@ -4687,28 +4422,10 @@ void SbRtl_Partition(StarBASIC *, SbxArray & rPar, bool)
#endif
-static tools::Long GetDayDiff( const Date& rDate )
-{
- Date aRefDate( 1,1,1900 );
- tools::Long nDiffDays;
- if ( aRefDate > rDate )
- {
- nDiffDays = aRefDate - rDate;
- nDiffDays *= -1;
- }
- else
- {
- nDiffDays = rDate - aRefDate;
- }
- nDiffDays += 2; // adjustment VisualBasic: 1.Jan.1900 == 2
- return nDiffDays;
-}
-
sal_Int16 implGetDateYear( double aDate )
{
- Date aRefDate( 1,1,1900 );
- tools::Long nDays = static_cast<tools::Long>(aDate);
- nDays -= 2; // standardize: 1.1.1900 => 0.0
+ Date aRefDate(1899'12'30);
+ sal_Int32 nDays = static_cast<sal_Int32>(aDate);
aRefDate.AddDays( nDays );
sal_Int16 nRet = aRefDate.GetYear();
return nRet;
@@ -4820,40 +4537,34 @@ bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
}
}
- tools::Long nDiffDays = GetDayDiff( aCurDate );
- rdRet = static_cast<double>(nDiffDays);
+ rdRet = GetDayDiff(aCurDate);
return true;
}
-double implTimeSerial( sal_Int16 nHours, sal_Int16 nMinutes, sal_Int16 nSeconds )
+double implTimeSerial(sal_Int16 nHours, sal_Int16 nMinutes, sal_Int16 nSeconds,
+ sal_Int32 nMilliSeconds)
{
- return
- static_cast<double>( nHours * ::tools::Time::secondPerHour +
- nMinutes * ::tools::Time::secondPerMinute +
- nSeconds)
- /
- static_cast<double>( ::tools::Time::secondPerDay );
+ return (nHours * ::tools::Time::milliSecPerHour + nMinutes * ::tools::Time::milliSecPerMinute
+ + nSeconds * ::tools::Time::milliSecPerSec + nMilliSeconds)
+ / static_cast<double>(::tools::Time::milliSecPerDay);
}
-bool implDateTimeSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay,
- sal_Int16 nHour, sal_Int16 nMinute, sal_Int16 nSecond,
- double& rdRet )
+bool implDateTimeSerial(sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, sal_Int16 nHour,
+ sal_Int16 nMinute, sal_Int16 nSecond, sal_Int32 nMilliSecond, double& rdRet)
{
double dDate;
if(!implDateSerial(nYear, nMonth, nDay, false/*bUseTwoDigitYear*/, SbDateCorrection::None, dDate))
return false;
- rdRet += dDate + implTimeSerial(nHour, nMinute, nSecond);
+ rdRet += dDate + implTimeSerial(nHour, nMinute, nSecond, nMilliSecond);
return true;
}
sal_Int16 implGetMinute( double dDate )
{
- double nFrac = dDate - floor( dDate );
- nFrac *= 86400.0;
- sal_Int32 nSeconds = static_cast<sal_Int32>(nFrac + 0.5);
- sal_Int16 nTemp = static_cast<sal_Int16>(nSeconds % 3600);
- sal_Int16 nMin = nTemp / 60;
- return nMin;
+ double nFrac = (dDate - floor(dDate)) * ::tools::Time::milliSecPerDay;
+ sal_uInt64 nMilliSeconds = static_cast<sal_uInt64>(nFrac + 0.5);
+ return static_cast<sal_Int16>((nMilliSeconds / ::tools::Time::milliSecPerMinute)
+ % ::tools::Time::minutePerHour);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */