diff options
Diffstat (limited to 'basic/source/runtime/methods.cxx')
-rw-r--r-- | basic/source/runtime/methods.cxx | 1691 |
1 files changed, 755 insertions, 936 deletions
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx index 7e9a1adcccd7..4dfcdc210ea3 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> @@ -60,6 +59,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 +68,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,10 +101,16 @@ 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 void FilterWhiteSpace( OUString& rStr ) @@ -136,8 +134,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 +181,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 +199,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) - { - 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()) + nCode = rPar.Get(1)->GetLong(); + if( nCode > 65535 ) { - 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 +251,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())); - } + 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 +371,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 +395,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 +410,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 +429,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 +444,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 +493,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 +623,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(); @@ -705,8 +653,7 @@ void SbRtl_RmDir(StarBASIC *, SbxArray & rPar, bool) { if( !xSFI->isFolder( aPath ) ) { - StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND ); - return; + return StarBASIC::Error( ERRCODE_BASIC_PATH_NOT_FOUND ); } SbiInstance* pInst = GetSbData()->pInst; bool bCompatibility = ( pInst && pInst->IsCompatibility() ); @@ -715,8 +662,7 @@ void SbRtl_RmDir(StarBASIC *, SbxArray & rPar, bool) Sequence< OUString > aContent = xSFI->getFolderContents( aPath, true ); if( aContent.hasElements() ) { - StarBASIC::Error( ERRCODE_BASIC_ACCESS_ERROR ); - return; + return StarBASIC::Error( ERRCODE_BASIC_ACCESS_ERROR ); } } @@ -748,72 +694,65 @@ 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) @@ -923,78 +862,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 +945,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); } @@ -1163,8 +1076,7 @@ void SbRtl_Mid(StarBASIC *, SbxArray & rPar, bool bWrite) bool bCompatibility = ( pInst && pInst->IsCompatibility() ); if( bCompatibility ) { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - return; + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); } nStartPos = nArgLen; } @@ -1224,23 +1136,14 @@ void SbRtl_Mid(StarBASIC *, SbxArray & rPar, bool bWrite) void SbRtl_Oct(StarBASIC *, SbxArray & rPar, bool) { if (rPar.Count() < 2) - { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - } - else - { - char aBuffer[16]; - SbxVariableRef pArg = rPar.Get(1); - if ( pArg->IsInteger() ) - { - snprintf( aBuffer, sizeof(aBuffer), "%o", pArg->GetInteger() ); - } - else - { - snprintf( aBuffer, sizeof(aBuffer), "%lo", static_cast<long unsigned int>(pArg->GetLong()) ); - } - rPar.Get(0)->PutString(OUString::createFromAscii(aBuffer)); - } + 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]]]) @@ -1249,10 +1152,7 @@ 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 +1163,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 +1177,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 +1201,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& rStr = rPar.Get(1)->GetOUString(); + int nResultLen = rPar.Get(2)->GetLong(); + if( nResultLen < 0 ) { + nResultLen = 0; StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); } - else + int nStrLen = rStr.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 = rStr.copy( nStrLen - nResultLen ); + rPar.Get(0)->PutString(aResultStr); } void SbRtl_RTL(StarBASIC * pBasic, SbxArray & rPar, bool) @@ -1372,53 +1279,31 @@ 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) - { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - } - else - { - double aDouble = rPar.Get(1)->GetDouble(); - sal_Int16 nResult = 0; - if ( aDouble > 0 ) - { - nResult = 1; - } - else if ( aDouble < 0 ) - { - nResult = -1; - } - rPar.Get(0)->PutInteger(nResult); - } -} + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); -void SbRtl_Space(StarBASIC *, SbxArray & rPar, bool) -{ - if (rPar.Count() < 2) + 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 ) { - OUStringBuffer aBuf; - string::padToLength(aBuf, rPar.Get(1)->GetLong(), ' '); - rPar.Get(0)->PutString(aBuf.makeStringAndClear()); + nResult = -1; } + rPar.Get(0)->PutInteger(nResult); } -void SbRtl_Spc(StarBASIC *, SbxArray & rPar, bool) +void SbRtl_Space(StarBASIC *, SbxArray & rPar, bool) { if (rPar.Count() < 2) { @@ -1426,8 +1311,9 @@ void SbRtl_Spc(StarBASIC *, SbxArray & rPar, bool) } else { - OUStringBuffer aBuf; - string::padToLength(aBuf, rPar.Get(1)->GetLong(), ' '); + const sal_Int32 nCount = rPar.Get(1)->GetLong(); + OUStringBuffer aBuf(nCount); + string::padToLength(aBuf, nCount, ' '); rPar.Get(0)->PutString(aBuf.makeStringAndClear()); } } @@ -1613,8 +1499,9 @@ void SbRtl_Tab(StarBASIC *, SbxArray & rPar, bool) StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); else { - OUStringBuffer aStr; - comphelper::string::padToLength(aStr, rPar.Get(1)->GetLong(), '\t'); + 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()); } } @@ -1707,9 +1594,8 @@ void SbRtl_Val(StarBASIC *, SbxArray & rPar, bool) // 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 +1604,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 +1637,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 +1648,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())); @@ -1799,8 +1682,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 +1693,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())); @@ -1855,8 +1736,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 +1747,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())); @@ -1937,7 +1816,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 +1826,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 +1839,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 +1849,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 +1872,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 +1889,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,8 +1902,7 @@ 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 @@ -2357,176 +2233,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; + ErrCode nPrevError = SbxBase::GetError(); + SbxBase::ResetError(); - if( eType == SbxDATE ) - { - bDate = true; - } - else if( eType == SbxSTRING ) - { - 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 +2381,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 +2435,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 +2444,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; @@ -2960,8 +2804,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 ); @@ -3128,8 +2971,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 +3011,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 +3039,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 +3083,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 +3098,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 +3124,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 +3160,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 +3198,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 +3221,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 +3238,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 +3255,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 +3338,11 @@ struct RandomNumberGenerator } }; -class theRandomNumberGenerator : public rtl::Static<RandomNumberGenerator, theRandomNumberGenerator> {}; +RandomNumberGenerator& theRandomNumberGenerator() +{ + static RandomNumberGenerator theGenerator; + return theGenerator; +} } @@ -3492,7 +3355,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 +3369,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); } } @@ -3744,7 +3607,7 @@ OUString getBasicTypeName( SbxDataType eType ) }; 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; @@ -3861,8 +3724,7 @@ 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(); @@ -3904,8 +3766,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,8 +3782,7 @@ 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(); @@ -3945,8 +3805,7 @@ 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(); @@ -3964,8 +3823,7 @@ 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(); @@ -3983,8 +3841,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 +3862,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 +3946,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(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 +4008,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 + if (nConversion == ooo::vba::VbStrConv::vbFromUnicode) // This mode does not combine { - 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 ) - { - 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()) + { + 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); + utl::TransliterationWrapper aWrapper(xContext, transliterationFlag); + aStr = aWrapper.transliterate(aStr, nLanguage, 0, aStr.getLength(), nullptr); } } - 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]; - } - 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 +4110,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 +4119,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 ); } @@ -4301,8 +4146,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 ); } @@ -4328,8 +4172,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 +4195,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,12 +4213,17 @@ 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()); + + // tdf#147529 - check for missing parameters + if (IsMissing(rPar, 1)) + { + return StarBASIC::Error(ERRCODE_BASIC_NOT_OPTIONAL); + } + + // tdf#151012 - initialize optional parameters with their default values (number of buttons) + WinBits nType = static_cast<WinBits>(GetOptionalIntegerParamOrDefault(rPar, 2, 0)); // MB_OK WinBits nStyle = nType; nStyle &= 15; // delete bits 4-16 if (nStyle > 5) @@ -4394,15 +4241,8 @@ void SbRtl_MsgBox(StarBASIC *, SbxArray & rPar, bool) }; OUString aMsg = rPar.Get(1)->GetOUString(); - OUString aTitle; - if( nArgCount >= 4 ) - { - aTitle = rPar.Get(3)->GetOUString(); - } - else - { - aTitle = Application::GetDisplayName(); - } + // tdf#151012 - initialize optional parameters with their default values (title of dialog box) + OUString aTitle = GetOptionalOUStringParamOrDefault(rPar, 3, Application::GetDisplayName()); WinBits nDialogType = nType & (16+32+64); @@ -4428,7 +4268,7 @@ void SbRtl_MsgBox(StarBASIC *, SbxArray & rPar, bool) } std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, - eType, VclButtonsType::NONE, aMsg)); + eType, VclButtonsType::NONE, aMsg, GetpApp())); switch (nStyle) { @@ -4609,8 +4449,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 +4459,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 +4525,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,8 +4640,7 @@ 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; } |