1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/date.hxx>
21 #include <basic/sbxvar.hxx>
22 #include <basic/sbuno.hxx>
23 #include <osl/process.h>
24 #include <vcl/svapp.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/sound.hxx>
27 #include <tools/wintypes.hxx>
28 #include <vcl/msgbox.hxx>
29 #include <basic/sbx.hxx>
30 #include <svl/zforlist.hxx>
31 #include <rtl/math.hxx>
32 #include <tools/urlobj.hxx>
34 #include <unotools/charclass.hxx>
35 #include <unotools/ucbstreamhelper.hxx>
36 #include <tools/wldcrd.hxx>
37 #include <i18nlangtag/lang.h>
38 #include <rtl/string.hxx>
39 #include <rtl/strbuf.hxx>
41 #include "runtime.hxx"
42 #include "sbunoobj.hxx"
43 #include <osl/file.hxx>
44 #include "errobject.hxx"
46 #include <comphelper/processfactory.hxx>
47 #include <comphelper/string.hxx>
49 #include <com/sun/star/uno/Sequence.hxx>
50 #include <com/sun/star/util/DateTime.hpp>
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #include <com/sun/star/lang/Locale.hpp>
53 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
54 #include <com/sun/star/script/XErrorQuery.hpp>
55 #include <ooo/vba/XHelperInterface.hpp>
56 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
58 using namespace comphelper
;
60 using namespace com::sun::star
;
61 using namespace com::sun::star::lang
;
62 using namespace com::sun::star::uno
;
66 #include <basic/sbstdobj.hxx>
67 #include "rtlproto.hxx"
72 #include "ddectrl.hxx"
73 #include <sbintern.hxx>
74 #include <basic/vbahelper.hxx>
82 SbxVariable
* getDefaultProp( SbxVariable
* pRef
);
85 #include <direct.h> // _getdcwd get current work directory, _chdrive
93 #include <basic/sbobjmod.hxx>
97 #pragma warning (push, 1)
98 #pragma warning (disable: 4005)
102 #pragma warning (pop)
106 #undef GradientSyle_RECT
109 #ifndef DISABLE_SCRIPTING
111 // from source/classes/sbxmod.cxx
112 uno::Reference
< frame::XModel
> getDocumentModel( StarBASIC
* );
114 static void FilterWhiteSpace( OUString
& rStr
)
122 for (sal_Int32 i
= 0; i
< rStr
.getLength(); ++i
)
124 sal_Unicode cChar
= rStr
[i
];
125 if ((cChar
!= ' ') && (cChar
!= '\t') &&
126 (cChar
!= '\n') && (cChar
!= '\r'))
132 rStr
= aRet
.makeStringAndClear();
135 static long GetDayDiff( const Date
& rDate
);
137 static const CharClass
& GetCharClass( void )
139 static bool bNeedsInit
= true;
140 static LanguageTag
aLanguageTag( LANGUAGE_SYSTEM
);
144 aLanguageTag
= Application::GetSettings().GetLanguageTag();
146 static CharClass
aCharClass( aLanguageTag
);
150 static inline bool isFolder( FileStatus::Type aType
)
152 return ( aType
== FileStatus::Directory
|| aType
== FileStatus::Volume
);
156 //*** UCB file access ***
158 // Converts possibly relative paths to absolute paths
159 // according to the setting done by ChDir/ChDrive
160 OUString
getFullPath( const OUString
& aRelPath
)
164 // #80204 Try first if it already is a valid URL
165 INetURLObject
aURLObj( aRelPath
);
166 aFileURL
= aURLObj
.GetMainURL( INetURLObject::NO_DECODE
);
168 if( aFileURL
.isEmpty() )
170 File::getFileURLFromSystemPath( aRelPath
, aFileURL
);
176 // TODO: -> SbiGlobals
177 static uno::Reference
< ucb::XSimpleFileAccess3
> getFileAccess( void )
179 static uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
;
182 xSFI
= ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
189 // Properties and methods lie down the return value at the Get (bPut = sal_False) in the
190 // element 0 of the Argv; the value of element 0 is saved at Put (bPut = sal_True)
192 // CreateObject( class )
194 RTLFUNC(CreateObject
)
198 OUString
aClass( rPar
.Get( 1 )->GetOUString() );
199 SbxObjectRef p
= SbxBase::CreateObject( aClass
);
201 StarBASIC::Error( SbERR_CANNOT_LOAD
);
204 // Convenience: enter BASIC as parent
205 p
->SetParent( pBasic
);
206 rPar
.Get( 0 )->PutObject( p
);
217 StarBASIC::Error( SbERR_INTERNAL_ERROR
);
223 if( rPar
.Count() == 1 )
225 nErr
= StarBASIC::GetErrBasic();
226 aErrorMsg
= StarBASIC::GetErrorMsg();
230 nCode
= rPar
.Get( 1 )->GetLong();
233 StarBASIC::Error( SbERR_CONVERSION
);
237 nErr
= StarBASIC::GetSfxFromVBError( (sal_uInt16
)nCode
);
241 bool bVBA
= SbiRuntime::isVBAEnabled();
243 if( bVBA
&& !aErrorMsg
.isEmpty())
245 tmpErrMsg
= aErrorMsg
;
249 pBasic
->MakeErrorText( nErr
, aErrorMsg
);
250 tmpErrMsg
= pBasic
->GetErrorText();
252 // If this rtlfunc 'Error' passed a errcode the same as the active Err Objects's
253 // current err then return the description for the error message if it is set
254 // ( complicated isn't it ? )
255 if ( bVBA
&& rPar
.Count() > 1 )
257 uno::Reference
< ooo::vba::XErrObject
> xErrObj( SbxErrObject::getUnoErrObject() );
258 if ( xErrObj
.is() && xErrObj
->getNumber() == nCode
&& !xErrObj
->getDescription().isEmpty() )
260 tmpErrMsg
= xErrObj
->getDescription();
263 rPar
.Get( 0 )->PutString( tmpErrMsg
);
274 if ( rPar
.Count() < 2 )
275 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
278 SbxVariableRef pArg
= rPar
.Get( 1 );
279 rPar
.Get( 0 )->PutDouble( sin( pArg
->GetDouble() ) );
289 if ( rPar
.Count() < 2 )
290 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
293 SbxVariableRef pArg
= rPar
.Get( 1 );
294 rPar
.Get( 0 )->PutDouble( cos( pArg
->GetDouble() ) );
304 if ( rPar
.Count() < 2 )
305 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
308 SbxVariableRef pArg
= rPar
.Get( 1 );
309 rPar
.Get( 0 )->PutDouble( atan( pArg
->GetDouble() ) );
320 if ( rPar
.Count() < 2 )
322 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
326 SbxVariableRef pArg
= rPar
.Get( 1 );
327 rPar
.Get( 0 )->PutDouble( fabs( pArg
->GetDouble() ) );
337 if ( rPar
.Count() < 2 )
339 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
343 SbxVariableRef pArg
= rPar
.Get( 1 );
344 OUString
aStr( pArg
->GetOUString() );
347 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
348 rPar
.Get(0)->PutEmpty();
352 sal_Unicode aCh
= aStr
[0];
353 rPar
.Get(0)->PutLong( aCh
);
358 void implChr( SbxArray
& rPar
, bool bChrW
)
360 if ( rPar
.Count() < 2 )
362 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
366 SbxVariableRef pArg
= rPar
.Get( 1 );
369 if( !bChrW
&& SbiRuntime::isVBAEnabled() )
371 sal_Char c
= static_cast<sal_Char
>(pArg
->GetByte());
372 aStr
= OUString(&c
, 1, osl_getThreadTextEncoding());
376 sal_Unicode aCh
= static_cast<sal_Unicode
>(pArg
->GetUShort());
377 aStr
= OUString(aCh
);
379 rPar
.Get(0)->PutString( aStr
);
389 implChr( rPar
, bChrW
);
398 implChr( rPar
, bChrW
);
403 #define _PATH_INCR 250
411 // #57064 Although this function doesn't work with DirEntry, it isn't touched
412 // by the adjustment to virtual URLs, as, using the DirEntry-functionality,
413 // there's no possibility to detect the current one in a way that a virtual URL
414 // could be delivered.
417 int nCurDir
= 0; // Current dir // JSM
418 if ( rPar
.Count() == 2 )
420 OUString aDrive
= rPar
.Get(1)->GetOUString();
421 if ( aDrive
.getLength() != 1 )
423 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
428 nCurDir
= (int)aDrive
[0];
429 if ( !isalpha( nCurDir
) )
431 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
436 nCurDir
-= ( 'A' - 1 );
440 char* pBuffer
= new char[ _MAX_PATH
];
441 if ( _getdcwd( nCurDir
, pBuffer
, _MAX_PATH
) != 0 )
443 rPar
.Get(0)->PutString( OUString::createFromAscii( pBuffer
) );
447 StarBASIC::Error( SbERR_NO_DEVICE
);
453 int nSize
= _PATH_INCR
;
457 pMem
= new char[nSize
];
460 StarBASIC::Error( SbERR_NO_MEMORY
);
463 if( getcwd( pMem
, nSize
-1 ) != NULL
)
465 rPar
.Get(0)->PutString( OUString::createFromAscii(pMem
) );
469 if( errno
!= ERANGE
)
471 StarBASIC::Error( SbERR_INTERNAL_ERROR
);
486 rPar
.Get(0)->PutEmpty();
487 if (rPar
.Count() == 2)
489 // VBA: track current directory per document type (separately for Writer, Calc, Impress, etc.)
490 if( SbiRuntime::isVBAEnabled() )
492 ::basic::vba::registerCurrentDirectory( getDocumentModel( pBasic
), rPar
.Get(1)->GetOUString() );
497 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
506 rPar
.Get(0)->PutEmpty();
507 if (rPar
.Count() != 2)
509 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
514 // Implementation of StepRENAME with UCB
515 void implStepRenameUCB( const OUString
& aSource
, const OUString
& aDest
)
517 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
522 OUString aSourceFullPath
= getFullPath( aSource
);
523 if( !xSFI
->exists( aSourceFullPath
) )
525 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
529 OUString aDestFullPath
= getFullPath( aDest
);
530 if( xSFI
->exists( aDestFullPath
) )
532 StarBASIC::Error( SbERR_FILE_EXISTS
);
536 xSFI
->move( aSourceFullPath
, aDestFullPath
);
539 catch(const Exception
& )
541 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
546 // Implementation of StepRENAME with OSL
547 void implStepRenameOSL( const OUString
& aSource
, const OUString
& aDest
)
549 FileBase::RC nRet
= File::move( getFullPath( aSource
), getFullPath( aDest
) );
550 if( nRet
!= FileBase::E_None
)
552 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
561 rPar
.Get(0)->PutEmpty();
562 if (rPar
.Count() == 3)
564 OUString aSource
= rPar
.Get(1)->GetOUString();
565 OUString aDest
= rPar
.Get(2)->GetOUString();
568 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
573 xSFI
->copy( getFullPath( aSource
), getFullPath( aDest
) );
575 catch(const Exception
& )
577 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
583 FileBase::RC nRet
= File::copy( getFullPath( aSource
), getFullPath( aDest
) );
584 if( nRet
!= FileBase::E_None
)
586 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
591 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
599 rPar
.Get(0)->PutEmpty();
600 if (rPar
.Count() == 2)
602 OUString aFileSpec
= rPar
.Get(1)->GetOUString();
606 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
609 OUString aFullPath
= getFullPath( aFileSpec
);
610 if( !xSFI
->exists( aFullPath
) || xSFI
->isFolder( aFullPath
) )
612 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
617 xSFI
->kill( aFullPath
);
619 catch(const Exception
& )
621 StarBASIC::Error( ERRCODE_IO_GENERAL
);
627 File::remove( getFullPath( aFileSpec
) );
632 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
641 rPar
.Get(0)->PutEmpty();
642 if (rPar
.Count() == 2)
644 OUString aPath
= rPar
.Get(1)->GetOUString();
645 if ( SbiRuntime::isVBAEnabled() )
647 // In vba if the full path is not specified then
648 // folder is created relative to the curdir
649 INetURLObject
aURLObj( getFullPath( aPath
) );
650 if ( aURLObj
.GetProtocol() != INET_PROT_FILE
)
652 SbxArrayRef pPar
= new SbxArray();
653 SbxVariableRef pResult
= new SbxVariable();
654 SbxVariableRef pParam
= new SbxVariable();
655 pPar
->Insert( pResult
, pPar
->Count() );
656 pPar
->Insert( pParam
, pPar
->Count() );
657 SbRtl_CurDir( pBasic
, *pPar
, bWrite
);
659 rtl::OUString sCurPathURL
;
660 File::getFileURLFromSystemPath( pPar
->Get(0)->GetOUString(), sCurPathURL
);
662 aURLObj
.SetURL( sCurPathURL
);
663 aURLObj
.Append( aPath
);
664 File::getSystemPathFromFileURL(aURLObj
.GetMainURL( INetURLObject::DECODE_TO_IURI
),aPath
) ;
670 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
675 xSFI
->createFolder( getFullPath( aPath
) );
677 catch(const Exception
& )
679 StarBASIC::Error( ERRCODE_IO_GENERAL
);
685 Directory::create( getFullPath( aPath
) );
690 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
695 // In OSL only empty directories can be deleted
696 // so we have to delete all files recursively
697 void implRemoveDirRecursive( const OUString
& aDirPath
)
700 FileBase::RC nRet
= DirectoryItem::get( aDirPath
, aItem
);
701 bool bExists
= (nRet
== FileBase::E_None
);
703 FileStatus
aFileStatus( osl_FileStatus_Mask_Type
);
704 nRet
= aItem
.getFileStatus( aFileStatus
);
705 FileStatus::Type aType
= aFileStatus
.getFileType();
706 bool bFolder
= isFolder( aType
);
708 if( !bExists
|| !bFolder
)
710 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
714 Directory
aDir( aDirPath
);
716 if( nRet
!= FileBase::E_None
)
718 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
724 DirectoryItem aItem2
;
725 nRet
= aDir
.getNextItem( aItem2
);
726 if( nRet
!= FileBase::E_None
)
731 FileStatus
aFileStatus2( osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileURL
);
732 nRet
= aItem2
.getFileStatus( aFileStatus2
);
733 OUString aPath
= aFileStatus2
.getFileURL();
736 FileStatus::Type aType2
= aFileStatus2
.getFileType();
737 bool bFolder2
= isFolder( aType2
);
740 implRemoveDirRecursive( aPath
);
744 File::remove( aPath
);
749 nRet
= Directory::remove( aDirPath
);
758 rPar
.Get(0)->PutEmpty();
759 if (rPar
.Count() == 2)
761 OUString aPath
= rPar
.Get(1)->GetOUString();
764 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
769 if( !xSFI
->isFolder( aPath
) )
771 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
774 SbiInstance
* pInst
= GetSbData()->pInst
;
775 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
778 Sequence
< OUString
> aContent
= xSFI
->getFolderContents( aPath
, true );
779 sal_Int32 nCount
= aContent
.getLength();
782 StarBASIC::Error( SbERR_ACCESS_ERROR
);
787 xSFI
->kill( getFullPath( aPath
) );
789 catch(const Exception
& )
791 StarBASIC::Error( ERRCODE_IO_GENERAL
);
797 implRemoveDirRecursive( getFullPath( aPath
) );
802 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
811 rPar
.Get(0)->PutEmpty();
812 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
820 if( rPar
.Count() < 2 )
821 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
824 double aDouble
= rPar
.Get( 1 )->GetDouble();
825 aDouble
= exp( aDouble
);
826 checkArithmeticOverflow( aDouble
);
827 rPar
.Get( 0 )->PutDouble( aDouble
);
836 if ( rPar
.Count() < 2 )
838 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
842 SbxVariableRef pArg
= rPar
.Get( 1 );
843 OUString
aStr( pArg
->GetOUString() );
847 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
852 nLen
= xSFI
->getSize( getFullPath( aStr
) );
854 catch(const Exception
& )
856 StarBASIC::Error( ERRCODE_IO_GENERAL
);
863 DirectoryItem::get( getFullPath( aStr
), aItem
);
864 FileStatus
aFileStatus( osl_FileStatus_Mask_FileSize
);
865 aItem
.getFileStatus( aFileStatus
);
866 nLen
= (sal_Int32
)aFileStatus
.getFileSize();
868 rPar
.Get(0)->PutLong( (long)nLen
);
878 if ( rPar
.Count() < 2 )
880 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
884 SbxVariableRef pArg
= rPar
.Get( 1 );
885 // converting value to unsigned and limit to 2 or 4 byte representation
886 sal_uInt32 nVal
= pArg
->IsInteger() ?
887 static_cast<sal_uInt16
>(pArg
->GetInteger()) :
888 static_cast<sal_uInt32
>(pArg
->GetLong());
889 OUString
aStr(OUString::valueOf( sal_Int64(nVal
), 16 ));
890 aStr
= aStr
.toAsciiUpperCase();
891 rPar
.Get(0)->PutString( aStr
);
899 if ( SbiRuntime::isVBAEnabled() && GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
901 if ( GetSbData()->pInst
->pRun
->GetExternalCaller() )
902 *rPar
.Get(0) = *GetSbData()->pInst
->pRun
->GetExternalCaller();
905 SbxVariableRef pVar
= new SbxVariable(SbxVARIANT
);
906 *rPar
.Get(0) = *pVar
;
911 StarBASIC::Error( SbERR_NOT_IMPLEMENTED
);
915 // InStr( [start],string,string,[compare] )
922 sal_uIntPtr nArgCount
= rPar
.Count()-1;
924 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
927 sal_Int32 nStartPos
= 1;
928 sal_Int32 nFirstStringPos
= 1;
930 if ( nArgCount
>= 3 )
932 nStartPos
= rPar
.Get(1)->GetLong();
935 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
941 SbiInstance
* pInst
= GetSbData()->pInst
;
943 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
946 SbiRuntime
* pRT
= pInst
->pRun
;
947 bTextMode
= pRT
? pRT
->GetImageFlag( SBIMG_COMPARETEXT
) : sal_False
;
953 if ( nArgCount
== 4 )
955 bTextMode
= rPar
.Get(4)->GetInteger();
958 const OUString
& rToken
= rPar
.Get(nFirstStringPos
+1)->GetOUString();
960 // #97545 Always find empty string
961 if( rToken
.isEmpty() )
969 const OUString
& rStr1
= rPar
.Get(nFirstStringPos
)->GetOUString();
970 nPos
= rStr1
.indexOf( rToken
, nStartPos
- 1 ) + 1;
974 OUString aStr1
= rPar
.Get(nFirstStringPos
)->GetOUString();
975 OUString aToken
= rToken
;
977 aStr1
= aStr1
.toAsciiUpperCase();
978 aToken
= aToken
.toAsciiUpperCase();
980 nPos
= aStr1
.indexOf( aToken
, nStartPos
-1 ) + 1;
983 rPar
.Get(0)->PutLong( nPos
);
988 // InstrRev(string1, string2[, start[, compare]])
995 sal_uIntPtr nArgCount
= rPar
.Count()-1;
998 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1002 OUString aStr1
= rPar
.Get(1)->GetOUString();
1003 OUString aToken
= rPar
.Get(2)->GetOUString();
1005 sal_Int32 nStartPos
= -1;
1006 if ( nArgCount
>= 3 )
1008 nStartPos
= rPar
.Get(3)->GetLong();
1009 if( (nStartPos
<= 0 && nStartPos
!= -1))
1011 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1016 SbiInstance
* pInst
= GetSbData()->pInst
;
1018 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1019 if( bCompatibility
)
1021 SbiRuntime
* pRT
= pInst
->pRun
;
1022 bTextMode
= pRT
? pRT
->GetImageFlag( SBIMG_COMPARETEXT
) : sal_False
;
1028 if ( nArgCount
== 4 )
1030 bTextMode
= rPar
.Get(4)->GetInteger();
1032 sal_Int32 nStrLen
= aStr1
.getLength();
1033 if( nStartPos
== -1 )
1035 nStartPos
= nStrLen
;
1039 if( nStartPos
<= nStrLen
)
1041 sal_Int32 nTokenLen
= aToken
.getLength();
1044 // Always find empty string
1047 else if( nStrLen
> 0 )
1051 nPos
= aStr1
.lastIndexOf( aToken
, nStartPos
) + 1;
1055 aStr1
= aStr1
.toAsciiUpperCase();
1056 aToken
= aToken
.toAsciiUpperCase();
1058 nPos
= aStr1
.lastIndexOf( aToken
, nStartPos
) + 1;
1062 rPar
.Get(0)->PutLong( nPos
);
1071 Fix( -2.8 ) = -2.0 <- !!
1079 if ( rPar
.Count() < 2 )
1080 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1083 SbxVariableRef pArg
= rPar
.Get( 1 );
1084 double aDouble
= pArg
->GetDouble();
1087 floor( -2.8 ) = -3.0
1089 aDouble
= floor( aDouble
);
1090 rPar
.Get(0)->PutDouble( aDouble
);
1101 if ( rPar
.Count() < 2 )
1102 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1105 SbxVariableRef pArg
= rPar
.Get( 1 );
1106 double aDouble
= pArg
->GetDouble();
1107 if ( aDouble
>= 0.0 )
1108 aDouble
= floor( aDouble
);
1110 aDouble
= ceil( aDouble
);
1111 rPar
.Get(0)->PutDouble( aDouble
);
1121 if ( rPar
.Count() < 2 )
1123 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1127 const CharClass
& rCharClass
= GetCharClass();
1128 OUString
aStr( rPar
.Get(1)->GetOUString() );
1129 aStr
= rCharClass
.lowercase(aStr
);
1130 rPar
.Get(0)->PutString( aStr
);
1139 if ( rPar
.Count() < 3 )
1141 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1145 OUString
aStr( rPar
.Get(1)->GetOUString() );
1146 sal_Int32 nResultLen
= rPar
.Get(2)->GetLong();
1147 if( nResultLen
< 0 )
1150 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1152 else if(nResultLen
> aStr
.getLength())
1154 nResultLen
= aStr
.getLength();
1156 aStr
= aStr
.copy(0, nResultLen
);
1157 rPar
.Get(0)->PutString( aStr
);
1166 if ( rPar
.Count() < 2 )
1168 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1172 double aArg
= rPar
.Get(1)->GetDouble();
1175 double d
= log( aArg
);
1176 checkArithmeticOverflow( d
);
1177 rPar
.Get( 0 )->PutDouble( d
);
1181 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1191 if ( rPar
.Count() < 2 )
1193 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1197 OUString
aStr(comphelper::string::stripStart(rPar
.Get(1)->GetOUString(), ' '));
1198 rPar
.Get(0)->PutString(aStr
);
1203 // Mid( String, nStart, nLength )
1210 int nArgCount
= rPar
.Count()-1;
1211 if ( nArgCount
< 2 )
1213 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1217 // #23178: replicate the functionality of Mid$ as a command
1218 // by adding a replacement-string as a fourth parameter.
1219 // In contrast to the original the third parameter (nLength)
1220 // can't be left out here. That's considered in bWrite already.
1221 if( nArgCount
== 4 )
1225 OUString aArgStr
= rPar
.Get(1)->GetOUString();
1226 sal_Int32 nStartPos
= rPar
.Get(2)->GetLong();
1227 if ( nStartPos
== 0 )
1229 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1234 sal_Int32 nLen
= -1;
1235 bool bWriteNoLenParam
= false;
1236 if ( nArgCount
== 3 || bWrite
)
1238 sal_Int32 n
= rPar
.Get(3)->GetLong();
1239 if( bWrite
&& n
== -1 )
1241 bWriteNoLenParam
= true;
1247 OUStringBuffer aResultStr
;
1248 SbiInstance
* pInst
= GetSbData()->pInst
;
1249 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1250 if( bCompatibility
)
1252 sal_Int32 nArgLen
= aArgStr
.getLength();
1253 if( nStartPos
+ 1 > nArgLen
)
1255 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1259 OUString aReplaceStr
= rPar
.Get(4)->GetOUString();
1260 sal_Int32 nReplaceStrLen
= aReplaceStr
.getLength();
1261 sal_Int32 nReplaceLen
;
1262 if( bWriteNoLenParam
)
1264 nReplaceLen
= nReplaceStrLen
;
1269 if( nReplaceLen
< 0 || nReplaceLen
> nReplaceStrLen
)
1271 nReplaceLen
= nReplaceStrLen
;
1275 sal_Int32 nReplaceEndPos
= nStartPos
+ nReplaceLen
;
1276 if( nReplaceEndPos
> nArgLen
)
1278 nReplaceLen
-= (nReplaceEndPos
- nArgLen
);
1280 aResultStr
= aArgStr
;
1281 sal_Int32 nErase
= nReplaceLen
;
1282 aResultStr
.remove( nStartPos
, nErase
);
1283 aResultStr
.insert( nStartPos
, aReplaceStr
.getStr(), nReplaceLen
);
1287 aResultStr
= aArgStr
;
1288 sal_Int32 nTmpStartPos
= nStartPos
;
1289 if ( nTmpStartPos
> aArgStr
.getLength() )
1290 nTmpStartPos
= aArgStr
.getLength();
1292 aResultStr
.remove( nTmpStartPos
, nLen
);
1293 aResultStr
.insert( nTmpStartPos
, rPar
.Get(4)->GetOUString().getStr(), std::min(nLen
, rPar
.Get(4)->GetOUString().getLength()));
1296 rPar
.Get(1)->PutString( aResultStr
.makeStringAndClear() );
1300 OUString aResultStr
;
1303 aResultStr
= aArgStr
.copy( nStartPos
);
1307 if(nStartPos
+ nLen
> aArgStr
.getLength())
1309 nLen
= aArgStr
.getLength() - nStartPos
;
1312 aResultStr
= aArgStr
.copy( nStartPos
, nLen
);
1314 rPar
.Get(0)->PutString( aResultStr
);
1325 if ( rPar
.Count() < 2 )
1327 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1332 SbxVariableRef pArg
= rPar
.Get( 1 );
1333 if ( pArg
->IsInteger() )
1335 snprintf( aBuffer
, sizeof(aBuffer
), "%o", pArg
->GetInteger() );
1339 snprintf( aBuffer
, sizeof(aBuffer
), "%lo", static_cast<long unsigned int>(pArg
->GetLong()) );
1341 rPar
.Get(0)->PutString( OUString::createFromAscii( aBuffer
) );
1345 // Replace(expression, find, replace[, start[, count[, compare]]])
1352 sal_uIntPtr nArgCount
= rPar
.Count()-1;
1353 if ( nArgCount
< 3 || nArgCount
> 6 )
1355 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1359 OUString aExpStr
= rPar
.Get(1)->GetOUString();
1360 OUString aFindStr
= rPar
.Get(2)->GetOUString();
1361 OUString aReplaceStr
= rPar
.Get(3)->GetOUString();
1363 sal_Int32 lStartPos
= 1;
1364 if ( nArgCount
>= 4 )
1366 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
1368 lStartPos
= rPar
.Get(4)->GetLong();
1372 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1377 sal_Int32 lCount
= -1;
1380 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
1382 lCount
= rPar
.Get(5)->GetLong();
1386 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1391 SbiInstance
* pInst
= GetSbData()->pInst
;
1393 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1394 if( bCompatibility
)
1396 SbiRuntime
* pRT
= pInst
->pRun
;
1397 bTextMode
= pRT
? pRT
->GetImageFlag( SBIMG_COMPARETEXT
) : sal_False
;
1403 if ( nArgCount
== 6 )
1405 bTextMode
= rPar
.Get(6)->GetInteger();
1407 sal_Int32 nExpStrLen
= aExpStr
.getLength();
1408 sal_Int32 nFindStrLen
= aFindStr
.getLength();
1409 sal_Int32 nReplaceStrLen
= aReplaceStr
.getLength();
1411 if( lStartPos
<= nExpStrLen
)
1413 sal_Int32 nPos
= lStartPos
- 1;
1414 sal_Int32 nCounts
= 0;
1415 while( lCount
== -1 || lCount
> nCounts
)
1417 OUString
aSrcStr( aExpStr
);
1420 aSrcStr
= aSrcStr
.toAsciiUpperCase();
1421 aFindStr
= aFindStr
.toAsciiUpperCase();
1423 nPos
= aSrcStr
.indexOf( aFindStr
, nPos
);
1426 aExpStr
= aExpStr
.replaceAt( nPos
, nFindStrLen
, aReplaceStr
);
1427 nPos
= nPos
- nFindStrLen
+ nReplaceStrLen
+ 1;
1436 rPar
.Get(0)->PutString( aExpStr
.copy( lStartPos
- 1 ) );
1445 if ( rPar
.Count() < 3 )
1447 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1451 const OUString
& rStr
= rPar
.Get(1)->GetOUString();
1452 int nResultLen
= rPar
.Get(2)->GetLong();
1453 if( nResultLen
< 0 )
1456 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1458 int nStrLen
= rStr
.getLength();
1459 if ( nResultLen
> nStrLen
)
1461 nResultLen
= nStrLen
;
1463 OUString aResultStr
= rStr
.copy( nStrLen
- nResultLen
);
1464 rPar
.Get(0)->PutString( aResultStr
);
1473 rPar
.Get( 0 )->PutObject( pBasic
->getRTL() );
1481 if ( rPar
.Count() < 2 )
1483 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1487 OUString
aStr(comphelper::string::stripEnd(rPar
.Get(1)->GetOUString(), ' '));
1488 rPar
.Get(0)->PutString(aStr
);
1497 if ( rPar
.Count() < 2 )
1499 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1503 double aDouble
= rPar
.Get(1)->GetDouble();
1504 sal_Int16 nResult
= 0;
1509 else if ( aDouble
< 0 )
1513 rPar
.Get(0)->PutInteger( nResult
);
1522 if ( rPar
.Count() < 2 )
1524 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1528 OUStringBuffer aBuf
;
1529 string::padToLength(aBuf
, rPar
.Get(1)->GetLong(), ' ');
1530 rPar
.Get(0)->PutString(aBuf
.makeStringAndClear());
1539 if ( rPar
.Count() < 2 )
1541 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1545 OUStringBuffer aBuf
;
1546 string::padToLength(aBuf
, rPar
.Get(1)->GetLong(), ' ');
1547 rPar
.Get(0)->PutString(aBuf
.makeStringAndClear());
1556 if ( rPar
.Count() < 2 )
1558 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1562 double aDouble
= rPar
.Get(1)->GetDouble();
1565 rPar
.Get(0)->PutDouble( sqrt( aDouble
));
1569 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1579 if ( rPar
.Count() < 2 )
1581 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1586 OUString
aStrNew("");
1587 SbxVariableRef pArg
= rPar
.Get( 1 );
1588 pArg
->Format( aStr
);
1590 // Numbers start with a space
1591 if( pArg
->IsNumericRTL() )
1593 // replace commas by points so that it's symmetric to Val!
1594 aStr
= aStr
.replaceFirst( ",", "." );
1596 SbiInstance
* pInst
= GetSbData()->pInst
;
1597 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1598 if( bCompatibility
)
1600 sal_Int32 nLen
= aStr
.getLength();
1602 const sal_Unicode
* pBuf
= aStr
.getStr();
1604 bool bNeg
= ( pBuf
[0] == '-' );
1605 sal_Int32 iZeroSearch
= 0;
1613 if( pBuf
[0] != ' ' )
1618 sal_Int32 iNext
= iZeroSearch
+ 1;
1619 if( pBuf
[iZeroSearch
] == '0' && nLen
> iNext
&& pBuf
[iNext
] == '.' )
1623 aStrNew
+= aStr
.copy(iZeroSearch
);
1627 aStrNew
= " " + aStr
;
1634 rPar
.Get(0)->PutString( aStrNew
);
1643 if ( rPar
.Count() < 3 )
1645 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1646 rPar
.Get(0)->PutEmpty();
1649 const OUString
& rStr1
= rPar
.Get(1)->GetOUString();
1650 const OUString
& rStr2
= rPar
.Get(2)->GetOUString();
1652 SbiInstance
* pInst
= GetSbData()->pInst
;
1653 sal_Int16 nTextCompare
;
1654 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1655 if( bCompatibility
)
1657 SbiRuntime
* pRT
= pInst
->pRun
;
1658 nTextCompare
= pRT
? pRT
->GetImageFlag( SBIMG_COMPARETEXT
) : sal_False
;
1662 nTextCompare
= sal_True
;
1664 if ( rPar
.Count() == 4 )
1665 nTextCompare
= rPar
.Get(3)->GetInteger();
1667 if( !bCompatibility
)
1669 nTextCompare
= !nTextCompare
;
1671 sal_Int32 nRetValue
= 0;
1674 ::utl::TransliterationWrapper
* pTransliterationWrapper
= GetSbData()->pTransliterationWrapper
;
1675 if( !pTransliterationWrapper
)
1677 uno::Reference
< uno::XComponentContext
> xContext
= getProcessComponentContext();
1678 pTransliterationWrapper
= GetSbData()->pTransliterationWrapper
=
1679 new ::utl::TransliterationWrapper( xContext
,
1680 i18n::TransliterationModules_IGNORE_CASE
|
1681 i18n::TransliterationModules_IGNORE_KANA
|
1682 i18n::TransliterationModules_IGNORE_WIDTH
);
1685 LanguageType eLangType
= GetpApp()->GetSettings().GetLanguageTag().getLanguageType();
1686 pTransliterationWrapper
->loadModuleIfNeeded( eLangType
);
1687 nRetValue
= pTransliterationWrapper
->compareString( rStr1
, rStr2
);
1692 aResult
= rStr1
.compareTo( rStr2
);
1697 else if ( aResult
> 0)
1702 rPar
.Get(0)->PutInteger( sal::static_int_cast
< sal_Int16
>( nRetValue
) );
1710 if ( rPar
.Count() < 2 )
1712 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1716 sal_Unicode aFiller
;
1717 sal_Int32 lCount
= rPar
.Get(1)->GetLong();
1718 if( lCount
< 0 || lCount
> 0xffff )
1720 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1722 if( rPar
.Get(2)->GetType() == SbxINTEGER
)
1724 aFiller
= (sal_Unicode
)rPar
.Get(2)->GetInteger();
1728 const OUString
& rStr
= rPar
.Get(2)->GetOUString();
1731 OUStringBuffer
aBuf(lCount
);
1732 string::padToLength(aBuf
, lCount
, aFiller
);
1733 rPar
.Get(0)->PutString(aBuf
.makeStringAndClear());
1742 if ( rPar
.Count() < 2 )
1744 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1748 SbxVariableRef pArg
= rPar
.Get( 1 );
1749 rPar
.Get( 0 )->PutDouble( tan( pArg
->GetDouble() ) );
1758 if ( rPar
.Count() < 2 )
1760 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1764 const CharClass
& rCharClass
= GetCharClass();
1765 OUString
aStr( rPar
.Get(1)->GetOUString() );
1766 aStr
= rCharClass
.uppercase( aStr
);
1767 rPar
.Get(0)->PutString( aStr
);
1777 if ( rPar
.Count() < 2 )
1779 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1783 double nResult
= 0.0;
1786 OUString
aStr( rPar
.Get(1)->GetOUString() );
1788 FilterWhiteSpace( aStr
);
1789 if ( aStr
[0] == '&' && aStr
.getLength() > 1 )
1792 char aChar
= (char)aStr
[1];
1793 if ( aChar
== 'h' || aChar
== 'H' )
1797 else if ( aChar
== 'o' || aChar
== 'O' )
1803 OString
aByteStr(OUStringToOString(aStr
, osl_getThreadTextEncoding()));
1804 sal_Int16 nlResult
= (sal_Int16
)strtol( aByteStr
.getStr()+2, &pEndPtr
, nRadix
);
1805 nResult
= (double)nlResult
;
1810 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
1811 sal_Int32 nParseEnd
= 0;
1812 nResult
= ::rtl::math::stringToDouble( aStr
, '.', ',', &eStatus
, &nParseEnd
);
1813 if ( eStatus
!= rtl_math_ConversionStatus_Ok
)
1814 StarBASIC::Error( SbERR_MATH_OVERFLOW
);
1815 /* TODO: we should check whether all characters were parsed here,
1816 * but earlier code silently ignored trailing nonsense such as "1x"
1817 * resulting in 1 with the side effect that any alpha-only-string
1818 * like "x" resulted in 0. Not changing that now (2013-03-22) as
1819 * user macros may rely on it. */
1821 else if ( nParseEnd
!= aStr
.getLength() )
1822 StarBASIC::Error( SbERR_CONVERSION
);
1826 rPar
.Get(0)->PutDouble( nResult
);
1831 // Helper functions for date conversion
1832 sal_Int16
implGetDateDay( double aDate
)
1834 aDate
-= 2.0; // standardize: 1.1.1900 => 0.0
1835 Date
aRefDate( 1, 1, 1900 );
1838 aDate
= floor( aDate
);
1839 aRefDate
+= (sal_uIntPtr
)aDate
;
1843 aDate
= ceil( aDate
);
1844 aRefDate
-= (sal_uIntPtr
)(-1.0 * aDate
);
1847 sal_Int16 nRet
= (sal_Int16
)( aRefDate
.GetDay() );
1851 sal_Int16
implGetDateMonth( double aDate
)
1853 Date
aRefDate( 1,1,1900 );
1854 long nDays
= (long)aDate
;
1855 nDays
-= 2; // standardize: 1.1.1900 => 0.0
1857 sal_Int16 nRet
= (sal_Int16
)( aRefDate
.GetMonth() );
1861 ::com::sun::star::util::Date
SbxDateToUNODate( const SbxValue
* const pVal
)
1863 double aDate
= pVal
->GetDate();
1865 com::sun::star::util::Date aUnoDate
;
1866 aUnoDate
.Day
= implGetDateDay ( aDate
);
1867 aUnoDate
.Month
= implGetDateMonth( aDate
);
1868 aUnoDate
.Year
= implGetDateYear ( aDate
);
1873 void SbxDateFromUNODate( SbxValue
*pVal
, const ::com::sun::star::util::Date
& aUnoDate
)
1876 if( implDateSerial( aUnoDate
.Year
, aUnoDate
.Month
, aUnoDate
.Day
, dDate
) )
1878 pVal
->PutDate( dDate
);
1882 // Function to convert date to UNO date (com.sun.star.util.Date)
1883 RTLFUNC(CDateToUnoDate
)
1888 if ( rPar
.Count() != 2 )
1890 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1894 unoToSbxValue(rPar
.Get(0), Any(SbxDateToUNODate(rPar
.Get(1))));
1897 // Function to convert date from UNO date (com.sun.star.util.Date)
1898 RTLFUNC(CDateFromUnoDate
)
1903 if ( rPar
.Count() != 2 || rPar
.Get(1)->GetType() != SbxOBJECT
)
1905 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1909 Any
aAny (sbxToUnoValue(rPar
.Get(1), ::getCppuType( (com::sun::star::util::Date
*)0 )));
1910 com::sun::star::util::Date aUnoDate
;
1911 if(aAny
>>= aUnoDate
)
1912 SbxDateFromUNODate(rPar
.Get(0), aUnoDate
);
1914 SbxBase::SetError( SbxERR_CONVERSION
);
1917 ::com::sun::star::util::Time
SbxDateToUNOTime( const SbxValue
* const pVal
)
1919 double aDate
= pVal
->GetDate();
1921 com::sun::star::util::Time aUnoTime
;
1922 aUnoTime
.Hours
= implGetHour ( aDate
);
1923 aUnoTime
.Minutes
= implGetMinute ( aDate
);
1924 aUnoTime
.Seconds
= implGetSecond ( aDate
);
1925 aUnoTime
.NanoSeconds
= 0;
1930 void SbxDateFromUNOTime( SbxValue
*pVal
, const ::com::sun::star::util::Time
& aUnoTime
)
1932 pVal
->PutDate( implTimeSerial(aUnoTime
.Hours
, aUnoTime
.Minutes
, aUnoTime
.Seconds
) );
1935 // Function to convert date to UNO time (com.sun.star.util.Time)
1936 RTLFUNC(CDateToUnoTime
)
1941 if ( rPar
.Count() != 2 )
1943 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1947 unoToSbxValue(rPar
.Get(0), Any(SbxDateToUNOTime(rPar
.Get(1))));
1950 // Function to convert date from UNO time (com.sun.star.util.Time)
1951 RTLFUNC(CDateFromUnoTime
)
1956 if ( rPar
.Count() != 2 || rPar
.Get(1)->GetType() != SbxOBJECT
)
1958 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1962 Any
aAny (sbxToUnoValue(rPar
.Get(1), ::getCppuType( (com::sun::star::util::Time
*)0 )));
1963 com::sun::star::util::Time aUnoTime
;
1964 if(aAny
>>= aUnoTime
)
1965 SbxDateFromUNOTime(rPar
.Get(0), aUnoTime
);
1967 SbxBase::SetError( SbxERR_CONVERSION
);
1970 ::com::sun::star::util::DateTime
SbxDateToUNODateTime( const SbxValue
* const pVal
)
1972 double aDate
= pVal
->GetDate();
1974 com::sun::star::util::DateTime aUnoDT
;
1975 aUnoDT
.Day
= implGetDateDay ( aDate
);
1976 aUnoDT
.Month
= implGetDateMonth( aDate
);
1977 aUnoDT
.Year
= implGetDateYear ( aDate
);
1978 aUnoDT
.Hours
= implGetHour ( aDate
);
1979 aUnoDT
.Minutes
= implGetMinute ( aDate
);
1980 aUnoDT
.Seconds
= implGetSecond ( aDate
);
1981 aUnoDT
.NanoSeconds
= 0;
1986 void SbxDateFromUNODateTime( SbxValue
*pVal
, const ::com::sun::star::util::DateTime
& aUnoDT
)
1989 if( implDateTimeSerial( aUnoDT
.Year
, aUnoDT
.Month
, aUnoDT
.Day
,
1990 aUnoDT
.Hours
, aUnoDT
.Minutes
, aUnoDT
.Seconds
,
1993 pVal
->PutDate( dDate
);
1997 // Function to convert date to UNO date (com.sun.star.util.Date)
1998 RTLFUNC(CDateToUnoDateTime
)
2003 if ( rPar
.Count() != 2 )
2005 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2009 unoToSbxValue(rPar
.Get(0), Any(SbxDateToUNODateTime(rPar
.Get(1))));
2012 // Function to convert date from UNO date (com.sun.star.util.Date)
2013 RTLFUNC(CDateFromUnoDateTime
)
2018 if ( rPar
.Count() != 2 || rPar
.Get(1)->GetType() != SbxOBJECT
)
2020 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2024 Any
aAny (sbxToUnoValue(rPar
.Get(1), ::getCppuType( (com::sun::star::util::DateTime
*)0 )));
2025 com::sun::star::util::DateTime aUnoDT
;
2027 SbxDateFromUNODateTime(rPar
.Get(0), aUnoDT
);
2029 SbxBase::SetError( SbxERR_CONVERSION
);
2032 // Function to convert date to ISO 8601 date format
2038 if ( rPar
.Count() == 2 )
2040 double aDate
= rPar
.Get(1)->GetDate();
2043 snprintf( Buffer
, sizeof( Buffer
), "%04d%02d%02d",
2044 implGetDateYear( aDate
),
2045 implGetDateMonth( aDate
),
2046 implGetDateDay( aDate
) );
2047 OUString aRetStr
= OUString::createFromAscii( Buffer
);
2048 rPar
.Get(0)->PutString( aRetStr
);
2052 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2056 // Function to convert date from ISO 8601 date format
2057 RTLFUNC(CDateFromIso
)
2062 if ( rPar
.Count() == 2 )
2064 OUString aStr
= rPar
.Get(1)->GetOUString();
2065 sal_Int16 iMonthStart
= aStr
.getLength() - 4;
2066 OUString aYearStr
= aStr
.copy( 0, iMonthStart
);
2067 OUString aMonthStr
= aStr
.copy( iMonthStart
, 2 );
2068 OUString aDayStr
= aStr
.copy( iMonthStart
+2, 2 );
2071 if( implDateSerial( (sal_Int16
)aYearStr
.toInt32(),
2072 (sal_Int16
)aMonthStr
.toInt32(), (sal_Int16
)aDayStr
.toInt32(), dDate
) )
2074 rPar
.Get(0)->PutDate( dDate
);
2079 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2088 if ( rPar
.Count() < 4 )
2090 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2093 sal_Int16 nYear
= rPar
.Get(1)->GetInteger();
2094 sal_Int16 nMonth
= rPar
.Get(2)->GetInteger();
2095 sal_Int16 nDay
= rPar
.Get(3)->GetInteger();
2098 if( implDateSerial( nYear
, nMonth
, nDay
, dDate
) )
2100 rPar
.Get(0)->PutDate( dDate
);
2109 if ( rPar
.Count() < 4 )
2111 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2114 sal_Int16 nHour
= rPar
.Get(1)->GetInteger();
2117 nHour
= 0; // because of UNO DateTimes, which go till 24 o'clock
2119 sal_Int16 nMinute
= rPar
.Get(2)->GetInteger();
2120 sal_Int16 nSecond
= rPar
.Get(3)->GetInteger();
2121 if ((nHour
< 0 || nHour
> 23) ||
2122 (nMinute
< 0 || nMinute
> 59 ) ||
2123 (nSecond
< 0 || nSecond
> 59 ))
2125 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2129 rPar
.Get(0)->PutDate( implTimeSerial(nHour
, nMinute
, nSecond
) ); // JSM
2137 if ( rPar
.Count() < 2 )
2139 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2143 // #39629 check GetSbData()->pInst, can be called from the URL line
2144 SvNumberFormatter
* pFormatter
= NULL
;
2145 if( GetSbData()->pInst
)
2147 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2151 sal_uInt32 n
; // Dummy
2152 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, n
, n
);
2155 sal_uInt32 nIndex
= 0;
2157 OUString
aStr( rPar
.Get(1)->GetOUString() );
2158 sal_Bool bSuccess
= pFormatter
->IsNumberFormat( aStr
, nIndex
, fResult
);
2159 short nType
= pFormatter
->GetType( nIndex
);
2161 // DateValue("February 12, 1969") raises error if the system locale is not en_US
2162 // by using SbiInstance::GetNumberFormatter.
2163 // It seems that both locale number formatter and English number formatter
2164 // are supported in Visual Basic.
2165 LanguageType eLangType
= GetpApp()->GetSettings().GetLanguageTag().getLanguageType();
2166 if( !bSuccess
&& ( eLangType
!= LANGUAGE_ENGLISH_US
) )
2168 // Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value;
2169 SvNumberFormatter
aFormatter( comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US
);
2171 bSuccess
= aFormatter
.IsNumberFormat( aStr
, nIndex
, fResult
);
2172 nType
= aFormatter
.GetType( nIndex
);
2175 if(bSuccess
&& (nType
==NUMBERFORMAT_DATE
|| nType
==NUMBERFORMAT_DATETIME
))
2177 if ( nType
== NUMBERFORMAT_DATETIME
)
2180 if ( fResult
> 0.0 )
2182 fResult
= floor( fResult
);
2186 fResult
= ceil( fResult
);
2189 rPar
.Get(0)->PutDate( fResult
);
2193 StarBASIC::Error( SbERR_CONVERSION
);
2195 // #39629 pFormatter can be requested itself
2196 if( !GetSbData()->pInst
)
2208 if ( rPar
.Count() < 2 )
2210 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2214 SvNumberFormatter
* pFormatter
= NULL
;
2215 if( GetSbData()->pInst
)
2216 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2220 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, n
, n
);
2223 sal_uInt32 nIndex
= 0;
2225 sal_Bool bSuccess
= pFormatter
->IsNumberFormat( rPar
.Get(1)->GetOUString(),
2227 short nType
= pFormatter
->GetType(nIndex
);
2228 if(bSuccess
&& (nType
==NUMBERFORMAT_TIME
||nType
==NUMBERFORMAT_DATETIME
))
2230 if ( nType
== NUMBERFORMAT_DATETIME
)
2233 fResult
= fmod( fResult
, 1 );
2235 rPar
.Get(0)->PutDate( fResult
);
2239 StarBASIC::Error( SbERR_CONVERSION
);
2241 if( !GetSbData()->pInst
)
2253 if ( rPar
.Count() < 2 )
2255 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2259 SbxVariableRef pArg
= rPar
.Get( 1 );
2260 double aDate
= pArg
->GetDate();
2262 sal_Int16 nDay
= implGetDateDay( aDate
);
2263 rPar
.Get(0)->PutInteger( nDay
);
2272 if ( rPar
.Count() < 2 )
2274 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2278 sal_Int16 nYear
= implGetDateYear( rPar
.Get(1)->GetDate() );
2279 rPar
.Get(0)->PutInteger( nYear
);
2283 sal_Int16
implGetHour( double dDate
)
2289 double nFrac
= dDate
- floor( dDate
);
2291 sal_Int32 nSeconds
= (sal_Int32
)(nFrac
+ 0.5);
2292 sal_Int16 nHour
= (sal_Int16
)(nSeconds
/ 3600);
2301 if ( rPar
.Count() < 2 )
2303 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2307 double nArg
= rPar
.Get(1)->GetDate();
2308 sal_Int16 nHour
= implGetHour( nArg
);
2309 rPar
.Get(0)->PutInteger( nHour
);
2318 if ( rPar
.Count() < 2 )
2320 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2324 double nArg
= rPar
.Get(1)->GetDate();
2325 sal_Int16 nMin
= implGetMinute( nArg
);
2326 rPar
.Get(0)->PutInteger( nMin
);
2335 if ( rPar
.Count() < 2 )
2337 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2341 sal_Int16 nMonth
= implGetDateMonth( rPar
.Get(1)->GetDate() );
2342 rPar
.Get(0)->PutInteger( nMonth
);
2346 sal_Int16
implGetSecond( double dDate
)
2352 double nFrac
= dDate
- floor( dDate
);
2354 sal_Int32 nSeconds
= (sal_Int32
)(nFrac
+ 0.5);
2355 sal_Int16 nTemp
= (sal_Int16
)(nSeconds
/ 3600);
2356 nSeconds
-= nTemp
* 3600;
2357 nTemp
= (sal_Int16
)(nSeconds
/ 60);
2358 nSeconds
-= nTemp
* 60;
2360 sal_Int16 nRet
= (sal_Int16
)nSeconds
;
2369 if ( rPar
.Count() < 2 )
2371 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2375 double nArg
= rPar
.Get(1)->GetDate();
2376 sal_Int16 nSecond
= implGetSecond( nArg
);
2377 rPar
.Get(0)->PutInteger( nSecond
);
2383 Date
aDate( Date::SYSTEM
);
2384 Time
aTime( Time::SYSTEM
);
2385 double aSerial
= (double)GetDayDiff( aDate
);
2386 long nSeconds
= aTime
.GetHour();
2388 nSeconds
+= aTime
.GetMin() * 60;
2389 nSeconds
+= aTime
.GetSec();
2390 double nDays
= ((double)nSeconds
) / (double)(24.0*3600.0);
2401 rPar
.Get(0)->PutDate( Now_Impl() );
2412 Time
aTime( Time::SYSTEM
);
2413 SbxVariable
* pMeth
= rPar
.Get( 0 );
2415 if( pMeth
->IsFixed() )
2419 snprintf( buf
, sizeof(buf
), "%02d:%02d:%02d",
2420 aTime
.GetHour(), aTime
.GetMin(), aTime
.GetSec() );
2421 aRes
= OUString::createFromAscii( buf
);
2425 // Time: system dependent
2426 long nSeconds
=aTime
.GetHour();
2428 nSeconds
+= aTime
.GetMin() * 60;
2429 nSeconds
+= aTime
.GetSec();
2430 double nDays
= (double)nSeconds
* ( 1.0 / (24.0*3600.0) );
2433 SvNumberFormatter
* pFormatter
= NULL
;
2435 if( GetSbData()->pInst
)
2437 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2438 nIndex
= GetSbData()->pInst
->GetStdTimeIdx();
2442 sal_uInt32 n
; // Dummy
2443 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, nIndex
, n
);
2446 pFormatter
->GetOutputString( nDays
, nIndex
, aRes
, &pCol
);
2448 if( !GetSbData()->pInst
)
2453 pMeth
->PutString( aRes
);
2457 StarBASIC::Error( SbERR_NOT_IMPLEMENTED
);
2466 Time
aTime( Time::SYSTEM
);
2467 long nSeconds
= aTime
.GetHour();
2469 nSeconds
+= aTime
.GetMin() * 60;
2470 nSeconds
+= aTime
.GetSec();
2471 rPar
.Get(0)->PutDate( (double)nSeconds
);
2482 Date
aToday( Date::SYSTEM
);
2483 double nDays
= (double)GetDayDiff( aToday
);
2484 SbxVariable
* pMeth
= rPar
.Get( 0 );
2485 if( pMeth
->IsString() )
2490 SvNumberFormatter
* pFormatter
= NULL
;
2492 if( GetSbData()->pInst
)
2494 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2495 nIndex
= GetSbData()->pInst
->GetStdDateIdx();
2500 SbiInstance::PrepareNumberFormatter( pFormatter
, nIndex
, n
, n
);
2503 pFormatter
->GetOutputString( nDays
, nIndex
, aRes
, &pCol
);
2504 pMeth
->PutString( aRes
);
2506 if( !GetSbData()->pInst
)
2513 pMeth
->PutDate( nDays
);
2518 StarBASIC::Error( SbERR_NOT_IMPLEMENTED
);
2527 if ( rPar
.Count() < 2 )
2529 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2533 rPar
.Get(0)->PutBool((rPar
.Get(1)->GetType() & SbxARRAY
) ? sal_True
: sal_False
);
2542 if ( rPar
.Count() < 2 )
2544 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2548 SbxVariable
* pVar
= rPar
.Get(1);
2549 SbxBase
* pObj
= (SbxBase
*)pVar
->GetObject();
2551 // #100385: GetObject can result in an error, so reset it
2552 SbxBase::ResetError();
2554 SbUnoClass
* pUnoClass
;
2556 if( pObj
&& NULL
!= ( pUnoClass
=PTR_CAST(SbUnoClass
,pObj
) ) )
2558 bObject
= pUnoClass
->getUnoClass().is();
2562 bObject
= pVar
->IsObject();
2564 rPar
.Get( 0 )->PutBool( bObject
);
2573 if ( rPar
.Count() < 2 )
2575 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2579 // #46134 only string is converted, all other types result in sal_False
2580 SbxVariableRef xArg
= rPar
.Get( 1 );
2581 SbxDataType eType
= xArg
->GetType();
2582 sal_Bool bDate
= sal_False
;
2584 if( eType
== SbxDATE
)
2588 else if( eType
== SbxSTRING
)
2590 SbxError nPrevError
= SbxBase::GetError();
2591 SbxBase::ResetError();
2593 // force conversion of the parameter to SbxDATE
2594 xArg
->SbxValue::GetDate();
2596 bDate
= !SbxBase::IsError();
2598 SbxBase::ResetError();
2599 SbxBase::SetError( nPrevError
);
2601 rPar
.Get( 0 )->PutBool( bDate
);
2610 if ( rPar
.Count() < 2 )
2612 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2616 SbxVariable
* pVar
= NULL
;
2617 if( SbiRuntime::isVBAEnabled() )
2619 pVar
= getDefaultProp( rPar
.Get(1) );
2623 pVar
->Broadcast( SBX_HINT_DATAWANTED
);
2624 rPar
.Get( 0 )->PutBool( pVar
->IsEmpty() );
2628 rPar
.Get( 0 )->PutBool( rPar
.Get(1)->IsEmpty() );
2638 if ( rPar
.Count() < 2 )
2640 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2644 SbxVariable
* pVar
=rPar
.Get( 1 );
2645 SbUnoObject
* pObj
= PTR_CAST(SbUnoObject
,pVar
);
2648 if ( SbxBase
* pBaseObj
= pVar
->GetObject() )
2650 pObj
= PTR_CAST(SbUnoObject
, pBaseObj
);
2653 uno::Reference
< script::XErrorQuery
> xError
;
2656 xError
.set( pObj
->getUnoAny(), uno::UNO_QUERY
);
2660 rPar
.Get( 0 )->PutBool( xError
->hasError() );
2664 rPar
.Get( 0 )->PutBool( rPar
.Get(1)->IsErr() );
2674 if ( rPar
.Count() < 2 )
2676 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2680 // #51475 because of Uno-objects return true
2681 // even if the pObj value is NULL
2682 SbxVariableRef pArg
= rPar
.Get( 1 );
2683 sal_Bool bNull
= rPar
.Get(1)->IsNull();
2684 if( !bNull
&& pArg
->GetType() == SbxOBJECT
)
2686 SbxBase
* pObj
= pArg
->GetObject();
2692 rPar
.Get( 0 )->PutBool( bNull
);
2701 if ( rPar
.Count() < 2 )
2703 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2707 rPar
.Get( 0 )->PutBool( rPar
.Get( 1 )->IsNumericRTL() );
2718 if ( rPar
.Count() < 2 )
2720 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2724 // #57915 Missing is reported by an error
2725 rPar
.Get( 0 )->PutBool( rPar
.Get(1)->IsErr() );
2729 // Function looks for wildcards, removes them and always returns the pure path
2730 OUString
implSetupWildcard( const OUString
& rFileParam
, SbiRTLData
* pRTLData
)
2732 static sal_Char cDelim1
= (sal_Char
)'/';
2733 static sal_Char cDelim2
= (sal_Char
)'\\';
2734 static sal_Char cWild1
= '*';
2735 static sal_Char cWild2
= '?';
2737 delete pRTLData
->pWildCard
;
2738 pRTLData
->pWildCard
= NULL
;
2739 pRTLData
->sFullNameToBeChecked
= OUString();
2741 OUString aFileParam
= rFileParam
;
2742 sal_Int32 nLastWild
= aFileParam
.lastIndexOf( cWild1
);
2745 nLastWild
= aFileParam
.lastIndexOf( cWild2
);
2747 bool bHasWildcards
= ( nLastWild
>= 0 );
2750 sal_Int32 nLastDelim
= aFileParam
.lastIndexOf( cDelim1
);
2751 if( nLastDelim
< 0 )
2753 nLastDelim
= aFileParam
.lastIndexOf( cDelim2
);
2757 // Wildcards in path?
2758 if( nLastDelim
>= 0 && nLastDelim
> nLastWild
)
2765 OUString aPathStr
= getFullPath( aFileParam
);
2766 if( nLastDelim
!= aFileParam
.getLength() - 1 )
2768 pRTLData
->sFullNameToBeChecked
= aPathStr
;
2773 OUString aPureFileName
;
2774 if( nLastDelim
< 0 )
2776 aPureFileName
= aFileParam
;
2777 aFileParam
= OUString();
2781 aPureFileName
= aFileParam
.copy( nLastDelim
+ 1 );
2782 aFileParam
= aFileParam
.copy( 0, nLastDelim
);
2785 // Try again to get a valid URL/UNC-path with only the path
2786 OUString aPathStr
= getFullPath( aFileParam
);
2788 // Is there a pure file name left? Otherwise the path is
2789 // invalid anyway because it was not accepted by OSL before
2790 if (!string::equals(aPureFileName
, '*'))
2792 pRTLData
->pWildCard
= new WildCard( aPureFileName
);
2797 inline sal_Bool
implCheckWildcard( const OUString
& rName
, SbiRTLData
* pRTLData
)
2799 sal_Bool bMatch
= sal_True
;
2801 if( pRTLData
->pWildCard
)
2803 bMatch
= pRTLData
->pWildCard
->Matches( rName
);
2809 bool isRootDir( OUString aDirURLStr
)
2811 INetURLObject
aDirURLObj( aDirURLStr
);
2814 // Check if it's a root directory
2815 sal_Int32 nCount
= aDirURLObj
.getSegmentCount();
2817 // No segment means Unix root directory "file:///"
2822 // Exactly one segment needs further checking, because it
2823 // can be Unix "file:///foo/" -> no root
2824 // or Windows "file:///c:/" -> root
2825 else if( nCount
== 1 )
2827 OUString aSeg1
= aDirURLObj
.getName( 0, sal_True
,
2828 INetURLObject::DECODE_WITH_CHARSET
);
2829 if( aSeg1
[1] == (sal_Unicode
)':' )
2834 // More than one segments can never be root
2835 // so bRoot remains false
2847 sal_uInt16 nParCount
= rPar
.Count();
2850 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2854 SbiRTLData
* pRTLData
= GetSbData()->pInst
->GetRTLData();
2856 // #34645: can also be called from the URL line via 'macro: Dir'
2857 // there's no pRTLDate existing in that case and the method must be left
2864 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
2867 if ( nParCount
>= 2 )
2869 OUString aFileParam
= rPar
.Get(1)->GetOUString();
2871 OUString aFileURLStr
= implSetupWildcard( aFileParam
, pRTLData
);
2872 if( !pRTLData
->sFullNameToBeChecked
.isEmpty())
2874 sal_Bool bExists
= sal_False
;
2875 try { bExists
= xSFI
->exists( aFileURLStr
); }
2876 catch(const Exception
& ) {}
2878 OUString aNameOnlyStr
;
2881 INetURLObject
aFileURL( aFileURLStr
);
2882 aNameOnlyStr
= aFileURL
.getName( INetURLObject::LAST_SEGMENT
,
2883 true, INetURLObject::DECODE_WITH_CHARSET
);
2885 rPar
.Get(0)->PutString( aNameOnlyStr
);
2891 OUString aDirURLStr
;
2892 sal_Bool bFolder
= xSFI
->isFolder( aFileURLStr
);
2896 aDirURLStr
= aFileURLStr
;
2901 rPar
.Get(0)->PutString( aEmptyStr
);
2904 sal_uInt16 nFlags
= 0;
2905 if ( nParCount
> 2 )
2907 pRTLData
->nDirFlags
= nFlags
= rPar
.Get(2)->GetInteger();
2911 pRTLData
->nDirFlags
= 0;
2914 sal_Bool bIncludeFolders
= ((nFlags
& Sb_ATTR_DIRECTORY
) != 0);
2915 pRTLData
->aDirSeq
= xSFI
->getFolderContents( aDirURLStr
, bIncludeFolders
);
2916 pRTLData
->nCurDirPos
= 0;
2918 // #78651 Add "." and ".." directories for VB compatibility
2919 if( bIncludeFolders
)
2921 bool bRoot
= isRootDir( aDirURLStr
);
2923 // If it's no root directory we flag the need for
2924 // the "." and ".." directories by the value -2
2925 // for the actual position. Later for -2 will be
2926 // returned "." and for -1 ".."
2929 pRTLData
->nCurDirPos
= -2;
2933 catch(const Exception
& )
2939 if( pRTLData
->aDirSeq
.getLength() > 0 )
2941 bool bFolderFlag
= ((pRTLData
->nDirFlags
& Sb_ATTR_DIRECTORY
) != 0);
2943 SbiInstance
* pInst
= GetSbData()->pInst
;
2944 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
2947 if( pRTLData
->nCurDirPos
< 0 )
2949 if( pRTLData
->nCurDirPos
== -2 )
2951 aPath
= OUString("." );
2953 else if( pRTLData
->nCurDirPos
== -1 )
2955 aPath
= OUString(".." );
2957 pRTLData
->nCurDirPos
++;
2959 else if( pRTLData
->nCurDirPos
>= pRTLData
->aDirSeq
.getLength() )
2961 pRTLData
->aDirSeq
.realloc( 0 );
2967 OUString aFile
= pRTLData
->aDirSeq
.getConstArray()[pRTLData
->nCurDirPos
++];
2969 if( bCompatibility
)
2973 sal_Bool bFolder
= xSFI
->isFolder( aFile
);
2985 sal_Bool bFolder
= xSFI
->isFolder( aFile
);
2993 INetURLObject
aURL( aFile
);
2994 aPath
= aURL
.getName( INetURLObject::LAST_SEGMENT
, sal_True
,
2995 INetURLObject::DECODE_WITH_CHARSET
);
2998 sal_Bool bMatch
= implCheckWildcard( aPath
, pRTLData
);
3006 rPar
.Get(0)->PutString( aPath
);
3012 if ( nParCount
>= 2 )
3014 OUString aFileParam
= rPar
.Get(1)->GetOUString();
3016 OUString aDirURL
= implSetupWildcard( aFileParam
, pRTLData
);
3018 sal_uInt16 nFlags
= 0;
3019 if ( nParCount
> 2 )
3021 pRTLData
->nDirFlags
= nFlags
= rPar
.Get(2)->GetInteger();
3025 pRTLData
->nDirFlags
= 0;
3029 bool bIncludeFolders
= ((nFlags
& Sb_ATTR_DIRECTORY
) != 0);
3030 pRTLData
->pDir
= new Directory( aDirURL
);
3031 FileBase::RC nRet
= pRTLData
->pDir
->open();
3032 if( nRet
!= FileBase::E_None
)
3034 delete pRTLData
->pDir
;
3035 pRTLData
->pDir
= NULL
;
3036 rPar
.Get(0)->PutString( OUString() );
3040 // #86950 Add "." and ".." directories for VB compatibility
3041 pRTLData
->nCurDirPos
= 0;
3042 if( bIncludeFolders
)
3044 bool bRoot
= isRootDir( aDirURL
);
3046 // If it's no root directory we flag the need for
3047 // the "." and ".." directories by the value -2
3048 // for the actual position. Later for -2 will be
3049 // returned "." and for -1 ".."
3052 pRTLData
->nCurDirPos
= -2;
3058 if( pRTLData
->pDir
)
3060 bool bFolderFlag
= ((pRTLData
->nDirFlags
& Sb_ATTR_DIRECTORY
) != 0);
3063 if( pRTLData
->nCurDirPos
< 0 )
3065 if( pRTLData
->nCurDirPos
== -2 )
3067 aPath
= OUString("." );
3069 else if( pRTLData
->nCurDirPos
== -1 )
3071 aPath
= OUString(".." );
3073 pRTLData
->nCurDirPos
++;
3077 DirectoryItem aItem
;
3078 FileBase::RC nRet
= pRTLData
->pDir
->getNextItem( aItem
);
3079 if( nRet
!= FileBase::E_None
)
3081 delete pRTLData
->pDir
;
3082 pRTLData
->pDir
= NULL
;
3088 FileStatus
aFileStatus( osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
);
3089 nRet
= aItem
.getFileStatus( aFileStatus
);
3091 // Only directories?
3094 FileStatus::Type aType
= aFileStatus
.getFileType();
3095 bool bFolder
= isFolder( aType
);
3102 aPath
= aFileStatus
.getFileName();
3105 sal_Bool bMatch
= implCheckWildcard( aPath
, pRTLData
);
3113 rPar
.Get(0)->PutString( aPath
);
3124 if ( rPar
.Count() == 2 )
3126 sal_Int16 nFlags
= 0;
3128 // In Windows, we want to use Windows API to get the file attributes
3129 // for VBA interoperability.
3131 if( SbiRuntime::isVBAEnabled() )
3133 OUString aPathURL
= getFullPath( rPar
.Get(1)->GetOUString() );
3135 FileBase::getSystemPathFromFileURL( aPathURL
, aPath
);
3136 OString
aSystemPath(OUStringToOString(aPath
, osl_getThreadTextEncoding()));
3137 DWORD nRealFlags
= GetFileAttributes (aSystemPath
.getStr());
3138 if (nRealFlags
!= 0xffffffff)
3140 if (nRealFlags
== FILE_ATTRIBUTE_NORMAL
)
3144 nFlags
= (sal_Int16
) (nRealFlags
);
3148 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
3150 rPar
.Get(0)->PutInteger( nFlags
);
3158 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
3163 OUString aPath
= getFullPath( rPar
.Get(1)->GetOUString() );
3164 sal_Bool bExists
= sal_False
;
3165 try { bExists
= xSFI
->exists( aPath
); }
3166 catch(const Exception
& ) {}
3169 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
3173 sal_Bool bReadOnly
= xSFI
->isReadOnly( aPath
);
3174 sal_Bool bHidden
= xSFI
->isHidden( aPath
);
3175 sal_Bool bDirectory
= xSFI
->isFolder( aPath
);
3178 nFlags
|= Sb_ATTR_READONLY
;
3182 nFlags
|= Sb_ATTR_HIDDEN
;
3186 nFlags
|= Sb_ATTR_DIRECTORY
;
3189 catch(const Exception
& )
3191 StarBASIC::Error( ERRCODE_IO_GENERAL
);
3197 DirectoryItem aItem
;
3198 DirectoryItem::get( getFullPath( rPar
.Get(1)->GetOUString() ), aItem
);
3199 FileStatus
aFileStatus( osl_FileStatus_Mask_Attributes
| osl_FileStatus_Mask_Type
);
3200 aItem
.getFileStatus( aFileStatus
);
3201 sal_uInt64 nAttributes
= aFileStatus
.getAttributes();
3202 bool bReadOnly
= (nAttributes
& osl_File_Attribute_ReadOnly
) != 0;
3204 FileStatus::Type aType
= aFileStatus
.getFileType();
3205 bool bDirectory
= isFolder( aType
);
3208 nFlags
|= Sb_ATTR_READONLY
;
3212 nFlags
|= Sb_ATTR_DIRECTORY
;
3215 rPar
.Get(0)->PutInteger( nFlags
);
3219 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3224 RTLFUNC(FileDateTime
)
3229 if ( rPar
.Count() != 2 )
3231 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3235 OUString aPath
= rPar
.Get(1)->GetOUString();
3236 Time
aTime( Time::EMPTY
);
3237 Date
aDate( Date::EMPTY
);
3240 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
3245 util::DateTime aUnoDT
= xSFI
->getDateTimeModified( aPath
);
3246 aTime
= Time( aUnoDT
.Hours
, aUnoDT
.Minutes
, aUnoDT
.Seconds
, aUnoDT
.NanoSeconds
);
3247 aDate
= Date( aUnoDT
.Day
, aUnoDT
.Month
, aUnoDT
.Year
);
3249 catch(const Exception
& )
3251 StarBASIC::Error( ERRCODE_IO_GENERAL
);
3257 DirectoryItem aItem
;
3258 DirectoryItem::get( getFullPath( aPath
), aItem
);
3259 FileStatus
aFileStatus( osl_FileStatus_Mask_ModifyTime
);
3260 aItem
.getFileStatus( aFileStatus
);
3261 TimeValue aTimeVal
= aFileStatus
.getModifyTime();
3263 osl_getDateTimeFromTimeValue( &aTimeVal
, &aDT
);
3265 aTime
= Time( aDT
.Hours
, aDT
.Minutes
, aDT
.Seconds
, aDT
.NanoSeconds
);
3266 aDate
= Date( aDT
.Day
, aDT
.Month
, aDT
.Year
);
3269 double fSerial
= (double)GetDayDiff( aDate
);
3270 long nSeconds
= aTime
.GetHour();
3272 nSeconds
+= aTime
.GetMin() * 60;
3273 nSeconds
+= aTime
.GetSec();
3274 double nDays
= ((double)nSeconds
) / (double)(24.0*3600.0);
3279 SvNumberFormatter
* pFormatter
= NULL
;
3281 if( GetSbData()->pInst
)
3283 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
3284 nIndex
= GetSbData()->pInst
->GetStdDateTimeIdx();
3289 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, n
, nIndex
);
3293 pFormatter
->GetOutputString( fSerial
, nIndex
, aRes
, &pCol
);
3294 rPar
.Get(0)->PutString( aRes
);
3296 if( !GetSbData()->pInst
)
3309 // No changes for UCB
3310 if ( rPar
.Count() != 2 )
3312 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3316 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3317 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3318 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3321 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3325 SvStream
* pSvStrm
= pSbStrm
->GetStrm();
3326 if ( pSbStrm
->IsText() )
3329 (*pSvStrm
) >> cBla
; // can we read another character?
3330 bIsEof
= pSvStrm
->IsEof();
3333 pSvStrm
->SeekRel( -1 );
3338 bIsEof
= pSvStrm
->IsEof(); // for binary data!
3340 rPar
.Get(0)->PutBool( bIsEof
);
3349 // No changes for UCB
3350 // #57064 Although this function doesn't operate with DirEntry, it is
3351 // not touched by the adjustment to virtual URLs, as it only works on
3352 // already opened files and the name doesn't matter there.
3354 if ( rPar
.Count() != 3 )
3356 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3360 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3361 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3362 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3365 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3369 if ( rPar
.Get(2)->GetInteger() == 1 )
3371 nRet
= (sal_Int16
)(pSbStrm
->GetMode());
3375 nRet
= 0; // System file handle not supported
3377 rPar
.Get(0)->PutInteger( nRet
);
3385 // No changes for UCB
3386 if ( rPar
.Count() != 2 )
3388 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3392 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3393 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3394 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3397 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3400 SvStream
* pSvStrm
= pSbStrm
->GetStrm();
3402 if( pSbStrm
->IsRandom())
3404 short nBlockLen
= pSbStrm
->GetBlockLen();
3405 nPos
= nBlockLen
? (pSvStrm
->Tell() / nBlockLen
) : 0;
3406 nPos
++; // block positions starting at 1
3408 else if ( pSbStrm
->IsText() )
3410 nPos
= pSbStrm
->GetLine();
3412 else if( pSbStrm
->IsBinary() )
3414 nPos
= pSvStrm
->Tell();
3416 else if ( pSbStrm
->IsSeq() )
3418 nPos
= ( pSvStrm
->Tell()+1 ) / 128;
3422 nPos
= pSvStrm
->Tell();
3424 rPar
.Get(0)->PutLong( (sal_Int32
)nPos
);
3433 // No changes for UCB
3434 if ( rPar
.Count() != 2 )
3436 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3440 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3441 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3442 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3445 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3448 SvStream
* pSvStrm
= pSbStrm
->GetStrm();
3449 sal_uIntPtr nOldPos
= pSvStrm
->Tell();
3450 sal_uIntPtr nLen
= pSvStrm
->Seek( STREAM_SEEK_TO_END
);
3451 pSvStrm
->Seek( nOldPos
);
3452 rPar
.Get(0)->PutLong( (sal_Int32
)nLen
);
3462 // No changes for UCB
3463 int nArgs
= (int)rPar
.Count();
3464 if ( nArgs
< 2 || nArgs
> 3 )
3466 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3469 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3470 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3471 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3474 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3477 SvStream
* pStrm
= pSbStrm
->GetStrm();
3479 if ( nArgs
== 2 ) // Seek-Function
3481 sal_uIntPtr nPos
= pStrm
->Tell();
3482 if( pSbStrm
->IsRandom() )
3484 nPos
= nPos
/ pSbStrm
->GetBlockLen();
3486 nPos
++; // Basic counts from 1
3487 rPar
.Get(0)->PutLong( (sal_Int32
)nPos
);
3489 else // Seek-Statement
3491 sal_Int32 nPos
= rPar
.Get(2)->GetLong();
3494 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3497 nPos
--; // Basic counts from 1, SvStreams count from 0
3498 pSbStrm
->SetExpandOnWriteTo( 0 );
3499 if ( pSbStrm
->IsRandom() )
3501 nPos
*= pSbStrm
->GetBlockLen();
3503 pStrm
->Seek( (sal_uIntPtr
)nPos
);
3504 pSbStrm
->SetExpandOnWriteTo( nPos
);
3513 sal_uInt16 nArgCount
= (sal_uInt16
)rPar
.Count();
3514 if ( nArgCount
< 2 || nArgCount
> 3 )
3516 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3521 if( nArgCount
== 2 )
3523 rPar
.Get(1)->Format( aResult
);
3527 OUString
aFmt( rPar
.Get(2)->GetOUString() );
3528 rPar
.Get(1)->Format( aResult
, &aFmt
);
3530 rPar
.Get(0)->PutString( aResult
);
3539 if ( rPar
.Count() > 2 )
3541 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3544 if( rPar
.Count() == 2 )
3546 nSeed
= (sal_Int16
)rPar
.Get(1)->GetInteger();
3550 nSeed
= (sal_Int16
)rand();
3560 if ( rPar
.Count() > 2 )
3562 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3566 double nRand
= (double)rand();
3567 nRand
= ( nRand
/ ((double)RAND_MAX
+ 1.0));
3568 rPar
.Get(0)->PutDouble( nRand
);
3573 // Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = sal_False ]]])
3574 // WindowStyles (VBA-kompatibel):
3577 // 10 == Full-Screen (text mode applications OS/2, WIN95, WNT)
3578 // HACK: The WindowStyle will be passed to
3579 // Application::StartApp in Creator. Format: "xxxx2"
3587 // No shell command for "virtual" portal users
3588 if( needSecurityRestrictions() )
3590 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
3594 sal_uIntPtr nArgCount
= rPar
.Count();
3595 if ( nArgCount
< 2 || nArgCount
> 5 )
3597 rPar
.Get(0)->PutLong(0);
3598 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3602 oslProcessOption nOptions
= osl_Process_SEARCHPATH
| osl_Process_DETACHED
;
3604 OUString aCmdLine
= rPar
.Get(1)->GetOUString();
3605 // attach additional parameters - everything must be parsed anyway
3606 if( nArgCount
>= 4 )
3609 aCmdLine
+= rPar
.Get(3)->GetOUString();
3611 else if( aCmdLine
.isEmpty() )
3613 // avaoid special treatment (empty list)
3616 sal_Int32 nLen
= aCmdLine
.getLength();
3618 // #55735 if there are parameters, they have to be separated
3619 // #72471 also separate the single parameters
3620 std::list
<String
> aTokenList
;
3629 if ( c
!= ' ' && c
!= '\t' )
3635 if( c
== '\"' || c
== '\'' )
3637 sal_Int32 iFoundPos
= aCmdLine
.indexOf( c
, i
+ 1 );
3641 aToken
= aCmdLine
.copy( i
);
3646 aToken
= aCmdLine
.copy( i
+ 1, (iFoundPos
- i
- 1) );
3652 sal_Int32 iFoundSpacePos
= aCmdLine
.indexOf( ' ', i
);
3653 sal_Int32 iFoundTabPos
= aCmdLine
.indexOf( '\t', i
);
3654 sal_Int32 iFoundPos
= iFoundSpacePos
>= 0 ? iFoundTabPos
>= 0 ? std::min( iFoundSpacePos
, iFoundTabPos
) : iFoundSpacePos
: -1;
3658 aToken
= aCmdLine
.copy( i
);
3663 aToken
= aCmdLine
.copy( i
, (iFoundPos
- i
) );
3668 // insert into the list
3669 aTokenList
.push_back( aToken
);
3671 // #55735 / #72471 end
3673 sal_Int16 nWinStyle
= 0;
3674 if( nArgCount
>= 3 )
3676 nWinStyle
= rPar
.Get(2)->GetInteger();
3680 nOptions
|= osl_Process_MINIMIZED
;
3683 nOptions
|= osl_Process_MAXIMIZED
;
3686 nOptions
|= osl_Process_FULLSCREEN
;
3690 sal_Bool bSync
= sal_False
;
3691 if( nArgCount
>= 5 )
3693 bSync
= rPar
.Get(4)->GetBool();
3697 nOptions
|= osl_Process_WAIT
;
3701 // #72471 work parameter(s) up
3702 std::list
<String
>::const_iterator iter
= aTokenList
.begin();
3703 const OUString
& rStr
= *iter
;
3704 OUString
aOUStrProg( rStr
.getStr(), rStr
.getLength() );
3705 OUString aOUStrProgURL
= getFullPath( aOUStrProg
);
3709 sal_uInt16 nParamCount
= sal::static_int_cast
< sal_uInt16
>(aTokenList
.size() - 1 );
3710 rtl_uString
** pParamList
= NULL
;
3713 pParamList
= new rtl_uString
*[nParamCount
];
3714 for(int iList
= 0; iter
!= aTokenList
.end(); ++iList
, ++iter
)
3716 const OUString
& rParamStr
= (*iter
);
3717 const OUString
aTempStr( rParamStr
.getStr(), rParamStr
.getLength());
3718 pParamList
[iList
] = NULL
;
3719 rtl_uString_assign(&(pParamList
[iList
]), aTempStr
.pData
);
3724 sal_Bool bSucc
= osl_executeProcess(
3725 aOUStrProgURL
.pData
,
3732 &pApp
) == osl_Process_E_None
;
3734 // 53521 only free process handle on success
3737 osl_freeProcessHandle( pApp
);
3740 for(int j
= 0; i
< nParamCount
; i
++)
3742 rtl_uString_release(pParamList
[j
]);
3743 pParamList
[j
] = NULL
;
3748 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
3752 rPar
.Get(0)->PutLong( 0 );
3762 if ( rPar
.Count() != 2 )
3764 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3768 SbxDataType eType
= rPar
.Get(1)->GetType();
3769 rPar
.Get(0)->PutInteger( (sal_Int16
)eType
);
3773 // Exported function
3774 OUString
getBasicTypeName( SbxDataType eType
)
3776 static const char* pTypeNames
[] =
3778 "Empty", // SbxEMPTY
3780 "Integer", // SbxINTEGER
3782 "Single", // SbxSINGLE
3783 "Double", // SbxDOUBLE
3784 "Currency", // SbxCURRENCY
3786 "String", // SbxSTRING
3787 "Object", // SbxOBJECT
3788 "Error", // SbxERROR
3789 "Boolean", // SbxBOOL
3790 "Variant", // SbxVARIANT
3791 "DataObject", // SbxDATAOBJECT
3796 "UShort", // SbxUSHORT
3797 "ULong", // SbxULONG
3798 "Long64", // SbxLONG64
3799 "ULong64", // SbxULONG64
3803 "HResult", // SbxHRESULT
3804 "Pointer", // SbxPOINTER
3805 "DimArray", // SbxDIMARRAY
3806 "CArray", // SbxCARRAY
3807 "Userdef", // SbxUSERDEF
3808 "Lpstr", // SbxLPSTR
3809 "Lpwstr", // SbxLPWSTR
3810 "Unknown Type", // SbxCoreSTRING
3811 "WString", // SbxWSTRING
3812 "WChar", // SbxWCHAR
3813 "Int64", // SbxSALINT64
3814 "UInt64", // SbxSALUINT64
3815 "Decimal", // SbxDECIMAL
3818 int nPos
= ((int)eType
) & 0x0FFF;
3819 sal_uInt16 nTypeNameCount
= sizeof( pTypeNames
) / sizeof( char* );
3820 if ( nPos
< 0 || nPos
>= nTypeNameCount
)
3822 nPos
= nTypeNameCount
- 1;
3824 return OUString::createFromAscii(pTypeNames
[nPos
]);
3827 String
getObjectTypeName( SbxVariable
* pVar
)
3829 OUString
sRet( "Object" );
3832 SbxBase
* pObj
= pVar
->GetObject();
3835 sRet
= OUString("Nothing");
3839 SbUnoObject
* pUnoObj
= PTR_CAST(SbUnoObject
,pVar
);
3842 if ( SbxBase
* pBaseObj
= pVar
->GetObject() )
3844 pUnoObj
= PTR_CAST(SbUnoObject
, pBaseObj
);
3849 Any aObj
= pUnoObj
->getUnoAny();
3850 // For upstreaming unless we start to build oovbaapi by default
3851 // we need to get detect the vba-ness of the object in some
3853 // note: Automation objects do not support XServiceInfo
3854 uno::Reference
< XServiceInfo
> xServInfo( aObj
, uno::UNO_QUERY
);
3855 if ( xServInfo
.is() )
3857 // is this a VBA object ?
3858 uno::Reference
< ooo::vba::XHelperInterface
> xVBA( aObj
, uno::UNO_QUERY
);
3859 Sequence
< OUString
> sServices
= xServInfo
->getSupportedServiceNames();
3860 if ( sServices
.getLength() )
3862 sRet
= sServices
[ 0 ];
3867 uno::Reference
< bridge::oleautomation::XAutomationObject
> xAutoMation( aObj
, uno::UNO_QUERY
);
3868 if ( xAutoMation
.is() )
3870 uno::Reference
< script::XInvocation
> xInv( aObj
, uno::UNO_QUERY
);
3875 xInv
->getValue( OUString( "$GetTypeName" ) ) >>= sRet
;
3877 catch(const Exception
& )
3883 sal_Int32 nDot
= sRet
.lastIndexOf( '.' );
3884 if ( nDot
!= -1 && nDot
< sRet
.getLength() )
3886 sRet
= sRet
.copy( nDot
+ 1 );
3899 if ( rPar
.Count() != 2 )
3901 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3905 SbxDataType eType
= rPar
.Get(1)->GetType();
3906 bool bIsArray
= ( ( eType
& SbxARRAY
) != 0 );
3909 if ( SbiRuntime::isVBAEnabled() && eType
== SbxOBJECT
)
3911 aRetStr
= getObjectTypeName( rPar
.Get(1) );
3915 aRetStr
= getBasicTypeName( eType
);
3921 rPar
.Get(0)->PutString( aRetStr
);
3930 if ( rPar
.Count() != 2 )
3932 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3936 const OUString
& rStr
= rPar
.Get(1)->GetOUString();
3937 rPar
.Get(0)->PutLong( rStr
.getLength() );
3941 RTLFUNC(DDEInitiate
)
3946 // No DDE for "virtual" portal users
3947 if( needSecurityRestrictions() )
3949 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
3953 int nArgs
= (int)rPar
.Count();
3956 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3959 const OUString
& rApp
= rPar
.Get(1)->GetOUString();
3960 const OUString
& rTopic
= rPar
.Get(2)->GetOUString();
3962 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
3964 SbError nDdeErr
= pDDE
->Initiate( rApp
, rTopic
, nChannel
);
3967 StarBASIC::Error( nDdeErr
);
3971 rPar
.Get(0)->PutInteger( (int)nChannel
);
3975 RTLFUNC(DDETerminate
)
3980 // No DDE for "virtual" portal users
3981 if( needSecurityRestrictions() )
3983 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
3987 rPar
.Get(0)->PutEmpty();
3988 int nArgs
= (int)rPar
.Count();
3991 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3994 size_t nChannel
= rPar
.Get(1)->GetInteger();
3995 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
3996 SbError nDdeErr
= pDDE
->Terminate( nChannel
);
3999 StarBASIC::Error( nDdeErr
);
4003 RTLFUNC(DDETerminateAll
)
4008 // No DDE for "virtual" portal users
4009 if( needSecurityRestrictions() )
4011 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4015 rPar
.Get(0)->PutEmpty();
4016 int nArgs
= (int)rPar
.Count();
4019 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4023 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4024 SbError nDdeErr
= pDDE
->TerminateAll();
4027 StarBASIC::Error( nDdeErr
);
4036 // No DDE for "virtual" portal users
4037 if( needSecurityRestrictions() )
4039 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4043 int nArgs
= (int)rPar
.Count();
4046 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4049 size_t nChannel
= rPar
.Get(1)->GetInteger();
4050 const OUString
& rItem
= rPar
.Get(2)->GetOUString();
4051 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4053 SbError nDdeErr
= pDDE
->Request( nChannel
, rItem
, aResult
);
4056 StarBASIC::Error( nDdeErr
);
4060 rPar
.Get(0)->PutString( aResult
);
4069 // No DDE for "virtual" portal users
4070 if( needSecurityRestrictions() )
4072 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4076 rPar
.Get(0)->PutEmpty();
4077 int nArgs
= (int)rPar
.Count();
4080 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4083 size_t nChannel
= rPar
.Get(1)->GetInteger();
4084 const OUString
& rCommand
= rPar
.Get(2)->GetOUString();
4085 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4086 SbError nDdeErr
= pDDE
->Execute( nChannel
, rCommand
);
4089 StarBASIC::Error( nDdeErr
);
4098 // No DDE for "virtual" portal users
4099 if( needSecurityRestrictions() )
4101 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4105 rPar
.Get(0)->PutEmpty();
4106 int nArgs
= (int)rPar
.Count();
4109 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4112 size_t nChannel
= rPar
.Get(1)->GetInteger();
4113 const OUString
& rItem
= rPar
.Get(2)->GetOUString();
4114 const OUString
& rData
= rPar
.Get(3)->GetOUString();
4115 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4116 SbError nDdeErr
= pDDE
->Poke( nChannel
, rItem
, rData
);
4119 StarBASIC::Error( nDdeErr
);
4129 if ( rPar
.Count() != 1 )
4131 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4134 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
4136 while( nChannel
< CHANNELS
)
4138 SbiStream
* pStrm
= pIO
->GetStream( nChannel
);
4141 rPar
.Get(0)->PutInteger( nChannel
);
4146 StarBASIC::Error( SbERR_TOO_MANY_FILES
);
4154 sal_uInt16 nParCount
= rPar
.Count();
4155 if ( nParCount
!= 3 && nParCount
!= 2 )
4157 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4160 SbxBase
* pParObj
= rPar
.Get(1)->GetObject();
4161 SbxDimArray
* pArr
= PTR_CAST(SbxDimArray
,pParObj
);
4164 sal_Int32 nLower
, nUpper
;
4165 short nDim
= (nParCount
== 3) ? (short)rPar
.Get(2)->GetInteger() : 1;
4166 if( !pArr
->GetDim32( nDim
, nLower
, nUpper
) )
4167 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
4169 rPar
.Get(0)->PutLong( nLower
);
4172 StarBASIC::Error( SbERR_MUST_HAVE_DIMS
);
4180 sal_uInt16 nParCount
= rPar
.Count();
4181 if ( nParCount
!= 3 && nParCount
!= 2 )
4183 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4187 SbxBase
* pParObj
= rPar
.Get(1)->GetObject();
4188 SbxDimArray
* pArr
= PTR_CAST(SbxDimArray
,pParObj
);
4191 sal_Int32 nLower
, nUpper
;
4192 short nDim
= (nParCount
== 3) ? (short)rPar
.Get(2)->GetInteger() : 1;
4193 if( !pArr
->GetDim32( nDim
, nLower
, nUpper
) )
4194 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
4196 rPar
.Get(0)->PutLong( nUpper
);
4199 StarBASIC::Error( SbERR_MUST_HAVE_DIMS
);
4207 if ( rPar
.Count() != 4 )
4209 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4213 sal_uIntPtr nRed
= rPar
.Get(1)->GetInteger() & 0xFF;
4214 sal_uIntPtr nGreen
= rPar
.Get(2)->GetInteger() & 0xFF;
4215 sal_uIntPtr nBlue
= rPar
.Get(3)->GetInteger() & 0xFF;
4218 SbiInstance
* pInst
= GetSbData()->pInst
;
4219 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
4220 if( bCompatibility
)
4222 nRGB
= (nBlue
<< 16) | (nGreen
<< 8) | nRed
;
4226 nRGB
= (nRed
<< 16) | (nGreen
<< 8) | nBlue
;
4228 rPar
.Get(0)->PutLong( nRGB
);
4236 static const sal_Int32 pRGB
[] =
4256 if ( rPar
.Count() != 2 )
4258 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4262 sal_Int16 nCol
= rPar
.Get(1)->GetInteger();
4263 if( nCol
< 0 || nCol
> 15 )
4265 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4268 sal_Int32 nRGB
= pRGB
[ nCol
];
4269 rPar
.Get(0)->PutLong( nRGB
);
4272 // StrConv(string, conversion, LCID)
4278 sal_uIntPtr nArgCount
= rPar
.Count()-1;
4279 if( nArgCount
< 2 || nArgCount
> 3 )
4281 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4285 OUString aOldStr
= rPar
.Get(1)->GetOUString();
4286 sal_Int32 nConversion
= rPar
.Get(2)->GetLong();
4288 sal_uInt16 nLanguage
= LANGUAGE_SYSTEM
;
4290 sal_Int32 nOldLen
= aOldStr
.getLength();
4293 // null string,return
4294 rPar
.Get(0)->PutString(aOldStr
);
4298 sal_Int32 nType
= 0;
4299 if ( (nConversion
& 0x03) == 3 ) // vbProperCase
4301 const CharClass
& rCharClass
= GetCharClass();
4302 aOldStr
= rCharClass
.titlecase( aOldStr
.toAsciiLowerCase(), 0, nOldLen
);
4304 else if ( (nConversion
& 0x01) == 1 ) // vbUpperCase
4306 nType
|= i18n::TransliterationModules_LOWERCASE_UPPERCASE
;
4308 else if ( (nConversion
& 0x02) == 2 ) // vbLowerCase
4310 nType
|= i18n::TransliterationModules_UPPERCASE_LOWERCASE
;
4312 if ( (nConversion
& 0x04) == 4 ) // vbWide
4314 nType
|= i18n::TransliterationModules_HALFWIDTH_FULLWIDTH
;
4316 else if ( (nConversion
& 0x08) == 8 ) // vbNarrow
4318 nType
|= i18n::TransliterationModules_FULLWIDTH_HALFWIDTH
;
4320 if ( (nConversion
& 0x10) == 16) // vbKatakana
4322 nType
|= i18n::TransliterationModules_HIRAGANA_KATAKANA
;
4324 else if ( (nConversion
& 0x20) == 32 ) // vbHiragana
4326 nType
|= i18n::TransliterationModules_KATAKANA_HIRAGANA
;
4328 OUString
aNewStr( aOldStr
);
4331 uno::Reference
< uno::XComponentContext
> xContext
= getProcessComponentContext();
4332 ::utl::TransliterationWrapper
aTransliterationWrapper( xContext
, nType
);
4333 uno::Sequence
<sal_Int32
> aOffsets
;
4334 aTransliterationWrapper
.loadModuleIfNeeded( nLanguage
);
4335 aNewStr
= aTransliterationWrapper
.transliterate( aOldStr
, nLanguage
, 0, nOldLen
, &aOffsets
);
4338 if ( (nConversion
& 0x40) == 64 ) // vbUnicode
4340 // convert the string to byte string, preserving unicode (2 bytes per character)
4341 sal_Int32 nSize
= aNewStr
.getLength()*2;
4342 const sal_Unicode
* pSrc
= aNewStr
.getStr();
4343 sal_Char
* pChar
= new sal_Char
[nSize
+1];
4344 for( sal_Int32 i
=0; i
< nSize
; i
++ )
4346 pChar
[i
] = static_cast< sal_Char
>( (i
%2) ? ((*pSrc
) >> 8) & 0xff : (*pSrc
) & 0xff );
4352 pChar
[nSize
] = '\0';
4353 OString
aOStr(pChar
);
4356 // there is no concept about default codepage in unix. so it is incorrectly in unix
4357 OUString aOUStr
= OStringToOUString(aOStr
, osl_getThreadTextEncoding());
4358 rPar
.Get(0)->PutString( aOUStr
);
4361 else if ( (nConversion
& 0x80) == 128 ) // vbFromUnicode
4363 // there is no concept about default codepage in unix. so it is incorrectly in unix
4364 OString aOStr
= OUStringToOString(aNewStr
,osl_getThreadTextEncoding());
4365 const sal_Char
* pChar
= aOStr
.getStr();
4366 sal_Int32 nArraySize
= aOStr
.getLength();
4367 SbxDimArray
* pArray
= new SbxDimArray(SbxBYTE
);
4368 bool bIncIndex
= (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
4373 pArray
->AddDim( 1, nArraySize
);
4377 pArray
->AddDim( 0, nArraySize
-1 );
4382 pArray
->unoAddDim( 0, -1 );
4385 for( sal_Int32 i
=0; i
< nArraySize
; i
++)
4387 SbxVariable
* pNew
= new SbxVariable( SbxBYTE
);
4388 pNew
->PutByte(*pChar
);
4390 pNew
->SetFlag( SBX_WRITE
);
4396 pArray
->Put( pNew
, &index
);
4399 SbxVariableRef refVar
= rPar
.Get(0);
4400 sal_uInt16 nFlags
= refVar
->GetFlags();
4401 refVar
->ResetFlag( SBX_FIXED
);
4402 refVar
->PutObject( pArray
);
4403 refVar
->SetFlags( nFlags
);
4404 refVar
->SetParameters( NULL
);
4407 rPar
.Get(0)->PutString(aNewStr
);
4416 if ( rPar
.Count() != 1 )
4418 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4429 if( rPar
.Count() != 2 )
4431 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4436 SbxBase
* pObj
= (SbxObject
*)rPar
.Get(1)->GetObject();
4439 if( pObj
->IsA( TYPE( SbUserFormModule
) ) )
4441 ((SbUserFormModule
*)pObj
)->Load();
4443 else if( pObj
->IsA( TYPE( SbxObject
) ) )
4445 SbxVariable
* pVar
= ((SbxObject
*)pObj
)->Find( OUString("Load"), SbxCLASS_METHOD
);
4459 rPar
.Get(0)->PutEmpty();
4460 if( rPar
.Count() != 2 )
4462 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4467 SbxBase
* pObj
= (SbxObject
*)rPar
.Get(1)->GetObject();
4470 if( pObj
->IsA( TYPE( SbUserFormModule
) ) )
4472 SbUserFormModule
* pFormModule
= ( SbUserFormModule
* )pObj
;
4473 pFormModule
->Unload();
4475 else if( pObj
->IsA( TYPE( SbxObject
) ) )
4477 SbxVariable
* pVar
= ((SbxObject
*)pObj
)->Find( OUString("Unload"), SbxCLASS_METHOD
);
4486 RTLFUNC(LoadPicture
)
4491 if( rPar
.Count() != 2 )
4493 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4497 OUString aFileURL
= getFullPath( rPar
.Get(1)->GetOUString() );
4498 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( aFileURL
, STREAM_READ
);
4499 if( pStream
!= NULL
)
4503 Graphic
aGraphic( aBmp
);
4505 SbxObjectRef xRef
= new SbStdPicture
;
4506 ((SbStdPicture
*)(SbxObject
*)xRef
)->SetGraphic( aGraphic
);
4507 rPar
.Get(0)->PutObject( xRef
);
4512 RTLFUNC(SavePicture
)
4517 rPar
.Get(0)->PutEmpty();
4518 if( rPar
.Count() != 3 )
4520 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4524 SbxBase
* pObj
= (SbxObject
*)rPar
.Get(1)->GetObject();
4525 if( pObj
->IsA( TYPE( SbStdPicture
) ) )
4527 SvFileStream
aOStream( rPar
.Get(2)->GetOUString(), STREAM_WRITE
| STREAM_TRUNC
);
4528 Graphic aGraphic
= ((SbStdPicture
*)pObj
)->GetGraphic();
4529 aOStream
<< aGraphic
;
4534 //-----------------------------------------------------------------------------------------
4541 static const WinBits nStyleMap
[] =
4544 WB_OK_CANCEL
, // MB_OKCANCEL
4545 WB_ABORT_RETRY_IGNORE
, // MB_ABORTRETRYIGNORE
4546 WB_YES_NO_CANCEL
, // MB_YESNOCANCEL
4547 WB_YES_NO
, // MB_YESNO
4548 WB_RETRY_CANCEL
// MB_RETRYCANCEL
4550 static const sal_Int16 nButtonMap
[] =
4552 2, // #define RET_CANCEL sal_False
4553 1, // #define RET_OK sal_True
4554 6, // #define RET_YES 2
4555 7, // #define RET_NO 3
4556 4 // #define RET_RETRY 4
4560 sal_uInt16 nArgCount
= (sal_uInt16
)rPar
.Count();
4561 if( nArgCount
< 2 || nArgCount
> 6 )
4563 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4567 WinBits nType
= 0; // MB_OK
4568 if( nArgCount
>= 3 )
4569 nType
= (WinBits
)rPar
.Get(2)->GetInteger();
4570 WinBits nStyle
= nType
;
4571 nStyle
&= 15; // delete bits 4-16
4576 nWinBits
= nStyleMap
[ nStyle
];
4578 WinBits nWinDefBits
;
4579 nWinDefBits
= (WB_DEF_OK
| WB_DEF_RETRY
| WB_DEF_YES
);
4584 nWinDefBits
= WB_DEF_CANCEL
;
4586 else if( nStyle
== 2 )
4588 nWinDefBits
= WB_DEF_RETRY
;
4592 nWinDefBits
= (WB_DEF_CANCEL
| WB_DEF_RETRY
| WB_DEF_NO
);
4595 else if( nType
& 512 )
4599 nWinDefBits
= WB_DEF_IGNORE
;
4603 nWinDefBits
= WB_DEF_CANCEL
;
4606 else if( nStyle
== 2)
4608 nWinDefBits
= WB_DEF_CANCEL
;
4610 nWinBits
|= nWinDefBits
;
4612 OUString aMsg
= rPar
.Get(1)->GetOUString();
4614 if( nArgCount
>= 4 )
4616 aTitle
= rPar
.Get(3)->GetOUString();
4620 aTitle
= GetpApp()->GetAppName();
4623 nType
&= (16+32+64);
4625 Window
* pParent
= GetpApp()->GetDefDialogParent();
4629 pBox
= new ErrorBox( pParent
, nWinBits
, aMsg
);
4632 pBox
= new QueryBox( pParent
, nWinBits
, aMsg
);
4635 pBox
= new WarningBox( pParent
, nWinBits
, aMsg
);
4638 pBox
= new InfoBox( pParent
, aMsg
);
4641 pBox
= new MessBox( pParent
, nWinBits
, aTitle
, aMsg
);
4643 pBox
->SetText( aTitle
);
4644 sal_uInt16 nRet
= (sal_uInt16
)pBox
->Execute();
4645 if( nRet
== sal_True
)
4649 sal_Int16 nMappedRet
;
4653 if( nMappedRet
== 0 )
4655 nMappedRet
= 3; // Abort
4660 nMappedRet
= nButtonMap
[ nRet
];
4662 rPar
.Get(0)->PutInteger( nMappedRet
);
4671 rPar
.Get(0)->PutEmpty();
4672 if ( rPar
.Count() == 3 )
4674 OUString aStr
= rPar
.Get(1)->GetOUString();
4675 sal_Int16 nFlags
= rPar
.Get(2)->GetInteger();
4679 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
4684 sal_Bool bReadOnly
= (nFlags
& Sb_ATTR_READONLY
) != 0;
4685 xSFI
->setReadOnly( aStr
, bReadOnly
);
4686 sal_Bool bHidden
= (nFlags
& Sb_ATTR_HIDDEN
) != 0;
4687 xSFI
->setHidden( aStr
, bHidden
);
4689 catch(const Exception
& )
4691 StarBASIC::Error( ERRCODE_IO_GENERAL
);
4698 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4708 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
4715 RTLFUNC(DumpAllObjects
)
4720 sal_uInt16 nArgCount
= (sal_uInt16
)rPar
.Count();
4721 if( nArgCount
< 2 || nArgCount
> 3 )
4723 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4727 StarBASIC::Error( SbERR_INTERNAL_ERROR
);
4731 SbxObject
* p
= pBasic
;
4732 while( p
->GetParent() )
4736 SvFileStream
aStrm( rPar
.Get( 1 )->GetOUString(),
4737 STREAM_WRITE
| STREAM_TRUNC
);
4738 p
->Dump( aStrm
, rPar
.Get( 2 )->GetBool() );
4740 if( aStrm
.GetError() != SVSTREAM_OK
)
4742 StarBASIC::Error( SbERR_IO_ERROR
);
4753 if ( rPar
.Count() == 2 )
4755 OUString aStr
= rPar
.Get(1)->GetOUString();
4756 sal_Bool bExists
= sal_False
;
4760 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
4765 bExists
= xSFI
->exists( aStr
);
4767 catch(const Exception
& )
4769 StarBASIC::Error( ERRCODE_IO_GENERAL
);
4775 DirectoryItem aItem
;
4776 FileBase::RC nRet
= DirectoryItem::get( getFullPath( aStr
), aItem
);
4777 bExists
= (nRet
== FileBase::E_None
);
4779 rPar
.Get(0)->PutBool( bExists
);
4783 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4792 if ( rPar
.Count() != 5 )
4794 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4798 sal_Int32 nNumber
= rPar
.Get(1)->GetLong();
4799 sal_Int32 nStart
= rPar
.Get(2)->GetLong();
4800 sal_Int32 nStop
= rPar
.Get(3)->GetLong();
4801 sal_Int32 nInterval
= rPar
.Get(4)->GetLong();
4803 if( nStart
< 0 || nStop
<= nStart
|| nInterval
< 1 )
4805 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4809 // the Partition function inserts leading spaces before lowervalue and uppervalue
4810 // so that they both have the same number of characters as the string
4811 // representation of the value (Stop + 1). This ensures that if you use the output
4812 // of the Partition function with several values of Number, the resulting text
4813 // will be handled properly during any subsequent sort operation.
4815 // calculate the maximun number of characters before lowervalue and uppervalue
4816 OUString aBeforeStart
= OUString::valueOf( nStart
- 1 );
4817 OUString aAfterStop
= OUString::valueOf( nStop
+ 1 );
4818 sal_Int32 nLen1
= aBeforeStart
.getLength();
4819 sal_Int32 nLen2
= aAfterStop
.getLength();
4820 sal_Int32 nLen
= nLen1
>= nLen2
? nLen1
:nLen2
;
4822 OUStringBuffer
aRetStr( nLen
* 2 + 1);
4823 OUString aLowerValue
;
4824 OUString aUpperValue
;
4825 if( nNumber
< nStart
)
4827 aUpperValue
= aBeforeStart
;
4829 else if( nNumber
> nStop
)
4831 aLowerValue
= aAfterStop
;
4835 sal_Int32 nLowerValue
= nNumber
;
4836 sal_Int32 nUpperValue
= nLowerValue
;
4839 nLowerValue
= ((( nNumber
- nStart
) / nInterval
) * nInterval
) + nStart
;
4840 nUpperValue
= nLowerValue
+ nInterval
- 1;
4842 aLowerValue
= OUString::valueOf( nLowerValue
);
4843 aUpperValue
= OUString::valueOf( nUpperValue
);
4846 nLen1
= aLowerValue
.getLength();
4847 nLen2
= aUpperValue
.getLength();
4851 // appending the leading spaces for the lowervalue
4852 for ( sal_Int32 i
= (nLen
- nLen1
) ; i
> 0; --i
)
4854 aRetStr
.appendAscii(" ");
4857 aRetStr
.append( aLowerValue
).appendAscii(":");
4860 // appending the leading spaces for the uppervalue
4861 for ( sal_Int32 i
= (nLen
- nLen2
) ; i
> 0; --i
)
4863 aRetStr
.appendAscii(" ");
4866 aRetStr
.append( aUpperValue
);
4867 rPar
.Get(0)->PutString( aRetStr
.makeStringAndClear());
4872 static long GetDayDiff( const Date
& rDate
)
4874 Date
aRefDate( 1,1,1900 );
4876 if ( aRefDate
> rDate
)
4878 nDiffDays
= (long)(aRefDate
- rDate
);
4883 nDiffDays
= (long)(rDate
- aRefDate
);
4885 nDiffDays
+= 2; // adjustment VisualBasic: 1.Jan.1900 == 2
4889 sal_Int16
implGetDateYear( double aDate
)
4891 Date
aRefDate( 1,1,1900 );
4892 long nDays
= (long) aDate
;
4893 nDays
-= 2; // standardize: 1.1.1900 => 0.0
4895 sal_Int16 nRet
= (sal_Int16
)( aRefDate
.GetYear() );
4899 bool implDateSerial( sal_Int16 nYear
, sal_Int16 nMonth
, sal_Int16 nDay
, double& rdRet
)
4901 #ifndef DISABLE_SCRIPTING
4902 if ( nYear
< 30 && SbiRuntime::isVBAEnabled() )
4914 Date
aCurDate( nDay
, nMonth
, nYear
);
4915 if ((nYear
< 100 || nYear
> 9999) )
4917 #ifndef DISABLE_SCRIPTING
4918 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4923 #ifndef DISABLE_SCRIPTING
4924 if ( !SbiRuntime::isVBAEnabled() )
4927 if ( (nMonth
< 1 || nMonth
> 12 )||
4928 (nDay
< 1 || nDay
> 31 ) )
4930 #ifndef DISABLE_SCRIPTING
4931 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4936 #ifndef DISABLE_SCRIPTING
4939 // grab the year & month
4940 aCurDate
= Date( 1, (( nMonth
% 12 ) > 0 ) ? ( nMonth
% 12 ) : 12 + ( nMonth
% 12 ), nYear
);
4942 // adjust year based on month value
4943 // e.g. 2000, 0, xx = 1999, 12, xx ( or December of the previous year )
4944 // 2000, 13, xx = 2001, 1, xx ( or January of the following year )
4945 if( ( nMonth
< 1 ) || ( nMonth
> 12 ) )
4947 // inacurrate around leap year, don't use days to calculate,
4948 // just modify the months directory
4949 sal_Int16 nYearAdj
= ( nMonth
/12 ); // default to positive months inputed
4952 nYearAdj
= ( ( nMonth
-12 ) / 12 );
4954 aCurDate
.SetYear( aCurDate
.GetYear() + nYearAdj
);
4957 // adjust day value,
4958 // e.g. 2000, 2, 0 = 2000, 1, 31 or the last day of the previous month
4959 // 2000, 1, 32 = 2000, 2, 1 or the first day of the following month
4960 if( ( nDay
< 1 ) || ( nDay
> aCurDate
.GetDaysInMonth() ) )
4962 aCurDate
+= nDay
- 1;
4966 aCurDate
.SetDay( nDay
);
4971 long nDiffDays
= GetDayDiff( aCurDate
);
4972 rdRet
= (double)nDiffDays
;
4976 double implTimeSerial( sal_Int16 nHours
, sal_Int16 nMinutes
, sal_Int16 nSeconds
)
4979 static_cast<double>( nHours
* ::Time::secondPerHour
+
4980 nMinutes
* ::Time::secondPerMinute
+
4983 static_cast<double>( ::Time::secondPerDay
);
4986 bool implDateTimeSerial( sal_Int16 nYear
, sal_Int16 nMonth
, sal_Int16 nDay
,
4987 sal_Int16 nHour
, sal_Int16 nMinute
, sal_Int16 nSecond
,
4991 if(!implDateSerial(nYear
, nMonth
, nDay
, dDate
))
4993 rdRet
+= dDate
+ implTimeSerial(nHour
, nMinute
, nSecond
);
4997 sal_Int16
implGetMinute( double dDate
)
5003 double nFrac
= dDate
- floor( dDate
);
5005 sal_Int32 nSeconds
= (sal_Int32
)(nFrac
+ 0.5);
5006 sal_Int16 nTemp
= (sal_Int16
)(nSeconds
% 3600);
5007 sal_Int16 nMin
= nTemp
/ 60;
5011 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */