1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <sal/config.h>
23 #include <config_version.h>
28 #include <vcl/svapp.hxx>
29 #include <vcl/mapmod.hxx>
30 #include <vcl/outdev.hxx>
31 #include <vcl/timer.hxx>
32 #include <vcl/settings.hxx>
33 #include <basic/sbxvar.hxx>
34 #include <basic/sbx.hxx>
35 #include <svl/zforlist.hxx>
36 #include <tools/urlobj.hxx>
37 #include <tools/fract.hxx>
38 #include <o3tl/temporary.hxx>
39 #include <osl/file.hxx>
40 #include <sbobjmod.hxx>
41 #include <basic/sbuno.hxx>
44 #include <sbintern.hxx>
45 #include <runtime.hxx>
46 #include <rtlproto.hxx>
49 #include <sbunoobj.hxx>
50 #include <propacc.hxx>
51 #include <sal/log.hxx>
52 #include <eventatt.hxx>
54 #include <comphelper/processfactory.hxx>
55 #include <comphelper/string.hxx>
57 #include <com/sun/star/uno/Sequence.hxx>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/i18n/LocaleCalendar2.hpp>
60 #include <com/sun/star/sheet/XFunctionAccess.hpp>
63 using namespace comphelper
;
64 using namespace com::sun::star::i18n
;
65 using namespace com::sun::star::lang
;
66 using namespace com::sun::star::sheet
;
67 using namespace com::sun::star::uno
;
69 static Reference
< XCalendar4
> const & getLocaleCalendar()
71 static Reference
< XCalendar4
> xCalendar
= LocaleCalendar2::create(getProcessComponentContext());
72 static css::lang::Locale aLastLocale
;
73 static bool bNeedsInit
= true;
75 css::lang::Locale aLocale
= Application::GetSettings().GetLanguageTag().getLocale();
76 bool bNeedsReload
= false;
82 else if( aLocale
.Language
!= aLastLocale
.Language
||
83 aLocale
.Country
!= aLastLocale
.Country
||
84 aLocale
.Variant
!= aLastLocale
.Variant
)
90 aLastLocale
= aLocale
;
91 xCalendar
->loadDefaultCalendar( aLocale
);
96 #if HAVE_FEATURE_SCRIPTING
98 void SbRtl_CallByName(StarBASIC
*, SbxArray
& rPar
, bool)
100 const sal_Int16 vbGet
= 2;
101 const sal_Int16 vbLet
= 4;
102 const sal_Int16 vbMethod
= 1;
103 const sal_Int16 vbSet
= 8;
105 // At least 3 parameter needed plus function itself -> 4
106 sal_uInt16 nParCount
= rPar
.Count();
109 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
113 // 1. parameter is object
114 SbxBase
* pObjVar
= rPar
.Get(1)->GetObject();
115 SbxObject
* pObj
= nullptr;
117 pObj
= dynamic_cast<SbxObject
*>( pObjVar
);
118 if( !pObj
&& dynamic_cast<const SbxVariable
*>( pObjVar
) )
120 SbxBase
* pObjVarObj
= static_cast<SbxVariable
*>(pObjVar
)->GetObject();
121 pObj
= dynamic_cast<SbxObject
*>( pObjVarObj
);
125 StarBASIC::Error( ERRCODE_BASIC_BAD_PARAMETER
);
129 // 2. parameter is ProcedureName
130 OUString aNameStr
= rPar
.Get(2)->GetOUString();
132 // 3. parameter is CallType
133 sal_Int16 nCallType
= rPar
.Get(3)->GetInteger();
135 //SbxObject* pFindObj = NULL;
136 SbxVariable
* pFindVar
= pObj
->Find( aNameStr
, SbxClassType::DontCare
);
137 if( pFindVar
== nullptr )
139 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
148 aVals
.eType
= SbxVARIANT
;
149 pFindVar
->Get( aVals
);
151 SbxVariableRef refVar
= rPar
.Get(0);
152 refVar
->Put( aVals
);
158 if ( nParCount
!= 5 )
160 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
163 SbxVariableRef pValVar
= rPar
.Get(4);
164 if( nCallType
== vbLet
)
167 aVals
.eType
= SbxVARIANT
;
168 pValVar
->Get( aVals
);
169 pFindVar
->Put( aVals
);
173 SbxVariableRef rFindVar
= pFindVar
;
174 SbiInstance
* pInst
= GetSbData()->pInst
;
175 SbiRuntime
* pRT
= pInst
? pInst
->pRun
: nullptr;
178 pRT
->StepSET_Impl( pValVar
, rFindVar
);
185 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pFindVar
);
186 if( pMeth
== nullptr )
188 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
194 sal_uInt16 nMethParamCount
= nParCount
- 4;
195 if( nMethParamCount
> 0 )
197 xArray
= new SbxArray
;
198 for( sal_uInt16 i
= 0 ; i
< nMethParamCount
; i
++ )
200 SbxVariable
* pPar
= rPar
.Get( i
+ 4 );
201 xArray
->Put( pPar
, i
+ 1 );
206 SbxVariableRef refVar
= rPar
.Get(0);
208 pMeth
->SetParameters( xArray
.get() );
209 pMeth
->Call( refVar
.get() );
210 pMeth
->SetParameters( nullptr );
214 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
218 void SbRtl_CBool(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
221 if ( rPar
.Count() == 2 )
223 SbxVariable
*pSbxVariable
= rPar
.Get(1);
224 bVal
= pSbxVariable
->GetBool();
228 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
230 rPar
.Get(0)->PutBool(bVal
);
233 void SbRtl_CByte(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
236 if ( rPar
.Count() == 2 )
238 SbxVariable
*pSbxVariable
= rPar
.Get(1);
239 nByte
= pSbxVariable
->GetByte();
243 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
245 rPar
.Get(0)->PutByte(nByte
);
248 void SbRtl_CCur(StarBASIC
*, SbxArray
& rPar
, bool)
251 if ( rPar
.Count() == 2 )
253 SbxVariable
*pSbxVariable
= rPar
.Get(1);
254 nCur
= pSbxVariable
->GetCurrency();
258 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
260 rPar
.Get(0)->PutCurrency( nCur
);
263 void SbRtl_CDec(StarBASIC
* pBasic
, SbxArray
& rPar
, bool bWrite
)
269 SbxDecimal
* pDec
= nullptr;
270 if ( rPar
.Count() == 2 )
272 SbxVariable
*pSbxVariable
= rPar
.Get(1);
273 pDec
= pSbxVariable
->GetDecimal();
277 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
279 rPar
.Get(0)->PutDecimal( pDec
);
281 rPar
.Get(0)->PutEmpty();
282 StarBASIC::Error(ERRCODE_BASIC_NOT_IMPLEMENTED
);
286 void SbRtl_CDate(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
289 if ( rPar
.Count() == 2 )
291 SbxVariable
*pSbxVariable
= rPar
.Get(1);
292 nVal
= pSbxVariable
->GetDate();
296 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
298 rPar
.Get(0)->PutDate(nVal
);
301 void SbRtl_CDbl(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
304 if ( rPar
.Count() == 2 )
306 SbxVariable
*pSbxVariable
= rPar
.Get(1);
307 if( pSbxVariable
->GetType() == SbxSTRING
)
310 OUString aScanStr
= pSbxVariable
->GetOUString();
311 ErrCode Error
= SbxValue::ScanNumIntnl( aScanStr
, nVal
);
312 if( Error
!= ERRCODE_NONE
)
314 StarBASIC::Error( Error
);
319 nVal
= pSbxVariable
->GetDouble();
324 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
327 rPar
.Get(0)->PutDouble(nVal
);
330 void SbRtl_CInt(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
333 if ( rPar
.Count() == 2 )
335 SbxVariable
*pSbxVariable
= rPar
.Get(1);
336 nVal
= pSbxVariable
->GetInteger();
340 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
342 rPar
.Get(0)->PutInteger(nVal
);
345 void SbRtl_CLng(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
348 if ( rPar
.Count() == 2 )
350 SbxVariable
*pSbxVariable
= rPar
.Get(1);
351 nVal
= pSbxVariable
->GetLong();
355 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
357 rPar
.Get(0)->PutLong(nVal
);
360 void SbRtl_CSng(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
362 float nVal
= float(0.0);
363 if ( rPar
.Count() == 2 )
365 SbxVariable
*pSbxVariable
= rPar
.Get(1);
366 if( pSbxVariable
->GetType() == SbxSTRING
)
370 OUString aScanStr
= pSbxVariable
->GetOUString();
371 ErrCode Error
= SbxValue::ScanNumIntnl( aScanStr
, dVal
, /*bSingle=*/true );
372 if( SbxBase::GetError() == ERRCODE_NONE
&& Error
!= ERRCODE_NONE
)
374 StarBASIC::Error( Error
);
376 nVal
= static_cast<float>(dVal
);
380 nVal
= pSbxVariable
->GetSingle();
385 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
387 rPar
.Get(0)->PutSingle(nVal
);
390 void SbRtl_CStr(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
393 if ( rPar
.Count() == 2 )
395 SbxVariable
*pSbxVariable
= rPar
.Get(1);
396 aString
= pSbxVariable
->GetOUString();
400 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
402 rPar
.Get(0)->PutString(aString
);
405 void SbRtl_CVar(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
407 SbxValues
aVals( SbxVARIANT
);
408 if ( rPar
.Count() == 2 )
410 SbxVariable
*pSbxVariable
= rPar
.Get(1);
411 pSbxVariable
->Get( aVals
);
415 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
417 rPar
.Get(0)->Put( aVals
);
420 void SbRtl_CVErr(StarBASIC
*, SbxArray
& rPar
, bool)
422 sal_Int16 nErrCode
= 0;
423 if ( rPar
.Count() == 2 )
425 SbxVariable
*pSbxVariable
= rPar
.Get(1);
426 nErrCode
= pSbxVariable
->GetInteger();
430 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
432 rPar
.Get(0)->PutErr( nErrCode
);
435 void SbRtl_Iif(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
437 if ( rPar
.Count() == 4 )
439 if (rPar
.Get(1)->GetBool())
441 *rPar
.Get(0) = *rPar
.Get(2);
445 *rPar
.Get(0) = *rPar
.Get(3);
450 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
454 void SbRtl_GetSystemType(StarBASIC
*, SbxArray
& rPar
, bool)
456 if ( rPar
.Count() != 1 )
458 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
462 // Removed for SRC595
463 rPar
.Get(0)->PutInteger( -1 );
467 void SbRtl_GetGUIType(StarBASIC
* pBasic
, SbxArray
& rPar
, bool bWrite
)
472 if ( rPar
.Count() != 1 )
474 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
478 // 17.7.2000 Make simple solution for testtool / fat office
480 rPar
.Get(0)->PutInteger( 1 );
482 rPar
.Get(0)->PutInteger( 4 );
484 rPar
.Get(0)->PutInteger( -1 );
489 void SbRtl_Red(StarBASIC
*, SbxArray
& rPar
, bool)
491 if ( rPar
.Count() != 2 )
493 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
497 sal_Int32 nRGB
= rPar
.Get(1)->GetLong();
500 rPar
.Get(0)->PutInteger( static_cast<sal_Int16
>(nRGB
) );
504 void SbRtl_Green(StarBASIC
*, SbxArray
& rPar
, bool)
506 if ( rPar
.Count() != 2 )
508 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
512 sal_Int32 nRGB
= rPar
.Get(1)->GetLong();
515 rPar
.Get(0)->PutInteger( static_cast<sal_Int16
>(nRGB
) );
519 void SbRtl_Blue(StarBASIC
*, SbxArray
& rPar
, bool)
521 if ( rPar
.Count() != 2 )
523 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
527 sal_Int32 nRGB
= rPar
.Get(1)->GetLong();
529 rPar
.Get(0)->PutInteger( static_cast<sal_Int16
>(nRGB
) );
534 void SbRtl_Switch(StarBASIC
*, SbxArray
& rPar
, bool)
536 sal_uInt16 nCount
= rPar
.Count();
537 if( !(nCount
& 0x0001 ))
539 // number of arguments must be odd
540 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
542 sal_uInt16 nCurExpr
= 1;
543 while( nCurExpr
< (nCount
-1) )
545 if( rPar
.Get( nCurExpr
)->GetBool())
547 (*rPar
.Get(0)) = *(rPar
.Get(nCurExpr
+1));
552 rPar
.Get(0)->PutNull();
555 //i#64882# Common wait impl for existing Wait and new WaitUntil
557 void Wait_Impl( bool bDurationBased
, SbxArray
& rPar
)
559 if( rPar
.Count() != 2 )
561 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
565 if ( bDurationBased
)
567 double dWait
= rPar
.Get(1)->GetDouble();
568 double dNow
= Now_Impl();
569 double dSecs
= ( dWait
- dNow
) * 24.0 * 3600.0;
570 nWait
= static_cast<long>( dSecs
* 1000 ); // wait in thousands of sec
574 nWait
= rPar
.Get(1)->GetLong();
578 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
583 aTimer
.SetTimeout( nWait
);
585 while ( aTimer
.IsActive() )
587 Application::Yield();
592 void SbRtl_Wait(StarBASIC
*, SbxArray
& rPar
, bool)
594 Wait_Impl( false, rPar
);
597 //i#64882# add new WaitUntil ( for application.wait )
598 // share wait_impl with 'normal' oobasic wait
599 void SbRtl_WaitUntil(StarBASIC
*, SbxArray
& rPar
, bool)
601 Wait_Impl( true, rPar
);
604 void SbRtl_DoEvents(StarBASIC
*, SbxArray
& rPar
, bool)
606 // don't understand what upstream are up to
607 // we already process application events etc. in between
608 // basic runtime pcode ( on a timed basis )
610 rPar
.Get(0)->PutInteger( 0 );
611 Application::Reschedule( true );
614 void SbRtl_GetGUIVersion(StarBASIC
*, SbxArray
& rPar
, bool)
616 if ( rPar
.Count() != 1 )
618 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
622 // Removed for SRC595
623 rPar
.Get(0)->PutLong( -1 );
627 void SbRtl_Choose(StarBASIC
*, SbxArray
& rPar
, bool)
629 if ( rPar
.Count() < 2 )
631 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
633 sal_Int16 nIndex
= rPar
.Get(1)->GetInteger();
634 sal_uInt16 nCount
= rPar
.Count();
636 if( nCount
== 1 || nIndex
> (nCount
-1) || nIndex
< 1 )
638 rPar
.Get(0)->PutNull();
641 (*rPar
.Get(0)) = *(rPar
.Get(nIndex
+1));
645 void SbRtl_Trim(StarBASIC
*, SbxArray
& rPar
, bool)
647 if ( rPar
.Count() < 2 )
649 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
653 OUString
aStr(comphelper::string::strip(rPar
.Get(1)->GetOUString(), ' '));
654 rPar
.Get(0)->PutString(aStr
);
658 void SbRtl_GetSolarVersion(StarBASIC
*, SbxArray
& rPar
, bool)
660 rPar
.Get(0)->PutLong( LIBO_VERSION_MAJOR
* 10000 + LIBO_VERSION_MINOR
* 100 + LIBO_VERSION_MICRO
* 1);
663 void SbRtl_TwipsPerPixelX(StarBASIC
*, SbxArray
& rPar
, bool)
665 sal_Int32 nResult
= 0;
667 MapMode
aMap( MapUnit::MapTwip
);
668 OutputDevice
* pDevice
= Application::GetDefaultDevice();
671 aSize
= pDevice
->PixelToLogic( aSize
, aMap
);
672 nResult
= aSize
.Width() / 100;
674 rPar
.Get(0)->PutLong( nResult
);
677 void SbRtl_TwipsPerPixelY(StarBASIC
*, SbxArray
& rPar
, bool)
679 sal_Int32 nResult
= 0;
681 MapMode
aMap( MapUnit::MapTwip
);
682 OutputDevice
* pDevice
= Application::GetDefaultDevice();
685 aSize
= pDevice
->PixelToLogic( aSize
, aMap
);
686 nResult
= aSize
.Height() / 100;
688 rPar
.Get(0)->PutLong( nResult
);
692 void SbRtl_FreeLibrary(StarBASIC
*, SbxArray
& rPar
, bool)
694 if ( rPar
.Count() != 2 )
696 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
698 GetSbData()->pInst
->GetDllMgr()->FreeDll( rPar
.Get(1)->GetOUString() );
700 bool IsBaseIndexOne()
702 bool bResult
= false;
703 if ( GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
705 sal_uInt16 res
= GetSbData()->pInst
->pRun
->GetBase();
714 void SbRtl_Array(StarBASIC
*, SbxArray
& rPar
, bool)
716 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
717 sal_uInt16 nArraySize
= rPar
.Count() - 1;
719 // ignore Option Base so far (unfortunately only known by the compiler)
720 bool bIncIndex
= (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
725 pArray
->AddDim( 1, nArraySize
);
729 pArray
->AddDim( 0, nArraySize
-1 );
734 pArray
->unoAddDim( 0, -1 );
737 // insert parameters into the array
738 for( sal_uInt16 i
= 0 ; i
< nArraySize
; i
++ )
740 SbxVariable
* pVar
= rPar
.Get(i
+1);
741 SbxVariable
* pNew
= new SbxEnsureParentVariable(*pVar
);
742 pNew
->SetFlag( SbxFlagBits::Write
);
744 aIdx
[0] = static_cast< short >(i
);
749 pArray
->Put(pNew
, aIdx
);
753 SbxVariableRef refVar
= rPar
.Get(0);
754 SbxFlagBits nFlags
= refVar
->GetFlags();
755 refVar
->ResetFlag( SbxFlagBits::Fixed
);
756 refVar
->PutObject( pArray
);
757 refVar
->SetFlags( nFlags
);
758 refVar
->SetParameters( nullptr );
762 // Featurewish #57868
763 // The function returns a variant-array; if there are no parameters passed,
764 // an empty array is created (according to dim a(); equal to a sequence of
765 // the length 0 in Uno).
766 // If there are parameters passed, there's a dimension created for each of
767 // them; DimArray( 2, 2, 4 ) is equal to DIM a( 2, 2, 4 )
768 // the array is always of the type variant
769 void SbRtl_DimArray(StarBASIC
*, SbxArray
& rPar
, bool)
771 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
772 sal_uInt16 nArrayDims
= rPar
.Count() - 1;
775 for( sal_uInt16 i
= 0; i
< nArrayDims
; i
++ )
777 sal_Int32 ub
= rPar
.Get(i
+1)->GetLong();
780 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
783 pArray
->AddDim32( 0, ub
);
788 pArray
->unoAddDim( 0, -1 );
790 SbxVariableRef refVar
= rPar
.Get(0);
791 SbxFlagBits nFlags
= refVar
->GetFlags();
792 refVar
->ResetFlag( SbxFlagBits::Fixed
);
793 refVar
->PutObject( pArray
);
794 refVar
->SetFlags( nFlags
);
795 refVar
->SetParameters( nullptr );
799 * FindObject and FindPropertyObject make it possible to
800 * address objects and properties of the type Object with
801 * their name as string-parameters at the runtime.
804 * MyObj.Prop1.Bla = 5
807 * dim ObjVar as Object
808 * dim ObjProp as Object
810 * ObjVar = FindObject( ObjName$ )
811 * PropName$ = "Prop1"
812 * ObjProp = FindPropertyObject( ObjVar, PropName$ )
815 * The names can be created dynamically at the runtime
816 * so that e. g. via controls "TextEdit1" to "TextEdit5"
817 * can be iterated in a dialog in a loop.
821 // 1st parameter = the object's name as string
822 void SbRtl_FindObject(StarBASIC
*, SbxArray
& rPar
, bool)
824 if ( rPar
.Count() < 2 )
826 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
830 OUString aNameStr
= rPar
.Get(1)->GetOUString();
832 SbxBase
* pFind
= StarBASIC::FindSBXInCurrentScope( aNameStr
);
833 SbxObject
* pFindObj
= nullptr;
836 pFindObj
= dynamic_cast<SbxObject
*>( pFind
);
838 SbxVariableRef refVar
= rPar
.Get(0);
839 refVar
->PutObject( pFindObj
);
842 // address object-property in an object
843 // 1st parameter = object
844 // 2nd parameter = the property's name as string
845 void SbRtl_FindPropertyObject(StarBASIC
*, SbxArray
& rPar
, bool)
847 if ( rPar
.Count() < 3 )
849 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
853 SbxBase
* pObjVar
= rPar
.Get(1)->GetObject();
854 SbxObject
* pObj
= nullptr;
857 pObj
= dynamic_cast<SbxObject
*>( pObjVar
);
859 if( !pObj
&& dynamic_cast<const SbxVariable
*>( pObjVar
) )
861 SbxBase
* pObjVarObj
= static_cast<SbxVariable
*>(pObjVar
)->GetObject();
862 pObj
= dynamic_cast<SbxObject
*>( pObjVarObj
);
865 OUString aNameStr
= rPar
.Get(2)->GetOUString();
867 SbxObject
* pFindObj
= nullptr;
870 SbxVariable
* pFindVar
= pObj
->Find( aNameStr
, SbxClassType::Object
);
871 pFindObj
= dynamic_cast<SbxObject
*>( pFindVar
);
875 StarBASIC::Error( ERRCODE_BASIC_BAD_PARAMETER
);
878 SbxVariableRef refVar
= rPar
.Get(0);
879 refVar
->PutObject( pFindObj
);
883 static bool lcl_WriteSbxVariable( const SbxVariable
& rVar
, SvStream
* pStrm
,
884 bool bBinary
, short nBlockLen
, bool bIsArray
)
886 sal_uInt64
const nFPos
= pStrm
->Tell();
888 bool bIsVariant
= !rVar
.IsFixed();
889 SbxDataType eType
= rVar
.GetType();
898 pStrm
->WriteUInt16( SbxBYTE
); // VarType Id
900 pStrm
->WriteUChar( rVar
.GetByte() );
912 pStrm
->WriteUInt16( SbxINTEGER
); // VarType Id
914 pStrm
->WriteInt16( rVar
.GetInteger() );
921 pStrm
->WriteUInt16( SbxLONG
); // VarType Id
923 pStrm
->WriteInt32( rVar
.GetLong() );
929 pStrm
->WriteUInt16( SbxSALINT64
); // VarType Id
931 pStrm
->WriteUInt64( rVar
.GetInt64() );
936 pStrm
->WriteUInt16( eType
); // VarType Id
938 pStrm
->WriteFloat( rVar
.GetSingle() );
946 pStrm
->WriteUInt16( eType
); // VarType Id
948 pStrm
->WriteDouble( rVar
.GetDouble() );
954 const OUString
& rStr
= rVar
.GetOUString();
955 if( !bBinary
|| bIsArray
)
959 pStrm
->WriteUInt16( SbxSTRING
);
961 pStrm
->WriteUniOrByteString( rStr
, osl_getThreadTextEncoding() );
965 // without any length information! without end-identifier!
966 // What does that mean for Unicode?! Choosing conversion to ByteString...
967 OString
aByteStr(OUStringToOString(rStr
, osl_getThreadTextEncoding()));
968 pStrm
->WriteOString( aByteStr
);
974 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
980 pStrm
->Seek( nFPos
+ nBlockLen
);
982 return pStrm
->GetErrorCode() == ERRCODE_NONE
;
985 static bool lcl_ReadSbxVariable( SbxVariable
& rVar
, SvStream
* pStrm
,
986 bool bBinary
, short nBlockLen
)
990 sal_uInt64
const nFPos
= pStrm
->Tell();
992 bool bIsVariant
= !rVar
.IsFixed();
993 SbxDataType eVarType
= rVar
.GetType();
995 SbxDataType eSrcType
= eVarType
;
999 pStrm
->ReadUInt16( nTemp
);
1000 eSrcType
= static_cast<SbxDataType
>(nTemp
);
1010 pStrm
->ReadUChar( aByte
);
1012 if( bBinary
&& SbiRuntime::isVBAEnabled() && aByte
== 1 && pStrm
->eof() )
1016 rVar
.PutByte( aByte
);
1029 pStrm
->ReadInt16( aInt
);
1030 rVar
.PutInteger( aInt
);
1038 pStrm
->ReadInt32( aInt
);
1039 rVar
.PutLong( aInt
);
1046 pStrm
->ReadUInt32( aInt
);
1047 rVar
.PutInt64( static_cast<sal_Int64
>(aInt
) );
1053 pStrm
->ReadFloat( nS
);
1054 rVar
.PutSingle( nS
);
1061 pStrm
->ReadDouble( aDouble
);
1062 rVar
.PutDouble( aDouble
);
1068 pStrm
->ReadDouble( aDouble
);
1069 rVar
.PutDate( aDouble
);
1076 OUString aStr
= pStrm
->ReadUniOrByteString(osl_getThreadTextEncoding());
1077 rVar
.PutString( aStr
);
1082 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1088 pStrm
->Seek( nFPos
+ nBlockLen
);
1090 return pStrm
->GetErrorCode() == ERRCODE_NONE
;
1095 static bool lcl_WriteReadSbxArray( SbxDimArray
& rArr
, SvStream
* pStrm
,
1096 bool bBinary
, short nCurDim
, short* pOtherDims
, bool bWrite
)
1098 SAL_WARN_IF( nCurDim
<= 0,"basic", "Bad Dim");
1099 short nLower
, nUpper
;
1100 if( !rArr
.GetDim( nCurDim
, nLower
, nUpper
) )
1102 for( short nCur
= nLower
; nCur
<= nUpper
; nCur
++ )
1104 pOtherDims
[ nCurDim
-1 ] = nCur
;
1106 lcl_WriteReadSbxArray(rArr
, pStrm
, bBinary
, nCurDim
-1, pOtherDims
, bWrite
);
1109 SbxVariable
* pVar
= rArr
.Get( const_cast<const short*>(pOtherDims
) );
1112 bRet
= lcl_WriteSbxVariable(*pVar
, pStrm
, bBinary
, 0, true );
1114 bRet
= lcl_ReadSbxVariable(*pVar
, pStrm
, bBinary
, 0 );
1122 static void PutGet( SbxArray
& rPar
, bool bPut
)
1124 if ( rPar
.Count() != 4 )
1126 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1129 sal_Int16 nFileNo
= rPar
.Get(1)->GetInteger();
1130 SbxVariable
* pVar2
= rPar
.Get(2);
1131 SbxDataType eType2
= pVar2
->GetType();
1132 bool bHasRecordNo
= (eType2
!= SbxEMPTY
&& eType2
!= SbxERROR
);
1133 long nRecordNo
= pVar2
->GetLong();
1134 if ( nFileNo
< 1 || ( bHasRecordNo
&& nRecordNo
< 1 ) )
1136 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1140 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
1141 SbiStream
* pSbStrm
= pIO
->GetStream( nFileNo
);
1143 if ( !pSbStrm
|| !(pSbStrm
->GetMode() & (SbiStreamFlags::Binary
| SbiStreamFlags::Random
)) )
1145 StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL
);
1149 SvStream
* pStrm
= pSbStrm
->GetStrm();
1150 bool bRandom
= pSbStrm
->IsRandom();
1151 short nBlockLen
= bRandom
? pSbStrm
->GetBlockLen() : 0;
1155 pSbStrm
->ExpandFile();
1160 sal_uInt64
const nFilePos
= bRandom
1161 ? static_cast<sal_uInt64
>(nBlockLen
* nRecordNo
)
1162 : static_cast<sal_uInt64
>(nRecordNo
);
1163 pStrm
->Seek( nFilePos
);
1166 SbxDimArray
* pArr
= nullptr;
1167 SbxVariable
* pVar
= rPar
.Get(3);
1168 if( pVar
->GetType() & SbxARRAY
)
1170 SbxBase
* pParObj
= pVar
->GetObject();
1171 pArr
= dynamic_cast<SbxDimArray
*>( pParObj
);
1178 sal_uInt64
const nFPos
= pStrm
->Tell();
1179 short nDims
= pArr
->GetDims();
1180 std::unique_ptr
<short[]> pDims(new short[ nDims
]);
1181 bRet
= lcl_WriteReadSbxArray(*pArr
,pStrm
,!bRandom
,nDims
,pDims
.get(),bPut
);
1184 pStrm
->Seek( nFPos
+ nBlockLen
);
1189 bRet
= lcl_WriteSbxVariable(*pVar
, pStrm
, !bRandom
, nBlockLen
, false);
1191 bRet
= lcl_ReadSbxVariable(*pVar
, pStrm
, !bRandom
, nBlockLen
);
1193 if( !bRet
|| pStrm
->GetErrorCode() )
1194 StarBASIC::Error( ERRCODE_BASIC_IO_ERROR
);
1197 void SbRtl_Put(StarBASIC
*, SbxArray
& rPar
, bool)
1199 PutGet( rPar
, true );
1202 void SbRtl_Get(StarBASIC
*, SbxArray
& rPar
, bool)
1204 PutGet( rPar
, false );
1207 void SbRtl_Environ(StarBASIC
*, SbxArray
& rPar
, bool)
1209 if ( rPar
.Count() != 2 )
1211 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1215 // should be ANSI but that's not possible under Win16 in the DLL
1216 OString
aByteStr(OUStringToOString(rPar
.Get(1)->GetOUString(),
1217 osl_getThreadTextEncoding()));
1218 const char* pEnvStr
= getenv(aByteStr
.getStr());
1221 aResult
= OUString(pEnvStr
, strlen(pEnvStr
), osl_getThreadTextEncoding());
1223 rPar
.Get(0)->PutString( aResult
);
1226 static double GetDialogZoomFactor( bool bX
, long nValue
)
1228 OutputDevice
* pDevice
= Application::GetDefaultDevice();
1232 Size
aRefSize( nValue
, nValue
);
1233 Fraction
aFracX( 1, 26 );
1234 Fraction
aFracY( 1, 24 );
1235 MapMode
aMap( MapUnit::MapAppFont
, Point(), aFracX
, aFracY
);
1236 Size aScaledSize
= pDevice
->LogicToPixel( aRefSize
, aMap
);
1237 aRefSize
= pDevice
->LogicToPixel( aRefSize
, MapMode(MapUnit::MapTwip
) );
1239 double nRef
, nScaled
;
1242 nRef
= aRefSize
.Width();
1243 nScaled
= aScaledSize
.Width();
1247 nRef
= aRefSize
.Height();
1248 nScaled
= aScaledSize
.Height();
1250 nResult
= nScaled
/ nRef
;
1256 void SbRtl_GetDialogZoomFactorX(StarBASIC
*, SbxArray
& rPar
, bool)
1258 if ( rPar
.Count() != 2 )
1260 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1263 rPar
.Get(0)->PutDouble( GetDialogZoomFactor( true, rPar
.Get(1)->GetLong() ));
1266 void SbRtl_GetDialogZoomFactorY(StarBASIC
*, SbxArray
& rPar
, bool)
1268 if ( rPar
.Count() != 2 )
1270 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1273 rPar
.Get(0)->PutDouble( GetDialogZoomFactor( false, rPar
.Get(1)->GetLong()));
1277 void SbRtl_EnableReschedule(StarBASIC
*, SbxArray
& rPar
, bool)
1279 rPar
.Get(0)->PutEmpty();
1280 if ( rPar
.Count() != 2 )
1281 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1282 if( GetSbData()->pInst
)
1283 GetSbData()->pInst
->EnableReschedule( rPar
.Get(1)->GetBool() );
1286 void SbRtl_GetSystemTicks(StarBASIC
*, SbxArray
& rPar
, bool)
1288 if ( rPar
.Count() != 1 )
1290 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1293 rPar
.Get(0)->PutLong( tools::Time::GetSystemTicks() );
1296 void SbRtl_GetPathSeparator(StarBASIC
*, SbxArray
& rPar
, bool)
1298 if ( rPar
.Count() != 1 )
1300 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1303 rPar
.Get(0)->PutString( OUString( SAL_PATHDELIMITER
) );
1306 void SbRtl_ResolvePath(StarBASIC
*, SbxArray
& rPar
, bool)
1308 if ( rPar
.Count() == 2 )
1310 OUString aStr
= rPar
.Get(1)->GetOUString();
1311 rPar
.Get(0)->PutString( aStr
);
1315 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1319 void SbRtl_TypeLen(StarBASIC
*, SbxArray
& rPar
, bool)
1321 if ( rPar
.Count() != 2 )
1323 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1327 SbxDataType eType
= rPar
.Get(1)->GetType();
1383 nLen
= static_cast<sal_Int16
>(rPar
.Get(1)->GetOUString().getLength());
1390 rPar
.Get(0)->PutInteger( nLen
);
1395 // 1st parameter == class name, other parameters for initialisation
1396 void SbRtl_CreateUnoStruct(StarBASIC
*, SbxArray
& rPar
, bool)
1398 RTL_Impl_CreateUnoStruct( rPar
);
1402 // 1st parameter == service-name
1403 void SbRtl_CreateUnoService(StarBASIC
*, SbxArray
& rPar
, bool)
1405 RTL_Impl_CreateUnoService( rPar
);
1408 void SbRtl_CreateUnoServiceWithArguments(StarBASIC
*, SbxArray
& rPar
, bool)
1410 RTL_Impl_CreateUnoServiceWithArguments( rPar
);
1414 void SbRtl_CreateUnoValue(StarBASIC
*, SbxArray
& rPar
, bool)
1416 RTL_Impl_CreateUnoValue( rPar
);
1421 void SbRtl_GetProcessServiceManager(StarBASIC
*, SbxArray
& rPar
, bool)
1423 RTL_Impl_GetProcessServiceManager( rPar
);
1427 // 1st parameter == Sequence<PropertyValue>
1428 void SbRtl_CreatePropertySet(StarBASIC
*, SbxArray
& rPar
, bool)
1430 RTL_Impl_CreatePropertySet( rPar
);
1434 // multiple interface-names as parameters
1435 void SbRtl_HasUnoInterfaces(StarBASIC
*, SbxArray
& rPar
, bool)
1437 RTL_Impl_HasInterfaces( rPar
);
1441 void SbRtl_IsUnoStruct(StarBASIC
*, SbxArray
& rPar
, bool)
1443 RTL_Impl_IsUnoStruct( rPar
);
1447 void SbRtl_EqualUnoObjects(StarBASIC
*, SbxArray
& rPar
, bool)
1449 RTL_Impl_EqualUnoObjects( rPar
);
1452 void SbRtl_CreateUnoDialog(StarBASIC
*, SbxArray
& rPar
, bool)
1454 RTL_Impl_CreateUnoDialog( rPar
);
1457 // Return the application standard lib as root scope
1458 void SbRtl_GlobalScope(StarBASIC
* pBasic
, SbxArray
& rPar
, bool)
1460 SbxObject
* p
= pBasic
;
1461 while( p
->GetParent() )
1465 SbxVariableRef refVar
= rPar
.Get(0);
1466 refVar
->PutObject( p
);
1469 // Helper functions to convert Url from/to system paths
1470 void SbRtl_ConvertToUrl(StarBASIC
*, SbxArray
& rPar
, bool)
1472 if ( rPar
.Count() == 2 )
1474 OUString aStr
= rPar
.Get(1)->GetOUString();
1475 INetURLObject
aURLObj( aStr
, INetProtocol::File
);
1476 OUString aFileURL
= aURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1477 if( aFileURL
.isEmpty() )
1479 osl::File::getFileURLFromSystemPath(aStr
, aFileURL
);
1481 if( aFileURL
.isEmpty() )
1485 rPar
.Get(0)->PutString(aFileURL
);
1489 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1493 void SbRtl_ConvertFromUrl(StarBASIC
*, SbxArray
& rPar
, bool)
1495 if ( rPar
.Count() == 2 )
1497 OUString aStr
= rPar
.Get(1)->GetOUString();
1499 ::osl::File::getSystemPathFromFileURL( aStr
, aSysPath
);
1500 if( aSysPath
.isEmpty() )
1504 rPar
.Get(0)->PutString(aSysPath
);
1508 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1513 // Provide DefaultContext
1514 void SbRtl_GetDefaultContext(StarBASIC
*, SbxArray
& rPar
, bool)
1516 RTL_Impl_GetDefaultContext( rPar
);
1519 void SbRtl_Join(StarBASIC
*, SbxArray
& rPar
, bool)
1521 sal_uInt16 nParCount
= rPar
.Count();
1522 if ( nParCount
!= 3 && nParCount
!= 2 )
1524 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1527 SbxBase
* pParObj
= rPar
.Get(1)->GetObject();
1528 SbxDimArray
* pArr
= dynamic_cast<SbxDimArray
*>( pParObj
);
1531 if( pArr
->GetDims() != 1 )
1533 StarBASIC::Error( ERRCODE_BASIC_WRONG_DIMS
); // Syntax Error?!
1537 if( nParCount
== 3 )
1539 aDelim
= rPar
.Get(2)->GetOUString();
1545 OUStringBuffer
aRetStr(32);
1546 short nLower
, nUpper
;
1547 pArr
->GetDim( 1, nLower
, nUpper
);
1549 for (aIdx
[0] = nLower
; aIdx
[0] <= nUpper
; ++aIdx
[0])
1551 OUString aStr
= pArr
->Get(aIdx
)->GetOUString();
1552 aRetStr
.append(aStr
);
1553 if (aIdx
[0] != nUpper
)
1555 aRetStr
.append(aDelim
);
1558 rPar
.Get(0)->PutString( aRetStr
.makeStringAndClear() );
1562 StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS
);
1567 void SbRtl_Split(StarBASIC
*, SbxArray
& rPar
, bool)
1569 sal_uInt16 nParCount
= rPar
.Count();
1570 if ( nParCount
< 2 )
1572 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1576 OUString aExpression
= rPar
.Get(1)->GetOUString();
1577 short nArraySize
= 0;
1578 std::vector
< OUString
> vRet
;
1579 if( !aExpression
.isEmpty() )
1582 if( nParCount
>= 3 )
1584 aDelim
= rPar
.Get(2)->GetOUString();
1591 sal_Int32 nCount
= -1;
1592 if( nParCount
== 4 )
1594 nCount
= rPar
.Get(3)->GetLong();
1596 sal_Int32 nDelimLen
= aDelim
.getLength();
1599 sal_Int32 iSearch
= -1;
1600 sal_Int32 iStart
= 0;
1603 bool bBreak
= false;
1604 if( nCount
>= 0 && nArraySize
== nCount
- 1 )
1608 iSearch
= aExpression
.indexOf( aDelim
, iStart
);
1610 if( iSearch
>= 0 && !bBreak
)
1612 aSubStr
= aExpression
.copy( iStart
, iSearch
- iStart
);
1613 iStart
= iSearch
+ nDelimLen
;
1617 aSubStr
= aExpression
.copy( iStart
);
1619 vRet
.push_back( aSubStr
);
1627 while( iSearch
>= 0 );
1631 vRet
.push_back( aExpression
);
1636 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
1637 pArray
->unoAddDim( 0, nArraySize
-1 );
1639 // insert parameter(s) into the array
1640 for( short i
= 0 ; i
< nArraySize
; i
++ )
1642 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
1643 xVar
->PutString( vRet
[i
] );
1644 pArray
->Put( xVar
.get(), &i
);
1648 SbxVariableRef refVar
= rPar
.Get(0);
1649 SbxFlagBits nFlags
= refVar
->GetFlags();
1650 refVar
->ResetFlag( SbxFlagBits::Fixed
);
1651 refVar
->PutObject( pArray
);
1652 refVar
->SetFlags( nFlags
);
1653 refVar
->SetParameters( nullptr );
1656 // MonthName(month[, abbreviate])
1657 void SbRtl_MonthName(StarBASIC
*, SbxArray
& rPar
, bool)
1659 sal_uInt16 nParCount
= rPar
.Count();
1660 if( nParCount
!= 2 && nParCount
!= 3 )
1662 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1666 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
1667 if( !xCalendar
.is() )
1669 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
1672 Sequence
< CalendarItem2
> aMonthSeq
= xCalendar
->getMonths2();
1673 sal_Int32 nMonthCount
= aMonthSeq
.getLength();
1675 sal_Int16 nVal
= rPar
.Get(1)->GetInteger();
1676 if( nVal
< 1 || nVal
> nMonthCount
)
1678 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1682 bool bAbbreviate
= false;
1683 if( nParCount
== 3 )
1684 bAbbreviate
= rPar
.Get(2)->GetBool();
1686 const CalendarItem2
* pCalendarItems
= aMonthSeq
.getConstArray();
1687 const CalendarItem2
& rItem
= pCalendarItems
[nVal
- 1];
1689 OUString aRetStr
= ( bAbbreviate
? rItem
.AbbrevName
: rItem
.FullName
);
1690 rPar
.Get(0)->PutString(aRetStr
);
1693 // WeekdayName(weekday, abbreviate, firstdayofweek)
1694 void SbRtl_WeekdayName(StarBASIC
*, SbxArray
& rPar
, bool)
1696 sal_uInt16 nParCount
= rPar
.Count();
1697 if( nParCount
< 2 || nParCount
> 4 )
1699 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1703 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
1704 if( !xCalendar
.is() )
1706 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
1710 Sequence
< CalendarItem2
> aDaySeq
= xCalendar
->getDays2();
1711 sal_Int16 nDayCount
= static_cast<sal_Int16
>(aDaySeq
.getLength());
1712 sal_Int16 nDay
= rPar
.Get(1)->GetInteger();
1713 sal_Int16 nFirstDay
= 0;
1714 if( nParCount
== 4 )
1716 nFirstDay
= rPar
.Get(3)->GetInteger();
1717 if( nFirstDay
< 0 || nFirstDay
> 7 )
1719 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1723 if( nFirstDay
== 0 )
1725 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
1727 nDay
= 1 + (nDay
+ nDayCount
+ nFirstDay
- 2) % nDayCount
;
1728 if( nDay
< 1 || nDay
> nDayCount
)
1730 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1734 bool bAbbreviate
= false;
1735 if( nParCount
>= 3 )
1737 SbxVariable
* pPar2
= rPar
.Get(2);
1738 if( !pPar2
->IsErr() )
1740 bAbbreviate
= pPar2
->GetBool();
1744 const CalendarItem2
* pCalendarItems
= aDaySeq
.getConstArray();
1745 const CalendarItem2
& rItem
= pCalendarItems
[nDay
- 1];
1747 OUString aRetStr
= ( bAbbreviate
? rItem
.AbbrevName
: rItem
.FullName
);
1748 rPar
.Get(0)->PutString( aRetStr
);
1751 void SbRtl_Weekday(StarBASIC
*, SbxArray
& rPar
, bool)
1753 sal_uInt16 nParCount
= rPar
.Count();
1754 if ( nParCount
< 2 )
1756 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1760 double aDate
= rPar
.Get(1)->GetDate();
1762 bool bFirstDay
= false;
1763 sal_Int16 nFirstDay
= 0;
1764 if ( nParCount
> 2 )
1766 nFirstDay
= rPar
.Get(2)->GetInteger();
1769 sal_Int16 nDay
= implGetWeekDay( aDate
, bFirstDay
, nFirstDay
);
1770 rPar
.Get(0)->PutInteger( nDay
);
1791 Interval meInterval
;
1792 char const * mStringCode
;
1797 static IntervalInfo
const * getIntervalInfo( const OUString
& rStringCode
)
1799 static IntervalInfo
const aIntervalTable
[] =
1801 { INTERVAL_YYYY
, "yyyy", 0.0, false }, // Year
1802 { INTERVAL_Q
, "q", 0.0, false }, // Quarter
1803 { INTERVAL_M
, "m", 0.0, false }, // Month
1804 { INTERVAL_Y
, "y", 1.0, true }, // Day of year
1805 { INTERVAL_D
, "d", 1.0, true }, // Day
1806 { INTERVAL_W
, "w", 1.0, true }, // Weekday
1807 { INTERVAL_WW
, "ww", 7.0, true }, // Week
1808 { INTERVAL_H
, "h", 1.0 / 24.0, true }, // Hour
1809 { INTERVAL_N
, "n", 1.0 / 1440.0, true }, // Minute
1810 { INTERVAL_S
, "s", 1.0 / 86400.0, true } // Second
1812 for( std::size_t i
= 0; i
!= SAL_N_ELEMENTS(aIntervalTable
); ++i
)
1814 if( rStringCode
.equalsIgnoreAsciiCaseAscii(
1815 aIntervalTable
[i
].mStringCode
) )
1817 return &aIntervalTable
[i
];
1823 static void implGetDayMonthYear( sal_Int16
& rnYear
, sal_Int16
& rnMonth
, sal_Int16
& rnDay
, double dDate
)
1825 rnDay
= implGetDateDay( dDate
);
1826 rnMonth
= implGetDateMonth( dDate
);
1827 rnYear
= implGetDateYear( dDate
);
1830 /** Limits a date to valid dates within tools' class Date capabilities.
1832 @return the year number, truncated if necessary and in that case also
1833 rMonth and rDay adjusted.
1835 static sal_Int16
limitDate( sal_Int32 n32Year
, sal_Int16
& rMonth
, sal_Int16
& rDay
)
1837 if( n32Year
> SAL_MAX_INT16
)
1839 n32Year
= SAL_MAX_INT16
;
1843 else if( n32Year
< SAL_MIN_INT16
)
1845 n32Year
= SAL_MIN_INT16
;
1849 return static_cast<sal_Int16
>(n32Year
);
1852 void SbRtl_DateAdd(StarBASIC
*, SbxArray
& rPar
, bool)
1854 sal_uInt16 nParCount
= rPar
.Count();
1855 if( nParCount
!= 4 )
1857 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1861 OUString aStringCode
= rPar
.Get(1)->GetOUString();
1862 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
1865 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1869 sal_Int32 lNumber
= rPar
.Get(2)->GetLong();
1870 double dDate
= rPar
.Get(3)->GetDate();
1871 double dNewDate
= 0;
1872 if( pInfo
->mbSimple
)
1874 double dAdd
= pInfo
->mdValue
* lNumber
;
1875 dNewDate
= dDate
+ dAdd
;
1879 // Keep hours, minutes, seconds
1880 double dHoursMinutesSeconds
= dDate
- floor( dDate
);
1883 sal_Int16 nYear
, nMonth
, nDay
;
1884 sal_Int16 nTargetYear16
= 0, nTargetMonth
= 0;
1885 implGetDayMonthYear( nYear
, nMonth
, nDay
, dDate
);
1886 switch( pInfo
->meInterval
)
1890 sal_Int32 nTargetYear
= lNumber
+ nYear
;
1891 nTargetYear16
= limitDate( nTargetYear
, nMonth
, nDay
);
1892 /* TODO: should the result be error if the date was limited? It never was. */
1893 nTargetMonth
= nMonth
;
1894 bOk
= implDateSerial( nTargetYear16
, nTargetMonth
, nDay
, false, SbDateCorrection::TruncateToMonth
, dNewDate
);
1900 bool bNeg
= (lNumber
< 0);
1903 sal_Int32 nYearsAdd
;
1904 sal_Int16 nMonthAdd
;
1905 if( pInfo
->meInterval
== INTERVAL_Q
)
1907 nYearsAdd
= lNumber
/ 4;
1908 nMonthAdd
= static_cast<sal_Int16
>( 3 * (lNumber
% 4) );
1912 nYearsAdd
= lNumber
/ 12;
1913 nMonthAdd
= static_cast<sal_Int16
>( lNumber
% 12 );
1916 sal_Int32 nTargetYear
;
1919 nTargetMonth
= nMonth
- nMonthAdd
;
1920 if( nTargetMonth
<= 0 )
1925 nTargetYear
= static_cast<sal_Int32
>(nYear
) - nYearsAdd
;
1929 nTargetMonth
= nMonth
+ nMonthAdd
;
1930 if( nTargetMonth
> 12 )
1935 nTargetYear
= static_cast<sal_Int32
>(nYear
) + nYearsAdd
;
1937 nTargetYear16
= limitDate( nTargetYear
, nTargetMonth
, nDay
);
1938 /* TODO: should the result be error if the date was limited? It never was. */
1939 bOk
= implDateSerial( nTargetYear16
, nTargetMonth
, nDay
, false, SbDateCorrection::TruncateToMonth
, dNewDate
);
1946 dNewDate
+= dHoursMinutesSeconds
;
1949 rPar
.Get(0)->PutDate( dNewDate
);
1952 static double RoundImpl( double d
)
1954 return ( d
>= 0 ) ? floor( d
+ 0.5 ) : -floor( -d
+ 0.5 );
1957 void SbRtl_DateDiff(StarBASIC
*, SbxArray
& rPar
, bool)
1959 // DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]])
1961 sal_uInt16 nParCount
= rPar
.Count();
1962 if( nParCount
< 4 || nParCount
> 6 )
1964 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1968 OUString aStringCode
= rPar
.Get(1)->GetOUString();
1969 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
1972 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1976 double dDate1
= rPar
.Get(2)->GetDate();
1977 double dDate2
= rPar
.Get(3)->GetDate();
1980 switch( pInfo
->meInterval
)
1984 sal_Int16 nYear1
= implGetDateYear( dDate1
);
1985 sal_Int16 nYear2
= implGetDateYear( dDate2
);
1986 dRet
= nYear2
- nYear1
;
1991 sal_Int16 nYear1
= implGetDateYear( dDate1
);
1992 sal_Int16 nYear2
= implGetDateYear( dDate2
);
1993 sal_Int16 nQ1
= 1 + (implGetDateMonth( dDate1
) - 1) / 3;
1994 sal_Int16 nQ2
= 1 + (implGetDateMonth( dDate2
) - 1) / 3;
1995 sal_Int16 nQGes1
= 4 * nYear1
+ nQ1
;
1996 sal_Int16 nQGes2
= 4 * nYear2
+ nQ2
;
1997 dRet
= nQGes2
- nQGes1
;
2002 sal_Int16 nYear1
= implGetDateYear( dDate1
);
2003 sal_Int16 nYear2
= implGetDateYear( dDate2
);
2004 sal_Int16 nMonth1
= implGetDateMonth( dDate1
);
2005 sal_Int16 nMonth2
= implGetDateMonth( dDate2
);
2006 sal_Int16 nMonthGes1
= 12 * nYear1
+ nMonth1
;
2007 sal_Int16 nMonthGes2
= 12 * nYear2
+ nMonth2
;
2008 dRet
= nMonthGes2
- nMonthGes1
;
2014 double dDays1
= floor( dDate1
);
2015 double dDays2
= floor( dDate2
);
2016 dRet
= dDays2
- dDays1
;
2022 double dDays1
= floor( dDate1
);
2023 double dDays2
= floor( dDate2
);
2024 if( pInfo
->meInterval
== INTERVAL_WW
)
2026 sal_Int16 nFirstDay
= 1; // Default
2027 if( nParCount
>= 5 )
2029 nFirstDay
= rPar
.Get(4)->GetInteger();
2030 if( nFirstDay
< 0 || nFirstDay
> 7 )
2032 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2035 if( nFirstDay
== 0 )
2037 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
2038 if( !xCalendar
.is() )
2040 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
2043 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
2046 sal_Int16 nDay1
= implGetWeekDay( dDate1
);
2047 sal_Int16 nDay1_Diff
= nDay1
- nFirstDay
;
2048 if( nDay1_Diff
< 0 )
2050 dDays1
-= nDay1_Diff
;
2052 sal_Int16 nDay2
= implGetWeekDay( dDate2
);
2053 sal_Int16 nDay2_Diff
= nDay2
- nFirstDay
;
2054 if( nDay2_Diff
< 0 )
2056 dDays2
-= nDay2_Diff
;
2059 double dDiff
= dDays2
- dDays1
;
2060 dRet
= ( dDiff
>= 0 ) ? floor( dDiff
/ 7.0 ) : -floor( -dDiff
/ 7.0 );
2065 dRet
= RoundImpl( 24.0 * (dDate2
- dDate1
) );
2070 dRet
= RoundImpl( 1440.0 * (dDate2
- dDate1
) );
2075 dRet
= RoundImpl( 86400.0 * (dDate2
- dDate1
) );
2079 rPar
.Get(0)->PutDouble( dRet
);
2082 static double implGetDateOfFirstDayInFirstWeek
2083 ( sal_Int16 nYear
, sal_Int16
& nFirstDay
, sal_Int16
& nFirstWeek
, bool* pbError
= nullptr )
2085 ErrCode nError
= ERRCODE_NONE
;
2086 if( nFirstDay
< 0 || nFirstDay
> 7 )
2087 nError
= ERRCODE_BASIC_BAD_ARGUMENT
;
2089 if( nFirstWeek
< 0 || nFirstWeek
> 3 )
2090 nError
= ERRCODE_BASIC_BAD_ARGUMENT
;
2092 Reference
< XCalendar4
> xCalendar
;
2093 if( nFirstDay
== 0 || nFirstWeek
== 0 )
2095 xCalendar
= getLocaleCalendar();
2096 if( !xCalendar
.is() )
2097 nError
= ERRCODE_BASIC_BAD_ARGUMENT
;
2100 if( nError
!= ERRCODE_NONE
)
2102 StarBASIC::Error( nError
);
2108 if( nFirstDay
== 0 )
2109 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
2111 sal_Int16 nFirstWeekMinDays
= 0; // Not used for vbFirstJan1 = default
2112 if( nFirstWeek
== 0 )
2114 nFirstWeekMinDays
= xCalendar
->getMinimumNumberOfDaysForFirstWeek();
2115 if( nFirstWeekMinDays
== 1 )
2117 nFirstWeekMinDays
= 0;
2120 else if( nFirstWeekMinDays
== 4 )
2122 else if( nFirstWeekMinDays
== 7 )
2125 else if( nFirstWeek
== 2 )
2126 nFirstWeekMinDays
= 4; // vbFirstFourDays
2127 else if( nFirstWeek
== 3 )
2128 nFirstWeekMinDays
= 7; // vbFirstFourDays
2131 implDateSerial( nYear
, 1, 1, false, SbDateCorrection::None
, dBaseDate
);
2133 sal_Int16 nWeekDay0101
= implGetWeekDay( dBaseDate
);
2134 sal_Int16 nDayDiff
= nWeekDay0101
- nFirstDay
;
2138 if( nFirstWeekMinDays
)
2140 sal_Int16 nThisWeeksDaysInYearCount
= 7 - nDayDiff
;
2141 if( nThisWeeksDaysInYearCount
< nFirstWeekMinDays
)
2144 double dRetDate
= dBaseDate
- nDayDiff
;
2148 void SbRtl_DatePart(StarBASIC
*, SbxArray
& rPar
, bool)
2150 // DatePart(interval, date[,firstdayofweek[, firstweekofyear]])
2152 sal_uInt16 nParCount
= rPar
.Count();
2153 if( nParCount
< 3 || nParCount
> 5 )
2155 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2159 OUString aStringCode
= rPar
.Get(1)->GetOUString();
2160 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
2163 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2167 double dDate
= rPar
.Get(2)->GetDate();
2170 switch( pInfo
->meInterval
)
2174 nRet
= implGetDateYear( dDate
);
2179 nRet
= 1 + (implGetDateMonth( dDate
) - 1) / 3;
2184 nRet
= implGetDateMonth( dDate
);
2189 sal_Int16 nYear
= implGetDateYear( dDate
);
2191 implDateSerial( nYear
, 1, 1, false, SbDateCorrection::None
, dBaseDate
);
2192 nRet
= 1 + sal_Int32( dDate
- dBaseDate
);
2197 nRet
= implGetDateDay( dDate
);
2202 bool bFirstDay
= false;
2203 sal_Int16 nFirstDay
= 1; // Default
2204 if( nParCount
>= 4 )
2206 nFirstDay
= rPar
.Get(3)->GetInteger();
2209 nRet
= implGetWeekDay( dDate
, bFirstDay
, nFirstDay
);
2214 sal_Int16 nFirstDay
= 1; // Default
2215 if( nParCount
>= 4 )
2216 nFirstDay
= rPar
.Get(3)->GetInteger();
2218 sal_Int16 nFirstWeek
= 1; // Default
2219 if( nParCount
== 5 )
2220 nFirstWeek
= rPar
.Get(4)->GetInteger();
2222 sal_Int16 nYear
= implGetDateYear( dDate
);
2223 bool bError
= false;
2224 double dYearFirstDay
= implGetDateOfFirstDayInFirstWeek( nYear
, nFirstDay
, nFirstWeek
, &bError
);
2227 if( dYearFirstDay
> dDate
)
2229 // Date belongs to last year's week
2230 dYearFirstDay
= implGetDateOfFirstDayInFirstWeek( nYear
- 1, nFirstDay
, nFirstWeek
);
2232 else if( nFirstWeek
!= 1 )
2234 // Check if date belongs to next year
2235 double dNextYearFirstDay
= implGetDateOfFirstDayInFirstWeek( nYear
+ 1, nFirstDay
, nFirstWeek
);
2236 if( dDate
>= dNextYearFirstDay
)
2237 dYearFirstDay
= dNextYearFirstDay
;
2241 double dDiff
= dDate
- dYearFirstDay
;
2242 nRet
= 1 + sal_Int32( dDiff
/ 7 );
2248 nRet
= implGetHour( dDate
);
2253 nRet
= implGetMinute( dDate
);
2258 nRet
= implGetSecond( dDate
);
2262 rPar
.Get(0)->PutLong( nRet
);
2265 // FormatDateTime(Date[,NamedFormat])
2266 void SbRtl_FormatDateTime(StarBASIC
*, SbxArray
& rPar
, bool)
2268 sal_uInt16 nParCount
= rPar
.Count();
2269 if( nParCount
< 2 || nParCount
> 3 )
2271 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2275 double dDate
= rPar
.Get(1)->GetDate();
2276 sal_Int16 nNamedFormat
= 0;
2279 nNamedFormat
= rPar
.Get(2)->GetInteger();
2280 if( nNamedFormat
< 0 || nNamedFormat
> 4 )
2282 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2287 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
2288 if( !xCalendar
.is() )
2290 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
2295 SbxVariableRef pSbxVar
= new SbxVariable( SbxSTRING
);
2296 switch( nNamedFormat
)
2299 // Display a date and/or time. If there is a date part,
2300 // display it as a short date. If there is a time part,
2301 // display it as a long time. If present, both parts are displayed.
2303 // 12/21/2004 11:24:50 AM
2304 // 21.12.2004 12:13:51
2306 pSbxVar
->PutDate( dDate
);
2307 aRetStr
= pSbxVar
->GetOUString();
2310 // LongDate: Display a date using the long date format specified
2311 // in your computer's regional settings.
2312 // Tuesday, December 21, 2004
2313 // Dienstag, 21. December 2004
2316 std::shared_ptr
<SvNumberFormatter
> pFormatter
;
2317 if( GetSbData()->pInst
)
2319 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2323 sal_uInt32 n
; // Dummy
2324 pFormatter
= SbiInstance::PrepareNumberFormatter( n
, n
, n
);
2327 LanguageType eLangType
= Application::GetSettings().GetLanguageTag().getLanguageType();
2328 const sal_uInt32 nIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYSTEM_LONG
, eLangType
);
2330 pFormatter
->GetOutputString( dDate
, nIndex
, aRetStr
, &pCol
);
2334 // ShortDate: Display a date using the short date format specified
2335 // in your computer's regional settings.
2338 pSbxVar
->PutDate( floor(dDate
) );
2339 aRetStr
= pSbxVar
->GetOUString();
2342 // LongTime: Display a time using the time format specified
2343 // in your computer's regional settings.
2347 // ShortTime: Display a time using the 24-hour format (hh:mm).
2350 double dTime
= modf( dDate
, &o3tl::temporary(double()) );
2351 pSbxVar
->PutDate( dTime
);
2352 if( nNamedFormat
== 3 )
2354 aRetStr
= pSbxVar
->GetOUString();
2358 aRetStr
= pSbxVar
->GetOUString().copy( 0, 5 );
2363 rPar
.Get(0)->PutString( aRetStr
);
2366 void SbRtl_Frac(StarBASIC
*, SbxArray
& rPar
, bool)
2368 sal_uInt16 nParCount
= rPar
.Count();
2371 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2375 SbxVariable
*pSbxVariable
= rPar
.Get(1);
2376 double dVal
= pSbxVariable
->GetDouble();
2378 rPar
.Get(0)->PutDouble(dVal
- ::rtl::math::approxFloor(dVal
));
2380 rPar
.Get(0)->PutDouble(dVal
- ::rtl::math::approxCeil(dVal
));
2383 void SbRtl_Round(StarBASIC
*, SbxArray
& rPar
, bool)
2385 sal_uInt16 nParCount
= rPar
.Count();
2386 if( nParCount
!= 2 && nParCount
!= 3 )
2388 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2392 SbxVariable
*pSbxVariable
= rPar
.Get(1);
2393 double dVal
= pSbxVariable
->GetDouble();
2404 sal_Int16 numdecimalplaces
= 0;
2405 if( nParCount
== 3 )
2407 numdecimalplaces
= rPar
.Get(2)->GetInteger();
2408 if( numdecimalplaces
< 0 || numdecimalplaces
> 22 )
2410 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2415 if( numdecimalplaces
== 0 )
2417 dRes
= floor( dVal
+ 0.5 );
2421 double dFactor
= pow( 10.0, numdecimalplaces
);
2423 dRes
= floor( dVal
+ 0.5 );
2430 rPar
.Get(0)->PutDouble( dRes
);
2433 static void CallFunctionAccessFunction( const Sequence
< Any
>& aArgs
, const OUString
& sFuncName
, SbxVariable
* pRet
)
2435 static Reference
< XFunctionAccess
> xFunc
;
2440 Reference
< XMultiServiceFactory
> xFactory( getProcessServiceFactory() );
2443 xFunc
.set( xFactory
->createInstance("com.sun.star.sheet.FunctionAccess"), UNO_QUERY_THROW
);
2446 Any aRet
= xFunc
->callFunction( sFuncName
, aArgs
);
2448 unoToSbxValue( pRet
, aRet
);
2451 catch(const Exception
& )
2453 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2457 void SbRtl_SYD(StarBASIC
*, SbxArray
& rPar
, bool)
2459 sal_uInt16 nArgCount
= rPar
.Count()-1;
2461 if ( nArgCount
< 4 )
2463 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2467 // retrieve non-optional params
2469 Sequence
< Any
> aParams( 4 );
2470 aParams
[ 0 ] <<= rPar
.Get(1)->GetDouble();
2471 aParams
[ 1 ] <<= rPar
.Get(2)->GetDouble();
2472 aParams
[ 2 ] <<= rPar
.Get(3)->GetDouble();
2473 aParams
[ 3 ] <<= rPar
.Get(4)->GetDouble();
2475 CallFunctionAccessFunction( aParams
, "SYD", rPar
.Get( 0 ) );
2478 void SbRtl_SLN(StarBASIC
*, SbxArray
& rPar
, bool)
2480 sal_uInt16 nArgCount
= rPar
.Count()-1;
2482 if ( nArgCount
< 3 )
2484 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2488 // retrieve non-optional params
2490 Sequence
< Any
> aParams( 3 );
2491 aParams
[ 0 ] <<= rPar
.Get(1)->GetDouble();
2492 aParams
[ 1 ] <<= rPar
.Get(2)->GetDouble();
2493 aParams
[ 2 ] <<= rPar
.Get(3)->GetDouble();
2495 CallFunctionAccessFunction( aParams
, "SLN", rPar
.Get( 0 ) );
2498 void SbRtl_Pmt(StarBASIC
*, SbxArray
& rPar
, bool)
2500 sal_uInt16 nArgCount
= rPar
.Count()-1;
2502 if ( nArgCount
< 3 || nArgCount
> 5 )
2504 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2507 // retrieve non-optional params
2509 double rate
= rPar
.Get(1)->GetDouble();
2510 double nper
= rPar
.Get(2)->GetDouble();
2511 double pmt
= rPar
.Get(3)->GetDouble();
2513 // set default values for Optional args
2518 if ( nArgCount
>= 4 )
2520 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
2521 fv
= rPar
.Get(4)->GetDouble();
2524 if ( nArgCount
>= 5 )
2526 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2527 type
= rPar
.Get(5)->GetDouble();
2530 Sequence
< Any
> aParams( 5 );
2531 aParams
[ 0 ] <<= rate
;
2532 aParams
[ 1 ] <<= nper
;
2533 aParams
[ 2 ] <<= pmt
;
2534 aParams
[ 3 ] <<= fv
;
2535 aParams
[ 4 ] <<= type
;
2537 CallFunctionAccessFunction( aParams
, "Pmt", rPar
.Get( 0 ) );
2540 void SbRtl_PPmt(StarBASIC
*, SbxArray
& rPar
, bool)
2542 sal_uInt16 nArgCount
= rPar
.Count()-1;
2544 if ( nArgCount
< 4 || nArgCount
> 6 )
2546 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2549 // retrieve non-optional params
2551 double rate
= rPar
.Get(1)->GetDouble();
2552 double per
= rPar
.Get(2)->GetDouble();
2553 double nper
= rPar
.Get(3)->GetDouble();
2554 double pv
= rPar
.Get(4)->GetDouble();
2556 // set default values for Optional args
2561 if ( nArgCount
>= 5 )
2563 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2564 fv
= rPar
.Get(5)->GetDouble();
2567 if ( nArgCount
>= 6 )
2569 if( rPar
.Get(6)->GetType() != SbxEMPTY
)
2570 type
= rPar
.Get(6)->GetDouble();
2573 Sequence
< Any
> aParams( 6 );
2574 aParams
[ 0 ] <<= rate
;
2575 aParams
[ 1 ] <<= per
;
2576 aParams
[ 2 ] <<= nper
;
2577 aParams
[ 3 ] <<= pv
;
2578 aParams
[ 4 ] <<= fv
;
2579 aParams
[ 5 ] <<= type
;
2581 CallFunctionAccessFunction( aParams
, "PPmt", rPar
.Get( 0 ) );
2584 void SbRtl_PV(StarBASIC
*, SbxArray
& rPar
, bool)
2586 sal_uInt16 nArgCount
= rPar
.Count()-1;
2588 if ( nArgCount
< 3 || nArgCount
> 5 )
2590 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2593 // retrieve non-optional params
2595 double rate
= rPar
.Get(1)->GetDouble();
2596 double nper
= rPar
.Get(2)->GetDouble();
2597 double pmt
= rPar
.Get(3)->GetDouble();
2599 // set default values for Optional args
2604 if ( nArgCount
>= 4 )
2606 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
2607 fv
= rPar
.Get(4)->GetDouble();
2610 if ( nArgCount
>= 5 )
2612 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2613 type
= rPar
.Get(5)->GetDouble();
2616 Sequence
< Any
> aParams( 5 );
2617 aParams
[ 0 ] <<= rate
;
2618 aParams
[ 1 ] <<= nper
;
2619 aParams
[ 2 ] <<= pmt
;
2620 aParams
[ 3 ] <<= fv
;
2621 aParams
[ 4 ] <<= type
;
2623 CallFunctionAccessFunction( aParams
, "PV", rPar
.Get( 0 ) );
2626 void SbRtl_NPV(StarBASIC
*, SbxArray
& rPar
, bool)
2628 sal_uInt16 nArgCount
= rPar
.Count()-1;
2630 if ( nArgCount
< 1 || nArgCount
> 2 )
2632 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2636 Sequence
< Any
> aParams( 2 );
2637 aParams
[ 0 ] <<= rPar
.Get(1)->GetDouble();
2638 Any aValues
= sbxToUnoValue( rPar
.Get(2),
2639 cppu::UnoType
<Sequence
<double>>::get() );
2641 // convert for calc functions
2642 Sequence
< Sequence
< double > > sValues(1);
2643 aValues
>>= sValues
[ 0 ];
2644 aValues
<<= sValues
;
2646 aParams
[ 1 ] = aValues
;
2648 CallFunctionAccessFunction( aParams
, "NPV", rPar
.Get( 0 ) );
2651 void SbRtl_NPer(StarBASIC
*, SbxArray
& rPar
, bool)
2653 sal_uInt16 nArgCount
= rPar
.Count()-1;
2655 if ( nArgCount
< 3 || nArgCount
> 5 )
2657 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2660 // retrieve non-optional params
2662 double rate
= rPar
.Get(1)->GetDouble();
2663 double pmt
= rPar
.Get(2)->GetDouble();
2664 double pv
= rPar
.Get(3)->GetDouble();
2666 // set default values for Optional args
2671 if ( nArgCount
>= 4 )
2673 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
2674 fv
= rPar
.Get(4)->GetDouble();
2677 if ( nArgCount
>= 5 )
2679 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2680 type
= rPar
.Get(5)->GetDouble();
2683 Sequence
< Any
> aParams( 5 );
2684 aParams
[ 0 ] <<= rate
;
2685 aParams
[ 1 ] <<= pmt
;
2686 aParams
[ 2 ] <<= pv
;
2687 aParams
[ 3 ] <<= fv
;
2688 aParams
[ 4 ] <<= type
;
2690 CallFunctionAccessFunction( aParams
, "NPer", rPar
.Get( 0 ) );
2693 void SbRtl_MIRR(StarBASIC
*, SbxArray
& rPar
, bool)
2695 sal_uInt16 nArgCount
= rPar
.Count()-1;
2697 if ( nArgCount
< 3 )
2699 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2703 // retrieve non-optional params
2705 Sequence
< Any
> aParams( 3 );
2706 Any aValues
= sbxToUnoValue( rPar
.Get(1),
2707 cppu::UnoType
<Sequence
<double>>::get() );
2709 // convert for calc functions
2710 Sequence
< Sequence
< double > > sValues(1);
2711 aValues
>>= sValues
[ 0 ];
2712 aValues
<<= sValues
;
2714 aParams
[ 0 ] = aValues
;
2715 aParams
[ 1 ] <<= rPar
.Get(2)->GetDouble();
2716 aParams
[ 2 ] <<= rPar
.Get(3)->GetDouble();
2718 CallFunctionAccessFunction( aParams
, "MIRR", rPar
.Get( 0 ) );
2721 void SbRtl_IRR(StarBASIC
*, SbxArray
& rPar
, bool)
2723 sal_uInt16 nArgCount
= rPar
.Count()-1;
2725 if ( nArgCount
< 1 || nArgCount
> 2 )
2727 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2730 // retrieve non-optional params
2731 Any aValues
= sbxToUnoValue( rPar
.Get(1),
2732 cppu::UnoType
<Sequence
<double>>::get() );
2734 // convert for calc functions
2735 Sequence
< Sequence
< double > > sValues(1);
2736 aValues
>>= sValues
[ 0 ];
2737 aValues
<<= sValues
;
2739 // set default values for Optional args
2742 if ( nArgCount
>= 2 )
2744 if( rPar
.Get(2)->GetType() != SbxEMPTY
)
2745 guess
= rPar
.Get(2)->GetDouble();
2748 Sequence
< Any
> aParams( 2 );
2749 aParams
[ 0 ] = aValues
;
2750 aParams
[ 1 ] <<= guess
;
2752 CallFunctionAccessFunction( aParams
, "IRR", rPar
.Get( 0 ) );
2755 void SbRtl_IPmt(StarBASIC
*, SbxArray
& rPar
, bool)
2757 sal_uInt16 nArgCount
= rPar
.Count()-1;
2759 if ( nArgCount
< 4 || nArgCount
> 6 )
2761 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2764 // retrieve non-optional params
2766 double rate
= rPar
.Get(1)->GetDouble();
2767 double per
= rPar
.Get(2)->GetInteger();
2768 double nper
= rPar
.Get(3)->GetDouble();
2769 double pv
= rPar
.Get(4)->GetDouble();
2771 // set default values for Optional args
2776 if ( nArgCount
>= 5 )
2778 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2779 fv
= rPar
.Get(5)->GetDouble();
2782 if ( nArgCount
>= 6 )
2784 if( rPar
.Get(6)->GetType() != SbxEMPTY
)
2785 type
= rPar
.Get(6)->GetDouble();
2788 Sequence
< Any
> aParams( 6 );
2789 aParams
[ 0 ] <<= rate
;
2790 aParams
[ 1 ] <<= per
;
2791 aParams
[ 2 ] <<= nper
;
2792 aParams
[ 3 ] <<= pv
;
2793 aParams
[ 4 ] <<= fv
;
2794 aParams
[ 5 ] <<= type
;
2796 CallFunctionAccessFunction( aParams
, "IPmt", rPar
.Get( 0 ) );
2799 void SbRtl_FV(StarBASIC
*, SbxArray
& rPar
, bool)
2801 sal_uInt16 nArgCount
= rPar
.Count()-1;
2803 if ( nArgCount
< 3 || nArgCount
> 5 )
2805 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2808 // retrieve non-optional params
2810 double rate
= rPar
.Get(1)->GetDouble();
2811 double nper
= rPar
.Get(2)->GetDouble();
2812 double pmt
= rPar
.Get(3)->GetDouble();
2814 // set default values for Optional args
2819 if ( nArgCount
>= 4 )
2821 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
2822 pv
= rPar
.Get(4)->GetDouble();
2825 if ( nArgCount
>= 5 )
2827 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2828 type
= rPar
.Get(5)->GetDouble();
2831 Sequence
< Any
> aParams( 5 );
2832 aParams
[ 0 ] <<= rate
;
2833 aParams
[ 1 ] <<= nper
;
2834 aParams
[ 2 ] <<= pmt
;
2835 aParams
[ 3 ] <<= pv
;
2836 aParams
[ 4 ] <<= type
;
2838 CallFunctionAccessFunction( aParams
, "FV", rPar
.Get( 0 ) );
2841 void SbRtl_DDB(StarBASIC
*, SbxArray
& rPar
, bool)
2843 sal_uInt16 nArgCount
= rPar
.Count()-1;
2845 if ( nArgCount
< 4 || nArgCount
> 5 )
2847 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2850 // retrieve non-optional params
2852 double cost
= rPar
.Get(1)->GetDouble();
2853 double salvage
= rPar
.Get(2)->GetDouble();
2854 double life
= rPar
.Get(3)->GetDouble();
2855 double period
= rPar
.Get(4)->GetDouble();
2857 // set default values for Optional args
2861 if ( nArgCount
>= 5 )
2863 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2864 factor
= rPar
.Get(5)->GetDouble();
2867 Sequence
< Any
> aParams( 5 );
2868 aParams
[ 0 ] <<= cost
;
2869 aParams
[ 1 ] <<= salvage
;
2870 aParams
[ 2 ] <<= life
;
2871 aParams
[ 3 ] <<= period
;
2872 aParams
[ 4 ] <<= factor
;
2874 CallFunctionAccessFunction( aParams
, "DDB", rPar
.Get( 0 ) );
2877 void SbRtl_Rate(StarBASIC
*, SbxArray
& rPar
, bool)
2879 sal_uInt16 nArgCount
= rPar
.Count()-1;
2881 if ( nArgCount
< 3 || nArgCount
> 6 )
2883 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2886 // retrieve non-optional params
2892 nper
= rPar
.Get(1)->GetDouble();
2893 pmt
= rPar
.Get(2)->GetDouble();
2894 pv
= rPar
.Get(3)->GetDouble();
2896 // set default values for Optional args
2902 if ( nArgCount
>= 4 )
2904 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
2905 fv
= rPar
.Get(4)->GetDouble();
2909 if ( nArgCount
>= 5 )
2911 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
2912 type
= rPar
.Get(5)->GetDouble();
2916 if ( nArgCount
>= 6 )
2918 if( rPar
.Get(6)->GetType() != SbxEMPTY
)
2919 guess
= rPar
.Get(6)->GetDouble();
2922 Sequence
< Any
> aParams( 6 );
2923 aParams
[ 0 ] <<= nper
;
2924 aParams
[ 1 ] <<= pmt
;
2925 aParams
[ 2 ] <<= pv
;
2926 aParams
[ 3 ] <<= fv
;
2927 aParams
[ 4 ] <<= type
;
2928 aParams
[ 5 ] <<= guess
;
2930 CallFunctionAccessFunction( aParams
, "Rate", rPar
.Get( 0 ) );
2933 void SbRtl_StrReverse(StarBASIC
*, SbxArray
& rPar
, bool)
2935 if ( rPar
.Count() != 2 )
2937 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2941 SbxVariable
*pSbxVariable
= rPar
.Get(1);
2942 if( pSbxVariable
->IsNull() )
2944 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2948 OUString aStr
= comphelper::string::reverseString(pSbxVariable
->GetOUString());
2949 rPar
.Get(0)->PutString( aStr
);
2952 void SbRtl_CompatibilityMode(StarBASIC
*, SbxArray
& rPar
, bool)
2954 bool bEnabled
= false;
2955 sal_uInt16 nCount
= rPar
.Count();
2956 if ( nCount
!= 1 && nCount
!= 2 )
2957 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2959 SbiInstance
* pInst
= GetSbData()->pInst
;
2964 pInst
->EnableCompatibility( rPar
.Get(1)->GetBool() );
2966 bEnabled
= pInst
->IsCompatibility();
2968 rPar
.Get(0)->PutBool( bEnabled
);
2971 void SbRtl_Input(StarBASIC
*, SbxArray
& rPar
, bool)
2973 // 2 parameters needed
2974 if ( rPar
.Count() < 3 )
2976 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2980 sal_uInt16 nByteCount
= rPar
.Get(1)->GetUShort();
2981 sal_Int16 nFileNumber
= rPar
.Get(2)->GetInteger();
2983 SbiIoSystem
* pIosys
= GetSbData()->pInst
->GetIoSystem();
2984 SbiStream
* pSbStrm
= pIosys
->GetStream( nFileNumber
);
2985 if ( !pSbStrm
|| !(pSbStrm
->GetMode() & (SbiStreamFlags::Binary
| SbiStreamFlags::Input
)) )
2987 StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL
);
2991 OString aByteBuffer
;
2992 ErrCode err
= pSbStrm
->Read( aByteBuffer
, nByteCount
, true );
2994 err
= pIosys
->GetError();
2998 StarBASIC::Error( err
);
3001 rPar
.Get(0)->PutString(OStringToOUString(aByteBuffer
, osl_getThreadTextEncoding()));
3004 void SbRtl_Me(StarBASIC
*, SbxArray
& rPar
, bool)
3006 SbModule
* pActiveModule
= GetSbData()->pInst
->GetActiveModule();
3007 SbClassModuleObject
* pClassModuleObject
= dynamic_cast<SbClassModuleObject
*>( pActiveModule
);
3008 SbxVariableRef refVar
= rPar
.Get(0);
3009 if( pClassModuleObject
== nullptr )
3011 SbObjModule
* pMod
= dynamic_cast<SbObjModule
*>( pActiveModule
);
3013 refVar
->PutObject( pMod
);
3015 StarBASIC::Error( ERRCODE_BASIC_INVALID_USAGE_OBJECT
);
3018 refVar
->PutObject( pClassModuleObject
);
3023 sal_Int16
implGetWeekDay( double aDate
, bool bFirstDayParam
, sal_Int16 nFirstDay
)
3025 Date
aRefDate( 1,1,1900 );
3026 sal_Int32 nDays
= static_cast<sal_Int32
>(aDate
);
3027 nDays
-= 2; // normalize: 1.1.1900 => 0
3028 aRefDate
.AddDays( nDays
);
3029 DayOfWeek aDay
= aRefDate
.GetDayOfWeek();
3031 if ( aDay
!= SUNDAY
)
3032 nDay
= static_cast<sal_Int16
>(aDay
) + 2;
3034 nDay
= 1; // 1 == Sunday
3036 // #117253 optional 2nd parameter "firstdayofweek"
3037 if( bFirstDayParam
)
3039 if( nFirstDay
< 0 || nFirstDay
> 7 )
3041 #if HAVE_FEATURE_SCRIPTING
3042 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3046 if( nFirstDay
== 0 )
3048 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
3049 if( !xCalendar
.is() )
3051 #if HAVE_FEATURE_SCRIPTING
3052 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
3056 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
3058 nDay
= 1 + (nDay
+ 7 - nFirstDay
) % 7;
3063 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */