update dev300-m58
[ooovba.git] / basic / source / runtime / methods1.cxx
blob9bacf3102c5900a5cfcfc7d26492d97f379d8739
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: methods1.cxx,v $
10 * $Revision: 1.38 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #if defined(WIN)
35 #include <string.h>
36 #else
37 #include <stdlib.h> // getenv
38 #endif
39 #include <vcl/svapp.hxx>
40 #include <vcl/mapmod.hxx>
41 #include <vcl/wrkwin.hxx>
42 #include <vcl/timer.hxx>
43 #include <basic/sbxvar.hxx>
44 #ifndef _SBX_HXX
45 #include <basic/sbx.hxx>
46 #endif
47 #include <basic/sbstar.hxx>
48 #include <svtools/zforlist.hxx>
49 #include <tools/fsys.hxx>
50 #include <tools/urlobj.hxx>
51 #include <osl/file.hxx>
53 #ifdef OS2
54 #define INCL_DOS
55 #define INCL_DOSPROCESS
56 #include <svpm.h>
57 #endif
59 #if defined(WIN)
60 #include <tools/svwin.h>
61 #endif
63 #ifndef CLK_TCK
64 #define CLK_TCK CLOCKS_PER_SEC
65 #endif
67 #include <vcl/jobset.hxx>
68 #include <basic/sbobjmod.hxx>
70 #include "sbintern.hxx"
71 #include "runtime.hxx"
72 #include "stdobj.hxx"
73 #include "rtlproto.hxx"
74 #include "dllmgr.hxx"
75 #include <iosys.hxx>
76 #include "sbunoobj.hxx"
77 #include "propacc.hxx"
80 #include <comphelper/processfactory.hxx>
82 #include <com/sun/star/uno/Sequence.hxx>
83 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
84 #include <com/sun/star/i18n/XCalendar.hpp>
85 #include <com/sun/star/sheet/XFunctionAccess.hpp>
87 using namespace comphelper;
88 using namespace com::sun::star::sheet;
89 using namespace com::sun::star::uno;
90 using namespace com::sun::star::i18n;
92 void unoToSbxValue( SbxVariable* pVar, const Any& aValue );
93 Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, com::sun::star::beans::Property* pUnoProperty = NULL );
95 static Reference< XCalendar > getLocaleCalendar( void )
97 static Reference< XCalendar > xCalendar;
98 if( !xCalendar.is() )
100 Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
101 if( xSMgr.is() )
103 xCalendar = Reference< XCalendar >( xSMgr->createInstance
104 ( ::rtl::OUString::createFromAscii( "com.sun.star.i18n.LocaleCalendar" ) ), UNO_QUERY );
108 static com::sun::star::lang::Locale aLastLocale;
109 static bool bNeedsInit = true;
111 com::sun::star::lang::Locale aLocale = Application::GetSettings().GetLocale();
112 bool bNeedsReload = false;
113 if( bNeedsInit )
115 bNeedsInit = false;
116 bNeedsReload = true;
118 else if( aLocale.Language != aLastLocale.Language ||
119 aLocale.Country != aLastLocale.Country )
121 bNeedsReload = true;
123 if( bNeedsReload )
125 aLastLocale = aLocale;
126 xCalendar->loadDefaultCalendar( aLocale );
128 return xCalendar;
132 RTLFUNC(CBool) // JSM
134 (void)pBasic;
135 (void)bWrite;
137 BOOL bVal = FALSE;
138 if ( rPar.Count() == 2 )
140 SbxVariable *pSbxVariable = rPar.Get(1);
141 bVal = pSbxVariable->GetBool();
143 else
144 StarBASIC::Error( SbERR_BAD_ARGUMENT );
146 rPar.Get(0)->PutBool(bVal);
149 RTLFUNC(CByte) // JSM
151 (void)pBasic;
152 (void)bWrite;
154 BYTE nByte = 0;
155 if ( rPar.Count() == 2 )
157 SbxVariable *pSbxVariable = rPar.Get(1);
158 nByte = pSbxVariable->GetByte();
160 else
161 StarBASIC::Error( SbERR_BAD_ARGUMENT );
163 rPar.Get(0)->PutByte(nByte);
166 RTLFUNC(CCur) // JSM
168 (void)pBasic;
169 (void)bWrite;
171 SbxINT64 nCur;
172 if ( rPar.Count() == 2 )
174 SbxVariable *pSbxVariable = rPar.Get(1);
175 nCur = pSbxVariable->GetCurrency();
177 else
178 StarBASIC::Error( SbERR_BAD_ARGUMENT );
180 rPar.Get(0)->PutCurrency( nCur );
183 RTLFUNC(CDec) // JSM
185 (void)pBasic;
186 (void)bWrite;
188 #ifdef WNT
189 SbxDecimal* pDec = NULL;
190 if ( rPar.Count() == 2 )
192 SbxVariable *pSbxVariable = rPar.Get(1);
193 pDec = pSbxVariable->GetDecimal();
195 else
196 StarBASIC::Error( SbERR_BAD_ARGUMENT );
198 rPar.Get(0)->PutDecimal( pDec );
199 #else
200 rPar.Get(0)->PutEmpty();
201 StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
202 #endif
205 RTLFUNC(CDate) // JSM
207 (void)pBasic;
208 (void)bWrite;
210 double nVal = 0.0;
211 if ( rPar.Count() == 2 )
213 SbxVariable *pSbxVariable = rPar.Get(1);
214 nVal = pSbxVariable->GetDate();
216 else
217 StarBASIC::Error( SbERR_BAD_ARGUMENT );
219 rPar.Get(0)->PutDate(nVal);
222 RTLFUNC(CDbl) // JSM
224 (void)pBasic;
225 (void)bWrite;
227 double nVal = 0.0;
228 if ( rPar.Count() == 2 )
230 SbxVariable *pSbxVariable = rPar.Get(1);
231 if( pSbxVariable->GetType() == SbxSTRING )
233 // AB #41690 , String holen
234 String aScanStr = pSbxVariable->GetString();
235 SbError Error = SbxValue::ScanNumIntnl( aScanStr, nVal );
236 if( Error != SbxERR_OK )
237 StarBASIC::Error( Error );
239 else
241 nVal = pSbxVariable->GetDouble();
244 else
245 StarBASIC::Error( SbERR_BAD_ARGUMENT );
247 rPar.Get(0)->PutDouble(nVal);
250 RTLFUNC(CInt) // JSM
252 (void)pBasic;
253 (void)bWrite;
255 INT16 nVal = 0;
256 if ( rPar.Count() == 2 )
258 SbxVariable *pSbxVariable = rPar.Get(1);
259 nVal = pSbxVariable->GetInteger();
261 else
262 StarBASIC::Error( SbERR_BAD_ARGUMENT );
264 rPar.Get(0)->PutInteger(nVal);
267 RTLFUNC(CLng) // JSM
269 (void)pBasic;
270 (void)bWrite;
272 INT32 nVal = 0;
273 if ( rPar.Count() == 2 )
275 SbxVariable *pSbxVariable = rPar.Get(1);
276 nVal = pSbxVariable->GetLong();
278 else
279 StarBASIC::Error( SbERR_BAD_ARGUMENT );
281 rPar.Get(0)->PutLong(nVal);
284 RTLFUNC(CSng) // JSM
286 (void)pBasic;
287 (void)bWrite;
289 float nVal = (float)0.0;
290 if ( rPar.Count() == 2 )
292 SbxVariable *pSbxVariable = rPar.Get(1);
293 if( pSbxVariable->GetType() == SbxSTRING )
295 // AB #41690 , String holen
296 double dVal = 0.0;
297 String aScanStr = pSbxVariable->GetString();
298 SbError Error = SbxValue::ScanNumIntnl( aScanStr, dVal, /*bSingle=*/TRUE );
299 if( SbxBase::GetError() == SbxERR_OK && Error != SbxERR_OK )
300 StarBASIC::Error( Error );
301 nVal = (float)dVal;
303 else
305 nVal = pSbxVariable->GetSingle();
308 else
309 StarBASIC::Error( SbERR_BAD_ARGUMENT );
311 rPar.Get(0)->PutSingle(nVal);
314 RTLFUNC(CStr) // JSM
316 (void)pBasic;
317 (void)bWrite;
319 String aString;
320 if ( rPar.Count() == 2 )
322 SbxVariable *pSbxVariable = rPar.Get(1);
323 aString = pSbxVariable->GetString();
325 else
326 StarBASIC::Error( SbERR_BAD_ARGUMENT );
328 rPar.Get(0)->PutString(aString);
331 RTLFUNC(CVar) // JSM
333 (void)pBasic;
334 (void)bWrite;
336 SbxValues aVals( SbxVARIANT );
337 if ( rPar.Count() == 2 )
339 SbxVariable *pSbxVariable = rPar.Get(1);
340 pSbxVariable->Get( aVals );
342 else
343 StarBASIC::Error( SbERR_BAD_ARGUMENT );
345 rPar.Get(0)->Put( aVals );
348 RTLFUNC(CVErr)
350 (void)pBasic;
351 (void)bWrite;
353 INT16 nErrCode = 0;
354 if ( rPar.Count() == 2 )
356 SbxVariable *pSbxVariable = rPar.Get(1);
357 nErrCode = pSbxVariable->GetInteger();
359 else
360 StarBASIC::Error( SbERR_BAD_ARGUMENT );
362 rPar.Get(0)->PutErr( nErrCode );
365 RTLFUNC(Iif) // JSM
367 (void)pBasic;
368 (void)bWrite;
370 if ( rPar.Count() == 4 )
372 if (rPar.Get(1)->GetBool())
373 *rPar.Get(0) = *rPar.Get(2);
374 else
375 *rPar.Get(0) = *rPar.Get(3);
377 else
378 StarBASIC::Error( SbERR_BAD_ARGUMENT );
381 RTLFUNC(GetSystemType)
383 (void)pBasic;
384 (void)bWrite;
386 if ( rPar.Count() != 1 )
387 StarBASIC::Error( SbERR_BAD_ARGUMENT );
388 else
389 // Removed for SRC595
390 rPar.Get(0)->PutInteger( -1 );
393 RTLFUNC(GetGUIType)
395 (void)pBasic;
396 (void)bWrite;
398 if ( rPar.Count() != 1 )
399 StarBASIC::Error( SbERR_BAD_ARGUMENT );
400 else
402 // 17.7.2000 Make simple solution for testtool / fat office
403 #if defined (WNT)
404 rPar.Get(0)->PutInteger( 1 );
405 #elif defined OS2
406 rPar.Get(0)->PutInteger( 2 );
407 #elif defined UNX
408 rPar.Get(0)->PutInteger( 4 );
409 #else
410 rPar.Get(0)->PutInteger( -1 );
411 #endif
415 RTLFUNC(Red)
417 (void)pBasic;
418 (void)bWrite;
420 if ( rPar.Count() != 2 )
421 StarBASIC::Error( SbERR_BAD_ARGUMENT );
422 else
424 ULONG nRGB = (ULONG)rPar.Get(1)->GetLong();
425 nRGB &= 0x00FF0000;
426 nRGB >>= 16;
427 rPar.Get(0)->PutInteger( (INT16)nRGB );
431 RTLFUNC(Green)
433 (void)pBasic;
434 (void)bWrite;
436 if ( rPar.Count() != 2 )
437 StarBASIC::Error( SbERR_BAD_ARGUMENT );
438 else
440 ULONG nRGB = (ULONG)rPar.Get(1)->GetLong();
441 nRGB &= 0x0000FF00;
442 nRGB >>= 8;
443 rPar.Get(0)->PutInteger( (INT16)nRGB );
447 RTLFUNC(Blue)
449 (void)pBasic;
450 (void)bWrite;
452 if ( rPar.Count() != 2 )
453 StarBASIC::Error( SbERR_BAD_ARGUMENT );
454 else
456 ULONG nRGB = (ULONG)rPar.Get(1)->GetLong();
457 nRGB &= 0x000000FF;
458 rPar.Get(0)->PutInteger( (INT16)nRGB );
463 RTLFUNC(Switch)
465 (void)pBasic;
466 (void)bWrite;
468 USHORT nCount = rPar.Count();
469 if( !(nCount & 0x0001 ))
470 // Anzahl der Argumente muss ungerade sein
471 StarBASIC::Error( SbERR_BAD_ARGUMENT );
472 USHORT nCurExpr = 1;
473 while( nCurExpr < (nCount-1) )
475 if( rPar.Get( nCurExpr )->GetBool())
477 (*rPar.Get(0)) = *(rPar.Get(nCurExpr+1));
478 return;
480 nCurExpr += 2;
482 rPar.Get(0)->PutNull();
485 //i#64882# Common wait impl for existing Wait and new WaitUntil
486 // rtl functions
487 void Wait_Impl( bool bDurationBased, SbxArray& rPar )
489 if( rPar.Count() != 2 )
491 StarBASIC::Error( SbERR_BAD_ARGUMENT );
492 return;
494 long nWait = 0;
495 if ( bDurationBased )
497 double dWait = rPar.Get(1)->GetDouble();
498 double dNow = Now_Impl();
499 double dSecs = (double)( ( dWait - dNow ) * (double)( 24.0*3600.0) );
500 nWait = (long)( dSecs * 1000 ); // wait in thousands of sec
502 else
503 nWait = rPar.Get(1)->GetLong();
504 if( nWait < 0 )
506 StarBASIC::Error( SbERR_BAD_ARGUMENT );
507 return;
510 Timer aTimer;
511 aTimer.SetTimeout( nWait );
512 aTimer.Start();
513 while ( aTimer.IsActive() )
514 Application::Yield();
517 //i#64882#
518 RTLFUNC(Wait)
520 (void)pBasic;
521 (void)bWrite;
522 Wait_Impl( false, rPar );
525 //i#64882# add new WaitUntil ( for application.wait )
526 // share wait_impl with 'normal' oobasic wait
527 RTLFUNC(WaitUntil)
529 (void)pBasic;
530 (void)bWrite;
531 Wait_Impl( true, rPar );
534 RTLFUNC(GetGUIVersion)
536 (void)pBasic;
537 (void)bWrite;
539 if ( rPar.Count() != 1 )
540 StarBASIC::Error( SbERR_BAD_ARGUMENT );
541 else
543 // Removed for SRC595
544 rPar.Get(0)->PutLong( -1 );
548 RTLFUNC(Choose)
550 (void)pBasic;
551 (void)bWrite;
553 if ( rPar.Count() < 2 )
554 StarBASIC::Error( SbERR_BAD_ARGUMENT );
555 INT16 nIndex = rPar.Get(1)->GetInteger();
556 USHORT nCount = rPar.Count();
557 nCount--;
558 if( nCount == 1 || nIndex > (nCount-1) || nIndex < 1 )
560 rPar.Get(0)->PutNull();
561 return;
563 (*rPar.Get(0)) = *(rPar.Get(nIndex+1));
567 RTLFUNC(Trim)
569 (void)pBasic;
570 (void)bWrite;
572 if ( rPar.Count() < 2 )
573 StarBASIC::Error( SbERR_BAD_ARGUMENT );
574 else
576 String aStr( rPar.Get(1)->GetString() );
577 aStr.EraseLeadingChars();
578 aStr.EraseTrailingChars();
579 rPar.Get(0)->PutString( aStr );
583 RTLFUNC(GetSolarVersion)
585 (void)pBasic;
586 (void)bWrite;
588 rPar.Get(0)->PutLong( (INT32)SUPD );
591 RTLFUNC(TwipsPerPixelX)
593 (void)pBasic;
594 (void)bWrite;
596 INT32 nResult = 0;
597 Size aSize( 100,0 );
598 MapMode aMap( MAP_TWIP );
599 OutputDevice* pDevice = Application::GetDefaultDevice();
600 if( pDevice )
602 aSize = pDevice->PixelToLogic( aSize, aMap );
603 nResult = aSize.Width() / 100;
605 rPar.Get(0)->PutLong( nResult );
608 RTLFUNC(TwipsPerPixelY)
610 (void)pBasic;
611 (void)bWrite;
613 INT32 nResult = 0;
614 Size aSize( 0,100 );
615 MapMode aMap( MAP_TWIP );
616 OutputDevice* pDevice = Application::GetDefaultDevice();
617 if( pDevice )
619 aSize = pDevice->PixelToLogic( aSize, aMap );
620 nResult = aSize.Height() / 100;
622 rPar.Get(0)->PutLong( nResult );
626 RTLFUNC(FreeLibrary)
628 (void)pBasic;
629 (void)bWrite;
631 if ( rPar.Count() != 2 )
632 StarBASIC::Error( SbERR_BAD_ARGUMENT );
633 ByteString aByteDLLName( rPar.Get(1)->GetString(), gsl_getSystemTextEncoding() );
634 pINST->GetDllMgr()->FreeDll( aByteDLLName );
636 bool IsBaseIndexOne()
638 bool result = false;
639 if ( pINST && pINST->pRun )
641 USHORT res = pINST->pRun->GetBase();
642 if ( res )
643 result = true;
645 return result;
648 RTLFUNC(Array)
650 (void)pBasic;
651 (void)bWrite;
653 SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
654 USHORT nArraySize = rPar.Count() - 1;
656 // Option Base zunaechst ignorieren (kennt leider nur der Compiler)
657 bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
658 if( nArraySize )
660 if ( bIncIndex )
661 pArray->AddDim( 1, nArraySize );
662 else
663 pArray->AddDim( 0, nArraySize-1 );
665 else
667 pArray->unoAddDim( 0, -1 );
670 // Parameter ins Array uebernehmen
671 for( short i = 0 ; i < nArraySize ; i++ )
673 SbxVariable* pVar = rPar.Get(i+1);
674 SbxVariable* pNew = new SbxVariable( *pVar );
675 pNew->SetFlag( SBX_WRITE );
676 short index = i;
677 if ( bIncIndex )
678 ++index;
679 pArray->Put( pNew, &index );
682 // Array zurueckliefern
683 SbxVariableRef refVar = rPar.Get(0);
684 USHORT nFlags = refVar->GetFlags();
685 refVar->ResetFlag( SBX_FIXED );
686 refVar->PutObject( pArray );
687 refVar->SetFlags( nFlags );
688 refVar->SetParameters( NULL );
692 // Featurewunsch #57868
693 // Die Funktion liefert ein Variant-Array, wenn keine Parameter angegeben
694 // werden, wird ein leeres Array erzeugt (entsprechend dim a(), entspricht
695 // einer Sequence der Laenge 0 in Uno).
696 // Wenn Parameter angegeben sind, wird fuer jeden eine Dimension erzeugt
697 // DimArray( 2, 2, 4 ) entspricht DIM a( 2, 2, 4 )
698 // Das Array ist immer vom Typ Variant
699 RTLFUNC(DimArray)
701 (void)pBasic;
702 (void)bWrite;
704 SbxDimArray * pArray = new SbxDimArray( SbxVARIANT );
705 USHORT nArrayDims = rPar.Count() - 1;
706 if( nArrayDims > 0 )
708 for( USHORT i = 0; i < nArrayDims ; i++ )
710 INT32 ub = rPar.Get(i+1)->GetLong();
711 if( ub < 0 )
713 StarBASIC::Error( SbERR_OUT_OF_RANGE );
714 ub = 0;
716 pArray->AddDim32( 0, ub );
719 else
720 pArray->unoAddDim( 0, -1 );
722 // Array zurueckliefern
723 SbxVariableRef refVar = rPar.Get(0);
724 USHORT nFlags = refVar->GetFlags();
725 refVar->ResetFlag( SBX_FIXED );
726 refVar->PutObject( pArray );
727 refVar->SetFlags( nFlags );
728 refVar->SetParameters( NULL );
732 * FindObject und FindPropertyObject ermoeglichen es,
733 * Objekte und Properties vom Typ Objekt zur Laufzeit
734 * ueber ihren Namen als String-Parameter anzusprechen.
736 * Bsp.:
737 * MyObj.Prop1.Bla = 5
739 * entspricht:
740 * dim ObjVar as Object
741 * dim ObjProp as Object
742 * ObjName$ = "MyObj"
743 * ObjVar = FindObject( ObjName$ )
744 * PropName$ = "Prop1"
745 * ObjProp = FindPropertyObject( ObjVar, PropName$ )
746 * ObjProp.Bla = 5
748 * Dabei koennen die Namen zur Laufzeit dynamisch
749 * erzeugt werden und, so dass z.B. ueber Controls
750 * "TextEdit1" bis "TextEdit5" in einem Dialog in
751 * einer Schleife iteriert werden kann.
754 // Objekt ueber den Namen ansprechen
755 // 1. Parameter = Name des Objekts als String
756 RTLFUNC(FindObject)
758 (void)pBasic;
759 (void)bWrite;
761 // Wir brauchen einen Parameter
762 if ( rPar.Count() < 2 )
764 StarBASIC::Error( SbERR_BAD_ARGUMENT );
765 return;
768 // 1. Parameter ist der Name
769 String aNameStr = rPar.Get(1)->GetString();
771 // Basic-Suchfunktion benutzen
772 SbxBase* pFind = StarBASIC::FindSBXInCurrentScope( aNameStr );
773 SbxObject* pFindObj = NULL;
774 if( pFind )
775 pFindObj = PTR_CAST(SbxObject,pFind);
777 if( !pFindObj )
779 StarBASIC::Error( SbERR_VAR_UNDEFINED );
780 return;
784 // Objekt zurueckliefern
785 SbxVariableRef refVar = rPar.Get(0);
786 refVar->PutObject( pFindObj );
789 // Objekt-Property in einem Objekt ansprechen
790 // 1. Parameter = Objekt
791 // 2. Parameter = Name der Property als String
792 RTLFUNC(FindPropertyObject)
794 (void)pBasic;
795 (void)bWrite;
797 // Wir brauchen 2 Parameter
798 if ( rPar.Count() < 3 )
800 StarBASIC::Error( SbERR_BAD_ARGUMENT );
801 return;
804 // 1. Parameter holen, muss Objekt sein
805 SbxBase* pObjVar = (SbxObject*)rPar.Get(1)->GetObject();
806 SbxObject* pObj = NULL;
807 if( pObjVar )
808 pObj = PTR_CAST(SbxObject,pObjVar);
809 if( !pObj && pObjVar && pObjVar->ISA(SbxVariable) )
811 SbxBase* pObjVarObj = ((SbxVariable*)pObjVar)->GetObject();
812 pObj = PTR_CAST(SbxObject,pObjVarObj);
815 if( !pObj )
817 StarBASIC::Error( SbERR_VAR_UNDEFINED );
818 return;
822 // 2. Parameter ist der Name
823 String aNameStr = rPar.Get(2)->GetString();
825 // Jetzt muss ein Objekt da sein, sonst Error
826 SbxObject* pFindObj = NULL;
827 if( pObj )
829 // Im Objekt nach Objekt suchen
830 SbxVariable* pFindVar = pObj->Find( aNameStr, SbxCLASS_OBJECT );
831 pFindObj = PTR_CAST(SbxObject,pFindVar);
833 else
834 StarBASIC::Error( SbERR_BAD_PARAMETER );
836 // Objekt zurueckliefern
837 SbxVariableRef refVar = rPar.Get(0);
838 refVar->PutObject( pFindObj );
843 BOOL lcl_WriteSbxVariable( const SbxVariable& rVar, SvStream* pStrm,
844 BOOL bBinary, short nBlockLen, BOOL bIsArray )
846 ULONG nFPos = pStrm->Tell();
848 BOOL bIsVariant = !rVar.IsFixed();
849 SbxDataType eType = rVar.GetType();
851 switch( eType )
853 case SbxBOOL:
854 case SbxCHAR:
855 case SbxBYTE:
856 if( bIsVariant )
857 *pStrm << (USHORT)SbxBYTE; // VarType Id
858 *pStrm << rVar.GetByte();
859 break;
861 case SbxEMPTY:
862 case SbxNULL:
863 case SbxVOID:
864 case SbxINTEGER:
865 case SbxUSHORT:
866 case SbxINT:
867 case SbxUINT:
868 if( bIsVariant )
869 *pStrm << (USHORT)SbxINTEGER; // VarType Id
870 *pStrm << rVar.GetInteger();
871 break;
873 case SbxLONG:
874 case SbxULONG:
875 case SbxLONG64:
876 case SbxULONG64:
877 if( bIsVariant )
878 *pStrm << (USHORT)SbxLONG; // VarType Id
879 *pStrm << rVar.GetLong();
880 break;
882 case SbxSINGLE:
883 if( bIsVariant )
884 *pStrm << (USHORT)eType; // VarType Id
885 *pStrm << rVar.GetSingle();
886 break;
888 case SbxDOUBLE:
889 case SbxCURRENCY:
890 case SbxDATE:
891 if( bIsVariant )
892 *pStrm << (USHORT)eType; // VarType Id
893 *pStrm << rVar.GetDouble();
894 break;
896 case SbxSTRING:
897 case SbxLPSTR:
899 const String& rStr = rVar.GetString();
900 if( !bBinary || bIsArray )
902 if( bIsVariant )
903 *pStrm << (USHORT)SbxSTRING;
904 pStrm->WriteByteString( rStr, gsl_getSystemTextEncoding() );
905 //*pStrm << rStr;
907 else
909 // ohne Laengenangabe! ohne Endekennung!
910 // What does that mean for Unicode?! Choosing conversion to ByteString...
911 ByteString aByteStr( rStr, gsl_getSystemTextEncoding() );
912 *pStrm << (const char*)aByteStr.GetBuffer();
913 //*pStrm << (const char*)rStr.GetStr();
916 break;
918 default:
919 StarBASIC::Error( SbERR_BAD_ARGUMENT );
920 return FALSE;
923 if( nBlockLen )
924 pStrm->Seek( nFPos + nBlockLen );
925 return pStrm->GetErrorCode() ? FALSE : TRUE;
928 BOOL lcl_ReadSbxVariable( SbxVariable& rVar, SvStream* pStrm,
929 BOOL bBinary, short nBlockLen, BOOL bIsArray )
931 (void)bBinary;
932 (void)bIsArray;
934 double aDouble;
936 ULONG nFPos = pStrm->Tell();
938 BOOL bIsVariant = !rVar.IsFixed();
939 SbxDataType eVarType = rVar.GetType();
941 SbxDataType eSrcType = eVarType;
942 if( bIsVariant )
944 USHORT nTemp;
945 *pStrm >> nTemp;
946 eSrcType = (SbxDataType)nTemp;
949 switch( eSrcType )
951 case SbxBOOL:
952 case SbxCHAR:
953 case SbxBYTE:
955 BYTE aByte;
956 *pStrm >> aByte;
957 rVar.PutByte( aByte );
959 break;
961 case SbxEMPTY:
962 case SbxNULL:
963 case SbxVOID:
964 case SbxINTEGER:
965 case SbxUSHORT:
966 case SbxINT:
967 case SbxUINT:
969 INT16 aInt;
970 *pStrm >> aInt;
971 rVar.PutInteger( aInt );
973 break;
975 case SbxLONG:
976 case SbxULONG:
977 case SbxLONG64:
978 case SbxULONG64:
980 INT32 aInt;
981 *pStrm >> aInt;
982 rVar.PutLong( aInt );
984 break;
986 case SbxSINGLE:
988 float nS;
989 *pStrm >> nS;
990 rVar.PutSingle( nS );
992 break;
994 case SbxDOUBLE:
995 case SbxCURRENCY:
997 *pStrm >> aDouble;
998 rVar.PutDouble( aDouble );
1000 break;
1002 case SbxDATE:
1004 *pStrm >> aDouble;
1005 rVar.PutDate( aDouble );
1007 break;
1009 case SbxSTRING:
1010 case SbxLPSTR:
1012 String aStr;
1013 pStrm->ReadByteString( aStr, gsl_getSystemTextEncoding() );
1014 rVar.PutString( aStr );
1016 break;
1018 default:
1019 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1020 return FALSE;
1023 if( nBlockLen )
1024 pStrm->Seek( nFPos + nBlockLen );
1025 return pStrm->GetErrorCode() ? FALSE : TRUE;
1029 // nCurDim = 1...n
1030 BOOL lcl_WriteReadSbxArray( SbxDimArray& rArr, SvStream* pStrm,
1031 BOOL bBinary, short nCurDim, short* pOtherDims, BOOL bWrite )
1033 DBG_ASSERT( nCurDim > 0,"Bad Dim");
1034 short nLower, nUpper;
1035 if( !rArr.GetDim( nCurDim, nLower, nUpper ) )
1036 return FALSE;
1037 for( short nCur = nLower; nCur <= nUpper; nCur++ )
1039 pOtherDims[ nCurDim-1 ] = nCur;
1040 if( nCurDim != 1 )
1041 lcl_WriteReadSbxArray(rArr, pStrm, bBinary, nCurDim-1, pOtherDims, bWrite);
1042 else
1044 SbxVariable* pVar = rArr.Get( (const short*)pOtherDims );
1045 BOOL bRet;
1046 if( bWrite )
1047 bRet = lcl_WriteSbxVariable(*pVar, pStrm, bBinary, 0, TRUE );
1048 else
1049 bRet = lcl_ReadSbxVariable(*pVar, pStrm, bBinary, 0, TRUE );
1050 if( !bRet )
1051 return FALSE;
1054 return TRUE;
1057 void PutGet( SbxArray& rPar, BOOL bPut )
1059 // Wir brauchen 3 Parameter
1060 if ( rPar.Count() != 4 )
1062 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1063 return;
1065 INT16 nFileNo = rPar.Get(1)->GetInteger();
1066 SbxVariable* pVar2 = rPar.Get(2);
1067 BOOL bHasRecordNo = (BOOL)(pVar2->GetType() != SbxEMPTY);
1068 long nRecordNo = pVar2->GetLong();
1069 if ( nFileNo < 1 || ( bHasRecordNo && nRecordNo < 1 ) )
1071 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1072 return;
1074 nRecordNo--; // wir moegen's ab 0!
1075 SbiIoSystem* pIO = pINST->GetIoSystem();
1076 SbiStream* pSbStrm = pIO->GetStream( nFileNo );
1077 // das File muss Random (feste Record-Laenge) oder Binary sein
1078 if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_RANDOM)) )
1080 StarBASIC::Error( SbERR_BAD_CHANNEL );
1081 return;
1084 SvStream* pStrm = pSbStrm->GetStrm();
1085 BOOL bRandom = pSbStrm->IsRandom();
1086 short nBlockLen = bRandom ? pSbStrm->GetBlockLen() : 0;
1088 if( bPut )
1090 // Datei aufplustern, falls jemand uebers Dateiende hinaus geseekt hat
1091 pSbStrm->ExpandFile();
1094 // auf die Startposition seeken
1095 if( bHasRecordNo )
1097 ULONG nFilePos = bRandom ? (ULONG)(nBlockLen*nRecordNo) : (ULONG)nRecordNo;
1098 pStrm->Seek( nFilePos );
1101 SbxDimArray* pArr = 0;
1102 SbxVariable* pVar = rPar.Get(3);
1103 if( pVar->GetType() & SbxARRAY )
1105 SbxBase* pParObj = pVar->GetObject();
1106 pArr = PTR_CAST(SbxDimArray,pParObj);
1109 BOOL bRet;
1111 if( pArr )
1113 ULONG nFPos = pStrm->Tell();
1114 short nDims = pArr->GetDims();
1115 short* pDims = new short[ nDims ];
1116 bRet = lcl_WriteReadSbxArray(*pArr,pStrm,!bRandom,nDims,pDims,bPut);
1117 delete [] pDims;
1118 if( nBlockLen )
1119 pStrm->Seek( nFPos + nBlockLen );
1121 else
1123 if( bPut )
1124 bRet = lcl_WriteSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, FALSE);
1125 else
1126 bRet = lcl_ReadSbxVariable(*pVar, pStrm, !bRandom, nBlockLen, FALSE);
1128 if( !bRet || pStrm->GetErrorCode() )
1129 StarBASIC::Error( SbERR_IO_ERROR );
1132 RTLFUNC(Put)
1134 (void)pBasic;
1135 (void)bWrite;
1137 PutGet( rPar, TRUE );
1140 RTLFUNC(Get)
1142 (void)pBasic;
1143 (void)bWrite;
1145 PutGet( rPar, FALSE );
1148 RTLFUNC(Environ)
1150 (void)pBasic;
1151 (void)bWrite;
1153 if ( rPar.Count() != 2 )
1155 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1156 return;
1158 String aResult;
1159 // sollte ANSI sein, aber unter Win16 in DLL nicht moeglich
1160 #if defined(WIN)
1161 LPSTR lpszEnv = GetDOSEnvironment();
1162 String aCompareStr( rPar.Get(1)->GetString() );
1163 aCompareStr += '=';
1164 const char* pCompare = aCompareStr.GetStr();
1165 int nCompareLen = aCompareStr.Len();
1166 while ( *lpszEnv )
1168 // Es werden alle EnvString in der Form ENV=VAL 0-terminiert
1169 // aneinander gehaengt.
1171 if ( strnicmp( pCompare, lpszEnv, nCompareLen ) == 0 )
1173 aResult = (const char*)(lpszEnv+nCompareLen);
1174 rPar.Get(0)->PutString( aResult );
1175 return;
1177 lpszEnv += lstrlen( lpszEnv ) + 1; // Next Enviroment-String
1179 #else
1180 ByteString aByteStr( rPar.Get(1)->GetString(), gsl_getSystemTextEncoding() );
1181 const char* pEnvStr = getenv( aByteStr.GetBuffer() );
1182 if ( pEnvStr )
1183 aResult = String::CreateFromAscii( pEnvStr );
1184 #endif
1185 rPar.Get(0)->PutString( aResult );
1188 static double GetDialogZoomFactor( BOOL bX, long nValue )
1190 OutputDevice* pDevice = Application::GetDefaultDevice();
1191 double nResult = 0;
1192 if( pDevice )
1194 Size aRefSize( nValue, nValue );
1195 #ifndef WIN
1196 Fraction aFracX( 1, 26 );
1197 #else
1198 Fraction aFracX( 1, 23 );
1199 #endif
1200 Fraction aFracY( 1, 24 );
1201 MapMode aMap( MAP_APPFONT, Point(), aFracX, aFracY );
1202 Size aScaledSize = pDevice->LogicToPixel( aRefSize, aMap );
1203 aRefSize = pDevice->LogicToPixel( aRefSize, MapMode(MAP_TWIP) );
1205 double nRef, nScaled;
1206 if( bX )
1208 nRef = aRefSize.Width();
1209 nScaled = aScaledSize.Width();
1211 else
1213 nRef = aRefSize.Height();
1214 nScaled = aScaledSize.Height();
1216 nResult = nScaled / nRef;
1218 return nResult;
1222 RTLFUNC(GetDialogZoomFactorX)
1224 (void)pBasic;
1225 (void)bWrite;
1227 if ( rPar.Count() != 2 )
1229 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1230 return;
1232 rPar.Get(0)->PutDouble( GetDialogZoomFactor( TRUE, rPar.Get(1)->GetLong() ));
1235 RTLFUNC(GetDialogZoomFactorY)
1237 (void)pBasic;
1238 (void)bWrite;
1240 if ( rPar.Count() != 2 )
1242 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1243 return;
1245 rPar.Get(0)->PutDouble( GetDialogZoomFactor( FALSE, rPar.Get(1)->GetLong()));
1249 RTLFUNC(EnableReschedule)
1251 (void)pBasic;
1252 (void)bWrite;
1254 rPar.Get(0)->PutEmpty();
1255 if ( rPar.Count() != 2 )
1256 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1257 if( pINST )
1258 pINST->EnableReschedule( rPar.Get(1)->GetBool() );
1261 RTLFUNC(GetSystemTicks)
1263 (void)pBasic;
1264 (void)bWrite;
1266 if ( rPar.Count() != 1 )
1268 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1269 return;
1271 rPar.Get(0)->PutLong( Time::GetSystemTicks() );
1274 RTLFUNC(GetPathSeparator)
1276 (void)pBasic;
1277 (void)bWrite;
1279 if ( rPar.Count() != 1 )
1281 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1282 return;
1284 rPar.Get(0)->PutString( DirEntry::GetAccessDelimiter() );
1287 RTLFUNC(ResolvePath)
1289 (void)pBasic;
1290 (void)bWrite;
1292 if ( rPar.Count() == 2 )
1294 String aStr = rPar.Get(1)->GetString();
1295 DirEntry aEntry( aStr );
1296 //if( aEntry.IsVirtual() )
1297 //aStr = aEntry.GetRealPathFromVirtualURL();
1298 rPar.Get(0)->PutString( aStr );
1300 else
1301 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1304 RTLFUNC(TypeLen)
1306 (void)pBasic;
1307 (void)bWrite;
1309 if ( rPar.Count() != 2 )
1310 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1311 else
1313 SbxDataType eType = rPar.Get(1)->GetType();
1314 INT16 nLen = 0;
1315 switch( eType )
1317 case SbxEMPTY:
1318 case SbxNULL:
1319 case SbxVECTOR:
1320 case SbxARRAY:
1321 case SbxBYREF:
1322 case SbxVOID:
1323 case SbxHRESULT:
1324 case SbxPOINTER:
1325 case SbxDIMARRAY:
1326 case SbxCARRAY:
1327 case SbxUSERDEF:
1328 nLen = 0;
1329 break;
1331 case SbxINTEGER:
1332 case SbxERROR:
1333 case SbxUSHORT:
1334 case SbxINT:
1335 case SbxUINT:
1336 nLen = 2;
1337 break;
1339 case SbxLONG:
1340 case SbxSINGLE:
1341 case SbxULONG:
1342 nLen = 4;
1343 break;
1345 case SbxDOUBLE:
1346 case SbxCURRENCY:
1347 case SbxDATE:
1348 case SbxLONG64:
1349 case SbxULONG64:
1350 nLen = 8;
1351 break;
1353 case SbxOBJECT:
1354 case SbxVARIANT:
1355 case SbxDATAOBJECT:
1356 nLen = 0;
1357 break;
1359 case SbxCHAR:
1360 case SbxBYTE:
1361 case SbxBOOL:
1362 nLen = 1;
1363 break;
1365 case SbxLPSTR:
1366 case SbxLPWSTR:
1367 case SbxCoreSTRING:
1368 case SbxSTRING:
1369 nLen = (INT16)rPar.Get(1)->GetString().Len();
1370 break;
1372 default:
1373 nLen = 0;
1375 rPar.Get(0)->PutInteger( nLen );
1380 // Uno-Struct eines beliebigen Typs erzeugen
1381 // 1. Parameter == Klassename, weitere Parameter zur Initialisierung
1382 RTLFUNC(CreateUnoStruct)
1384 (void)pBasic;
1385 (void)bWrite;
1387 RTL_Impl_CreateUnoStruct( pBasic, rPar, bWrite );
1390 // Uno-Service erzeugen
1391 // 1. Parameter == Service-Name
1392 RTLFUNC(CreateUnoService)
1394 (void)pBasic;
1395 (void)bWrite;
1397 RTL_Impl_CreateUnoService( pBasic, rPar, bWrite );
1400 RTLFUNC(CreateUnoServiceWithArguments)
1402 (void)pBasic;
1403 (void)bWrite;
1405 RTL_Impl_CreateUnoServiceWithArguments( pBasic, rPar, bWrite );
1409 RTLFUNC(CreateUnoValue)
1411 (void)pBasic;
1412 (void)bWrite;
1414 RTL_Impl_CreateUnoValue( pBasic, rPar, bWrite );
1418 // ServiceManager liefern (keine Parameter)
1419 RTLFUNC(GetProcessServiceManager)
1421 (void)pBasic;
1422 (void)bWrite;
1424 RTL_Impl_GetProcessServiceManager( pBasic, rPar, bWrite );
1427 // PropertySet erzeugen
1428 // 1. Parameter == Sequence<PropertyValue>
1429 RTLFUNC(CreatePropertySet)
1431 (void)pBasic;
1432 (void)bWrite;
1434 RTL_Impl_CreatePropertySet( pBasic, rPar, bWrite );
1437 // Abfragen, ob ein Interface unterstuetzt wird
1438 // Mehrere Interface-Namen als Parameter
1439 RTLFUNC(HasUnoInterfaces)
1441 (void)pBasic;
1442 (void)bWrite;
1444 RTL_Impl_HasInterfaces( pBasic, rPar, bWrite );
1447 // Abfragen, ob ein Basic-Objekt ein Uno-Struct repraesentiert
1448 RTLFUNC(IsUnoStruct)
1450 (void)pBasic;
1451 (void)bWrite;
1453 RTL_Impl_IsUnoStruct( pBasic, rPar, bWrite );
1456 // Abfragen, ob zwei Uno-Objekte identisch sind
1457 RTLFUNC(EqualUnoObjects)
1459 (void)pBasic;
1460 (void)bWrite;
1462 RTL_Impl_EqualUnoObjects( pBasic, rPar, bWrite );
1465 // Instanciate "com.sun.star.awt.UnoControlDialog" on basis
1466 // of a DialogLibrary entry: Convert from XML-ByteSequence
1467 // and attach events. Implemented in classes\eventatt.cxx
1468 void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite );
1470 RTLFUNC(CreateUnoDialog)
1472 (void)pBasic;
1473 (void)bWrite;
1475 RTL_Impl_CreateUnoDialog( pBasic, rPar, bWrite );
1478 // Return the application standard lib as root scope
1479 RTLFUNC(GlobalScope)
1481 (void)pBasic;
1482 (void)bWrite;
1484 SbxObject* p = pBasic;
1485 while( p->GetParent() )
1486 p = p->GetParent();
1488 SbxVariableRef refVar = rPar.Get(0);
1489 refVar->PutObject( p );
1492 // Helper functions to convert Url from/to system paths
1493 RTLFUNC(ConvertToUrl)
1495 (void)pBasic;
1496 (void)bWrite;
1498 if ( rPar.Count() == 2 )
1500 String aStr = rPar.Get(1)->GetString();
1501 INetURLObject aURLObj( aStr, INET_PROT_FILE );
1502 ::rtl::OUString aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
1503 if( !aFileURL.getLength() )
1504 ::osl::File::getFileURLFromSystemPath( aFileURL, aFileURL );
1505 if( !aFileURL.getLength() )
1506 aFileURL = aStr;
1507 rPar.Get(0)->PutString( String(aFileURL) );
1509 else
1510 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1513 RTLFUNC(ConvertFromUrl)
1515 (void)pBasic;
1516 (void)bWrite;
1518 if ( rPar.Count() == 2 )
1520 String aStr = rPar.Get(1)->GetString();
1521 ::rtl::OUString aSysPath;
1522 ::osl::File::getSystemPathFromFileURL( aStr, aSysPath );
1523 if( !aSysPath.getLength() )
1524 aSysPath = aStr;
1525 rPar.Get(0)->PutString( String(aSysPath) );
1527 else
1528 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1532 // Provide DefaultContext
1533 RTLFUNC(GetDefaultContext)
1535 (void)pBasic;
1536 (void)bWrite;
1538 RTL_Impl_GetDefaultContext( pBasic, rPar, bWrite );
1542 RTLFUNC(Join)
1544 (void)pBasic;
1545 (void)bWrite;
1547 USHORT nParCount = rPar.Count();
1548 if ( nParCount != 3 && nParCount != 2 )
1550 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1551 return;
1553 SbxBase* pParObj = rPar.Get(1)->GetObject();
1554 SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
1555 if( pArr )
1557 if( pArr->GetDims() != 1 )
1558 StarBASIC::Error( SbERR_WRONG_DIMS ); // Syntax Error?!
1560 String aDelim;
1561 if( nParCount == 3 )
1562 aDelim = rPar.Get(2)->GetString();
1563 else
1564 aDelim = String::CreateFromAscii( " " );
1566 String aRetStr;
1567 short nLower, nUpper;
1568 pArr->GetDim( 1, nLower, nUpper );
1569 for( short i = nLower ; i <= nUpper ; ++i )
1571 String aStr = pArr->Get( &i )->GetString();
1572 aRetStr += aStr;
1573 if( i != nUpper )
1574 aRetStr += aDelim;
1576 rPar.Get(0)->PutString( aRetStr );
1578 else
1579 StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
1583 typedef ::std::vector< String > StringVector;
1585 RTLFUNC(Split)
1587 (void)pBasic;
1588 (void)bWrite;
1590 USHORT nParCount = rPar.Count();
1591 if ( nParCount < 2 )
1593 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1594 return;
1597 String aExpression = rPar.Get(1)->GetString();
1598 short nArraySize = 0;
1599 StringVector vRet;
1600 if( aExpression.Len() )
1602 String aDelim;
1603 if( nParCount >= 3 )
1604 aDelim = rPar.Get(2)->GetString();
1605 else
1606 aDelim = String::CreateFromAscii( " " );
1608 INT32 nCount = -1;
1609 if( nParCount == 4 )
1610 nCount = rPar.Get(3)->GetLong();
1612 xub_StrLen nDelimLen = aDelim.Len();
1613 if( nDelimLen )
1615 xub_StrLen iSearch = STRING_NOTFOUND;
1616 xub_StrLen iStart = 0;
1619 bool bBreak = false;
1620 if( nCount >= 0 && nArraySize == nCount - 1 )
1621 bBreak = true;
1623 iSearch = aExpression.Search( aDelim, iStart );
1624 String aSubStr;
1625 if( iSearch != STRING_NOTFOUND && !bBreak )
1627 aSubStr = aExpression.Copy( iStart, iSearch - iStart );
1628 iStart = iSearch + nDelimLen;
1630 else
1632 aSubStr = aExpression.Copy( iStart );
1634 vRet.push_back( aSubStr );
1635 nArraySize++;
1637 if( bBreak )
1638 break;
1640 while( iSearch != STRING_NOTFOUND );
1642 else
1644 vRet.push_back( aExpression );
1645 nArraySize = 1;
1649 SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
1650 pArray->unoAddDim( 0, nArraySize-1 );
1652 // Parameter ins Array uebernehmen
1653 for( short i = 0 ; i < nArraySize ; i++ )
1655 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
1656 xVar->PutString( vRet[i] );
1657 pArray->Put( (SbxVariable*)xVar, &i );
1660 // Array zurueckliefern
1661 SbxVariableRef refVar = rPar.Get(0);
1662 USHORT nFlags = refVar->GetFlags();
1663 refVar->ResetFlag( SBX_FIXED );
1664 refVar->PutObject( pArray );
1665 refVar->SetFlags( nFlags );
1666 refVar->SetParameters( NULL );
1669 // MonthName(month[, abbreviate])
1670 RTLFUNC(MonthName)
1672 (void)pBasic;
1673 (void)bWrite;
1675 USHORT nParCount = rPar.Count();
1676 if( nParCount != 2 && nParCount != 3 )
1678 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1679 return;
1682 Reference< XCalendar > xCalendar = getLocaleCalendar();
1683 if( !xCalendar.is() )
1685 StarBASIC::Error( SbERR_INTERNAL_ERROR );
1686 return;
1688 Sequence< CalendarItem > aMonthSeq = xCalendar->getMonths();
1689 sal_Int32 nMonthCount = aMonthSeq.getLength();
1691 INT16 nVal = rPar.Get(1)->GetInteger();
1692 if( nVal < 1 || nVal > nMonthCount )
1694 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1695 return;
1698 BOOL bAbbreviate = false;
1699 if( nParCount == 3 )
1700 bAbbreviate = rPar.Get(2)->GetBool();
1702 const CalendarItem* pCalendarItems = aMonthSeq.getConstArray();
1703 const CalendarItem& rItem = pCalendarItems[nVal - 1];
1705 ::rtl::OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName );
1706 rPar.Get(0)->PutString( String(aRetStr) );
1709 // WeekdayName(weekday, abbreviate, firstdayofweek)
1710 RTLFUNC(WeekdayName)
1712 (void)pBasic;
1713 (void)bWrite;
1715 USHORT nParCount = rPar.Count();
1716 if( nParCount < 2 || nParCount > 4 )
1718 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1719 return;
1722 Reference< XCalendar > xCalendar = getLocaleCalendar();
1723 if( !xCalendar.is() )
1725 StarBASIC::Error( SbERR_INTERNAL_ERROR );
1726 return;
1729 Sequence< CalendarItem > aDaySeq = xCalendar->getDays();
1730 INT16 nDayCount = (INT16)aDaySeq.getLength();
1731 INT16 nDay = rPar.Get(1)->GetInteger();
1732 INT16 nFirstDay = 0;
1733 if( nParCount == 4 )
1735 nFirstDay = rPar.Get(3)->GetInteger();
1736 if( nFirstDay < 0 || nFirstDay > 7 )
1738 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1739 return;
1742 if( nFirstDay == 0 )
1743 nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
1745 nDay = 1 + (nDay + nDayCount + nFirstDay - 2) % nDayCount;
1746 if( nDay < 1 || nDay > nDayCount )
1748 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1749 return;
1752 BOOL bAbbreviate = false;
1753 if( nParCount >= 3 )
1755 SbxVariable* pPar2 = rPar.Get(2);
1756 if( !pPar2->IsErr() )
1757 bAbbreviate = pPar2->GetBool();
1760 const CalendarItem* pCalendarItems = aDaySeq.getConstArray();
1761 const CalendarItem& rItem = pCalendarItems[nDay - 1];
1763 ::rtl::OUString aRetStr = ( bAbbreviate ? rItem.AbbrevName : rItem.FullName );
1764 rPar.Get(0)->PutString( String(aRetStr) );
1767 INT16 implGetWeekDay( double aDate, bool bFirstDayParam = false, INT16 nFirstDay = 0 )
1769 Date aRefDate( 1,1,1900 );
1770 long nDays = (long) aDate;
1771 nDays -= 2; // normieren: 1.1.1900 => 0
1772 aRefDate += nDays;
1773 DayOfWeek aDay = aRefDate.GetDayOfWeek();
1774 INT16 nDay;
1775 if ( aDay != SUNDAY )
1776 nDay = (INT16)aDay + 2;
1777 else
1778 nDay = 1; // 1==Sonntag
1780 // #117253 Optional 2. parameter "firstdayofweek"
1781 if( bFirstDayParam )
1783 if( nFirstDay < 0 || nFirstDay > 7 )
1785 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1786 return 0;
1788 if( nFirstDay == 0 )
1790 Reference< XCalendar > xCalendar = getLocaleCalendar();
1791 if( !xCalendar.is() )
1793 StarBASIC::Error( SbERR_INTERNAL_ERROR );
1794 return 0;
1796 nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
1798 nDay = 1 + (nDay + 7 - nFirstDay) % 7;
1800 return nDay;
1803 RTLFUNC(Weekday)
1805 (void)pBasic;
1806 (void)bWrite;
1808 USHORT nParCount = rPar.Count();
1809 if ( nParCount < 2 )
1810 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1811 else
1813 double aDate = rPar.Get(1)->GetDate();
1815 bool bFirstDay = false;
1816 INT16 nFirstDay = 0;
1817 if ( nParCount > 2 )
1819 nFirstDay = rPar.Get(2)->GetInteger();
1820 bFirstDay = true;
1822 INT16 nDay = implGetWeekDay( aDate, bFirstDay, nFirstDay );
1823 rPar.Get(0)->PutInteger( nDay );
1828 enum Interval
1830 INTERVAL_NONE,
1831 INTERVAL_YYYY,
1832 INTERVAL_Q,
1833 INTERVAL_M,
1834 INTERVAL_Y,
1835 INTERVAL_D,
1836 INTERVAL_W,
1837 INTERVAL_WW,
1838 INTERVAL_H,
1839 INTERVAL_N,
1840 INTERVAL_S
1843 struct IntervalInfo
1845 Interval meInterval;
1846 const char* mpStringCode;
1847 double mdValue;
1848 bool mbSimple;
1850 IntervalInfo( Interval eInterval, const char* pStringCode, double dValue, bool bSimple )
1851 : meInterval( eInterval )
1852 , mpStringCode( pStringCode )
1853 , mdValue( dValue )
1854 , mbSimple( bSimple )
1858 static IntervalInfo pIntervalTable[] =
1860 IntervalInfo( INTERVAL_YYYY, "yyyy", 0.0, false ), // Year
1861 IntervalInfo( INTERVAL_Q, "q", 0.0, false ), // Quarter
1862 IntervalInfo( INTERVAL_M, "m", 0.0, false ), // Month
1863 IntervalInfo( INTERVAL_Y, "y", 1.0, true ), // Day of year
1864 IntervalInfo( INTERVAL_D, "d", 1.0, true ), // Day
1865 IntervalInfo( INTERVAL_W, "w", 1.0, true ), // Weekday
1866 IntervalInfo( INTERVAL_WW, "ww", 7.0, true ), // Week
1867 IntervalInfo( INTERVAL_H, "h", (1.0 / 24.0), true ), // Hour
1868 IntervalInfo( INTERVAL_N, "n", (1.0 / 1440.0), true), // Minute
1869 IntervalInfo( INTERVAL_S, "s", (1.0 / 86400.0), true ), // Second
1870 IntervalInfo( INTERVAL_NONE, NULL, 0.0, false )
1873 IntervalInfo* getIntervalInfo( const String& rStringCode )
1875 IntervalInfo* pInfo = NULL;
1876 INT16 i = 0;
1877 while( (pInfo = pIntervalTable + i)->mpStringCode != NULL )
1879 if( rStringCode.EqualsIgnoreCaseAscii( pInfo->mpStringCode ) )
1880 break;
1881 i++;
1883 return pInfo;
1886 // From methods.cxx
1887 BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet );
1888 INT16 implGetDateDay( double aDate );
1889 INT16 implGetDateMonth( double aDate );
1890 INT16 implGetDateYear( double aDate );
1892 INT16 implGetHour( double dDate );
1893 INT16 implGetMinute( double dDate );
1894 INT16 implGetSecond( double dDate );
1897 inline void implGetDayMonthYear( INT16& rnYear, INT16& rnMonth, INT16& rnDay, double dDate )
1899 rnDay = implGetDateDay( dDate );
1900 rnMonth = implGetDateMonth( dDate );
1901 rnYear = implGetDateYear( dDate );
1904 inline INT16 limitToINT16( INT32 n32 )
1906 if( n32 > 32767 )
1907 n32 = 32767;
1908 else if( n32 < -32768 )
1909 n32 = -32768;
1910 return (INT16)n32;
1913 RTLFUNC(DateAdd)
1915 (void)pBasic;
1916 (void)bWrite;
1918 USHORT nParCount = rPar.Count();
1919 if( nParCount != 4 )
1921 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1922 return;
1925 String aStringCode = rPar.Get(1)->GetString();
1926 IntervalInfo* pInfo = getIntervalInfo( aStringCode );
1927 if( !pInfo )
1929 StarBASIC::Error( SbERR_BAD_ARGUMENT );
1930 return;
1933 INT32 lNumber = rPar.Get(2)->GetLong();
1934 double dDate = rPar.Get(3)->GetDate();
1935 double dNewDate = 0;
1936 if( pInfo->mbSimple )
1938 double dAdd = pInfo->mdValue * lNumber;
1939 dNewDate = dDate + dAdd;
1941 else
1943 // Keep hours, minutes, seconds
1944 double dHoursMinutesSeconds = dDate - floor( dDate );
1946 BOOL bOk = TRUE;
1947 INT16 nYear, nMonth, nDay;
1948 INT16 nTargetYear16 = 0, nTargetMonth = 0;
1949 implGetDayMonthYear( nYear, nMonth, nDay, dDate );
1950 switch( pInfo->meInterval )
1952 case INTERVAL_YYYY:
1954 INT32 nTargetYear = lNumber + nYear;
1955 nTargetYear16 = limitToINT16( nTargetYear );
1956 nTargetMonth = nMonth;
1957 bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate );
1958 break;
1960 case INTERVAL_Q:
1961 case INTERVAL_M:
1963 bool bNeg = (lNumber < 0);
1964 if( bNeg )
1965 lNumber = -lNumber;
1966 INT32 nYearsAdd;
1967 INT16 nMonthAdd;
1968 if( pInfo->meInterval == INTERVAL_Q )
1970 nYearsAdd = lNumber / 4;
1971 nMonthAdd = (INT16)( 3 * (lNumber % 4) );
1973 else
1975 nYearsAdd = lNumber / 12;
1976 nMonthAdd = (INT16)( lNumber % 12 );
1979 INT32 nTargetYear;
1980 if( bNeg )
1982 nTargetMonth = nMonth - nMonthAdd;
1983 if( nTargetMonth <= 0 )
1985 nTargetMonth += 12;
1986 nYearsAdd++;
1988 nTargetYear = (INT32)nYear - nYearsAdd;
1990 else
1992 nTargetMonth = nMonth + nMonthAdd;
1993 if( nTargetMonth > 12 )
1995 nTargetMonth -= 12;
1996 nYearsAdd++;
1998 nTargetYear = (INT32)nYear + nYearsAdd;
2000 nTargetYear16 = limitToINT16( nTargetYear );
2001 bOk = implDateSerial( nTargetYear16, nTargetMonth, nDay, dNewDate );
2002 break;
2004 default: break;
2007 if( bOk )
2009 // Overflow?
2010 INT16 nNewYear, nNewMonth, nNewDay;
2011 implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
2012 if( nNewYear > 9999 || nNewYear < 100 )
2014 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2015 return;
2017 INT16 nCorrectionDay = nDay;
2018 while( nNewMonth > nTargetMonth )
2020 nCorrectionDay--;
2021 implDateSerial( nTargetYear16, nTargetMonth, nCorrectionDay, dNewDate );
2022 implGetDayMonthYear( nNewYear, nNewMonth, nNewDay, dNewDate );
2024 dNewDate += dHoursMinutesSeconds;
2028 rPar.Get(0)->PutDate( dNewDate );
2031 inline double RoundImpl( double d )
2033 return ( d >= 0 ) ? floor( d + 0.5 ) : -floor( -d + 0.5 );
2036 RTLFUNC(DateDiff)
2038 (void)pBasic;
2039 (void)bWrite;
2041 // DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]])
2043 USHORT nParCount = rPar.Count();
2044 if( nParCount < 4 || nParCount > 6 )
2046 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2047 return;
2050 String aStringCode = rPar.Get(1)->GetString();
2051 IntervalInfo* pInfo = getIntervalInfo( aStringCode );
2052 if( !pInfo )
2054 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2055 return;
2058 double dDate1 = rPar.Get(2)->GetDate();
2059 double dDate2 = rPar.Get(3)->GetDate();
2061 double dRet = 0.0;
2062 switch( pInfo->meInterval )
2064 case INTERVAL_YYYY:
2066 INT16 nYear1 = implGetDateYear( dDate1 );
2067 INT16 nYear2 = implGetDateYear( dDate2 );
2068 dRet = nYear2 - nYear1;
2069 break;
2071 case INTERVAL_Q:
2073 INT16 nYear1 = implGetDateYear( dDate1 );
2074 INT16 nYear2 = implGetDateYear( dDate2 );
2075 INT16 nQ1 = 1 + (implGetDateMonth( dDate1 ) - 1) / 3;
2076 INT16 nQ2 = 1 + (implGetDateMonth( dDate2 ) - 1) / 3;
2077 INT16 nQGes1 = 4 * nYear1 + nQ1;
2078 INT16 nQGes2 = 4 * nYear2 + nQ2;
2079 dRet = nQGes2 - nQGes1;
2080 break;
2082 case INTERVAL_M:
2084 INT16 nYear1 = implGetDateYear( dDate1 );
2085 INT16 nYear2 = implGetDateYear( dDate2 );
2086 INT16 nMonth1 = implGetDateMonth( dDate1 );
2087 INT16 nMonth2 = implGetDateMonth( dDate2 );
2088 INT16 nMonthGes1 = 12 * nYear1 + nMonth1;
2089 INT16 nMonthGes2 = 12 * nYear2 + nMonth2;
2090 dRet = nMonthGes2 - nMonthGes1;
2091 break;
2093 case INTERVAL_Y:
2094 case INTERVAL_D:
2096 double dDays1 = floor( dDate1 );
2097 double dDays2 = floor( dDate2 );
2098 dRet = dDays2 - dDays1;
2099 break;
2101 case INTERVAL_W:
2102 case INTERVAL_WW:
2104 double dDays1 = floor( dDate1 );
2105 double dDays2 = floor( dDate2 );
2106 if( pInfo->meInterval == INTERVAL_WW )
2108 INT16 nFirstDay = 1; // Default
2109 if( nParCount >= 5 )
2111 nFirstDay = rPar.Get(4)->GetInteger();
2112 if( nFirstDay < 0 || nFirstDay > 7 )
2114 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2115 return;
2117 if( nFirstDay == 0 )
2119 Reference< XCalendar > xCalendar = getLocaleCalendar();
2120 if( !xCalendar.is() )
2122 StarBASIC::Error( SbERR_INTERNAL_ERROR );
2123 return;
2125 nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
2128 INT16 nDay1 = implGetWeekDay( dDate1 );
2129 INT16 nDay1_Diff = nDay1 - nFirstDay;
2130 if( nDay1_Diff < 0 )
2131 nDay1_Diff += 7;
2132 dDays1 -= nDay1_Diff;
2134 INT16 nDay2 = implGetWeekDay( dDate2 );
2135 INT16 nDay2_Diff = nDay2 - nFirstDay;
2136 if( nDay2_Diff < 0 )
2137 nDay2_Diff += 7;
2138 dDays2 -= nDay2_Diff;
2141 double dDiff = dDays2 - dDays1;
2142 dRet = ( dDiff >= 0 ) ? floor( dDiff / 7.0 ) : -floor( -dDiff / 7.0 );
2143 break;
2145 case INTERVAL_H:
2147 double dFactor = 24.0;
2148 dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
2149 break;
2151 case INTERVAL_N:
2153 double dFactor =1440.0;
2154 dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
2155 break;
2157 case INTERVAL_S:
2159 double dFactor = 86400.0;
2160 dRet = RoundImpl( dFactor * (dDate2 - dDate1) );
2161 break;
2163 case INTERVAL_NONE:
2164 break;
2166 rPar.Get(0)->PutDouble( dRet );
2169 double implGetDateOfFirstDayInFirstWeek
2170 ( INT16 nYear, INT16& nFirstDay, INT16& nFirstWeek, bool* pbError = NULL )
2172 SbError nError = 0;
2173 if( nFirstDay < 0 || nFirstDay > 7 )
2174 nError = SbERR_BAD_ARGUMENT;
2176 if( nFirstWeek < 0 || nFirstWeek > 3 )
2177 nError = SbERR_BAD_ARGUMENT;
2179 Reference< XCalendar > xCalendar;
2180 if( nFirstDay == 0 || nFirstWeek == 0 )
2182 xCalendar = getLocaleCalendar();
2183 if( !xCalendar.is() )
2184 nError = SbERR_BAD_ARGUMENT;
2187 if( nError != 0 )
2189 StarBASIC::Error( nError );
2190 if( pbError )
2191 *pbError = true;
2192 return 0.0;
2195 if( nFirstDay == 0 )
2196 nFirstDay = INT16( xCalendar->getFirstDayOfWeek() + 1 );
2198 INT16 nFirstWeekMinDays = 0; // Not used for vbFirstJan1 = default
2199 if( nFirstWeek == 0 )
2201 nFirstWeekMinDays = xCalendar->getMinimumNumberOfDaysForFirstWeek();
2202 if( nFirstWeekMinDays == 1 )
2204 nFirstWeekMinDays = 0;
2205 nFirstWeek = 1;
2207 else if( nFirstWeekMinDays == 4 )
2208 nFirstWeek = 2;
2209 else if( nFirstWeekMinDays == 7 )
2210 nFirstWeek = 3;
2212 else if( nFirstWeek == 2 )
2213 nFirstWeekMinDays = 4; // vbFirstFourDays
2214 else if( nFirstWeek == 3 )
2215 nFirstWeekMinDays = 7; // vbFirstFourDays
2217 double dBaseDate;
2218 implDateSerial( nYear, 1, 1, dBaseDate );
2219 double dRetDate = dBaseDate;
2221 INT16 nWeekDay0101 = implGetWeekDay( dBaseDate );
2222 INT16 nDayDiff = nWeekDay0101 - nFirstDay;
2223 if( nDayDiff < 0 )
2224 nDayDiff += 7;
2226 if( nFirstWeekMinDays )
2228 INT16 nThisWeeksDaysInYearCount = 7 - nDayDiff;
2229 if( nThisWeeksDaysInYearCount < nFirstWeekMinDays )
2230 nDayDiff -= 7;
2232 dRetDate = dBaseDate - nDayDiff;
2233 return dRetDate;
2236 RTLFUNC(DatePart)
2238 (void)pBasic;
2239 (void)bWrite;
2241 // DatePart(interval, date[,firstdayofweek[, firstweekofyear]])
2243 USHORT nParCount = rPar.Count();
2244 if( nParCount < 3 || nParCount > 5 )
2246 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2247 return;
2250 String aStringCode = rPar.Get(1)->GetString();
2251 IntervalInfo* pInfo = getIntervalInfo( aStringCode );
2252 if( !pInfo )
2254 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2255 return;
2258 double dDate = rPar.Get(2)->GetDate();
2260 INT32 nRet = 0;
2261 switch( pInfo->meInterval )
2263 case INTERVAL_YYYY:
2265 nRet = implGetDateYear( dDate );
2266 break;
2268 case INTERVAL_Q:
2270 nRet = 1 + (implGetDateMonth( dDate ) - 1) / 3;
2271 break;
2273 case INTERVAL_M:
2275 nRet = implGetDateMonth( dDate );
2276 break;
2278 case INTERVAL_Y:
2280 INT16 nYear = implGetDateYear( dDate );
2281 double dBaseDate;
2282 implDateSerial( nYear, 1, 1, dBaseDate );
2283 nRet = 1 + INT32( dDate - dBaseDate );
2284 break;
2286 case INTERVAL_D:
2288 nRet = implGetDateDay( dDate );
2289 break;
2291 case INTERVAL_W:
2293 bool bFirstDay = false;
2294 INT16 nFirstDay = 1; // Default
2295 if( nParCount >= 4 )
2297 nFirstDay = rPar.Get(3)->GetInteger();
2298 bFirstDay = true;
2300 nRet = implGetWeekDay( dDate, bFirstDay, nFirstDay );
2301 break;
2303 case INTERVAL_WW:
2305 INT16 nFirstDay = 1; // Default
2306 if( nParCount >= 4 )
2307 nFirstDay = rPar.Get(3)->GetInteger();
2309 INT16 nFirstWeek = 1; // Default
2310 if( nParCount == 5 )
2311 nFirstWeek = rPar.Get(4)->GetInteger();
2313 INT16 nYear = implGetDateYear( dDate );
2314 bool bError = false;
2315 double dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear, nFirstDay, nFirstWeek, &bError );
2316 if( !bError )
2318 if( dYearFirstDay > dDate )
2320 // Date belongs to last year's week
2321 dYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear - 1, nFirstDay, nFirstWeek );
2323 else if( nFirstWeek != 1 )
2325 // Check if date belongs to next year
2326 double dNextYearFirstDay = implGetDateOfFirstDayInFirstWeek( nYear + 1, nFirstDay, nFirstWeek );
2327 if( dDate >= dNextYearFirstDay )
2328 dYearFirstDay = dNextYearFirstDay;
2331 // Calculate week
2332 double dDiff = dDate - dYearFirstDay;
2333 nRet = 1 + INT32( dDiff / 7 );
2335 break;
2337 case INTERVAL_H:
2339 nRet = implGetHour( dDate );
2340 break;
2342 case INTERVAL_N:
2344 nRet = implGetMinute( dDate );
2345 break;
2347 case INTERVAL_S:
2349 nRet = implGetSecond( dDate );
2350 break;
2352 case INTERVAL_NONE:
2353 break;
2355 rPar.Get(0)->PutLong( nRet );
2358 // FormatDateTime(Date[,NamedFormat])
2359 RTLFUNC(FormatDateTime)
2361 (void)pBasic;
2362 (void)bWrite;
2364 USHORT nParCount = rPar.Count();
2365 if( nParCount < 2 || nParCount > 3 )
2367 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2368 return;
2371 double dDate = rPar.Get(1)->GetDate();
2372 INT16 nNamedFormat = 0;
2373 if( nParCount > 2 )
2375 nNamedFormat = rPar.Get(2)->GetInteger();
2376 if( nNamedFormat < 0 || nNamedFormat > 4 )
2378 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2379 return;
2383 Reference< XCalendar > xCalendar = getLocaleCalendar();
2384 if( !xCalendar.is() )
2386 StarBASIC::Error( SbERR_INTERNAL_ERROR );
2387 return;
2390 String aRetStr;
2391 SbxVariableRef pSbxVar = new SbxVariable( SbxSTRING );
2392 switch( nNamedFormat )
2394 // GeneralDate:
2395 // Display a date and/or time. If there is a date part,
2396 // display it as a short date. If there is a time part,
2397 // display it as a long time. If present, both parts are displayed.
2399 // 12/21/2004 11:24:50 AM
2400 // 21.12.2004 12:13:51
2401 case 0:
2402 pSbxVar->PutDate( dDate );
2403 aRetStr = pSbxVar->GetString();
2404 break;
2406 // LongDate: Display a date using the long date format specified
2407 // in your computer's regional settings.
2408 // Tuesday, December 21, 2004
2409 // Dienstag, 21. December 2004
2410 case 1:
2412 SvNumberFormatter* pFormatter = NULL;
2413 if( pINST )
2414 pFormatter = pINST->GetNumberFormatter();
2415 else
2417 sal_uInt32 n; // Dummy
2418 SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
2421 LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
2422 ULONG nIndex = pFormatter->GetFormatIndex( NF_DATE_SYSTEM_LONG, eLangType );
2423 Color* pCol;
2424 pFormatter->GetOutputString( dDate, nIndex, aRetStr, &pCol );
2426 if( !pINST )
2427 delete pFormatter;
2429 break;
2432 // ShortDate: Display a date using the short date format specified
2433 // in your computer's regional settings.
2434 // 12/21/2004
2435 // 21.12.2004
2436 case 2:
2437 pSbxVar->PutDate( floor(dDate) );
2438 aRetStr = pSbxVar->GetString();
2439 break;
2441 // LongTime: Display a time using the time format specified
2442 // in your computer's regional settings.
2443 // 11:24:50 AM
2444 // 12:13:51
2445 case 3:
2446 // ShortTime: Display a time using the 24-hour format (hh:mm).
2447 // 11:24
2448 case 4:
2449 double n;
2450 double dTime = modf( dDate, &n );
2451 pSbxVar->PutDate( dTime );
2452 if( nNamedFormat == 3 )
2453 aRetStr = pSbxVar->GetString();
2454 else
2455 aRetStr = pSbxVar->GetString().Copy( 0, 5 );
2456 break;
2459 rPar.Get(0)->PutString( aRetStr );
2462 RTLFUNC(Round)
2464 (void)pBasic;
2465 (void)bWrite;
2467 USHORT nParCount = rPar.Count();
2468 if( nParCount != 2 && nParCount != 3 )
2470 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2471 return;
2474 SbxVariable *pSbxVariable = rPar.Get(1);
2475 double dVal = pSbxVariable->GetDouble();
2476 double dRes = 0.0;
2477 if( dVal != 0.0 )
2479 bool bNeg = false;
2480 if( dVal < 0.0 )
2482 bNeg = true;
2483 dVal = -dVal;
2486 INT16 numdecimalplaces = 0;
2487 if( nParCount == 3 )
2489 numdecimalplaces = rPar.Get(2)->GetInteger();
2490 if( numdecimalplaces < 0 || numdecimalplaces > 22 )
2492 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2493 return;
2497 if( numdecimalplaces == 0 )
2499 dRes = floor( dVal + 0.5 );
2501 else
2503 double dFactor = pow( 10.0, numdecimalplaces );
2504 dVal *= dFactor;
2505 dRes = floor( dVal + 0.5 );
2506 dRes /= dFactor;
2509 if( bNeg )
2510 dRes = -dRes;
2512 rPar.Get(0)->PutDouble( dRes );
2515 void CallFunctionAccessFunction( const Sequence< Any >& aArgs, const rtl::OUString& sFuncName, SbxVariable* pRet )
2517 static Reference< XFunctionAccess > xFunc;
2518 Any aRes;
2521 if ( !xFunc.is() )
2523 Reference< XMultiServiceFactory > xFactory( getProcessServiceFactory() );
2524 if( xFactory.is() )
2526 xFunc.set( xFactory->createInstance(::rtl::OUString::createFromAscii( "com.sun.star.sheet.FunctionAccess")), UNO_QUERY_THROW);
2529 Any aRet = xFunc->callFunction( sFuncName, aArgs );
2531 unoToSbxValue( pRet, aRet );
2534 catch( Exception& )
2536 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2540 RTLFUNC(SYD)
2542 (void)pBasic;
2543 (void)bWrite;
2545 ULONG nArgCount = rPar.Count()-1;
2547 if ( nArgCount < 4 )
2549 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2550 return;
2553 // retrieve non-optional params
2555 Sequence< Any > aParams( 4 );
2556 aParams[ 0 ] <<= makeAny( rPar.Get(1)->GetDouble() );
2557 aParams[ 1 ] <<= makeAny( rPar.Get(2)->GetDouble() );
2558 aParams[ 2 ] <<= makeAny( rPar.Get(3)->GetDouble() );
2559 aParams[ 3 ] <<= makeAny( rPar.Get(4)->GetDouble() );
2561 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SYD") ), rPar.Get( 0 ) );
2564 RTLFUNC(SLN)
2566 (void)pBasic;
2567 (void)bWrite;
2569 ULONG nArgCount = rPar.Count()-1;
2571 if ( nArgCount < 3 )
2573 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2574 return;
2577 // retrieve non-optional params
2579 Sequence< Any > aParams( 3 );
2580 aParams[ 0 ] <<= makeAny( rPar.Get(1)->GetDouble() );
2581 aParams[ 1 ] <<= makeAny( rPar.Get(2)->GetDouble() );
2582 aParams[ 2 ] <<= makeAny( rPar.Get(3)->GetDouble() );
2584 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SLN") ), rPar.Get( 0 ) );
2587 RTLFUNC(Pmt)
2589 (void)pBasic;
2590 (void)bWrite;
2592 ULONG nArgCount = rPar.Count()-1;
2594 if ( nArgCount < 3 || nArgCount > 5 )
2596 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2597 return;
2599 // retrieve non-optional params
2601 double rate = rPar.Get(1)->GetDouble();
2602 double nper = rPar.Get(2)->GetDouble();
2603 double pmt = rPar.Get(3)->GetDouble();
2605 // set default values for Optional args
2606 double fv = 0;
2607 double type = 0;
2609 // fv
2610 if ( nArgCount >= 4 )
2612 if( rPar.Get(4)->GetType() != SbxEMPTY )
2613 fv = rPar.Get(4)->GetDouble();
2615 // type
2616 if ( nArgCount >= 5 )
2618 if( rPar.Get(5)->GetType() != SbxEMPTY )
2619 type = rPar.Get(5)->GetDouble();
2622 Sequence< Any > aParams( 5 );
2623 aParams[ 0 ] <<= rate;
2624 aParams[ 1 ] <<= nper;
2625 aParams[ 2 ] <<= pmt;
2626 aParams[ 3 ] <<= fv;
2627 aParams[ 4 ] <<= type;
2629 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Pmt") ), rPar.Get( 0 ) );
2632 RTLFUNC(PPmt)
2634 (void)pBasic;
2635 (void)bWrite;
2637 ULONG nArgCount = rPar.Count()-1;
2639 if ( nArgCount < 4 || nArgCount > 6 )
2641 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2642 return;
2644 // retrieve non-optional params
2646 double rate = rPar.Get(1)->GetDouble();
2647 double per = rPar.Get(2)->GetDouble();
2648 double nper = rPar.Get(3)->GetDouble();
2649 double pv = rPar.Get(4)->GetDouble();
2651 // set default values for Optional args
2652 double fv = 0;
2653 double type = 0;
2655 // fv
2656 if ( nArgCount >= 5 )
2658 if( rPar.Get(5)->GetType() != SbxEMPTY )
2659 fv = rPar.Get(5)->GetDouble();
2661 // type
2662 if ( nArgCount >= 6 )
2664 if( rPar.Get(6)->GetType() != SbxEMPTY )
2665 type = rPar.Get(6)->GetDouble();
2668 Sequence< Any > aParams( 6 );
2669 aParams[ 0 ] <<= rate;
2670 aParams[ 1 ] <<= per;
2671 aParams[ 2 ] <<= nper;
2672 aParams[ 3 ] <<= pv;
2673 aParams[ 4 ] <<= fv;
2674 aParams[ 5 ] <<= type;
2676 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PPmt") ), rPar.Get( 0 ) );
2679 RTLFUNC(PV)
2681 (void)pBasic;
2682 (void)bWrite;
2684 ULONG nArgCount = rPar.Count()-1;
2686 if ( nArgCount < 3 || nArgCount > 5 )
2688 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2689 return;
2691 // retrieve non-optional params
2693 double rate = rPar.Get(1)->GetDouble();
2694 double nper = rPar.Get(2)->GetDouble();
2695 double pmt = rPar.Get(3)->GetDouble();
2697 // set default values for Optional args
2698 double fv = 0;
2699 double type = 0;
2701 // fv
2702 if ( nArgCount >= 4 )
2704 if( rPar.Get(4)->GetType() != SbxEMPTY )
2705 fv = rPar.Get(4)->GetDouble();
2707 // type
2708 if ( nArgCount >= 5 )
2710 if( rPar.Get(5)->GetType() != SbxEMPTY )
2711 type = rPar.Get(5)->GetDouble();
2714 Sequence< Any > aParams( 5 );
2715 aParams[ 0 ] <<= rate;
2716 aParams[ 1 ] <<= nper;
2717 aParams[ 2 ] <<= pmt;
2718 aParams[ 3 ] <<= fv;
2719 aParams[ 4 ] <<= type;
2721 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PV") ), rPar.Get( 0 ) );
2724 RTLFUNC(NPV)
2726 (void)pBasic;
2727 (void)bWrite;
2729 ULONG nArgCount = rPar.Count()-1;
2731 if ( nArgCount < 1 || nArgCount > 2 )
2733 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2734 return;
2737 Sequence< Any > aParams( 2 );
2738 aParams[ 0 ] <<= makeAny( rPar.Get(1)->GetDouble() );
2739 Any aValues = sbxToUnoValue( rPar.Get(2),
2740 getCppuType( (Sequence<double>*)0 ) );
2742 // convert for calc functions
2743 Sequence< Sequence< double > > sValues(1);
2744 aValues >>= sValues[ 0 ];
2745 aValues <<= sValues;
2747 aParams[ 1 ] <<= aValues;
2749 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("NPV") ), rPar.Get( 0 ) );
2752 RTLFUNC(NPer)
2754 (void)pBasic;
2755 (void)bWrite;
2757 ULONG nArgCount = rPar.Count()-1;
2759 if ( nArgCount < 3 || nArgCount > 5 )
2761 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2762 return;
2764 // retrieve non-optional params
2766 double rate = rPar.Get(1)->GetDouble();
2767 double pmt = rPar.Get(2)->GetDouble();
2768 double pv = rPar.Get(3)->GetDouble();
2770 // set default values for Optional args
2771 double fv = 0;
2772 double type = 0;
2774 // fv
2775 if ( nArgCount >= 4 )
2777 if( rPar.Get(4)->GetType() != SbxEMPTY )
2778 fv = rPar.Get(4)->GetDouble();
2780 // type
2781 if ( nArgCount >= 5 )
2783 if( rPar.Get(5)->GetType() != SbxEMPTY )
2784 type = rPar.Get(5)->GetDouble();
2787 Sequence< Any > aParams( 5 );
2788 aParams[ 0 ] <<= rate;
2789 aParams[ 1 ] <<= pmt;
2790 aParams[ 2 ] <<= pv;
2791 aParams[ 3 ] <<= fv;
2792 aParams[ 4 ] <<= type;
2794 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("NPer") ), rPar.Get( 0 ) );
2797 RTLFUNC(MIRR)
2799 (void)pBasic;
2800 (void)bWrite;
2802 ULONG nArgCount = rPar.Count()-1;
2804 if ( nArgCount < 3 )
2806 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2807 return;
2810 // retrieve non-optional params
2812 Sequence< Any > aParams( 3 );
2813 Any aValues = sbxToUnoValue( rPar.Get(1),
2814 getCppuType( (Sequence<double>*)0 ) );
2816 // convert for calc functions
2817 Sequence< Sequence< double > > sValues(1);
2818 aValues >>= sValues[ 0 ];
2819 aValues <<= sValues;
2821 aParams[ 0 ] <<= aValues;
2822 aParams[ 1 ] <<= makeAny( rPar.Get(2)->GetDouble() );
2823 aParams[ 2 ] <<= makeAny( rPar.Get(3)->GetDouble() );
2825 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("MIRR") ), rPar.Get( 0 ) );
2828 RTLFUNC(IRR)
2830 (void)pBasic;
2831 (void)bWrite;
2833 ULONG nArgCount = rPar.Count()-1;
2835 if ( nArgCount < 1 || nArgCount > 2 )
2837 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2838 return;
2840 // retrieve non-optional params
2841 Any aValues = sbxToUnoValue( rPar.Get(1),
2842 getCppuType( (Sequence<double>*)0 ) );
2844 // convert for calc functions
2845 Sequence< Sequence< double > > sValues(1);
2846 aValues >>= sValues[ 0 ];
2847 aValues <<= sValues;
2849 // set default values for Optional args
2850 double guess = 0.1;
2851 // guess
2852 if ( nArgCount >= 2 )
2854 if( rPar.Get(2)->GetType() != SbxEMPTY )
2855 guess = rPar.Get(2)->GetDouble();
2858 Sequence< Any > aParams( 2 );
2859 aParams[ 0 ] <<= aValues;
2860 aParams[ 1 ] <<= guess;
2862 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IRR") ), rPar.Get( 0 ) );
2865 RTLFUNC(IPmt)
2867 (void)pBasic;
2868 (void)bWrite;
2870 ULONG nArgCount = rPar.Count()-1;
2872 if ( nArgCount < 4 || nArgCount > 6 )
2874 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2875 return;
2877 // retrieve non-optional params
2879 double rate = rPar.Get(1)->GetDouble();
2880 double per = rPar.Get(2)->GetInteger();
2881 double nper = rPar.Get(3)->GetDouble();
2882 double pv = rPar.Get(4)->GetDouble();
2884 // set default values for Optional args
2885 double fv = 0;
2886 double type = 0;
2888 // fv
2889 if ( nArgCount >= 5 )
2891 if( rPar.Get(5)->GetType() != SbxEMPTY )
2892 fv = rPar.Get(5)->GetDouble();
2894 // type
2895 if ( nArgCount >= 6 )
2897 if( rPar.Get(6)->GetType() != SbxEMPTY )
2898 type = rPar.Get(6)->GetDouble();
2901 Sequence< Any > aParams( 6 );
2902 aParams[ 0 ] <<= rate;
2903 aParams[ 1 ] <<= per;
2904 aParams[ 2 ] <<= nper;
2905 aParams[ 3 ] <<= pv;
2906 aParams[ 4 ] <<= fv;
2907 aParams[ 5 ] <<= type;
2909 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IPmt") ), rPar.Get( 0 ) );
2912 RTLFUNC(FV)
2914 (void)pBasic;
2915 (void)bWrite;
2917 ULONG nArgCount = rPar.Count()-1;
2919 if ( nArgCount < 3 || nArgCount > 5 )
2921 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2922 return;
2924 // retrieve non-optional params
2926 double rate = rPar.Get(1)->GetDouble();
2927 double nper = rPar.Get(2)->GetDouble();
2928 double pmt = rPar.Get(3)->GetDouble();
2930 // set default values for Optional args
2931 double pv = 0;
2932 double type = 0;
2934 // pv
2935 if ( nArgCount >= 4 )
2937 if( rPar.Get(4)->GetType() != SbxEMPTY )
2938 pv = rPar.Get(4)->GetDouble();
2940 // type
2941 if ( nArgCount >= 5 )
2943 if( rPar.Get(5)->GetType() != SbxEMPTY )
2944 type = rPar.Get(5)->GetDouble();
2947 Sequence< Any > aParams( 5 );
2948 aParams[ 0 ] <<= rate;
2949 aParams[ 1 ] <<= nper;
2950 aParams[ 2 ] <<= pmt;
2951 aParams[ 3 ] <<= pv;
2952 aParams[ 4 ] <<= type;
2954 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FV") ), rPar.Get( 0 ) );
2957 RTLFUNC(DDB)
2959 (void)pBasic;
2960 (void)bWrite;
2962 ULONG nArgCount = rPar.Count()-1;
2964 if ( nArgCount < 4 || nArgCount > 5 )
2966 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2967 return;
2969 // retrieve non-optional params
2971 double cost = rPar.Get(1)->GetDouble();
2972 double salvage = rPar.Get(2)->GetDouble();
2973 double life = rPar.Get(3)->GetDouble();
2974 double period = rPar.Get(4)->GetDouble();
2976 // set default values for Optional args
2977 double factor = 2;
2979 // factor
2980 if ( nArgCount >= 5 )
2982 if( rPar.Get(5)->GetType() != SbxEMPTY )
2983 factor = rPar.Get(5)->GetDouble();
2986 Sequence< Any > aParams( 5 );
2987 aParams[ 0 ] <<= cost;
2988 aParams[ 1 ] <<= salvage;
2989 aParams[ 2 ] <<= life;
2990 aParams[ 3 ] <<= period;
2991 aParams[ 4 ] <<= factor;
2993 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DDB") ), rPar.Get( 0 ) );
2996 RTLFUNC(Rate)
2998 (void)pBasic;
2999 (void)bWrite;
3001 ULONG nArgCount = rPar.Count()-1;
3003 if ( nArgCount < 3 || nArgCount > 6 )
3005 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3006 return;
3008 // retrieve non-optional params
3010 double nper = 0;
3011 double pmt = 0;
3012 double pv = 0;
3014 nper = rPar.Get(1)->GetDouble();
3015 pmt = rPar.Get(2)->GetDouble();
3016 pv = rPar.Get(3)->GetDouble();
3018 // set default values for Optional args
3019 double fv = 0;
3020 double type = 0;
3021 double guess = 0.1;
3023 // fv
3024 if ( nArgCount >= 4 )
3026 if( rPar.Get(4)->GetType() != SbxEMPTY )
3027 fv = rPar.Get(4)->GetDouble();
3030 // type
3031 if ( nArgCount >= 5 )
3033 if( rPar.Get(5)->GetType() != SbxEMPTY )
3034 type = rPar.Get(5)->GetDouble();
3037 // guess
3038 if ( nArgCount >= 6 )
3040 if( rPar.Get(6)->GetType() != SbxEMPTY )
3041 type = rPar.Get(6)->GetDouble();
3044 Sequence< Any > aParams( 6 );
3045 aParams[ 0 ] <<= nper;
3046 aParams[ 1 ] <<= pmt;
3047 aParams[ 2 ] <<= pv;
3048 aParams[ 3 ] <<= fv;
3049 aParams[ 4 ] <<= type;
3050 aParams[ 5 ] <<= guess;
3052 CallFunctionAccessFunction( aParams, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Rate") ), rPar.Get( 0 ) );
3055 RTLFUNC(StrReverse)
3057 (void)pBasic;
3058 (void)bWrite;
3060 if ( rPar.Count() != 2 )
3062 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3063 return;
3066 SbxVariable *pSbxVariable = rPar.Get(1);
3067 if( pSbxVariable->IsNull() )
3069 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3070 return;
3073 String aStr = pSbxVariable->GetString();
3074 aStr.Reverse();
3075 rPar.Get(0)->PutString( aStr );
3078 RTLFUNC(CompatibilityMode)
3080 (void)pBasic;
3081 (void)bWrite;
3083 bool bEnabled = false;
3084 USHORT nCount = rPar.Count();
3085 if ( nCount != 1 && nCount != 2 )
3086 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3088 SbiInstance* pInst = pINST;
3089 if( pInst )
3091 if ( nCount == 2 )
3092 pInst->EnableCompatibility( rPar.Get(1)->GetBool() );
3094 bEnabled = pInst->IsCompatibility();
3096 rPar.Get(0)->PutBool( bEnabled );
3099 RTLFUNC(Input)
3101 (void)pBasic;
3102 (void)bWrite;
3104 // 2 parameters needed
3105 if ( rPar.Count() < 3 )
3107 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3108 return;
3111 USHORT nByteCount = rPar.Get(1)->GetUShort();
3112 INT16 nFileNumber = rPar.Get(2)->GetInteger();
3114 SbiIoSystem* pIosys = pINST->GetIoSystem();
3115 SbiStream* pSbStrm = pIosys->GetStream( nFileNumber );
3116 if ( !pSbStrm || !(pSbStrm->GetMode() & (SBSTRM_BINARY | SBSTRM_INPUT)) )
3118 StarBASIC::Error( SbERR_BAD_CHANNEL );
3119 return;
3122 ByteString aByteBuffer;
3123 SbError err = pSbStrm->Read( aByteBuffer, nByteCount, true );
3124 if( !err )
3125 err = pIosys->GetError();
3127 if( err )
3129 StarBASIC::Error( err );
3130 return;
3132 rPar.Get(0)->PutString( String( aByteBuffer, gsl_getSystemTextEncoding() ) );
3135 // #115824
3136 RTLFUNC(Me)
3138 (void)pBasic;
3139 (void)bWrite;
3141 SbModule* pActiveModule = pINST->GetActiveModule();
3142 SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pActiveModule);
3143 SbxVariableRef refVar = rPar.Get(0);
3144 if( pClassModuleObject == NULL )
3146 SbObjModule* pMod = PTR_CAST(SbObjModule,pActiveModule);
3147 if ( pMod )
3148 refVar->PutObject( pMod );
3150 else
3151 refVar->PutObject( pClassModuleObject );