bump product version to 5.0.4.1
[LibreOffice.git] / basic / source / runtime / methods1.cxx
bloba1eca5f5a1aef9e2e0817a725af2ae43cbd40004
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
25 #include <cstddef>
27 #include <stdlib.h>
28 #include <vcl/svapp.hxx>
29 #include <vcl/mapmod.hxx>
30 #include <vcl/wrkwin.hxx>
31 #include <vcl/timer.hxx>
32 #include <vcl/settings.hxx>
33 #include <basic/sbxvar.hxx>
34 #include <basic/sbx.hxx>
35 #include <svl/zforlist.hxx>
36 #include <tools/urlobj.hxx>
37 #include <tools/fract.hxx>
38 #include <osl/file.hxx>
39 #include <vcl/jobset.hxx>
40 #include "sbobjmod.hxx"
41 #include <basic/sbuno.hxx>
43 #include "date.hxx"
44 #include "sbintern.hxx"
45 #include "runtime.hxx"
46 #include "stdobj.hxx"
47 #include "rtlproto.hxx"
48 #include "dllmgr.hxx"
49 #include <iosys.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>
62 #include <boost/scoped_array.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 > getLocaleCalendar()
72 static Reference< XCalendar4 > xCalendar;
73 if( !xCalendar.is() )
75 Reference< XComponentContext > xContext = getProcessComponentContext();
76 xCalendar = LocaleCalendar2::create(xContext);
79 static com::sun::star::lang::Locale aLastLocale;
80 static bool bNeedsInit = true;
82 com::sun::star::lang::Locale aLocale = Application::GetSettings().GetLanguageTag().getLocale();
83 bool bNeedsReload = false;
84 if( bNeedsInit )
86 bNeedsInit = false;
87 bNeedsReload = true;
89 else if( aLocale.Language != aLastLocale.Language ||
90 aLocale.Country != aLastLocale.Country ||
91 aLocale.Variant != aLastLocale.Variant )
93 bNeedsReload = true;
95 if( bNeedsReload )
97 aLastLocale = aLocale;
98 xCalendar->loadDefaultCalendar( aLocale );
100 return xCalendar;
103 #if HAVE_FEATURE_SCRIPTING
105 RTLFUNC(CallByName)
107 (void)pBasic;
108 (void)bWrite;
110 const sal_Int16 vbGet = 2;
111 const sal_Int16 vbLet = 4;
112 const sal_Int16 vbMethod = 1;
113 const sal_Int16 vbSet = 8;
115 // At least 3 parameter needed plus function itself -> 4
116 sal_uInt16 nParCount = rPar.Count();
117 if ( nParCount < 4 )
119 StarBASIC::Error( SbERR_BAD_ARGUMENT );
120 return;
123 // 1. parameter is object
124 SbxBase* pObjVar = static_cast<SbxObject*>(rPar.Get(1)->GetObject());
125 SbxObject* pObj = NULL;
126 if( pObjVar )
127 pObj = PTR_CAST(SbxObject,pObjVar);
128 if( !pObj && pObjVar && pObjVar->ISA(SbxVariable) )
130 SbxBase* pObjVarObj = static_cast<SbxVariable*>(pObjVar)->GetObject();
131 pObj = PTR_CAST(SbxObject,pObjVarObj);
133 if( !pObj )
135 StarBASIC::Error( SbERR_BAD_PARAMETER );
136 return;
139 // 2. parameter is ProcedureName
140 OUString aNameStr = rPar.Get(2)->GetOUString();
142 // 3. parameter is CallType
143 sal_Int16 nCallType = rPar.Get(3)->GetInteger();
145 //SbxObject* pFindObj = NULL;
146 SbxVariable* pFindVar = pObj->Find( aNameStr, SbxCLASS_DONTCARE );
147 if( pFindVar == NULL )
149 StarBASIC::Error( SbERR_PROC_UNDEFINED );
150 return;
153 switch( nCallType )
155 case vbGet:
157 SbxValues aVals;
158 aVals.eType = SbxVARIANT;
159 pFindVar->Get( aVals );
161 SbxVariableRef refVar = rPar.Get(0);
162 refVar->Put( aVals );
164 break;
165 case vbLet:
166 case vbSet:
168 if ( nParCount != 5 )
170 StarBASIC::Error( SbERR_BAD_ARGUMENT );
171 return;
173 SbxVariableRef pValVar = rPar.Get(4);
174 if( nCallType == vbLet )
176 SbxValues aVals;
177 aVals.eType = SbxVARIANT;
178 pValVar->Get( aVals );
179 pFindVar->Put( aVals );
181 else
183 SbxVariableRef rFindVar = pFindVar;
184 SbiInstance* pInst = GetSbData()->pInst;
185 SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
186 if( pRT != NULL )
188 pRT->StepSET_Impl( pValVar, rFindVar, false );
192 break;
193 case vbMethod:
195 SbMethod* pMeth = PTR_CAST(SbMethod,pFindVar);
196 if( pMeth == NULL )
198 StarBASIC::Error( SbERR_PROC_UNDEFINED );
199 return;
202 // Setup parameters
203 SbxArrayRef xArray;
204 sal_uInt16 nMethParamCount = nParCount - 4;
205 if( nMethParamCount > 0 )
207 xArray = new SbxArray;
208 for( sal_uInt16 i = 0 ; i < nMethParamCount ; i++ )
210 SbxVariable* pPar = rPar.Get( i + 4 );
211 xArray->Put( pPar, i + 1 );
215 // Call method
216 SbxVariableRef refVar = rPar.Get(0);
217 if( xArray.Is() )
218 pMeth->SetParameters( xArray );
219 pMeth->Call( refVar );
220 pMeth->SetParameters( NULL );
222 break;
223 default:
224 StarBASIC::Error( SbERR_PROC_UNDEFINED );
228 RTLFUNC(CBool) // JSM
230 (void)pBasic;
231 (void)bWrite;
233 bool bVal = false;
234 if ( rPar.Count() == 2 )
236 SbxVariable *pSbxVariable = rPar.Get(1);
237 bVal = pSbxVariable->GetBool();
239 else
241 StarBASIC::Error( SbERR_BAD_ARGUMENT );
243 rPar.Get(0)->PutBool(bVal);
246 RTLFUNC(CByte) // JSM
248 (void)pBasic;
249 (void)bWrite;
251 sal_uInt8 nByte = 0;
252 if ( rPar.Count() == 2 )
254 SbxVariable *pSbxVariable = rPar.Get(1);
255 nByte = pSbxVariable->GetByte();
257 else
259 StarBASIC::Error( SbERR_BAD_ARGUMENT );
261 rPar.Get(0)->PutByte(nByte);
264 RTLFUNC(CCur)
266 (void)pBasic;
267 (void)bWrite;
269 sal_Int64 nCur = 0;
270 if ( rPar.Count() == 2 )
272 SbxVariable *pSbxVariable = rPar.Get(1);
273 nCur = pSbxVariable->GetCurrency();
275 else
277 StarBASIC::Error( SbERR_BAD_ARGUMENT );
279 rPar.Get(0)->PutCurrency( nCur );
282 RTLFUNC(CDec)
284 (void)pBasic;
285 (void)bWrite;
287 #ifdef WNT
288 SbxDecimal* pDec = NULL;
289 if ( rPar.Count() == 2 )
291 SbxVariable *pSbxVariable = rPar.Get(1);
292 pDec = pSbxVariable->GetDecimal();
294 else
296 StarBASIC::Error( SbERR_BAD_ARGUMENT );
298 rPar.Get(0)->PutDecimal( pDec );
299 #else
300 rPar.Get(0)->PutEmpty();
301 StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
302 #endif
305 RTLFUNC(CDate) // JSM
307 (void)pBasic;
308 (void)bWrite;
310 double nVal = 0.0;
311 if ( rPar.Count() == 2 )
313 SbxVariable *pSbxVariable = rPar.Get(1);
314 nVal = pSbxVariable->GetDate();
316 else
318 StarBASIC::Error( SbERR_BAD_ARGUMENT );
320 rPar.Get(0)->PutDate(nVal);
323 RTLFUNC(CDbl) // JSM
325 (void)pBasic;
326 (void)bWrite;
328 double nVal = 0.0;
329 if ( rPar.Count() == 2 )
331 SbxVariable *pSbxVariable = rPar.Get(1);
332 if( pSbxVariable->GetType() == SbxSTRING )
334 // #41690
335 OUString aScanStr = pSbxVariable->GetOUString();
336 SbError Error = SbxValue::ScanNumIntnl( aScanStr, nVal );
337 if( Error != SbxERR_OK )
339 StarBASIC::Error( Error );
342 else
344 nVal = pSbxVariable->GetDouble();
347 else
349 StarBASIC::Error( SbERR_BAD_ARGUMENT );
352 rPar.Get(0)->PutDouble(nVal);
355 RTLFUNC(CInt) // JSM
357 (void)pBasic;
358 (void)bWrite;
360 sal_Int16 nVal = 0;
361 if ( rPar.Count() == 2 )
363 SbxVariable *pSbxVariable = rPar.Get(1);
364 nVal = pSbxVariable->GetInteger();
366 else
368 StarBASIC::Error( SbERR_BAD_ARGUMENT );
370 rPar.Get(0)->PutInteger(nVal);
373 RTLFUNC(CLng) // JSM
375 (void)pBasic;
376 (void)bWrite;
378 sal_Int32 nVal = 0;
379 if ( rPar.Count() == 2 )
381 SbxVariable *pSbxVariable = rPar.Get(1);
382 nVal = pSbxVariable->GetLong();
384 else
386 StarBASIC::Error( SbERR_BAD_ARGUMENT );
388 rPar.Get(0)->PutLong(nVal);
391 RTLFUNC(CSng) // JSM
393 (void)pBasic;
394 (void)bWrite;
396 float nVal = (float)0.0;
397 if ( rPar.Count() == 2 )
399 SbxVariable *pSbxVariable = rPar.Get(1);
400 if( pSbxVariable->GetType() == SbxSTRING )
402 // #41690
403 double dVal = 0.0;
404 OUString aScanStr = pSbxVariable->GetOUString();
405 SbError Error = SbxValue::ScanNumIntnl( aScanStr, dVal, /*bSingle=*/true );
406 if( SbxBase::GetError() == SbxERR_OK && Error != SbxERR_OK )
408 StarBASIC::Error( Error );
410 nVal = (float)dVal;
412 else
414 nVal = pSbxVariable->GetSingle();
417 else
419 StarBASIC::Error( SbERR_BAD_ARGUMENT );
421 rPar.Get(0)->PutSingle(nVal);
424 RTLFUNC(CStr) // JSM
426 (void)pBasic;
427 (void)bWrite;
429 OUString aString;
430 if ( rPar.Count() == 2 )
432 SbxVariable *pSbxVariable = rPar.Get(1);
433 aString = pSbxVariable->GetOUString();
435 else
437 StarBASIC::Error( SbERR_BAD_ARGUMENT );
439 rPar.Get(0)->PutString(aString);
442 RTLFUNC(CVar) // JSM
444 (void)pBasic;
445 (void)bWrite;
447 SbxValues aVals( SbxVARIANT );
448 if ( rPar.Count() == 2 )
450 SbxVariable *pSbxVariable = rPar.Get(1);
451 pSbxVariable->Get( aVals );
453 else
455 StarBASIC::Error( SbERR_BAD_ARGUMENT );
457 rPar.Get(0)->Put( aVals );
460 RTLFUNC(CVErr)
462 (void)pBasic;
463 (void)bWrite;
465 sal_Int16 nErrCode = 0;
466 if ( rPar.Count() == 2 )
468 SbxVariable *pSbxVariable = rPar.Get(1);
469 nErrCode = pSbxVariable->GetInteger();
471 else
473 StarBASIC::Error( SbERR_BAD_ARGUMENT );
475 rPar.Get(0)->PutErr( nErrCode );
478 RTLFUNC(Iif) // JSM
480 (void)pBasic;
481 (void)bWrite;
483 if ( rPar.Count() == 4 )
485 if (rPar.Get(1)->GetBool())
487 *rPar.Get(0) = *rPar.Get(2);
489 else
491 *rPar.Get(0) = *rPar.Get(3);
494 else
496 StarBASIC::Error( SbERR_BAD_ARGUMENT );
500 RTLFUNC(GetSystemType)
502 (void)pBasic;
503 (void)bWrite;
505 if ( rPar.Count() != 1 )
507 StarBASIC::Error( SbERR_BAD_ARGUMENT );
509 else
511 // Removed for SRC595
512 rPar.Get(0)->PutInteger( -1 );
516 RTLFUNC(GetGUIType)
518 (void)pBasic;
519 (void)bWrite;
521 if ( rPar.Count() != 1 )
523 StarBASIC::Error( SbERR_BAD_ARGUMENT );
525 else
527 // 17.7.2000 Make simple solution for testtool / fat office
528 #if defined (WNT)
529 rPar.Get(0)->PutInteger( 1 );
530 #elif defined UNX
531 rPar.Get(0)->PutInteger( 4 );
532 #else
533 rPar.Get(0)->PutInteger( -1 );
534 #endif
538 RTLFUNC(Red)
540 (void)pBasic;
541 (void)bWrite;
543 if ( rPar.Count() != 2 )
545 StarBASIC::Error( SbERR_BAD_ARGUMENT );
547 else
549 sal_Int32 nRGB = rPar.Get(1)->GetLong();
550 nRGB &= 0x00FF0000;
551 nRGB >>= 16;
552 rPar.Get(0)->PutInteger( (sal_Int16)nRGB );
556 RTLFUNC(Green)
558 (void)pBasic;
559 (void)bWrite;
561 if ( rPar.Count() != 2 )
563 StarBASIC::Error( SbERR_BAD_ARGUMENT );
565 else
567 sal_Int32 nRGB = rPar.Get(1)->GetLong();
568 nRGB &= 0x0000FF00;
569 nRGB >>= 8;
570 rPar.Get(0)->PutInteger( (sal_Int16)nRGB );
574 RTLFUNC(Blue)
576 (void)pBasic;
577 (void)bWrite;
579 if ( rPar.Count() != 2 )
581 StarBASIC::Error( SbERR_BAD_ARGUMENT );
583 else
585 sal_Int32 nRGB = rPar.Get(1)->GetLong();
586 nRGB &= 0x000000FF;
587 rPar.Get(0)->PutInteger( (sal_Int16)nRGB );
592 RTLFUNC(Switch)
594 (void)pBasic;
595 (void)bWrite;
597 sal_uInt16 nCount = rPar.Count();
598 if( !(nCount & 0x0001 ))
600 // number of arguments must be odd
601 StarBASIC::Error( SbERR_BAD_ARGUMENT );
603 sal_uInt16 nCurExpr = 1;
604 while( nCurExpr < (nCount-1) )
606 if( rPar.Get( nCurExpr )->GetBool())
608 (*rPar.Get(0)) = *(rPar.Get(nCurExpr+1));
609 return;
611 nCurExpr += 2;
613 rPar.Get(0)->PutNull();
616 //i#64882# Common wait impl for existing Wait and new WaitUntil
617 // rtl functions
618 void Wait_Impl( bool bDurationBased, SbxArray& rPar )
620 if( rPar.Count() != 2 )
622 StarBASIC::Error( SbERR_BAD_ARGUMENT );
623 return;
625 long nWait = 0;
626 if ( bDurationBased )
628 double dWait = rPar.Get(1)->GetDouble();
629 double dNow = Now_Impl();
630 double dSecs = (double)( ( dWait - dNow ) * (double)( 24.0*3600.0) );
631 nWait = (long)( dSecs * 1000 ); // wait in thousands of sec
633 else
635 nWait = rPar.Get(1)->GetLong();
637 if( nWait < 0 )
639 StarBASIC::Error( SbERR_BAD_ARGUMENT );
640 return;
643 Timer aTimer;
644 aTimer.SetTimeout( nWait );
645 aTimer.Start();
646 while ( aTimer.IsActive() )
648 Application::Yield();
652 //i#64882#
653 RTLFUNC(Wait)
655 (void)pBasic;
656 (void)bWrite;
657 Wait_Impl( false, rPar );
660 //i#64882# add new WaitUntil ( for application.wait )
661 // share wait_impl with 'normal' oobasic wait
662 RTLFUNC(WaitUntil)
664 (void)pBasic;
665 (void)bWrite;
666 Wait_Impl( true, rPar );
669 RTLFUNC(DoEvents)
671 (void)pBasic;
672 (void)bWrite;
673 (void)rPar;
674 // don't undstand what upstream are up to
675 // we already process application events etc. in between
676 // basic runtime pcode ( on a timed basis )
677 // always return 0
678 rPar.Get(0)->PutInteger( 0 );
679 Application::Reschedule( true );
682 RTLFUNC(GetGUIVersion)
684 (void)pBasic;
685 (void)bWrite;
687 if ( rPar.Count() != 1 )
689 StarBASIC::Error( SbERR_BAD_ARGUMENT );
691 else
693 // Removed for SRC595
694 rPar.Get(0)->PutLong( -1 );
698 RTLFUNC(Choose)
700 (void)pBasic;
701 (void)bWrite;
703 if ( rPar.Count() < 2 )
705 StarBASIC::Error( SbERR_BAD_ARGUMENT );
707 sal_Int16 nIndex = rPar.Get(1)->GetInteger();
708 sal_uInt16 nCount = rPar.Count();
709 nCount--;
710 if( nCount == 1 || nIndex > (nCount-1) || nIndex < 1 )
712 rPar.Get(0)->PutNull();
713 return;
715 (*rPar.Get(0)) = *(rPar.Get(nIndex+1));
719 RTLFUNC(Trim)
721 (void)pBasic;
722 (void)bWrite;
724 if ( rPar.Count() < 2 )
726 StarBASIC::Error( SbERR_BAD_ARGUMENT );
728 else
730 OUString aStr(comphelper::string::strip(rPar.Get(1)->GetOUString(), ' '));
731 rPar.Get(0)->PutString(aStr);
735 RTLFUNC(GetSolarVersion)
737 (void)pBasic;
738 (void)bWrite;
740 rPar.Get(0)->PutLong( LIBO_VERSION_MAJOR * 10000 + LIBO_VERSION_MINOR * 100 + LIBO_VERSION_MICRO * 1);
743 RTLFUNC(TwipsPerPixelX)
745 (void)pBasic;
746 (void)bWrite;
748 sal_Int32 nResult = 0;
749 Size aSize( 100,0 );
750 MapMode aMap( MAP_TWIP );
751 OutputDevice* pDevice = Application::GetDefaultDevice();
752 if( pDevice )
754 aSize = pDevice->PixelToLogic( aSize, aMap );
755 nResult = aSize.Width() / 100;
757 rPar.Get(0)->PutLong( nResult );
760 RTLFUNC(TwipsPerPixelY)
762 (void)pBasic;
763 (void)bWrite;
765 sal_Int32 nResult = 0;
766 Size aSize( 0,100 );
767 MapMode aMap( MAP_TWIP );
768 OutputDevice* pDevice = Application::GetDefaultDevice();
769 if( pDevice )
771 aSize = pDevice->PixelToLogic( aSize, aMap );
772 nResult = aSize.Height() / 100;
774 rPar.Get(0)->PutLong( nResult );
778 RTLFUNC(FreeLibrary)
780 (void)pBasic;
781 (void)bWrite;
783 if ( rPar.Count() != 2 )
785 StarBASIC::Error( SbERR_BAD_ARGUMENT );
787 GetSbData()->pInst->GetDllMgr()->FreeDll( rPar.Get(1)->GetOUString() );
789 bool IsBaseIndexOne()
791 bool result = false;
792 if ( GetSbData()->pInst && GetSbData()->pInst->pRun )
794 sal_uInt16 res = GetSbData()->pInst->pRun->GetBase();
795 if ( res )
797 result = true;
800 return result;
803 RTLFUNC(Array)
805 (void)pBasic;
806 (void)bWrite;
808 SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
809 sal_uInt16 nArraySize = rPar.Count() - 1;
811 // ignore Option Base so far (unfortunately only known by the compiler)
812 bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
813 if( nArraySize )
815 if ( bIncIndex )
817 pArray->AddDim( 1, nArraySize );
819 else
821 pArray->AddDim( 0, nArraySize-1 );
824 else
826 pArray->unoAddDim( 0, -1 );
829 // insert parameters into the array
830 // ATTENTION: Using type sal_uInt16 for loop variable is
831 // mandatory to workaround a problem with the
832 // Solaris Intel compiler optimizer! See i104354
833 for( sal_uInt16 i = 0 ; i < nArraySize ; i++ )
835 SbxVariable* pVar = rPar.Get(i+1);
836 SbxVariable* pNew = new SbxVariable( *pVar );
837 pNew->SetFlag( SBX_WRITE );
838 short index = static_cast< short >(i);
839 if ( bIncIndex )
841 ++index;
843 // coverity[callee_ptr_arith]
844 pArray->Put( pNew, &index );
847 // return array
848 SbxVariableRef refVar = rPar.Get(0);
849 SbxFlagBits nFlags = refVar->GetFlags();
850 refVar->ResetFlag( SBX_FIXED );
851 refVar->PutObject( pArray );
852 refVar->SetFlags( nFlags );
853 refVar->SetParameters( NULL );
857 // Featurewish #57868
858 // The function returns a variant-array; if there are no parameters passed,
859 // an empty array is created (according to dim a(); equal to a sequence of
860 // the length 0 in Uno).
861 // If there are parameters passed, there's a dimension created for each of
862 // them; DimArray( 2, 2, 4 ) is equal to DIM a( 2, 2, 4 )
863 // the array is always of the type variant
864 RTLFUNC(DimArray)
866 (void)pBasic;
867 (void)bWrite;
869 SbxDimArray * pArray = new SbxDimArray( SbxVARIANT );
870 sal_uInt16 nArrayDims = rPar.Count() - 1;
871 if( nArrayDims > 0 )
873 for( sal_uInt16 i = 0; i < nArrayDims ; i++ )
875 sal_Int32 ub = rPar.Get(i+1)->GetLong();
876 if( ub < 0 )
878 StarBASIC::Error( SbERR_OUT_OF_RANGE );
879 ub = 0;
881 pArray->AddDim32( 0, ub );
884 else
886 pArray->unoAddDim( 0, -1 );
888 SbxVariableRef refVar = rPar.Get(0);
889 SbxFlagBits nFlags = refVar->GetFlags();
890 refVar->ResetFlag( SBX_FIXED );
891 refVar->PutObject( pArray );
892 refVar->SetFlags( nFlags );
893 refVar->SetParameters( NULL );
897 * FindObject and FindPropertyObject make it possible to
898 * address objects and properties of the type Object with
899 * their name as string-pararmeters at the runtime.
901 * Example:
902 * MyObj.Prop1.Bla = 5
904 * is equal to:
905 * dim ObjVar as Object
906 * dim ObjProp as Object
907 * ObjName$ = "MyObj"
908 * ObjVar = FindObject( ObjName$ )
909 * PropName$ = "Prop1"
910 * ObjProp = FindPropertyObject( ObjVar, PropName$ )
911 * ObjProp.Bla = 5
913 * The names can be created dynamically at the runtime
914 * so that e. g. via controls "TextEdit1" to "TextEdit5"
915 * can be iterated in a dialog in a loop.
919 // 1st parameter = the object's name as string
920 RTLFUNC(FindObject)
922 (void)pBasic;
923 (void)bWrite;
925 if ( rPar.Count() < 2 )
927 StarBASIC::Error( SbERR_BAD_ARGUMENT );
928 return;
931 OUString aNameStr = rPar.Get(1)->GetOUString();
933 SbxBase* pFind = StarBASIC::FindSBXInCurrentScope( aNameStr );
934 SbxObject* pFindObj = NULL;
935 if( pFind )
937 pFindObj = PTR_CAST(SbxObject,pFind);
939 SbxVariableRef refVar = rPar.Get(0);
940 refVar->PutObject( pFindObj );
943 // address object-property in an object
944 // 1st parameter = object
945 // 2nd parameter = the property's name as string
946 RTLFUNC(FindPropertyObject)
948 (void)pBasic;
949 (void)bWrite;
951 if ( rPar.Count() < 3 )
953 StarBASIC::Error( SbERR_BAD_ARGUMENT );
954 return;
957 SbxBase* pObjVar = static_cast<SbxObject*>(rPar.Get(1)->GetObject());
958 SbxObject* pObj = NULL;
959 if( pObjVar )
961 pObj = PTR_CAST(SbxObject,pObjVar);
963 if( !pObj && pObjVar && pObjVar->ISA(SbxVariable) )
965 SbxBase* pObjVarObj = static_cast<SbxVariable*>(pObjVar)->GetObject();
966 pObj = PTR_CAST(SbxObject,pObjVarObj);
969 OUString aNameStr = rPar.Get(2)->GetOUString();
971 SbxObject* pFindObj = NULL;
972 if( pObj )
974 SbxVariable* pFindVar = pObj->Find( aNameStr, SbxCLASS_OBJECT );
975 pFindObj = PTR_CAST(SbxObject,pFindVar);
977 else
979 StarBASIC::Error( SbERR_BAD_PARAMETER );
982 SbxVariableRef refVar = rPar.Get(0);
983 refVar->PutObject( pFindObj );
988 static bool lcl_WriteSbxVariable( const SbxVariable& rVar, SvStream* pStrm,
989 bool bBinary, short nBlockLen, bool bIsArray )
991 sal_Size nFPos = pStrm->Tell();
993 bool bIsVariant = !rVar.IsFixed();
994 SbxDataType eType = rVar.GetType();
996 switch( eType )
998 case SbxBOOL:
999 case SbxCHAR:
1000 case SbxBYTE:
1001 if( bIsVariant )
1003 pStrm->WriteUInt16( SbxBYTE ); // VarType Id
1005 pStrm->WriteUChar( rVar.GetByte() );
1006 break;
1008 case SbxEMPTY:
1009 case SbxNULL:
1010 case SbxVOID:
1011 case SbxINTEGER:
1012 case SbxUSHORT:
1013 case SbxINT:
1014 case SbxUINT:
1015 if( bIsVariant )
1017 pStrm->WriteUInt16( SbxINTEGER ); // VarType Id
1019 pStrm->WriteInt16( rVar.GetInteger() );
1020 break;
1022 case SbxLONG:
1023 case SbxULONG:
1024 if( bIsVariant )
1026 pStrm->WriteUInt16( SbxLONG ); // VarType Id
1028 pStrm->WriteInt32( rVar.GetLong() );
1029 break;
1030 case SbxSALINT64:
1031 case SbxSALUINT64:
1032 if( bIsVariant )
1034 pStrm->WriteUInt16( SbxSALINT64 ); // VarType Id
1036 pStrm->WriteUInt64( rVar.GetInt64() );
1037 break;
1038 case SbxSINGLE:
1039 if( bIsVariant )
1041 pStrm->WriteUInt16( eType ); // VarType Id
1043 pStrm->WriteFloat( rVar.GetSingle() );
1044 break;
1046 case SbxDOUBLE:
1047 case SbxCURRENCY:
1048 case SbxDATE:
1049 if( bIsVariant )
1051 pStrm->WriteUInt16( eType ); // VarType Id
1053 pStrm->WriteDouble( rVar.GetDouble() );
1054 break;
1056 case SbxSTRING:
1057 case SbxLPSTR:
1059 const OUString& rStr = rVar.GetOUString();
1060 if( !bBinary || bIsArray )
1062 if( bIsVariant )
1064 pStrm->WriteUInt16( SbxSTRING );
1066 pStrm->WriteUniOrByteString( rStr, osl_getThreadTextEncoding() );
1068 else
1070 // without any length information! without end-identifier!
1071 // What does that mean for Unicode?! Choosing conversion to ByteString...
1072 OString aByteStr(OUStringToOString(rStr, osl_getThreadTextEncoding()));
1073 pStrm->WriteCharPtr( (const char*)aByteStr.getStr() );
1076 break;
1078 default:
1079 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1080 return false;
1083 if( nBlockLen )
1085 pStrm->Seek( nFPos + nBlockLen );
1087 return pStrm->GetErrorCode() == 0;
1090 static bool lcl_ReadSbxVariable( SbxVariable& rVar, SvStream* pStrm,
1091 bool bBinary, short nBlockLen, bool bIsArray )
1093 (void)bBinary;
1094 (void)bIsArray;
1096 double aDouble;
1098 sal_Size nFPos = pStrm->Tell();
1100 bool bIsVariant = !rVar.IsFixed();
1101 SbxDataType eVarType = rVar.GetType();
1103 SbxDataType eSrcType = eVarType;
1104 if( bIsVariant )
1106 sal_uInt16 nTemp;
1107 pStrm->ReadUInt16( nTemp );
1108 eSrcType = (SbxDataType)nTemp;
1111 switch( eSrcType )
1113 case SbxBOOL:
1114 case SbxCHAR:
1115 case SbxBYTE:
1117 sal_uInt8 aByte;
1118 pStrm->ReadUChar( aByte );
1120 if( bBinary && SbiRuntime::isVBAEnabled() && aByte == 1 && pStrm->IsEof() )
1122 aByte = 0;
1124 rVar.PutByte( aByte );
1126 break;
1128 case SbxEMPTY:
1129 case SbxNULL:
1130 case SbxVOID:
1131 case SbxINTEGER:
1132 case SbxUSHORT:
1133 case SbxINT:
1134 case SbxUINT:
1136 sal_Int16 aInt;
1137 pStrm->ReadInt16( aInt );
1138 rVar.PutInteger( aInt );
1140 break;
1142 case SbxLONG:
1143 case SbxULONG:
1145 sal_Int32 aInt;
1146 pStrm->ReadInt32( aInt );
1147 rVar.PutLong( aInt );
1149 break;
1150 case SbxSALINT64:
1151 case SbxSALUINT64:
1153 sal_uInt32 aInt;
1154 pStrm->ReadUInt32( aInt );
1155 rVar.PutInt64( (sal_Int64)aInt );
1157 break;
1158 case SbxSINGLE:
1160 float nS;
1161 pStrm->ReadFloat( nS );
1162 rVar.PutSingle( nS );
1164 break;
1166 case SbxDOUBLE:
1167 case SbxCURRENCY:
1169 pStrm->ReadDouble( aDouble );
1170 rVar.PutDouble( aDouble );
1172 break;
1174 case SbxDATE:
1176 pStrm->ReadDouble( aDouble );
1177 rVar.PutDate( aDouble );
1179 break;
1181 case SbxSTRING:
1182 case SbxLPSTR:
1184 OUString aStr = pStrm->ReadUniOrByteString(osl_getThreadTextEncoding());
1185 rVar.PutString( aStr );
1187 break;
1189 default:
1190 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1191 return false;
1194 if( nBlockLen )
1196 pStrm->Seek( nFPos + nBlockLen );
1198 return pStrm->GetErrorCode() == 0;
1202 // nCurDim = 1...n
1203 static bool lcl_WriteReadSbxArray( SbxDimArray& rArr, SvStream* pStrm,
1204 bool bBinary, short nCurDim, short* pOtherDims, bool bWrite )
1206 SAL_WARN_IF( nCurDim <= 0,"basic", "Bad Dim");
1207 short nLower, nUpper;
1208 if( !rArr.GetDim( nCurDim, nLower, nUpper ) )
1209 return false;
1210 for( short nCur = nLower; nCur <= nUpper; nCur++ )
1212 pOtherDims[ nCurDim-1 ] = nCur;
1213 if( nCurDim != 1 )
1214 lcl_WriteReadSbxArray(rArr, pStrm, bBinary, nCurDim-1, pOtherDims, bWrite);
1215 else
1217 SbxVariable* pVar = rArr.Get( (const short*)pOtherDims );
1218 bool bRet;
1219 if( bWrite )
1220 bRet = lcl_WriteSbxVariable(*pVar, pStrm, bBinary, 0, true );
1221 else
1222 bRet = lcl_ReadSbxVariable(*pVar, pStrm, bBinary, 0, true );
1223 if( !bRet )
1224 return false;
1227 return true;
1230 void PutGet( SbxArray& rPar, bool bPut )
1232 if ( rPar.Count() != 4 )
1234 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1235 return;
1237 sal_Int16 nFileNo = rPar.Get(1)->GetInteger();
1238 SbxVariable* pVar2 = rPar.Get(2);
1239 SbxDataType eType2 = pVar2->GetType();
1240 bool bHasRecordNo = (eType2 != SbxEMPTY && eType2 != SbxERROR);
1241 long nRecordNo = pVar2->GetLong();
1242 if ( nFileNo < 1 || ( bHasRecordNo && nRecordNo < 1 ) )
1244 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1245 return;
1247 nRecordNo--;
1248 SbiIoSystem* pIO = GetSbData()->pInst->GetIoSystem();
1249 SbiStream* pSbStrm = pIO->GetStream( nFileNo );
1251 if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_RANDOM)) )
1253 StarBASIC::Error( SbERR_BAD_CHANNEL );
1254 return;
1257 SvStream* pStrm = pSbStrm->GetStrm();
1258 bool bRandom = pSbStrm->IsRandom();
1259 short nBlockLen = bRandom ? pSbStrm->GetBlockLen() : 0;
1261 if( bPut )
1263 pSbStrm->ExpandFile();
1266 if( bHasRecordNo )
1268 sal_Size nFilePos = bRandom ? (sal_Size)(nBlockLen * nRecordNo) : (sal_Size)nRecordNo;
1269 pStrm->Seek( nFilePos );
1272 SbxDimArray* pArr = 0;
1273 SbxVariable* pVar = rPar.Get(3);
1274 if( pVar->GetType() & SbxARRAY )
1276 SbxBase* pParObj = pVar->GetObject();
1277 pArr = PTR_CAST(SbxDimArray,pParObj);
1280 bool bRet;
1282 if( pArr )
1284 sal_Size nFPos = pStrm->Tell();
1285 short nDims = pArr->GetDims();
1286 boost::scoped_array<short> pDims(new short[ nDims ]);
1287 bRet = lcl_WriteReadSbxArray(*pArr,pStrm,!bRandom,nDims,pDims.get(),bPut);
1288 pDims.reset();
1289 if( nBlockLen )
1290 pStrm->Seek( nFPos + nBlockLen );
1292 else
1294 if( bPut )
1295 bRet = lcl_WriteSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, false);
1296 else
1297 bRet = lcl_ReadSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, false);
1299 if( !bRet || pStrm->GetErrorCode() )
1300 StarBASIC::Error( SbERR_IO_ERROR );
1303 RTLFUNC(Put)
1305 (void)pBasic;
1306 (void)bWrite;
1308 PutGet( rPar, true );
1311 RTLFUNC(Get)
1313 (void)pBasic;
1314 (void)bWrite;
1316 PutGet( rPar, false );
1319 RTLFUNC(Environ)
1321 (void)pBasic;
1322 (void)bWrite;
1324 if ( rPar.Count() != 2 )
1326 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1327 return;
1329 OUString aResult;
1330 // should be ANSI but that's not possible under Win16 in the DLL
1331 OString aByteStr(OUStringToOString(rPar.Get(1)->GetOUString(),
1332 osl_getThreadTextEncoding()));
1333 const char* pEnvStr = getenv(aByteStr.getStr());
1334 if ( pEnvStr )
1336 aResult = OUString(pEnvStr, strlen(pEnvStr), osl_getThreadTextEncoding());
1338 rPar.Get(0)->PutString( aResult );
1341 static double GetDialogZoomFactor( bool bX, long nValue )
1343 OutputDevice* pDevice = Application::GetDefaultDevice();
1344 double nResult = 0;
1345 if( pDevice )
1347 Size aRefSize( nValue, nValue );
1348 Fraction aFracX( 1, 26 );
1349 Fraction aFracY( 1, 24 );
1350 MapMode aMap( MAP_APPFONT, Point(), aFracX, aFracY );
1351 Size aScaledSize = pDevice->LogicToPixel( aRefSize, aMap );
1352 aRefSize = pDevice->LogicToPixel( aRefSize, MapMode(MAP_TWIP) );
1354 double nRef, nScaled;
1355 if( bX )
1357 nRef = aRefSize.Width();
1358 nScaled = aScaledSize.Width();
1360 else
1362 nRef = aRefSize.Height();
1363 nScaled = aScaledSize.Height();
1365 nResult = nScaled / nRef;
1367 return nResult;
1371 RTLFUNC(GetDialogZoomFactorX)
1373 (void)pBasic;
1374 (void)bWrite;
1376 if ( rPar.Count() != 2 )
1378 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1379 return;
1381 rPar.Get(0)->PutDouble( GetDialogZoomFactor( true, rPar.Get(1)->GetLong() ));
1384 RTLFUNC(GetDialogZoomFactorY)
1386 (void)pBasic;
1387 (void)bWrite;
1389 if ( rPar.Count() != 2 )
1391 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1392 return;
1394 rPar.Get(0)->PutDouble( GetDialogZoomFactor( false, rPar.Get(1)->GetLong()));
1398 RTLFUNC(EnableReschedule)
1400 (void)pBasic;
1401 (void)bWrite;
1403 rPar.Get(0)->PutEmpty();
1404 if ( rPar.Count() != 2 )
1405 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1406 if( GetSbData()->pInst )
1407 GetSbData()->pInst->EnableReschedule( rPar.Get(1)->GetBool() );
1410 RTLFUNC(GetSystemTicks)
1412 (void)pBasic;
1413 (void)bWrite;
1415 if ( rPar.Count() != 1 )
1417 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1418 return;
1420 rPar.Get(0)->PutLong( tools::Time::GetSystemTicks() );
1423 RTLFUNC(GetPathSeparator)
1425 (void)pBasic;
1426 (void)bWrite;
1428 if ( rPar.Count() != 1 )
1430 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1431 return;
1433 rPar.Get(0)->PutString( OUString( SAL_PATHDELIMITER ) );
1436 RTLFUNC(ResolvePath)
1438 (void)pBasic;
1439 (void)bWrite;
1441 if ( rPar.Count() == 2 )
1443 OUString aStr = rPar.Get(1)->GetOUString();
1444 rPar.Get(0)->PutString( aStr );
1446 else
1448 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1452 RTLFUNC(TypeLen)
1454 (void)pBasic;
1455 (void)bWrite;
1457 if ( rPar.Count() != 2 )
1459 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1461 else
1463 SbxDataType eType = rPar.Get(1)->GetType();
1464 sal_Int16 nLen = 0;
1465 switch( eType )
1467 case SbxEMPTY:
1468 case SbxNULL:
1469 case SbxVECTOR:
1470 case SbxARRAY:
1471 case SbxBYREF:
1472 case SbxVOID:
1473 case SbxHRESULT:
1474 case SbxPOINTER:
1475 case SbxDIMARRAY:
1476 case SbxCARRAY:
1477 case SbxUSERDEF:
1478 nLen = 0;
1479 break;
1481 case SbxINTEGER:
1482 case SbxERROR:
1483 case SbxUSHORT:
1484 case SbxINT:
1485 case SbxUINT:
1486 nLen = 2;
1487 break;
1489 case SbxLONG:
1490 case SbxSINGLE:
1491 case SbxULONG:
1492 nLen = 4;
1493 break;
1495 case SbxDOUBLE:
1496 case SbxCURRENCY:
1497 case SbxDATE:
1498 case SbxSALINT64:
1499 case SbxSALUINT64:
1500 nLen = 8;
1501 break;
1503 case SbxOBJECT:
1504 case SbxVARIANT:
1505 case SbxDATAOBJECT:
1506 nLen = 0;
1507 break;
1509 case SbxCHAR:
1510 case SbxBYTE:
1511 case SbxBOOL:
1512 nLen = 1;
1513 break;
1515 case SbxLPSTR:
1516 case SbxLPWSTR:
1517 case SbxCoreSTRING:
1518 case SbxSTRING:
1519 nLen = (sal_Int16)rPar.Get(1)->GetOUString().getLength();
1520 break;
1522 default:
1523 nLen = 0;
1524 break;
1526 rPar.Get(0)->PutInteger( nLen );
1531 // 1st parameter == class name, other parameters for initialisation
1532 RTLFUNC(CreateUnoStruct)
1534 (void)pBasic;
1535 (void)bWrite;
1537 RTL_Impl_CreateUnoStruct( pBasic, rPar, bWrite );
1541 // 1st parameter == service-name
1542 RTLFUNC(CreateUnoService)
1544 (void)pBasic;
1545 (void)bWrite;
1547 RTL_Impl_CreateUnoService( pBasic, rPar, bWrite );
1550 RTLFUNC(CreateUnoServiceWithArguments)
1552 (void)pBasic;
1553 (void)bWrite;
1555 RTL_Impl_CreateUnoServiceWithArguments( pBasic, rPar, bWrite );
1559 RTLFUNC(CreateUnoValue)
1561 (void)pBasic;
1562 (void)bWrite;
1564 RTL_Impl_CreateUnoValue( pBasic, rPar, bWrite );
1568 // no parameters
1569 RTLFUNC(GetProcessServiceManager)
1571 (void)pBasic;
1572 (void)bWrite;
1574 RTL_Impl_GetProcessServiceManager( pBasic, rPar, bWrite );
1578 // 1st parameter == Sequence<PropertyValue>
1579 RTLFUNC(CreatePropertySet)
1581 (void)pBasic;
1582 (void)bWrite;
1584 RTL_Impl_CreatePropertySet( pBasic, rPar, bWrite );
1588 // multiple interface-names as parameters
1589 RTLFUNC(HasUnoInterfaces)
1591 (void)pBasic;
1592 (void)bWrite;
1594 RTL_Impl_HasInterfaces( pBasic, rPar, bWrite );
1598 RTLFUNC(IsUnoStruct)
1600 (void)pBasic;
1601 (void)bWrite;
1603 RTL_Impl_IsUnoStruct( pBasic, rPar, bWrite );
1607 RTLFUNC(EqualUnoObjects)
1609 (void)pBasic;
1610 (void)bWrite;
1612 RTL_Impl_EqualUnoObjects( pBasic, rPar, bWrite );
1615 RTLFUNC(CreateUnoDialog)
1617 (void)pBasic;
1618 (void)bWrite;
1620 RTL_Impl_CreateUnoDialog( pBasic, rPar, bWrite );
1623 // Return the application standard lib as root scope
1624 RTLFUNC(GlobalScope)
1626 (void)pBasic;
1627 (void)bWrite;
1629 SbxObject* p = pBasic;
1630 while( p->GetParent() )
1632 p = p->GetParent();
1634 SbxVariableRef refVar = rPar.Get(0);
1635 refVar->PutObject( p );
1638 // Helper functions to convert Url from/to system paths
1639 RTLFUNC(ConvertToUrl)
1641 (void)pBasic;
1642 (void)bWrite;
1644 if ( rPar.Count() == 2 )
1646 OUString aStr = rPar.Get(1)->GetOUString();
1647 INetURLObject aURLObj( aStr, INetProtocol::File );
1648 OUString aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
1649 if( aFileURL.isEmpty() )
1651 ::osl::File::getFileURLFromSystemPath( aFileURL, aFileURL );
1653 if( aFileURL.isEmpty() )
1655 aFileURL = aStr;
1657 rPar.Get(0)->PutString(aFileURL);
1659 else
1661 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1665 RTLFUNC(ConvertFromUrl)
1667 (void)pBasic;
1668 (void)bWrite;
1670 if ( rPar.Count() == 2 )
1672 OUString aStr = rPar.Get(1)->GetOUString();
1673 OUString aSysPath;
1674 ::osl::File::getSystemPathFromFileURL( aStr, aSysPath );
1675 if( aSysPath.isEmpty() )
1677 aSysPath = aStr;
1679 rPar.Get(0)->PutString(aSysPath);
1681 else
1683 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1688 // Provide DefaultContext
1689 RTLFUNC(GetDefaultContext)
1691 (void)pBasic;
1692 (void)bWrite;
1694 RTL_Impl_GetDefaultContext( pBasic, rPar, bWrite );
1697 #ifdef DBG_TRACE_BASIC
1698 RTLFUNC(TraceCommand)
1700 RTL_Impl_TraceCommand( pBasic, rPar, bWrite );
1702 #endif
1704 RTLFUNC(Join)
1706 (void)pBasic;
1707 (void)bWrite;
1709 sal_uInt16 nParCount = rPar.Count();
1710 if ( nParCount != 3 && nParCount != 2 )
1712 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1713 return;
1715 SbxBase* pParObj = rPar.Get(1)->GetObject();
1716 SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
1717 if( pArr )
1719 if( pArr->GetDims() != 1 )
1721 StarBASIC::Error( SbERR_WRONG_DIMS ); // Syntax Error?!
1722 return;
1724 OUString aDelim;
1725 if( nParCount == 3 )
1727 aDelim = rPar.Get(2)->GetOUString();
1729 else
1731 aDelim = " ";
1733 OUString aRetStr;
1734 short nLower, nUpper;
1735 pArr->GetDim( 1, nLower, nUpper );
1736 for (short i = nLower; i <= nUpper; ++i)
1738 // coverity[callee_ptr_arith]
1739 OUString aStr = pArr->Get( &i )->GetOUString();
1740 aRetStr += aStr;
1741 if( i != nUpper )
1743 aRetStr += aDelim;
1746 rPar.Get(0)->PutString( aRetStr );
1748 else
1750 StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
1755 RTLFUNC(Split)
1757 (void)pBasic;
1758 (void)bWrite;
1760 sal_uInt16 nParCount = rPar.Count();
1761 if ( nParCount < 2 )
1763 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1764 return;
1767 OUString aExpression = rPar.Get(1)->GetOUString();
1768 short nArraySize = 0;
1769 StringVector vRet;
1770 if( !aExpression.isEmpty() )
1772 OUString aDelim;
1773 if( nParCount >= 3 )
1775 aDelim = rPar.Get(2)->GetOUString();
1777 else
1779 aDelim = " ";
1782 sal_Int32 nCount = -1;
1783 if( nParCount == 4 )
1785 nCount = rPar.Get(3)->GetLong();
1787 sal_Int32 nDelimLen = aDelim.getLength();
1788 if( nDelimLen )
1790 sal_Int32 iSearch = -1;
1791 sal_Int32 iStart = 0;
1794 bool bBreak = false;
1795 if( nCount >= 0 && nArraySize == nCount - 1 )
1797 bBreak = true;
1799 iSearch = aExpression.indexOf( aDelim, iStart );
1800 OUString aSubStr;
1801 if( iSearch >= 0 && !bBreak )
1803 aSubStr = aExpression.copy( iStart, iSearch - iStart );
1804 iStart = iSearch + nDelimLen;
1806 else
1808 aSubStr = aExpression.copy( iStart );
1810 vRet.push_back( aSubStr );
1811 nArraySize++;
1813 if( bBreak )
1815 break;
1818 while( iSearch >= 0 );
1820 else
1822 vRet.push_back( aExpression );
1823 nArraySize = 1;
1827 SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
1828 pArray->unoAddDim( 0, nArraySize-1 );
1830 // insert parameter(s) into the array
1831 for( short i = 0 ; i < nArraySize ; i++ )
1833 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
1834 xVar->PutString( vRet[i] );
1835 pArray->Put( xVar.get(), &i );
1838 // return array
1839 SbxVariableRef refVar = rPar.Get(0);
1840 SbxFlagBits nFlags = refVar->GetFlags();
1841 refVar->ResetFlag( SBX_FIXED );
1842 refVar->PutObject( pArray );
1843 refVar->SetFlags( nFlags );
1844 refVar->SetParameters( NULL );
1847 // MonthName(month[, abbreviate])
1848 RTLFUNC(MonthName)
1850 (void)pBasic;
1851 (void)bWrite;
1853 sal_uInt16 nParCount = rPar.Count();
1854 if( nParCount != 2 && nParCount != 3 )
1856 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1857 return;
1860 Reference< XCalendar4 > xCalendar = getLocaleCalendar();
1861 if( !xCalendar.is() )
1863 StarBASIC::Error( SbERR_INTERNAL_ERROR );
1864 return;
1866 Sequence< CalendarItem2 > aMonthSeq = xCalendar->getMonths2();
1867 sal_Int32 nMonthCount = aMonthSeq.getLength();
1869 sal_Int16 nVal = rPar.Get(1)->GetInteger();
1870 if( nVal < 1 || nVal > nMonthCount )
1872 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1873 return;
1876 bool bAbbreviate = false;
1877 if( nParCount == 3 )
1878 bAbbreviate = rPar.Get(2)->GetBool();
1880 const CalendarItem2* pCalendarItems = aMonthSeq.getConstArray();
1881 const CalendarItem2& rItem = pCalendarItems[nVal - 1];
1883 OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName );
1884 rPar.Get(0)->PutString(aRetStr);
1887 // WeekdayName(weekday, abbreviate, firstdayofweek)
1888 RTLFUNC(WeekdayName)
1890 (void)pBasic;
1891 (void)bWrite;
1893 sal_uInt16 nParCount = rPar.Count();
1894 if( nParCount < 2 || nParCount > 4 )
1896 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1897 return;
1900 Reference< XCalendar4 > xCalendar = getLocaleCalendar();
1901 if( !xCalendar.is() )
1903 StarBASIC::Error( SbERR_INTERNAL_ERROR );
1904 return;
1907 Sequence< CalendarItem2 > aDaySeq = xCalendar->getDays2();
1908 sal_Int16 nDayCount = (sal_Int16)aDaySeq.getLength();
1909 sal_Int16 nDay = rPar.Get(1)->GetInteger();
1910 sal_Int16 nFirstDay = 0;
1911 if( nParCount == 4 )
1913 nFirstDay = rPar.Get(3)->GetInteger();
1914 if( nFirstDay < 0 || nFirstDay > 7 )
1916 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1917 return;
1920 if( nFirstDay == 0 )
1922 nFirstDay = sal_Int16( xCalendar->getFirstDayOfWeek() + 1 );
1924 nDay = 1 + (nDay + nDayCount + nFirstDay - 2) % nDayCount;
1925 if( nDay < 1 || nDay > nDayCount )
1927 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1928 return;
1931 bool bAbbreviate = false;
1932 if( nParCount >= 3 )
1934 SbxVariable* pPar2 = rPar.Get(2);
1935 if( !pPar2->IsErr() )
1937 bAbbreviate = pPar2->GetBool();
1941 const CalendarItem2* pCalendarItems = aDaySeq.getConstArray();
1942 const CalendarItem2& rItem = pCalendarItems[nDay - 1];
1944 OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName );
1945 rPar.Get(0)->PutString( aRetStr );
1948 RTLFUNC(Weekday)
1950 (void)pBasic;
1951 (void)bWrite;
1953 sal_uInt16 nParCount = rPar.Count();
1954 if ( nParCount < 2 )
1956 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1958 else
1960 double aDate = rPar.Get(1)->GetDate();
1962 bool bFirstDay = false;
1963 sal_Int16 nFirstDay = 0;
1964 if ( nParCount > 2 )
1966 nFirstDay = rPar.Get(2)->GetInteger();
1967 bFirstDay = true;
1969 sal_Int16 nDay = implGetWeekDay( aDate, bFirstDay, nFirstDay );
1970 rPar.Get(0)->PutInteger( nDay );
1975 enum Interval
1977 INTERVAL_YYYY,
1978 INTERVAL_Q,
1979 INTERVAL_M,
1980 INTERVAL_Y,
1981 INTERVAL_D,
1982 INTERVAL_W,
1983 INTERVAL_WW,
1984 INTERVAL_H,
1985 INTERVAL_N,
1986 INTERVAL_S
1989 struct IntervalInfo
1991 Interval meInterval;
1992 char const * mStringCode;
1993 double mdValue;
1994 bool mbSimple;
1997 IntervalInfo const * getIntervalInfo( const OUString& rStringCode )
1999 static IntervalInfo const aIntervalTable[] =
2001 { INTERVAL_YYYY, "yyyy", 0.0, false }, // Year
2002 { INTERVAL_Q, "q", 0.0, false }, // Quarter
2003 { INTERVAL_M, "m", 0.0, false }, // Month
2004 { INTERVAL_Y, "y", 1.0, true }, // Day of year
2005 { INTERVAL_D, "d", 1.0, true }, // Day
2006 { INTERVAL_W, "w", 1.0, true }, // Weekday
2007 { INTERVAL_WW, "ww", 7.0, true }, // Week
2008 { INTERVAL_H, "h", 1.0 / 24.0, true }, // Hour
2009 { INTERVAL_N, "n", 1.0 / 1440.0, true }, // Minute
2010 { INTERVAL_S, "s", 1.0 / 86400.0, true } // Second
2012 for( std::size_t i = 0; i != SAL_N_ELEMENTS(aIntervalTable); ++i )
2014 if( rStringCode.equalsIgnoreAsciiCaseAscii(
2015 aIntervalTable[i].mStringCode ) )
2017 return &aIntervalTable[i];
2020 return NULL;
2023 inline void implGetDayMonthYear( sal_Int16& rnYear, sal_Int16& rnMonth, sal_Int16& rnDay, double dDate )
2025 rnDay = implGetDateDay( dDate );
2026 rnMonth = implGetDateMonth( dDate );
2027 rnYear = implGetDateYear( dDate );
2030 inline sal_Int16 limitToINT16( sal_Int32 n32 )
2032 if( n32 > 32767 )
2034 n32 = 32767;
2036 else if( n32 < -32768 )
2038 n32 = -32768;
2040 return (sal_Int16)n32;
2043 RTLFUNC(DateAdd)
2045 (void)pBasic;
2046 (void)bWrite;
2048 sal_uInt16 nParCount = rPar.Count();
2049 if( nParCount != 4 )
2051 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2052 return;
2055 OUString aStringCode = rPar.Get(1)->GetOUString();
2056 IntervalInfo const * pInfo = getIntervalInfo( aStringCode );
2057 if( !pInfo )
2059 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2060 return;
2063 sal_Int32 lNumber = rPar.Get(2)->GetLong();
2064 double dDate = rPar.Get(3)->GetDate();
2065 double dNewDate = 0;
2066 if( pInfo->mbSimple )
2068 double dAdd = pInfo->mdValue * lNumber;
2069 dNewDate = dDate + dAdd;
2071 else
2073 // Keep hours, minutes, seconds
2074 double dHoursMinutesSeconds = dDate - floor( dDate );
2076 bool bOk = true;
2077 sal_Int16 nYear, nMonth, nDay;
2078 sal_Int16 nTargetYear16 = 0, nTargetMonth = 0;
2079 implGetDayMonthYear( nYear, nMonth, nDay, dDate );
2080 switch( pInfo->meInterval )
2082 case INTERVAL_YYYY:
2084 sal_Int32 nTargetYear = lNumber + nYear;
2085 nTargetYear16 = limitToINT16( nTargetYear );
2086 nTargetMonth = nMonth;
2087 bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate );
2088 break;
2090 case INTERVAL_Q:
2091 case INTERVAL_M:
2093 bool bNeg = (lNumber < 0);
2094 if( bNeg )
2095 lNumber = -lNumber;
2096 sal_Int32 nYearsAdd;
2097 sal_Int16 nMonthAdd;
2098 if( pInfo->meInterval == INTERVAL_Q )
2100 nYearsAdd = lNumber / 4;
2101 nMonthAdd = (sal_Int16)( 3 * (lNumber % 4) );
2103 else
2105 nYearsAdd = lNumber / 12;
2106 nMonthAdd = (sal_Int16)( lNumber % 12 );
2109 sal_Int32 nTargetYear;
2110 if( bNeg )
2112 nTargetMonth = nMonth - nMonthAdd;
2113 if( nTargetMonth <= 0 )
2115 nTargetMonth += 12;
2116 nYearsAdd++;
2118 nTargetYear = (sal_Int32)nYear - nYearsAdd;
2120 else
2122 nTargetMonth = nMonth + nMonthAdd;
2123 if( nTargetMonth > 12 )
2125 nTargetMonth -= 12;
2126 nYearsAdd++;
2128 nTargetYear = (sal_Int32)nYear + nYearsAdd;
2130 nTargetYear16 = limitToINT16( nTargetYear );
2131 bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate );
2132 break;
2134 default: break;
2137 if( bOk )
2139 // Overflow?
2140 sal_Int16 nNewYear, nNewMonth, nNewDay;
2141 implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
2142 if( nNewYear > 9999 || nNewYear < 100 )
2144 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2145 return;
2147 sal_Int16 nCorrectionDay = nDay;
2148 while( nNewMonth > nTargetMonth )
2150 nCorrectionDay--;
2151 implDateSerial( nTargetYear16, nTargetMonth, nCorrectionDay, dNewDate );
2152 implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
2154 dNewDate += dHoursMinutesSeconds;
2158 rPar.Get(0)->PutDate( dNewDate );
2161 inline double RoundImpl( double d )
2163 return ( d >= 0 ) ? floor( d + 0.5 ) : -floor( -d + 0.5 );
2166 RTLFUNC(DateDiff)
2168 (void)pBasic;
2169 (void)bWrite;
2171 // DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]])
2173 sal_uInt16 nParCount = rPar.Count();
2174 if( nParCount < 4 || nParCount > 6 )
2176 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2177 return;
2180 OUString aStringCode = rPar.Get(1)->GetOUString();
2181 IntervalInfo const * pInfo = getIntervalInfo( aStringCode );
2182 if( !pInfo )
2184 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2185 return;
2188 double dDate1 = rPar.Get(2)->GetDate();
2189 double dDate2 = rPar.Get(3)->GetDate();
2191 double dRet = 0.0;
2192 switch( pInfo->meInterval )
2194 case INTERVAL_YYYY:
2196 sal_Int16 nYear1 = implGetDateYear( dDate1 );
2197 sal_Int16 nYear2 = implGetDateYear( dDate2 );
2198 dRet = nYear2 - nYear1;
2199 break;
2201 case INTERVAL_Q:
2203 sal_Int16 nYear1 = implGetDateYear( dDate1 );
2204 sal_Int16 nYear2 = implGetDateYear( dDate2 );
2205 sal_Int16 nQ1 = 1 + (implGetDateMonth( dDate1 ) - 1) / 3;
2206 sal_Int16 nQ2 = 1 + (implGetDateMonth( dDate2 ) - 1) / 3;
2207 sal_Int16 nQGes1 = 4 * nYear1 + nQ1;
2208 sal_Int16 nQGes2 = 4 * nYear2 + nQ2;
2209 dRet = nQGes2 - nQGes1;
2210 break;
2212 case INTERVAL_M:
2214 sal_Int16 nYear1 = implGetDateYear( dDate1 );
2215 sal_Int16 nYear2 = implGetDateYear( dDate2 );
2216 sal_Int16 nMonth1 = implGetDateMonth( dDate1 );
2217 sal_Int16 nMonth2 = implGetDateMonth( dDate2 );
2218 sal_Int16 nMonthGes1 = 12 * nYear1 + nMonth1;
2219 sal_Int16 nMonthGes2 = 12 * nYear2 + nMonth2;
2220 dRet = nMonthGes2 - nMonthGes1;
2221 break;
2223 case INTERVAL_Y:
2224 case INTERVAL_D:
2226 double dDays1 = floor( dDate1 );
2227 double dDays2 = floor( dDate2 );
2228 dRet = dDays2 - dDays1;
2229 break;
2231 case INTERVAL_W:
2232 case INTERVAL_WW:
2234 double dDays1 = floor( dDate1 );
2235 double dDays2 = floor( dDate2 );
2236 if( pInfo->meInterval == INTERVAL_WW )
2238 sal_Int16 nFirstDay = 1; // Default
2239 if( nParCount >= 5 )
2241 nFirstDay = rPar.Get(4)->GetInteger();
2242 if( nFirstDay < 0 || nFirstDay > 7 )
2244 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2245 return;
2247 if( nFirstDay == 0 )
2249 Reference< XCalendar4 > xCalendar = getLocaleCalendar();
2250 if( !xCalendar.is() )
2252 StarBASIC::Error( SbERR_INTERNAL_ERROR );
2253 return;
2255 nFirstDay = sal_Int16( xCalendar->getFirstDayOfWeek() + 1 );
2258 sal_Int16 nDay1 = implGetWeekDay( dDate1 );
2259 sal_Int16 nDay1_Diff = nDay1 - nFirstDay;
2260 if( nDay1_Diff < 0 )
2261 nDay1_Diff += 7;
2262 dDays1 -= nDay1_Diff;
2264 sal_Int16 nDay2 = implGetWeekDay( dDate2 );
2265 sal_Int16 nDay2_Diff = nDay2 - nFirstDay;
2266 if( nDay2_Diff < 0 )
2267 nDay2_Diff += 7;
2268 dDays2 -= nDay2_Diff;
2271 double dDiff = dDays2 - dDays1;
2272 dRet = ( dDiff >= 0 ) ? floor( dDiff / 7.0 ) : -floor( -dDiff / 7.0 );
2273 break;
2275 case INTERVAL_H:
2277 double dFactor = 24.0;
2278 dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
2279 break;
2281 case INTERVAL_N:
2283 double dFactor =1440.0;
2284 dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
2285 break;
2287 case INTERVAL_S:
2289 double dFactor = 86400.0;
2290 dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
2291 break;
2294 rPar.Get(0)->PutDouble( dRet );
2297 double implGetDateOfFirstDayInFirstWeek
2298 ( sal_Int16 nYear, sal_Int16& nFirstDay, sal_Int16& nFirstWeek, bool* pbError = NULL )
2300 SbError nError = 0;
2301 if( nFirstDay < 0 || nFirstDay > 7 )
2302 nError = SbERR_BAD_ARGUMENT;
2304 if( nFirstWeek < 0 || nFirstWeek > 3 )
2305 nError = SbERR_BAD_ARGUMENT;
2307 Reference< XCalendar4 > xCalendar;
2308 if( nFirstDay == 0 || nFirstWeek == 0 )
2310 xCalendar = getLocaleCalendar();
2311 if( !xCalendar.is() )
2312 nError = SbERR_BAD_ARGUMENT;
2315 if( nError != 0 )
2317 StarBASIC::Error( nError );
2318 if( pbError )
2319 *pbError = true;
2320 return 0.0;
2323 if( nFirstDay == 0 )
2324 nFirstDay = sal_Int16( xCalendar->getFirstDayOfWeek() + 1 );
2326 sal_Int16 nFirstWeekMinDays = 0; // Not used for vbFirstJan1 = default
2327 if( nFirstWeek == 0 )
2329 nFirstWeekMinDays = xCalendar->getMinimumNumberOfDaysForFirstWeek();
2330 if( nFirstWeekMinDays == 1 )
2332 nFirstWeekMinDays = 0;
2333 nFirstWeek = 1;
2335 else if( nFirstWeekMinDays == 4 )
2336 nFirstWeek = 2;
2337 else if( nFirstWeekMinDays == 7 )
2338 nFirstWeek = 3;
2340 else if( nFirstWeek == 2 )
2341 nFirstWeekMinDays = 4; // vbFirstFourDays
2342 else if( nFirstWeek == 3 )
2343 nFirstWeekMinDays = 7; // vbFirstFourDays
2345 double dBaseDate;
2346 implDateSerial( nYear, 1, 1, dBaseDate );
2348 sal_Int16 nWeekDay0101 = implGetWeekDay( dBaseDate );
2349 sal_Int16 nDayDiff = nWeekDay0101 - nFirstDay;
2350 if( nDayDiff < 0 )
2351 nDayDiff += 7;
2353 if( nFirstWeekMinDays )
2355 sal_Int16 nThisWeeksDaysInYearCount = 7 - nDayDiff;
2356 if( nThisWeeksDaysInYearCount < nFirstWeekMinDays )
2357 nDayDiff -= 7;
2359 double dRetDate = dBaseDate - nDayDiff;
2360 return dRetDate;
2363 RTLFUNC(DatePart)
2365 (void)pBasic;
2366 (void)bWrite;
2368 // DatePart(interval, date[,firstdayofweek[, firstweekofyear]])
2370 sal_uInt16 nParCount = rPar.Count();
2371 if( nParCount < 3 || nParCount > 5 )
2373 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2374 return;
2377 OUString aStringCode = rPar.Get(1)->GetOUString();
2378 IntervalInfo const * pInfo = getIntervalInfo( aStringCode );
2379 if( !pInfo )
2381 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2382 return;
2385 double dDate = rPar.Get(2)->GetDate();
2387 sal_Int32 nRet = 0;
2388 switch( pInfo->meInterval )
2390 case INTERVAL_YYYY:
2392 nRet = implGetDateYear( dDate );
2393 break;
2395 case INTERVAL_Q:
2397 nRet = 1 + (implGetDateMonth( dDate ) - 1) / 3;
2398 break;
2400 case INTERVAL_M:
2402 nRet = implGetDateMonth( dDate );
2403 break;
2405 case INTERVAL_Y:
2407 sal_Int16 nYear = implGetDateYear( dDate );
2408 double dBaseDate;
2409 implDateSerial( nYear, 1, 1, dBaseDate );
2410 nRet = 1 + sal_Int32( dDate - dBaseDate );
2411 break;
2413 case INTERVAL_D:
2415 nRet = implGetDateDay( dDate );
2416 break;
2418 case INTERVAL_W:
2420 bool bFirstDay = false;
2421 sal_Int16 nFirstDay = 1; // Default
2422 if( nParCount >= 4 )
2424 nFirstDay = rPar.Get(3)->GetInteger();
2425 bFirstDay = true;
2427 nRet = implGetWeekDay( dDate, bFirstDay, nFirstDay );
2428 break;
2430 case INTERVAL_WW:
2432 sal_Int16 nFirstDay = 1; // Default
2433 if( nParCount >= 4 )
2434 nFirstDay = rPar.Get(3)->GetInteger();
2436 sal_Int16 nFirstWeek = 1; // Default
2437 if( nParCount == 5 )
2438 nFirstWeek = rPar.Get(4)->GetInteger();
2440 sal_Int16 nYear = implGetDateYear( dDate );
2441 bool bError = false;
2442 double dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear, nFirstDay, nFirstWeek, &bError );
2443 if( !bError )
2445 if( dYearFirstDay > dDate )
2447 // Date belongs to last year's week
2448 dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear - 1, nFirstDay, nFirstWeek );
2450 else if( nFirstWeek != 1 )
2452 // Check if date belongs to next year
2453 double dNextYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear + 1, nFirstDay, nFirstWeek );
2454 if( dDate >= dNextYearFirstDay )
2455 dYearFirstDay = dNextYearFirstDay;
2458 // Calculate week
2459 double dDiff = dDate - dYearFirstDay;
2460 nRet = 1 + sal_Int32( dDiff / 7 );
2462 break;
2464 case INTERVAL_H:
2466 nRet = implGetHour( dDate );
2467 break;
2469 case INTERVAL_N:
2471 nRet = implGetMinute( dDate );
2472 break;
2474 case INTERVAL_S:
2476 nRet = implGetSecond( dDate );
2477 break;
2480 rPar.Get(0)->PutLong( nRet );
2483 // FormatDateTime(Date[,NamedFormat])
2484 RTLFUNC(FormatDateTime)
2486 (void)pBasic;
2487 (void)bWrite;
2489 sal_uInt16 nParCount = rPar.Count();
2490 if( nParCount < 2 || nParCount > 3 )
2492 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2493 return;
2496 double dDate = rPar.Get(1)->GetDate();
2497 sal_Int16 nNamedFormat = 0;
2498 if( nParCount > 2 )
2500 nNamedFormat = rPar.Get(2)->GetInteger();
2501 if( nNamedFormat < 0 || nNamedFormat > 4 )
2503 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2504 return;
2508 Reference< XCalendar4 > xCalendar = getLocaleCalendar();
2509 if( !xCalendar.is() )
2511 StarBASIC::Error( SbERR_INTERNAL_ERROR );
2512 return;
2515 OUString aRetStr;
2516 SbxVariableRef pSbxVar = new SbxVariable( SbxSTRING );
2517 switch( nNamedFormat )
2519 // GeneralDate:
2520 // Display a date and/or time. If there is a date part,
2521 // display it as a short date. If there is a time part,
2522 // display it as a long time. If present, both parts are displayed.
2524 // 12/21/2004 11:24:50 AM
2525 // 21.12.2004 12:13:51
2526 case 0:
2527 pSbxVar->PutDate( dDate );
2528 aRetStr = pSbxVar->GetOUString();
2529 break;
2531 // LongDate: Display a date using the long date format specified
2532 // in your computer's regional settings.
2533 // Tuesday, December 21, 2004
2534 // Dienstag, 21. December 2004
2535 case 1:
2537 SvNumberFormatter* pFormatter = NULL;
2538 if( GetSbData()->pInst )
2540 pFormatter = GetSbData()->pInst->GetNumberFormatter();
2542 else
2544 sal_uInt32 n; // Dummy
2545 SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
2548 LanguageType eLangType = Application::GetSettings().GetLanguageTag().getLanguageType();
2549 sal_uIntPtr nIndex = pFormatter->GetFormatIndex( NF_DATE_SYSTEM_LONG, eLangType );
2550 Color* pCol;
2551 pFormatter->GetOutputString( dDate, nIndex, aRetStr, &pCol );
2553 if( !GetSbData()->pInst )
2555 delete pFormatter;
2557 break;
2560 // ShortDate: Display a date using the short date format specified
2561 // in your computer's regional settings.
2562 // 21.12.2004
2563 case 2:
2564 pSbxVar->PutDate( floor(dDate) );
2565 aRetStr = pSbxVar->GetOUString();
2566 break;
2568 // LongTime: Display a time using the time format specified
2569 // in your computer's regional settings.
2570 // 11:24:50 AM
2571 // 12:13:51
2572 case 3:
2573 // ShortTime: Display a time using the 24-hour format (hh:mm).
2574 // 11:24
2575 case 4:
2576 double n;
2577 double dTime = modf( dDate, &n );
2578 pSbxVar->PutDate( dTime );
2579 if( nNamedFormat == 3 )
2581 aRetStr = pSbxVar->GetOUString();
2583 else
2585 aRetStr = pSbxVar->GetOUString().copy( 0, 5 );
2587 break;
2590 rPar.Get(0)->PutString( aRetStr );
2593 RTLFUNC(Frac)
2595 (void)pBasic;
2596 (void)bWrite;
2598 sal_uInt16 nParCount = rPar.Count();
2599 if( nParCount != 2)
2601 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2602 return;
2605 SbxVariable *pSbxVariable = rPar.Get(1);
2606 double dVal = pSbxVariable->GetDouble();
2607 if(dVal >= 0)
2608 rPar.Get(0)->PutDouble(dVal - ::rtl::math::approxFloor(dVal));
2609 else
2610 rPar.Get(0)->PutDouble(dVal - ::rtl::math::approxCeil(dVal));
2613 RTLFUNC(Round)
2615 (void)pBasic;
2616 (void)bWrite;
2618 sal_uInt16 nParCount = rPar.Count();
2619 if( nParCount != 2 && nParCount != 3 )
2621 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2622 return;
2625 SbxVariable *pSbxVariable = rPar.Get(1);
2626 double dVal = pSbxVariable->GetDouble();
2627 double dRes = 0.0;
2628 if( dVal != 0.0 )
2630 bool bNeg = false;
2631 if( dVal < 0.0 )
2633 bNeg = true;
2634 dVal = -dVal;
2637 sal_Int16 numdecimalplaces = 0;
2638 if( nParCount == 3 )
2640 numdecimalplaces = rPar.Get(2)->GetInteger();
2641 if( numdecimalplaces < 0 || numdecimalplaces > 22 )
2643 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2644 return;
2648 if( numdecimalplaces == 0 )
2650 dRes = floor( dVal + 0.5 );
2652 else
2654 double dFactor = pow( 10.0, numdecimalplaces );
2655 dVal *= dFactor;
2656 dRes = floor( dVal + 0.5 );
2657 dRes /= dFactor;
2660 if( bNeg )
2661 dRes = -dRes;
2663 rPar.Get(0)->PutDouble( dRes );
2666 void CallFunctionAccessFunction( const Sequence< Any >& aArgs, const OUString& sFuncName, SbxVariable* pRet )
2668 static Reference< XFunctionAccess > xFunc;
2671 if ( !xFunc.is() )
2673 Reference< XMultiServiceFactory > xFactory( getProcessServiceFactory() );
2674 if( xFactory.is() )
2676 xFunc.set( xFactory->createInstance("com.sun.star.sheet.FunctionAccess"), UNO_QUERY_THROW);
2679 Any aRet = xFunc->callFunction( sFuncName, aArgs );
2681 unoToSbxValue( pRet, aRet );
2684 catch(const Exception& )
2686 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2690 RTLFUNC(SYD)
2692 (void)pBasic;
2693 (void)bWrite;
2695 sal_uLong nArgCount = rPar.Count()-1;
2697 if ( nArgCount < 4 )
2699 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2700 return;
2703 // retrieve non-optional params
2705 Sequence< Any > aParams( 4 );
2706 aParams[ 0 ] <<= makeAny( rPar.Get(1)->GetDouble() );
2707 aParams[ 1 ] <<= makeAny( rPar.Get(2)->GetDouble() );
2708 aParams[ 2 ] <<= makeAny( rPar.Get(3)->GetDouble() );
2709 aParams[ 3 ] <<= makeAny( rPar.Get(4)->GetDouble() );
2711 CallFunctionAccessFunction( aParams, "SYD", rPar.Get( 0 ) );
2714 RTLFUNC(SLN)
2716 (void)pBasic;
2717 (void)bWrite;
2719 sal_uLong nArgCount = rPar.Count()-1;
2721 if ( nArgCount < 3 )
2723 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2724 return;
2727 // retrieve non-optional params
2729 Sequence< Any > aParams( 3 );
2730 aParams[ 0 ] <<= makeAny( rPar.Get(1)->GetDouble() );
2731 aParams[ 1 ] <<= makeAny( rPar.Get(2)->GetDouble() );
2732 aParams[ 2 ] <<= makeAny( rPar.Get(3)->GetDouble() );
2734 CallFunctionAccessFunction( aParams, "SLN", rPar.Get( 0 ) );
2737 RTLFUNC(Pmt)
2739 (void)pBasic;
2740 (void)bWrite;
2742 sal_uLong nArgCount = rPar.Count()-1;
2744 if ( nArgCount < 3 || nArgCount > 5 )
2746 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2747 return;
2749 // retrieve non-optional params
2751 double rate = rPar.Get(1)->GetDouble();
2752 double nper = rPar.Get(2)->GetDouble();
2753 double pmt = rPar.Get(3)->GetDouble();
2755 // set default values for Optional args
2756 double fv = 0;
2757 double type = 0;
2759 // fv
2760 if ( nArgCount >= 4 )
2762 if( rPar.Get(4)->GetType() != SbxEMPTY )
2763 fv = rPar.Get(4)->GetDouble();
2765 // type
2766 if ( nArgCount >= 5 )
2768 if( rPar.Get(5)->GetType() != SbxEMPTY )
2769 type = rPar.Get(5)->GetDouble();
2772 Sequence< Any > aParams( 5 );
2773 aParams[ 0 ] <<= rate;
2774 aParams[ 1 ] <<= nper;
2775 aParams[ 2 ] <<= pmt;
2776 aParams[ 3 ] <<= fv;
2777 aParams[ 4 ] <<= type;
2779 CallFunctionAccessFunction( aParams, "Pmt", rPar.Get( 0 ) );
2782 RTLFUNC(PPmt)
2784 (void)pBasic;
2785 (void)bWrite;
2787 sal_uLong nArgCount = rPar.Count()-1;
2789 if ( nArgCount < 4 || nArgCount > 6 )
2791 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2792 return;
2794 // retrieve non-optional params
2796 double rate = rPar.Get(1)->GetDouble();
2797 double per = rPar.Get(2)->GetDouble();
2798 double nper = rPar.Get(3)->GetDouble();
2799 double pv = rPar.Get(4)->GetDouble();
2801 // set default values for Optional args
2802 double fv = 0;
2803 double type = 0;
2805 // fv
2806 if ( nArgCount >= 5 )
2808 if( rPar.Get(5)->GetType() != SbxEMPTY )
2809 fv = rPar.Get(5)->GetDouble();
2811 // type
2812 if ( nArgCount >= 6 )
2814 if( rPar.Get(6)->GetType() != SbxEMPTY )
2815 type = rPar.Get(6)->GetDouble();
2818 Sequence< Any > aParams( 6 );
2819 aParams[ 0 ] <<= rate;
2820 aParams[ 1 ] <<= per;
2821 aParams[ 2 ] <<= nper;
2822 aParams[ 3 ] <<= pv;
2823 aParams[ 4 ] <<= fv;
2824 aParams[ 5 ] <<= type;
2826 CallFunctionAccessFunction( aParams, "PPmt", rPar.Get( 0 ) );
2829 RTLFUNC(PV)
2831 (void)pBasic;
2832 (void)bWrite;
2834 sal_uLong nArgCount = rPar.Count()-1;
2836 if ( nArgCount < 3 || nArgCount > 5 )
2838 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2839 return;
2841 // retrieve non-optional params
2843 double rate = rPar.Get(1)->GetDouble();
2844 double nper = rPar.Get(2)->GetDouble();
2845 double pmt = rPar.Get(3)->GetDouble();
2847 // set default values for Optional args
2848 double fv = 0;
2849 double type = 0;
2851 // fv
2852 if ( nArgCount >= 4 )
2854 if( rPar.Get(4)->GetType() != SbxEMPTY )
2855 fv = rPar.Get(4)->GetDouble();
2857 // type
2858 if ( nArgCount >= 5 )
2860 if( rPar.Get(5)->GetType() != SbxEMPTY )
2861 type = rPar.Get(5)->GetDouble();
2864 Sequence< Any > aParams( 5 );
2865 aParams[ 0 ] <<= rate;
2866 aParams[ 1 ] <<= nper;
2867 aParams[ 2 ] <<= pmt;
2868 aParams[ 3 ] <<= fv;
2869 aParams[ 4 ] <<= type;
2871 CallFunctionAccessFunction( aParams, "PV", rPar.Get( 0 ) );
2874 RTLFUNC(NPV)
2876 (void)pBasic;
2877 (void)bWrite;
2879 sal_uLong nArgCount = rPar.Count()-1;
2881 if ( nArgCount < 1 || nArgCount > 2 )
2883 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2884 return;
2887 Sequence< Any > aParams( 2 );
2888 aParams[ 0 ] <<= makeAny( rPar.Get(1)->GetDouble() );
2889 Any aValues = sbxToUnoValue( rPar.Get(2),
2890 cppu::UnoType<Sequence<double>>::get() );
2892 // convert for calc functions
2893 Sequence< Sequence< double > > sValues(1);
2894 aValues >>= sValues[ 0 ];
2895 aValues <<= sValues;
2897 aParams[ 1 ] <<= aValues;
2899 CallFunctionAccessFunction( aParams, "NPV", rPar.Get( 0 ) );
2902 RTLFUNC(NPer)
2904 (void)pBasic;
2905 (void)bWrite;
2907 sal_uLong nArgCount = rPar.Count()-1;
2909 if ( nArgCount < 3 || nArgCount > 5 )
2911 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2912 return;
2914 // retrieve non-optional params
2916 double rate = rPar.Get(1)->GetDouble();
2917 double pmt = rPar.Get(2)->GetDouble();
2918 double pv = rPar.Get(3)->GetDouble();
2920 // set default values for Optional args
2921 double fv = 0;
2922 double type = 0;
2924 // fv
2925 if ( nArgCount >= 4 )
2927 if( rPar.Get(4)->GetType() != SbxEMPTY )
2928 fv = rPar.Get(4)->GetDouble();
2930 // type
2931 if ( nArgCount >= 5 )
2933 if( rPar.Get(5)->GetType() != SbxEMPTY )
2934 type = rPar.Get(5)->GetDouble();
2937 Sequence< Any > aParams( 5 );
2938 aParams[ 0 ] <<= rate;
2939 aParams[ 1 ] <<= pmt;
2940 aParams[ 2 ] <<= pv;
2941 aParams[ 3 ] <<= fv;
2942 aParams[ 4 ] <<= type;
2944 CallFunctionAccessFunction( aParams, "NPer", rPar.Get( 0 ) );
2947 RTLFUNC(MIRR)
2949 (void)pBasic;
2950 (void)bWrite;
2952 sal_uLong nArgCount = rPar.Count()-1;
2954 if ( nArgCount < 3 )
2956 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2957 return;
2960 // retrieve non-optional params
2962 Sequence< Any > aParams( 3 );
2963 Any aValues = sbxToUnoValue( rPar.Get(1),
2964 cppu::UnoType<Sequence<double>>::get() );
2966 // convert for calc functions
2967 Sequence< Sequence< double > > sValues(1);
2968 aValues >>= sValues[ 0 ];
2969 aValues <<= sValues;
2971 aParams[ 0 ] <<= aValues;
2972 aParams[ 1 ] <<= makeAny( rPar.Get(2)->GetDouble() );
2973 aParams[ 2 ] <<= makeAny( rPar.Get(3)->GetDouble() );
2975 CallFunctionAccessFunction( aParams, "MIRR", rPar.Get( 0 ) );
2978 RTLFUNC(IRR)
2980 (void)pBasic;
2981 (void)bWrite;
2983 sal_uLong nArgCount = rPar.Count()-1;
2985 if ( nArgCount < 1 || nArgCount > 2 )
2987 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2988 return;
2990 // retrieve non-optional params
2991 Any aValues = sbxToUnoValue( rPar.Get(1),
2992 cppu::UnoType<Sequence<double>>::get() );
2994 // convert for calc functions
2995 Sequence< Sequence< double > > sValues(1);
2996 aValues >>= sValues[ 0 ];
2997 aValues <<= sValues;
2999 // set default values for Optional args
3000 double guess = 0.1;
3001 // guess
3002 if ( nArgCount >= 2 )
3004 if( rPar.Get(2)->GetType() != SbxEMPTY )
3005 guess = rPar.Get(2)->GetDouble();
3008 Sequence< Any > aParams( 2 );
3009 aParams[ 0 ] <<= aValues;
3010 aParams[ 1 ] <<= guess;
3012 CallFunctionAccessFunction( aParams, "IRR", rPar.Get( 0 ) );
3015 RTLFUNC(IPmt)
3017 (void)pBasic;
3018 (void)bWrite;
3020 sal_uLong nArgCount = rPar.Count()-1;
3022 if ( nArgCount < 4 || nArgCount > 6 )
3024 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3025 return;
3027 // retrieve non-optional params
3029 double rate = rPar.Get(1)->GetDouble();
3030 double per = rPar.Get(2)->GetInteger();
3031 double nper = rPar.Get(3)->GetDouble();
3032 double pv = rPar.Get(4)->GetDouble();
3034 // set default values for Optional args
3035 double fv = 0;
3036 double type = 0;
3038 // fv
3039 if ( nArgCount >= 5 )
3041 if( rPar.Get(5)->GetType() != SbxEMPTY )
3042 fv = rPar.Get(5)->GetDouble();
3044 // type
3045 if ( nArgCount >= 6 )
3047 if( rPar.Get(6)->GetType() != SbxEMPTY )
3048 type = rPar.Get(6)->GetDouble();
3051 Sequence< Any > aParams( 6 );
3052 aParams[ 0 ] <<= rate;
3053 aParams[ 1 ] <<= per;
3054 aParams[ 2 ] <<= nper;
3055 aParams[ 3 ] <<= pv;
3056 aParams[ 4 ] <<= fv;
3057 aParams[ 5 ] <<= type;
3059 CallFunctionAccessFunction( aParams, "IPmt", rPar.Get( 0 ) );
3062 RTLFUNC(FV)
3064 (void)pBasic;
3065 (void)bWrite;
3067 sal_uLong nArgCount = rPar.Count()-1;
3069 if ( nArgCount < 3 || nArgCount > 5 )
3071 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3072 return;
3074 // retrieve non-optional params
3076 double rate = rPar.Get(1)->GetDouble();
3077 double nper = rPar.Get(2)->GetDouble();
3078 double pmt = rPar.Get(3)->GetDouble();
3080 // set default values for Optional args
3081 double pv = 0;
3082 double type = 0;
3084 // pv
3085 if ( nArgCount >= 4 )
3087 if( rPar.Get(4)->GetType() != SbxEMPTY )
3088 pv = rPar.Get(4)->GetDouble();
3090 // type
3091 if ( nArgCount >= 5 )
3093 if( rPar.Get(5)->GetType() != SbxEMPTY )
3094 type = rPar.Get(5)->GetDouble();
3097 Sequence< Any > aParams( 5 );
3098 aParams[ 0 ] <<= rate;
3099 aParams[ 1 ] <<= nper;
3100 aParams[ 2 ] <<= pmt;
3101 aParams[ 3 ] <<= pv;
3102 aParams[ 4 ] <<= type;
3104 CallFunctionAccessFunction( aParams, "FV", rPar.Get( 0 ) );
3107 RTLFUNC(DDB)
3109 (void)pBasic;
3110 (void)bWrite;
3112 sal_uLong nArgCount = rPar.Count()-1;
3114 if ( nArgCount < 4 || nArgCount > 5 )
3116 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3117 return;
3119 // retrieve non-optional params
3121 double cost = rPar.Get(1)->GetDouble();
3122 double salvage = rPar.Get(2)->GetDouble();
3123 double life = rPar.Get(3)->GetDouble();
3124 double period = rPar.Get(4)->GetDouble();
3126 // set default values for Optional args
3127 double factor = 2;
3129 // factor
3130 if ( nArgCount >= 5 )
3132 if( rPar.Get(5)->GetType() != SbxEMPTY )
3133 factor = rPar.Get(5)->GetDouble();
3136 Sequence< Any > aParams( 5 );
3137 aParams[ 0 ] <<= cost;
3138 aParams[ 1 ] <<= salvage;
3139 aParams[ 2 ] <<= life;
3140 aParams[ 3 ] <<= period;
3141 aParams[ 4 ] <<= factor;
3143 CallFunctionAccessFunction( aParams, "DDB", rPar.Get( 0 ) );
3146 RTLFUNC(Rate)
3148 (void)pBasic;
3149 (void)bWrite;
3151 sal_uLong nArgCount = rPar.Count()-1;
3153 if ( nArgCount < 3 || nArgCount > 6 )
3155 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3156 return;
3158 // retrieve non-optional params
3160 double nper = 0;
3161 double pmt = 0;
3162 double pv = 0;
3164 nper = rPar.Get(1)->GetDouble();
3165 pmt = rPar.Get(2)->GetDouble();
3166 pv = rPar.Get(3)->GetDouble();
3168 // set default values for Optional args
3169 double fv = 0;
3170 double type = 0;
3171 double guess = 0.1;
3173 // fv
3174 if ( nArgCount >= 4 )
3176 if( rPar.Get(4)->GetType() != SbxEMPTY )
3177 fv = rPar.Get(4)->GetDouble();
3180 // type
3181 if ( nArgCount >= 5 )
3183 if( rPar.Get(5)->GetType() != SbxEMPTY )
3184 type = rPar.Get(5)->GetDouble();
3187 // guess
3188 if ( nArgCount >= 6 )
3190 if( rPar.Get(6)->GetType() != SbxEMPTY )
3191 type = rPar.Get(6)->GetDouble();
3194 Sequence< Any > aParams( 6 );
3195 aParams[ 0 ] <<= nper;
3196 aParams[ 1 ] <<= pmt;
3197 aParams[ 2 ] <<= pv;
3198 aParams[ 3 ] <<= fv;
3199 aParams[ 4 ] <<= type;
3200 aParams[ 5 ] <<= guess;
3202 CallFunctionAccessFunction( aParams, "Rate", rPar.Get( 0 ) );
3205 RTLFUNC(StrReverse)
3207 (void)pBasic;
3208 (void)bWrite;
3210 if ( rPar.Count() != 2 )
3212 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3213 return;
3216 SbxVariable *pSbxVariable = rPar.Get(1);
3217 if( pSbxVariable->IsNull() )
3219 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3220 return;
3223 OUString aStr = comphelper::string::reverseString(pSbxVariable->GetOUString());
3224 rPar.Get(0)->PutString( aStr );
3227 RTLFUNC(CompatibilityMode)
3229 (void)pBasic;
3230 (void)bWrite;
3232 bool bEnabled = false;
3233 sal_uInt16 nCount = rPar.Count();
3234 if ( nCount != 1 && nCount != 2 )
3235 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3237 SbiInstance* pInst = GetSbData()->pInst;
3238 if( pInst )
3240 if ( nCount == 2 )
3242 pInst->EnableCompatibility( rPar.Get(1)->GetBool() );
3244 bEnabled = pInst->IsCompatibility();
3246 rPar.Get(0)->PutBool( bEnabled );
3249 RTLFUNC(Input)
3251 (void)pBasic;
3252 (void)bWrite;
3254 // 2 parameters needed
3255 if ( rPar.Count() < 3 )
3257 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3258 return;
3261 sal_uInt16 nByteCount = rPar.Get(1)->GetUShort();
3262 sal_Int16 nFileNumber = rPar.Get(2)->GetInteger();
3264 SbiIoSystem* pIosys = GetSbData()->pInst->GetIoSystem();
3265 SbiStream* pSbStrm = pIosys->GetStream( nFileNumber );
3266 if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_INPUT)) )
3268 StarBASIC::Error( SbERR_BAD_CHANNEL );
3269 return;
3272 OString aByteBuffer;
3273 SbError err = pSbStrm->Read( aByteBuffer, nByteCount, true );
3274 if( !err )
3275 err = pIosys->GetError();
3277 if( err )
3279 StarBASIC::Error( err );
3280 return;
3282 rPar.Get(0)->PutString(OStringToOUString(aByteBuffer, osl_getThreadTextEncoding()));
3285 RTLFUNC(Me)
3287 (void)pBasic;
3288 (void)bWrite;
3290 SbModule* pActiveModule = GetSbData()->pInst->GetActiveModule();
3291 SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pActiveModule);
3292 SbxVariableRef refVar = rPar.Get(0);
3293 if( pClassModuleObject == NULL )
3295 SbObjModule* pMod = PTR_CAST(SbObjModule,pActiveModule);
3296 if ( pMod )
3297 refVar->PutObject( pMod );
3298 else
3299 StarBASIC::Error( SbERR_INVALID_USAGE_OBJECT );
3301 else
3302 refVar->PutObject( pClassModuleObject );
3305 #endif
3307 sal_Int16 implGetWeekDay( double aDate, bool bFirstDayParam, sal_Int16 nFirstDay )
3309 Date aRefDate( 1,1,1900 );
3310 long nDays = (long) aDate;
3311 nDays -= 2; // normalize: 1.1.1900 => 0
3312 aRefDate += nDays;
3313 DayOfWeek aDay = aRefDate.GetDayOfWeek();
3314 sal_Int16 nDay;
3315 if ( aDay != SUNDAY )
3316 nDay = (sal_Int16)aDay + 2;
3317 else
3318 nDay = 1; // 1 == Sunday
3320 // #117253 optional 2nd parameter "firstdayofweek"
3321 if( bFirstDayParam )
3323 if( nFirstDay < 0 || nFirstDay > 7 )
3325 #if HAVE_FEATURE_SCRIPTING
3326 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3327 #endif
3328 return 0;
3330 if( nFirstDay == 0 )
3332 Reference< XCalendar4 > xCalendar = getLocaleCalendar();
3333 if( !xCalendar.is() )
3335 #if HAVE_FEATURE_SCRIPTING
3336 StarBASIC::Error( SbERR_INTERNAL_ERROR );
3337 #endif
3338 return 0;
3340 nFirstDay = sal_Int16( xCalendar->getFirstDayOfWeek() + 1 );
3342 nDay = 1 + (nDay + 7 - nFirstDay) % 7;
3344 return nDay;
3347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */