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 <comphelper/processfactory.hxx>
56 #include <comphelper/string.hxx>
58 #include <com/sun/star/uno/Sequence.hxx>
59 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
60 #include <com/sun/star/i18n/LocaleCalendar2.hpp>
61 #include <com/sun/star/sheet/XFunctionAccess.hpp>
64 using namespace comphelper
;
65 using namespace com::sun::star::i18n
;
66 using namespace com::sun::star::lang
;
67 using namespace com::sun::star::sheet
;
68 using namespace com::sun::star::uno
;
70 static Reference
< XCalendar4
> const & getLocaleCalendar()
72 static Reference
< XCalendar4
> xCalendar
= LocaleCalendar2::create(getProcessComponentContext());
73 static css::lang::Locale aLastLocale
;
74 static bool bNeedsInit
= true;
76 css::lang::Locale aLocale
= Application::GetSettings().GetLanguageTag().getLocale();
77 bool bNeedsReload
= false;
83 else if( aLocale
.Language
!= aLastLocale
.Language
||
84 aLocale
.Country
!= aLastLocale
.Country
||
85 aLocale
.Variant
!= aLastLocale
.Variant
)
91 aLastLocale
= aLocale
;
92 xCalendar
->loadDefaultCalendar( aLocale
);
97 #if HAVE_FEATURE_SCRIPTING
99 void SbRtl_CallByName(StarBASIC
*, SbxArray
& rPar
, bool)
101 const sal_Int16 vbGet
= 2;
102 const sal_Int16 vbLet
= 4;
103 const sal_Int16 vbMethod
= 1;
104 const sal_Int16 vbSet
= 8;
106 // At least 3 parameter needed plus function itself -> 4
107 sal_uInt32 nParCount
= rPar
.Count32();
110 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
114 // 1. parameter is object
115 SbxBase
* pObjVar
= rPar
.Get32(1)->GetObject();
116 SbxObject
* pObj
= nullptr;
118 pObj
= dynamic_cast<SbxObject
*>( pObjVar
);
120 if (auto pSbxVar
= dynamic_cast<const SbxVariable
*>( pObjVar
))
121 pObj
= dynamic_cast<SbxObject
*>( pSbxVar
->GetObject() );
124 StarBASIC::Error( ERRCODE_BASIC_BAD_PARAMETER
);
128 // 2. parameter is ProcedureName
129 OUString aNameStr
= rPar
.Get32(2)->GetOUString();
131 // 3. parameter is CallType
132 sal_Int16 nCallType
= rPar
.Get32(3)->GetInteger();
134 //SbxObject* pFindObj = NULL;
135 SbxVariable
* pFindVar
= pObj
->Find( aNameStr
, SbxClassType::DontCare
);
136 if( pFindVar
== nullptr )
138 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
147 aVals
.eType
= SbxVARIANT
;
148 pFindVar
->Get( aVals
);
150 SbxVariableRef refVar
= rPar
.Get32(0);
151 refVar
->Put( aVals
);
157 if ( nParCount
!= 5 )
159 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
162 SbxVariableRef pValVar
= rPar
.Get32(4);
163 if( nCallType
== vbLet
)
166 aVals
.eType
= SbxVARIANT
;
167 pValVar
->Get( aVals
);
168 pFindVar
->Put( aVals
);
172 SbxVariableRef rFindVar
= pFindVar
;
173 SbiInstance
* pInst
= GetSbData()->pInst
;
174 SbiRuntime
* pRT
= pInst
? pInst
->pRun
: nullptr;
177 pRT
->StepSET_Impl( pValVar
, rFindVar
);
184 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pFindVar
);
185 if( pMeth
== nullptr )
187 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
193 sal_uInt32 nMethParamCount
= nParCount
- 4;
194 if( nMethParamCount
> 0 )
196 xArray
= new SbxArray
;
197 for( sal_uInt32 i
= 0 ; i
< nMethParamCount
; i
++ )
199 SbxVariable
* pPar
= rPar
.Get32( i
+ 4 );
200 xArray
->Put32( pPar
, i
+ 1 );
205 SbxVariableRef refVar
= rPar
.Get32(0);
207 pMeth
->SetParameters( xArray
.get() );
208 pMeth
->Call( refVar
.get() );
209 pMeth
->SetParameters( nullptr );
213 StarBASIC::Error( ERRCODE_BASIC_PROC_UNDEFINED
);
217 void SbRtl_CBool(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
220 if ( rPar
.Count32() == 2 )
222 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
223 bVal
= pSbxVariable
->GetBool();
227 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
229 rPar
.Get32(0)->PutBool(bVal
);
232 void SbRtl_CByte(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
235 if ( rPar
.Count32() == 2 )
237 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
238 nByte
= pSbxVariable
->GetByte();
242 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
244 rPar
.Get32(0)->PutByte(nByte
);
247 void SbRtl_CCur(StarBASIC
*, SbxArray
& rPar
, bool)
250 if ( rPar
.Count32() == 2 )
252 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
253 nCur
= pSbxVariable
->GetCurrency();
257 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
259 rPar
.Get32(0)->PutCurrency( nCur
);
262 void SbRtl_CDec(StarBASIC
* pBasic
, SbxArray
& rPar
, bool bWrite
)
268 SbxDecimal
* pDec
= nullptr;
269 if ( rPar
.Count32() == 2 )
271 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
272 pDec
= pSbxVariable
->GetDecimal();
276 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
278 rPar
.Get32(0)->PutDecimal( pDec
);
280 rPar
.Get32(0)->PutEmpty();
281 StarBASIC::Error(ERRCODE_BASIC_NOT_IMPLEMENTED
);
285 void SbRtl_CDate(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
288 if ( rPar
.Count32() == 2 )
290 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
291 nVal
= pSbxVariable
->GetDate();
295 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
297 rPar
.Get32(0)->PutDate(nVal
);
300 void SbRtl_CDbl(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
303 if ( rPar
.Count32() == 2 )
305 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
306 if( pSbxVariable
->GetType() == SbxSTRING
)
309 OUString aScanStr
= pSbxVariable
->GetOUString();
310 ErrCode Error
= SbxValue::ScanNumIntnl( aScanStr
, nVal
);
311 if( Error
!= ERRCODE_NONE
)
313 StarBASIC::Error( Error
);
318 nVal
= pSbxVariable
->GetDouble();
323 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
326 rPar
.Get32(0)->PutDouble(nVal
);
329 void SbRtl_CInt(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
332 if ( rPar
.Count32() == 2 )
334 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
335 nVal
= pSbxVariable
->GetInteger();
339 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
341 rPar
.Get32(0)->PutInteger(nVal
);
344 void SbRtl_CLng(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
347 if ( rPar
.Count32() == 2 )
349 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
350 nVal
= pSbxVariable
->GetLong();
354 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
356 rPar
.Get32(0)->PutLong(nVal
);
359 void SbRtl_CSng(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
361 float nVal
= float(0.0);
362 if ( rPar
.Count32() == 2 )
364 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
365 if( pSbxVariable
->GetType() == SbxSTRING
)
369 OUString aScanStr
= pSbxVariable
->GetOUString();
370 ErrCode Error
= SbxValue::ScanNumIntnl( aScanStr
, dVal
, /*bSingle=*/true );
371 if( SbxBase::GetError() == ERRCODE_NONE
&& Error
!= ERRCODE_NONE
)
373 StarBASIC::Error( Error
);
375 nVal
= static_cast<float>(dVal
);
379 nVal
= pSbxVariable
->GetSingle();
384 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
386 rPar
.Get32(0)->PutSingle(nVal
);
389 void SbRtl_CStr(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
392 if ( rPar
.Count32() == 2 )
394 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
395 aString
= pSbxVariable
->GetOUString();
399 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
401 rPar
.Get32(0)->PutString(aString
);
404 void SbRtl_CVar(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
406 SbxValues
aVals( SbxVARIANT
);
407 if ( rPar
.Count32() == 2 )
409 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
410 pSbxVariable
->Get( aVals
);
414 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
416 rPar
.Get32(0)->Put( aVals
);
419 void SbRtl_CVErr(StarBASIC
*, SbxArray
& rPar
, bool)
421 sal_Int16 nErrCode
= 0;
422 if ( rPar
.Count32() == 2 )
424 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
425 nErrCode
= pSbxVariable
->GetInteger();
429 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
431 rPar
.Get32(0)->PutErr( nErrCode
);
434 void SbRtl_Iif(StarBASIC
*, SbxArray
& rPar
, bool) // JSM
436 if ( rPar
.Count32() == 4 )
438 if (rPar
.Get32(1)->GetBool())
440 *rPar
.Get32(0) = *rPar
.Get32(2);
444 *rPar
.Get32(0) = *rPar
.Get32(3);
449 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
453 void SbRtl_GetSystemType(StarBASIC
*, SbxArray
& rPar
, bool)
455 if ( rPar
.Count32() != 1 )
457 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
461 // Removed for SRC595
462 rPar
.Get32(0)->PutInteger( -1 );
466 void SbRtl_GetGUIType(StarBASIC
* pBasic
, SbxArray
& rPar
, bool bWrite
)
471 if ( rPar
.Count32() != 1 )
473 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
477 // 17.7.2000 Make simple solution for testtool / fat office
479 rPar
.Get32(0)->PutInteger( 1 );
481 rPar
.Get32(0)->PutInteger( 4 );
483 rPar
.Get32(0)->PutInteger( -1 );
488 void SbRtl_Red(StarBASIC
*, SbxArray
& rPar
, bool)
490 if ( rPar
.Count32() != 2 )
492 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
496 sal_Int32 nRGB
= rPar
.Get32(1)->GetLong();
499 rPar
.Get32(0)->PutInteger( static_cast<sal_Int16
>(nRGB
) );
503 void SbRtl_Green(StarBASIC
*, SbxArray
& rPar
, bool)
505 if ( rPar
.Count32() != 2 )
507 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
511 sal_Int32 nRGB
= rPar
.Get32(1)->GetLong();
514 rPar
.Get32(0)->PutInteger( static_cast<sal_Int16
>(nRGB
) );
518 void SbRtl_Blue(StarBASIC
*, SbxArray
& rPar
, bool)
520 if ( rPar
.Count32() != 2 )
522 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
526 sal_Int32 nRGB
= rPar
.Get32(1)->GetLong();
528 rPar
.Get32(0)->PutInteger( static_cast<sal_Int16
>(nRGB
) );
533 void SbRtl_Switch(StarBASIC
*, SbxArray
& rPar
, bool)
535 sal_uInt32 nCount
= rPar
.Count32();
536 if( !(nCount
& 0x0001 ))
538 // number of arguments must be odd
539 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
541 sal_uInt32 nCurExpr
= 1;
542 while( nCurExpr
< (nCount
-1) )
544 if( rPar
.Get32( nCurExpr
)->GetBool())
546 (*rPar
.Get32(0)) = *(rPar
.Get32(nCurExpr
+1));
551 rPar
.Get32(0)->PutNull();
554 //i#64882# Common wait impl for existing Wait and new WaitUntil
556 void Wait_Impl( bool bDurationBased
, SbxArray
& rPar
)
558 if( rPar
.Count32() != 2 )
560 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
563 tools::Long nWait
= 0;
564 if ( bDurationBased
)
566 double dWait
= rPar
.Get32(1)->GetDouble();
567 double dNow
= Now_Impl();
568 double dSecs
= ( dWait
- dNow
) * 24.0 * 3600.0;
569 nWait
= static_cast<tools::Long
>( dSecs
* 1000 ); // wait in thousands of sec
573 nWait
= rPar
.Get32(1)->GetLong();
577 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
582 aTimer
.SetTimeout( nWait
);
584 while ( aTimer
.IsActive() )
586 Application::Yield();
591 void SbRtl_Wait(StarBASIC
*, SbxArray
& rPar
, bool)
593 Wait_Impl( false, rPar
);
596 //i#64882# add new WaitUntil ( for application.wait )
597 // share wait_impl with 'normal' oobasic wait
598 void SbRtl_WaitUntil(StarBASIC
*, SbxArray
& rPar
, bool)
600 Wait_Impl( true, rPar
);
603 void SbRtl_DoEvents(StarBASIC
*, SbxArray
& rPar
, bool)
605 // don't understand what upstream are up to
606 // we already process application events etc. in between
607 // basic runtime pcode ( on a timed basis )
609 rPar
.Get32(0)->PutInteger( 0 );
610 Application::Reschedule( true );
613 void SbRtl_GetGUIVersion(StarBASIC
*, SbxArray
& rPar
, bool)
615 if ( rPar
.Count32() != 1 )
617 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
621 // Removed for SRC595
622 rPar
.Get32(0)->PutLong( -1 );
626 void SbRtl_Choose(StarBASIC
*, SbxArray
& rPar
, bool)
628 if ( rPar
.Count32() < 2 )
630 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
632 sal_Int16 nIndex
= rPar
.Get32(1)->GetInteger();
633 sal_uInt32 nCount
= rPar
.Count32();
635 if( nCount
== 1 || nIndex
> sal::static_int_cast
<sal_Int16
>(nCount
-1) || nIndex
< 1 )
637 rPar
.Get32(0)->PutNull();
640 (*rPar
.Get32(0)) = *(rPar
.Get32(nIndex
+1));
644 void SbRtl_Trim(StarBASIC
*, SbxArray
& rPar
, bool)
646 if ( rPar
.Count32() < 2 )
648 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
652 OUString
aStr(comphelper::string::strip(rPar
.Get32(1)->GetOUString(), ' '));
653 rPar
.Get32(0)->PutString(aStr
);
657 void SbRtl_GetSolarVersion(StarBASIC
*, SbxArray
& rPar
, bool)
659 rPar
.Get32(0)->PutLong( LIBO_VERSION_MAJOR
* 10000 + LIBO_VERSION_MINOR
* 100 + LIBO_VERSION_MICRO
* 1);
662 void SbRtl_TwipsPerPixelX(StarBASIC
*, SbxArray
& rPar
, bool)
664 sal_Int32 nResult
= 0;
666 MapMode
aMap( MapUnit::MapTwip
);
667 OutputDevice
* pDevice
= Application::GetDefaultDevice();
670 aSize
= pDevice
->PixelToLogic( aSize
, aMap
);
671 nResult
= aSize
.Width() / 100;
673 rPar
.Get32(0)->PutLong( nResult
);
676 void SbRtl_TwipsPerPixelY(StarBASIC
*, SbxArray
& rPar
, bool)
678 sal_Int32 nResult
= 0;
680 MapMode
aMap( MapUnit::MapTwip
);
681 OutputDevice
* pDevice
= Application::GetDefaultDevice();
684 aSize
= pDevice
->PixelToLogic( aSize
, aMap
);
685 nResult
= aSize
.Height() / 100;
687 rPar
.Get32(0)->PutLong( nResult
);
691 void SbRtl_FreeLibrary(StarBASIC
*, SbxArray
& rPar
, bool)
693 if ( rPar
.Count32() != 2 )
695 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
697 GetSbData()->pInst
->GetDllMgr()->FreeDll( rPar
.Get32(1)->GetOUString() );
699 bool IsBaseIndexOne()
701 bool bResult
= false;
702 if ( GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
704 sal_uInt16 res
= GetSbData()->pInst
->pRun
->GetBase();
713 void SbRtl_Array(StarBASIC
*, SbxArray
& rPar
, bool)
715 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
716 sal_uInt32 nArraySize
= rPar
.Count32() - 1;
717 bool bIncIndex
= IsBaseIndexOne();
722 pArray
->AddDim32( 1, sal::static_int_cast
<sal_Int32
>(nArraySize
) );
726 pArray
->AddDim32( 0, sal::static_int_cast
<sal_Int32
>(nArraySize
) - 1 );
731 pArray
->unoAddDim32( 0, -1 );
734 // insert parameters into the array
735 for( sal_uInt32 i
= 0 ; i
< nArraySize
; i
++ )
737 SbxVariable
* pVar
= rPar
.Get32(i
+1);
738 SbxVariable
* pNew
= new SbxEnsureParentVariable(*pVar
);
739 pNew
->SetFlag( SbxFlagBits::Write
);
741 aIdx
[0] = static_cast<sal_Int32
>(i
);
746 pArray
->Put32(pNew
, aIdx
);
750 SbxVariableRef refVar
= rPar
.Get32(0);
751 SbxFlagBits nFlags
= refVar
->GetFlags();
752 refVar
->ResetFlag( SbxFlagBits::Fixed
);
753 refVar
->PutObject( pArray
);
754 refVar
->SetFlags( nFlags
);
755 refVar
->SetParameters( nullptr );
759 // Featurewish #57868
760 // The function returns a variant-array; if there are no parameters passed,
761 // an empty array is created (according to dim a(); equal to a sequence of
762 // the length 0 in Uno).
763 // If there are parameters passed, there's a dimension created for each of
764 // them; DimArray( 2, 2, 4 ) is equal to DIM a( 2, 2, 4 )
765 // the array is always of the type variant
766 void SbRtl_DimArray(StarBASIC
*, SbxArray
& rPar
, bool)
768 SbxDimArray
* pArray
= new SbxDimArray( SbxVARIANT
);
769 sal_uInt32 nArrayDims
= rPar
.Count32() - 1;
772 for( sal_uInt32 i
= 0; i
< nArrayDims
; i
++ )
774 sal_Int32 ub
= rPar
.Get32(i
+1)->GetLong();
777 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
780 pArray
->AddDim32( 0, ub
);
785 pArray
->unoAddDim32( 0, -1 );
787 SbxVariableRef refVar
= rPar
.Get32(0);
788 SbxFlagBits nFlags
= refVar
->GetFlags();
789 refVar
->ResetFlag( SbxFlagBits::Fixed
);
790 refVar
->PutObject( pArray
);
791 refVar
->SetFlags( nFlags
);
792 refVar
->SetParameters( nullptr );
796 * FindObject and FindPropertyObject make it possible to
797 * address objects and properties of the type Object with
798 * their name as string-parameters at the runtime.
801 * MyObj.Prop1.Bla = 5
804 * dim ObjVar as Object
805 * dim ObjProp as Object
807 * ObjVar = FindObject( ObjName$ )
808 * PropName$ = "Prop1"
809 * ObjProp = FindPropertyObject( ObjVar, PropName$ )
812 * The names can be created dynamically at the runtime
813 * so that e. g. via controls "TextEdit1" to "TextEdit5"
814 * can be iterated in a dialog in a loop.
818 // 1st parameter = the object's name as string
819 void SbRtl_FindObject(StarBASIC
*, SbxArray
& rPar
, bool)
821 if ( rPar
.Count32() < 2 )
823 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
827 OUString aNameStr
= rPar
.Get32(1)->GetOUString();
829 SbxBase
* pFind
= StarBASIC::FindSBXInCurrentScope( aNameStr
);
830 SbxObject
* pFindObj
= nullptr;
833 pFindObj
= dynamic_cast<SbxObject
*>( pFind
);
835 SbxVariableRef refVar
= rPar
.Get32(0);
836 refVar
->PutObject( pFindObj
);
839 // address object-property in an object
840 // 1st parameter = object
841 // 2nd parameter = the property's name as string
842 void SbRtl_FindPropertyObject(StarBASIC
*, SbxArray
& rPar
, bool)
844 if ( rPar
.Count32() < 3 )
846 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
850 SbxBase
* pObjVar
= rPar
.Get32(1)->GetObject();
851 SbxObject
* pObj
= nullptr;
854 pObj
= dynamic_cast<SbxObject
*>( pObjVar
);
857 if (auto pSbxVar
= dynamic_cast<const SbxVariable
*>( pObjVar
))
858 pObj
= dynamic_cast<SbxObject
*>( pSbxVar
->GetObject() );
860 OUString aNameStr
= rPar
.Get32(2)->GetOUString();
862 SbxObject
* pFindObj
= nullptr;
865 SbxVariable
* pFindVar
= pObj
->Find( aNameStr
, SbxClassType::Object
);
866 pFindObj
= dynamic_cast<SbxObject
*>( pFindVar
);
870 StarBASIC::Error( ERRCODE_BASIC_BAD_PARAMETER
);
873 SbxVariableRef refVar
= rPar
.Get32(0);
874 refVar
->PutObject( pFindObj
);
878 static bool lcl_WriteSbxVariable( const SbxVariable
& rVar
, SvStream
* pStrm
,
879 bool bBinary
, short nBlockLen
, bool bIsArray
)
881 sal_uInt64
const nFPos
= pStrm
->Tell();
883 bool bIsVariant
= !rVar
.IsFixed();
884 SbxDataType eType
= rVar
.GetType();
893 pStrm
->WriteUInt16( SbxBYTE
); // VarType Id
895 pStrm
->WriteUChar( rVar
.GetByte() );
907 pStrm
->WriteUInt16( SbxINTEGER
); // VarType Id
909 pStrm
->WriteInt16( rVar
.GetInteger() );
916 pStrm
->WriteUInt16( SbxLONG
); // VarType Id
918 pStrm
->WriteInt32( rVar
.GetLong() );
924 pStrm
->WriteUInt16( SbxSALINT64
); // VarType Id
926 pStrm
->WriteUInt64( rVar
.GetInt64() );
931 pStrm
->WriteUInt16( eType
); // VarType Id
933 pStrm
->WriteFloat( rVar
.GetSingle() );
941 pStrm
->WriteUInt16( eType
); // VarType Id
943 pStrm
->WriteDouble( rVar
.GetDouble() );
949 const OUString
& rStr
= rVar
.GetOUString();
950 if( !bBinary
|| bIsArray
)
954 pStrm
->WriteUInt16( SbxSTRING
);
956 pStrm
->WriteUniOrByteString( rStr
, osl_getThreadTextEncoding() );
960 // without any length information! without end-identifier!
961 // What does that mean for Unicode?! Choosing conversion to ByteString...
962 OString
aByteStr(OUStringToOString(rStr
, osl_getThreadTextEncoding()));
963 pStrm
->WriteOString( aByteStr
);
969 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
975 pStrm
->Seek( nFPos
+ nBlockLen
);
977 return pStrm
->GetErrorCode() == ERRCODE_NONE
;
980 static bool lcl_ReadSbxVariable( SbxVariable
& rVar
, SvStream
* pStrm
,
981 bool bBinary
, short nBlockLen
)
985 sal_uInt64
const nFPos
= pStrm
->Tell();
987 bool bIsVariant
= !rVar
.IsFixed();
988 SbxDataType eVarType
= rVar
.GetType();
990 SbxDataType eSrcType
= eVarType
;
994 pStrm
->ReadUInt16( nTemp
);
995 eSrcType
= static_cast<SbxDataType
>(nTemp
);
1005 pStrm
->ReadUChar( aByte
);
1007 if( bBinary
&& SbiRuntime::isVBAEnabled() && aByte
== 1 && pStrm
->eof() )
1011 rVar
.PutByte( aByte
);
1024 pStrm
->ReadInt16( aInt
);
1025 rVar
.PutInteger( aInt
);
1033 pStrm
->ReadInt32( aInt
);
1034 rVar
.PutLong( aInt
);
1041 pStrm
->ReadUInt32( aInt
);
1042 rVar
.PutInt64( static_cast<sal_Int64
>(aInt
) );
1048 pStrm
->ReadFloat( nS
);
1049 rVar
.PutSingle( nS
);
1056 pStrm
->ReadDouble( aDouble
);
1057 rVar
.PutDouble( aDouble
);
1063 pStrm
->ReadDouble( aDouble
);
1064 rVar
.PutDate( aDouble
);
1071 OUString aStr
= pStrm
->ReadUniOrByteString(osl_getThreadTextEncoding());
1072 rVar
.PutString( aStr
);
1077 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1083 pStrm
->Seek( nFPos
+ nBlockLen
);
1085 return pStrm
->GetErrorCode() == ERRCODE_NONE
;
1090 static bool lcl_WriteReadSbxArray( SbxDimArray
& rArr
, SvStream
* pStrm
,
1091 bool bBinary
, sal_Int32 nCurDim
, sal_Int32
* pOtherDims
, bool bWrite
)
1093 SAL_WARN_IF( nCurDim
<= 0,"basic", "Bad Dim");
1094 sal_Int32 nLower
, nUpper
;
1095 if( !rArr
.GetDim32( nCurDim
, nLower
, nUpper
) )
1097 for(sal_Int32 nCur
= nLower
; nCur
<= nUpper
; nCur
++ )
1099 pOtherDims
[ nCurDim
-1 ] = nCur
;
1101 lcl_WriteReadSbxArray(rArr
, pStrm
, bBinary
, nCurDim
-1, pOtherDims
, bWrite
);
1104 SbxVariable
* pVar
= rArr
.Get32( pOtherDims
);
1107 bRet
= lcl_WriteSbxVariable(*pVar
, pStrm
, bBinary
, 0, true );
1109 bRet
= lcl_ReadSbxVariable(*pVar
, pStrm
, bBinary
, 0 );
1117 static void PutGet( SbxArray
& rPar
, bool bPut
)
1119 if ( rPar
.Count32() != 4 )
1121 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1124 sal_Int16 nFileNo
= rPar
.Get32(1)->GetInteger();
1125 SbxVariable
* pVar2
= rPar
.Get32(2);
1126 SbxDataType eType2
= pVar2
->GetType();
1127 bool bHasRecordNo
= (eType2
!= SbxEMPTY
&& eType2
!= SbxERROR
);
1128 tools::Long nRecordNo
= pVar2
->GetLong();
1129 if ( nFileNo
< 1 || ( bHasRecordNo
&& nRecordNo
< 1 ) )
1131 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1135 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
1136 SbiStream
* pSbStrm
= pIO
->GetStream( nFileNo
);
1138 if ( !pSbStrm
|| !(pSbStrm
->GetMode() & (SbiStreamFlags::Binary
| SbiStreamFlags::Random
)) )
1140 StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL
);
1144 SvStream
* pStrm
= pSbStrm
->GetStrm();
1145 bool bRandom
= pSbStrm
->IsRandom();
1146 short nBlockLen
= bRandom
? pSbStrm
->GetBlockLen() : 0;
1150 pSbStrm
->ExpandFile();
1155 sal_uInt64
const nFilePos
= bRandom
1156 ? static_cast<sal_uInt64
>(nBlockLen
* nRecordNo
)
1157 : static_cast<sal_uInt64
>(nRecordNo
);
1158 pStrm
->Seek( nFilePos
);
1161 SbxDimArray
* pArr
= nullptr;
1162 SbxVariable
* pVar
= rPar
.Get32(3);
1163 if( pVar
->GetType() & SbxARRAY
)
1165 SbxBase
* pParObj
= pVar
->GetObject();
1166 pArr
= dynamic_cast<SbxDimArray
*>( pParObj
);
1173 sal_uInt64
const nFPos
= pStrm
->Tell();
1174 sal_Int32 nDims
= pArr
->GetDims32();
1175 std::unique_ptr
<sal_Int32
[]> pDims(new sal_Int32
[ nDims
]);
1176 bRet
= lcl_WriteReadSbxArray(*pArr
,pStrm
,!bRandom
,nDims
,pDims
.get(),bPut
);
1179 pStrm
->Seek( nFPos
+ nBlockLen
);
1184 bRet
= lcl_WriteSbxVariable(*pVar
, pStrm
, !bRandom
, nBlockLen
, false);
1186 bRet
= lcl_ReadSbxVariable(*pVar
, pStrm
, !bRandom
, nBlockLen
);
1188 if( !bRet
|| pStrm
->GetErrorCode() )
1189 StarBASIC::Error( ERRCODE_BASIC_IO_ERROR
);
1192 void SbRtl_Put(StarBASIC
*, SbxArray
& rPar
, bool)
1194 PutGet( rPar
, true );
1197 void SbRtl_Get(StarBASIC
*, SbxArray
& rPar
, bool)
1199 PutGet( rPar
, false );
1202 void SbRtl_Environ(StarBASIC
*, SbxArray
& rPar
, bool)
1204 if ( rPar
.Count32() != 2 )
1206 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1210 // should be ANSI but that's not possible under Win16 in the DLL
1211 OString
aByteStr(OUStringToOString(rPar
.Get32(1)->GetOUString(),
1212 osl_getThreadTextEncoding()));
1213 const char* pEnvStr
= getenv(aByteStr
.getStr());
1216 aResult
= OUString(pEnvStr
, strlen(pEnvStr
), osl_getThreadTextEncoding());
1218 rPar
.Get32(0)->PutString( aResult
);
1221 static double GetDialogZoomFactor( bool bX
, tools::Long nValue
)
1223 OutputDevice
* pDevice
= Application::GetDefaultDevice();
1227 Size
aRefSize( nValue
, nValue
);
1228 Fraction
aFracX( 1, 26 );
1229 Fraction
aFracY( 1, 24 );
1230 MapMode
aMap( MapUnit::MapAppFont
, Point(), aFracX
, aFracY
);
1231 Size aScaledSize
= pDevice
->LogicToPixel( aRefSize
, aMap
);
1232 aRefSize
= pDevice
->LogicToPixel( aRefSize
, MapMode(MapUnit::MapTwip
) );
1234 double nRef
, nScaled
;
1237 nRef
= aRefSize
.Width();
1238 nScaled
= aScaledSize
.Width();
1242 nRef
= aRefSize
.Height();
1243 nScaled
= aScaledSize
.Height();
1245 nResult
= nScaled
/ nRef
;
1251 void SbRtl_GetDialogZoomFactorX(StarBASIC
*, SbxArray
& rPar
, bool)
1253 if ( rPar
.Count32() != 2 )
1255 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1258 rPar
.Get32(0)->PutDouble( GetDialogZoomFactor( true, rPar
.Get32(1)->GetLong() ));
1261 void SbRtl_GetDialogZoomFactorY(StarBASIC
*, SbxArray
& rPar
, bool)
1263 if ( rPar
.Count32() != 2 )
1265 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1268 rPar
.Get32(0)->PutDouble( GetDialogZoomFactor( false, rPar
.Get32(1)->GetLong()));
1272 void SbRtl_EnableReschedule(StarBASIC
*, SbxArray
& rPar
, bool)
1274 rPar
.Get32(0)->PutEmpty();
1275 if ( rPar
.Count32() != 2 )
1276 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1277 if( GetSbData()->pInst
)
1278 GetSbData()->pInst
->EnableReschedule( rPar
.Get32(1)->GetBool() );
1281 void SbRtl_GetSystemTicks(StarBASIC
*, SbxArray
& rPar
, bool)
1283 if ( rPar
.Count32() != 1 )
1285 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1288 rPar
.Get32(0)->PutLong( tools::Time::GetSystemTicks() );
1291 void SbRtl_GetPathSeparator(StarBASIC
*, SbxArray
& rPar
, bool)
1293 if ( rPar
.Count32() != 1 )
1295 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1298 rPar
.Get32(0)->PutString( OUString( SAL_PATHDELIMITER
) );
1301 void SbRtl_ResolvePath(StarBASIC
*, SbxArray
& rPar
, bool)
1303 if ( rPar
.Count32() == 2 )
1305 OUString aStr
= rPar
.Get32(1)->GetOUString();
1306 rPar
.Get32(0)->PutString( aStr
);
1310 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1314 void SbRtl_TypeLen(StarBASIC
*, SbxArray
& rPar
, bool)
1316 if ( rPar
.Count32() != 2 )
1318 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1322 SbxDataType eType
= rPar
.Get32(1)->GetType();
1378 nLen
= static_cast<sal_Int16
>(rPar
.Get32(1)->GetOUString().getLength());
1385 rPar
.Get32(0)->PutInteger( nLen
);
1390 // 1st parameter == class name, other parameters for initialisation
1391 void SbRtl_CreateUnoStruct(StarBASIC
*, SbxArray
& rPar
, bool)
1393 RTL_Impl_CreateUnoStruct( rPar
);
1397 // 1st parameter == service-name
1398 void SbRtl_CreateUnoService(StarBASIC
*, SbxArray
& rPar
, bool)
1400 RTL_Impl_CreateUnoService( rPar
);
1403 void SbRtl_CreateUnoServiceWithArguments(StarBASIC
*, SbxArray
& rPar
, bool)
1405 RTL_Impl_CreateUnoServiceWithArguments( rPar
);
1409 void SbRtl_CreateUnoValue(StarBASIC
*, SbxArray
& rPar
, bool)
1411 RTL_Impl_CreateUnoValue( rPar
);
1416 void SbRtl_GetProcessServiceManager(StarBASIC
*, SbxArray
& rPar
, bool)
1418 RTL_Impl_GetProcessServiceManager( rPar
);
1422 // 1st parameter == Sequence<PropertyValue>
1423 void SbRtl_CreatePropertySet(StarBASIC
*, SbxArray
& rPar
, bool)
1425 RTL_Impl_CreatePropertySet( rPar
);
1429 // multiple interface-names as parameters
1430 void SbRtl_HasUnoInterfaces(StarBASIC
*, SbxArray
& rPar
, bool)
1432 RTL_Impl_HasInterfaces( rPar
);
1436 void SbRtl_IsUnoStruct(StarBASIC
*, SbxArray
& rPar
, bool)
1438 RTL_Impl_IsUnoStruct( rPar
);
1442 void SbRtl_EqualUnoObjects(StarBASIC
*, SbxArray
& rPar
, bool)
1444 RTL_Impl_EqualUnoObjects( rPar
);
1447 void SbRtl_CreateUnoDialog(StarBASIC
*, SbxArray
& rPar
, bool)
1449 RTL_Impl_CreateUnoDialog( rPar
);
1452 // Return the application standard lib as root scope
1453 void SbRtl_GlobalScope(StarBASIC
* pBasic
, SbxArray
& rPar
, bool)
1455 SbxObject
* p
= pBasic
;
1456 while( p
->GetParent() )
1460 SbxVariableRef refVar
= rPar
.Get32(0);
1461 refVar
->PutObject( p
);
1464 // Helper functions to convert Url from/to system paths
1465 void SbRtl_ConvertToUrl(StarBASIC
*, SbxArray
& rPar
, bool)
1467 if ( rPar
.Count32() == 2 )
1469 OUString aStr
= rPar
.Get32(1)->GetOUString();
1470 INetURLObject
aURLObj( aStr
, INetProtocol::File
);
1471 OUString aFileURL
= aURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1472 if( aFileURL
.isEmpty() )
1474 osl::File::getFileURLFromSystemPath(aStr
, aFileURL
);
1476 if( aFileURL
.isEmpty() )
1480 rPar
.Get32(0)->PutString(aFileURL
);
1484 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1488 void SbRtl_ConvertFromUrl(StarBASIC
*, SbxArray
& rPar
, bool)
1490 if ( rPar
.Count32() == 2 )
1492 OUString aStr
= rPar
.Get32(1)->GetOUString();
1494 ::osl::File::getSystemPathFromFileURL( aStr
, aSysPath
);
1495 if( aSysPath
.isEmpty() )
1499 rPar
.Get32(0)->PutString(aSysPath
);
1503 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1508 // Provide DefaultContext
1509 void SbRtl_GetDefaultContext(StarBASIC
*, SbxArray
& rPar
, bool)
1511 RTL_Impl_GetDefaultContext( rPar
);
1514 void SbRtl_Join(StarBASIC
*, SbxArray
& rPar
, bool)
1516 sal_uInt32 nParCount
= rPar
.Count32();
1517 if ( nParCount
!= 3 && nParCount
!= 2 )
1519 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1522 SbxBase
* pParObj
= rPar
.Get32(1)->GetObject();
1523 SbxDimArray
* pArr
= dynamic_cast<SbxDimArray
*>( pParObj
);
1526 if( pArr
->GetDims32() != 1 )
1528 StarBASIC::Error( ERRCODE_BASIC_WRONG_DIMS
); // Syntax Error?!
1532 if( nParCount
== 3 )
1534 aDelim
= rPar
.Get32(2)->GetOUString();
1540 OUStringBuffer
aRetStr(32);
1541 sal_Int32 nLower
, nUpper
;
1542 pArr
->GetDim32( 1, nLower
, nUpper
);
1544 for (aIdx
[0] = nLower
; aIdx
[0] <= nUpper
; ++aIdx
[0])
1546 OUString aStr
= pArr
->Get32(aIdx
)->GetOUString();
1547 aRetStr
.append(aStr
);
1548 if (aIdx
[0] != nUpper
)
1550 aRetStr
.append(aDelim
);
1553 rPar
.Get32(0)->PutString( aRetStr
.makeStringAndClear() );
1557 StarBASIC::Error( ERRCODE_BASIC_MUST_HAVE_DIMS
);
1562 void SbRtl_Split(StarBASIC
*, SbxArray
& rPar
, bool)
1564 sal_uInt32 nParCount
= rPar
.Count32();
1565 if ( nParCount
< 2 )
1567 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1571 OUString aExpression
= rPar
.Get32(1)->GetOUString();
1572 sal_Int32 nArraySize
= 0;
1573 std::vector
< OUString
> vRet
;
1574 if( !aExpression
.isEmpty() )
1577 if( nParCount
>= 3 )
1579 aDelim
= rPar
.Get32(2)->GetOUString();
1586 sal_Int32 nCount
= -1;
1587 if( nParCount
== 4 )
1589 nCount
= rPar
.Get32(3)->GetLong();
1591 sal_Int32 nDelimLen
= aDelim
.getLength();
1594 sal_Int32 iSearch
= -1;
1595 sal_Int32 iStart
= 0;
1598 bool bBreak
= false;
1599 if( nCount
>= 0 && nArraySize
== nCount
- 1 )
1603 iSearch
= aExpression
.indexOf( aDelim
, iStart
);
1605 if( iSearch
>= 0 && !bBreak
)
1607 aSubStr
= aExpression
.copy( iStart
, iSearch
- iStart
);
1608 iStart
= iSearch
+ nDelimLen
;
1612 aSubStr
= aExpression
.copy( iStart
);
1614 vRet
.push_back( aSubStr
);
1622 while( iSearch
>= 0 );
1626 vRet
.push_back( aExpression
);
1631 // tdf#123025 - split returns an array of substrings
1632 SbxDimArray
* pArray
= new SbxDimArray( SbxSTRING
);
1633 pArray
->unoAddDim32( 0, nArraySize
-1 );
1635 // insert parameter(s) into the array
1636 for(sal_Int32 i
= 0 ; i
< nArraySize
; i
++ )
1638 // tdf#123025 - split returns an array of substrings
1639 SbxVariableRef xVar
= new SbxVariable( SbxSTRING
);
1640 xVar
->PutString( vRet
[i
] );
1641 pArray
->Put32( xVar
.get(), &i
);
1645 SbxVariableRef refVar
= rPar
.Get32(0);
1646 SbxFlagBits nFlags
= refVar
->GetFlags();
1647 refVar
->ResetFlag( SbxFlagBits::Fixed
);
1648 refVar
->PutObject( pArray
);
1649 refVar
->SetFlags( nFlags
);
1650 refVar
->SetParameters( nullptr );
1653 // MonthName(month[, abbreviate])
1654 void SbRtl_MonthName(StarBASIC
*, SbxArray
& rPar
, bool)
1656 sal_uInt32 nParCount
= rPar
.Count32();
1657 if( nParCount
!= 2 && nParCount
!= 3 )
1659 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1663 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
1664 if( !xCalendar
.is() )
1666 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
1669 Sequence
< CalendarItem2
> aMonthSeq
= xCalendar
->getMonths2();
1670 sal_Int32 nMonthCount
= aMonthSeq
.getLength();
1672 sal_Int16 nVal
= rPar
.Get32(1)->GetInteger();
1673 if( nVal
< 1 || nVal
> nMonthCount
)
1675 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1679 bool bAbbreviate
= false;
1680 if( nParCount
== 3 )
1681 bAbbreviate
= rPar
.Get32(2)->GetBool();
1683 const CalendarItem2
* pCalendarItems
= aMonthSeq
.getConstArray();
1684 const CalendarItem2
& rItem
= pCalendarItems
[nVal
- 1];
1686 OUString aRetStr
= ( bAbbreviate
? rItem
.AbbrevName
: rItem
.FullName
);
1687 rPar
.Get32(0)->PutString(aRetStr
);
1690 // WeekdayName(weekday, abbreviate, firstdayofweek)
1691 void SbRtl_WeekdayName(StarBASIC
*, SbxArray
& rPar
, bool)
1693 sal_uInt32 nParCount
= rPar
.Count32();
1694 if( nParCount
< 2 || nParCount
> 4 )
1696 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1700 const Reference
< XCalendar4
>& xCalendar
= getLocaleCalendar();
1701 if( !xCalendar
.is() )
1703 StarBASIC::Error( ERRCODE_BASIC_INTERNAL_ERROR
);
1707 Sequence
< CalendarItem2
> aDaySeq
= xCalendar
->getDays2();
1708 sal_Int16 nDayCount
= static_cast<sal_Int16
>(aDaySeq
.getLength());
1709 sal_Int16 nDay
= rPar
.Get32(1)->GetInteger();
1710 sal_Int16 nFirstDay
= 0;
1711 if( nParCount
== 4 )
1713 nFirstDay
= rPar
.Get32(3)->GetInteger();
1714 if( nFirstDay
< 0 || nFirstDay
> 7 )
1716 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1720 if( nFirstDay
== 0 )
1722 nFirstDay
= sal_Int16( xCalendar
->getFirstDayOfWeek() + 1 );
1724 nDay
= 1 + (nDay
+ nDayCount
+ nFirstDay
- 2) % nDayCount
;
1725 if( nDay
< 1 || nDay
> nDayCount
)
1727 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1731 bool bAbbreviate
= false;
1732 if( nParCount
>= 3 )
1734 SbxVariable
* pPar2
= rPar
.Get32(2);
1735 if( !pPar2
->IsErr() )
1737 bAbbreviate
= pPar2
->GetBool();
1741 const CalendarItem2
* pCalendarItems
= aDaySeq
.getConstArray();
1742 const CalendarItem2
& rItem
= pCalendarItems
[nDay
- 1];
1744 OUString aRetStr
= ( bAbbreviate
? rItem
.AbbrevName
: rItem
.FullName
);
1745 rPar
.Get32(0)->PutString( aRetStr
);
1748 void SbRtl_Weekday(StarBASIC
*, SbxArray
& rPar
, bool)
1750 sal_uInt32 nParCount
= rPar
.Count32();
1751 if ( nParCount
< 2 )
1753 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1757 double aDate
= rPar
.Get32(1)->GetDate();
1759 bool bFirstDay
= false;
1760 sal_Int16 nFirstDay
= 0;
1761 if ( nParCount
> 2 )
1763 nFirstDay
= rPar
.Get32(2)->GetInteger();
1766 sal_Int16 nDay
= implGetWeekDay( aDate
, bFirstDay
, nFirstDay
);
1767 rPar
.Get32(0)->PutInteger( nDay
);
1789 Interval meInterval
;
1790 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_uInt32 nParCount
= rPar
.Count32();
1855 if( nParCount
!= 4 )
1857 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1861 OUString aStringCode
= rPar
.Get32(1)->GetOUString();
1862 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
1865 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1869 sal_Int32 lNumber
= rPar
.Get32(2)->GetLong();
1870 double dDate
= rPar
.Get32(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
.Get32(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_uInt32 nParCount
= rPar
.Count32();
1962 if( nParCount
< 4 || nParCount
> 6 )
1964 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1968 OUString aStringCode
= rPar
.Get32(1)->GetOUString();
1969 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
1972 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
1976 double dDate1
= rPar
.Get32(2)->GetDate();
1977 double dDate2
= rPar
.Get32(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
.Get32(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
.Get32(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_uInt32 nParCount
= rPar
.Count32();
2153 if( nParCount
< 3 || nParCount
> 5 )
2155 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2159 OUString aStringCode
= rPar
.Get32(1)->GetOUString();
2160 IntervalInfo
const * pInfo
= getIntervalInfo( aStringCode
);
2163 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2167 double dDate
= rPar
.Get32(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
.Get32(3)->GetInteger();
2209 nRet
= implGetWeekDay( dDate
, bFirstDay
, nFirstDay
);
2214 sal_Int16 nFirstDay
= 1; // Default
2215 if( nParCount
>= 4 )
2216 nFirstDay
= rPar
.Get32(3)->GetInteger();
2218 sal_Int16 nFirstWeek
= 1; // Default
2219 if( nParCount
== 5 )
2220 nFirstWeek
= rPar
.Get32(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
.Get32(0)->PutLong( nRet
);
2265 // FormatDateTime(Date[,NamedFormat])
2266 void SbRtl_FormatDateTime(StarBASIC
*, SbxArray
& rPar
, bool)
2268 sal_uInt32 nParCount
= rPar
.Count32();
2269 if( nParCount
< 2 || nParCount
> 3 )
2271 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2275 double dDate
= rPar
.Get32(1)->GetDate();
2276 sal_Int16 nNamedFormat
= 0;
2279 nNamedFormat
= rPar
.Get32(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
.Get32(0)->PutString( aRetStr
);
2366 void SbRtl_Frac(StarBASIC
*, SbxArray
& rPar
, bool)
2368 sal_uInt32 nParCount
= rPar
.Count32();
2371 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2375 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
2376 double dVal
= pSbxVariable
->GetDouble();
2378 rPar
.Get32(0)->PutDouble(dVal
- ::rtl::math::approxFloor(dVal
));
2380 rPar
.Get32(0)->PutDouble(dVal
- ::rtl::math::approxCeil(dVal
));
2383 void SbRtl_Round(StarBASIC
*, SbxArray
& rPar
, bool)
2385 sal_uInt32 nParCount
= rPar
.Count32();
2386 if( nParCount
!= 2 && nParCount
!= 3 )
2388 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2392 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
2393 double dVal
= pSbxVariable
->GetDouble();
2404 sal_Int16 numdecimalplaces
= 0;
2405 if( nParCount
== 3 )
2407 numdecimalplaces
= rPar
.Get32(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
.Get32(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_uInt32 nArgCount
= rPar
.Count32()-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
.Get32(1)->GetDouble();
2471 aParams
[ 1 ] <<= rPar
.Get32(2)->GetDouble();
2472 aParams
[ 2 ] <<= rPar
.Get32(3)->GetDouble();
2473 aParams
[ 3 ] <<= rPar
.Get32(4)->GetDouble();
2475 CallFunctionAccessFunction( aParams
, "SYD", rPar
.Get32( 0 ) );
2478 void SbRtl_SLN(StarBASIC
*, SbxArray
& rPar
, bool)
2480 sal_uInt32 nArgCount
= rPar
.Count32()-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
.Get32(1)->GetDouble();
2492 aParams
[ 1 ] <<= rPar
.Get32(2)->GetDouble();
2493 aParams
[ 2 ] <<= rPar
.Get32(3)->GetDouble();
2495 CallFunctionAccessFunction( aParams
, "SLN", rPar
.Get32( 0 ) );
2498 void SbRtl_Pmt(StarBASIC
*, SbxArray
& rPar
, bool)
2500 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2502 if ( nArgCount
< 3 || nArgCount
> 5 )
2504 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2507 // retrieve non-optional params
2509 double rate
= rPar
.Get32(1)->GetDouble();
2510 double nper
= rPar
.Get32(2)->GetDouble();
2511 double pmt
= rPar
.Get32(3)->GetDouble();
2513 // set default values for Optional args
2518 if ( nArgCount
>= 4 )
2520 if( rPar
.Get32(4)->GetType() != SbxEMPTY
)
2521 fv
= rPar
.Get32(4)->GetDouble();
2524 if ( nArgCount
>= 5 )
2526 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2527 type
= rPar
.Get32(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
.Get32( 0 ) );
2540 void SbRtl_PPmt(StarBASIC
*, SbxArray
& rPar
, bool)
2542 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2544 if ( nArgCount
< 4 || nArgCount
> 6 )
2546 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2549 // retrieve non-optional params
2551 double rate
= rPar
.Get32(1)->GetDouble();
2552 double per
= rPar
.Get32(2)->GetDouble();
2553 double nper
= rPar
.Get32(3)->GetDouble();
2554 double pv
= rPar
.Get32(4)->GetDouble();
2556 // set default values for Optional args
2561 if ( nArgCount
>= 5 )
2563 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2564 fv
= rPar
.Get32(5)->GetDouble();
2567 if ( nArgCount
>= 6 )
2569 if( rPar
.Get32(6)->GetType() != SbxEMPTY
)
2570 type
= rPar
.Get32(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
.Get32( 0 ) );
2584 void SbRtl_PV(StarBASIC
*, SbxArray
& rPar
, bool)
2586 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2588 if ( nArgCount
< 3 || nArgCount
> 5 )
2590 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2593 // retrieve non-optional params
2595 double rate
= rPar
.Get32(1)->GetDouble();
2596 double nper
= rPar
.Get32(2)->GetDouble();
2597 double pmt
= rPar
.Get32(3)->GetDouble();
2599 // set default values for Optional args
2604 if ( nArgCount
>= 4 )
2606 if( rPar
.Get32(4)->GetType() != SbxEMPTY
)
2607 fv
= rPar
.Get32(4)->GetDouble();
2610 if ( nArgCount
>= 5 )
2612 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2613 type
= rPar
.Get32(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
.Get32( 0 ) );
2626 void SbRtl_NPV(StarBASIC
*, SbxArray
& rPar
, bool)
2628 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2630 if ( nArgCount
< 1 || nArgCount
> 2 )
2632 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2636 Sequence
< Any
> aParams( 2 );
2637 aParams
[ 0 ] <<= rPar
.Get32(1)->GetDouble();
2638 Any aValues
= sbxToUnoValue( rPar
.Get32(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
.Get32( 0 ) );
2651 void SbRtl_NPer(StarBASIC
*, SbxArray
& rPar
, bool)
2653 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2655 if ( nArgCount
< 3 || nArgCount
> 5 )
2657 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2660 // retrieve non-optional params
2662 double rate
= rPar
.Get32(1)->GetDouble();
2663 double pmt
= rPar
.Get32(2)->GetDouble();
2664 double pv
= rPar
.Get32(3)->GetDouble();
2666 // set default values for Optional args
2671 if ( nArgCount
>= 4 )
2673 if( rPar
.Get32(4)->GetType() != SbxEMPTY
)
2674 fv
= rPar
.Get32(4)->GetDouble();
2677 if ( nArgCount
>= 5 )
2679 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2680 type
= rPar
.Get32(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
.Get32( 0 ) );
2693 void SbRtl_MIRR(StarBASIC
*, SbxArray
& rPar
, bool)
2695 sal_uInt32 nArgCount
= rPar
.Count32()-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
.Get32(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
.Get32(2)->GetDouble();
2716 aParams
[ 2 ] <<= rPar
.Get32(3)->GetDouble();
2718 CallFunctionAccessFunction( aParams
, "MIRR", rPar
.Get32( 0 ) );
2721 void SbRtl_IRR(StarBASIC
*, SbxArray
& rPar
, bool)
2723 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2725 if ( nArgCount
< 1 || nArgCount
> 2 )
2727 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2730 // retrieve non-optional params
2731 Any aValues
= sbxToUnoValue( rPar
.Get32(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
.Get32(2)->GetType() != SbxEMPTY
)
2745 guess
= rPar
.Get32(2)->GetDouble();
2748 Sequence
< Any
> aParams( 2 );
2749 aParams
[ 0 ] = aValues
;
2750 aParams
[ 1 ] <<= guess
;
2752 CallFunctionAccessFunction( aParams
, "IRR", rPar
.Get32( 0 ) );
2755 void SbRtl_IPmt(StarBASIC
*, SbxArray
& rPar
, bool)
2757 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2759 if ( nArgCount
< 4 || nArgCount
> 6 )
2761 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2764 // retrieve non-optional params
2766 double rate
= rPar
.Get32(1)->GetDouble();
2767 double per
= rPar
.Get32(2)->GetInteger();
2768 double nper
= rPar
.Get32(3)->GetDouble();
2769 double pv
= rPar
.Get32(4)->GetDouble();
2771 // set default values for Optional args
2776 if ( nArgCount
>= 5 )
2778 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2779 fv
= rPar
.Get32(5)->GetDouble();
2782 if ( nArgCount
>= 6 )
2784 if( rPar
.Get32(6)->GetType() != SbxEMPTY
)
2785 type
= rPar
.Get32(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
.Get32( 0 ) );
2799 void SbRtl_FV(StarBASIC
*, SbxArray
& rPar
, bool)
2801 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2803 if ( nArgCount
< 3 || nArgCount
> 5 )
2805 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2808 // retrieve non-optional params
2810 double rate
= rPar
.Get32(1)->GetDouble();
2811 double nper
= rPar
.Get32(2)->GetDouble();
2812 double pmt
= rPar
.Get32(3)->GetDouble();
2814 // set default values for Optional args
2819 if ( nArgCount
>= 4 )
2821 if( rPar
.Get32(4)->GetType() != SbxEMPTY
)
2822 pv
= rPar
.Get32(4)->GetDouble();
2825 if ( nArgCount
>= 5 )
2827 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2828 type
= rPar
.Get32(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
.Get32( 0 ) );
2841 void SbRtl_DDB(StarBASIC
*, SbxArray
& rPar
, bool)
2843 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2845 if ( nArgCount
< 4 || nArgCount
> 5 )
2847 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2850 // retrieve non-optional params
2852 double cost
= rPar
.Get32(1)->GetDouble();
2853 double salvage
= rPar
.Get32(2)->GetDouble();
2854 double life
= rPar
.Get32(3)->GetDouble();
2855 double period
= rPar
.Get32(4)->GetDouble();
2857 // set default values for Optional args
2861 if ( nArgCount
>= 5 )
2863 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2864 factor
= rPar
.Get32(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
.Get32( 0 ) );
2877 void SbRtl_Rate(StarBASIC
*, SbxArray
& rPar
, bool)
2879 sal_uInt32 nArgCount
= rPar
.Count32()-1;
2881 if ( nArgCount
< 3 || nArgCount
> 6 )
2883 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2886 // retrieve non-optional params
2892 nper
= rPar
.Get32(1)->GetDouble();
2893 pmt
= rPar
.Get32(2)->GetDouble();
2894 pv
= rPar
.Get32(3)->GetDouble();
2896 // set default values for Optional args
2902 if ( nArgCount
>= 4 )
2904 if( rPar
.Get32(4)->GetType() != SbxEMPTY
)
2905 fv
= rPar
.Get32(4)->GetDouble();
2909 if ( nArgCount
>= 5 )
2911 if( rPar
.Get32(5)->GetType() != SbxEMPTY
)
2912 type
= rPar
.Get32(5)->GetDouble();
2916 if ( nArgCount
>= 6 )
2918 if( rPar
.Get32(6)->GetType() != SbxEMPTY
)
2919 guess
= rPar
.Get32(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
.Get32( 0 ) );
2933 void SbRtl_StrReverse(StarBASIC
*, SbxArray
& rPar
, bool)
2935 if ( rPar
.Count32() != 2 )
2937 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2941 SbxVariable
*pSbxVariable
= rPar
.Get32(1);
2942 if( pSbxVariable
->IsNull() )
2944 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2948 OUString aStr
= comphelper::string::reverseString(pSbxVariable
->GetOUString());
2949 rPar
.Get32(0)->PutString( aStr
);
2952 void SbRtl_CompatibilityMode(StarBASIC
*, SbxArray
& rPar
, bool)
2954 bool bEnabled
= false;
2955 sal_uInt32 nCount
= rPar
.Count32();
2956 if ( nCount
!= 1 && nCount
!= 2 )
2957 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2959 SbiInstance
* pInst
= GetSbData()->pInst
;
2964 pInst
->EnableCompatibility( rPar
.Get32(1)->GetBool() );
2966 bEnabled
= pInst
->IsCompatibility();
2968 rPar
.Get32(0)->PutBool( bEnabled
);
2971 void SbRtl_Input(StarBASIC
*, SbxArray
& rPar
, bool)
2973 // 2 parameters needed
2974 if ( rPar
.Count32() < 3 )
2976 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2980 sal_uInt16 nByteCount
= rPar
.Get32(1)->GetUShort();
2981 sal_Int16 nFileNumber
= rPar
.Get32(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
.Get32(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
.Get32(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: */