1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <tools/date.hxx>
23 #include <basic/sbxvar.hxx>
24 #include <basic/sbuno.hxx>
25 #include <osl/process.h>
26 #include <vcl/dibtools.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/sound.hxx>
30 #include <tools/wintypes.hxx>
31 #include <vcl/msgbox.hxx>
32 #include <basic/sbx.hxx>
33 #include <svl/zforlist.hxx>
34 #include <rtl/math.hxx>
35 #include <tools/urlobj.hxx>
37 #include <unotools/charclass.hxx>
38 #include <unotools/ucbstreamhelper.hxx>
39 #include <tools/wldcrd.hxx>
40 #include <i18nlangtag/lang.h>
41 #include <rtl/string.hxx>
42 #include <rtl/strbuf.hxx>
44 #include "runtime.hxx"
45 #include "sbunoobj.hxx"
46 #include <osl/file.hxx>
47 #include "errobject.hxx"
49 #include <comphelper/processfactory.hxx>
50 #include <comphelper/string.hxx>
52 #include <com/sun/star/uno/Sequence.hxx>
53 #include <com/sun/star/util/DateTime.hpp>
54 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
55 #include <com/sun/star/lang/Locale.hpp>
56 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
57 #include <com/sun/star/script/XErrorQuery.hpp>
58 #include <ooo/vba/XHelperInterface.hpp>
59 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
60 #include <boost/scoped_array.hpp>
61 #include <boost/scoped_ptr.hpp>
65 using namespace comphelper
;
67 using namespace com::sun::star
;
68 using namespace com::sun::star::lang
;
69 using namespace com::sun::star::uno
;
73 #include "sbstdobj.hxx"
74 #include "rtlproto.hxx"
79 #include "ddectrl.hxx"
80 #include <sbintern.hxx>
81 #include <basic/vbahelper.hxx>
90 #include "sbobjmod.hxx"
100 #if HAVE_FEATURE_SCRIPTING
102 static void FilterWhiteSpace( OUString
& rStr
)
110 for (sal_Int32 i
= 0; i
< rStr
.getLength(); ++i
)
112 sal_Unicode cChar
= rStr
[i
];
113 if ((cChar
!= ' ') && (cChar
!= '\t') &&
114 (cChar
!= '\n') && (cChar
!= '\r'))
120 rStr
= aRet
.makeStringAndClear();
123 static long GetDayDiff( const Date
& rDate
);
125 static const CharClass
& GetCharClass()
127 static bool bNeedsInit
= true;
128 static LanguageTag
aLanguageTag( LANGUAGE_SYSTEM
);
132 aLanguageTag
= Application::GetSettings().GetLanguageTag();
134 static CharClass
aCharClass( aLanguageTag
);
138 static inline bool isFolder( FileStatus::Type aType
)
140 return ( aType
== FileStatus::Directory
|| aType
== FileStatus::Volume
);
144 //*** UCB file access ***
146 // Converts possibly relative paths to absolute paths
147 // according to the setting done by ChDir/ChDrive
148 OUString
getFullPath( const OUString
& aRelPath
)
152 // #80204 Try first if it already is a valid URL
153 INetURLObject
aURLObj( aRelPath
);
154 aFileURL
= aURLObj
.GetMainURL( INetURLObject::NO_DECODE
);
156 if( aFileURL
.isEmpty() )
158 File::getFileURLFromSystemPath( aRelPath
, aFileURL
);
164 // TODO: -> SbiGlobals
165 static uno::Reference
< ucb::XSimpleFileAccess3
> getFileAccess()
167 static uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
;
170 xSFI
= ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
177 // Properties and methods lie down the return value at the Get (bPut = sal_False) in the
178 // element 0 of the Argv; the value of element 0 is saved at Put (bPut = sal_True)
180 // CreateObject( class )
182 RTLFUNC(CreateObject
)
186 OUString
aClass( rPar
.Get( 1 )->GetOUString() );
187 SbxObjectRef p
= SbxBase::CreateObject( aClass
);
189 StarBASIC::Error( SbERR_CANNOT_LOAD
);
192 // Convenience: enter BASIC as parent
193 p
->SetParent( pBasic
);
194 rPar
.Get( 0 )->PutObject( p
);
205 StarBASIC::Error( SbERR_INTERNAL_ERROR
);
211 if( rPar
.Count() == 1 )
213 nErr
= StarBASIC::GetErrBasic();
214 aErrorMsg
= StarBASIC::GetErrorMsg();
218 nCode
= rPar
.Get( 1 )->GetLong();
221 StarBASIC::Error( SbERR_CONVERSION
);
225 nErr
= StarBASIC::GetSfxFromVBError( (sal_uInt16
)nCode
);
229 bool bVBA
= SbiRuntime::isVBAEnabled();
231 if( bVBA
&& !aErrorMsg
.isEmpty())
233 tmpErrMsg
= aErrorMsg
;
237 StarBASIC::MakeErrorText( nErr
, aErrorMsg
);
238 tmpErrMsg
= StarBASIC::GetErrorText();
240 // If this rtlfunc 'Error' passed a errcode the same as the active Err Objects's
241 // current err then return the description for the error message if it is set
242 // ( complicated isn't it ? )
243 if ( bVBA
&& rPar
.Count() > 1 )
245 uno::Reference
< ooo::vba::XErrObject
> xErrObj( SbxErrObject::getUnoErrObject() );
246 if ( xErrObj
.is() && xErrObj
->getNumber() == nCode
&& !xErrObj
->getDescription().isEmpty() )
248 tmpErrMsg
= xErrObj
->getDescription();
251 rPar
.Get( 0 )->PutString( tmpErrMsg
);
262 if ( rPar
.Count() < 2 )
263 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
266 SbxVariableRef pArg
= rPar
.Get( 1 );
267 rPar
.Get( 0 )->PutDouble( sin( pArg
->GetDouble() ) );
277 if ( rPar
.Count() < 2 )
278 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
281 SbxVariableRef pArg
= rPar
.Get( 1 );
282 rPar
.Get( 0 )->PutDouble( cos( pArg
->GetDouble() ) );
292 if ( rPar
.Count() < 2 )
293 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
296 SbxVariableRef pArg
= rPar
.Get( 1 );
297 rPar
.Get( 0 )->PutDouble( atan( pArg
->GetDouble() ) );
308 if ( rPar
.Count() < 2 )
310 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
314 SbxVariableRef pArg
= rPar
.Get( 1 );
315 rPar
.Get( 0 )->PutDouble( fabs( pArg
->GetDouble() ) );
325 if ( rPar
.Count() < 2 )
327 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
331 SbxVariableRef pArg
= rPar
.Get( 1 );
332 OUString
aStr( pArg
->GetOUString() );
335 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
336 rPar
.Get(0)->PutEmpty();
340 sal_Unicode aCh
= aStr
[0];
341 rPar
.Get(0)->PutLong( aCh
);
346 void implChr( SbxArray
& rPar
, bool bChrW
)
348 if ( rPar
.Count() < 2 )
350 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
354 SbxVariableRef pArg
= rPar
.Get( 1 );
357 if( !bChrW
&& SbiRuntime::isVBAEnabled() )
359 sal_Char c
= static_cast<sal_Char
>(pArg
->GetByte());
360 aStr
= OUString(&c
, 1, osl_getThreadTextEncoding());
364 sal_Unicode aCh
= static_cast<sal_Unicode
>(pArg
->GetUShort());
365 aStr
= OUString(aCh
);
367 rPar
.Get(0)->PutString( aStr
);
377 implChr( rPar
, bChrW
);
386 implChr( rPar
, bChrW
);
394 // #57064 Although this function doesn't work with DirEntry, it isn't touched
395 // by the adjustment to virtual URLs, as, using the DirEntry-functionality,
396 // there's no possibility to detect the current one in a way that a virtual URL
397 // could be delivered.
400 int nCurDir
= 0; // Current dir // JSM
401 if ( rPar
.Count() == 2 )
403 OUString aDrive
= rPar
.Get(1)->GetOUString();
404 if ( aDrive
.getLength() != 1 )
406 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
411 nCurDir
= (int)aDrive
[0];
412 if ( !isalpha( nCurDir
) )
414 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
419 nCurDir
-= ( 'A' - 1 );
423 char* pBuffer
= new char[ _MAX_PATH
];
424 if ( _getdcwd( nCurDir
, pBuffer
, _MAX_PATH
) != 0 )
426 rPar
.Get(0)->PutString( OUString::createFromAscii( pBuffer
) );
430 StarBASIC::Error( SbERR_NO_DEVICE
);
436 const int PATH_INCR
= 250;
438 int nSize
= PATH_INCR
;
439 boost::scoped_array
<char> pMem
;
442 pMem
.reset(new char[nSize
]);
445 StarBASIC::Error( SbERR_NO_MEMORY
);
448 if( getcwd( pMem
.get(), nSize
-1 ) != NULL
)
450 rPar
.Get(0)->PutString( OUString::createFromAscii(pMem
.get()) );
453 if( errno
!= ERANGE
)
455 StarBASIC::Error( SbERR_INTERNAL_ERROR
);
468 rPar
.Get(0)->PutEmpty();
469 if (rPar
.Count() == 2)
471 // VBA: track current directory per document type (separately for Writer, Calc, Impress, etc.)
472 if( SbiRuntime::isVBAEnabled() )
474 ::basic::vba::registerCurrentDirectory( getDocumentModel( pBasic
), rPar
.Get(1)->GetOUString() );
479 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
488 rPar
.Get(0)->PutEmpty();
489 if (rPar
.Count() != 2)
491 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
496 // Implementation of StepRENAME with UCB
497 void implStepRenameUCB( const OUString
& aSource
, const OUString
& aDest
)
499 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
504 OUString aSourceFullPath
= getFullPath( aSource
);
505 if( !xSFI
->exists( aSourceFullPath
) )
507 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
511 OUString aDestFullPath
= getFullPath( aDest
);
512 if( xSFI
->exists( aDestFullPath
) )
514 StarBASIC::Error( SbERR_FILE_EXISTS
);
518 xSFI
->move( aSourceFullPath
, aDestFullPath
);
521 catch(const Exception
& )
523 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
528 // Implementation of StepRENAME with OSL
529 void implStepRenameOSL( const OUString
& aSource
, const OUString
& aDest
)
531 FileBase::RC nRet
= File::move( getFullPath( aSource
), getFullPath( aDest
) );
532 if( nRet
!= FileBase::E_None
)
534 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
543 rPar
.Get(0)->PutEmpty();
544 if (rPar
.Count() == 3)
546 OUString aSource
= rPar
.Get(1)->GetOUString();
547 OUString aDest
= rPar
.Get(2)->GetOUString();
550 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
555 xSFI
->copy( getFullPath( aSource
), getFullPath( aDest
) );
557 catch(const Exception
& )
559 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
565 FileBase::RC nRet
= File::copy( getFullPath( aSource
), getFullPath( aDest
) );
566 if( nRet
!= FileBase::E_None
)
568 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
573 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
581 rPar
.Get(0)->PutEmpty();
582 if (rPar
.Count() == 2)
584 OUString aFileSpec
= rPar
.Get(1)->GetOUString();
588 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
591 OUString aFullPath
= getFullPath( aFileSpec
);
592 if( !xSFI
->exists( aFullPath
) || xSFI
->isFolder( aFullPath
) )
594 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
599 xSFI
->kill( aFullPath
);
601 catch(const Exception
& )
603 StarBASIC::Error( ERRCODE_IO_GENERAL
);
609 File::remove( getFullPath( aFileSpec
) );
614 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
623 rPar
.Get(0)->PutEmpty();
624 if (rPar
.Count() == 2)
626 OUString aPath
= rPar
.Get(1)->GetOUString();
627 if ( SbiRuntime::isVBAEnabled() )
629 // In vba if the full path is not specified then
630 // folder is created relative to the curdir
631 INetURLObject
aURLObj( getFullPath( aPath
) );
632 if ( aURLObj
.GetProtocol() != INetProtocol::File
)
634 SbxArrayRef pPar
= new SbxArray();
635 SbxVariableRef pResult
= new SbxVariable();
636 SbxVariableRef pParam
= new SbxVariable();
637 pPar
->Insert( pResult
, pPar
->Count() );
638 pPar
->Insert( pParam
, pPar
->Count() );
639 SbRtl_CurDir( pBasic
, *pPar
, bWrite
);
641 rtl::OUString sCurPathURL
;
642 File::getFileURLFromSystemPath( pPar
->Get(0)->GetOUString(), sCurPathURL
);
644 aURLObj
.SetURL( sCurPathURL
);
645 aURLObj
.Append( aPath
);
646 File::getSystemPathFromFileURL(aURLObj
.GetMainURL( INetURLObject::DECODE_TO_IURI
),aPath
) ;
652 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
657 xSFI
->createFolder( getFullPath( aPath
) );
659 catch(const Exception
& )
661 StarBASIC::Error( ERRCODE_IO_GENERAL
);
667 Directory::create( getFullPath( aPath
) );
672 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
677 // In OSL only empty directories can be deleted
678 // so we have to delete all files recursively
679 void implRemoveDirRecursive( const OUString
& aDirPath
)
682 FileBase::RC nRet
= DirectoryItem::get( aDirPath
, aItem
);
683 bool bExists
= (nRet
== FileBase::E_None
);
685 FileStatus
aFileStatus( osl_FileStatus_Mask_Type
);
686 nRet
= aItem
.getFileStatus( aFileStatus
);
687 FileStatus::Type aType
= aFileStatus
.getFileType();
688 bool bFolder
= isFolder( aType
);
690 if( !bExists
|| !bFolder
)
692 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
696 Directory
aDir( aDirPath
);
698 if( nRet
!= FileBase::E_None
)
700 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
706 DirectoryItem aItem2
;
707 nRet
= aDir
.getNextItem( aItem2
);
708 if( nRet
!= FileBase::E_None
)
713 FileStatus
aFileStatus2( osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileURL
);
714 nRet
= aItem2
.getFileStatus( aFileStatus2
);
715 OUString aPath
= aFileStatus2
.getFileURL();
718 FileStatus::Type aType2
= aFileStatus2
.getFileType();
719 bool bFolder2
= isFolder( aType2
);
722 implRemoveDirRecursive( aPath
);
726 File::remove( aPath
);
731 nRet
= Directory::remove( aDirPath
);
740 rPar
.Get(0)->PutEmpty();
741 if (rPar
.Count() == 2)
743 OUString aPath
= rPar
.Get(1)->GetOUString();
746 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
751 if( !xSFI
->isFolder( aPath
) )
753 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
756 SbiInstance
* pInst
= GetSbData()->pInst
;
757 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
760 Sequence
< OUString
> aContent
= xSFI
->getFolderContents( aPath
, true );
761 sal_Int32 nCount
= aContent
.getLength();
764 StarBASIC::Error( SbERR_ACCESS_ERROR
);
769 xSFI
->kill( getFullPath( aPath
) );
771 catch(const Exception
& )
773 StarBASIC::Error( ERRCODE_IO_GENERAL
);
779 implRemoveDirRecursive( getFullPath( aPath
) );
784 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
793 rPar
.Get(0)->PutEmpty();
794 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
802 if( rPar
.Count() < 2 )
803 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
806 double aDouble
= rPar
.Get( 1 )->GetDouble();
807 aDouble
= exp( aDouble
);
808 checkArithmeticOverflow( aDouble
);
809 rPar
.Get( 0 )->PutDouble( aDouble
);
818 if ( rPar
.Count() < 2 )
820 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
824 SbxVariableRef pArg
= rPar
.Get( 1 );
825 OUString
aStr( pArg
->GetOUString() );
829 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
834 nLen
= xSFI
->getSize( getFullPath( aStr
) );
836 catch(const Exception
& )
838 StarBASIC::Error( ERRCODE_IO_GENERAL
);
845 DirectoryItem::get( getFullPath( aStr
), aItem
);
846 FileStatus
aFileStatus( osl_FileStatus_Mask_FileSize
);
847 aItem
.getFileStatus( aFileStatus
);
848 nLen
= (sal_Int32
)aFileStatus
.getFileSize();
850 rPar
.Get(0)->PutLong( (long)nLen
);
860 if ( rPar
.Count() < 2 )
862 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
866 SbxVariableRef pArg
= rPar
.Get( 1 );
867 // converting value to unsigned and limit to 2 or 4 byte representation
868 sal_uInt32 nVal
= pArg
->IsInteger() ?
869 static_cast<sal_uInt16
>(pArg
->GetInteger()) :
870 static_cast<sal_uInt32
>(pArg
->GetLong());
871 OUString
aStr(OUString::number( nVal
, 16 ));
872 aStr
= aStr
.toAsciiUpperCase();
873 rPar
.Get(0)->PutString( aStr
);
881 if ( SbiRuntime::isVBAEnabled() && GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
883 if ( GetSbData()->pInst
->pRun
->GetExternalCaller() )
884 *rPar
.Get(0) = *GetSbData()->pInst
->pRun
->GetExternalCaller();
887 SbxVariableRef pVar
= new SbxVariable(SbxVARIANT
);
888 *rPar
.Get(0) = *pVar
;
893 StarBASIC::Error( SbERR_NOT_IMPLEMENTED
);
897 // InStr( [start],string,string,[compare] )
904 sal_Size nArgCount
= rPar
.Count()-1;
906 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
909 sal_Int32 nStartPos
= 1;
910 sal_Int32 nFirstStringPos
= 1;
912 if ( nArgCount
>= 3 )
914 nStartPos
= rPar
.Get(1)->GetLong();
917 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
923 SbiInstance
* pInst
= GetSbData()->pInst
;
925 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
928 SbiRuntime
* pRT
= pInst
->pRun
;
929 bTextMode
= pRT
? pRT
->IsImageFlag( SbiImageFlags::COMPARETEXT
) : sal_False
;
935 if ( nArgCount
== 4 )
937 bTextMode
= rPar
.Get(4)->GetInteger();
940 const OUString
& rToken
= rPar
.Get(nFirstStringPos
+1)->GetOUString();
942 // #97545 Always find empty string
943 if( rToken
.isEmpty() )
951 const OUString
& rStr1
= rPar
.Get(nFirstStringPos
)->GetOUString();
952 nPos
= rStr1
.indexOf( rToken
, nStartPos
- 1 ) + 1;
956 OUString aStr1
= rPar
.Get(nFirstStringPos
)->GetOUString();
957 OUString aToken
= rToken
;
959 aStr1
= aStr1
.toAsciiUpperCase();
960 aToken
= aToken
.toAsciiUpperCase();
962 nPos
= aStr1
.indexOf( aToken
, nStartPos
-1 ) + 1;
965 rPar
.Get(0)->PutLong( nPos
);
970 // InstrRev(string1, string2[, start[, compare]])
977 sal_Size nArgCount
= rPar
.Count()-1;
980 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
984 OUString aStr1
= rPar
.Get(1)->GetOUString();
985 OUString aToken
= rPar
.Get(2)->GetOUString();
987 sal_Int32 nStartPos
= -1;
988 if ( nArgCount
>= 3 )
990 nStartPos
= rPar
.Get(3)->GetLong();
991 if( (nStartPos
<= 0 && nStartPos
!= -1))
993 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
998 SbiInstance
* pInst
= GetSbData()->pInst
;
1000 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1001 if( bCompatibility
)
1003 SbiRuntime
* pRT
= pInst
->pRun
;
1004 bTextMode
= pRT
? pRT
->IsImageFlag( SbiImageFlags::COMPARETEXT
) : sal_False
;
1010 if ( nArgCount
== 4 )
1012 bTextMode
= rPar
.Get(4)->GetInteger();
1014 sal_Int32 nStrLen
= aStr1
.getLength();
1015 if( nStartPos
== -1 )
1017 nStartPos
= nStrLen
;
1021 if( nStartPos
<= nStrLen
)
1023 sal_Int32 nTokenLen
= aToken
.getLength();
1026 // Always find empty string
1029 else if( nStrLen
> 0 )
1033 nPos
= aStr1
.lastIndexOf( aToken
, nStartPos
) + 1;
1037 aStr1
= aStr1
.toAsciiUpperCase();
1038 aToken
= aToken
.toAsciiUpperCase();
1040 nPos
= aStr1
.lastIndexOf( aToken
, nStartPos
) + 1;
1044 rPar
.Get(0)->PutLong( nPos
);
1053 Fix( -2.8 ) = -2.0 <- !!
1061 if ( rPar
.Count() < 2 )
1062 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1065 SbxVariableRef pArg
= rPar
.Get( 1 );
1066 double aDouble
= pArg
->GetDouble();
1069 floor( -2.8 ) = -3.0
1071 aDouble
= floor( aDouble
);
1072 rPar
.Get(0)->PutDouble( aDouble
);
1083 if ( rPar
.Count() < 2 )
1084 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1087 SbxVariableRef pArg
= rPar
.Get( 1 );
1088 double aDouble
= pArg
->GetDouble();
1089 if ( aDouble
>= 0.0 )
1090 aDouble
= floor( aDouble
);
1092 aDouble
= ceil( aDouble
);
1093 rPar
.Get(0)->PutDouble( aDouble
);
1103 if ( rPar
.Count() < 2 )
1105 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1109 const CharClass
& rCharClass
= GetCharClass();
1110 OUString
aStr( rPar
.Get(1)->GetOUString() );
1111 aStr
= rCharClass
.lowercase(aStr
);
1112 rPar
.Get(0)->PutString( aStr
);
1121 if ( rPar
.Count() < 3 )
1123 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1127 OUString
aStr( rPar
.Get(1)->GetOUString() );
1128 sal_Int32 nResultLen
= rPar
.Get(2)->GetLong();
1129 if( nResultLen
< 0 )
1132 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1134 else if(nResultLen
> aStr
.getLength())
1136 nResultLen
= aStr
.getLength();
1138 aStr
= aStr
.copy(0, nResultLen
);
1139 rPar
.Get(0)->PutString( aStr
);
1148 if ( rPar
.Count() < 2 )
1150 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1154 double aArg
= rPar
.Get(1)->GetDouble();
1157 double d
= log( aArg
);
1158 checkArithmeticOverflow( d
);
1159 rPar
.Get( 0 )->PutDouble( d
);
1163 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1173 if ( rPar
.Count() < 2 )
1175 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1179 OUString
aStr(comphelper::string::stripStart(rPar
.Get(1)->GetOUString(), ' '));
1180 rPar
.Get(0)->PutString(aStr
);
1185 // Mid( String, nStart, nLength )
1192 int nArgCount
= rPar
.Count()-1;
1193 if ( nArgCount
< 2 )
1195 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1199 // #23178: replicate the functionality of Mid$ as a command
1200 // by adding a replacement-string as a fourth parameter.
1201 // In contrast to the original the third parameter (nLength)
1202 // can't be left out here. That's considered in bWrite already.
1203 if( nArgCount
== 4 )
1207 OUString aArgStr
= rPar
.Get(1)->GetOUString();
1208 sal_Int32 nStartPos
= rPar
.Get(2)->GetLong();
1209 if ( nStartPos
< 1 )
1211 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1216 sal_Int32 nLen
= -1;
1217 bool bWriteNoLenParam
= false;
1218 if ( nArgCount
== 3 || bWrite
)
1220 sal_Int32 n
= rPar
.Get(3)->GetLong();
1221 if( bWrite
&& n
== -1 )
1223 bWriteNoLenParam
= true;
1229 OUStringBuffer aResultStr
;
1230 SbiInstance
* pInst
= GetSbData()->pInst
;
1231 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1232 if( bCompatibility
)
1234 sal_Int32 nArgLen
= aArgStr
.getLength();
1235 if( nStartPos
+ 1 > nArgLen
)
1237 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1241 OUString aReplaceStr
= rPar
.Get(4)->GetOUString();
1242 sal_Int32 nReplaceStrLen
= aReplaceStr
.getLength();
1243 sal_Int32 nReplaceLen
;
1244 if( bWriteNoLenParam
)
1246 nReplaceLen
= nReplaceStrLen
;
1251 if( nReplaceLen
< 0 || nReplaceLen
> nReplaceStrLen
)
1253 nReplaceLen
= nReplaceStrLen
;
1257 sal_Int32 nReplaceEndPos
= nStartPos
+ nReplaceLen
;
1258 if( nReplaceEndPos
> nArgLen
)
1260 nReplaceLen
-= (nReplaceEndPos
- nArgLen
);
1262 aResultStr
= aArgStr
;
1263 sal_Int32 nErase
= nReplaceLen
;
1264 aResultStr
.remove( nStartPos
, nErase
);
1265 aResultStr
.insert( nStartPos
, aReplaceStr
.getStr(), nReplaceLen
);
1269 aResultStr
= aArgStr
;
1270 sal_Int32 nTmpStartPos
= nStartPos
;
1271 if ( nTmpStartPos
> aArgStr
.getLength() )
1272 nTmpStartPos
= aArgStr
.getLength();
1274 aResultStr
.remove( nTmpStartPos
, nLen
);
1275 aResultStr
.insert( nTmpStartPos
, rPar
.Get(4)->GetOUString().getStr(), std::min(nLen
, rPar
.Get(4)->GetOUString().getLength()));
1278 rPar
.Get(1)->PutString( aResultStr
.makeStringAndClear() );
1282 OUString aResultStr
;
1283 if (nStartPos
> aArgStr
.getLength())
1287 else if(nArgCount
== 2)
1289 aResultStr
= aArgStr
.copy( nStartPos
);
1295 if(nStartPos
+ nLen
> aArgStr
.getLength())
1297 nLen
= aArgStr
.getLength() - nStartPos
;
1300 aResultStr
= aArgStr
.copy( nStartPos
, nLen
);
1302 rPar
.Get(0)->PutString( aResultStr
);
1313 if ( rPar
.Count() < 2 )
1315 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1320 SbxVariableRef pArg
= rPar
.Get( 1 );
1321 if ( pArg
->IsInteger() )
1323 snprintf( aBuffer
, sizeof(aBuffer
), "%o", pArg
->GetInteger() );
1327 snprintf( aBuffer
, sizeof(aBuffer
), "%lo", static_cast<long unsigned int>(pArg
->GetLong()) );
1329 rPar
.Get(0)->PutString( OUString::createFromAscii( aBuffer
) );
1333 // Replace(expression, find, replace[, start[, count[, compare]]])
1340 sal_Size nArgCount
= rPar
.Count()-1;
1341 if ( nArgCount
< 3 || nArgCount
> 6 )
1343 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1347 OUString aExpStr
= rPar
.Get(1)->GetOUString();
1348 OUString aFindStr
= rPar
.Get(2)->GetOUString();
1349 OUString aReplaceStr
= rPar
.Get(3)->GetOUString();
1351 sal_Int32 lStartPos
= 1;
1352 if ( nArgCount
>= 4 )
1354 if( rPar
.Get(4)->GetType() != SbxEMPTY
)
1356 lStartPos
= rPar
.Get(4)->GetLong();
1360 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1365 sal_Int32 lCount
= -1;
1368 if( rPar
.Get(5)->GetType() != SbxEMPTY
)
1370 lCount
= rPar
.Get(5)->GetLong();
1374 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1379 SbiInstance
* pInst
= GetSbData()->pInst
;
1381 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1382 if( bCompatibility
)
1384 SbiRuntime
* pRT
= pInst
->pRun
;
1385 bTextMode
= pRT
? pRT
->IsImageFlag( SbiImageFlags::COMPARETEXT
) : sal_False
;
1391 if ( nArgCount
== 6 )
1393 bTextMode
= rPar
.Get(6)->GetInteger();
1395 sal_Int32 nExpStrLen
= aExpStr
.getLength();
1396 sal_Int32 nFindStrLen
= aFindStr
.getLength();
1397 sal_Int32 nReplaceStrLen
= aReplaceStr
.getLength();
1399 if( lStartPos
<= nExpStrLen
)
1401 sal_Int32 nPos
= lStartPos
- 1;
1402 sal_Int32 nCounts
= 0;
1403 while( lCount
== -1 || lCount
> nCounts
)
1405 OUString
aSrcStr( aExpStr
);
1408 aSrcStr
= aSrcStr
.toAsciiUpperCase();
1409 aFindStr
= aFindStr
.toAsciiUpperCase();
1411 nPos
= aSrcStr
.indexOf( aFindStr
, nPos
);
1414 aExpStr
= aExpStr
.replaceAt( nPos
, nFindStrLen
, aReplaceStr
);
1415 nPos
= nPos
+ nReplaceStrLen
;
1424 rPar
.Get(0)->PutString( aExpStr
.copy( lStartPos
- 1 ) );
1433 if ( rPar
.Count() < 3 )
1435 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1439 const OUString
& rStr
= rPar
.Get(1)->GetOUString();
1440 int nResultLen
= rPar
.Get(2)->GetLong();
1441 if( nResultLen
< 0 )
1444 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1446 int nStrLen
= rStr
.getLength();
1447 if ( nResultLen
> nStrLen
)
1449 nResultLen
= nStrLen
;
1451 OUString aResultStr
= rStr
.copy( nStrLen
- nResultLen
);
1452 rPar
.Get(0)->PutString( aResultStr
);
1461 rPar
.Get( 0 )->PutObject( pBasic
->getRTL() );
1469 if ( rPar
.Count() < 2 )
1471 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1475 OUString
aStr(comphelper::string::stripEnd(rPar
.Get(1)->GetOUString(), ' '));
1476 rPar
.Get(0)->PutString(aStr
);
1485 if ( rPar
.Count() < 2 )
1487 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1491 double aDouble
= rPar
.Get(1)->GetDouble();
1492 sal_Int16 nResult
= 0;
1497 else if ( aDouble
< 0 )
1501 rPar
.Get(0)->PutInteger( nResult
);
1510 if ( rPar
.Count() < 2 )
1512 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1516 OUStringBuffer aBuf
;
1517 string::padToLength(aBuf
, rPar
.Get(1)->GetLong(), ' ');
1518 rPar
.Get(0)->PutString(aBuf
.makeStringAndClear());
1527 if ( rPar
.Count() < 2 )
1529 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1533 OUStringBuffer aBuf
;
1534 string::padToLength(aBuf
, rPar
.Get(1)->GetLong(), ' ');
1535 rPar
.Get(0)->PutString(aBuf
.makeStringAndClear());
1544 if ( rPar
.Count() < 2 )
1546 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1550 double aDouble
= rPar
.Get(1)->GetDouble();
1553 rPar
.Get(0)->PutDouble( sqrt( aDouble
));
1557 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1567 if ( rPar
.Count() < 2 )
1569 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1574 OUString
aStrNew("");
1575 SbxVariableRef pArg
= rPar
.Get( 1 );
1576 pArg
->Format( aStr
);
1578 // Numbers start with a space
1579 if( pArg
->IsNumericRTL() )
1581 // replace commas by points so that it's symmetric to Val!
1582 aStr
= aStr
.replaceFirst( ",", "." );
1584 SbiInstance
* pInst
= GetSbData()->pInst
;
1585 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1586 if( bCompatibility
)
1588 sal_Int32 nLen
= aStr
.getLength();
1590 const sal_Unicode
* pBuf
= aStr
.getStr();
1592 bool bNeg
= ( pBuf
[0] == '-' );
1593 sal_Int32 iZeroSearch
= 0;
1601 if( pBuf
[0] != ' ' )
1606 sal_Int32 iNext
= iZeroSearch
+ 1;
1607 if( pBuf
[iZeroSearch
] == '0' && nLen
> iNext
&& pBuf
[iNext
] == '.' )
1611 aStrNew
+= aStr
.copy(iZeroSearch
);
1615 aStrNew
= " " + aStr
;
1622 rPar
.Get(0)->PutString( aStrNew
);
1631 if ( rPar
.Count() < 3 )
1633 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1634 rPar
.Get(0)->PutEmpty();
1637 const OUString
& rStr1
= rPar
.Get(1)->GetOUString();
1638 const OUString
& rStr2
= rPar
.Get(2)->GetOUString();
1640 SbiInstance
* pInst
= GetSbData()->pInst
;
1642 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
1643 if( bCompatibility
)
1645 SbiRuntime
* pRT
= pInst
->pRun
;
1646 nTextCompare
= pRT
&& pRT
->IsImageFlag( SbiImageFlags::COMPARETEXT
);
1650 nTextCompare
= true;
1652 if ( rPar
.Count() == 4 )
1653 nTextCompare
= rPar
.Get(3)->GetInteger();
1655 if( !bCompatibility
)
1657 nTextCompare
= !nTextCompare
;
1659 sal_Int32 nRetValue
= 0;
1662 ::utl::TransliterationWrapper
* pTransliterationWrapper
= GetSbData()->pTransliterationWrapper
;
1663 if( !pTransliterationWrapper
)
1665 uno::Reference
< uno::XComponentContext
> xContext
= getProcessComponentContext();
1666 pTransliterationWrapper
= GetSbData()->pTransliterationWrapper
=
1667 new ::utl::TransliterationWrapper( xContext
,
1668 i18n::TransliterationModules_IGNORE_CASE
|
1669 i18n::TransliterationModules_IGNORE_KANA
|
1670 i18n::TransliterationModules_IGNORE_WIDTH
);
1673 LanguageType eLangType
= Application::GetSettings().GetLanguageTag().getLanguageType();
1674 pTransliterationWrapper
->loadModuleIfNeeded( eLangType
);
1675 nRetValue
= pTransliterationWrapper
->compareString( rStr1
, rStr2
);
1680 aResult
= rStr1
.compareTo( rStr2
);
1685 else if ( aResult
> 0)
1690 rPar
.Get(0)->PutInteger( sal::static_int_cast
< sal_Int16
>( nRetValue
) );
1698 if ( rPar
.Count() < 2 )
1700 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1704 sal_Unicode aFiller
;
1705 sal_Int32 lCount
= rPar
.Get(1)->GetLong();
1706 if( lCount
< 0 || lCount
> 0xffff )
1708 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1710 if( rPar
.Get(2)->GetType() == SbxINTEGER
)
1712 aFiller
= (sal_Unicode
)rPar
.Get(2)->GetInteger();
1716 const OUString
& rStr
= rPar
.Get(2)->GetOUString();
1719 OUStringBuffer
aBuf(lCount
);
1720 string::padToLength(aBuf
, lCount
, aFiller
);
1721 rPar
.Get(0)->PutString(aBuf
.makeStringAndClear());
1730 if ( rPar
.Count() < 2 )
1732 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1736 SbxVariableRef pArg
= rPar
.Get( 1 );
1737 rPar
.Get( 0 )->PutDouble( tan( pArg
->GetDouble() ) );
1746 if ( rPar
.Count() < 2 )
1748 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1752 const CharClass
& rCharClass
= GetCharClass();
1753 OUString
aStr( rPar
.Get(1)->GetOUString() );
1754 aStr
= rCharClass
.uppercase( aStr
);
1755 rPar
.Get(0)->PutString( aStr
);
1765 if ( rPar
.Count() < 2 )
1767 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1771 double nResult
= 0.0;
1774 OUString
aStr( rPar
.Get(1)->GetOUString() );
1776 FilterWhiteSpace( aStr
);
1777 if ( aStr
[0] == '&' && aStr
.getLength() > 1 )
1780 char aChar
= (char)aStr
[1];
1781 if ( aChar
== 'h' || aChar
== 'H' )
1785 else if ( aChar
== 'o' || aChar
== 'O' )
1791 OString
aByteStr(OUStringToOString(aStr
, osl_getThreadTextEncoding()));
1792 sal_Int16 nlResult
= (sal_Int16
)strtol( aByteStr
.getStr()+2, &pEndPtr
, nRadix
);
1793 nResult
= (double)nlResult
;
1798 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
1799 sal_Int32 nParseEnd
= 0;
1800 nResult
= ::rtl::math::stringToDouble( aStr
, '.', ',', &eStatus
, &nParseEnd
);
1801 if ( eStatus
!= rtl_math_ConversionStatus_Ok
)
1802 StarBASIC::Error( SbERR_MATH_OVERFLOW
);
1803 /* TODO: we should check whether all characters were parsed here,
1804 * but earlier code silently ignored trailing nonsense such as "1x"
1805 * resulting in 1 with the side effect that any alpha-only-string
1806 * like "x" resulted in 0. Not changing that now (2013-03-22) as
1807 * user macros may rely on it. */
1809 else if ( nParseEnd
!= aStr
.getLength() )
1810 StarBASIC::Error( SbERR_CONVERSION
);
1814 rPar
.Get(0)->PutDouble( nResult
);
1819 // Helper functions for date conversion
1820 sal_Int16
implGetDateDay( double aDate
)
1822 aDate
-= 2.0; // standardize: 1.1.1900 => 0.0
1823 Date
aRefDate( 1, 1, 1900 );
1826 aDate
= floor( aDate
);
1827 aRefDate
+= static_cast<long>(aDate
);
1831 aDate
= ceil( aDate
);
1832 aRefDate
-= static_cast<long>(-1.0 * aDate
);
1835 sal_Int16 nRet
= (sal_Int16
)( aRefDate
.GetDay() );
1839 sal_Int16
implGetDateMonth( double aDate
)
1841 Date
aRefDate( 1,1,1900 );
1842 long nDays
= (long)aDate
;
1843 nDays
-= 2; // standardize: 1.1.1900 => 0.0
1845 sal_Int16 nRet
= (sal_Int16
)( aRefDate
.GetMonth() );
1849 ::com::sun::star::util::Date
SbxDateToUNODate( const SbxValue
* const pVal
)
1851 double aDate
= pVal
->GetDate();
1853 com::sun::star::util::Date aUnoDate
;
1854 aUnoDate
.Day
= implGetDateDay ( aDate
);
1855 aUnoDate
.Month
= implGetDateMonth( aDate
);
1856 aUnoDate
.Year
= implGetDateYear ( aDate
);
1861 void SbxDateFromUNODate( SbxValue
*pVal
, const ::com::sun::star::util::Date
& aUnoDate
)
1864 if( implDateSerial( aUnoDate
.Year
, aUnoDate
.Month
, aUnoDate
.Day
, dDate
) )
1866 pVal
->PutDate( dDate
);
1870 // Function to convert date to UNO date (com.sun.star.util.Date)
1871 RTLFUNC(CDateToUnoDate
)
1876 if ( rPar
.Count() != 2 )
1878 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1882 unoToSbxValue(rPar
.Get(0), Any(SbxDateToUNODate(rPar
.Get(1))));
1885 // Function to convert date from UNO date (com.sun.star.util.Date)
1886 RTLFUNC(CDateFromUnoDate
)
1891 if ( rPar
.Count() != 2 || rPar
.Get(1)->GetType() != SbxOBJECT
)
1893 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1897 Any
aAny (sbxToUnoValue(rPar
.Get(1), cppu::UnoType
<com::sun::star::util::Date
>::get()));
1898 com::sun::star::util::Date aUnoDate
;
1899 if(aAny
>>= aUnoDate
)
1900 SbxDateFromUNODate(rPar
.Get(0), aUnoDate
);
1902 SbxBase::SetError( SbxERR_CONVERSION
);
1905 ::com::sun::star::util::Time
SbxDateToUNOTime( const SbxValue
* const pVal
)
1907 double aDate
= pVal
->GetDate();
1909 com::sun::star::util::Time aUnoTime
;
1910 aUnoTime
.Hours
= implGetHour ( aDate
);
1911 aUnoTime
.Minutes
= implGetMinute ( aDate
);
1912 aUnoTime
.Seconds
= implGetSecond ( aDate
);
1913 aUnoTime
.NanoSeconds
= 0;
1918 void SbxDateFromUNOTime( SbxValue
*pVal
, const ::com::sun::star::util::Time
& aUnoTime
)
1920 pVal
->PutDate( implTimeSerial(aUnoTime
.Hours
, aUnoTime
.Minutes
, aUnoTime
.Seconds
) );
1923 // Function to convert date to UNO time (com.sun.star.util.Time)
1924 RTLFUNC(CDateToUnoTime
)
1929 if ( rPar
.Count() != 2 )
1931 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1935 unoToSbxValue(rPar
.Get(0), Any(SbxDateToUNOTime(rPar
.Get(1))));
1938 // Function to convert date from UNO time (com.sun.star.util.Time)
1939 RTLFUNC(CDateFromUnoTime
)
1944 if ( rPar
.Count() != 2 || rPar
.Get(1)->GetType() != SbxOBJECT
)
1946 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1950 Any
aAny (sbxToUnoValue(rPar
.Get(1), cppu::UnoType
<com::sun::star::util::Time
>::get()));
1951 com::sun::star::util::Time aUnoTime
;
1952 if(aAny
>>= aUnoTime
)
1953 SbxDateFromUNOTime(rPar
.Get(0), aUnoTime
);
1955 SbxBase::SetError( SbxERR_CONVERSION
);
1958 ::com::sun::star::util::DateTime
SbxDateToUNODateTime( const SbxValue
* const pVal
)
1960 double aDate
= pVal
->GetDate();
1962 com::sun::star::util::DateTime aUnoDT
;
1963 aUnoDT
.Day
= implGetDateDay ( aDate
);
1964 aUnoDT
.Month
= implGetDateMonth( aDate
);
1965 aUnoDT
.Year
= implGetDateYear ( aDate
);
1966 aUnoDT
.Hours
= implGetHour ( aDate
);
1967 aUnoDT
.Minutes
= implGetMinute ( aDate
);
1968 aUnoDT
.Seconds
= implGetSecond ( aDate
);
1969 aUnoDT
.NanoSeconds
= 0;
1974 void SbxDateFromUNODateTime( SbxValue
*pVal
, const ::com::sun::star::util::DateTime
& aUnoDT
)
1977 if( implDateTimeSerial( aUnoDT
.Year
, aUnoDT
.Month
, aUnoDT
.Day
,
1978 aUnoDT
.Hours
, aUnoDT
.Minutes
, aUnoDT
.Seconds
,
1981 pVal
->PutDate( dDate
);
1985 // Function to convert date to UNO date (com.sun.star.util.Date)
1986 RTLFUNC(CDateToUnoDateTime
)
1991 if ( rPar
.Count() != 2 )
1993 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
1997 unoToSbxValue(rPar
.Get(0), Any(SbxDateToUNODateTime(rPar
.Get(1))));
2000 // Function to convert date from UNO date (com.sun.star.util.Date)
2001 RTLFUNC(CDateFromUnoDateTime
)
2006 if ( rPar
.Count() != 2 || rPar
.Get(1)->GetType() != SbxOBJECT
)
2008 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2012 Any
aAny (sbxToUnoValue(rPar
.Get(1), cppu::UnoType
<com::sun::star::util::DateTime
>::get()));
2013 com::sun::star::util::DateTime aUnoDT
;
2015 SbxDateFromUNODateTime(rPar
.Get(0), aUnoDT
);
2017 SbxBase::SetError( SbxERR_CONVERSION
);
2020 // Function to convert date to ISO 8601 date format
2026 if ( rPar
.Count() == 2 )
2028 double aDate
= rPar
.Get(1)->GetDate();
2031 snprintf( Buffer
, sizeof( Buffer
), "%04d%02d%02d",
2032 implGetDateYear( aDate
),
2033 implGetDateMonth( aDate
),
2034 implGetDateDay( aDate
) );
2035 OUString aRetStr
= OUString::createFromAscii( Buffer
);
2036 rPar
.Get(0)->PutString( aRetStr
);
2040 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2044 // Function to convert date from ISO 8601 date format
2045 RTLFUNC(CDateFromIso
)
2050 if ( rPar
.Count() == 2 )
2052 OUString aStr
= rPar
.Get(1)->GetOUString();
2053 sal_Int16 iMonthStart
= aStr
.getLength() - 4;
2054 OUString aYearStr
= aStr
.copy( 0, iMonthStart
);
2055 OUString aMonthStr
= aStr
.copy( iMonthStart
, 2 );
2056 OUString aDayStr
= aStr
.copy( iMonthStart
+2, 2 );
2059 if( implDateSerial( (sal_Int16
)aYearStr
.toInt32(),
2060 (sal_Int16
)aMonthStr
.toInt32(), (sal_Int16
)aDayStr
.toInt32(), dDate
) )
2062 rPar
.Get(0)->PutDate( dDate
);
2067 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2076 if ( rPar
.Count() < 4 )
2078 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2081 sal_Int16 nYear
= rPar
.Get(1)->GetInteger();
2082 sal_Int16 nMonth
= rPar
.Get(2)->GetInteger();
2083 sal_Int16 nDay
= rPar
.Get(3)->GetInteger();
2086 if( implDateSerial( nYear
, nMonth
, nDay
, dDate
) )
2088 rPar
.Get(0)->PutDate( dDate
);
2097 if ( rPar
.Count() < 4 )
2099 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2102 sal_Int16 nHour
= rPar
.Get(1)->GetInteger();
2105 nHour
= 0; // because of UNO DateTimes, which go till 24 o'clock
2107 sal_Int16 nMinute
= rPar
.Get(2)->GetInteger();
2108 sal_Int16 nSecond
= rPar
.Get(3)->GetInteger();
2109 if ((nHour
< 0 || nHour
> 23) ||
2110 (nMinute
< 0 || nMinute
> 59 ) ||
2111 (nSecond
< 0 || nSecond
> 59 ))
2113 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2117 rPar
.Get(0)->PutDate( implTimeSerial(nHour
, nMinute
, nSecond
) ); // JSM
2125 if ( rPar
.Count() < 2 )
2127 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2131 // #39629 check GetSbData()->pInst, can be called from the URL line
2132 SvNumberFormatter
* pFormatter
= NULL
;
2133 if( GetSbData()->pInst
)
2135 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2139 sal_uInt32 n
; // Dummy
2140 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, n
, n
);
2143 sal_uInt32 nIndex
= 0;
2145 OUString
aStr( rPar
.Get(1)->GetOUString() );
2146 bool bSuccess
= pFormatter
->IsNumberFormat( aStr
, nIndex
, fResult
);
2147 short nType
= pFormatter
->GetType( nIndex
);
2149 // DateValue("February 12, 1969") raises error if the system locale is not en_US
2150 // by using SbiInstance::GetNumberFormatter.
2151 // It seems that both locale number formatter and English number formatter
2152 // are supported in Visual Basic.
2153 LanguageType eLangType
= Application::GetSettings().GetLanguageTag().getLanguageType();
2154 if( !bSuccess
&& ( eLangType
!= LANGUAGE_ENGLISH_US
) )
2156 // Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value;
2157 SvNumberFormatter
aFormatter( comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US
);
2159 bSuccess
= aFormatter
.IsNumberFormat( aStr
, nIndex
, fResult
);
2160 nType
= aFormatter
.GetType( nIndex
);
2163 if(bSuccess
&& (nType
==css::util::NumberFormat::DATE
|| nType
==css::util::NumberFormat::DATETIME
))
2165 if ( nType
== css::util::NumberFormat::DATETIME
)
2168 if ( fResult
> 0.0 )
2170 fResult
= floor( fResult
);
2174 fResult
= ceil( fResult
);
2177 rPar
.Get(0)->PutDate( fResult
);
2181 StarBASIC::Error( SbERR_CONVERSION
);
2183 // #39629 pFormatter can be requested itself
2184 if( !GetSbData()->pInst
)
2196 if ( rPar
.Count() < 2 )
2198 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2202 SvNumberFormatter
* pFormatter
= NULL
;
2203 if( GetSbData()->pInst
)
2204 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2208 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, n
, n
);
2211 sal_uInt32 nIndex
= 0;
2213 bool bSuccess
= pFormatter
->IsNumberFormat( rPar
.Get(1)->GetOUString(),
2215 short nType
= pFormatter
->GetType(nIndex
);
2216 if(bSuccess
&& (nType
==css::util::NumberFormat::TIME
||nType
==css::util::NumberFormat::DATETIME
))
2218 if ( nType
== css::util::NumberFormat::DATETIME
)
2221 fResult
= fmod( fResult
, 1 );
2223 rPar
.Get(0)->PutDate( fResult
);
2227 StarBASIC::Error( SbERR_CONVERSION
);
2229 if( !GetSbData()->pInst
)
2241 if ( rPar
.Count() < 2 )
2243 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2247 SbxVariableRef pArg
= rPar
.Get( 1 );
2248 double aDate
= pArg
->GetDate();
2250 sal_Int16 nDay
= implGetDateDay( aDate
);
2251 rPar
.Get(0)->PutInteger( nDay
);
2260 if ( rPar
.Count() < 2 )
2262 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2266 sal_Int16 nYear
= implGetDateYear( rPar
.Get(1)->GetDate() );
2267 rPar
.Get(0)->PutInteger( nYear
);
2271 sal_Int16
implGetHour( double dDate
)
2277 double nFrac
= dDate
- floor( dDate
);
2279 sal_Int32 nSeconds
= (sal_Int32
)(nFrac
+ 0.5);
2280 sal_Int16 nHour
= (sal_Int16
)(nSeconds
/ 3600);
2289 if ( rPar
.Count() < 2 )
2291 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2295 double nArg
= rPar
.Get(1)->GetDate();
2296 sal_Int16 nHour
= implGetHour( nArg
);
2297 rPar
.Get(0)->PutInteger( nHour
);
2306 if ( rPar
.Count() < 2 )
2308 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2312 double nArg
= rPar
.Get(1)->GetDate();
2313 sal_Int16 nMin
= implGetMinute( nArg
);
2314 rPar
.Get(0)->PutInteger( nMin
);
2323 if ( rPar
.Count() < 2 )
2325 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2329 sal_Int16 nMonth
= implGetDateMonth( rPar
.Get(1)->GetDate() );
2330 rPar
.Get(0)->PutInteger( nMonth
);
2334 sal_Int16
implGetSecond( double dDate
)
2340 double nFrac
= dDate
- floor( dDate
);
2342 sal_Int32 nSeconds
= (sal_Int32
)(nFrac
+ 0.5);
2343 sal_Int16 nTemp
= (sal_Int16
)(nSeconds
/ 3600);
2344 nSeconds
-= nTemp
* 3600;
2345 nTemp
= (sal_Int16
)(nSeconds
/ 60);
2346 nSeconds
-= nTemp
* 60;
2348 sal_Int16 nRet
= (sal_Int16
)nSeconds
;
2357 if ( rPar
.Count() < 2 )
2359 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2363 double nArg
= rPar
.Get(1)->GetDate();
2364 sal_Int16 nSecond
= implGetSecond( nArg
);
2365 rPar
.Get(0)->PutInteger( nSecond
);
2371 Date
aDate( Date::SYSTEM
);
2372 tools::Time
aTime( tools::Time::SYSTEM
);
2373 double aSerial
= (double)GetDayDiff( aDate
);
2374 long nSeconds
= aTime
.GetHour();
2376 nSeconds
+= aTime
.GetMin() * 60;
2377 nSeconds
+= aTime
.GetSec();
2378 double nDays
= ((double)nSeconds
) / (double)(24.0*3600.0);
2389 rPar
.Get(0)->PutDate( Now_Impl() );
2400 tools::Time
aTime( tools::Time::SYSTEM
);
2401 SbxVariable
* pMeth
= rPar
.Get( 0 );
2403 if( pMeth
->IsFixed() )
2407 snprintf( buf
, sizeof(buf
), "%02d:%02d:%02d",
2408 aTime
.GetHour(), aTime
.GetMin(), aTime
.GetSec() );
2409 aRes
= OUString::createFromAscii( buf
);
2413 // Time: system dependent
2414 long nSeconds
=aTime
.GetHour();
2416 nSeconds
+= aTime
.GetMin() * 60;
2417 nSeconds
+= aTime
.GetSec();
2418 double nDays
= (double)nSeconds
* ( 1.0 / (24.0*3600.0) );
2421 SvNumberFormatter
* pFormatter
= NULL
;
2423 if( GetSbData()->pInst
)
2425 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2426 nIndex
= GetSbData()->pInst
->GetStdTimeIdx();
2430 sal_uInt32 n
; // Dummy
2431 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, nIndex
, n
);
2434 pFormatter
->GetOutputString( nDays
, nIndex
, aRes
, &pCol
);
2436 if( !GetSbData()->pInst
)
2441 pMeth
->PutString( aRes
);
2445 StarBASIC::Error( SbERR_NOT_IMPLEMENTED
);
2454 tools::Time
aTime( tools::Time::SYSTEM
);
2455 long nSeconds
= aTime
.GetHour();
2457 nSeconds
+= aTime
.GetMin() * 60;
2458 nSeconds
+= aTime
.GetSec();
2459 rPar
.Get(0)->PutDate( (double)nSeconds
);
2470 Date
aToday( Date::SYSTEM
);
2471 double nDays
= (double)GetDayDiff( aToday
);
2472 SbxVariable
* pMeth
= rPar
.Get( 0 );
2473 if( pMeth
->IsString() )
2478 SvNumberFormatter
* pFormatter
= NULL
;
2480 if( GetSbData()->pInst
)
2482 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
2483 nIndex
= GetSbData()->pInst
->GetStdDateIdx();
2488 SbiInstance::PrepareNumberFormatter( pFormatter
, nIndex
, n
, n
);
2491 pFormatter
->GetOutputString( nDays
, nIndex
, aRes
, &pCol
);
2492 pMeth
->PutString( aRes
);
2494 if( !GetSbData()->pInst
)
2501 pMeth
->PutDate( nDays
);
2506 StarBASIC::Error( SbERR_NOT_IMPLEMENTED
);
2515 if ( rPar
.Count() < 2 )
2517 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2521 rPar
.Get(0)->PutBool((rPar
.Get(1)->GetType() & SbxARRAY
) != 0);
2530 if ( rPar
.Count() < 2 )
2532 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2536 SbxVariable
* pVar
= rPar
.Get(1);
2537 SbxBase
* pObj
= pVar
->GetObject();
2539 // #100385: GetObject can result in an error, so reset it
2540 SbxBase::ResetError();
2542 SbUnoClass
* pUnoClass
;
2544 if( pObj
&& NULL
!= ( pUnoClass
=PTR_CAST(SbUnoClass
,pObj
) ) )
2546 bObject
= pUnoClass
->getUnoClass().is();
2550 bObject
= pVar
->IsObject();
2552 rPar
.Get( 0 )->PutBool( bObject
);
2561 if ( rPar
.Count() < 2 )
2563 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2567 // #46134 only string is converted, all other types result in sal_False
2568 SbxVariableRef xArg
= rPar
.Get( 1 );
2569 SbxDataType eType
= xArg
->GetType();
2572 if( eType
== SbxDATE
)
2576 else if( eType
== SbxSTRING
)
2578 SbxError nPrevError
= SbxBase::GetError();
2579 SbxBase::ResetError();
2581 // force conversion of the parameter to SbxDATE
2582 xArg
->SbxValue::GetDate();
2584 bDate
= !SbxBase::IsError();
2586 SbxBase::ResetError();
2587 SbxBase::SetError( nPrevError
);
2589 rPar
.Get( 0 )->PutBool( bDate
);
2598 if ( rPar
.Count() < 2 )
2600 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2604 SbxVariable
* pVar
= NULL
;
2605 if( SbiRuntime::isVBAEnabled() )
2607 pVar
= getDefaultProp( rPar
.Get(1) );
2611 pVar
->Broadcast( SBX_HINT_DATAWANTED
);
2612 rPar
.Get( 0 )->PutBool( pVar
->IsEmpty() );
2616 rPar
.Get( 0 )->PutBool( rPar
.Get(1)->IsEmpty() );
2626 if ( rPar
.Count() < 2 )
2628 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2632 SbxVariable
* pVar
=rPar
.Get( 1 );
2633 SbUnoObject
* pObj
= PTR_CAST(SbUnoObject
,pVar
);
2636 if ( SbxBase
* pBaseObj
= pVar
->GetObject() )
2638 pObj
= PTR_CAST(SbUnoObject
, pBaseObj
);
2641 uno::Reference
< script::XErrorQuery
> xError
;
2644 xError
.set( pObj
->getUnoAny(), uno::UNO_QUERY
);
2648 rPar
.Get( 0 )->PutBool( xError
->hasError() );
2652 rPar
.Get( 0 )->PutBool( rPar
.Get(1)->IsErr() );
2662 if ( rPar
.Count() < 2 )
2664 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2668 // #51475 because of Uno-objects return true
2669 // even if the pObj value is NULL
2670 SbxVariableRef pArg
= rPar
.Get( 1 );
2671 bool bNull
= rPar
.Get(1)->IsNull();
2672 if( !bNull
&& pArg
->GetType() == SbxOBJECT
)
2674 SbxBase
* pObj
= pArg
->GetObject();
2680 rPar
.Get( 0 )->PutBool( bNull
);
2689 if ( rPar
.Count() < 2 )
2691 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2695 rPar
.Get( 0 )->PutBool( rPar
.Get( 1 )->IsNumericRTL() );
2706 if ( rPar
.Count() < 2 )
2708 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2712 // #57915 Missing is reported by an error
2713 rPar
.Get( 0 )->PutBool( rPar
.Get(1)->IsErr() );
2717 // Function looks for wildcards, removes them and always returns the pure path
2718 OUString
implSetupWildcard( const OUString
& rFileParam
, SbiRTLData
* pRTLData
)
2720 static sal_Char cDelim1
= (sal_Char
)'/';
2721 static sal_Char cDelim2
= (sal_Char
)'\\';
2722 static sal_Char cWild1
= '*';
2723 static sal_Char cWild2
= '?';
2725 delete pRTLData
->pWildCard
;
2726 pRTLData
->pWildCard
= NULL
;
2727 pRTLData
->sFullNameToBeChecked
.clear();
2729 OUString aFileParam
= rFileParam
;
2730 sal_Int32 nLastWild
= aFileParam
.lastIndexOf( cWild1
);
2733 nLastWild
= aFileParam
.lastIndexOf( cWild2
);
2735 bool bHasWildcards
= ( nLastWild
>= 0 );
2738 sal_Int32 nLastDelim
= aFileParam
.lastIndexOf( cDelim1
);
2739 if( nLastDelim
< 0 )
2741 nLastDelim
= aFileParam
.lastIndexOf( cDelim2
);
2745 // Wildcards in path?
2746 if( nLastDelim
>= 0 && nLastDelim
> nLastWild
)
2753 OUString aPathStr
= getFullPath( aFileParam
);
2754 if( nLastDelim
!= aFileParam
.getLength() - 1 )
2756 pRTLData
->sFullNameToBeChecked
= aPathStr
;
2761 OUString aPureFileName
;
2762 if( nLastDelim
< 0 )
2764 aPureFileName
= aFileParam
;
2769 aPureFileName
= aFileParam
.copy( nLastDelim
+ 1 );
2770 aFileParam
= aFileParam
.copy( 0, nLastDelim
);
2773 // Try again to get a valid URL/UNC-path with only the path
2774 OUString aPathStr
= getFullPath( aFileParam
);
2776 // Is there a pure file name left? Otherwise the path is
2777 // invalid anyway because it was not accepted by OSL before
2778 if (!string::equals(aPureFileName
, '*'))
2780 pRTLData
->pWildCard
= new WildCard( aPureFileName
);
2785 inline bool implCheckWildcard( const OUString
& rName
, SbiRTLData
* pRTLData
)
2789 if( pRTLData
->pWildCard
)
2791 bMatch
= pRTLData
->pWildCard
->Matches( rName
);
2797 bool isRootDir( const OUString
& aDirURLStr
)
2799 INetURLObject
aDirURLObj( aDirURLStr
);
2802 // Check if it's a root directory
2803 sal_Int32 nCount
= aDirURLObj
.getSegmentCount();
2805 // No segment means Unix root directory "file:///"
2810 // Exactly one segment needs further checking, because it
2811 // can be Unix "file:///foo/" -> no root
2812 // or Windows "file:///c:/" -> root
2813 else if( nCount
== 1 )
2815 OUString aSeg1
= aDirURLObj
.getName( 0, true,
2816 INetURLObject::DECODE_WITH_CHARSET
);
2817 if( aSeg1
[1] == (sal_Unicode
)':' )
2822 // More than one segments can never be root
2823 // so bRoot remains false
2835 sal_uInt16 nParCount
= rPar
.Count();
2838 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
2842 SbiRTLData
* pRTLData
= GetSbData()->pInst
->GetRTLData();
2844 // #34645: can also be called from the URL line via 'macro: Dir'
2845 // there's no pRTLDate existing in that case and the method must be left
2852 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
2855 if ( nParCount
>= 2 )
2857 OUString aFileParam
= rPar
.Get(1)->GetOUString();
2859 OUString aFileURLStr
= implSetupWildcard( aFileParam
, pRTLData
);
2860 if( !pRTLData
->sFullNameToBeChecked
.isEmpty())
2862 bool bExists
= false;
2863 try { bExists
= xSFI
->exists( aFileURLStr
); }
2864 catch(const Exception
& ) {}
2866 OUString aNameOnlyStr
;
2869 INetURLObject
aFileURL( aFileURLStr
);
2870 aNameOnlyStr
= aFileURL
.getName( INetURLObject::LAST_SEGMENT
,
2871 true, INetURLObject::DECODE_WITH_CHARSET
);
2873 rPar
.Get(0)->PutString( aNameOnlyStr
);
2879 OUString aDirURLStr
;
2880 bool bFolder
= xSFI
->isFolder( aFileURLStr
);
2884 aDirURLStr
= aFileURLStr
;
2889 rPar
.Get(0)->PutString( aEmptyStr
);
2892 sal_uInt16 nFlags
= 0;
2893 if ( nParCount
> 2 )
2895 pRTLData
->nDirFlags
= nFlags
= rPar
.Get(2)->GetInteger();
2899 pRTLData
->nDirFlags
= 0;
2902 bool bIncludeFolders
= ((nFlags
& Sb_ATTR_DIRECTORY
) != 0);
2903 pRTLData
->aDirSeq
= xSFI
->getFolderContents( aDirURLStr
, bIncludeFolders
);
2904 pRTLData
->nCurDirPos
= 0;
2906 // #78651 Add "." and ".." directories for VB compatibility
2907 if( bIncludeFolders
)
2909 bool bRoot
= isRootDir( aDirURLStr
);
2911 // If it's no root directory we flag the need for
2912 // the "." and ".." directories by the value -2
2913 // for the actual position. Later for -2 will be
2914 // returned "." and for -1 ".."
2917 pRTLData
->nCurDirPos
= -2;
2921 catch(const Exception
& )
2927 if( pRTLData
->aDirSeq
.getLength() > 0 )
2929 bool bFolderFlag
= ((pRTLData
->nDirFlags
& Sb_ATTR_DIRECTORY
) != 0);
2931 SbiInstance
* pInst
= GetSbData()->pInst
;
2932 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
2935 if( pRTLData
->nCurDirPos
< 0 )
2937 if( pRTLData
->nCurDirPos
== -2 )
2941 else if( pRTLData
->nCurDirPos
== -1 )
2945 pRTLData
->nCurDirPos
++;
2947 else if( pRTLData
->nCurDirPos
>= pRTLData
->aDirSeq
.getLength() )
2949 pRTLData
->aDirSeq
.realloc( 0 );
2955 OUString aFile
= pRTLData
->aDirSeq
.getConstArray()[pRTLData
->nCurDirPos
++];
2957 if( bCompatibility
)
2961 bool bFolder
= xSFI
->isFolder( aFile
);
2973 bool bFolder
= xSFI
->isFolder( aFile
);
2981 INetURLObject
aURL( aFile
);
2982 aPath
= aURL
.getName( INetURLObject::LAST_SEGMENT
, true,
2983 INetURLObject::DECODE_WITH_CHARSET
);
2986 bool bMatch
= implCheckWildcard( aPath
, pRTLData
);
2994 rPar
.Get(0)->PutString( aPath
);
3000 if ( nParCount
>= 2 )
3002 OUString aFileParam
= rPar
.Get(1)->GetOUString();
3004 OUString aDirURL
= implSetupWildcard( aFileParam
, pRTLData
);
3006 sal_uInt16 nFlags
= 0;
3007 if ( nParCount
> 2 )
3009 pRTLData
->nDirFlags
= nFlags
= rPar
.Get(2)->GetInteger();
3013 pRTLData
->nDirFlags
= 0;
3017 bool bIncludeFolders
= ((nFlags
& Sb_ATTR_DIRECTORY
) != 0);
3018 pRTLData
->pDir
= new Directory( aDirURL
);
3019 FileBase::RC nRet
= pRTLData
->pDir
->open();
3020 if( nRet
!= FileBase::E_None
)
3022 delete pRTLData
->pDir
;
3023 pRTLData
->pDir
= NULL
;
3024 rPar
.Get(0)->PutString( OUString() );
3028 // #86950 Add "." and ".." directories for VB compatibility
3029 pRTLData
->nCurDirPos
= 0;
3030 if( bIncludeFolders
)
3032 bool bRoot
= isRootDir( aDirURL
);
3034 // If it's no root directory we flag the need for
3035 // the "." and ".." directories by the value -2
3036 // for the actual position. Later for -2 will be
3037 // returned "." and for -1 ".."
3040 pRTLData
->nCurDirPos
= -2;
3046 if( pRTLData
->pDir
)
3048 bool bFolderFlag
= ((pRTLData
->nDirFlags
& Sb_ATTR_DIRECTORY
) != 0);
3051 if( pRTLData
->nCurDirPos
< 0 )
3053 if( pRTLData
->nCurDirPos
== -2 )
3057 else if( pRTLData
->nCurDirPos
== -1 )
3061 pRTLData
->nCurDirPos
++;
3065 DirectoryItem aItem
;
3066 FileBase::RC nRet
= pRTLData
->pDir
->getNextItem( aItem
);
3067 if( nRet
!= FileBase::E_None
)
3069 delete pRTLData
->pDir
;
3070 pRTLData
->pDir
= NULL
;
3076 FileStatus
aFileStatus( osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
);
3077 nRet
= aItem
.getFileStatus( aFileStatus
);
3079 // Only directories?
3082 FileStatus::Type aType
= aFileStatus
.getFileType();
3083 bool bFolder
= isFolder( aType
);
3090 aPath
= aFileStatus
.getFileName();
3093 bool bMatch
= implCheckWildcard( aPath
, pRTLData
);
3101 rPar
.Get(0)->PutString( aPath
);
3112 if ( rPar
.Count() == 2 )
3114 sal_Int16 nFlags
= 0;
3116 // In Windows, we want to use Windows API to get the file attributes
3117 // for VBA interoperability.
3119 if( SbiRuntime::isVBAEnabled() )
3121 OUString aPathURL
= getFullPath( rPar
.Get(1)->GetOUString() );
3123 FileBase::getSystemPathFromFileURL( aPathURL
, aPath
);
3124 OString
aSystemPath(OUStringToOString(aPath
, osl_getThreadTextEncoding()));
3125 DWORD nRealFlags
= GetFileAttributes (aSystemPath
.getStr());
3126 if (nRealFlags
!= 0xffffffff)
3128 if (nRealFlags
== FILE_ATTRIBUTE_NORMAL
)
3132 nFlags
= (sal_Int16
) (nRealFlags
);
3136 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
3138 rPar
.Get(0)->PutInteger( nFlags
);
3146 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
3151 OUString aPath
= getFullPath( rPar
.Get(1)->GetOUString() );
3152 bool bExists
= false;
3153 try { bExists
= xSFI
->exists( aPath
); }
3154 catch(const Exception
& ) {}
3157 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
3161 bool bReadOnly
= xSFI
->isReadOnly( aPath
);
3162 bool bHidden
= xSFI
->isHidden( aPath
);
3163 bool bDirectory
= xSFI
->isFolder( aPath
);
3166 nFlags
|= Sb_ATTR_READONLY
;
3170 nFlags
|= Sb_ATTR_HIDDEN
;
3174 nFlags
|= Sb_ATTR_DIRECTORY
;
3177 catch(const Exception
& )
3179 StarBASIC::Error( ERRCODE_IO_GENERAL
);
3185 DirectoryItem aItem
;
3186 DirectoryItem::get( getFullPath( rPar
.Get(1)->GetOUString() ), aItem
);
3187 FileStatus
aFileStatus( osl_FileStatus_Mask_Attributes
| osl_FileStatus_Mask_Type
);
3188 aItem
.getFileStatus( aFileStatus
);
3189 sal_uInt64 nAttributes
= aFileStatus
.getAttributes();
3190 bool bReadOnly
= (nAttributes
& osl_File_Attribute_ReadOnly
) != 0;
3192 FileStatus::Type aType
= aFileStatus
.getFileType();
3193 bool bDirectory
= isFolder( aType
);
3196 nFlags
|= Sb_ATTR_READONLY
;
3200 nFlags
|= Sb_ATTR_DIRECTORY
;
3203 rPar
.Get(0)->PutInteger( nFlags
);
3207 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3212 RTLFUNC(FileDateTime
)
3217 if ( rPar
.Count() != 2 )
3219 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3223 OUString aPath
= rPar
.Get(1)->GetOUString();
3224 tools::Time
aTime( tools::Time::EMPTY
);
3225 Date
aDate( Date::EMPTY
);
3228 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
3233 util::DateTime aUnoDT
= xSFI
->getDateTimeModified( aPath
);
3234 aTime
= tools::Time( aUnoDT
);
3235 aDate
= Date( aUnoDT
);
3237 catch(const Exception
& )
3239 StarBASIC::Error( ERRCODE_IO_GENERAL
);
3245 DirectoryItem aItem
;
3246 DirectoryItem::get( getFullPath( aPath
), aItem
);
3247 FileStatus
aFileStatus( osl_FileStatus_Mask_ModifyTime
);
3248 aItem
.getFileStatus( aFileStatus
);
3249 TimeValue aTimeVal
= aFileStatus
.getModifyTime();
3251 osl_getDateTimeFromTimeValue( &aTimeVal
, &aDT
);
3253 aTime
= tools::Time( aDT
.Hours
, aDT
.Minutes
, aDT
.Seconds
, aDT
.NanoSeconds
);
3254 aDate
= Date( aDT
.Day
, aDT
.Month
, aDT
.Year
);
3257 double fSerial
= (double)GetDayDiff( aDate
);
3258 long nSeconds
= aTime
.GetHour();
3260 nSeconds
+= aTime
.GetMin() * 60;
3261 nSeconds
+= aTime
.GetSec();
3262 double nDays
= ((double)nSeconds
) / (double)(24.0*3600.0);
3267 SvNumberFormatter
* pFormatter
= NULL
;
3269 if( GetSbData()->pInst
)
3271 pFormatter
= GetSbData()->pInst
->GetNumberFormatter();
3272 nIndex
= GetSbData()->pInst
->GetStdDateTimeIdx();
3277 SbiInstance::PrepareNumberFormatter( pFormatter
, n
, n
, nIndex
);
3281 pFormatter
->GetOutputString( fSerial
, nIndex
, aRes
, &pCol
);
3282 rPar
.Get(0)->PutString( aRes
);
3284 if( !GetSbData()->pInst
)
3297 // No changes for UCB
3298 if ( rPar
.Count() != 2 )
3300 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3304 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3305 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3306 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3309 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3313 SvStream
* pSvStrm
= pSbStrm
->GetStrm();
3314 if ( pSbStrm
->IsText() )
3317 (*pSvStrm
).ReadChar( cBla
); // can we read another character?
3318 bIsEof
= pSvStrm
->IsEof();
3321 pSvStrm
->SeekRel( -1 );
3326 bIsEof
= pSvStrm
->IsEof(); // for binary data!
3328 rPar
.Get(0)->PutBool( bIsEof
);
3337 // No changes for UCB
3338 // #57064 Although this function doesn't operate with DirEntry, it is
3339 // not touched by the adjustment to virtual URLs, as it only works on
3340 // already opened files and the name doesn't matter there.
3342 if ( rPar
.Count() != 3 )
3344 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3348 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3349 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3350 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3353 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3357 if ( rPar
.Get(2)->GetInteger() == 1 )
3359 nRet
= (sal_Int16
)(pSbStrm
->GetMode());
3363 nRet
= 0; // System file handle not supported
3365 rPar
.Get(0)->PutInteger( nRet
);
3373 // No changes for UCB
3374 if ( rPar
.Count() != 2 )
3376 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3380 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3381 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3382 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3385 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3388 SvStream
* pSvStrm
= pSbStrm
->GetStrm();
3390 if( pSbStrm
->IsRandom())
3392 short nBlockLen
= pSbStrm
->GetBlockLen();
3393 nPos
= nBlockLen
? (pSvStrm
->Tell() / nBlockLen
) : 0;
3394 nPos
++; // block positions starting at 1
3396 else if ( pSbStrm
->IsText() )
3398 nPos
= pSbStrm
->GetLine();
3400 else if( pSbStrm
->IsBinary() )
3402 nPos
= pSvStrm
->Tell();
3404 else if ( pSbStrm
->IsSeq() )
3406 nPos
= ( pSvStrm
->Tell()+1 ) / 128;
3410 nPos
= pSvStrm
->Tell();
3412 rPar
.Get(0)->PutLong( (sal_Int32
)nPos
);
3421 // No changes for UCB
3422 if ( rPar
.Count() != 2 )
3424 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3428 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3429 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3430 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3433 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3436 SvStream
* pSvStrm
= pSbStrm
->GetStrm();
3437 sal_Size nOldPos
= pSvStrm
->Tell();
3438 sal_Size nLen
= pSvStrm
->Seek( STREAM_SEEK_TO_END
);
3439 pSvStrm
->Seek( nOldPos
);
3440 rPar
.Get(0)->PutLong( (sal_Int32
)nLen
);
3450 // No changes for UCB
3451 int nArgs
= (int)rPar
.Count();
3452 if ( nArgs
< 2 || nArgs
> 3 )
3454 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3457 sal_Int16 nChannel
= rPar
.Get(1)->GetInteger();
3458 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
3459 SbiStream
* pSbStrm
= pIO
->GetStream( nChannel
);
3462 StarBASIC::Error( SbERR_BAD_CHANNEL
);
3465 SvStream
* pStrm
= pSbStrm
->GetStrm();
3467 if ( nArgs
== 2 ) // Seek-Function
3469 sal_Size nPos
= pStrm
->Tell();
3470 if( pSbStrm
->IsRandom() )
3472 nPos
= nPos
/ pSbStrm
->GetBlockLen();
3474 nPos
++; // Basic counts from 1
3475 rPar
.Get(0)->PutLong( (sal_Int32
)nPos
);
3477 else // Seek-Statement
3479 sal_Int32 nPos
= rPar
.Get(2)->GetLong();
3482 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3485 nPos
--; // Basic counts from 1, SvStreams count from 0
3486 pSbStrm
->SetExpandOnWriteTo( 0 );
3487 if ( pSbStrm
->IsRandom() )
3489 nPos
*= pSbStrm
->GetBlockLen();
3491 pStrm
->Seek( (sal_Size
)nPos
);
3492 pSbStrm
->SetExpandOnWriteTo( nPos
);
3501 sal_uInt16 nArgCount
= (sal_uInt16
)rPar
.Count();
3502 if ( nArgCount
< 2 || nArgCount
> 3 )
3504 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3509 if( nArgCount
== 2 )
3511 rPar
.Get(1)->Format( aResult
);
3515 OUString
aFmt( rPar
.Get(2)->GetOUString() );
3516 rPar
.Get(1)->Format( aResult
, &aFmt
);
3518 rPar
.Get(0)->PutString( aResult
);
3524 // note: BASIC does not use comphelper::random, because
3525 // Randomize(int) must be supported and should not affect non-BASIC random use
3526 struct RandomNumberGenerator
3528 std::mt19937 global_rng
;
3530 RandomNumberGenerator()
3534 std::random_device rd
;
3535 // initialises the state of the global random number generator
3536 // should only be called once.
3537 // (note, a few std::variate_generator<> (like normal) have their
3538 // own state which would need a reset as well to guarantee identical
3539 // sequence of numbers, e.g. via myrand.distribution().reset())
3540 global_rng
.seed(rd() ^ time(nullptr));
3542 catch (std::runtime_error
& e
)
3544 SAL_WARN("basic", "Using std::random_device failed: " << e
.what());
3545 global_rng
.seed(time(nullptr));
3550 class theRandomNumberGenerator
: public rtl::Static
<RandomNumberGenerator
, theRandomNumberGenerator
> {};
3559 if ( rPar
.Count() > 2 )
3561 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3564 if( rPar
.Count() == 2 )
3566 nSeed
= (int)rPar
.Get(1)->GetInteger();
3567 theRandomNumberGenerator::get().global_rng
.seed(nSeed
);
3569 // without parameter, no need to do anything - RNG is seeded at first use
3577 if ( rPar
.Count() > 2 )
3579 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3583 std::uniform_real_distribution
<double> dist(0.0, 1.0);
3584 double const tmp(dist(theRandomNumberGenerator::get().global_rng
));
3585 rPar
.Get(0)->PutDouble(tmp
);
3590 // Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = sal_False ]]])
3591 // WindowStyles (VBA-kompatibel):
3594 // 10 == Full-Screen (text mode applications OS/2, WIN95, WNT)
3595 // HACK: The WindowStyle will be passed to
3596 // Application::StartApp in Creator. Format: "xxxx2"
3604 // No shell command for "virtual" portal users
3605 if( needSecurityRestrictions() )
3607 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
3611 sal_Size nArgCount
= rPar
.Count();
3612 if ( nArgCount
< 2 || nArgCount
> 5 )
3614 rPar
.Get(0)->PutLong(0);
3615 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3619 oslProcessOption nOptions
= osl_Process_SEARCHPATH
| osl_Process_DETACHED
;
3621 OUString aCmdLine
= rPar
.Get(1)->GetOUString();
3622 // attach additional parameters - everything must be parsed anyway
3623 if( nArgCount
>= 4 )
3625 OUString tmp
= rPar
.Get(3)->GetOUString().trim();
3632 else if( aCmdLine
.isEmpty() )
3634 // avaoid special treatment (empty list)
3637 sal_Int32 nLen
= aCmdLine
.getLength();
3639 // #55735 if there are parameters, they have to be separated
3640 // #72471 also separate the single parameters
3641 std::list
<OUString
> aTokenList
;
3650 if ( c
!= ' ' && c
!= '\t' )
3656 if( c
== '\"' || c
== '\'' )
3658 sal_Int32 iFoundPos
= aCmdLine
.indexOf( c
, i
+ 1 );
3662 aToken
= aCmdLine
.copy( i
);
3667 aToken
= aCmdLine
.copy( i
+ 1, (iFoundPos
- i
- 1) );
3673 sal_Int32 iFoundSpacePos
= aCmdLine
.indexOf( ' ', i
);
3674 sal_Int32 iFoundTabPos
= aCmdLine
.indexOf( '\t', i
);
3675 sal_Int32 iFoundPos
= iFoundSpacePos
>= 0 ? iFoundTabPos
>= 0 ? std::min( iFoundSpacePos
, iFoundTabPos
) : iFoundSpacePos
: -1;
3679 aToken
= aCmdLine
.copy( i
);
3684 aToken
= aCmdLine
.copy( i
, (iFoundPos
- i
) );
3689 // insert into the list
3690 aTokenList
.push_back( aToken
);
3692 // #55735 / #72471 end
3694 sal_Int16 nWinStyle
= 0;
3695 if( nArgCount
>= 3 )
3697 nWinStyle
= rPar
.Get(2)->GetInteger();
3701 nOptions
|= osl_Process_MINIMIZED
;
3704 nOptions
|= osl_Process_MAXIMIZED
;
3707 nOptions
|= osl_Process_FULLSCREEN
;
3712 if( nArgCount
>= 5 )
3714 bSync
= rPar
.Get(4)->GetBool();
3718 nOptions
|= osl_Process_WAIT
;
3722 // #72471 work parameter(s) up
3723 std::list
<OUString
>::const_iterator iter
= aTokenList
.begin();
3724 const OUString
& rStr
= *iter
;
3725 OUString
aOUStrProg( rStr
.getStr(), rStr
.getLength() );
3726 OUString aOUStrProgURL
= getFullPath( aOUStrProg
);
3730 sal_uInt16 nParamCount
= sal::static_int_cast
< sal_uInt16
>(aTokenList
.size() - 1 );
3731 rtl_uString
** pParamList
= NULL
;
3734 pParamList
= new rtl_uString
*[nParamCount
];
3735 for(int iList
= 0; iter
!= aTokenList
.end(); ++iList
, ++iter
)
3737 const OUString
& rParamStr
= (*iter
);
3738 const OUString
aTempStr( rParamStr
.getStr(), rParamStr
.getLength());
3739 pParamList
[iList
] = NULL
;
3740 rtl_uString_assign(&(pParamList
[iList
]), aTempStr
.pData
);
3745 bool bSucc
= osl_executeProcess(
3746 aOUStrProgURL
.pData
,
3753 &pApp
) == osl_Process_E_None
;
3755 // 53521 only free process handle on success
3758 osl_freeProcessHandle( pApp
);
3761 for(int j
= 0; j
< nParamCount
; ++j
)
3763 rtl_uString_release(pParamList
[j
]);
3766 delete [] pParamList
;
3770 StarBASIC::Error( SbERR_FILE_NOT_FOUND
);
3774 rPar
.Get(0)->PutLong( 0 );
3784 if ( rPar
.Count() != 2 )
3786 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3790 SbxDataType eType
= rPar
.Get(1)->GetType();
3791 rPar
.Get(0)->PutInteger( (sal_Int16
)eType
);
3795 // Exported function
3796 OUString
getBasicTypeName( SbxDataType eType
)
3798 static const char* pTypeNames
[] =
3800 "Empty", // SbxEMPTY
3802 "Integer", // SbxINTEGER
3804 "Single", // SbxSINGLE
3805 "Double", // SbxDOUBLE
3806 "Currency", // SbxCURRENCY
3808 "String", // SbxSTRING
3809 "Object", // SbxOBJECT
3810 "Error", // SbxERROR
3811 "Boolean", // SbxBOOL
3812 "Variant", // SbxVARIANT
3813 "DataObject", // SbxDATAOBJECT
3818 "UShort", // SbxUSHORT
3819 "ULong", // SbxULONG
3820 "Long64", // SbxLONG64
3821 "ULong64", // SbxULONG64
3825 "HResult", // SbxHRESULT
3826 "Pointer", // SbxPOINTER
3827 "DimArray", // SbxDIMARRAY
3828 "CArray", // SbxCARRAY
3829 "Userdef", // SbxUSERDEF
3830 "Lpstr", // SbxLPSTR
3831 "Lpwstr", // SbxLPWSTR
3832 "Unknown Type", // SbxCoreSTRING
3833 "WString", // SbxWSTRING
3834 "WChar", // SbxWCHAR
3835 "Int64", // SbxSALINT64
3836 "UInt64", // SbxSALUINT64
3837 "Decimal", // SbxDECIMAL
3840 int nPos
= ((int)eType
) & 0x0FFF;
3841 sal_uInt16 nTypeNameCount
= sizeof( pTypeNames
) / sizeof( char* );
3842 if ( nPos
< 0 || nPos
>= nTypeNameCount
)
3844 nPos
= nTypeNameCount
- 1;
3846 return OUString::createFromAscii(pTypeNames
[nPos
]);
3849 OUString
getObjectTypeName( SbxVariable
* pVar
)
3851 OUString
sRet( "Object" );
3854 SbxBase
* pObj
= pVar
->GetObject();
3861 SbUnoObject
* pUnoObj
= PTR_CAST(SbUnoObject
,pVar
);
3864 if ( SbxBase
* pBaseObj
= pVar
->GetObject() )
3866 pUnoObj
= PTR_CAST(SbUnoObject
, pBaseObj
);
3871 Any aObj
= pUnoObj
->getUnoAny();
3872 // For upstreaming unless we start to build oovbaapi by default
3873 // we need to get detect the vba-ness of the object in some
3875 // note: Automation objects do not support XServiceInfo
3876 uno::Reference
< XServiceInfo
> xServInfo( aObj
, uno::UNO_QUERY
);
3877 if ( xServInfo
.is() )
3879 // is this a VBA object ?
3880 uno::Reference
< ooo::vba::XHelperInterface
> xVBA( aObj
, uno::UNO_QUERY
);
3881 Sequence
< OUString
> sServices
= xServInfo
->getSupportedServiceNames();
3882 if ( sServices
.getLength() )
3884 sRet
= sServices
[ 0 ];
3889 uno::Reference
< bridge::oleautomation::XAutomationObject
> xAutoMation( aObj
, uno::UNO_QUERY
);
3890 if ( xAutoMation
.is() )
3892 uno::Reference
< script::XInvocation
> xInv( aObj
, uno::UNO_QUERY
);
3897 xInv
->getValue( OUString( "$GetTypeName" ) ) >>= sRet
;
3899 catch(const Exception
& )
3905 sal_Int32 nDot
= sRet
.lastIndexOf( '.' );
3906 if ( nDot
!= -1 && nDot
< sRet
.getLength() )
3908 sRet
= sRet
.copy( nDot
+ 1 );
3921 if ( rPar
.Count() != 2 )
3923 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3927 SbxDataType eType
= rPar
.Get(1)->GetType();
3928 bool bIsArray
= ( ( eType
& SbxARRAY
) != 0 );
3931 if ( SbiRuntime::isVBAEnabled() && eType
== SbxOBJECT
)
3933 aRetStr
= getObjectTypeName( rPar
.Get(1) );
3937 aRetStr
= getBasicTypeName( eType
);
3943 rPar
.Get(0)->PutString( aRetStr
);
3952 if ( rPar
.Count() != 2 )
3954 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3958 const OUString
& rStr
= rPar
.Get(1)->GetOUString();
3959 rPar
.Get(0)->PutLong( rStr
.getLength() );
3963 RTLFUNC(DDEInitiate
)
3968 // No DDE for "virtual" portal users
3969 if( needSecurityRestrictions() )
3971 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
3975 int nArgs
= (int)rPar
.Count();
3978 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
3981 const OUString
& rApp
= rPar
.Get(1)->GetOUString();
3982 const OUString
& rTopic
= rPar
.Get(2)->GetOUString();
3984 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
3986 SbError nDdeErr
= pDDE
->Initiate( rApp
, rTopic
, nChannel
);
3989 StarBASIC::Error( nDdeErr
);
3993 rPar
.Get(0)->PutInteger( (int)nChannel
);
3997 RTLFUNC(DDETerminate
)
4002 // No DDE for "virtual" portal users
4003 if( needSecurityRestrictions() )
4005 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4009 rPar
.Get(0)->PutEmpty();
4010 int nArgs
= (int)rPar
.Count();
4013 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4016 size_t nChannel
= rPar
.Get(1)->GetInteger();
4017 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4018 SbError nDdeErr
= pDDE
->Terminate( nChannel
);
4021 StarBASIC::Error( nDdeErr
);
4025 RTLFUNC(DDETerminateAll
)
4030 // No DDE for "virtual" portal users
4031 if( needSecurityRestrictions() )
4033 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4037 rPar
.Get(0)->PutEmpty();
4038 int nArgs
= (int)rPar
.Count();
4041 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4045 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4046 SbError nDdeErr
= pDDE
->TerminateAll();
4049 StarBASIC::Error( nDdeErr
);
4058 // No DDE for "virtual" portal users
4059 if( needSecurityRestrictions() )
4061 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4065 int nArgs
= (int)rPar
.Count();
4068 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4071 size_t nChannel
= rPar
.Get(1)->GetInteger();
4072 const OUString
& rItem
= rPar
.Get(2)->GetOUString();
4073 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4075 SbError nDdeErr
= pDDE
->Request( nChannel
, rItem
, aResult
);
4078 StarBASIC::Error( nDdeErr
);
4082 rPar
.Get(0)->PutString( aResult
);
4091 // No DDE for "virtual" portal users
4092 if( needSecurityRestrictions() )
4094 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4098 rPar
.Get(0)->PutEmpty();
4099 int nArgs
= (int)rPar
.Count();
4102 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4105 size_t nChannel
= rPar
.Get(1)->GetInteger();
4106 const OUString
& rCommand
= rPar
.Get(2)->GetOUString();
4107 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4108 SbError nDdeErr
= pDDE
->Execute( nChannel
, rCommand
);
4111 StarBASIC::Error( nDdeErr
);
4120 // No DDE for "virtual" portal users
4121 if( needSecurityRestrictions() )
4123 StarBASIC::Error(SbERR_NOT_IMPLEMENTED
);
4127 rPar
.Get(0)->PutEmpty();
4128 int nArgs
= (int)rPar
.Count();
4131 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4134 size_t nChannel
= rPar
.Get(1)->GetInteger();
4135 const OUString
& rItem
= rPar
.Get(2)->GetOUString();
4136 const OUString
& rData
= rPar
.Get(3)->GetOUString();
4137 SbiDdeControl
* pDDE
= GetSbData()->pInst
->GetDdeControl();
4138 SbError nDdeErr
= pDDE
->Poke( nChannel
, rItem
, rData
);
4141 StarBASIC::Error( nDdeErr
);
4151 if ( rPar
.Count() != 1 )
4153 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4156 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
4158 while( nChannel
< CHANNELS
)
4160 SbiStream
* pStrm
= pIO
->GetStream( nChannel
);
4163 rPar
.Get(0)->PutInteger( nChannel
);
4168 StarBASIC::Error( SbERR_TOO_MANY_FILES
);
4176 sal_uInt16 nParCount
= rPar
.Count();
4177 if ( nParCount
!= 3 && nParCount
!= 2 )
4179 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4182 SbxBase
* pParObj
= rPar
.Get(1)->GetObject();
4183 SbxDimArray
* pArr
= PTR_CAST(SbxDimArray
,pParObj
);
4186 sal_Int32 nLower
, nUpper
;
4187 short nDim
= (nParCount
== 3) ? (short)rPar
.Get(2)->GetInteger() : 1;
4188 if( !pArr
->GetDim32( nDim
, nLower
, nUpper
) )
4189 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
4191 rPar
.Get(0)->PutLong( nLower
);
4194 StarBASIC::Error( SbERR_MUST_HAVE_DIMS
);
4202 sal_uInt16 nParCount
= rPar
.Count();
4203 if ( nParCount
!= 3 && nParCount
!= 2 )
4205 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4209 SbxBase
* pParObj
= rPar
.Get(1)->GetObject();
4210 SbxDimArray
* pArr
= PTR_CAST(SbxDimArray
,pParObj
);
4213 sal_Int32 nLower
, nUpper
;
4214 short nDim
= (nParCount
== 3) ? (short)rPar
.Get(2)->GetInteger() : 1;
4215 if( !pArr
->GetDim32( nDim
, nLower
, nUpper
) )
4216 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
4218 rPar
.Get(0)->PutLong( nUpper
);
4221 StarBASIC::Error( SbERR_MUST_HAVE_DIMS
);
4229 if ( rPar
.Count() != 4 )
4231 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4235 sal_Int32 nRed
= rPar
.Get(1)->GetInteger() & 0xFF;
4236 sal_Int32 nGreen
= rPar
.Get(2)->GetInteger() & 0xFF;
4237 sal_Int32 nBlue
= rPar
.Get(3)->GetInteger() & 0xFF;
4240 SbiInstance
* pInst
= GetSbData()->pInst
;
4241 bool bCompatibility
= ( pInst
&& pInst
->IsCompatibility() );
4242 if( bCompatibility
)
4244 nRGB
= (nBlue
<< 16) | (nGreen
<< 8) | nRed
;
4248 nRGB
= (nRed
<< 16) | (nGreen
<< 8) | nBlue
;
4250 rPar
.Get(0)->PutLong( nRGB
);
4258 static const sal_Int32 pRGB
[] =
4278 if ( rPar
.Count() != 2 )
4280 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4284 sal_Int16 nCol
= rPar
.Get(1)->GetInteger();
4285 if( nCol
< 0 || nCol
> 15 )
4287 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4290 sal_Int32 nRGB
= pRGB
[ nCol
];
4291 rPar
.Get(0)->PutLong( nRGB
);
4294 // StrConv(string, conversion, LCID)
4300 sal_Size nArgCount
= rPar
.Count()-1;
4301 if( nArgCount
< 2 || nArgCount
> 3 )
4303 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4307 OUString aOldStr
= rPar
.Get(1)->GetOUString();
4308 sal_Int32 nConversion
= rPar
.Get(2)->GetLong();
4310 sal_uInt16 nLanguage
= LANGUAGE_SYSTEM
;
4312 sal_Int32 nOldLen
= aOldStr
.getLength();
4315 // null string,return
4316 rPar
.Get(0)->PutString(aOldStr
);
4320 sal_Int32 nType
= 0;
4321 if ( (nConversion
& 0x03) == 3 ) // vbProperCase
4323 const CharClass
& rCharClass
= GetCharClass();
4324 aOldStr
= rCharClass
.titlecase( aOldStr
.toAsciiLowerCase(), 0, nOldLen
);
4326 else if ( (nConversion
& 0x01) == 1 ) // vbUpperCase
4328 nType
|= i18n::TransliterationModules_LOWERCASE_UPPERCASE
;
4330 else if ( (nConversion
& 0x02) == 2 ) // vbLowerCase
4332 nType
|= i18n::TransliterationModules_UPPERCASE_LOWERCASE
;
4334 if ( (nConversion
& 0x04) == 4 ) // vbWide
4336 nType
|= i18n::TransliterationModules_HALFWIDTH_FULLWIDTH
;
4338 else if ( (nConversion
& 0x08) == 8 ) // vbNarrow
4340 nType
|= i18n::TransliterationModules_FULLWIDTH_HALFWIDTH
;
4342 if ( (nConversion
& 0x10) == 16) // vbKatakana
4344 nType
|= i18n::TransliterationModules_HIRAGANA_KATAKANA
;
4346 else if ( (nConversion
& 0x20) == 32 ) // vbHiragana
4348 nType
|= i18n::TransliterationModules_KATAKANA_HIRAGANA
;
4350 OUString
aNewStr( aOldStr
);
4353 uno::Reference
< uno::XComponentContext
> xContext
= getProcessComponentContext();
4354 ::utl::TransliterationWrapper
aTransliterationWrapper( xContext
, nType
);
4355 uno::Sequence
<sal_Int32
> aOffsets
;
4356 aTransliterationWrapper
.loadModuleIfNeeded( nLanguage
);
4357 aNewStr
= aTransliterationWrapper
.transliterate( aOldStr
, nLanguage
, 0, nOldLen
, &aOffsets
);
4360 if ( (nConversion
& 0x40) == 64 ) // vbUnicode
4362 // convert the string to byte string, preserving unicode (2 bytes per character)
4363 sal_Int32 nSize
= aNewStr
.getLength()*2;
4364 const sal_Unicode
* pSrc
= aNewStr
.getStr();
4365 sal_Char
* pChar
= new sal_Char
[nSize
+1];
4366 for( sal_Int32 i
=0; i
< nSize
; i
++ )
4368 pChar
[i
] = static_cast< sal_Char
>( (i
%2) ? ((*pSrc
) >> 8) & 0xff : (*pSrc
) & 0xff );
4374 pChar
[nSize
] = '\0';
4375 OString
aOStr(pChar
);
4378 // there is no concept about default codepage in unix. so it is incorrectly in unix
4379 OUString aOUStr
= OStringToOUString(aOStr
, osl_getThreadTextEncoding());
4380 rPar
.Get(0)->PutString( aOUStr
);
4383 else if ( (nConversion
& 0x80) == 128 ) // vbFromUnicode
4385 // there is no concept about default codepage in unix. so it is incorrectly in unix
4386 OString aOStr
= OUStringToOString(aNewStr
,osl_getThreadTextEncoding());
4387 const sal_Char
* pChar
= aOStr
.getStr();
4388 sal_Int32 nArraySize
= aOStr
.getLength();
4389 SbxDimArray
* pArray
= new SbxDimArray(SbxBYTE
);
4390 bool bIncIndex
= (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
4395 pArray
->AddDim( 1, nArraySize
);
4399 pArray
->AddDim( 0, nArraySize
-1 );
4404 pArray
->unoAddDim( 0, -1 );
4407 for( sal_Int32 i
=0; i
< nArraySize
; i
++)
4409 SbxVariable
* pNew
= new SbxVariable( SbxBYTE
);
4410 pNew
->PutByte(*pChar
);
4412 pNew
->SetFlag( SBX_WRITE
);
4418 // coverity[callee_ptr_arith]
4419 pArray
->Put( pNew
, &index
);
4422 SbxVariableRef refVar
= rPar
.Get(0);
4423 SbxFlagBits nFlags
= refVar
->GetFlags();
4424 refVar
->ResetFlag( SBX_FIXED
);
4425 refVar
->PutObject( pArray
);
4426 refVar
->SetFlags( nFlags
);
4427 refVar
->SetParameters( NULL
);
4430 rPar
.Get(0)->PutString(aNewStr
);
4439 if ( rPar
.Count() != 1 )
4441 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4452 if( rPar
.Count() != 2 )
4454 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4459 SbxBase
* pObj
= static_cast<SbxObject
*>(rPar
.Get(1)->GetObject());
4462 if( pObj
->IsA( TYPE( SbUserFormModule
) ) )
4464 static_cast<SbUserFormModule
*>(pObj
)->Load();
4466 else if( pObj
->IsA( TYPE( SbxObject
) ) )
4468 SbxVariable
* pVar
= static_cast<SbxObject
*>(pObj
)->Find( OUString("Load"), SbxCLASS_METHOD
);
4482 rPar
.Get(0)->PutEmpty();
4483 if( rPar
.Count() != 2 )
4485 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4490 SbxBase
* pObj
= static_cast<SbxObject
*>(rPar
.Get(1)->GetObject());
4493 if( pObj
->IsA( TYPE( SbUserFormModule
) ) )
4495 SbUserFormModule
* pFormModule
= static_cast<SbUserFormModule
*>(pObj
);
4496 pFormModule
->Unload();
4498 else if( pObj
->IsA( TYPE( SbxObject
) ) )
4500 SbxVariable
* pVar
= static_cast<SbxObject
*>(pObj
)->Find( OUString("Unload"), SbxCLASS_METHOD
);
4509 RTLFUNC(LoadPicture
)
4514 if( rPar
.Count() != 2 )
4516 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4520 OUString aFileURL
= getFullPath( rPar
.Get(1)->GetOUString() );
4521 boost::scoped_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream( aFileURL
, StreamMode::READ
));
4525 ReadDIB(aBmp
, *pStream
, true);
4526 Graphic
aGraphic(aBmp
);
4528 SbxObjectRef xRef
= new SbStdPicture
;
4529 static_cast<SbStdPicture
*>((SbxObject
*)xRef
)->SetGraphic( aGraphic
);
4530 rPar
.Get(0)->PutObject( xRef
);
4534 RTLFUNC(SavePicture
)
4539 rPar
.Get(0)->PutEmpty();
4540 if( rPar
.Count() != 3 )
4542 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4546 SbxBase
* pObj
= static_cast<SbxObject
*>(rPar
.Get(1)->GetObject());
4547 if( pObj
->IsA( TYPE( SbStdPicture
) ) )
4549 SvFileStream
aOStream( rPar
.Get(2)->GetOUString(), StreamMode::WRITE
| StreamMode::TRUNC
);
4550 Graphic aGraphic
= static_cast<SbStdPicture
*>(pObj
)->GetGraphic();
4551 WriteGraphic( aOStream
, aGraphic
);
4563 static const WinBits nStyleMap
[] =
4566 WB_OK_CANCEL
, // MB_OKCANCEL
4567 WB_ABORT_RETRY_IGNORE
, // MB_ABORTRETRYIGNORE
4568 WB_YES_NO_CANCEL
, // MB_YESNOCANCEL
4569 WB_YES_NO
, // MB_YESNO
4570 WB_RETRY_CANCEL
// MB_RETRYCANCEL
4572 static const sal_Int16 nButtonMap
[] =
4574 2, // RET_CANCEL is 0
4582 sal_uInt16 nArgCount
= (sal_uInt16
)rPar
.Count();
4583 if( nArgCount
< 2 || nArgCount
> 6 )
4585 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4589 WinBits nType
= 0; // MB_OK
4590 if( nArgCount
>= 3 )
4591 nType
= (WinBits
)rPar
.Get(2)->GetInteger();
4592 WinBits nStyle
= nType
;
4593 nStyle
&= 15; // delete bits 4-16
4598 nWinBits
= nStyleMap
[ nStyle
];
4600 WinBits nWinDefBits
;
4601 nWinDefBits
= (WB_DEF_OK
| WB_DEF_RETRY
| WB_DEF_YES
);
4606 nWinDefBits
= WB_DEF_CANCEL
;
4608 else if( nStyle
== 2 )
4610 nWinDefBits
= WB_DEF_RETRY
;
4614 nWinDefBits
= (WB_DEF_CANCEL
| WB_DEF_RETRY
| WB_DEF_NO
);
4617 else if( nType
& 512 )
4621 nWinDefBits
= WB_DEF_IGNORE
;
4625 nWinDefBits
= WB_DEF_CANCEL
;
4628 else if( nStyle
== 2)
4630 nWinDefBits
= WB_DEF_CANCEL
;
4632 nWinBits
|= nWinDefBits
;
4634 OUString aMsg
= rPar
.Get(1)->GetOUString();
4636 if( nArgCount
>= 4 )
4638 aTitle
= rPar
.Get(3)->GetOUString();
4642 aTitle
= Application::GetAppName();
4645 nType
&= (16+32+64);
4646 VclPtr
<MessBox
> pBox
;
4648 SolarMutexGuard aSolarGuard
;
4650 vcl::Window
* pParent
= Application::GetDefDialogParent();
4654 pBox
.reset(VclPtr
<ErrorBox
>::Create( pParent
, nWinBits
, aMsg
));
4657 pBox
.reset(VclPtr
<QueryBox
>::Create( pParent
, nWinBits
, aMsg
));
4660 pBox
.reset(VclPtr
<WarningBox
>::Create( pParent
, nWinBits
, aMsg
));
4663 pBox
.reset(VclPtr
<InfoBox
>::Create( pParent
, nWinBits
, aMsg
));
4666 pBox
.reset(VclPtr
<MessBox
>::Create( pParent
, nWinBits
, aTitle
, aMsg
));
4668 pBox
->SetText( aTitle
);
4669 short nRet
= pBox
->Execute();
4670 sal_Int16 nMappedRet
;
4674 if( nMappedRet
== 0 )
4676 nMappedRet
= 3; // Abort
4681 nMappedRet
= nButtonMap
[ nRet
];
4683 rPar
.Get(0)->PutInteger( nMappedRet
);
4684 pBox
.disposeAndClear();
4692 rPar
.Get(0)->PutEmpty();
4693 if ( rPar
.Count() == 3 )
4695 OUString aStr
= rPar
.Get(1)->GetOUString();
4696 sal_Int16 nFlags
= rPar
.Get(2)->GetInteger();
4700 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
4705 bool bReadOnly
= (nFlags
& Sb_ATTR_READONLY
) != 0;
4706 xSFI
->setReadOnly( aStr
, bReadOnly
);
4707 bool bHidden
= (nFlags
& Sb_ATTR_HIDDEN
) != 0;
4708 xSFI
->setHidden( aStr
, bHidden
);
4710 catch(const Exception
& )
4712 StarBASIC::Error( ERRCODE_IO_GENERAL
);
4719 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4729 SbiIoSystem
* pIO
= GetSbData()->pInst
->GetIoSystem();
4736 RTLFUNC(DumpAllObjects
)
4741 sal_uInt16 nArgCount
= (sal_uInt16
)rPar
.Count();
4742 if( nArgCount
< 2 || nArgCount
> 3 )
4744 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4748 StarBASIC::Error( SbERR_INTERNAL_ERROR
);
4752 SbxObject
* p
= pBasic
;
4753 while( p
->GetParent() )
4757 SvFileStream
aStrm( rPar
.Get( 1 )->GetOUString(),
4758 StreamMode::WRITE
| StreamMode::TRUNC
);
4759 p
->Dump( aStrm
, rPar
.Get( 2 )->GetBool() );
4761 if( aStrm
.GetError() != SVSTREAM_OK
)
4763 StarBASIC::Error( SbERR_IO_ERROR
);
4774 if ( rPar
.Count() == 2 )
4776 OUString aStr
= rPar
.Get(1)->GetOUString();
4777 bool bExists
= false;
4781 uno::Reference
< ucb::XSimpleFileAccess3
> xSFI
= getFileAccess();
4786 bExists
= xSFI
->exists( aStr
);
4788 catch(const Exception
& )
4790 StarBASIC::Error( ERRCODE_IO_GENERAL
);
4796 DirectoryItem aItem
;
4797 FileBase::RC nRet
= DirectoryItem::get( getFullPath( aStr
), aItem
);
4798 bExists
= (nRet
== FileBase::E_None
);
4800 rPar
.Get(0)->PutBool( bExists
);
4804 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4813 if ( rPar
.Count() != 5 )
4815 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4819 sal_Int32 nNumber
= rPar
.Get(1)->GetLong();
4820 sal_Int32 nStart
= rPar
.Get(2)->GetLong();
4821 sal_Int32 nStop
= rPar
.Get(3)->GetLong();
4822 sal_Int32 nInterval
= rPar
.Get(4)->GetLong();
4824 if( nStart
< 0 || nStop
<= nStart
|| nInterval
< 1 )
4826 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4830 // the Partition function inserts leading spaces before lowervalue and uppervalue
4831 // so that they both have the same number of characters as the string
4832 // representation of the value (Stop + 1). This ensures that if you use the output
4833 // of the Partition function with several values of Number, the resulting text
4834 // will be handled properly during any subsequent sort operation.
4836 // calculate the maximun number of characters before lowervalue and uppervalue
4837 OUString aBeforeStart
= OUString::number( nStart
- 1 );
4838 OUString aAfterStop
= OUString::number( nStop
+ 1 );
4839 sal_Int32 nLen1
= aBeforeStart
.getLength();
4840 sal_Int32 nLen2
= aAfterStop
.getLength();
4841 sal_Int32 nLen
= nLen1
>= nLen2
? nLen1
:nLen2
;
4843 OUStringBuffer
aRetStr( nLen
* 2 + 1);
4844 OUString aLowerValue
;
4845 OUString aUpperValue
;
4846 if( nNumber
< nStart
)
4848 aUpperValue
= aBeforeStart
;
4850 else if( nNumber
> nStop
)
4852 aLowerValue
= aAfterStop
;
4856 sal_Int32 nLowerValue
= nNumber
;
4857 sal_Int32 nUpperValue
= nLowerValue
;
4860 nLowerValue
= ((( nNumber
- nStart
) / nInterval
) * nInterval
) + nStart
;
4861 nUpperValue
= nLowerValue
+ nInterval
- 1;
4863 aLowerValue
= OUString::number( nLowerValue
);
4864 aUpperValue
= OUString::number( nUpperValue
);
4867 nLen1
= aLowerValue
.getLength();
4868 nLen2
= aUpperValue
.getLength();
4872 // appending the leading spaces for the lowervalue
4873 for ( sal_Int32 i
= (nLen
- nLen1
) ; i
> 0; --i
)
4875 aRetStr
.appendAscii(" ");
4878 aRetStr
.append( aLowerValue
).appendAscii(":");
4881 // appending the leading spaces for the uppervalue
4882 for ( sal_Int32 i
= (nLen
- nLen2
) ; i
> 0; --i
)
4884 aRetStr
.appendAscii(" ");
4887 aRetStr
.append( aUpperValue
);
4888 rPar
.Get(0)->PutString( aRetStr
.makeStringAndClear());
4893 static long GetDayDiff( const Date
& rDate
)
4895 Date
aRefDate( 1,1,1900 );
4897 if ( aRefDate
> rDate
)
4899 nDiffDays
= (long)(aRefDate
- rDate
);
4904 nDiffDays
= (long)(rDate
- aRefDate
);
4906 nDiffDays
+= 2; // adjustment VisualBasic: 1.Jan.1900 == 2
4910 sal_Int16
implGetDateYear( double aDate
)
4912 Date
aRefDate( 1,1,1900 );
4913 long nDays
= (long) aDate
;
4914 nDays
-= 2; // standardize: 1.1.1900 => 0.0
4916 sal_Int16 nRet
= (sal_Int16
)( aRefDate
.GetYear() );
4920 bool implDateSerial( sal_Int16 nYear
, sal_Int16 nMonth
, sal_Int16 nDay
, double& rdRet
)
4922 #if HAVE_FEATURE_SCRIPTING
4923 if ( nYear
< 30 && SbiRuntime::isVBAEnabled() )
4935 Date
aCurDate( nDay
, nMonth
, nYear
);
4936 if ((nYear
< 100 || nYear
> 9999) )
4938 #if HAVE_FEATURE_SCRIPTING
4939 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4944 #if HAVE_FEATURE_SCRIPTING
4945 if ( !SbiRuntime::isVBAEnabled() )
4948 if ( (nMonth
< 1 || nMonth
> 12 )||
4949 (nDay
< 1 || nDay
> 31 ) )
4951 #if HAVE_FEATURE_SCRIPTING
4952 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
4957 #if HAVE_FEATURE_SCRIPTING
4960 // grab the year & month
4961 aCurDate
= Date( 1, (( nMonth
% 12 ) > 0 ) ? ( nMonth
% 12 ) : 12 + ( nMonth
% 12 ), nYear
);
4963 // adjust year based on month value
4964 // e.g. 2000, 0, xx = 1999, 12, xx ( or December of the previous year )
4965 // 2000, 13, xx = 2001, 1, xx ( or January of the following year )
4966 if( ( nMonth
< 1 ) || ( nMonth
> 12 ) )
4968 // inacurrate around leap year, don't use days to calculate,
4969 // just modify the months directory
4970 sal_Int16 nYearAdj
= ( nMonth
/12 ); // default to positive months inputed
4973 nYearAdj
= ( ( nMonth
-12 ) / 12 );
4975 aCurDate
.SetYear( aCurDate
.GetYear() + nYearAdj
);
4978 // adjust day value,
4979 // e.g. 2000, 2, 0 = 2000, 1, 31 or the last day of the previous month
4980 // 2000, 1, 32 = 2000, 2, 1 or the first day of the following month
4981 if( ( nDay
< 1 ) || ( nDay
> aCurDate
.GetDaysInMonth() ) )
4983 aCurDate
+= nDay
- 1;
4987 aCurDate
.SetDay( nDay
);
4992 long nDiffDays
= GetDayDiff( aCurDate
);
4993 rdRet
= (double)nDiffDays
;
4997 double implTimeSerial( sal_Int16 nHours
, sal_Int16 nMinutes
, sal_Int16 nSeconds
)
5000 static_cast<double>( nHours
* ::tools::Time::secondPerHour
+
5001 nMinutes
* ::tools::Time::secondPerMinute
+
5004 static_cast<double>( ::tools::Time::secondPerDay
);
5007 bool implDateTimeSerial( sal_Int16 nYear
, sal_Int16 nMonth
, sal_Int16 nDay
,
5008 sal_Int16 nHour
, sal_Int16 nMinute
, sal_Int16 nSecond
,
5012 if(!implDateSerial(nYear
, nMonth
, nDay
, dDate
))
5014 rdRet
+= dDate
+ implTimeSerial(nHour
, nMinute
, nSecond
);
5018 sal_Int16
implGetMinute( double dDate
)
5024 double nFrac
= dDate
- floor( dDate
);
5026 sal_Int32 nSeconds
= (sal_Int32
)(nFrac
+ 0.5);
5027 sal_Int16 nTemp
= (sal_Int16
)(nSeconds
% 3600);
5028 sal_Int16 nMin
= nTemp
/ 60;
5032 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */