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 <rtl/math.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/mapmod.hxx>
31 #include <vcl/outdev.hxx>
32 #include <vcl/timer.hxx>
33 #include <vcl/settings.hxx>
34 #include <basic/sbxvar.hxx>
35 #include <basic/sbx.hxx>
36 #include <svl/zforlist.hxx>
37 #include <tools/urlobj.hxx>
38 #include <tools/fract.hxx>
39 #include <o3tl/temporary.hxx>
40 #include <osl/file.hxx>
41 #include <sbobjmod.hxx>
42 #include <basic/sbuno.hxx>
45 #include <sbintern.hxx>
46 #include <runtime.hxx>
47 #include <rtlproto.hxx>
50 #include <sbunoobj.hxx>
51 #include <propacc.hxx>
52 #include <sal/log.hxx>
53 #include <eventatt.hxx>
55 #include <svl/numformat.hxx>
57 #include <comphelper/processfactory.hxx>
58 #include <comphelper/string.hxx>
60 #include <com/sun/star/uno/Sequence.hxx>
61 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
62 #include <com/sun/star/i18n/LocaleCalendar2.hpp>
63 #include <com/sun/star/sheet/XFunctionAccess.hpp>
65 #include <officecfg/Office/Scripting.hxx>
69 using namespace comphelper
;
70 using namespace com::sun::star::i18n
;
71 using namespace com::sun::star::lang
;
72 using namespace com::sun::star::sheet
;
73 using namespace com::sun::star::uno
;
75 static Reference
< XCalendar4
> const & getLocaleCalendar()
77 static Reference
< XCalendar4
> xCalendar
= LocaleCalendar2::create(getProcessComponentContext());
78 static css::lang::Locale aLastLocale
;
79 static bool bNeedsReload
= true;
81 css::lang::Locale aLocale
= Application::GetSettings().GetLanguageTag().getLocale();
82 bNeedsReload
= bNeedsReload
||
83 ( aLocale
.Language
!= aLastLocale
.Language
||
84 aLocale
.Country
!= aLastLocale
.Country
||
85 aLocale
.Variant
!= aLastLocale
.Variant
);
89 aLastLocale
= aLocale
;
90 xCalendar
->loadDefaultCalendar( aLocale
);
95 #if HAVE_FEATURE_SCRIPTING
97 void SbRtl_CallByName(StarBASIC
*, SbxArray
& rPar
, bool)
99 const sal_Int16 vbGet
= 2;
100 const sal_Int16 vbLet
= 4;
101 const sal_Int16 vbMethod
= 1;
102 const sal_Int16 vbSet
= 8;
104 // At least 3 parameter needed plus function itself -> 4
105 sal_uInt32 nParCount
= rPar
.Count();
108 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
112 // 1. parameter is object
113 SbxBase
* pObjVar
= rPar
.Get(1)->GetObject();
114 SbxObject
* pObj
= nullptr;
116 pObj
= dynamic_cast<SbxObject
*>( pObjVar
);
118 if (auto pSbxVar
= dynamic_cast<const SbxVariable
*>( pObjVar
))
119 pObj
= dynamic_cast<SbxObject
*>( pSbxVar
->GetObject() );
122 StarBASIC::Error( ERRCODE_BASIC_BAD_PARAMETER
);
126 // 2. parameter is ProcName
127 OUString aNameStr
= rPar
.Get(2)->GetOUString();
129 // 3. parameter is CallType
130 sal_Int16 nCallType
= rPar
.Get(3)->GetInteger();
132 //SbxObject* pFindObj = NULL;
133 SbxVariable
* pFindVar
= pObj
->Find( aNameStr
, SbxClassType::DontCare
);
134 if( pFindVar
== nullptr )
136 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
145 aVals
.eType
= SbxVARIANT
;
146 pFindVar
->Get( aVals
);
148 SbxVariableRef refVar
= rPar
.Get(0);
149 refVar
->Put( aVals
);
155 if ( nParCount
!= 5 )
157 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
160 SbxVariableRef pValVar
= rPar
.Get(4);
161 if( nCallType
== vbLet
)
164 aVals
.eType
= SbxVARIANT
;
165 pValVar
->Get( aVals
);
166 pFindVar
->Put( aVals
);
170 SbxVariableRef rFindVar
= pFindVar
;
171 SbiInstance
* pInst
= GetSbData()->pInst
;
172 SbiRuntime
* pRT
= pInst
? pInst
->pRun
: nullptr;
175 pRT
->StepSET_Impl( pValVar
, rFindVar
);
182 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pFindVar
);
183 if( pMeth
== nullptr )
185 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
191 sal_uInt32 nMethParamCount
= nParCount
- 4;
192 if( nMethParamCount
> 0 )
194 xArray
= new SbxArray
;
195 for( sal_uInt32 i
= 0 ; i
< nMethParamCount
; i
++ )
197 SbxVariable
* pPar
= rPar
.Get(i
+ 4);
198 xArray
->Put(pPar
, i
+ 1);
203 SbxVariableRef refVar
= rPar
.Get(0);
205 pMeth
->SetParameters( xArray
.get() );
206 pMeth
->Call( refVar
.get() );
207 pMeth
->SetParameters( nullptr );
211 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
215 void SbRtl_CBool(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
218 if (rPar
.Count() == 2)
220 SbxVariable
* pSbxVariable
= rPar
.Get(1);
221 bVal
= pSbxVariable
->GetBool();
225 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
227 rPar
.Get(0)->PutBool(bVal
);
230 void SbRtl_CByte(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
233 if (rPar
.Count() == 2)
235 SbxVariable
* pSbxVariable
= rPar
.Get(1);
236 nByte
= pSbxVariable
->GetByte();
240 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
242 rPar
.Get(0)->PutByte(nByte
);
245 void SbRtl_CCur(StarBASIC
*, SbxArray
& rPar
, bool)
248 if (rPar
.Count() == 2)
250 SbxVariable
* pSbxVariable
= rPar
.Get(1);
251 nCur
= pSbxVariable
->GetCurrency();
255 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
257 rPar
.Get(0)->PutCurrency(nCur
);
260 void SbRtl_CDec(StarBASIC
*, SbxArray
& rPar
, bool)
263 SbxDecimal
* pDec
= nullptr;
264 if (rPar
.Count() == 2)
266 SbxVariable
* pSbxVariable
= rPar
.Get(1);
267 pDec
= pSbxVariable
->GetDecimal();
271 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
273 rPar
.Get(0)->PutDecimal(pDec
);
275 rPar
.Get(0)->PutEmpty();
276 StarBASIC::Error(ERRCODE_BASIC_NOT_IMPLEMENTED
);
280 void SbRtl_CDate(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
283 if (rPar
.Count() == 2)
285 SbxVariable
* pSbxVariable
= rPar
.Get(1);
286 nVal
= pSbxVariable
->GetDate();
290 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
292 rPar
.Get(0)->PutDate(nVal
);
295 void SbRtl_CDbl(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
298 if (rPar
.Count() == 2)
300 SbxVariable
* pSbxVariable
= rPar
.Get(1);
301 if( pSbxVariable
->GetType() == SbxSTRING
)
304 OUString aScanStr
= pSbxVariable
->GetOUString();
305 ErrCode Error
= SbxValue::ScanNumIntnl( aScanStr
, nVal
);
306 if( Error
!= ERRCODE_NONE
)
308 StarBASIC::Error( Error
);
313 nVal
= pSbxVariable
->GetDouble();
318 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
321 rPar
.Get(0)->PutDouble(nVal
);
324 void SbRtl_CInt(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
327 if (rPar
.Count() == 2)
329 SbxVariable
* pSbxVariable
= rPar
.Get(1);
330 nVal
= pSbxVariable
->GetInteger();
334 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
336 rPar
.Get(0)->PutInteger(nVal
);
339 void SbRtl_CLng(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
342 if (rPar
.Count() == 2)
344 SbxVariable
* pSbxVariable
= rPar
.Get(1);
345 nVal
= pSbxVariable
->GetLong();
349 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
351 rPar
.Get(0)->PutLong(nVal
);
354 void SbRtl_CSng(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
356 float nVal
= float(0.0);
357 if (rPar
.Count() == 2)
359 SbxVariable
* pSbxVariable
= rPar
.Get(1);
360 if( pSbxVariable
->GetType() == SbxSTRING
)
364 OUString aScanStr
= pSbxVariable
->GetOUString();
365 ErrCode Error
= SbxValue::ScanNumIntnl( aScanStr
, dVal
, /*bSingle=*/true );
366 if( SbxBase::GetError() == ERRCODE_NONE
&& Error
!= ERRCODE_NONE
)
368 StarBASIC::Error( Error
);
370 nVal
= static_cast<float>(dVal
);
374 nVal
= pSbxVariable
->GetSingle();
379 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
381 rPar
.Get(0)->PutSingle(nVal
);
384 void SbRtl_CStr(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
387 if (rPar
.Count() == 2)
389 SbxVariable
* pSbxVariable
= rPar
.Get(1);
390 aString
= pSbxVariable
->GetOUString();
394 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
396 rPar
.Get(0)->PutString(aString
);
399 void SbRtl_CVar(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
401 SbxValues
aVals( SbxVARIANT
);
402 if (rPar
.Count() == 2)
404 SbxVariable
* pSbxVariable
= rPar
.Get(1);
405 pSbxVariable
->Get( aVals
);
409 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
411 rPar
.Get(0)->Put(aVals
);
414 void SbRtl_CVErr(StarBASIC
*, SbxArray
& rPar
, bool)
416 sal_Int16 nErrCode
= 0;
417 if (rPar
.Count() == 2)
419 SbxVariable
* pSbxVariable
= rPar
.Get(1);
420 nErrCode
= pSbxVariable
->GetInteger();
424 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
426 rPar
.Get(0)->PutErr(nErrCode
);
429 void SbRtl_Iif(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
431 if (rPar
.Count() == 4)
433 if (rPar
.Get(1)->GetBool())
435 *rPar
.Get(0) = *rPar
.Get(2);
439 *rPar
.Get(0) = *rPar
.Get(3);
444 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
448 void SbRtl_GetSystemType(StarBASIC
*, SbxArray
& rPar
, bool)
450 if (rPar
.Count() != 1)
452 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
456 // Removed for SRC595
457 rPar
.Get(0)->PutInteger(-1);
461 void SbRtl_GetGUIType(StarBASIC
*, SbxArray
& rPar
, bool)
463 if (rPar
.Count() != 1)
465 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
469 // 17.7.2000 Make simple solution for testtool / fat office
471 rPar
.Get(0)->PutInteger(1);
473 rPar
.Get(0)->PutInteger(4);
475 rPar
.Get(0)->PutInteger(-1);
480 void SbRtl_Red(StarBASIC
*, SbxArray
& rPar
, bool)
482 if (rPar
.Count() != 2)
484 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
488 sal_Int32 nRGB
= rPar
.Get(1)->GetLong();
491 rPar
.Get(0)->PutInteger(static_cast<sal_Int16
>(nRGB
));
495 void SbRtl_Green(StarBASIC
*, SbxArray
& rPar
, bool)
497 if (rPar
.Count() != 2)
499 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
503 sal_Int32 nRGB
= rPar
.Get(1)->GetLong();
506 rPar
.Get(0)->PutInteger(static_cast<sal_Int16
>(nRGB
));
510 void SbRtl_Blue(StarBASIC
*, SbxArray
& rPar
, bool)
512 if (rPar
.Count() != 2)
514 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
518 sal_Int32 nRGB
= rPar
.Get(1)->GetLong();
520 rPar
.Get(0)->PutInteger(static_cast<sal_Int16
>(nRGB
));
525 void SbRtl_Switch(StarBASIC
*, SbxArray
& rPar
, bool)
527 sal_uInt32 nCount
= rPar
.Count();
528 if( !(nCount
& 0x0001 ))
530 // number of arguments must be odd
531 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
533 sal_uInt32 nCurExpr
= 1;
534 while( nCurExpr
< (nCount
-1) )
536 if (rPar
.Get(nCurExpr
)->GetBool())
538 (*rPar
.Get(0)) = *(rPar
.Get(nCurExpr
+ 1));
543 rPar
.Get(0)->PutNull();
546 //i#64882# Common wait impl for existing Wait and new WaitUntil
548 void Wait_Impl( bool bDurationBased
, SbxArray
& rPar
)
550 if (rPar
.Count() != 2)
552 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
555 tools::Long nWait
= 0;
556 if ( bDurationBased
)
558 double dWait
= rPar
.Get(1)->GetDouble();
559 double dNow
= Now_Impl();
560 double dSecs
= ( dWait
- dNow
) * 24.0 * 3600.0;
561 nWait
= static_cast<tools::Long
>( dSecs
* 1000 ); // wait in thousands of sec
565 nWait
= rPar
.Get(1)->GetLong();
569 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
573 Timer
aTimer("basic Wait_Impl");
574 aTimer
.SetTimeout( nWait
);
576 while ( aTimer
.IsActive() && !Application::IsQuit())
578 Application::Yield();
583 void SbRtl_Wait(StarBASIC
*, SbxArray
& rPar
, bool)
585 Wait_Impl( false, rPar
);
588 //i#64882# add new WaitUntil ( for application.wait )
589 // share wait_impl with 'normal' oobasic wait
590 void SbRtl_WaitUntil(StarBASIC
*, SbxArray
& rPar
, bool)
592 Wait_Impl( true, rPar
);
595 void SbRtl_DoEvents(StarBASIC
*, SbxArray
& rPar
, bool)
597 // don't understand what upstream are up to
598 // we already process application events etc. in between
599 // basic runtime pcode ( on a timed basis )
601 rPar
.Get(0)->PutInteger(0);
602 Application::Reschedule( true );
605 void SbRtl_GetGUIVersion(StarBASIC
*, SbxArray
& rPar
, bool)
607 if (rPar
.Count() != 1)
609 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
613 // Removed for SRC595
614 rPar
.Get(0)->PutLong(-1);
618 void SbRtl_Choose(StarBASIC
*, SbxArray
& rPar
, bool)
620 if (rPar
.Count() < 2)
622 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
624 sal_Int16 nIndex
= rPar
.Get(1)->GetInteger();
625 sal_uInt32 nCount
= rPar
.Count();
627 if( nCount
== 1 || nIndex
> sal::static_int_cast
<sal_Int16
>(nCount
-1) || nIndex
< 1 )
629 rPar
.Get(0)->PutNull();
632 (*rPar
.Get(0)) = *(rPar
.Get(nIndex
+ 1));
636 void SbRtl_Trim(StarBASIC
*, SbxArray
& rPar
, bool)
638 if (rPar
.Count() < 2)
640 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
644 OUString
aStr(comphelper::string::strip(rPar
.Get(1)->GetOUString(), ' '));
645 rPar
.Get(0)->PutString(aStr
);
649 void SbRtl_GetSolarVersion(StarBASIC
*, SbxArray
& rPar
, bool)
651 rPar
.Get(0)->PutLong(LIBO_VERSION_MAJOR
* 10000 + LIBO_VERSION_MINOR
* 100
652 + LIBO_VERSION_MICRO
* 1);
655 void SbRtl_TwipsPerPixelX(StarBASIC
*, SbxArray
& rPar
, bool)
657 sal_Int32 nResult
= 0;
659 MapMode
aMap( MapUnit::MapTwip
);
660 OutputDevice
* pDevice
= Application::GetDefaultDevice();
663 aSize
= pDevice
->PixelToLogic( aSize
, aMap
);
664 nResult
= aSize
.Width() / 100;
666 rPar
.Get(0)->PutLong(nResult
);
669 void SbRtl_TwipsPerPixelY(StarBASIC
*, SbxArray
& rPar
, bool)
671 sal_Int32 nResult
= 0;
673 MapMode
aMap( MapUnit::MapTwip
);
674 OutputDevice
* pDevice
= Application::GetDefaultDevice();
677 aSize
= pDevice
->PixelToLogic( aSize
, aMap
);
678 nResult
= aSize
.Height() / 100;
680 rPar
.Get(0)->PutLong(nResult
);
684 void SbRtl_FreeLibrary(StarBASIC
*, SbxArray
& rPar
, bool)
686 if (rPar
.Count() != 2)
688 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
690 GetSbData()->pInst
->GetDllMgr()->FreeDll(rPar
.Get(1)->GetOUString());
692 bool IsBaseIndexOne()
694 bool bResult
= false;
695 if ( GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
697 sal_uInt16 res
= GetSbData()->pInst
->pRun
->GetBase();
706 void SbRtl_Array(StarBASIC
*, SbxArray
& rPar
, bool)
708 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
709 sal_uInt32 nArraySize
= rPar
.Count() - 1;
710 bool bIncIndex
= IsBaseIndexOne();
715 pArray
->AddDim(1, sal::static_int_cast
<sal_Int32
>(nArraySize
));
719 pArray
->AddDim(0, sal::static_int_cast
<sal_Int32
>(nArraySize
) - 1);
724 pArray
->unoAddDim(0, -1);
727 // insert parameters into the array
728 for( sal_uInt32 i
= 0 ; i
< nArraySize
; i
++ )
730 SbxVariable
* pVar
= rPar
.Get(i
+ 1);
731 SbxVariable
* pNew
= new SbxEnsureParentVariable(*pVar
);
732 pNew
->SetFlag( SbxFlagBits::Write
);
734 aIdx
[0] = static_cast<sal_Int32
>(i
);
739 pArray
->Put(pNew
, aIdx
);
743 SbxVariableRef refVar
= rPar
.Get(0);
744 SbxFlagBits nFlags
= refVar
->GetFlags();
745 refVar
->ResetFlag( SbxFlagBits::Fixed
);
746 refVar
->PutObject( pArray
);
747 refVar
->SetFlags( nFlags
);
748 refVar
->SetParameters( nullptr );
752 // Featurewish #57868
753 // The function returns a variant-array; if there are no parameters passed,
754 // an empty array is created (according to dim a(); equal to a sequence of
755 // the length 0 in Uno).
756 // If there are parameters passed, there's a dimension created for each of
757 // them; DimArray( 2, 2, 4 ) is equal to DIM a( 2, 2, 4 )
758 // the array is always of the type variant
759 void SbRtl_DimArray(StarBASIC
*, SbxArray
& rPar
, bool)
761 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
762 sal_uInt32 nArrayDims
= rPar
.Count() - 1;
765 for( sal_uInt32 i
= 0; i
< nArrayDims
; i
++ )
767 sal_Int32 ub
= rPar
.Get(i
+ 1)->GetLong();
770 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
773 pArray
->AddDim(0, ub
);
778 pArray
->unoAddDim(0, -1);
780 SbxVariableRef refVar
= rPar
.Get(0);
781 SbxFlagBits nFlags
= refVar
->GetFlags();
782 refVar
->ResetFlag( SbxFlagBits::Fixed
);
783 refVar
->PutObject( pArray
);
784 refVar
->SetFlags( nFlags
);
785 refVar
->SetParameters( nullptr );
789 * FindObject and FindPropertyObject make it possible to
790 * address objects and properties of the type Object with
791 * their name as string-parameters at the runtime.
794 * MyObj.Prop1.Bla = 5
797 * dim ObjVar as Object
798 * dim ObjProp as Object
800 * ObjVar = FindObject( ObjName$ )
801 * PropName$ = "Prop1"
802 * ObjProp = FindPropertyObject( ObjVar, PropName$ )
805 * The names can be created dynamically at the runtime
806 * so that e. g. via controls "TextEdit1" to "TextEdit5"
807 * can be iterated in a dialog in a loop.
811 // 1st parameter = the object's name as string
812 void SbRtl_FindObject(StarBASIC
*, SbxArray
& rPar
, bool)
814 if (rPar
.Count() < 2)
816 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
820 OUString aNameStr
= rPar
.Get(1)->GetOUString();
822 SbxBase
* pFind
= StarBASIC::FindSBXInCurrentScope( aNameStr
);
823 SbxObject
* pFindObj
= nullptr;
826 pFindObj
= dynamic_cast<SbxObject
*>( pFind
);
828 SbxVariableRef refVar
= rPar
.Get(0);
829 refVar
->PutObject( pFindObj
);
832 // address object-property in an object
833 // 1st parameter = object
834 // 2nd parameter = the property's name as string
835 void SbRtl_FindPropertyObject(StarBASIC
*, SbxArray
& rPar
, bool)
837 if (rPar
.Count() < 3)
839 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
843 SbxBase
* pObjVar
= rPar
.Get(1)->GetObject();
844 SbxObject
* pObj
= nullptr;
847 pObj
= dynamic_cast<SbxObject
*>( pObjVar
);
850 if (auto pSbxVar
= dynamic_cast<const SbxVariable
*>( pObjVar
))
851 pObj
= dynamic_cast<SbxObject
*>( pSbxVar
->GetObject() );
853 OUString aNameStr
= rPar
.Get(2)->GetOUString();
855 SbxObject
* pFindObj
= nullptr;
858 SbxVariable
* pFindVar
= pObj
->Find( aNameStr
, SbxClassType::Object
);
859 pFindObj
= dynamic_cast<SbxObject
*>( pFindVar
);
863 StarBASIC::Error( ERRCODE_BASIC_BAD_PARAMETER
);
866 SbxVariableRef refVar
= rPar
.Get(0);
867 refVar
->PutObject( pFindObj
);
871 static bool lcl_WriteSbxVariable( const SbxVariable
& rVar
, SvStream
* pStrm
,
872 bool bBinary
, short nBlockLen
, bool bIsArray
)
874 sal_uInt64
const nFPos
= pStrm
->Tell();
876 bool bIsVariant
= !rVar
.IsFixed();
877 SbxDataType eType
= rVar
.GetType();
886 pStrm
->WriteUInt16( SbxBYTE
); // VarType Id
888 pStrm
->WriteUChar( rVar
.GetByte() );
900 pStrm
->WriteUInt16( SbxINTEGER
); // VarType Id
902 pStrm
->WriteInt16( rVar
.GetInteger() );
909 pStrm
->WriteUInt16( SbxLONG
); // VarType Id
911 pStrm
->WriteInt32( rVar
.GetLong() );
917 pStrm
->WriteUInt16( SbxSALINT64
); // VarType Id
919 pStrm
->WriteUInt64( rVar
.GetInt64() );
924 pStrm
->WriteUInt16( eType
); // VarType Id
926 pStrm
->WriteFloat( rVar
.GetSingle() );
934 pStrm
->WriteUInt16( eType
); // VarType Id
936 pStrm
->WriteDouble( rVar
.GetDouble() );
942 const OUString
& rStr
= rVar
.GetOUString();
943 if( !bBinary
|| bIsArray
)
947 pStrm
->WriteUInt16( SbxSTRING
);
949 pStrm
->WriteUniOrByteString( rStr
, osl_getThreadTextEncoding() );
953 // without any length information! without end-identifier!
954 // What does that mean for Unicode?! Choosing conversion to ByteString...
955 OString
aByteStr(OUStringToOString(rStr
, osl_getThreadTextEncoding()));
956 pStrm
->WriteOString( aByteStr
);
962 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
968 pStrm
->Seek( nFPos
+ nBlockLen
);
970 return pStrm
->GetErrorCode() == ERRCODE_NONE
;
973 static bool lcl_ReadSbxVariable( SbxVariable
& rVar
, SvStream
* pStrm
,
974 bool bBinary
, short nBlockLen
)
978 sal_uInt64
const nFPos
= pStrm
->Tell();
980 bool bIsVariant
= !rVar
.IsFixed();
981 SbxDataType eVarType
= rVar
.GetType();
983 SbxDataType eSrcType
= eVarType
;
987 pStrm
->ReadUInt16( nTemp
);
988 eSrcType
= static_cast<SbxDataType
>(nTemp
);
998 pStrm
->ReadUChar( aByte
);
1000 if( bBinary
&& SbiRuntime::isVBAEnabled() && aByte
== 1 && pStrm
->eof() )
1004 rVar
.PutByte( aByte
);
1017 pStrm
->ReadInt16( aInt
);
1018 rVar
.PutInteger( aInt
);
1026 pStrm
->ReadInt32( aInt
);
1027 rVar
.PutLong( aInt
);
1034 pStrm
->ReadUInt32( aInt
);
1035 rVar
.PutInt64( static_cast<sal_Int64
>(aInt
) );
1041 pStrm
->ReadFloat( nS
);
1042 rVar
.PutSingle( nS
);
1049 pStrm
->ReadDouble( aDouble
);
1050 rVar
.PutDouble( aDouble
);
1056 pStrm
->ReadDouble( aDouble
);
1057 rVar
.PutDate( aDouble
);
1064 OUString aStr
= pStrm
->ReadUniOrByteString(osl_getThreadTextEncoding());
1065 rVar
.PutString( aStr
);
1070 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1076 pStrm
->Seek( nFPos
+ nBlockLen
);
1078 return pStrm
->GetErrorCode() == ERRCODE_NONE
;
1083 static bool lcl_WriteReadSbxArray( SbxDimArray
& rArr
, SvStream
* pStrm
,
1084 bool bBinary
, sal_Int32 nCurDim
, sal_Int32
* pOtherDims
, bool bWrite
)
1086 SAL_WARN_IF( nCurDim
<= 0,"basic", "Bad Dim");
1087 sal_Int32 nLower
, nUpper
;
1088 if (!rArr
.GetDim(nCurDim
, nLower
, nUpper
))
1090 for(sal_Int32 nCur
= nLower
; nCur
<= nUpper
; nCur
++ )
1092 pOtherDims
[ nCurDim
-1 ] = nCur
;
1094 lcl_WriteReadSbxArray(rArr
, pStrm
, bBinary
, nCurDim
-1, pOtherDims
, bWrite
);
1097 SbxVariable
* pVar
= rArr
.Get(pOtherDims
);
1100 bRet
= lcl_WriteSbxVariable(*pVar
, pStrm
, bBinary
, 0, true );
1102 bRet
= lcl_ReadSbxVariable(*pVar
, pStrm
, bBinary
, 0 );
1110 static void PutGet( SbxArray
& rPar
, bool bPut
)
1112 if (rPar
.Count() != 4)
1114 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1117 sal_Int16 nFileNo
= rPar
.Get(1)->GetInteger();
1118 SbxVariable
* pVar2
= rPar
.Get(2);
1119 SbxDataType eType2
= pVar2
->GetType();
1120 bool bHasRecordNo
= (eType2
!= SbxEMPTY
&& eType2
!= SbxERROR
);
1121 tools::Long nRecordNo
= pVar2
->GetLong();
1122 if ( nFileNo
< 1 || ( bHasRecordNo
&& nRecordNo
< 1 ) )
1124 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1128 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
1129 SbiStream
* pSbStrm
= pIO
->GetStream( nFileNo
);
1131 if ( !pSbStrm
|| !(pSbStrm
->GetMode() & (SbiStreamFlags::Binary
| SbiStreamFlags::Random
)) )
1133 StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL
);
1137 SvStream
* pStrm
= pSbStrm
->GetStrm();
1138 bool bRandom
= pSbStrm
->IsRandom();
1139 short nBlockLen
= bRandom
? pSbStrm
->GetBlockLen() : 0;
1143 pSbStrm
->ExpandFile();
1148 sal_uInt64
const nFilePos
= bRandom
1149 ? static_cast<sal_uInt64
>(nBlockLen
* nRecordNo
)
1150 : static_cast<sal_uInt64
>(nRecordNo
);
1151 pStrm
->Seek( nFilePos
);
1154 SbxDimArray
* pArr
= nullptr;
1155 SbxVariable
* pVar
= rPar
.Get(3);
1156 if( pVar
->GetType() & SbxARRAY
)
1158 SbxBase
* pParObj
= pVar
->GetObject();
1159 pArr
= dynamic_cast<SbxDimArray
*>( pParObj
);
1166 sal_uInt64
const nFPos
= pStrm
->Tell();
1167 sal_Int32 nDims
= pArr
->GetDims();
1168 std::unique_ptr
<sal_Int32
[]> pDims(new sal_Int32
[ nDims
]);
1169 bRet
= lcl_WriteReadSbxArray(*pArr
,pStrm
,!bRandom
,nDims
,pDims
.get(),bPut
);
1172 pStrm
->Seek( nFPos
+ nBlockLen
);
1177 bRet
= lcl_WriteSbxVariable(*pVar
, pStrm
, !bRandom
, nBlockLen
, false);
1179 bRet
= lcl_ReadSbxVariable(*pVar
, pStrm
, !bRandom
, nBlockLen
);
1181 if( !bRet
|| pStrm
->GetErrorCode() )
1182 StarBASIC::Error( ERRCODE_BASIC_IO_ERROR
);
1185 void SbRtl_Put(StarBASIC
*, SbxArray
& rPar
, bool)
1187 PutGet( rPar
, true );
1190 void SbRtl_Get(StarBASIC
*, SbxArray
& rPar
, bool)
1192 PutGet( rPar
, false );
1195 void SbRtl_Environ(StarBASIC
*, SbxArray
& rPar
, bool)
1197 if (rPar
.Count() != 2)
1199 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1203 // should be ANSI but that's not possible under Win16 in the DLL
1204 OString
aByteStr(OUStringToOString(rPar
.Get(1)->GetOUString(),
1205 osl_getThreadTextEncoding()));
1206 const char* pEnvStr
= getenv(aByteStr
.getStr());
1209 aResult
= OUString(pEnvStr
, strlen(pEnvStr
), osl_getThreadTextEncoding());
1211 rPar
.Get(0)->PutString(aResult
);
1214 static double GetDialogZoomFactor( bool bX
, tools::Long nValue
)
1216 OutputDevice
* pDevice
= Application::GetDefaultDevice();
1220 Size
aRefSize( nValue
, nValue
);
1221 Fraction
aFracX( 1, 26 );
1222 Fraction
aFracY( 1, 24 );
1223 MapMode
aMap( MapUnit::MapAppFont
, Point(), aFracX
, aFracY
);
1224 Size aScaledSize
= pDevice
->LogicToPixel( aRefSize
, aMap
);
1225 aRefSize
= pDevice
->LogicToPixel( aRefSize
, MapMode(MapUnit::MapTwip
) );
1227 double nRef
, nScaled
;
1230 nRef
= aRefSize
.Width();
1231 nScaled
= aScaledSize
.Width();
1235 nRef
= aRefSize
.Height();
1236 nScaled
= aScaledSize
.Height();
1238 nResult
= nScaled
/ nRef
;
1244 void SbRtl_GetDialogZoomFactorX(StarBASIC
*, SbxArray
& rPar
, bool)
1246 if (rPar
.Count() != 2)
1248 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1251 rPar
.Get(0)->PutDouble(GetDialogZoomFactor(true, rPar
.Get(1)->GetLong()));
1254 void SbRtl_GetDialogZoomFactorY(StarBASIC
*, SbxArray
& rPar
, bool)
1256 if (rPar
.Count() != 2)
1258 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1261 rPar
.Get(0)->PutDouble(GetDialogZoomFactor(false, rPar
.Get(1)->GetLong()));
1265 void SbRtl_EnableReschedule(StarBASIC
*, SbxArray
& rPar
, bool)
1267 rPar
.Get(0)->PutEmpty();
1268 if (rPar
.Count() != 2)
1269 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1270 if( GetSbData()->pInst
)
1271 GetSbData()->pInst
->EnableReschedule(rPar
.Get(1)->GetBool());
1274 void SbRtl_GetSystemTicks(StarBASIC
*, SbxArray
& rPar
, bool)
1276 if (rPar
.Count() != 1)
1278 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1281 rPar
.Get(0)->PutLong(tools::Time::GetSystemTicks());
1284 void SbRtl_GetPathSeparator(StarBASIC
*, SbxArray
& rPar
, bool)
1286 if (rPar
.Count() != 1)
1288 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1291 rPar
.Get(0)->PutString(OUString(SAL_PATHDELIMITER
));
1294 void SbRtl_ResolvePath(StarBASIC
*, SbxArray
& rPar
, bool)
1296 if (rPar
.Count() == 2)
1298 OUString aStr
= rPar
.Get(1)->GetOUString();
1299 rPar
.Get(0)->PutString(aStr
);
1303 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1307 void SbRtl_TypeLen(StarBASIC
*, SbxArray
& rPar
, bool)
1309 if (rPar
.Count() != 2)
1311 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1315 SbxDataType eType
= rPar
.Get(1)->GetType();
1371 nLen
= static_cast<sal_Int16
>(rPar
.Get(1)->GetOUString().getLength());
1378 rPar
.Get(0)->PutInteger(nLen
);
1383 // 1st parameter == class name, other parameters for initialisation
1384 void SbRtl_CreateUnoStruct(StarBASIC
*, SbxArray
& rPar
, bool)
1386 RTL_Impl_CreateUnoStruct( rPar
);
1390 // 1st parameter == service-name
1391 void SbRtl_CreateUnoService(StarBASIC
*, SbxArray
& rPar
, bool)
1393 RTL_Impl_CreateUnoService( rPar
);
1396 void SbRtl_CreateUnoServiceWithArguments(StarBASIC
*, SbxArray
& rPar
, bool)
1398 RTL_Impl_CreateUnoServiceWithArguments( rPar
);
1402 void SbRtl_CreateUnoValue(StarBASIC
*, SbxArray
& rPar
, bool)
1404 RTL_Impl_CreateUnoValue( rPar
);
1409 void SbRtl_GetProcessServiceManager(StarBASIC
*, SbxArray
& rPar
, bool)
1411 RTL_Impl_GetProcessServiceManager( rPar
);
1415 // 1st parameter == Sequence<PropertyValue>
1416 void SbRtl_CreatePropertySet(StarBASIC
*, SbxArray
& rPar
, bool)
1418 RTL_Impl_CreatePropertySet( rPar
);
1422 // multiple interface-names as parameters
1423 void SbRtl_HasUnoInterfaces(StarBASIC
*, SbxArray
& rPar
, bool)
1425 RTL_Impl_HasInterfaces( rPar
);
1429 void SbRtl_IsUnoStruct(StarBASIC
*, SbxArray
& rPar
, bool)
1431 RTL_Impl_IsUnoStruct( rPar
);
1435 void SbRtl_EqualUnoObjects(StarBASIC
*, SbxArray
& rPar
, bool)
1437 RTL_Impl_EqualUnoObjects( rPar
);
1440 void SbRtl_CreateUnoDialog(StarBASIC
*, SbxArray
& rPar
, bool)
1442 RTL_Impl_CreateUnoDialog( rPar
);
1445 // Return the application standard lib as root scope
1446 void SbRtl_GlobalScope(StarBASIC
* pBasic
, SbxArray
& rPar
, bool)
1448 SbxObject
* p
= pBasic
;
1449 while( p
->GetParent() )
1453 SbxVariableRef refVar
= rPar
.Get(0);
1454 refVar
->PutObject( p
);
1457 // Helper functions to convert Url from/to system paths
1458 void SbRtl_ConvertToUrl(StarBASIC
*, SbxArray
& rPar
, bool)
1460 if (rPar
.Count() == 2)
1462 OUString aStr
= rPar
.Get(1)->GetOUString();
1463 INetURLObject
aURLObj( aStr
, INetProtocol::File
);
1464 OUString aFileURL
= aURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1465 if( aFileURL
.isEmpty() )
1467 osl::File::getFileURLFromSystemPath(aStr
, aFileURL
);
1469 if( aFileURL
.isEmpty() )
1473 rPar
.Get(0)->PutString(aFileURL
);
1477 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1481 void SbRtl_ConvertFromUrl(StarBASIC
*, SbxArray
& rPar
, bool)
1483 if (rPar
.Count() == 2)
1485 OUString aStr
= rPar
.Get(1)->GetOUString();
1487 ::osl::File::getSystemPathFromFileURL( aStr
, aSysPath
);
1488 if( aSysPath
.isEmpty() )
1492 rPar
.Get(0)->PutString(aSysPath
);
1496 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1501 // Provide DefaultContext
1502 void SbRtl_GetDefaultContext(StarBASIC
*, SbxArray
& rPar
, bool)
1504 RTL_Impl_GetDefaultContext( rPar
);
1507 void SbRtl_Join(StarBASIC
*, SbxArray
& rPar
, bool)
1509 sal_uInt32 nParCount
= rPar
.Count();
1510 if ( nParCount
!= 3 && nParCount
!= 2 )
1512 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1515 SbxBase
* pParObj
= rPar
.Get(1)->GetObject();
1516 SbxDimArray
* pArr
= dynamic_cast<SbxDimArray
*>( pParObj
);
1519 if (pArr
->GetDims() != 1)
1521 StarBASIC::Error( ERRCODE_BASIC_WRONG_DIMS
); // Syntax Error?!
1525 if( nParCount
== 3 )
1527 aDelim
= rPar
.Get(2)->GetOUString();
1533 OUStringBuffer
aRetStr(32);
1534 sal_Int32 nLower
, nUpper
;
1535 pArr
->GetDim(1, nLower
, nUpper
);
1537 for (aIdx
[0] = nLower
; aIdx
[0] <= nUpper
; ++aIdx
[0])
1539 OUString aStr
= pArr
->Get(aIdx
)->GetOUString();
1540 aRetStr
.append(aStr
);
1541 if (aIdx
[0] != nUpper
)
1543 aRetStr
.append(aDelim
);
1546 rPar
.Get(0)->PutString(aRetStr
.makeStringAndClear());
1550 StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS
);
1555 void SbRtl_Split(StarBASIC
*, SbxArray
& rPar
, bool)
1557 sal_uInt32 nParCount
= rPar
.Count();
1558 if ( nParCount
< 2 )
1560 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1564 OUString aExpression
= rPar
.Get(1)->GetOUString();
1565 sal_Int32 nArraySize
= 0;
1566 std::vector
< OUString
> vRet
;
1567 if( !aExpression
.isEmpty() )
1570 if( nParCount
>= 3 )
1572 aDelim
= rPar
.Get(2)->GetOUString();
1579 sal_Int32 nCount
= -1;
1580 if( nParCount
== 4 )
1582 nCount
= rPar
.Get(3)->GetLong();
1584 sal_Int32 nDelimLen
= aDelim
.getLength();
1587 sal_Int32 iSearch
= -1;
1588 sal_Int32 iStart
= 0;
1591 bool bBreak
= false;
1592 if( nCount
>= 0 && nArraySize
== nCount
- 1 )
1596 iSearch
= aExpression
.indexOf( aDelim
, iStart
);
1598 if( iSearch
>= 0 && !bBreak
)
1600 aSubStr
= aExpression
.copy( iStart
, iSearch
- iStart
);
1601 iStart
= iSearch
+ nDelimLen
;
1605 aSubStr
= aExpression
.copy( iStart
);
1607 vRet
.push_back( aSubStr
);
1615 while( iSearch
>= 0 );
1619 vRet
.push_back( aExpression
);
1624 // tdf#123025 - split returns an array of substrings
1625 SbxDimArray
* pArray
= new SbxDimArray( SbxSTRING
);
1626 pArray
->unoAddDim(0, nArraySize
- 1);
1628 // insert parameter(s) into the array
1629 const bool bIsVBAInterOp
= SbiRuntime::isVBAEnabled();
1630 for(sal_Int32 i
= 0 ; i
< nArraySize
; i
++ )
1632 // tdf#123025 - split returns an array of substrings
1633 SbxVariableRef xVar
= new SbxVariable( SbxSTRING
);
1634 xVar
->PutString( vRet
[i
] );
1635 // tdf#144924 - allow the assignment of different data types to the individual elements
1638 xVar
->ResetFlag(SbxFlagBits::Fixed
);
1640 pArray
->Put(xVar
.get(), &i
);
1644 SbxVariableRef refVar
= rPar
.Get(0);
1645 SbxFlagBits nFlags
= refVar
->GetFlags();
1646 refVar
->ResetFlag( SbxFlagBits::Fixed
);
1647 refVar
->PutObject( pArray
);
1648 refVar
->SetFlags( nFlags
);
1649 refVar
->SetParameters( nullptr );
1652 // MonthName(month[, abbreviate])
1653 void SbRtl_MonthName(StarBASIC
*, SbxArray
& rPar
, bool)
1655 sal_uInt32 nParCount
= rPar
.Count();
1656 if( nParCount
!= 2 && nParCount
!= 3 )
1658 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1662 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
1663 if( !xCalendar
.is() )
1665 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
1668 Sequence
< CalendarItem2
> aMonthSeq
= xCalendar
->getMonths2();
1669 sal_Int32 nMonthCount
= aMonthSeq
.getLength();
1671 sal_Int16 nVal
= rPar
.Get(1)->GetInteger();
1672 if( nVal
< 1 || nVal
> nMonthCount
)
1674 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1678 bool bAbbreviate
= false;
1679 if( nParCount
== 3 )
1680 bAbbreviate
= rPar
.Get(2)->GetBool();
1682 const CalendarItem2
* pCalendarItems
= aMonthSeq
.getConstArray();
1683 const CalendarItem2
& rItem
= pCalendarItems
[nVal
- 1];
1685 OUString aRetStr
= ( bAbbreviate
? rItem
.AbbrevName
: rItem
.FullName
);
1686 rPar
.Get(0)->PutString(aRetStr
);
1689 // WeekdayName(weekday, abbreviate, firstdayofweek)
1690 void SbRtl_WeekdayName(StarBASIC
*, SbxArray
& rPar
, bool)
1692 sal_uInt32 nParCount
= rPar
.Count();
1693 if( nParCount
< 2 || nParCount
> 4 )
1695 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1699 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
1700 if( !xCalendar
.is() )
1702 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
1706 Sequence
< CalendarItem2
> aDaySeq
= xCalendar
->getDays2();
1707 sal_Int16 nDayCount
= static_cast<sal_Int16
>(aDaySeq
.getLength());
1708 sal_Int16 nDay
= rPar
.Get(1)->GetInteger();
1709 sal_Int16 nFirstDay
= 0;
1710 if( nParCount
== 4 )
1712 nFirstDay
= rPar
.Get(3)->GetInteger();
1713 if( nFirstDay
< 0 || nFirstDay
> 7 )
1715 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1719 if( nFirstDay
== 0 )
1721 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
1723 nDay
= 1 + (nDay
+ nDayCount
+ nFirstDay
- 2) % nDayCount
;
1724 if( nDay
< 1 || nDay
> nDayCount
)
1726 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1730 bool bAbbreviate
= false;
1731 if( nParCount
>= 3 )
1733 SbxVariable
* pPar2
= rPar
.Get(2);
1734 if( !pPar2
->IsErr() )
1736 bAbbreviate
= pPar2
->GetBool();
1740 const CalendarItem2
* pCalendarItems
= aDaySeq
.getConstArray();
1741 const CalendarItem2
& rItem
= pCalendarItems
[nDay
- 1];
1743 OUString aRetStr
= ( bAbbreviate
? rItem
.AbbrevName
: rItem
.FullName
);
1744 rPar
.Get(0)->PutString(aRetStr
);
1747 void SbRtl_Weekday(StarBASIC
*, SbxArray
& rPar
, bool)
1749 sal_uInt32 nParCount
= rPar
.Count();
1750 if ( nParCount
< 2 )
1752 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1756 double aDate
= rPar
.Get(1)->GetDate();
1758 bool bFirstDay
= false;
1759 sal_Int16 nFirstDay
= 0;
1760 if ( nParCount
> 2 )
1762 nFirstDay
= rPar
.Get(2)->GetInteger();
1765 sal_Int16 nDay
= implGetWeekDay( aDate
, bFirstDay
, nFirstDay
);
1766 rPar
.Get(0)->PutInteger(nDay
);
1788 Interval meInterval
;
1789 char const * mStringCode
;
1796 static IntervalInfo
const * getIntervalInfo( const OUString
& rStringCode
)
1798 static IntervalInfo
const aIntervalTable
[] =
1800 { INTERVAL_YYYY
, "yyyy", 0.0, false }, // Year
1801 { INTERVAL_Q
, "q", 0.0, false }, // Quarter
1802 { INTERVAL_M
, "m", 0.0, false }, // Month
1803 { INTERVAL_Y
, "y", 1.0, true }, // Day of year
1804 { INTERVAL_D
, "d", 1.0, true }, // Day
1805 { INTERVAL_W
, "w", 1.0, true }, // Weekday
1806 { INTERVAL_WW
, "ww", 7.0, true }, // Week
1807 { INTERVAL_H
, "h", 1.0 / 24.0, true }, // Hour
1808 { INTERVAL_N
, "n", 1.0 / 1440.0, true }, // Minute
1809 { INTERVAL_S
, "s", 1.0 / 86400.0, true } // Second
1811 for( std::size_t i
= 0; i
!= SAL_N_ELEMENTS(aIntervalTable
); ++i
)
1813 if( rStringCode
.equalsIgnoreAsciiCaseAscii(
1814 aIntervalTable
[i
].mStringCode
) )
1816 return &aIntervalTable
[i
];
1822 static void implGetDayMonthYear( sal_Int16
& rnYear
, sal_Int16
& rnMonth
, sal_Int16
& rnDay
, double dDate
)
1824 rnDay
= implGetDateDay( dDate
);
1825 rnMonth
= implGetDateMonth( dDate
);
1826 rnYear
= implGetDateYear( dDate
);
1829 /** Limits a date to valid dates within tools' class Date capabilities.
1831 @return the year number, truncated if necessary and in that case also
1832 rMonth and rDay adjusted.
1834 static sal_Int16
limitDate( sal_Int32 n32Year
, sal_Int16
& rMonth
, sal_Int16
& rDay
)
1836 if( n32Year
> SAL_MAX_INT16
)
1838 n32Year
= SAL_MAX_INT16
;
1842 else if( n32Year
< SAL_MIN_INT16
)
1844 n32Year
= SAL_MIN_INT16
;
1848 return static_cast<sal_Int16
>(n32Year
);
1851 void SbRtl_DateAdd(StarBASIC
*, SbxArray
& rPar
, bool)
1853 sal_uInt32 nParCount
= rPar
.Count();
1854 if( nParCount
!= 4 )
1856 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1860 OUString aStringCode
= rPar
.Get(1)->GetOUString();
1861 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
1864 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1868 sal_Int32 lNumber
= rPar
.Get(2)->GetLong();
1869 double dDate
= rPar
.Get(3)->GetDate();
1870 double dNewDate
= 0;
1871 if( pInfo
->mbSimple
)
1873 double dAdd
= pInfo
->mdValue
* lNumber
;
1874 dNewDate
= dDate
+ dAdd
;
1878 // Keep hours, minutes, seconds
1879 double dHoursMinutesSeconds
= dDate
- floor( dDate
);
1882 sal_Int16 nYear
, nMonth
, nDay
;
1883 sal_Int16 nTargetYear16
= 0, nTargetMonth
= 0;
1884 implGetDayMonthYear( nYear
, nMonth
, nDay
, dDate
);
1885 switch( pInfo
->meInterval
)
1889 sal_Int32 nTargetYear
= lNumber
+ nYear
;
1890 nTargetYear16
= limitDate( nTargetYear
, nMonth
, nDay
);
1891 /* TODO: should the result be error if the date was limited? It never was. */
1892 nTargetMonth
= nMonth
;
1893 bOk
= implDateSerial( nTargetYear16
, nTargetMonth
, nDay
, false, SbDateCorrection::TruncateToMonth
, dNewDate
);
1899 bool bNeg
= (lNumber
< 0);
1902 sal_Int32 nYearsAdd
;
1903 sal_Int16 nMonthAdd
;
1904 if( pInfo
->meInterval
== INTERVAL_Q
)
1906 nYearsAdd
= lNumber
/ 4;
1907 nMonthAdd
= static_cast<sal_Int16
>( 3 * (lNumber
% 4) );
1911 nYearsAdd
= lNumber
/ 12;
1912 nMonthAdd
= static_cast<sal_Int16
>( lNumber
% 12 );
1915 sal_Int32 nTargetYear
;
1918 nTargetMonth
= nMonth
- nMonthAdd
;
1919 if( nTargetMonth
<= 0 )
1924 nTargetYear
= static_cast<sal_Int32
>(nYear
) - nYearsAdd
;
1928 nTargetMonth
= nMonth
+ nMonthAdd
;
1929 if( nTargetMonth
> 12 )
1934 nTargetYear
= static_cast<sal_Int32
>(nYear
) + nYearsAdd
;
1936 nTargetYear16
= limitDate( nTargetYear
, nTargetMonth
, nDay
);
1937 /* TODO: should the result be error if the date was limited? It never was. */
1938 bOk
= implDateSerial( nTargetYear16
, nTargetMonth
, nDay
, false, SbDateCorrection::TruncateToMonth
, dNewDate
);
1945 dNewDate
+= dHoursMinutesSeconds
;
1948 rPar
.Get(0)->PutDate(dNewDate
);
1951 static double RoundImpl( double d
)
1953 return ( d
>= 0 ) ? floor( d
+ 0.5 ) : -floor( -d
+ 0.5 );
1956 void SbRtl_DateDiff(StarBASIC
*, SbxArray
& rPar
, bool)
1958 // DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]])
1960 sal_uInt32 nParCount
= rPar
.Count();
1961 if( nParCount
< 4 || nParCount
> 6 )
1963 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1967 OUString aStringCode
= rPar
.Get(1)->GetOUString();
1968 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
1971 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1975 double dDate1
= rPar
.Get(2)->GetDate();
1976 double dDate2
= rPar
.Get(3)->GetDate();
1979 switch( pInfo
->meInterval
)
1983 sal_Int16 nYear1
= implGetDateYear( dDate1
);
1984 sal_Int16 nYear2
= implGetDateYear( dDate2
);
1985 dRet
= nYear2
- nYear1
;
1990 sal_Int16 nYear1
= implGetDateYear( dDate1
);
1991 sal_Int16 nYear2
= implGetDateYear( dDate2
);
1992 sal_Int16 nQ1
= 1 + (implGetDateMonth( dDate1
) - 1) / 3;
1993 sal_Int16 nQ2
= 1 + (implGetDateMonth( dDate2
) - 1) / 3;
1994 sal_Int16 nQGes1
= 4 * nYear1
+ nQ1
;
1995 sal_Int16 nQGes2
= 4 * nYear2
+ nQ2
;
1996 dRet
= nQGes2
- nQGes1
;
2001 sal_Int16 nYear1
= implGetDateYear( dDate1
);
2002 sal_Int16 nYear2
= implGetDateYear( dDate2
);
2003 sal_Int16 nMonth1
= implGetDateMonth( dDate1
);
2004 sal_Int16 nMonth2
= implGetDateMonth( dDate2
);
2005 sal_Int16 nMonthGes1
= 12 * nYear1
+ nMonth1
;
2006 sal_Int16 nMonthGes2
= 12 * nYear2
+ nMonth2
;
2007 dRet
= nMonthGes2
- nMonthGes1
;
2013 double dDays1
= floor( dDate1
);
2014 double dDays2
= floor( dDate2
);
2015 dRet
= dDays2
- dDays1
;
2021 double dDays1
= floor( dDate1
);
2022 double dDays2
= floor( dDate2
);
2023 if( pInfo
->meInterval
== INTERVAL_WW
)
2025 sal_Int16 nFirstDay
= 1; // Default
2026 if( nParCount
>= 5 )
2028 nFirstDay
= rPar
.Get(4)->GetInteger();
2029 if( nFirstDay
< 0 || nFirstDay
> 7 )
2031 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2034 if( nFirstDay
== 0 )
2036 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
2037 if( !xCalendar
.is() )
2039 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
2042 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
2045 sal_Int16 nDay1
= implGetWeekDay( dDate1
);
2046 sal_Int16 nDay1_Diff
= nDay1
- nFirstDay
;
2047 if( nDay1_Diff
< 0 )
2049 dDays1
-= nDay1_Diff
;
2051 sal_Int16 nDay2
= implGetWeekDay( dDate2
);
2052 sal_Int16 nDay2_Diff
= nDay2
- nFirstDay
;
2053 if( nDay2_Diff
< 0 )
2055 dDays2
-= nDay2_Diff
;
2058 double dDiff
= dDays2
- dDays1
;
2059 dRet
= ( dDiff
>= 0 ) ? floor( dDiff
/ 7.0 ) : -floor( -dDiff
/ 7.0 );
2064 dRet
= RoundImpl( 24.0 * (dDate2
- dDate1
) );
2069 dRet
= RoundImpl( 1440.0 * (dDate2
- dDate1
) );
2074 dRet
= RoundImpl( 86400.0 * (dDate2
- dDate1
) );
2078 rPar
.Get(0)->PutDouble(dRet
);
2081 static double implGetDateOfFirstDayInFirstWeek
2082 ( sal_Int16 nYear
, sal_Int16
& nFirstDay
, sal_Int16
& nFirstWeek
, bool* pbError
= nullptr )
2084 ErrCode nError
= ERRCODE_NONE
;
2085 if( nFirstDay
< 0 || nFirstDay
> 7 )
2086 nError
= ERRCODE_BASIC_BAD_ARGUMENT
;
2088 if( nFirstWeek
< 0 || nFirstWeek
> 3 )
2089 nError
= ERRCODE_BASIC_BAD_ARGUMENT
;
2091 Reference
< XCalendar4
> xCalendar
;
2092 if( nFirstDay
== 0 || nFirstWeek
== 0 )
2094 xCalendar
= getLocaleCalendar();
2095 if( !xCalendar
.is() )
2096 nError
= ERRCODE_BASIC_BAD_ARGUMENT
;
2099 if( nError
!= ERRCODE_NONE
)
2101 StarBASIC::Error( nError
);
2107 if( nFirstDay
== 0 )
2108 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
2110 sal_Int16 nFirstWeekMinDays
= 0; // Not used for vbFirstJan1 = default
2111 if( nFirstWeek
== 0 )
2113 nFirstWeekMinDays
= xCalendar
->getMinimumNumberOfDaysForFirstWeek();
2114 if( nFirstWeekMinDays
== 1 )
2116 nFirstWeekMinDays
= 0;
2119 else if( nFirstWeekMinDays
== 4 )
2121 else if( nFirstWeekMinDays
== 7 )
2124 else if( nFirstWeek
== 2 )
2125 nFirstWeekMinDays
= 4; // vbFirstFourDays
2126 else if( nFirstWeek
== 3 )
2127 nFirstWeekMinDays
= 7; // vbFirstFourDays
2130 implDateSerial( nYear
, 1, 1, false, SbDateCorrection::None
, dBaseDate
);
2132 sal_Int16 nWeekDay0101
= implGetWeekDay( dBaseDate
);
2133 sal_Int16 nDayDiff
= nWeekDay0101
- nFirstDay
;
2137 if( nFirstWeekMinDays
)
2139 sal_Int16 nThisWeeksDaysInYearCount
= 7 - nDayDiff
;
2140 if( nThisWeeksDaysInYearCount
< nFirstWeekMinDays
)
2143 double dRetDate
= dBaseDate
- nDayDiff
;
2147 void SbRtl_DatePart(StarBASIC
*, SbxArray
& rPar
, bool)
2149 // DatePart(interval, date[,firstdayofweek[, firstweekofyear]])
2151 sal_uInt32 nParCount
= rPar
.Count();
2152 if( nParCount
< 3 || nParCount
> 5 )
2154 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2158 OUString aStringCode
= rPar
.Get(1)->GetOUString();
2159 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
2162 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2166 double dDate
= rPar
.Get(2)->GetDate();
2169 switch( pInfo
->meInterval
)
2173 nRet
= implGetDateYear( dDate
);
2178 nRet
= 1 + (implGetDateMonth( dDate
) - 1) / 3;
2183 nRet
= implGetDateMonth( dDate
);
2188 sal_Int16 nYear
= implGetDateYear( dDate
);
2190 implDateSerial( nYear
, 1, 1, false, SbDateCorrection::None
, dBaseDate
);
2191 nRet
= 1 + sal_Int32( dDate
- dBaseDate
);
2196 nRet
= implGetDateDay( dDate
);
2201 bool bFirstDay
= false;
2202 sal_Int16 nFirstDay
= 1; // Default
2203 if( nParCount
>= 4 )
2205 nFirstDay
= rPar
.Get(3)->GetInteger();
2208 nRet
= implGetWeekDay( dDate
, bFirstDay
, nFirstDay
);
2213 sal_Int16 nFirstDay
= 1; // Default
2214 if( nParCount
>= 4 )
2215 nFirstDay
= rPar
.Get(3)->GetInteger();
2217 sal_Int16 nFirstWeek
= 1; // Default
2218 if( nParCount
== 5 )
2219 nFirstWeek
= rPar
.Get(4)->GetInteger();
2221 sal_Int16 nYear
= implGetDateYear( dDate
);
2222 bool bError
= false;
2223 double dYearFirstDay
= implGetDateOfFirstDayInFirstWeek( nYear
, nFirstDay
, nFirstWeek
, &bError
);
2226 if( dYearFirstDay
> dDate
)
2228 // Date belongs to last year's week
2229 dYearFirstDay
= implGetDateOfFirstDayInFirstWeek( nYear
- 1, nFirstDay
, nFirstWeek
);
2231 else if( nFirstWeek
!= 1 )
2233 // Check if date belongs to next year
2234 double dNextYearFirstDay
= implGetDateOfFirstDayInFirstWeek( nYear
+ 1, nFirstDay
, nFirstWeek
);
2235 if( dDate
>= dNextYearFirstDay
)
2236 dYearFirstDay
= dNextYearFirstDay
;
2240 double dDiff
= dDate
- dYearFirstDay
;
2241 nRet
= 1 + sal_Int32( dDiff
/ 7 );
2247 nRet
= implGetHour( dDate
);
2252 nRet
= implGetMinute( dDate
);
2257 nRet
= implGetSecond( dDate
);
2261 rPar
.Get(0)->PutLong(nRet
);
2264 // FormatDateTime(Date[,NamedFormat])
2265 void SbRtl_FormatDateTime(StarBASIC
*, SbxArray
& rPar
, bool)
2267 sal_uInt32 nParCount
= rPar
.Count();
2268 if( nParCount
< 2 || nParCount
> 3 )
2270 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2274 double dDate
= rPar
.Get(1)->GetDate();
2275 sal_Int16 nNamedFormat
= 0;
2278 nNamedFormat
= rPar
.Get(2)->GetInteger();
2279 if( nNamedFormat
< 0 || nNamedFormat
> 4 )
2281 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2286 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
2287 if( !xCalendar
.is() )
2289 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
2294 SbxVariableRef pSbxVar
= new SbxVariable( SbxSTRING
);
2295 switch( nNamedFormat
)
2298 // Display a date and/or time. If there is a date part,
2299 // display it as a short date. If there is a time part,
2300 // display it as a long time. If present, both parts are displayed.
2302 // 12/21/2004 11:24:50 AM
2303 // 21.12.2004 12:13:51
2305 pSbxVar
->PutDate( dDate
);
2306 aRetStr
= pSbxVar
->GetOUString();
2309 // LongDate: Display a date using the long date format specified
2310 // in your computer's regional settings.
2311 // Tuesday, December 21, 2004
2312 // Dienstag, 21. December 2004
2315 std::shared_ptr
<SvNumberFormatter
> pFormatter
;
2316 if( GetSbData()->pInst
)
2318 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2322 sal_uInt32 n
; // Dummy
2323 pFormatter
= SbiInstance::PrepareNumberFormatter( n
, n
, n
);
2326 LanguageType eLangType
= Application::GetSettings().GetLanguageTag().getLanguageType();
2327 const sal_uInt32 nIndex
= pFormatter
->GetFormatIndex( NF_DATE_SYSTEM_LONG
, eLangType
);
2329 pFormatter
->GetOutputString( dDate
, nIndex
, aRetStr
, &pCol
);
2333 // ShortDate: Display a date using the short date format specified
2334 // in your computer's regional settings.
2337 pSbxVar
->PutDate( floor(dDate
) );
2338 aRetStr
= pSbxVar
->GetOUString();
2341 // LongTime: Display a time using the time format specified
2342 // in your computer's regional settings.
2346 // ShortTime: Display a time using the 24-hour format (hh:mm).
2349 double dTime
= modf( dDate
, &o3tl::temporary(double()) );
2350 pSbxVar
->PutDate( dTime
);
2351 if( nNamedFormat
== 3 )
2353 aRetStr
= pSbxVar
->GetOUString();
2357 aRetStr
= pSbxVar
->GetOUString().copy( 0, 5 );
2362 rPar
.Get(0)->PutString(aRetStr
);
2365 void SbRtl_Frac(StarBASIC
*, SbxArray
& rPar
, bool)
2367 sal_uInt32 nParCount
= rPar
.Count();
2370 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2374 SbxVariable
* pSbxVariable
= rPar
.Get(1);
2375 double dVal
= pSbxVariable
->GetDouble();
2377 rPar
.Get(0)->PutDouble(dVal
- ::rtl::math::approxFloor(dVal
));
2379 rPar
.Get(0)->PutDouble(dVal
- ::rtl::math::approxCeil(dVal
));
2382 void SbRtl_Round(StarBASIC
*, SbxArray
& rPar
, bool)
2384 sal_uInt32 nParCount
= rPar
.Count();
2385 if( nParCount
!= 2 && nParCount
!= 3 )
2387 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2391 SbxVariable
* pSbxVariable
= rPar
.Get(1);
2392 double dVal
= pSbxVariable
->GetDouble();
2396 sal_Int16 numdecimalplaces
= 0;
2397 if( nParCount
== 3 )
2399 numdecimalplaces
= rPar
.Get(2)->GetInteger();
2400 if( numdecimalplaces
< 0 || numdecimalplaces
> 22 )
2402 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2407 dRes
= rtl_math_round(dVal
, numdecimalplaces
, rtl_math_RoundingMode_HalfEven
);
2409 rPar
.Get(0)->PutDouble(dRes
);
2412 static void CallFunctionAccessFunction( const Sequence
< Any
>& aArgs
, const OUString
& sFuncName
, SbxVariable
* pRet
)
2414 static Reference
< XFunctionAccess
> xFunc
;
2419 Reference
< XMultiServiceFactory
> xFactory( getProcessServiceFactory() );
2422 xFunc
.set( xFactory
->createInstance("com.sun.star.sheet.FunctionAccess"), UNO_QUERY_THROW
);
2425 Any aRet
= xFunc
->callFunction( sFuncName
, aArgs
);
2427 unoToSbxValue( pRet
, aRet
);
2430 catch(const Exception
& )
2432 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2436 void SbRtl_SYD(StarBASIC
*, SbxArray
& rPar
, bool)
2438 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2440 if ( nArgCount
< 4 )
2442 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2446 // retrieve non-optional params
2448 Sequence
< Any
> aParams
2450 makeAny(rPar
.Get(1)->GetDouble()),
2451 makeAny(rPar
.Get(2)->GetDouble()),
2452 makeAny(rPar
.Get(3)->GetDouble()),
2453 makeAny(rPar
.Get(4)->GetDouble())
2456 CallFunctionAccessFunction(aParams
, "SYD", rPar
.Get(0));
2459 void SbRtl_SLN(StarBASIC
*, SbxArray
& rPar
, bool)
2461 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2463 if ( nArgCount
< 3 )
2465 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2469 // retrieve non-optional params
2471 Sequence
< Any
> aParams
2473 makeAny(rPar
.Get(1)->GetDouble()),
2474 makeAny(rPar
.Get(2)->GetDouble()),
2475 makeAny(rPar
.Get(3)->GetDouble())
2478 CallFunctionAccessFunction(aParams
, "SLN", rPar
.Get(0));
2481 void SbRtl_Pmt(StarBASIC
*, SbxArray
& rPar
, bool)
2483 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2485 if ( nArgCount
< 3 || nArgCount
> 5 )
2487 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2490 // retrieve non-optional params
2492 double rate
= rPar
.Get(1)->GetDouble();
2493 double nper
= rPar
.Get(2)->GetDouble();
2494 double pmt
= rPar
.Get(3)->GetDouble();
2496 // set default values for Optional args
2501 if ( nArgCount
>= 4 )
2503 if (rPar
.Get(4)->GetType() != SbxEMPTY
)
2504 fv
= rPar
.Get(4)->GetDouble();
2507 if ( nArgCount
>= 5 )
2509 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2510 type
= rPar
.Get(5)->GetDouble();
2513 Sequence
< Any
> aParams
2522 CallFunctionAccessFunction(aParams
, "Pmt", rPar
.Get(0));
2525 void SbRtl_PPmt(StarBASIC
*, SbxArray
& rPar
, bool)
2527 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2529 if ( nArgCount
< 4 || nArgCount
> 6 )
2531 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2534 // retrieve non-optional params
2536 double rate
= rPar
.Get(1)->GetDouble();
2537 double per
= rPar
.Get(2)->GetDouble();
2538 double nper
= rPar
.Get(3)->GetDouble();
2539 double pv
= rPar
.Get(4)->GetDouble();
2541 // set default values for Optional args
2546 if ( nArgCount
>= 5 )
2548 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2549 fv
= rPar
.Get(5)->GetDouble();
2552 if ( nArgCount
>= 6 )
2554 if (rPar
.Get(6)->GetType() != SbxEMPTY
)
2555 type
= rPar
.Get(6)->GetDouble();
2558 Sequence
< Any
> aParams
2568 CallFunctionAccessFunction(aParams
, "PPmt", rPar
.Get(0));
2571 void SbRtl_PV(StarBASIC
*, SbxArray
& rPar
, bool)
2573 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2575 if ( nArgCount
< 3 || nArgCount
> 5 )
2577 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2580 // retrieve non-optional params
2582 double rate
= rPar
.Get(1)->GetDouble();
2583 double nper
= rPar
.Get(2)->GetDouble();
2584 double pmt
= rPar
.Get(3)->GetDouble();
2586 // set default values for Optional args
2591 if ( nArgCount
>= 4 )
2593 if (rPar
.Get(4)->GetType() != SbxEMPTY
)
2594 fv
= rPar
.Get(4)->GetDouble();
2597 if ( nArgCount
>= 5 )
2599 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2600 type
= rPar
.Get(5)->GetDouble();
2603 Sequence
< Any
> aParams
2612 CallFunctionAccessFunction(aParams
, "PV", rPar
.Get(0));
2615 void SbRtl_NPV(StarBASIC
*, SbxArray
& rPar
, bool)
2617 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2619 if ( nArgCount
< 1 || nArgCount
> 2 )
2621 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2625 Any aValues
= sbxToUnoValue(rPar
.Get(2),
2626 cppu::UnoType
<Sequence
<double>>::get() );
2628 // convert for calc functions
2629 Sequence
< Sequence
< double > > sValues(1);
2630 aValues
>>= sValues
.getArray()[ 0 ];
2631 aValues
<<= sValues
;
2633 Sequence
< Any
> aParams
2635 makeAny(rPar
.Get(1)->GetDouble()),
2639 CallFunctionAccessFunction(aParams
, "NPV", rPar
.Get(0));
2642 void SbRtl_NPer(StarBASIC
*, SbxArray
& rPar
, bool)
2644 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2646 if ( nArgCount
< 3 || nArgCount
> 5 )
2648 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2651 // retrieve non-optional params
2653 double rate
= rPar
.Get(1)->GetDouble();
2654 double pmt
= rPar
.Get(2)->GetDouble();
2655 double pv
= rPar
.Get(3)->GetDouble();
2657 // set default values for Optional args
2662 if ( nArgCount
>= 4 )
2664 if (rPar
.Get(4)->GetType() != SbxEMPTY
)
2665 fv
= rPar
.Get(4)->GetDouble();
2668 if ( nArgCount
>= 5 )
2670 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2671 type
= rPar
.Get(5)->GetDouble();
2674 Sequence
< Any
> aParams
2683 CallFunctionAccessFunction(aParams
, "NPer", rPar
.Get(0));
2686 void SbRtl_MIRR(StarBASIC
*, SbxArray
& rPar
, bool)
2688 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2690 if ( nArgCount
< 3 )
2692 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2696 // retrieve non-optional params
2698 Any aValues
= sbxToUnoValue(rPar
.Get(1),
2699 cppu::UnoType
<Sequence
<double>>::get() );
2701 // convert for calc functions
2702 Sequence
< Sequence
< double > > sValues(1);
2703 aValues
>>= sValues
.getArray()[ 0 ];
2704 aValues
<<= sValues
;
2706 Sequence
< Any
> aParams
2709 makeAny(rPar
.Get(2)->GetDouble()),
2710 makeAny(rPar
.Get(3)->GetDouble())
2713 CallFunctionAccessFunction(aParams
, "MIRR", rPar
.Get(0));
2716 void SbRtl_IRR(StarBASIC
*, SbxArray
& rPar
, bool)
2718 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2720 if ( nArgCount
< 1 || nArgCount
> 2 )
2722 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2725 // retrieve non-optional params
2726 Any aValues
= sbxToUnoValue(rPar
.Get(1),
2727 cppu::UnoType
<Sequence
<double>>::get() );
2729 // convert for calc functions
2730 Sequence
< Sequence
< double > > sValues(1);
2731 aValues
>>= sValues
.getArray()[ 0 ];
2732 aValues
<<= sValues
;
2734 // set default values for Optional args
2737 if ( nArgCount
>= 2 )
2739 if (rPar
.Get(2)->GetType() != SbxEMPTY
)
2740 guess
= rPar
.Get(2)->GetDouble();
2743 Sequence
< Any
> aParams
2749 CallFunctionAccessFunction(aParams
, "IRR", rPar
.Get(0));
2752 void SbRtl_IPmt(StarBASIC
*, SbxArray
& rPar
, bool)
2754 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2756 if ( nArgCount
< 4 || nArgCount
> 6 )
2758 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2761 // retrieve non-optional params
2763 double rate
= rPar
.Get(1)->GetDouble();
2764 double per
= rPar
.Get(2)->GetInteger();
2765 double nper
= rPar
.Get(3)->GetDouble();
2766 double pv
= rPar
.Get(4)->GetDouble();
2768 // set default values for Optional args
2773 if ( nArgCount
>= 5 )
2775 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2776 fv
= rPar
.Get(5)->GetDouble();
2779 if ( nArgCount
>= 6 )
2781 if (rPar
.Get(6)->GetType() != SbxEMPTY
)
2782 type
= rPar
.Get(6)->GetDouble();
2785 Sequence
< Any
> aParams
2795 CallFunctionAccessFunction(aParams
, "IPmt", rPar
.Get(0));
2798 void SbRtl_FV(StarBASIC
*, SbxArray
& rPar
, bool)
2800 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2802 if ( nArgCount
< 3 || nArgCount
> 5 )
2804 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2807 // retrieve non-optional params
2809 double rate
= rPar
.Get(1)->GetDouble();
2810 double nper
= rPar
.Get(2)->GetDouble();
2811 double pmt
= rPar
.Get(3)->GetDouble();
2813 // set default values for Optional args
2818 if ( nArgCount
>= 4 )
2820 if (rPar
.Get(4)->GetType() != SbxEMPTY
)
2821 pv
= rPar
.Get(4)->GetDouble();
2824 if ( nArgCount
>= 5 )
2826 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2827 type
= rPar
.Get(5)->GetDouble();
2830 Sequence
< Any
> aParams
2839 CallFunctionAccessFunction(aParams
, "FV", rPar
.Get(0));
2842 void SbRtl_DDB(StarBASIC
*, SbxArray
& rPar
, bool)
2844 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2846 if ( nArgCount
< 4 || nArgCount
> 5 )
2848 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2851 // retrieve non-optional params
2853 double cost
= rPar
.Get(1)->GetDouble();
2854 double salvage
= rPar
.Get(2)->GetDouble();
2855 double life
= rPar
.Get(3)->GetDouble();
2856 double period
= rPar
.Get(4)->GetDouble();
2858 // set default values for Optional args
2862 if ( nArgCount
>= 5 )
2864 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2865 factor
= rPar
.Get(5)->GetDouble();
2868 Sequence
< Any
> aParams
2877 CallFunctionAccessFunction(aParams
, "DDB", rPar
.Get(0));
2880 void SbRtl_Rate(StarBASIC
*, SbxArray
& rPar
, bool)
2882 sal_uInt32 nArgCount
= rPar
.Count() - 1;
2884 if ( nArgCount
< 3 || nArgCount
> 6 )
2886 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2889 // retrieve non-optional params
2895 nper
= rPar
.Get(1)->GetDouble();
2896 pmt
= rPar
.Get(2)->GetDouble();
2897 pv
= rPar
.Get(3)->GetDouble();
2899 // set default values for Optional args
2905 if ( nArgCount
>= 4 )
2907 if (rPar
.Get(4)->GetType() != SbxEMPTY
)
2908 fv
= rPar
.Get(4)->GetDouble();
2912 if ( nArgCount
>= 5 )
2914 if (rPar
.Get(5)->GetType() != SbxEMPTY
)
2915 type
= rPar
.Get(5)->GetDouble();
2919 if ( nArgCount
>= 6 )
2921 if (rPar
.Get(6)->GetType() != SbxEMPTY
)
2922 guess
= rPar
.Get(6)->GetDouble();
2925 Sequence
< Any
> aParams
2935 CallFunctionAccessFunction(aParams
, "Rate", rPar
.Get(0));
2938 void SbRtl_StrReverse(StarBASIC
*, SbxArray
& rPar
, bool)
2940 if (rPar
.Count() != 2)
2942 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2946 SbxVariable
* pSbxVariable
= rPar
.Get(1);
2947 if( pSbxVariable
->IsNull() )
2949 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2953 OUString aStr
= comphelper::string::reverseString(pSbxVariable
->GetOUString());
2954 rPar
.Get(0)->PutString(aStr
);
2957 void SbRtl_CompatibilityMode(StarBASIC
*, SbxArray
& rPar
, bool)
2959 bool bEnabled
= false;
2960 sal_uInt32 nCount
= rPar
.Count();
2961 if ( nCount
!= 1 && nCount
!= 2 )
2962 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2964 SbiInstance
* pInst
= GetSbData()->pInst
;
2969 pInst
->EnableCompatibility(rPar
.Get(1)->GetBool());
2971 bEnabled
= pInst
->IsCompatibility();
2973 rPar
.Get(0)->PutBool(bEnabled
);
2976 bool LibreOffice6FloatingPointMode()
2978 static bool bMode
= std::getenv("LIBREOFFICE6FLOATINGPOINTMODE") != nullptr;
2980 return bMode
|| officecfg::Office::Scripting::Basic::Compatibility::UseLibreOffice6FloatingPointConversion::get();
2983 void SbRtl_Input(StarBASIC
*, SbxArray
& rPar
, bool)
2985 // 2 parameters needed
2986 if (rPar
.Count() < 3)
2988 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2992 sal_uInt16 nByteCount
= rPar
.Get(1)->GetUShort();
2993 sal_Int16 nFileNumber
= rPar
.Get(2)->GetInteger();
2995 SbiIoSystem
* pIosys
= GetSbData()->pInst
->GetIoSystem();
2996 SbiStream
* pSbStrm
= pIosys
->GetStream( nFileNumber
);
2997 if ( !pSbStrm
|| !(pSbStrm
->GetMode() & (SbiStreamFlags::Binary
| SbiStreamFlags::Input
)) )
2999 StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL
);
3003 OString aByteBuffer
;
3004 ErrCode err
= pSbStrm
->Read( aByteBuffer
, nByteCount
, true );
3006 err
= pIosys
->GetError();
3010 StarBASIC::Error( err
);
3013 rPar
.Get(0)->PutString(OStringToOUString(aByteBuffer
, osl_getThreadTextEncoding()));
3016 void SbRtl_Me(StarBASIC
*, SbxArray
& rPar
, bool)
3018 SbModule
* pActiveModule
= GetSbData()->pInst
->GetActiveModule();
3019 SbClassModuleObject
* pClassModuleObject
= dynamic_cast<SbClassModuleObject
*>( pActiveModule
);
3020 SbxVariableRef refVar
= rPar
.Get(0);
3021 if( pClassModuleObject
== nullptr )
3023 SbObjModule
* pMod
= dynamic_cast<SbObjModule
*>( pActiveModule
);
3025 refVar
->PutObject( pMod
);
3027 StarBASIC::Error( ERRCODE_BASIC_INVALID_USAGE_OBJECT
);
3030 refVar
->PutObject( pClassModuleObject
);
3035 sal_Int16
implGetWeekDay( double aDate
, bool bFirstDayParam
, sal_Int16 nFirstDay
)
3037 Date
aRefDate( 1,1,1900 );
3038 sal_Int32 nDays
= static_cast<sal_Int32
>(aDate
);
3039 nDays
-= 2; // normalize: 1.1.1900 => 0
3040 aRefDate
.AddDays( nDays
);
3041 DayOfWeek aDay
= aRefDate
.GetDayOfWeek();
3043 if ( aDay
!= SUNDAY
)
3044 nDay
= static_cast<sal_Int16
>(aDay
) + 2;
3046 nDay
= 1; // 1 == Sunday
3048 // #117253 optional 2nd parameter "firstdayofweek"
3049 if( bFirstDayParam
)
3051 if( nFirstDay
< 0 || nFirstDay
> 7 )
3053 #if HAVE_FEATURE_SCRIPTING
3054 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3058 if( nFirstDay
== 0 )
3060 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
3061 if( !xCalendar
.is() )
3063 #if HAVE_FEATURE_SCRIPTING
3064 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
3068 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
3070 nDay
= 1 + (nDay
+ 7 - nFirstDay
) % 7;
3075 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */