xref: /trunk/main/basic/source/runtime/methods.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 
32 #include <tools/date.hxx>
33 #include <basic/sbxvar.hxx>
34 #ifndef _VOS_PROCESS_HXX
35 #include <vos/process.hxx>
36 #endif
37 #include <vcl/svapp.hxx>
38 #include <vcl/settings.hxx>
39 #include <vcl/sound.hxx>
40 #include <tools/wintypes.hxx>
41 #include <vcl/msgbox.hxx>
42 #include <basic/sbx.hxx>
43 #include <svl/zforlist.hxx>
44 #include <rtl/math.hxx>
45 #include <tools/urlobj.hxx>
46 #include <osl/time.h>
47 #include <unotools/charclass.hxx>
48 #include <unotools/ucbstreamhelper.hxx>
49 #include <tools/wldcrd.hxx>
50 #include <i18npool/lang.h>
51 
52 #include "runtime.hxx"
53 #include "sbunoobj.hxx"
54 #ifdef WNT
55 #include <tools/prewin.h>
56 #include "winbase.h"
57 #include <tools/postwin.h>
58 #ifndef _FSYS_HXX //autogen
59 #include <tools/fsys.hxx>
60 #endif
61 #else
62 #include <osl/file.hxx>
63 #endif
64 #include "errobject.hxx"
65 
66 #ifdef _USE_UNO
67 #include <comphelper/processfactory.hxx>
68 
69 #include <com/sun/star/uno/Sequence.hxx>
70 #include <com/sun/star/util/DateTime.hpp>
71 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
72 #include <com/sun/star/lang/Locale.hpp>
73 #include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
74 #include <com/sun/star/io/XInputStream.hpp>
75 #include <com/sun/star/io/XOutputStream.hpp>
76 #include <com/sun/star/io/XStream.hpp>
77 #include <com/sun/star/io/XSeekable.hpp>
78 
79 using namespace comphelper;
80 using namespace osl;
81 using namespace com::sun::star::uno;
82 using namespace com::sun::star::lang;
83 using namespace com::sun::star::ucb;
84 using namespace com::sun::star::io;
85 using namespace com::sun::star::frame;
86 
87 #endif /* _USE_UNO */
88 
89 //#define _ENABLE_CUR_DIR
90 
91 #include "stdobj.hxx"
92 #include <basic/sbstdobj.hxx>
93 #include "rtlproto.hxx"
94 #include "basrid.hxx"
95 #include "image.hxx"
96 #include "sb.hrc"
97 #include "iosys.hxx"
98 #include "ddectrl.hxx"
99 #include <sbintern.hxx>
100 #include <basic/vbahelper.hxx>
101 
102 #include <list>
103 #include <math.h>
104 #include <stdio.h>
105 #include <stdlib.h>
106 #include <ctype.h>
107 
108 #if defined (WNT) || defined (OS2)
109 #include <direct.h>   // _getdcwd get current work directory, _chdrive
110 #endif
111 
112 #ifdef UNX
113 #include <errno.h>
114 #include <unistd.h>
115 #endif
116 
117 #ifdef WNT
118 #include <io.h>
119 #endif
120 
121 #include <basic/sbobjmod.hxx>
122 
123 // from source/classes/sbxmod.cxx
124 Reference< XModel > getDocumentModel( StarBASIC* );
125 
126 static void FilterWhiteSpace( String& rStr )
127 {
128 	rStr.EraseAllChars( ' ' );
129 	rStr.EraseAllChars( '\t' );
130 	rStr.EraseAllChars( '\n' );
131 	rStr.EraseAllChars( '\r' );
132 }
133 
134 static long GetDayDiff( const Date& rDate )
135 {
136 	Date aRefDate( 1,1,1900 );
137 	long nDiffDays;
138 	if ( aRefDate > rDate )
139 	{
140 		nDiffDays = (long)(aRefDate - rDate);
141 		nDiffDays *= -1;
142 	}
143 	else
144 		nDiffDays = (long)(rDate - aRefDate);
145 	nDiffDays += 2; // Anpassung VisualBasic: 1.Jan.1900 == 2
146 	return nDiffDays;
147 }
148 
149 static CharClass& GetCharClass( void )
150 {
151 	static sal_Bool bNeedsInit = sal_True;
152 	static ::com::sun::star::lang::Locale aLocale;
153 	if( bNeedsInit )
154 	{
155         bNeedsInit = sal_False;
156 		aLocale = Application::GetSettings().GetLocale();
157 	}
158 	static CharClass aCharClass( aLocale );
159 	return aCharClass;
160 }
161 
162 static inline sal_Bool isFolder( FileStatus::Type aType )
163 {
164     return ( aType == FileStatus::Directory || aType == FileStatus::Volume );
165 }
166 
167 
168 //*** UCB file access ***
169 
170 // Converts possibly relative paths to absolute paths
171 // according to the setting done by ChDir/ChDrive
172 String getFullPath( const String& aRelPath )
173 {
174 	::rtl::OUString aFileURL;
175 
176 	// #80204 Try first if it already is a valid URL
177 	INetURLObject aURLObj( aRelPath );
178 	aFileURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
179 
180 	if( !aFileURL.getLength() )
181 	{
182 		File::getFileURLFromSystemPath( aRelPath, aFileURL );
183 	}
184 
185     return aFileURL;
186 }
187 
188 // Sets (virtual) current path for UCB file access
189 void implChDir( const String& aDir )
190 {
191     (void)aDir;
192 	// TODO
193 }
194 
195 // Sets (virtual) current drive for UCB file access
196 void implChDrive( const String& aDrive )
197 {
198     (void)aDrive;
199 	// TODO
200 }
201 
202 // Returns (virtual) current path for UCB file access
203 String implGetCurDir( void )
204 {
205 	String aRetStr;
206 
207 	return aRetStr;
208 }
209 
210 // TODO: -> SbiGlobals
211 static com::sun::star::uno::Reference< XSimpleFileAccess3 > getFileAccess( void )
212 {
213 	static com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI;
214 	if( !xSFI.is() )
215 	{
216 		com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
217 		if( xSMgr.is() )
218 		{
219 			xSFI = com::sun::star::uno::Reference< XSimpleFileAccess3 >( xSMgr->createInstance
220 				( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY );
221 		}
222 	}
223 	return xSFI;
224 }
225 
226 
227 
228 // Properties und Methoden legen beim Get (bPut = sal_False) den Returnwert
229 // im Element 0 des Argv ab; beim Put (bPut = sal_True) wird der Wert aus
230 // Element 0 gespeichert.
231 
232 // CreateObject( class )
233 
234 RTLFUNC(CreateObject)
235 {
236     (void)bWrite;
237 
238 	String aClass( rPar.Get( 1 )->GetString() );
239 	SbxObjectRef p = SbxBase::CreateObject( aClass );
240 	if( !p )
241 		StarBASIC::Error( SbERR_CANNOT_LOAD );
242 	else
243 	{
244 		// Convenience: BASIC als Parent eintragen
245 		p->SetParent( pBasic );
246 		rPar.Get( 0 )->PutObject( p );
247 	}
248 }
249 
250 // Error( n )
251 
252 RTLFUNC(Error)
253 {
254     (void)bWrite;
255 
256 	if( !pBasic )
257 		StarBASIC::Error( SbERR_INTERNAL_ERROR );
258 	else
259 	{
260 		String aErrorMsg;
261 		SbError nErr = 0L;
262 		sal_Int32 nCode = 0;
263 		if( rPar.Count() == 1 )
264 		{
265 			nErr = StarBASIC::GetErrBasic();
266 			aErrorMsg = StarBASIC::GetErrorMsg();
267 		}
268 		else
269 		{
270 			nCode = rPar.Get( 1 )->GetLong();
271 			if( nCode > 65535L )
272 				StarBASIC::Error( SbERR_CONVERSION );
273 			else
274 				nErr = StarBASIC::GetSfxFromVBError( (sal_uInt16)nCode );
275 		}
276 
277 		bool bVBA = SbiRuntime::isVBAEnabled();
278 		String tmpErrMsg;
279 		if( bVBA && aErrorMsg.Len() > 0 )
280 		{
281 			tmpErrMsg = aErrorMsg;
282 		}
283 		else
284 		{
285 			pBasic->MakeErrorText( nErr, aErrorMsg );
286 			tmpErrMsg = pBasic->GetErrorText();
287 		}
288 		// If this rtlfunc 'Error'  passed a errcode the same as the active Err Objects's
289 		// current err then  return the description for the error message if it is set
290 		// ( complicated isn't it ? )
291 		if ( bVBA && rPar.Count() > 1 )
292 		{
293 			com::sun::star::uno::Reference< ooo::vba::XErrObject > xErrObj( SbxErrObject::getUnoErrObject() );
294 			if ( xErrObj.is() && xErrObj->getNumber() == nCode && xErrObj->getDescription().getLength() )
295 				tmpErrMsg = xErrObj->getDescription();
296 		}
297 		rPar.Get( 0 )->PutString( tmpErrMsg );
298 	}
299 }
300 
301 // Sinus
302 
303 RTLFUNC(Sin)
304 {
305     (void)pBasic;
306     (void)bWrite;
307 
308 	if ( rPar.Count() < 2 )
309 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
310 	else
311 	{
312 		SbxVariableRef pArg = rPar.Get( 1 );
313 		rPar.Get( 0 )->PutDouble( sin( pArg->GetDouble() ) );
314 	}
315 }
316 
317 // Cosinus
318 
319 RTLFUNC(Cos)
320 {
321     (void)pBasic;
322     (void)bWrite;
323 
324 	if ( rPar.Count() < 2 )
325 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
326 	else
327 	{
328 		SbxVariableRef pArg = rPar.Get( 1 );
329 		rPar.Get( 0 )->PutDouble( cos( pArg->GetDouble() ) );
330 	}
331 }
332 
333 // Atn
334 
335 RTLFUNC(Atn)
336 {
337     (void)pBasic;
338     (void)bWrite;
339 
340 	if ( rPar.Count() < 2 )
341 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
342 	else
343 	{
344 		SbxVariableRef pArg = rPar.Get( 1 );
345 		rPar.Get( 0 )->PutDouble( atan( pArg->GetDouble() ) );
346 	}
347 }
348 
349 
350 
351 RTLFUNC(Abs)
352 {
353     (void)pBasic;
354     (void)bWrite;
355 
356 	if ( rPar.Count() < 2 )
357 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
358 	else
359 	{
360 		SbxVariableRef pArg = rPar.Get( 1 );
361 		rPar.Get( 0 )->PutDouble( fabs( pArg->GetDouble() ) );
362 	}
363 }
364 
365 
366 RTLFUNC(Asc)
367 {
368     (void)pBasic;
369     (void)bWrite;
370 
371 	if ( rPar.Count() < 2 )
372 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
373 	else
374 	{
375 		SbxVariableRef pArg = rPar.Get( 1 );
376 		String aStr( pArg->GetString() );
377 		if ( aStr.Len() == 0 )
378 		{
379 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
380 			rPar.Get(0)->PutEmpty();
381 		}
382 		else
383 		{
384 			sal_Unicode aCh = aStr.GetBuffer()[0];
385 			rPar.Get(0)->PutLong( aCh );
386 		}
387 	}
388 }
389 
390 void implChr( SbxArray& rPar, bool bChrW )
391 {
392 	if ( rPar.Count() < 2 )
393 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
394 	else
395 	{
396 		SbxVariableRef pArg = rPar.Get( 1 );
397 
398 		String aStr;
399 		if( !bChrW && SbiRuntime::isVBAEnabled() )
400 		{
401 			sal_Char c = (sal_Char)pArg->GetByte();
402 			ByteString s( c );
403 			aStr = String( s, gsl_getSystemTextEncoding() );
404 		}
405 		else
406 		{
407 			sal_Unicode aCh = (sal_Unicode)pArg->GetUShort();
408 			aStr = String( aCh );
409 		}
410 		rPar.Get(0)->PutString( aStr );
411 	}
412 }
413 
414 RTLFUNC(Chr)
415 {
416     (void)pBasic;
417     (void)bWrite;
418 
419 	bool bChrW = false;
420 	implChr( rPar, bChrW );
421 }
422 
423 RTLFUNC(ChrW)
424 {
425     (void)pBasic;
426     (void)bWrite;
427 
428 	bool bChrW = true;
429 	implChr( rPar, bChrW );
430 }
431 
432 
433 #ifdef UNX
434 #define _MAX_PATH 260
435 #define _PATH_INCR 250
436 #endif
437 
438 RTLFUNC(CurDir)
439 {
440     (void)pBasic;
441     (void)bWrite;
442 
443 	// #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von
444 	// der Anpassung an virtuelle URLs nich betroffen, da bei Nutzung der
445 	// DirEntry-Funktionalitaet keine Moeglichkeit besteht, das aktuelle so
446 	// zu ermitteln, dass eine virtuelle URL geliefert werden koennte.
447 
448 //	rPar.Get(0)->PutEmpty();
449 #if defined (WNT) || defined (OS2)
450 	int nCurDir = 0;  // Current dir // JSM
451 	if ( rPar.Count() == 2 )
452 	{
453 		String aDrive = rPar.Get(1)->GetString();
454 		if ( aDrive.Len() != 1 )
455 		{
456 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
457 			return;
458 		}
459 		else
460 		{
461 			nCurDir = (int)aDrive.GetBuffer()[0];
462 			if ( !isalpha( nCurDir ) )
463 			{
464 				StarBASIC::Error( SbERR_BAD_ARGUMENT );
465 				return;
466 			}
467 			else
468 				nCurDir -= ( 'A' - 1 );
469 		}
470 	}
471 	char* pBuffer = new char[ _MAX_PATH ];
472 #ifdef OS2
473 	if( !nCurDir )
474 		nCurDir = _getdrive();
475 #endif
476 	if ( _getdcwd( nCurDir, pBuffer, _MAX_PATH ) != 0 )
477 		rPar.Get(0)->PutString( String::CreateFromAscii( pBuffer ) );
478 	else
479 		StarBASIC::Error( SbERR_NO_DEVICE );
480 	delete [] pBuffer;
481 
482 #elif defined( UNX )
483 
484 	int nSize = _PATH_INCR;
485 	char* pMem;
486 	while( sal_True )
487 	  {
488 		pMem = new char[nSize];
489 		if( !pMem )
490 		  {
491 			StarBASIC::Error( SbERR_NO_MEMORY );
492 			return;
493 		  }
494 		if( getcwd( pMem, nSize-1 ) != NULL )
495 		  {
496 			rPar.Get(0)->PutString( String::CreateFromAscii(pMem) );
497 			delete [] pMem;
498 			return;
499 		  }
500 		if( errno != ERANGE )
501 		  {
502 			StarBASIC::Error( SbERR_INTERNAL_ERROR );
503 			delete [] pMem;
504 			return;
505 		  }
506 		delete [] pMem;
507 		nSize += _PATH_INCR;
508 	  };
509 
510 #endif
511 }
512 
513 RTLFUNC(ChDir) // JSM
514 {
515     (void)bWrite;
516 
517 	rPar.Get(0)->PutEmpty();
518 	if (rPar.Count() == 2)
519 	{
520 #ifdef _ENABLE_CUR_DIR
521 		String aPath = rPar.Get(1)->GetString();
522 		sal_Bool bError = sal_False;
523 #ifdef WNT
524 		// #55997 Laut MI hilft es bei File-URLs einen DirEntry zwischenzuschalten
525 		// #40996 Harmoniert bei Verwendung der WIN32-Funktion nicht mit getdir
526 		DirEntry aEntry( aPath );
527 		ByteString aFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() );
528 		if( chdir( aFullPath.GetBuffer()) )
529 			bError = sal_True;
530 #else
531 		if (!DirEntry(aPath).SetCWD())
532 			bError = sal_True;
533 #endif
534 		if( bError )
535 			StarBASIC::Error( SbERR_PATH_NOT_FOUND );
536 #endif
537         // VBA: track current directory per document type (separately for Writer, Calc, Impress, etc.)
538         if( SbiRuntime::isVBAEnabled() )
539             ::basic::vba::registerCurrentDirectory( getDocumentModel( pBasic ), rPar.Get(1)->GetString() );
540 	}
541 	else
542 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
543 }
544 
545 RTLFUNC(ChDrive) // JSM
546 {
547     (void)pBasic;
548     (void)bWrite;
549 
550 	rPar.Get(0)->PutEmpty();
551 	if (rPar.Count() == 2)
552 	{
553 #ifdef _ENABLE_CUR_DIR
554 		// Keine Laufwerke in Unix
555 #ifndef UNX
556 		String aPar1 = rPar.Get(1)->GetString();
557 
558 #if defined (WNT) || defined (OS2)
559 		if (aPar1.Len() > 0)
560 		{
561 			int nCurDrive = (int)aPar1.GetBuffer()[0]; ;
562 			if ( !isalpha( nCurDrive ) )
563 			{
564 				StarBASIC::Error( SbERR_BAD_ARGUMENT );
565 				return;
566 			}
567 			else
568 				nCurDrive -= ( 'A' - 1 );
569 			if (_chdrive(nCurDrive))
570 				StarBASIC::Error( SbERR_NO_DEVICE );
571 		}
572 #endif
573 
574 #endif
575 		// #ifndef UNX
576 #endif
577 	}
578 	else
579 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
580 }
581 
582 
583 // Implementation of StepRENAME with UCB
584 void implStepRenameUCB( const String& aSource, const String& aDest )
585 {
586 	com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
587 	if( xSFI.is() )
588 	{
589 		try
590 		{
591 			String aSourceFullPath = getFullPath( aSource );
592 			if( !xSFI->exists( aSourceFullPath ) )
593 			{
594 				StarBASIC::Error( SbERR_FILE_NOT_FOUND );
595 				return;
596 			}
597 
598 			String aDestFullPath = getFullPath( aDest );
599 			if( xSFI->exists( aDestFullPath ) )
600 				StarBASIC::Error( SbERR_FILE_EXISTS );
601 			else
602 				xSFI->move( aSourceFullPath, aDestFullPath );
603 		}
604 		catch( Exception & )
605 		{
606 			StarBASIC::Error( SbERR_FILE_NOT_FOUND );
607 		}
608 	}
609 }
610 
611 // Implementation of StepRENAME with OSL
612 void implStepRenameOSL( const String& aSource, const String& aDest )
613 {
614 	FileBase::RC nRet = File::move( getFullPathUNC( aSource ), getFullPathUNC( aDest ) );
615 	if( nRet != FileBase::E_None )
616 	{
617 		StarBASIC::Error( SbERR_PATH_NOT_FOUND );
618 	}
619 }
620 
621 RTLFUNC(FileCopy) // JSM
622 {
623     (void)pBasic;
624     (void)bWrite;
625 
626 	rPar.Get(0)->PutEmpty();
627 	if (rPar.Count() == 3)
628 	{
629 		String aSource = rPar.Get(1)->GetString();
630 		String aDest = rPar.Get(2)->GetString();
631 		// <-- UCB
632 		if( hasUno() )
633 		{
634 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
635 			if( xSFI.is() )
636 			{
637 				try
638 				{
639 					xSFI->copy( getFullPath( aSource ), getFullPath( aDest ) );
640 				}
641 				catch( Exception & )
642 				{
643 					StarBASIC::Error( SbERR_PATH_NOT_FOUND );
644 				}
645 			}
646 		}
647 		else
648 		// --> UCB
649 		{
650 #ifdef _OLD_FILE_IMPL
651 			DirEntry aSourceDirEntry(aSource);
652 			if (aSourceDirEntry.Exists())
653 			{
654 				if (aSourceDirEntry.CopyTo(DirEntry(aDest),FSYS_ACTION_COPYFILE) != FSYS_ERR_OK)
655 					StarBASIC::Error( SbERR_PATH_NOT_FOUND );
656 			}
657 			else
658 					StarBASIC::Error( SbERR_PATH_NOT_FOUND );
659 #else
660 			FileBase::RC nRet = File::copy( getFullPathUNC( aSource ), getFullPathUNC( aDest ) );
661 			if( nRet != FileBase::E_None )
662 			{
663 				StarBASIC::Error( SbERR_PATH_NOT_FOUND );
664 			}
665 #endif
666 		}
667 	}
668 	else
669 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
670 }
671 
672 RTLFUNC(Kill) // JSM
673 {
674     (void)pBasic;
675     (void)bWrite;
676 
677 	rPar.Get(0)->PutEmpty();
678 	if (rPar.Count() == 2)
679 	{
680 		String aFileSpec = rPar.Get(1)->GetString();
681 
682 		// <-- UCB
683 		if( hasUno() )
684 		{
685 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
686 			if( xSFI.is() )
687 			{
688 			    String aFullPath = getFullPath( aFileSpec );
689 				if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) )
690 				{
691 					StarBASIC::Error( SbERR_FILE_NOT_FOUND );
692 					return;
693 				}
694 				try
695 				{
696 					xSFI->kill( aFullPath );
697 				}
698 				catch( Exception & )
699 				{
700 					StarBASIC::Error( ERRCODE_IO_GENERAL );
701 				}
702 			}
703 		}
704 		else
705 		// --> UCB
706 		{
707 #ifdef _OLD_FILE_IMPL
708 			if(DirEntry(aFileSpec).Kill() != FSYS_ERR_OK)
709 				StarBASIC::Error( SbERR_PATH_NOT_FOUND );
710 #else
711 			File::remove( getFullPathUNC( aFileSpec ) );
712 #endif
713 		}
714 	}
715 	else
716 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
717 }
718 
719 RTLFUNC(MkDir) // JSM
720 {
721     (void)pBasic;
722     (void)bWrite;
723 
724 	rPar.Get(0)->PutEmpty();
725 	if (rPar.Count() == 2)
726 	{
727 		String aPath = rPar.Get(1)->GetString();
728 
729 		// <-- UCB
730 		if( hasUno() )
731 		{
732 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
733 			if( xSFI.is() )
734 			{
735 				try
736 				{
737 					xSFI->createFolder( getFullPath( aPath ) );
738 				}
739 				catch( Exception & )
740 				{
741 					StarBASIC::Error( ERRCODE_IO_GENERAL );
742 				}
743 			}
744 		}
745 		else
746 		// --> UCB
747 		{
748 #ifdef _OLD_FILE_IMPL
749 			if (!DirEntry(aPath).MakeDir())
750 				StarBASIC::Error( SbERR_PATH_NOT_FOUND );
751 #else
752 			Directory::create( getFullPathUNC( aPath ) );
753 #endif
754 		}
755 	}
756 	else
757 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
758 }
759 
760 
761 #ifndef _OLD_FILE_IMPL
762 
763 // In OSL only empty directories can be deleted
764 // so we have to delete all files recursively
765 void implRemoveDirRecursive( const String& aDirPath )
766 {
767 	DirectoryItem aItem;
768 	FileBase::RC nRet = DirectoryItem::get( aDirPath, aItem );
769 	sal_Bool bExists = (nRet == FileBase::E_None);
770 
771 	FileStatus aFileStatus( FileStatusMask_Type );
772 	nRet = aItem.getFileStatus( aFileStatus );
773 	FileStatus::Type aType = aFileStatus.getFileType();
774 	sal_Bool bFolder = isFolder( aType );
775 
776 	if( !bExists || !bFolder )
777 	{
778 		StarBASIC::Error( SbERR_PATH_NOT_FOUND );
779 		return;
780 	}
781 
782 	Directory aDir( aDirPath );
783 	nRet = aDir.open();
784 	if( nRet != FileBase::E_None )
785 	{
786 		StarBASIC::Error( SbERR_PATH_NOT_FOUND );
787 		return;
788 	}
789 
790 	for( ;; )
791 	{
792 		DirectoryItem aItem2;
793 		nRet = aDir.getNextItem( aItem2 );
794 		if( nRet != FileBase::E_None )
795 			break;
796 
797 		// Handle flags
798         FileStatus aFileStatus2( FileStatusMask_Type | FileStatusMask_FileURL );
799 		nRet = aItem2.getFileStatus( aFileStatus2 );
800 		::rtl::OUString aPath = aFileStatus2.getFileURL();
801 
802 		// Directory?
803 		FileStatus::Type aType2 = aFileStatus2.getFileType();
804 		sal_Bool bFolder2 = isFolder( aType2 );
805 		if( bFolder2 )
806 		{
807 			implRemoveDirRecursive( aPath );
808 		}
809 		else
810 		{
811 			File::remove( aPath );
812 		}
813 	}
814 	nRet = aDir.close();
815 
816 	nRet = Directory::remove( aDirPath );
817 }
818 #endif
819 
820 
821 RTLFUNC(RmDir) // JSM
822 {
823     (void)pBasic;
824     (void)bWrite;
825 
826 	rPar.Get(0)->PutEmpty();
827 	if (rPar.Count() == 2)
828 	{
829 		String aPath = rPar.Get(1)->GetString();
830 		// <-- UCB
831 		if( hasUno() )
832 		{
833 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
834 			if( xSFI.is() )
835 			{
836 				try
837 				{
838 					if( !xSFI->isFolder( aPath ) )
839 					{
840 						StarBASIC::Error( SbERR_PATH_NOT_FOUND );
841 						return;
842 					}
843 					SbiInstance* pInst = pINST;
844 					bool bCompatibility = ( pInst && pInst->IsCompatibility() );
845 					if( bCompatibility )
846 					{
847 						Sequence< ::rtl::OUString > aContent = xSFI->getFolderContents( aPath, true );
848 						sal_Int32 nCount = aContent.getLength();
849 						if( nCount > 0 )
850 						{
851 							StarBASIC::Error( SbERR_ACCESS_ERROR );
852 							return;
853 						}
854 					}
855 
856 					xSFI->kill( getFullPath( aPath ) );
857 				}
858 				catch( Exception & )
859 				{
860 					StarBASIC::Error( ERRCODE_IO_GENERAL );
861 				}
862 			}
863 		}
864 		else
865 		// --> UCB
866 		{
867 #ifdef _OLD_FILE_IMPL
868 			DirEntry aDirEntry(aPath);
869 			if (aDirEntry.Kill() != FSYS_ERR_OK)
870 				StarBASIC::Error( SbERR_PATH_NOT_FOUND );
871 #else
872 			implRemoveDirRecursive( getFullPathUNC( aPath ) );
873 #endif
874 		}
875 	}
876 	else
877 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
878 }
879 
880 RTLFUNC(SendKeys) // JSM
881 {
882     (void)pBasic;
883     (void)bWrite;
884 
885 	rPar.Get(0)->PutEmpty();
886 	StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
887 }
888 
889 RTLFUNC(Exp)
890 {
891     (void)pBasic;
892     (void)bWrite;
893 
894 	if( rPar.Count() < 2 )
895 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
896 	else
897 	{
898 		double aDouble = rPar.Get( 1 )->GetDouble();
899 		aDouble = exp( aDouble );
900         checkArithmeticOverflow( aDouble );
901 		rPar.Get( 0 )->PutDouble( aDouble );
902 	}
903 }
904 
905 RTLFUNC(FileLen)
906 {
907     (void)pBasic;
908     (void)bWrite;
909 
910 	if ( rPar.Count() < 2 )
911 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
912 	else
913 	{
914 		SbxVariableRef pArg = rPar.Get( 1 );
915 		String aStr( pArg->GetString() );
916 		sal_Int32 nLen = 0;
917 		// <-- UCB
918 		if( hasUno() )
919 		{
920 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
921 			if( xSFI.is() )
922 			{
923 				try
924 				{
925 					nLen = xSFI->getSize( getFullPath( aStr ) );
926 				}
927 				catch( Exception & )
928 				{
929 					StarBASIC::Error( ERRCODE_IO_GENERAL );
930 				}
931 			}
932 		}
933 		else
934 		// --> UCB
935 		{
936 #ifdef _OLD_FILE_IMPL
937 			FileStat aStat = DirEntry( aStr );
938 			nLen = aStat.GetSize();
939 #else
940 			DirectoryItem aItem;
941 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem );
942 			FileStatus aFileStatus( FileStatusMask_FileSize );
943 		    nRet = aItem.getFileStatus( aFileStatus );
944 		    nLen = (sal_Int32)aFileStatus.getFileSize();
945 #endif
946 		}
947 		rPar.Get(0)->PutLong( (long)nLen );
948 	}
949 }
950 
951 
952 RTLFUNC(Hex)
953 {
954     (void)pBasic;
955     (void)bWrite;
956 
957 	if ( rPar.Count() < 2 )
958 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
959 	else
960 	{
961 		char aBuffer[16];
962 		SbxVariableRef pArg = rPar.Get( 1 );
963 		if ( pArg->IsInteger() )
964             snprintf( aBuffer, sizeof(aBuffer), "%X", pArg->GetInteger() );
965 		else
966             snprintf( aBuffer, sizeof(aBuffer), "%lX", static_cast<long unsigned int>(pArg->GetLong()) );
967 		rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) );
968 	}
969 }
970 
971 // InStr( [start],string,string,[compare] )
972 
973 RTLFUNC(InStr)
974 {
975     (void)pBasic;
976     (void)bWrite;
977 
978 	sal_uIntPtr nArgCount = rPar.Count()-1;
979 	if ( nArgCount < 2 )
980 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
981 	else
982 	{
983 		sal_uInt16 nStartPos = 1;
984 
985 		sal_uInt16 nFirstStringPos = 1;
986 		if ( nArgCount >= 3 )
987 		{
988 			sal_Int32 lStartPos = rPar.Get(1)->GetLong();
989 			if( lStartPos <= 0 || lStartPos > 0xffff )
990 			{
991 				StarBASIC::Error( SbERR_BAD_ARGUMENT );
992 				lStartPos = 1;
993 			}
994 			nStartPos = (sal_uInt16)lStartPos;
995 			nFirstStringPos++;
996 		}
997 
998 		SbiInstance* pInst = pINST;
999 		int bTextMode;
1000 		bool bCompatibility = ( pInst && pInst->IsCompatibility() );
1001 		if( bCompatibility )
1002 		{
1003 			SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
1004 			bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : sal_False;
1005 		}
1006 		else
1007 		{
1008 			bTextMode = 1;;
1009 		}
1010 		if ( nArgCount == 4 )
1011 			bTextMode = rPar.Get(4)->GetInteger();
1012 
1013 		sal_uInt16 nPos;
1014 		const String& rToken = rPar.Get(nFirstStringPos+1)->GetString();
1015 
1016 		// #97545 Always find empty string
1017 		if( !rToken.Len() )
1018 		{
1019 			nPos = nStartPos;
1020 		}
1021 		else
1022 		{
1023 			if( !bTextMode )
1024 			{
1025 				const String& rStr1 = rPar.Get(nFirstStringPos)->GetString();
1026 
1027 				nPos = rStr1.Search( rToken, nStartPos-1 );
1028 				if ( nPos == STRING_NOTFOUND )
1029 					nPos = 0;
1030 				else
1031 					nPos++;
1032 			}
1033 			else
1034 			{
1035 				String aStr1 = rPar.Get(nFirstStringPos)->GetString();
1036 				String aToken = rToken;
1037 
1038 				aStr1.ToUpperAscii();
1039 				aToken.ToUpperAscii();
1040 
1041 				nPos = aStr1.Search( aToken, nStartPos-1 );
1042 				if ( nPos == STRING_NOTFOUND )
1043 					nPos = 0;
1044 				else
1045 					nPos++;
1046 			}
1047 		}
1048 		rPar.Get(0)->PutLong( nPos );
1049 	}
1050 }
1051 
1052 
1053 // InstrRev(string1, string2[, start[, compare]])
1054 
1055 RTLFUNC(InStrRev)
1056 {
1057     (void)pBasic;
1058     (void)bWrite;
1059 
1060 	sal_uIntPtr nArgCount = rPar.Count()-1;
1061 	if ( nArgCount < 2 )
1062 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1063 	else
1064 	{
1065 		String aStr1 = rPar.Get(1)->GetString();
1066 		String aToken = rPar.Get(2)->GetString();
1067 
1068 		sal_Int32 lStartPos = -1;
1069 		if ( nArgCount >= 3 )
1070 		{
1071 			lStartPos = rPar.Get(3)->GetLong();
1072 			if( (lStartPos <= 0 && lStartPos != -1) || lStartPos > 0xffff )
1073 			{
1074 				StarBASIC::Error( SbERR_BAD_ARGUMENT );
1075 				lStartPos = -1;
1076 			}
1077 		}
1078 
1079 		SbiInstance* pInst = pINST;
1080 		int bTextMode;
1081 		bool bCompatibility = ( pInst && pInst->IsCompatibility() );
1082 		if( bCompatibility )
1083 		{
1084 			SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
1085 			bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : sal_False;
1086 		}
1087 		else
1088 		{
1089 			bTextMode = 1;;
1090 		}
1091 		if ( nArgCount == 4 )
1092 			bTextMode = rPar.Get(4)->GetInteger();
1093 
1094 		sal_uInt16 nStrLen = aStr1.Len();
1095 		sal_uInt16 nStartPos = lStartPos == -1 ? nStrLen : (sal_uInt16)lStartPos;
1096 
1097 		sal_uInt16 nPos = 0;
1098 		if( nStartPos <= nStrLen )
1099 		{
1100 			sal_uInt16 nTokenLen = aToken.Len();
1101 			if( !nTokenLen )
1102 			{
1103 				// Always find empty string
1104 				nPos = nStartPos;
1105 			}
1106 			else if( nStrLen > 0 )
1107 			{
1108 				if( !bTextMode )
1109 				{
1110 					::rtl::OUString aOUStr1 ( aStr1 );
1111 					::rtl::OUString aOUToken( aToken );
1112 				    sal_Int32 nRet = aOUStr1.lastIndexOf( aOUToken, nStartPos );
1113 					if( nRet == -1 )
1114 						nPos = 0;
1115 					else
1116 						nPos = (sal_uInt16)nRet + 1;
1117 				}
1118 				else
1119 				{
1120 					aStr1.ToUpperAscii();
1121 					aToken.ToUpperAscii();
1122 
1123 					::rtl::OUString aOUStr1 ( aStr1 );
1124 					::rtl::OUString aOUToken( aToken );
1125 				    sal_Int32 nRet = aOUStr1.lastIndexOf( aOUToken, nStartPos );
1126 
1127 					if( nRet == -1 )
1128 						nPos = 0;
1129 					else
1130 						nPos = (sal_uInt16)nRet + 1;
1131 				}
1132 			}
1133 		}
1134 		rPar.Get(0)->PutLong( nPos );
1135 	}
1136 }
1137 
1138 
1139 /*
1140 	Int( 2.8 ) 	=  2.0
1141 	Int( -2.8 ) = -3.0
1142 	Fix( 2.8 ) 	=  2.0
1143 	Fix( -2.8 ) = -2.0    <- !!
1144 */
1145 
1146 RTLFUNC(Int)
1147 {
1148     (void)pBasic;
1149     (void)bWrite;
1150 
1151 	if ( rPar.Count() < 2 )
1152 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1153 	else
1154 	{
1155 		SbxVariableRef pArg = rPar.Get( 1 );
1156 		double aDouble= pArg->GetDouble();
1157 		/*
1158 			floor( 2.8 ) =  2.0
1159 			floor( -2.8 ) = -3.0
1160 		*/
1161 		aDouble = floor( aDouble );
1162 		rPar.Get(0)->PutDouble( aDouble );
1163 	}
1164 }
1165 
1166 
1167 
1168 RTLFUNC(Fix)
1169 {
1170     (void)pBasic;
1171     (void)bWrite;
1172 
1173 	if ( rPar.Count() < 2 )
1174 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1175 	else
1176 	{
1177 		SbxVariableRef pArg = rPar.Get( 1 );
1178 		double aDouble = pArg->GetDouble();
1179 		if ( aDouble >= 0.0 )
1180 			aDouble = floor( aDouble );
1181 		else
1182 			aDouble = ceil( aDouble );
1183 		rPar.Get(0)->PutDouble( aDouble );
1184 	}
1185 }
1186 
1187 
1188 RTLFUNC(LCase)
1189 {
1190     (void)pBasic;
1191     (void)bWrite;
1192 
1193 	if ( rPar.Count() < 2 )
1194 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1195 	else
1196 	{
1197 		CharClass& rCharClass = GetCharClass();
1198 		String aStr( rPar.Get(1)->GetString() );
1199 		rCharClass.toLower( aStr );
1200 		rPar.Get(0)->PutString( aStr );
1201 	}
1202 }
1203 
1204 RTLFUNC(Left)
1205 {
1206     (void)pBasic;
1207     (void)bWrite;
1208 
1209 	if ( rPar.Count() < 3 )
1210 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1211 	else
1212 	{
1213 		String aStr( rPar.Get(1)->GetString() );
1214 		sal_Int32 lResultLen = rPar.Get(2)->GetLong();
1215 		if( lResultLen > 0xffff )
1216 		{
1217 			lResultLen = 0xffff;
1218 		}
1219 		else if( lResultLen < 0 )
1220 		{
1221 			lResultLen = 0;
1222 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1223 		}
1224 		aStr.Erase( (sal_uInt16)lResultLen );
1225 		rPar.Get(0)->PutString( aStr );
1226 	}
1227 }
1228 
1229 RTLFUNC(Log)
1230 {
1231     (void)pBasic;
1232     (void)bWrite;
1233 
1234 	if ( rPar.Count() < 2 )
1235 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1236 	else
1237 	{
1238 		double aArg = rPar.Get(1)->GetDouble();
1239 		if ( aArg > 0 )
1240         {
1241             double d = log( aArg );
1242             checkArithmeticOverflow( d );
1243 			rPar.Get( 0 )->PutDouble( d );
1244         }
1245 		else
1246 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1247 	}
1248 }
1249 
1250 RTLFUNC(LTrim)
1251 {
1252     (void)pBasic;
1253     (void)bWrite;
1254 
1255 	if ( rPar.Count() < 2 )
1256 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1257 	else
1258 	{
1259 		String aStr( rPar.Get(1)->GetString() );
1260 		aStr.EraseLeadingChars();
1261 		rPar.Get(0)->PutString( aStr );
1262 	}
1263 }
1264 
1265 
1266 // Mid( String, nStart, nLength )
1267 
1268 RTLFUNC(Mid)
1269 {
1270     (void)pBasic;
1271     (void)bWrite;
1272 
1273 	sal_uIntPtr nArgCount = rPar.Count()-1;
1274 	if ( nArgCount < 2 )
1275 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1276 	else
1277 	{
1278 		// #23178: Funktionalitaet von Mid$ als Anweisung nachbilden, indem
1279 		// als weiterer (4.) Parameter ein Ersetzungsstring aufgenommen wird.
1280 		// Anders als im Original kann in dieser Variante der 3. Parameter
1281 		// nLength nicht weggelassen werden. Ist ueber bWrite schon vorgesehen.
1282 		if( nArgCount == 4 )
1283 			bWrite = sal_True;
1284 
1285 		String aArgStr = rPar.Get(1)->GetString();
1286 		sal_uInt16 nStartPos = (sal_uInt16)(rPar.Get(2)->GetLong() );
1287 		if ( nStartPos == 0 )
1288 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1289 		else
1290 		{
1291 			nStartPos--;
1292 			sal_uInt16 nLen = 0xffff;
1293 			bool bWriteNoLenParam = false;
1294 			if ( nArgCount == 3 || bWrite )
1295 			{
1296 				sal_Int32 n = rPar.Get(3)->GetLong();
1297 				if( bWrite && n == -1 )
1298 					bWriteNoLenParam = true;
1299 				nLen = (sal_uInt16)n;
1300 			}
1301 			String aResultStr;
1302 			if ( bWrite )
1303 			{
1304 				SbiInstance* pInst = pINST;
1305 				bool bCompatibility = ( pInst && pInst->IsCompatibility() );
1306 				if( bCompatibility )
1307 				{
1308 					sal_uInt16 nArgLen = aArgStr.Len();
1309 					if( nStartPos + 1 > nArgLen )
1310 					{
1311 						StarBASIC::Error( SbERR_BAD_ARGUMENT );
1312 						return;
1313 					}
1314 
1315 					String aReplaceStr = rPar.Get(4)->GetString();
1316 					sal_uInt16 nReplaceStrLen = aReplaceStr.Len();
1317 					sal_uInt16 nReplaceLen;
1318 					if( bWriteNoLenParam )
1319 					{
1320 						nReplaceLen = nReplaceStrLen;
1321 					}
1322 					else
1323 					{
1324 						nReplaceLen = nLen;
1325 						if( nReplaceLen > nReplaceStrLen )
1326 							nReplaceLen = nReplaceStrLen;
1327 					}
1328 
1329 					sal_uInt16 nReplaceEndPos = nStartPos + nReplaceLen;
1330 					if( nReplaceEndPos > nArgLen )
1331 						nReplaceLen -= (nReplaceEndPos - nArgLen);
1332 
1333 					aResultStr = aArgStr;
1334 					sal_uInt16 nErase = nReplaceLen;
1335 					aResultStr.Erase( nStartPos, nErase );
1336 					aResultStr.Insert( aReplaceStr, 0, nReplaceLen, nStartPos );
1337 				}
1338 				else
1339 				{
1340 					aResultStr = aArgStr;
1341 					aResultStr.Erase( nStartPos, nLen );
1342 					aResultStr.Insert(rPar.Get(4)->GetString(),0,nLen,nStartPos);
1343 				}
1344 
1345 				rPar.Get(1)->PutString( aResultStr );
1346 			}
1347 			else
1348 			{
1349 				aResultStr = aArgStr.Copy( nStartPos, nLen );
1350 				rPar.Get(0)->PutString( aResultStr );
1351 			}
1352 		}
1353 	}
1354 }
1355 
1356 RTLFUNC(Oct)
1357 {
1358     (void)pBasic;
1359     (void)bWrite;
1360 
1361 	if ( rPar.Count() < 2 )
1362 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1363 	else
1364 	{
1365 		char aBuffer[16];
1366 		SbxVariableRef pArg = rPar.Get( 1 );
1367 		if ( pArg->IsInteger() )
1368             snprintf( aBuffer, sizeof(aBuffer), "%o", pArg->GetInteger() );
1369 		else
1370             snprintf( aBuffer, sizeof(aBuffer), "%lo", static_cast<long unsigned int>(pArg->GetLong()) );
1371 		rPar.Get(0)->PutString( String::CreateFromAscii( aBuffer ) );
1372 	}
1373 }
1374 
1375 // Replace(expression, find, replace[, start[, count[, compare]]])
1376 
1377 RTLFUNC(Replace)
1378 {
1379     (void)pBasic;
1380     (void)bWrite;
1381 
1382 	sal_uIntPtr nArgCount = rPar.Count()-1;
1383 	if ( nArgCount < 3 || nArgCount > 6 )
1384 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1385 	else
1386 	{
1387 		String aExpStr = rPar.Get(1)->GetString();
1388 		String aFindStr = rPar.Get(2)->GetString();
1389 		String aReplaceStr = rPar.Get(3)->GetString();
1390 
1391 		sal_Int32 lStartPos = 1;
1392 		if ( nArgCount >= 4 )
1393 		{
1394 			if( rPar.Get(4)->GetType() != SbxEMPTY )
1395 				lStartPos = rPar.Get(4)->GetLong();
1396 			if( lStartPos < 1  || lStartPos > 0xffff )
1397 			{
1398 				StarBASIC::Error( SbERR_BAD_ARGUMENT );
1399 				lStartPos = 1;
1400 			}
1401 		}
1402 
1403 		sal_Int32 lCount = -1;
1404 		if( nArgCount >=5 )
1405 		{
1406 			if( rPar.Get(5)->GetType() != SbxEMPTY )
1407 				lCount = rPar.Get(5)->GetLong();
1408 			if( lCount < -1 || lCount > 0xffff )
1409 			{
1410 				StarBASIC::Error( SbERR_BAD_ARGUMENT );
1411 				lCount = -1;
1412 			}
1413 		}
1414 
1415 		SbiInstance* pInst = pINST;
1416 		int bTextMode;
1417 		bool bCompatibility = ( pInst && pInst->IsCompatibility() );
1418 		if( bCompatibility )
1419 		{
1420 			SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
1421 			bTextMode = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : sal_False;
1422 		}
1423 		else
1424 		{
1425 			bTextMode = 1;
1426 		}
1427 		if ( nArgCount == 6 )
1428 			bTextMode = rPar.Get(6)->GetInteger();
1429 
1430 		sal_uInt16 nExpStrLen = aExpStr.Len();
1431 		sal_uInt16 nFindStrLen = aFindStr.Len();
1432 		sal_uInt16 nReplaceStrLen = aReplaceStr.Len();
1433 
1434 		if( lStartPos <= nExpStrLen )
1435 		{
1436 			sal_uInt16 nPos = static_cast<sal_uInt16>( lStartPos - 1 );
1437 			sal_uInt16 nCounts = 0;
1438 			while( lCount == -1 || lCount > nCounts )
1439 			{
1440 				String aSrcStr( aExpStr );
1441 				if( bTextMode )
1442 				{
1443 					aSrcStr.ToUpperAscii();
1444 					aFindStr.ToUpperAscii();
1445 				}
1446 				nPos = aSrcStr.Search( aFindStr, nPos );
1447 				if( nPos != STRING_NOTFOUND )
1448 				{
1449 					aExpStr.Replace( nPos, nFindStrLen, aReplaceStr );
1450 					nPos = nPos - nFindStrLen + nReplaceStrLen + 1;
1451 					nCounts++;
1452 				}
1453 				else
1454 				{
1455 					break;
1456 				}
1457 			}
1458 		}
1459 		rPar.Get(0)->PutString( aExpStr.Copy( static_cast<sal_uInt16>(lStartPos - 1) )  );
1460 	}
1461 }
1462 
1463 RTLFUNC(Right)
1464 {
1465     (void)pBasic;
1466     (void)bWrite;
1467 
1468 	if ( rPar.Count() < 3 )
1469 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1470 	else
1471 	{
1472 		const String& rStr = rPar.Get(1)->GetString();
1473 		sal_Int32 lResultLen = rPar.Get(2)->GetLong();
1474 		if( lResultLen > 0xffff )
1475 		{
1476 			lResultLen = 0xffff;
1477 		}
1478 		else if( lResultLen < 0 )
1479 		{
1480 			lResultLen = 0;
1481 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1482 		}
1483 		sal_uInt16 nResultLen = (sal_uInt16)lResultLen;
1484 		sal_uInt16 nStrLen = rStr.Len();
1485 		if ( nResultLen > nStrLen )
1486 			nResultLen = nStrLen;
1487 		String aResultStr = rStr.Copy( nStrLen-nResultLen );
1488 		rPar.Get(0)->PutString( aResultStr );
1489 	}
1490 }
1491 
1492 RTLFUNC(RTL)
1493 {
1494     (void)pBasic;
1495     (void)bWrite;
1496 
1497 	rPar.Get( 0 )->PutObject( pBasic->getRTL() );
1498 }
1499 
1500 RTLFUNC(RTrim)
1501 {
1502     (void)pBasic;
1503     (void)bWrite;
1504 
1505 	if ( rPar.Count() < 2 )
1506 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1507 	else
1508 	{
1509 		String aStr( rPar.Get(1)->GetString() );
1510 		aStr.EraseTrailingChars();
1511 		rPar.Get(0)->PutString( aStr );
1512 	}
1513 }
1514 
1515 RTLFUNC(Sgn)
1516 {
1517     (void)pBasic;
1518     (void)bWrite;
1519 
1520 	if ( rPar.Count() < 2 )
1521 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1522 	else
1523 	{
1524 		double aDouble = rPar.Get(1)->GetDouble();
1525 		sal_Int16 nResult = 0;
1526 		if ( aDouble > 0 )
1527 			nResult = 1;
1528 		else if ( aDouble < 0 )
1529 			nResult = -1;
1530 		rPar.Get(0)->PutInteger( nResult );
1531 	}
1532 }
1533 
1534 RTLFUNC(Space)
1535 {
1536     (void)pBasic;
1537     (void)bWrite;
1538 
1539 	if ( rPar.Count() < 2 )
1540 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1541 	else
1542 	{
1543 		String aStr;
1544 		aStr.Fill( (sal_uInt16)(rPar.Get(1)->GetLong() ));
1545 		rPar.Get(0)->PutString( aStr );
1546 	}
1547 }
1548 
1549 RTLFUNC(Spc)
1550 {
1551     (void)pBasic;
1552     (void)bWrite;
1553 
1554 	if ( rPar.Count() < 2 )
1555 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1556 	else
1557 	{
1558 		String aStr;
1559 		aStr.Fill( (sal_uInt16)(rPar.Get(1)->GetLong() ));
1560 		rPar.Get(0)->PutString( aStr );
1561 	}
1562 }
1563 
1564 RTLFUNC(Sqr)
1565 {
1566     (void)pBasic;
1567     (void)bWrite;
1568 
1569 	if ( rPar.Count() < 2 )
1570 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1571 	else
1572 	{
1573 		double aDouble = rPar.Get(1)->GetDouble();
1574 		if ( aDouble >= 0 )
1575 			rPar.Get(0)->PutDouble( sqrt( aDouble ));
1576 		else
1577 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1578 	}
1579 }
1580 
1581 RTLFUNC(Str)
1582 {
1583     (void)pBasic;
1584     (void)bWrite;
1585 
1586 	if ( rPar.Count() < 2 )
1587 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1588 	else
1589 	{
1590 		String aStr;
1591 		SbxVariableRef pArg = rPar.Get( 1 );
1592 		pArg->Format( aStr );
1593 
1594 		// Numbers start with a space
1595 		if( pArg->IsNumericRTL() )
1596         {
1597     		// Kommas durch Punkte ersetzen, damit es symmetrisch zu Val ist!
1598 	    	aStr.SearchAndReplace( ',', '.' );
1599 
1600 			SbiInstance* pInst = pINST;
1601 			bool bCompatibility = ( pInst && pInst->IsCompatibility() );
1602 			if( bCompatibility )
1603 			{
1604 				xub_StrLen nLen = aStr.Len();
1605 
1606 				const sal_Unicode* pBuf = aStr.GetBuffer();
1607 
1608 				bool bNeg = ( pBuf[0] == '-' );
1609 				sal_uInt16 iZeroSearch = 0;
1610 				if( bNeg )
1611 					iZeroSearch++;
1612 
1613 				sal_uInt16 iNext = iZeroSearch + 1;
1614 				if( pBuf[iZeroSearch] == '0' && nLen > iNext && pBuf[iNext] == '.' )
1615 				{
1616 					aStr.Erase( iZeroSearch, 1 );
1617 					pBuf = aStr.GetBuffer();
1618 				}
1619 				if( !bNeg )
1620 					aStr.Insert( ' ', 0 );
1621 			}
1622 			else
1623 				aStr.Insert( ' ', 0 );
1624         }
1625 		rPar.Get(0)->PutString( aStr );
1626 	}
1627 }
1628 
1629 RTLFUNC(StrComp)
1630 {
1631     (void)pBasic;
1632     (void)bWrite;
1633 
1634 	if ( rPar.Count() < 3 )
1635 	{
1636 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1637 		rPar.Get(0)->PutEmpty();
1638 		return;
1639 	}
1640 	const String& rStr1 = rPar.Get(1)->GetString();
1641 	const String& rStr2 = rPar.Get(2)->GetString();
1642 
1643 	SbiInstance* pInst = pINST;
1644 	sal_Int16 nTextCompare;
1645 	bool bCompatibility = ( pInst && pInst->IsCompatibility() );
1646 	if( bCompatibility )
1647 	{
1648 		SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
1649 		nTextCompare = pRT ? pRT->GetImageFlag( SBIMG_COMPARETEXT ) : sal_False;
1650 	}
1651 	else
1652 	{
1653 		nTextCompare = sal_True;
1654 	}
1655 	if ( rPar.Count() == 4 )
1656 		nTextCompare = rPar.Get(3)->GetInteger();
1657 
1658 	if( !bCompatibility )
1659 		nTextCompare = !nTextCompare;
1660 
1661 	StringCompare aResult;
1662     sal_Int32 nRetValue = 0;
1663 	if( nTextCompare )
1664     {
1665         ::utl::TransliterationWrapper* pTransliterationWrapper = GetSbData()->pTransliterationWrapper;
1666         if( !pTransliterationWrapper )
1667         {
1668 		    com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
1669             pTransliterationWrapper = GetSbData()->pTransliterationWrapper =
1670     	        new ::utl::TransliterationWrapper( xSMgr,
1671                     ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE |
1672                     ::com::sun::star::i18n::TransliterationModules_IGNORE_KANA |
1673                     ::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH );
1674         }
1675 
1676         LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
1677         pTransliterationWrapper->loadModuleIfNeeded( eLangType );
1678         nRetValue = pTransliterationWrapper->compareString( rStr1, rStr2 );
1679     }
1680 	else
1681     {
1682 		aResult = rStr1.CompareTo( rStr2 );
1683 	    if ( aResult == COMPARE_LESS )
1684 		    nRetValue = -1;
1685 	    else if ( aResult == COMPARE_GREATER )
1686 		    nRetValue = 1;
1687     }
1688 
1689 	rPar.Get(0)->PutInteger( sal::static_int_cast< sal_Int16 >( nRetValue ) );
1690 }
1691 
1692 RTLFUNC(String)
1693 {
1694     (void)pBasic;
1695     (void)bWrite;
1696 
1697 	if ( rPar.Count() < 2 )
1698 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1699 	else
1700 	{
1701 		String aStr;
1702 		sal_Unicode aFiller;
1703 		sal_Int32 lCount = rPar.Get(1)->GetLong();
1704 		if( lCount < 0 || lCount > 0xffff )
1705 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1706 		sal_uInt16 nCount = (sal_uInt16)lCount;
1707 		if( rPar.Get(2)->GetType() == SbxINTEGER )
1708 			aFiller = (sal_Unicode)rPar.Get(2)->GetInteger();
1709 		else
1710 		{
1711 			const String& rStr = rPar.Get(2)->GetString();
1712 			aFiller = rStr.GetBuffer()[0];
1713 		}
1714 		aStr.Fill( nCount, aFiller );
1715 		rPar.Get(0)->PutString( aStr );
1716 	}
1717 }
1718 
1719 RTLFUNC(Tan)
1720 {
1721     (void)pBasic;
1722     (void)bWrite;
1723 
1724 	if ( rPar.Count() < 2 )
1725 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1726 	else
1727 	{
1728 		SbxVariableRef pArg = rPar.Get( 1 );
1729 		rPar.Get( 0 )->PutDouble( tan( pArg->GetDouble() ) );
1730 	}
1731 }
1732 
1733 RTLFUNC(UCase)
1734 {
1735     (void)pBasic;
1736     (void)bWrite;
1737 
1738 	if ( rPar.Count() < 2 )
1739 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1740 	else
1741 	{
1742 		CharClass& rCharClass = GetCharClass();
1743 		String aStr( rPar.Get(1)->GetString() );
1744 		rCharClass.toUpper( aStr );
1745 		rPar.Get(0)->PutString( aStr );
1746 	}
1747 }
1748 
1749 
1750 RTLFUNC(Val)
1751 {
1752     (void)pBasic;
1753     (void)bWrite;
1754 
1755 	if ( rPar.Count() < 2 )
1756 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1757 	else
1758 	{
1759 		double nResult = 0.0;
1760 		char* pEndPtr;
1761 
1762 		String aStr( rPar.Get(1)->GetString() );
1763 // lt. Mikkysoft bei Kommas abbrechen!
1764 //		for( sal_uInt16 n=0; n < aStr.Len(); n++ )
1765 //			if( aStr[n] == ',' ) aStr[n] = '.';
1766 
1767 		FilterWhiteSpace( aStr );
1768 		if ( aStr.GetBuffer()[0] == '&' && aStr.Len() > 1 )
1769 		{
1770 			int nRadix = 10;
1771 			char aChar = (char)aStr.GetBuffer()[1];
1772 			if ( aChar == 'h' || aChar == 'H' )
1773 				nRadix = 16;
1774 			else if ( aChar == 'o' || aChar == 'O' )
1775 				nRadix = 8;
1776 			if ( nRadix != 10 )
1777 			{
1778 				ByteString aByteStr( aStr, gsl_getSystemTextEncoding() );
1779 				sal_Int16 nlResult = (sal_Int16)strtol( aByteStr.GetBuffer()+2, &pEndPtr, nRadix);
1780 				nResult = (double)nlResult;
1781 			}
1782 		}
1783 		else
1784 		{
1785 			// #57844 Lokalisierte Funktion benutzen
1786 			nResult = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
1787             checkArithmeticOverflow( nResult );
1788 			// ATL: nResult = strtod( aStr.GetStr(), &pEndPtr );
1789 		}
1790 
1791 		rPar.Get(0)->PutDouble( nResult );
1792 	}
1793 }
1794 
1795 
1796 // Helper functions for date conversion
1797 sal_Int16 implGetDateDay( double aDate )
1798 {
1799 	aDate -= 2.0; // normieren: 1.1.1900 => 0.0
1800 	Date aRefDate( 1, 1, 1900 );
1801 	if ( aDate >= 0.0 )
1802 	{
1803 		aDate = floor( aDate );
1804 		aRefDate += (sal_uIntPtr)aDate;
1805 	}
1806 	else
1807 	{
1808 		aDate = ceil( aDate );
1809 		aRefDate -= (sal_uIntPtr)(-1.0 * aDate);
1810 	}
1811 
1812     sal_Int16 nRet = (sal_Int16)( aRefDate.GetDay() );
1813     return nRet;
1814 }
1815 
1816 sal_Int16 implGetDateMonth( double aDate )
1817 {
1818 	Date aRefDate( 1,1,1900 );
1819 	long nDays = (long)aDate;
1820 	nDays -= 2; // normieren: 1.1.1900 => 0.0
1821 	aRefDate += nDays;
1822 	sal_Int16 nRet = (sal_Int16)( aRefDate.GetMonth() );
1823     return nRet;
1824 }
1825 
1826 sal_Int16 implGetDateYear( double aDate )
1827 {
1828 	Date aRefDate( 1,1,1900 );
1829 	long nDays = (long) aDate;
1830 	nDays -= 2; // normieren: 1.1.1900 => 0.0
1831 	aRefDate += nDays;
1832 	sal_Int16 nRet = (sal_Int16)( aRefDate.GetYear() );
1833     return nRet;
1834 }
1835 
1836 sal_Bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, double& rdRet )
1837 {
1838 	if ( nYear < 30 && SbiRuntime::isVBAEnabled() )
1839 		nYear += 2000;
1840 	else if ( nYear < 100 )
1841 		nYear += 1900;
1842 	Date aCurDate( nDay, nMonth, nYear );
1843 	if ((nYear < 100 || nYear > 9999) )
1844 	{
1845 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1846 		return sal_False;
1847 	}
1848 	if ( !SbiRuntime::isVBAEnabled() )
1849 	{
1850 		if ( (nMonth < 1 || nMonth > 12 )||
1851 		(nDay < 1 || nDay > 31 ) )
1852 		{
1853 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1854 			return sal_False;
1855 		}
1856 	}
1857 	else
1858 	{
1859 		// grab the year & month
1860 		aCurDate = Date( 1, (( nMonth % 12 ) > 0 ) ? ( nMonth % 12 ) : 12 + ( nMonth % 12 ), nYear );
1861 
1862 		// adjust year based on month value
1863 		// e.g. 2000, 0, xx = 1999, 12, xx ( or December of the previous year )
1864 		//		2000, 13, xx = 2001, 1, xx ( or January of the following year )
1865 		if( ( nMonth < 1 ) || ( nMonth > 12 ) )
1866 		{
1867 			// inacurrate around leap year, don't use days to calculate,
1868 			// just modify the months directory
1869 			sal_Int16 nYearAdj = ( nMonth /12 ); // default to positive months inputed
1870 			if ( nMonth <=0 )
1871 				nYearAdj = ( ( nMonth -12 ) / 12 );
1872 			aCurDate.SetYear( aCurDate.GetYear() + nYearAdj );
1873 		}
1874 
1875 		// adjust day value,
1876 		// e.g. 2000, 2, 0 = 2000, 1, 31 or the last day of the previous month
1877 		//		2000, 1, 32 = 2000, 2, 1 or the first day of the following month
1878 		if( ( nDay < 1 ) || ( nDay > aCurDate.GetDaysInMonth() ) )
1879 			aCurDate += nDay - 1;
1880 		else
1881 			aCurDate.SetDay( nDay );
1882 	}
1883 
1884 	long nDiffDays = GetDayDiff( aCurDate );
1885     rdRet = (double)nDiffDays;
1886     return sal_True;
1887 }
1888 
1889 // Function to convert date to ISO 8601 date format
1890 RTLFUNC(CDateToIso)
1891 {
1892     (void)pBasic;
1893     (void)bWrite;
1894 
1895 	if ( rPar.Count() == 2 )
1896 	{
1897         double aDate = rPar.Get(1)->GetDate();
1898 
1899         char Buffer[9];
1900         snprintf( Buffer, sizeof( Buffer ), "%04d%02d%02d",
1901             implGetDateYear( aDate ),
1902             implGetDateMonth( aDate ),
1903             implGetDateDay( aDate ) );
1904 		String aRetStr = String::CreateFromAscii( Buffer );
1905         rPar.Get(0)->PutString( aRetStr );
1906 	}
1907 	else
1908 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1909 }
1910 
1911 // Function to convert date from ISO 8601 date format
1912 RTLFUNC(CDateFromIso)
1913 {
1914     (void)pBasic;
1915     (void)bWrite;
1916 
1917 	if ( rPar.Count() == 2 )
1918 	{
1919 		String aStr = rPar.Get(1)->GetString();
1920         sal_Int16 iMonthStart = aStr.Len() - 4;
1921         String aYearStr  = aStr.Copy( 0, iMonthStart );
1922         String aMonthStr = aStr.Copy( iMonthStart, 2 );
1923         String aDayStr   = aStr.Copy( iMonthStart+2, 2 );
1924 
1925         double dDate;
1926         if( implDateSerial( (sal_Int16)aYearStr.ToInt32(),
1927             (sal_Int16)aMonthStr.ToInt32(), (sal_Int16)aDayStr.ToInt32(), dDate ) )
1928         {
1929     	    rPar.Get(0)->PutDate( dDate );
1930         }
1931 	}
1932 	else
1933 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1934 }
1935 
1936 RTLFUNC(DateSerial)
1937 {
1938     (void)pBasic;
1939     (void)bWrite;
1940 
1941 	if ( rPar.Count() < 4 )
1942 	{
1943 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1944 		return;
1945 	}
1946 	sal_Int16 nYear = rPar.Get(1)->GetInteger();
1947 	sal_Int16 nMonth = rPar.Get(2)->GetInteger();
1948 	sal_Int16 nDay = rPar.Get(3)->GetInteger();
1949 
1950     double dDate;
1951     if( implDateSerial( nYear, nMonth, nDay, dDate ) )
1952     	rPar.Get(0)->PutDate( dDate );
1953 }
1954 
1955 RTLFUNC(TimeSerial)
1956 {
1957     (void)pBasic;
1958     (void)bWrite;
1959 
1960 	if ( rPar.Count() < 4 )
1961 	{
1962 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1963 		return;
1964 	}
1965 	sal_Int16 nHour = rPar.Get(1)->GetInteger();
1966 	if ( nHour == 24 )
1967 		nHour = 0;                      // Wegen UNO DateTimes, die bis 24 Uhr gehen
1968 	sal_Int16 nMinute = rPar.Get(2)->GetInteger();
1969 	sal_Int16 nSecond = rPar.Get(3)->GetInteger();
1970 	if ((nHour < 0 || nHour > 23)   ||
1971 		(nMinute < 0 || nMinute > 59 )	||
1972 		(nSecond < 0 || nSecond > 59 ))
1973 	{
1974 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1975 		return;
1976 	}
1977 
1978 	sal_Int32 nSeconds = nHour;
1979 	nSeconds *= 3600;
1980 	nSeconds += nMinute * 60;
1981 	nSeconds += nSecond;
1982 	double nDays = ((double)nSeconds) / (double)(86400.0);
1983 	rPar.Get(0)->PutDate( nDays ); // JSM
1984 }
1985 
1986 RTLFUNC(DateValue)
1987 {
1988     (void)pBasic;
1989     (void)bWrite;
1990 
1991 	if ( rPar.Count() < 2 )
1992 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1993 	else
1994 	{
1995 		// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
1996 		SvNumberFormatter* pFormatter = NULL;
1997 		if( pINST )
1998 			pFormatter = pINST->GetNumberFormatter();
1999 		else
2000 		{
2001 			sal_uInt32 n;	// Dummy
2002 			SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
2003 		}
2004 
2005 		sal_uInt32 nIndex;
2006 		double fResult;
2007 		String aStr( rPar.Get(1)->GetString() );
2008 		sal_Bool bSuccess = pFormatter->IsNumberFormat( aStr, nIndex, fResult );
2009 		short nType = pFormatter->GetType( nIndex );
2010 
2011 		// DateValue("February 12, 1969") raises error if the system locale is not en_US
2012 		// by using SbiInstance::GetNumberFormatter.
2013 		// It seems that both locale number formatter and English number formatter
2014 		// are supported in Visual Basic.
2015 		LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
2016         if( !bSuccess && ( eLangType != LANGUAGE_ENGLISH_US ) )
2017 		{
2018 			// Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value;
2019 			com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
2020 				xFactory = comphelper::getProcessServiceFactory();
2021 			SvNumberFormatter aFormatter( xFactory, LANGUAGE_ENGLISH_US );
2022 			bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, fResult );
2023 			nType = aFormatter.GetType( nIndex );
2024 		}
2025 
2026 		if(bSuccess && (nType==NUMBERFORMAT_DATE || nType==NUMBERFORMAT_DATETIME))
2027 		{
2028 			if ( nType == NUMBERFORMAT_DATETIME )
2029 			{
2030 				// Zeit abschneiden
2031 				if ( fResult  > 0.0 )
2032 					fResult = floor( fResult );
2033 				else
2034 					fResult = ceil( fResult );
2035 			}
2036 			// fResult += 2.0; // Anpassung  StarCalcFormatter
2037 			rPar.Get(0)->PutDate( fResult ); // JSM
2038 		}
2039 		else
2040 			StarBASIC::Error( SbERR_CONVERSION );
2041 
2042 		// #39629 pFormatter kann selbst angefordert sein
2043 		if( !pINST )
2044 			delete pFormatter;
2045 	}
2046 }
2047 
2048 RTLFUNC(TimeValue)
2049 {
2050     (void)pBasic;
2051     (void)bWrite;
2052 
2053 	if ( rPar.Count() < 2 )
2054 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2055 	else
2056 	{
2057 		// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
2058 		SvNumberFormatter* pFormatter = NULL;
2059 		if( pINST )
2060 			pFormatter = pINST->GetNumberFormatter();
2061 		else
2062 		{
2063 			sal_uInt32 n;	// Dummy
2064 			SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
2065 		}
2066 
2067 		sal_uInt32 nIndex;
2068 		double fResult;
2069 		sal_Bool bSuccess = pFormatter->IsNumberFormat( rPar.Get(1)->GetString(),
2070 												   nIndex, fResult );
2071 		short nType = pFormatter->GetType(nIndex);
2072 		if(bSuccess && (nType==NUMBERFORMAT_TIME||nType==NUMBERFORMAT_DATETIME))
2073 		{
2074 			if ( nType == NUMBERFORMAT_DATETIME )
2075 				// Tage abschneiden
2076 				fResult = fmod( fResult, 1 );
2077 			rPar.Get(0)->PutDate( fResult ); // JSM
2078 		}
2079 		else
2080 			StarBASIC::Error( SbERR_CONVERSION );
2081 
2082 		// #39629 pFormatter kann selbst angefordert sein
2083 		if( !pINST )
2084 			delete pFormatter;
2085 	}
2086 }
2087 
2088 RTLFUNC(Day)
2089 {
2090     (void)pBasic;
2091     (void)bWrite;
2092 
2093 	if ( rPar.Count() < 2 )
2094 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2095 	else
2096 	{
2097 		SbxVariableRef pArg = rPar.Get( 1 );
2098 		double aDate = pArg->GetDate();
2099 
2100         sal_Int16 nDay = implGetDateDay( aDate );
2101 		rPar.Get(0)->PutInteger( nDay );
2102 	}
2103 }
2104 
2105 RTLFUNC(Year)
2106 {
2107     (void)pBasic;
2108     (void)bWrite;
2109 
2110 	if ( rPar.Count() < 2 )
2111 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2112 	else
2113 	{
2114         sal_Int16 nYear = implGetDateYear( rPar.Get(1)->GetDate() );
2115 		rPar.Get(0)->PutInteger( nYear );
2116 	}
2117 }
2118 
2119 sal_Int16 implGetHour( double dDate )
2120 {
2121 	if( dDate < 0.0 )
2122 		dDate *= -1.0;
2123 	double nFrac = dDate - floor( dDate );
2124 	nFrac *= 86400.0;
2125 	sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
2126 	sal_Int16 nHour = (sal_Int16)(nSeconds / 3600);
2127     return nHour;
2128 }
2129 
2130 RTLFUNC(Hour)
2131 {
2132     (void)pBasic;
2133     (void)bWrite;
2134 
2135 	if ( rPar.Count() < 2 )
2136 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2137 	else
2138 	{
2139 		double nArg = rPar.Get(1)->GetDate();
2140 		sal_Int16 nHour = implGetHour( nArg );
2141 		rPar.Get(0)->PutInteger( nHour );
2142 	}
2143 }
2144 
2145 sal_Int16 implGetMinute( double dDate )
2146 {
2147 	if( dDate < 0.0 )
2148 		dDate *= -1.0;
2149 	double nFrac = dDate - floor( dDate );
2150 	nFrac *= 86400.0;
2151 	sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
2152 	sal_Int16 nTemp = (sal_Int16)(nSeconds % 3600);
2153 	sal_Int16 nMin = nTemp / 60;
2154     return nMin;
2155 }
2156 
2157 RTLFUNC(Minute)
2158 {
2159     (void)pBasic;
2160     (void)bWrite;
2161 
2162 	if ( rPar.Count() < 2 )
2163 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2164 	else
2165 	{
2166 		double nArg = rPar.Get(1)->GetDate();
2167 		sal_Int16 nMin = implGetMinute( nArg );
2168 		rPar.Get(0)->PutInteger( nMin );
2169 	}
2170 }
2171 
2172 RTLFUNC(Month)
2173 {
2174     (void)pBasic;
2175     (void)bWrite;
2176 
2177 	if ( rPar.Count() < 2 )
2178 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2179 	else
2180 	{
2181         sal_Int16 nMonth = implGetDateMonth( rPar.Get(1)->GetDate() );
2182 		rPar.Get(0)->PutInteger( nMonth );
2183 	}
2184 }
2185 
2186 sal_Int16 implGetSecond( double dDate )
2187 {
2188 	if( dDate < 0.0 )
2189 		dDate *= -1.0;
2190 	double nFrac = dDate - floor( dDate );
2191 	nFrac *= 86400.0;
2192 	sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
2193 	sal_Int16 nTemp = (sal_Int16)(nSeconds / 3600);
2194 	nSeconds -= nTemp * 3600;
2195 	nTemp = (sal_Int16)(nSeconds / 60);
2196 	nSeconds -= nTemp * 60;
2197 
2198 	sal_Int16 nRet = (sal_Int16)nSeconds;
2199     return nRet;
2200 }
2201 
2202 RTLFUNC(Second)
2203 {
2204     (void)pBasic;
2205     (void)bWrite;
2206 
2207 	if ( rPar.Count() < 2 )
2208 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2209 	else
2210 	{
2211 		double nArg = rPar.Get(1)->GetDate();
2212 		sal_Int16 nSecond = implGetSecond( nArg );
2213 		rPar.Get(0)->PutInteger( nSecond );
2214 	}
2215 }
2216 
2217 double Now_Impl()
2218 {
2219 	Date aDate;
2220 	Time aTime;
2221 	double aSerial = (double)GetDayDiff( aDate );
2222 	long nSeconds = aTime.GetHour();
2223 	nSeconds *= 3600;
2224 	nSeconds += aTime.GetMin() * 60;
2225 	nSeconds += aTime.GetSec();
2226 	double nDays = ((double)nSeconds) / (double)(24.0*3600.0);
2227 	aSerial += nDays;
2228 	return aSerial;
2229 }
2230 
2231 // Date Now(void)
2232 
2233 RTLFUNC(Now)
2234 {
2235     	(void)pBasic;
2236     	(void)bWrite;
2237 	rPar.Get(0)->PutDate( Now_Impl() );
2238 }
2239 
2240 // Date Time(void)
2241 
2242 RTLFUNC(Time)
2243 {
2244     (void)pBasic;
2245 
2246 	if ( !bWrite )
2247 	{
2248 		Time aTime;
2249 		SbxVariable* pMeth = rPar.Get( 0 );
2250 		String aRes;
2251 		if( pMeth->IsFixed() )
2252 		{
2253 			// Time$: hh:mm:ss
2254 			char buf[ 20 ];
2255             snprintf( buf, sizeof(buf), "%02d:%02d:%02d",
2256 				aTime.GetHour(), aTime.GetMin(), aTime.GetSec() );
2257 			aRes = String::CreateFromAscii( buf );
2258 		}
2259 		else
2260 		{
2261 			// Time: system dependent
2262 			long nSeconds=aTime.GetHour();
2263 			nSeconds *= 3600;
2264 			nSeconds += aTime.GetMin() * 60;
2265 			nSeconds += aTime.GetSec();
2266 			double nDays = (double)nSeconds * ( 1.0 / (24.0*3600.0) );
2267 			Color* pCol;
2268 
2269 			// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
2270 			SvNumberFormatter* pFormatter = NULL;
2271 			sal_uInt32 nIndex;
2272 			if( pINST )
2273 			{
2274 				pFormatter = pINST->GetNumberFormatter();
2275 				nIndex = pINST->GetStdTimeIdx();
2276 			}
2277 			else
2278 			{
2279 				sal_uInt32 n;	// Dummy
2280 				SbiInstance::PrepareNumberFormatter( pFormatter, n, nIndex, n );
2281 			}
2282 
2283 			pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
2284 
2285 			// #39629 pFormatter kann selbst angefordert sein
2286 			if( !pINST )
2287 				delete pFormatter;
2288 		}
2289 		pMeth->PutString( aRes );
2290 	}
2291 	else
2292 	{
2293 		StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
2294 	}
2295 }
2296 
2297 RTLFUNC(Timer)
2298 {
2299     (void)pBasic;
2300     (void)bWrite;
2301 
2302 	Time aTime;
2303 	long nSeconds = aTime.GetHour();
2304 	nSeconds *= 3600;
2305 	nSeconds += aTime.GetMin() * 60;
2306 	nSeconds += aTime.GetSec();
2307 	rPar.Get(0)->PutDate( (double)nSeconds );
2308 }
2309 
2310 
2311 RTLFUNC(Date)
2312 {
2313     (void)pBasic;
2314     (void)bWrite;
2315 
2316 	if ( !bWrite )
2317 	{
2318 		Date aToday;
2319 		double nDays = (double)GetDayDiff( aToday );
2320 		SbxVariable* pMeth = rPar.Get( 0 );
2321 		if( pMeth->IsString() )
2322 		{
2323 			String aRes;
2324 			Color* pCol;
2325 
2326 			// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
2327 			SvNumberFormatter* pFormatter = NULL;
2328 			sal_uInt32 nIndex;
2329 			if( pINST )
2330 			{
2331 				pFormatter = pINST->GetNumberFormatter();
2332 				nIndex = pINST->GetStdDateIdx();
2333 			}
2334 			else
2335 			{
2336 				sal_uInt32 n;	// Dummy
2337 				SbiInstance::PrepareNumberFormatter( pFormatter, nIndex, n, n );
2338 			}
2339 
2340 			pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
2341 			pMeth->PutString( aRes );
2342 
2343 			// #39629 pFormatter kann selbst angefordert sein
2344 			if( !pINST )
2345 				delete pFormatter;
2346 		}
2347 		else
2348 			pMeth->PutDate( nDays );
2349 	}
2350 	else
2351 	{
2352 		StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
2353 	}
2354 }
2355 
2356 RTLFUNC(IsArray)
2357 {
2358     (void)pBasic;
2359     (void)bWrite;
2360 
2361 	if ( rPar.Count() < 2 )
2362 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2363 	else
2364 		rPar.Get(0)->PutBool((rPar.Get(1)->GetType() & SbxARRAY) ? sal_True : sal_False );
2365 }
2366 
2367 RTLFUNC(IsObject)
2368 {
2369     (void)pBasic;
2370     (void)bWrite;
2371 
2372 	if ( rPar.Count() < 2 )
2373 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2374 	else
2375     {
2376     	SbxVariable* pVar = rPar.Get(1);
2377 	    SbxBase* pObj = (SbxBase*)pVar->GetObject();
2378 
2379 		// #100385: GetObject can result in an error, so reset it
2380 		SbxBase::ResetError();
2381 
2382         SbUnoClass* pUnoClass;
2383         sal_Bool bObject;
2384 	    if( pObj &&  NULL != ( pUnoClass=PTR_CAST(SbUnoClass,pObj) ) )
2385         {
2386             bObject = pUnoClass->getUnoClass().is();
2387         }
2388         else
2389         {
2390             bObject = pVar->IsObject();
2391         }
2392 		rPar.Get( 0 )->PutBool( bObject );
2393     }
2394 }
2395 
2396 RTLFUNC(IsDate)
2397 {
2398     (void)pBasic;
2399     (void)bWrite;
2400 
2401 	if ( rPar.Count() < 2 )
2402 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2403 	else
2404 	{
2405 		// #46134 Nur String wird konvertiert, andere Typen ergeben sal_False
2406 		SbxVariableRef xArg = rPar.Get( 1 );
2407 		SbxDataType eType = xArg->GetType();
2408 		sal_Bool bDate = sal_False;
2409 
2410 		if( eType == SbxDATE )
2411 		{
2412 			bDate = sal_True;
2413 		}
2414 		else if( eType == SbxSTRING )
2415 		{
2416 			// Error loeschen
2417 			SbxError nPrevError = SbxBase::GetError();
2418 			SbxBase::ResetError();
2419 
2420 			// Konvertierung des Parameters nach SbxDATE erzwingen
2421 			xArg->SbxValue::GetDate();
2422 
2423 			// Bei Fehler ist es kein Date
2424 			bDate = !SbxBase::IsError();
2425 
2426 			// Error-Situation wiederherstellen
2427 			SbxBase::ResetError();
2428 			SbxBase::SetError( nPrevError );
2429 		}
2430 		rPar.Get( 0 )->PutBool( bDate );
2431 	}
2432 }
2433 
2434 RTLFUNC(IsEmpty)
2435 {
2436     (void)pBasic;
2437     (void)bWrite;
2438 
2439 	if ( rPar.Count() < 2 )
2440 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2441 	else
2442 		rPar.Get( 0 )->PutBool( rPar.Get(1)->IsEmpty() );
2443 }
2444 
2445 RTLFUNC(IsError)
2446 {
2447     (void)pBasic;
2448     (void)bWrite;
2449 
2450 	if ( rPar.Count() < 2 )
2451 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2452 	else
2453 		rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
2454 }
2455 
2456 RTLFUNC(IsNull)
2457 {
2458     (void)pBasic;
2459     (void)bWrite;
2460 
2461 	if ( rPar.Count() < 2 )
2462 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2463 	else
2464 	{
2465 		// #51475 Wegen Uno-Objekten auch true liefern,
2466 		// wenn der pObj-Wert NULL ist
2467 		SbxVariableRef pArg = rPar.Get( 1 );
2468 		sal_Bool bNull = rPar.Get(1)->IsNull();
2469 		if( !bNull && pArg->GetType() == SbxOBJECT )
2470 		{
2471 			SbxBase* pObj = pArg->GetObject();
2472 			if( !pObj )
2473 				bNull = sal_True;
2474 		}
2475 		rPar.Get( 0 )->PutBool( bNull );
2476 	}
2477 }
2478 
2479 RTLFUNC(IsNumeric)
2480 {
2481     (void)pBasic;
2482     (void)bWrite;
2483 
2484 	if ( rPar.Count() < 2 )
2485 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2486 	else
2487 		rPar.Get( 0 )->PutBool( rPar.Get( 1 )->IsNumericRTL() );
2488 }
2489 
2490 // Das machen wir auf die billige Tour
2491 
2492 RTLFUNC(IsMissing)
2493 {
2494     (void)pBasic;
2495     (void)bWrite;
2496 
2497 	if ( rPar.Count() < 2 )
2498 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2499 	else
2500 		// #57915 Missing wird durch Error angezeigt
2501 		rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
2502 }
2503 
2504 // Dir( [Maske] [,Attrs] )
2505 // ToDo: Library-globaler Datenbereich fuer Dir-Objekt und Flags
2506 
2507 
2508 String getDirectoryPath( String aPathStr )
2509 {
2510     String aRetStr;
2511 
2512     DirectoryItem aItem;
2513     FileBase::RC nRet = DirectoryItem::get( aPathStr, aItem );
2514 	if( nRet == FileBase::E_None )
2515 	{
2516 		FileStatus aFileStatus( FileStatusMask_Type );
2517 		nRet = aItem.getFileStatus( aFileStatus );
2518 		if( nRet == FileBase::E_None )
2519 		{
2520 			FileStatus::Type aType = aFileStatus.getFileType();
2521 			if( isFolder( aType ) )
2522             {
2523         		aRetStr = aPathStr;
2524             }
2525             else if( aType == FileStatus::Link )
2526             {
2527         		FileStatus aFileStatus2( FileStatusMask_LinkTargetURL );
2528         		nRet = aItem.getFileStatus( aFileStatus2 );
2529 		        if( nRet == FileBase::E_None )
2530                     aRetStr = getDirectoryPath( aFileStatus2.getLinkTargetURL() );
2531             }
2532 		}
2533     }
2534     return aRetStr;
2535 }
2536 
2537 // Function looks for wildcards, removes them and always returns the pure path
2538 String implSetupWildcard( const String& rFileParam, SbiRTLData* pRTLData )
2539 {
2540     static String aAsterisk = String::CreateFromAscii( "*" );
2541 	static sal_Char cDelim1 = (sal_Char)'/';
2542 	static sal_Char cDelim2 = (sal_Char)'\\';
2543 	static sal_Char cWild1 = '*';
2544 	static sal_Char cWild2 = '?';
2545 
2546 	delete pRTLData->pWildCard;
2547 	pRTLData->pWildCard = NULL;
2548 	pRTLData->sFullNameToBeChecked = String();
2549 
2550 	String aFileParam = rFileParam;
2551 	xub_StrLen nLastWild = aFileParam.SearchBackward( cWild1 );
2552 	if( nLastWild == STRING_NOTFOUND )
2553 		nLastWild = aFileParam.SearchBackward( cWild2 );
2554 	sal_Bool bHasWildcards = ( nLastWild != STRING_NOTFOUND );
2555 
2556 
2557 	xub_StrLen nLastDelim = aFileParam.SearchBackward( cDelim1 );
2558 	if( nLastDelim == STRING_NOTFOUND )
2559 		nLastDelim = aFileParam.SearchBackward( cDelim2 );
2560 
2561     if( bHasWildcards )
2562     {
2563         // Wildcards in path?
2564         if( nLastDelim != STRING_NOTFOUND && nLastDelim > nLastWild )
2565             return aFileParam;
2566     }
2567     else
2568     {
2569 	    String aPathStr = getFullPath( aFileParam );
2570         if( nLastDelim != aFileParam.Len() - 1 )
2571             pRTLData->sFullNameToBeChecked = aPathStr;
2572         return aPathStr;
2573     }
2574 
2575 	String aPureFileName;
2576 	if( nLastDelim == STRING_NOTFOUND )
2577 	{
2578 		aPureFileName = aFileParam;
2579 		aFileParam = String();
2580 	}
2581 	else
2582 	{
2583 		aPureFileName = aFileParam.Copy( nLastDelim + 1 );
2584 		aFileParam = aFileParam.Copy( 0, nLastDelim );
2585 	}
2586 
2587 	// Try again to get a valid URL/UNC-path with only the path
2588 	String aPathStr = getFullPath( aFileParam );
2589 	xub_StrLen nPureLen = aPureFileName.Len();
2590 
2591 	// Is there a pure file name left? Otherwise the path is
2592 	// invalid anyway because it was not accepted by OSL before
2593 	if( nPureLen && aPureFileName != aAsterisk )
2594 	{
2595 		pRTLData->pWildCard = new WildCard( aPureFileName );
2596 	}
2597 	return aPathStr;
2598 }
2599 
2600 inline sal_Bool implCheckWildcard( const String& rName, SbiRTLData* pRTLData )
2601 {
2602 	sal_Bool bMatch = sal_True;
2603 
2604 	if( pRTLData->pWildCard )
2605 		bMatch = pRTLData->pWildCard->Matches( rName );
2606 	return bMatch;
2607 }
2608 
2609 
2610 bool isRootDir( String aDirURLStr )
2611 {
2612 	INetURLObject aDirURLObj( aDirURLStr );
2613 	sal_Bool bRoot = sal_False;
2614 
2615 	// Check if it's a root directory
2616 	sal_Int32 nCount = aDirURLObj.getSegmentCount();
2617 
2618 	// No segment means Unix root directory "file:///"
2619 	if( nCount == 0 )
2620 	{
2621 		bRoot = sal_True;
2622 	}
2623 	// Exactly one segment needs further checking, because it
2624 	// can be Unix "file:///foo/" -> no root
2625 	// or Windows  "file:///c:/"  -> root
2626 	else if( nCount == 1 )
2627 	{
2628 		::rtl::OUString aSeg1 = aDirURLObj.getName( 0, sal_True,
2629 			INetURLObject::DECODE_WITH_CHARSET );
2630 		if( aSeg1.getStr()[1] == (sal_Unicode)':' )
2631 		{
2632 			bRoot = sal_True;
2633 		}
2634 	}
2635 	// More than one segments can never be root
2636 	// so bRoot remains sal_False
2637 
2638     return bRoot;
2639 }
2640 
2641 RTLFUNC(Dir)
2642 {
2643     (void)pBasic;
2644     (void)bWrite;
2645 
2646 	String aPath;
2647 
2648 	sal_uInt16 nParCount = rPar.Count();
2649 	if( nParCount > 3 )
2650 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2651 	else
2652 	{
2653 		SbiRTLData* pRTLData = pINST->GetRTLData();
2654 
2655 		// #34645: Kann auch von der URL-Zeile ueber 'macro: Dir' aufgerufen werden
2656 		// dann existiert kein pRTLData und die Methode muss verlassen werden
2657 		if( !pRTLData )
2658 			return;
2659 
2660 		// <-- UCB
2661 		if( hasUno() )
2662 		{
2663 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
2664 			if( xSFI.is() )
2665 			{
2666 				if ( nParCount >= 2 )
2667 				{
2668 					String aFileParam = rPar.Get(1)->GetString();
2669 
2670 					String aFileURLStr = implSetupWildcard( aFileParam, pRTLData );
2671                     if( pRTLData->sFullNameToBeChecked.Len() > 0 )
2672                     {
2673 						sal_Bool bExists = sal_False;
2674 						try	{ bExists = xSFI->exists( aFileURLStr ); }
2675 						catch( Exception & ) {}
2676 
2677                         String aNameOnlyStr;
2678 						if( bExists )
2679                         {
2680 							INetURLObject aFileURL( aFileURLStr );
2681 							aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT,
2682 								true, INetURLObject::DECODE_WITH_CHARSET );
2683                         }
2684 						rPar.Get(0)->PutString( aNameOnlyStr );
2685 						return;
2686                     }
2687 
2688 					try
2689 					{
2690 						String aDirURLStr;
2691 						sal_Bool bFolder = xSFI->isFolder( aFileURLStr );
2692 
2693 						if( bFolder )
2694 						{
2695 							aDirURLStr = aFileURLStr;
2696 						}
2697 						else
2698 						{
2699                             String aEmptyStr;
2700 							rPar.Get(0)->PutString( aEmptyStr );
2701 						}
2702 
2703 						sal_uInt16 nFlags = 0;
2704 						if ( nParCount > 2 )
2705 							pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
2706 						else
2707 							pRTLData->nDirFlags = 0;
2708 
2709 						// Read directory
2710 						sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0);
2711 						pRTLData->aDirSeq = xSFI->getFolderContents( aDirURLStr, bIncludeFolders );
2712 						pRTLData->nCurDirPos = 0;
2713 
2714 						// #78651 Add "." and ".." directories for VB compatibility
2715 						if( bIncludeFolders )
2716 						{
2717 							sal_Bool bRoot = isRootDir( aDirURLStr );
2718 
2719 							// If it's no root directory we flag the need for
2720 							// the "." and ".." directories by the value -2
2721 							// for the actual position. Later for -2 will be
2722 							// returned "." and for -1 ".."
2723 							if( !bRoot )
2724 							{
2725 								pRTLData->nCurDirPos = -2;
2726 							}
2727 						}
2728 					}
2729 					catch( Exception & )
2730 					{
2731 						//StarBASIC::Error( ERRCODE_IO_GENERAL );
2732 					}
2733 				}
2734 
2735 
2736 				if( pRTLData->aDirSeq.getLength() > 0 )
2737 				{
2738 					sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
2739 
2740 					SbiInstance* pInst = pINST;
2741 					bool bCompatibility = ( pInst && pInst->IsCompatibility() );
2742 					for( ;; )
2743 					{
2744 						if( pRTLData->nCurDirPos < 0 )
2745 						{
2746 							if( pRTLData->nCurDirPos == -2 )
2747 							{
2748 								aPath = ::rtl::OUString::createFromAscii( "." );
2749 							}
2750 							else if( pRTLData->nCurDirPos == -1 )
2751 							{
2752 								aPath = ::rtl::OUString::createFromAscii( ".." );
2753 							}
2754 							pRTLData->nCurDirPos++;
2755 						}
2756 						else if( pRTLData->nCurDirPos >= pRTLData->aDirSeq.getLength() )
2757 						{
2758 							pRTLData->aDirSeq.realloc( 0 );
2759 							aPath.Erase();
2760 							break;
2761 						}
2762 						else
2763 						{
2764 							::rtl::OUString aFile = pRTLData->aDirSeq.getConstArray()[pRTLData->nCurDirPos++];
2765 
2766 							if( bCompatibility )
2767 							{
2768 								if( !bFolderFlag )
2769 								{
2770 									sal_Bool bFolder = xSFI->isFolder( aFile );
2771 									if( bFolder )
2772 										continue;
2773 								}
2774 							}
2775 							else
2776 							{
2777 								// Only directories
2778 								if( bFolderFlag )
2779 								{
2780 									sal_Bool bFolder = xSFI->isFolder( aFile );
2781 									if( !bFolder )
2782 										continue;
2783 								}
2784 							}
2785 
2786 							INetURLObject aURL( aFile );
2787 							aPath = aURL.getName( INetURLObject::LAST_SEGMENT, sal_True,
2788 								INetURLObject::DECODE_WITH_CHARSET );
2789 						}
2790 
2791 						sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
2792 						if( !bMatch )
2793 							continue;
2794 
2795 						break;
2796 					}
2797 				}
2798 				rPar.Get(0)->PutString( aPath );
2799 			}
2800 		}
2801 		else
2802 		// --> UCB
2803 		{
2804 #ifdef _OLD_FILE_IMPL
2805 			if ( nParCount >= 2 )
2806 			{
2807 				delete pRTLData->pDir;
2808 				pRTLData->pDir = 0; // wg. Sonderbehandlung Sb_ATTR_VOLUME
2809 				DirEntry aEntry( rPar.Get(1)->GetString() );
2810 				FileStat aStat( aEntry );
2811 				if(!aStat.GetError() && (aStat.GetKind() & FSYS_KIND_FILE))
2812 				{
2813 					// ah ja, ist nur ein dateiname
2814 					// Pfad abschneiden (wg. VB4)
2815 					rPar.Get(0)->PutString( aEntry.GetName() );
2816 					return;
2817 				}
2818 				sal_uInt16 nFlags = 0;
2819 				if ( nParCount > 2 )
2820 					pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
2821 				else
2822 					pRTLData->nDirFlags = 0;
2823 
2824 				// Sb_ATTR_VOLUME wird getrennt gehandelt
2825 				if( pRTLData->nDirFlags & Sb_ATTR_VOLUME )
2826 					aPath = aEntry.GetVolume();
2827 				else
2828 				{
2829 					// Die richtige Auswahl treffen
2830 					sal_uInt16 nMode = FSYS_KIND_FILE;
2831 					if( nFlags & Sb_ATTR_DIRECTORY )
2832 						nMode |= FSYS_KIND_DIR;
2833 					if( nFlags == Sb_ATTR_DIRECTORY )
2834 						nMode = FSYS_KIND_DIR;
2835 					pRTLData->pDir = new Dir( aEntry, (DirEntryKind) nMode );
2836 					pRTLData->nCurDirPos = 0;
2837 				}
2838 			}
2839 
2840 			if( pRTLData->pDir )
2841 			{
2842 				for( ;; )
2843 				{
2844 					if( pRTLData->nCurDirPos >= pRTLData->pDir->Count() )
2845 					{
2846 						delete pRTLData->pDir;
2847 						pRTLData->pDir = 0;
2848 						aPath.Erase();
2849 						break;
2850 					}
2851 					DirEntry aNextEntry=(*(pRTLData->pDir))[pRTLData->nCurDirPos++];
2852 					aPath = aNextEntry.GetName(); //Full();
2853 					break;
2854 				}
2855 			}
2856 			rPar.Get(0)->PutString( aPath );
2857 #else
2858 			// TODO: OSL
2859 			if ( nParCount >= 2 )
2860 			{
2861 				String aFileParam = rPar.Get(1)->GetString();
2862 
2863 				String aDirURL = implSetupWildcard( aFileParam, pRTLData );
2864 
2865 				sal_uInt16 nFlags = 0;
2866 				if ( nParCount > 2 )
2867 					pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
2868 				else
2869 					pRTLData->nDirFlags = 0;
2870 
2871 				// Read directory
2872 				sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0);
2873 				pRTLData->pDir = new Directory( aDirURL );
2874 				FileBase::RC nRet = pRTLData->pDir->open();
2875 				if( nRet != FileBase::E_None )
2876 				{
2877 					delete pRTLData->pDir;
2878 					pRTLData->pDir = NULL;
2879 					rPar.Get(0)->PutString( String() );
2880 					return;
2881 				}
2882 
2883 				// #86950 Add "." and ".." directories for VB compatibility
2884 				pRTLData->nCurDirPos = 0;
2885 				if( bIncludeFolders )
2886 				{
2887 					sal_Bool bRoot = isRootDir( aDirURL );
2888 
2889 					// If it's no root directory we flag the need for
2890 					// the "." and ".." directories by the value -2
2891 					// for the actual position. Later for -2 will be
2892 					// returned "." and for -1 ".."
2893 					if( !bRoot )
2894 					{
2895 						pRTLData->nCurDirPos = -2;
2896 					}
2897 				}
2898 
2899 			}
2900 
2901 			if( pRTLData->pDir )
2902 			{
2903 				sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
2904 				for( ;; )
2905 				{
2906 					if( pRTLData->nCurDirPos < 0 )
2907 					{
2908 						if( pRTLData->nCurDirPos == -2 )
2909 						{
2910 							aPath = ::rtl::OUString::createFromAscii( "." );
2911 						}
2912 						else if( pRTLData->nCurDirPos == -1 )
2913 						{
2914 							aPath = ::rtl::OUString::createFromAscii( ".." );
2915 						}
2916 						pRTLData->nCurDirPos++;
2917 					}
2918                     else
2919                     {
2920 					    DirectoryItem aItem;
2921 				        FileBase::RC nRet = pRTLData->pDir->getNextItem( aItem );
2922 					    if( nRet != FileBase::E_None )
2923 					    {
2924 						    delete pRTLData->pDir;
2925 						    pRTLData->pDir = NULL;
2926 						    aPath.Erase();
2927 						    break;
2928 					    }
2929 
2930 					    // Handle flags
2931 					    FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileName );
2932 					    nRet = aItem.getFileStatus( aFileStatus );
2933 
2934 					    // Only directories?
2935 					    if( bFolderFlag )
2936 					    {
2937 						    FileStatus::Type aType = aFileStatus.getFileType();
2938 						    sal_Bool bFolder = isFolder( aType );
2939 						    if( !bFolder )
2940 							    continue;
2941 					    }
2942 
2943 					    aPath = aFileStatus.getFileName();
2944                     }
2945 
2946 					sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
2947 					if( !bMatch )
2948 						continue;
2949 
2950 					break;
2951 				}
2952 			}
2953 			rPar.Get(0)->PutString( aPath );
2954 #endif
2955 		}
2956 	}
2957 }
2958 
2959 
2960 RTLFUNC(GetAttr)
2961 {
2962     (void)pBasic;
2963     (void)bWrite;
2964 
2965 	if ( rPar.Count() == 2 )
2966 	{
2967 		sal_Int16 nFlags = 0;
2968 
2969 		// In Windows, We want to use Windows API to get the file attributes
2970 		// for VBA interoperability.
2971 	#if defined( WNT )
2972 		if( SbiRuntime::isVBAEnabled() )
2973 		{
2974 			DirEntry aEntry( rPar.Get(1)->GetString() );
2975 			aEntry.ToAbs();
2976 
2977 			// #57064 Bei virtuellen URLs den Real-Path extrahieren
2978 			ByteString aByteStrFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() );
2979 			DWORD nRealFlags = GetFileAttributes (aByteStrFullPath.GetBuffer());
2980 			if (nRealFlags != 0xffffffff)
2981 			{
2982 				if (nRealFlags == FILE_ATTRIBUTE_NORMAL)
2983 					nRealFlags = 0;
2984 				nFlags = (sal_Int16) (nRealFlags);
2985 			}
2986 			else
2987 				StarBASIC::Error( SbERR_FILE_NOT_FOUND );
2988 
2989 			rPar.Get(0)->PutInteger( nFlags );
2990 
2991 			return;
2992 		}
2993 	#endif
2994 
2995 		// <-- UCB
2996 		if( hasUno() )
2997 		{
2998 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
2999 			if( xSFI.is() )
3000 			{
3001 				try
3002 				{
3003 					String aPath = getFullPath( rPar.Get(1)->GetString() );
3004 					sal_Bool bExists = sal_False;
3005 					try { bExists = xSFI->exists( aPath ); }
3006 					catch( Exception & ) {}
3007 					if( !bExists )
3008 					{
3009 						StarBASIC::Error( SbERR_FILE_NOT_FOUND );
3010 						return;
3011 					}
3012 
3013 					sal_Bool bReadOnly = xSFI->isReadOnly( aPath );
3014 					sal_Bool bHidden = xSFI->isHidden( aPath );
3015 					sal_Bool bDirectory = xSFI->isFolder( aPath );
3016 					if( bReadOnly )
3017 						nFlags |= 0x0001; // ATTR_READONLY
3018 					if( bHidden )
3019 						nFlags |= 0x0002; // ATTR_HIDDEN
3020 					if( bDirectory )
3021 						nFlags |= 0x0010; // ATTR_DIRECTORY
3022 				}
3023 				catch( Exception & )
3024 				{
3025 					StarBASIC::Error( ERRCODE_IO_GENERAL );
3026 				}
3027 			}
3028 		}
3029 		else
3030 		// --> UCB
3031 		{
3032 			DirectoryItem aItem;
3033 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetString() ), aItem );
3034 			FileStatus aFileStatus( FileStatusMask_Attributes | FileStatusMask_Type );
3035 			nRet = aItem.getFileStatus( aFileStatus );
3036 			sal_uInt64 nAttributes = aFileStatus.getAttributes();
3037 			sal_Bool bReadOnly = (nAttributes & Attribute_ReadOnly) != 0;
3038 
3039 			FileStatus::Type aType = aFileStatus.getFileType();
3040 			sal_Bool bDirectory = isFolder( aType );
3041 			if( bReadOnly )
3042 				nFlags |= 0x0001; // ATTR_READONLY
3043 			if( bDirectory )
3044 				nFlags |= 0x0010; // ATTR_DIRECTORY
3045 		}
3046 		rPar.Get(0)->PutInteger( nFlags );
3047 	}
3048 	else
3049 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3050 }
3051 
3052 
3053 RTLFUNC(FileDateTime)
3054 {
3055     (void)pBasic;
3056     (void)bWrite;
3057 
3058 	if ( rPar.Count() != 2 )
3059 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3060 	else
3061 	{
3062 		// <-- UCB
3063 		String aPath = rPar.Get(1)->GetString();
3064 		Time aTime;
3065 		Date aDate;
3066 		if( hasUno() )
3067 		{
3068 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
3069 			if( xSFI.is() )
3070 			{
3071 				try
3072 				{
3073 					com::sun::star::util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath );
3074 					aTime = Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds );
3075 					aDate = Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year );
3076 				}
3077 				catch( Exception & )
3078 				{
3079 					StarBASIC::Error( ERRCODE_IO_GENERAL );
3080 				}
3081 			}
3082 		}
3083 		else
3084 		// --> UCB
3085 		{
3086 #ifdef _OLD_FILE_IMPL
3087 			DirEntry aEntry( aPath );
3088 			FileStat aStat( aEntry );
3089 			aTime = Time( aStat.TimeModified() );
3090 			aDate = Date( aStat.DateModified() );
3091 #else
3092 			DirectoryItem aItem;
3093 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aPath ), aItem );
3094 			FileStatus aFileStatus( FileStatusMask_ModifyTime );
3095 		    nRet = aItem.getFileStatus( aFileStatus );
3096 		    TimeValue aTimeVal = aFileStatus.getModifyTime();
3097 			oslDateTime aDT;
3098 			osl_getDateTimeFromTimeValue( &aTimeVal, &aDT );
3099 
3100 			aTime = Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 10000000*aDT.NanoSeconds );
3101 			aDate = Date( aDT.Day, aDT.Month, aDT.Year );
3102 #endif
3103 		}
3104 
3105 		double fSerial = (double)GetDayDiff( aDate );
3106 		long nSeconds = aTime.GetHour();
3107 		nSeconds *= 3600;
3108 		nSeconds += aTime.GetMin() * 60;
3109 		nSeconds += aTime.GetSec();
3110 		double nDays = ((double)nSeconds) / (double)(24.0*3600.0);
3111 		fSerial += nDays;
3112 
3113 		Color* pCol;
3114 
3115 		// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
3116 		SvNumberFormatter* pFormatter = NULL;
3117 		sal_uInt32 nIndex;
3118 		if( pINST )
3119 		{
3120 			pFormatter = pINST->GetNumberFormatter();
3121 			nIndex = pINST->GetStdDateTimeIdx();
3122 		}
3123 		else
3124 		{
3125 			sal_uInt32 n;	// Dummy
3126 			SbiInstance::PrepareNumberFormatter( pFormatter, n, n, nIndex );
3127 		}
3128 
3129 		String aRes;
3130 		pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol );
3131 		rPar.Get(0)->PutString( aRes );
3132 
3133 		// #39629 pFormatter kann selbst angefordert sein
3134 		if( !pINST )
3135 			delete pFormatter;
3136 	}
3137 }
3138 
3139 
3140 RTLFUNC(EOF)
3141 {
3142     (void)pBasic;
3143     (void)bWrite;
3144 
3145 	// AB 08/16/2000: No changes for UCB
3146 	if ( rPar.Count() != 2 )
3147 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3148 	else
3149 	{
3150 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3151 		// nChannel--;  // macht MD beim Oeffnen auch nicht
3152 		SbiIoSystem* pIO = pINST->GetIoSystem();
3153 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3154 		if ( !pSbStrm )
3155 		{
3156 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3157 			return;
3158 		}
3159 		sal_Bool bIsEof;
3160 		SvStream* pSvStrm = pSbStrm->GetStrm();
3161 		if ( pSbStrm->IsText() )
3162 		{
3163 			char cBla;
3164 			(*pSvStrm) >> cBla;	// koennen wir noch ein Zeichen lesen
3165 			bIsEof = pSvStrm->IsEof();
3166 			if ( !bIsEof )
3167 				pSvStrm->SeekRel( -1 );
3168 		}
3169 		else
3170 			bIsEof = pSvStrm->IsEof();  // fuer binaerdateien!
3171 		rPar.Get(0)->PutBool( bIsEof );
3172 	}
3173 }
3174 
3175 RTLFUNC(FileAttr)
3176 {
3177     (void)pBasic;
3178     (void)bWrite;
3179 
3180 	// AB 08/16/2000: No changes for UCB
3181 
3182 	// #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von
3183 	// der Anpassung an virtuelle URLs nich betroffen, da sie nur auf bereits
3184 	// geoeffneten Dateien arbeitet und der Name hier keine Rolle spielt.
3185 
3186 	if ( rPar.Count() != 3 )
3187 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3188 	else
3189 	{
3190 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3191 //		nChannel--;
3192 		SbiIoSystem* pIO = pINST->GetIoSystem();
3193 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3194 		if ( !pSbStrm )
3195 		{
3196 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3197 			return;
3198 		}
3199 		sal_Int16 nRet;
3200 		if ( rPar.Get(2)->GetInteger() == 1 )
3201 			nRet = (sal_Int16)(pSbStrm->GetMode());
3202 		else
3203 			nRet = 0; // System file handle not supported
3204 
3205 		rPar.Get(0)->PutInteger( nRet );
3206 	}
3207 }
3208 RTLFUNC(Loc)
3209 {
3210     (void)pBasic;
3211     (void)bWrite;
3212 
3213 	// AB 08/16/2000: No changes for UCB
3214 	if ( rPar.Count() != 2 )
3215 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3216 	else
3217 	{
3218 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3219 		SbiIoSystem* pIO = pINST->GetIoSystem();
3220 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3221 		if ( !pSbStrm )
3222 		{
3223 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3224 			return;
3225 		}
3226 		SvStream* pSvStrm = pSbStrm->GetStrm();
3227 		sal_uIntPtr nPos;
3228 		if( pSbStrm->IsRandom())
3229 		{
3230 			short nBlockLen = pSbStrm->GetBlockLen();
3231 			nPos = nBlockLen ? (pSvStrm->Tell() / nBlockLen) : 0;
3232 			nPos++; // Blockpositionen beginnen bei 1
3233 		}
3234 		else if ( pSbStrm->IsText() )
3235 			nPos = pSbStrm->GetLine();
3236 		else if( pSbStrm->IsBinary() )
3237 			nPos = pSvStrm->Tell();
3238 		else if ( pSbStrm->IsSeq() )
3239 			nPos = ( pSvStrm->Tell()+1 ) / 128;
3240 		else
3241 			nPos = pSvStrm->Tell();
3242 		rPar.Get(0)->PutLong( (sal_Int32)nPos );
3243 	}
3244 }
3245 
3246 RTLFUNC(Lof)
3247 {
3248     (void)pBasic;
3249     (void)bWrite;
3250 
3251 	// AB 08/16/2000: No changes for UCB
3252 	if ( rPar.Count() != 2 )
3253 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3254 	else
3255 	{
3256 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3257 		SbiIoSystem* pIO = pINST->GetIoSystem();
3258 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3259 		if ( !pSbStrm )
3260 		{
3261 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3262 			return;
3263 		}
3264 		SvStream* pSvStrm = pSbStrm->GetStrm();
3265 		sal_uIntPtr nOldPos = pSvStrm->Tell();
3266 		sal_uIntPtr nLen = pSvStrm->Seek( STREAM_SEEK_TO_END );
3267 		pSvStrm->Seek( nOldPos );
3268 		rPar.Get(0)->PutLong( (sal_Int32)nLen );
3269 	}
3270 }
3271 
3272 
3273 RTLFUNC(Seek)
3274 {
3275     (void)pBasic;
3276     (void)bWrite;
3277 
3278 	// AB 08/16/2000: No changes for UCB
3279 	int nArgs = (int)rPar.Count();
3280 	if ( nArgs < 2 || nArgs > 3 )
3281 	{
3282 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3283 		return;
3284 	}
3285 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3286 //	nChannel--;
3287 	SbiIoSystem* pIO = pINST->GetIoSystem();
3288 	SbiStream* pSbStrm = pIO->GetStream( nChannel );
3289 	if ( !pSbStrm )
3290 	{
3291 		StarBASIC::Error( SbERR_BAD_CHANNEL );
3292 		return;
3293 	}
3294 	SvStream* pStrm = pSbStrm->GetStrm();
3295 
3296 	if ( nArgs == 2 )   // Seek-Function
3297 	{
3298 		sal_uIntPtr nPos = pStrm->Tell();
3299 		if( pSbStrm->IsRandom() )
3300 			nPos = nPos / pSbStrm->GetBlockLen();
3301 		nPos++;	// Basic zaehlt ab 1
3302 		rPar.Get(0)->PutLong( (sal_Int32)nPos );
3303 	}
3304 	else                // Seek-Statement
3305 	{
3306 		sal_Int32 nPos = rPar.Get(2)->GetLong();
3307 		if ( nPos < 1 )
3308 		{
3309 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
3310 			return;
3311 		}
3312 		nPos--; // Basic zaehlt ab 1, SvStreams zaehlen ab 0
3313 		pSbStrm->SetExpandOnWriteTo( 0 );
3314 		if ( pSbStrm->IsRandom() )
3315 			nPos *= pSbStrm->GetBlockLen();
3316 		pStrm->Seek( (sal_uIntPtr)nPos );
3317 		pSbStrm->SetExpandOnWriteTo( nPos );
3318 	}
3319 }
3320 
3321 RTLFUNC(Format)
3322 {
3323     (void)pBasic;
3324     (void)bWrite;
3325 
3326 	sal_uInt16 nArgCount = (sal_uInt16)rPar.Count();
3327 	if ( nArgCount < 2 || nArgCount > 3 )
3328 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3329 	else
3330 	{
3331 		String aResult;
3332 		if( nArgCount == 2 )
3333 			rPar.Get(1)->Format( aResult );
3334 		else
3335 		{
3336 			String aFmt( rPar.Get(2)->GetString() );
3337 		    rPar.Get(1)->Format( aResult, &aFmt );
3338 		}
3339 		rPar.Get(0)->PutString( aResult );
3340 	}
3341 }
3342 
3343 RTLFUNC(Randomize)
3344 {
3345     (void)pBasic;
3346     (void)bWrite;
3347 
3348 	if ( rPar.Count() > 2 )
3349 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3350 	sal_Int16 nSeed;
3351 	if( rPar.Count() == 2 )
3352 		nSeed = (sal_Int16)rPar.Get(1)->GetInteger();
3353 	else
3354 		nSeed = (sal_Int16)rand();
3355 	srand( nSeed );
3356 }
3357 
3358 RTLFUNC(Rnd)
3359 {
3360     (void)pBasic;
3361     (void)bWrite;
3362 
3363 	if ( rPar.Count() > 2 )
3364 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3365 	else
3366 	{
3367 		double nRand = (double)rand();
3368 		nRand = ( nRand / (double)RAND_MAX );
3369 		rPar.Get(0)->PutDouble( nRand );
3370 	}
3371 }
3372 
3373 
3374 //
3375 //  Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = sal_False ]]])
3376 //
3377 //  WindowStyles (VBA-kompatibel):
3378 //      2 == Minimized
3379 //	    3 == Maximized
3380 //     10 == Full-Screen (Textmodus-Anwendungen OS/2, WIN95, WNT)
3381 //
3382 // !!!HACK der WindowStyle wird im Creator an Application::StartApp
3383 //         uebergeben. Format: "xxxx2"
3384 //
3385 
3386 
3387 RTLFUNC(Shell)
3388 {
3389     (void)pBasic;
3390     (void)bWrite;
3391 
3392 	// No shell command for "virtual" portal users
3393 	if( needSecurityRestrictions() )
3394 	{
3395 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3396 		return;
3397 	}
3398 
3399 	sal_uIntPtr nArgCount = rPar.Count();
3400 	if ( nArgCount < 2 || nArgCount > 5 )
3401 	{
3402 		rPar.Get(0)->PutLong(0);
3403 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3404 	}
3405 	else
3406 	{
3407 		sal_uInt16 nOptions = vos::OProcess::TOption_SearchPath|
3408 						  vos::OProcess::TOption_Detached;
3409 		String aCmdLine = rPar.Get(1)->GetString();
3410 		// Zusaetzliche Parameter anhaengen, es muss eh alles geparsed werden
3411 		if( nArgCount >= 4 )
3412 		{
3413 			aCmdLine.AppendAscii( " " );
3414 			aCmdLine += rPar.Get(3)->GetString();
3415 		}
3416 		else if( !aCmdLine.Len() )
3417 		{
3418 			// Spezial-Behandlung (leere Liste) vermeiden
3419 			aCmdLine.AppendAscii( " " );
3420 		}
3421 		sal_uInt16 nLen = aCmdLine.Len();
3422 
3423 		// #55735 Wenn Parameter dabei sind, muessen die abgetrennt werden
3424 		// #72471 Auch die einzelnen Parameter trennen
3425 		std::list<String> aTokenList;
3426 		String aToken;
3427 		sal_uInt16 i = 0;
3428 		sal_Unicode c;
3429 		while( i < nLen )
3430 		{
3431 			// Spaces weg
3432             for ( ;; ++i )
3433             {
3434                 c = aCmdLine.GetBuffer()[ i ];
3435                 if ( c != ' ' && c != '\t' )
3436                     break;
3437             }
3438 
3439 			if( c == '\"' || c == '\'' )
3440 			{
3441 				sal_uInt16 iFoundPos = aCmdLine.Search( c, i + 1 );
3442 
3443 				// Wenn nichts gefunden wurde, Rest kopieren
3444 				if( iFoundPos == STRING_NOTFOUND )
3445 				{
3446 					aToken = aCmdLine.Copy( i, STRING_LEN );
3447 					i = nLen;
3448 				}
3449 				else
3450 				{
3451 					aToken = aCmdLine.Copy( i + 1, (iFoundPos - i - 1) );
3452 					i = iFoundPos + 1;
3453 				}
3454 			}
3455 			else
3456 			{
3457 				sal_uInt16 iFoundSpacePos = aCmdLine.Search( ' ', i );
3458 				sal_uInt16 iFoundTabPos = aCmdLine.Search( '\t', i );
3459 				sal_uInt16 iFoundPos = Min( iFoundSpacePos, iFoundTabPos );
3460 
3461 				// Wenn nichts gefunden wurde, Rest kopieren
3462 				if( iFoundPos == STRING_NOTFOUND )
3463 				{
3464 					aToken = aCmdLine.Copy( i, STRING_LEN );
3465 					i = nLen;
3466 				}
3467 				else
3468 				{
3469 					aToken = aCmdLine.Copy( i, (iFoundPos - i) );
3470 					i = iFoundPos;
3471 				}
3472 			}
3473 
3474 			// In die Liste uebernehmen
3475 			aTokenList.push_back( aToken );
3476 		}
3477 		// #55735 / #72471 Ende
3478 
3479 		sal_Int16 nWinStyle = 0;
3480 		if( nArgCount >= 3 )
3481 		{
3482 			nWinStyle = rPar.Get(2)->GetInteger();
3483 			switch( nWinStyle )
3484 			{
3485 				case 2:
3486 					nOptions |= vos::OProcess::TOption_Minimized;
3487 					break;
3488 				case 3:
3489 					nOptions |= vos::OProcess::TOption_Maximized;
3490 					break;
3491 				case 10:
3492 					nOptions |= vos::OProcess::TOption_FullScreen;
3493 					break;
3494 			}
3495 
3496 			sal_Bool bSync = sal_False;
3497 			if( nArgCount >= 5 )
3498 				bSync = rPar.Get(4)->GetBool();
3499 			if( bSync )
3500 				nOptions |= vos::OProcess::TOption_Wait;
3501 		}
3502 		vos::OProcess::TProcessOption eOptions =
3503 			(vos::OProcess::TProcessOption)nOptions;
3504 
3505 
3506 		// #72471 Parameter aufbereiten
3507 		std::list<String>::const_iterator iter = aTokenList.begin();
3508 		const String& rStr = *iter;
3509 		::rtl::OUString aOUStrProg( rStr.GetBuffer(), rStr.Len() );
3510 		String aOUStrProgUNC = getFullPathUNC( aOUStrProg );
3511 
3512 		iter++;
3513 
3514 		sal_uInt16 nParamCount = sal::static_int_cast< sal_uInt16 >(
3515             aTokenList.size() - 1 );
3516 		::rtl::OUString* pArgumentList = NULL;
3517 		//const char** pParamList = NULL;
3518 		if( nParamCount )
3519 		{
3520 			pArgumentList = new ::rtl::OUString[ nParamCount ];
3521 			//pParamList = new const char*[ nParamCount ];
3522 			sal_uInt16 iList = 0;
3523 			while( iter != aTokenList.end() )
3524 			{
3525 				const String& rParamStr = (*iter);
3526 				pArgumentList[iList++] = ::rtl::OUString( rParamStr.GetBuffer(), rParamStr.Len() );
3527 				//pParamList[iList++] = (*iter).GetStr();
3528 				iter++;
3529 			}
3530 		}
3531 
3532 		//const char* pParams = aParams.Len() ? aParams.GetStr() : 0;
3533 		vos::OProcess* pApp;
3534 		pApp = new vos::OProcess( aOUStrProgUNC );
3535 		sal_Bool bSucc;
3536 		if( nParamCount == 0 )
3537 		{
3538 			bSucc = pApp->execute( eOptions ) == vos::OProcess::E_None;
3539 		}
3540 		else
3541 		{
3542 		    vos::OArgumentList aArgList( pArgumentList, nParamCount );
3543 			bSucc = pApp->execute( eOptions, aArgList ) == vos::OProcess::E_None;
3544 		}
3545 
3546 		/*
3547 		if( nParamCount == 0 )
3548 			pApp = new vos::OProcess( pProg );
3549 		else
3550 			pApp = new vos::OProcess( pProg, pParamList, nParamCount );
3551 		sal_Bool bSucc = pApp->execute( eOptions ) == vos::OProcess::E_None;
3552 		*/
3553 
3554 		delete pApp;
3555 		delete[] pArgumentList;
3556 		if( !bSucc )
3557 			StarBASIC::Error( SbERR_FILE_NOT_FOUND );
3558 		else
3559 			rPar.Get(0)->PutLong( 0 );
3560 	}
3561 }
3562 
3563 RTLFUNC(VarType)
3564 {
3565     (void)pBasic;
3566     (void)bWrite;
3567 
3568 	if ( rPar.Count() != 2 )
3569 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3570 	else
3571 	{
3572 		SbxDataType eType = rPar.Get(1)->GetType();
3573 		rPar.Get(0)->PutInteger( (sal_Int16)eType );
3574 	}
3575 }
3576 
3577 // Exported function
3578 String getBasicTypeName( SbxDataType eType )
3579 {
3580 	static const char* pTypeNames[] =
3581 	{
3582 		"Empty",            // SbxEMPTY
3583 		"Null",             // SbxNULL
3584 		"Integer",          // SbxINTEGER
3585 		"Long",             // SbxLONG
3586 		"Single",           // SbxSINGLE
3587 		"Double",           // SbxDOUBLE
3588 		"Currency",         // SbxCURRENCY
3589 		"Date",             // SbxDATE
3590 		"String",           // SbxSTRING
3591 		"Object",           // SbxOBJECT
3592 		"Error",            // SbxERROR
3593 		"Boolean",          // SbxBOOL
3594 		"Variant",          // SbxVARIANT
3595 		"DataObject",       // SbxDATAOBJECT
3596 		"Unknown Type",     //
3597 		"Unknown Type",     //
3598 		"Char",             // SbxCHAR
3599 		"Byte",             // SbxBYTE
3600 		"UShort",           // SbxUSHORT
3601 		"ULong",            // SbxULONG
3602 		"Long64",           // SbxLONG64
3603 		"ULong64",          // SbxULONG64
3604 		"Int",              // SbxINT
3605 		"UInt",             // SbxUINT
3606 		"Void",             // SbxVOID
3607 		"HResult",          // SbxHRESULT
3608 		"Pointer",          // SbxPOINTER
3609 		"DimArray",         // SbxDIMARRAY
3610 		"CArray",           // SbxCARRAY
3611 		"Userdef",          // SbxUSERDEF
3612 		"Lpstr",            // SbxLPSTR
3613 		"Lpwstr",           // SbxLPWSTR
3614 		"Unknown Type",     // SbxCoreSTRING
3615 		"WString",          // SbxWSTRING
3616 		"WChar",            // SbxWCHAR
3617 		"Int64",            // SbxSALINT64
3618 		"UInt64",           // SbxSALUINT64
3619 		"Decimal",          // SbxDECIMAL
3620 	};
3621 
3622 	int nPos = ((int)eType) & 0x0FFF;
3623 	sal_uInt16 nTypeNameCount = sizeof( pTypeNames ) / sizeof( char* );
3624 	if ( nPos < 0 || nPos >= nTypeNameCount )
3625 		nPos = nTypeNameCount - 1;
3626 	String aRetStr = String::CreateFromAscii( pTypeNames[nPos] );
3627 	return aRetStr;
3628 }
3629 
3630 RTLFUNC(TypeName)
3631 {
3632     (void)pBasic;
3633     (void)bWrite;
3634 
3635 	if ( rPar.Count() != 2 )
3636 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3637 	else
3638 	{
3639 		SbxDataType eType = rPar.Get(1)->GetType();
3640 		sal_Bool bIsArray = ( ( eType & SbxARRAY ) != 0 );
3641 		String aRetStr = getBasicTypeName( eType );
3642 		if( bIsArray )
3643 			aRetStr.AppendAscii( "()" );
3644 		rPar.Get(0)->PutString( aRetStr );
3645 	}
3646 }
3647 
3648 RTLFUNC(Len)
3649 {
3650     (void)pBasic;
3651     (void)bWrite;
3652 
3653 	if ( rPar.Count() != 2 )
3654 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3655 	else
3656 	{
3657 		const String& rStr = rPar.Get(1)->GetString();
3658 		rPar.Get(0)->PutLong( (sal_Int32)rStr.Len() );
3659 	}
3660 }
3661 
3662 RTLFUNC(DDEInitiate)
3663 {
3664     (void)pBasic;
3665     (void)bWrite;
3666 
3667 	// No DDE for "virtual" portal users
3668 	if( needSecurityRestrictions() )
3669 	{
3670 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3671 		return;
3672 	}
3673 
3674 	int nArgs = (int)rPar.Count();
3675 	if ( nArgs != 3 )
3676 	{
3677 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3678 		return;
3679 	}
3680 	const String& rApp = rPar.Get(1)->GetString();
3681 	const String& rTopic = rPar.Get(2)->GetString();
3682 
3683 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3684 	sal_Int16 nChannel;
3685 	SbError nDdeErr = pDDE->Initiate( rApp, rTopic, nChannel );
3686 	if( nDdeErr )
3687 		StarBASIC::Error( nDdeErr );
3688 	else
3689 		rPar.Get(0)->PutInteger( nChannel );
3690 }
3691 
3692 RTLFUNC(DDETerminate)
3693 {
3694     (void)pBasic;
3695     (void)bWrite;
3696 
3697 	// No DDE for "virtual" portal users
3698 	if( needSecurityRestrictions() )
3699 	{
3700 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3701 		return;
3702 	}
3703 
3704 	rPar.Get(0)->PutEmpty();
3705 	int nArgs = (int)rPar.Count();
3706 	if ( nArgs != 2 )
3707 	{
3708 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3709 		return;
3710 	}
3711 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3712 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3713 	SbError nDdeErr = pDDE->Terminate( nChannel );
3714 	if( nDdeErr )
3715 		StarBASIC::Error( nDdeErr );
3716 }
3717 
3718 RTLFUNC(DDETerminateAll)
3719 {
3720     (void)pBasic;
3721     (void)bWrite;
3722 
3723 	// No DDE for "virtual" portal users
3724 	if( needSecurityRestrictions() )
3725 	{
3726 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3727 		return;
3728 	}
3729 
3730 	rPar.Get(0)->PutEmpty();
3731 	int nArgs = (int)rPar.Count();
3732 	if ( nArgs != 1 )
3733 	{
3734 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3735 		return;
3736 	}
3737 
3738 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3739 	SbError nDdeErr = pDDE->TerminateAll();
3740 	if( nDdeErr )
3741 		StarBASIC::Error( nDdeErr );
3742 
3743 }
3744 
3745 RTLFUNC(DDERequest)
3746 {
3747     (void)pBasic;
3748     (void)bWrite;
3749 
3750 	// No DDE for "virtual" portal users
3751 	if( needSecurityRestrictions() )
3752 	{
3753 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3754 		return;
3755 	}
3756 
3757 	int nArgs = (int)rPar.Count();
3758 	if ( nArgs != 3 )
3759 	{
3760 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3761 		return;
3762 	}
3763 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3764 	const String& rItem = rPar.Get(2)->GetString();
3765 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3766 	String aResult;
3767 	SbError nDdeErr = pDDE->Request( nChannel, rItem, aResult );
3768 	if( nDdeErr )
3769 		StarBASIC::Error( nDdeErr );
3770 	else
3771 		rPar.Get(0)->PutString( aResult );
3772 }
3773 
3774 RTLFUNC(DDEExecute)
3775 {
3776     (void)pBasic;
3777     (void)bWrite;
3778 
3779 	// No DDE for "virtual" portal users
3780 	if( needSecurityRestrictions() )
3781 	{
3782 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3783 		return;
3784 	}
3785 
3786 	rPar.Get(0)->PutEmpty();
3787 	int nArgs = (int)rPar.Count();
3788 	if ( nArgs != 3 )
3789 	{
3790 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3791 		return;
3792 	}
3793 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3794 	const String& rCommand = rPar.Get(2)->GetString();
3795 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3796 	SbError nDdeErr = pDDE->Execute( nChannel, rCommand );
3797 	if( nDdeErr )
3798 		StarBASIC::Error( nDdeErr );
3799 }
3800 
3801 RTLFUNC(DDEPoke)
3802 {
3803     (void)pBasic;
3804     (void)bWrite;
3805 
3806 	// No DDE for "virtual" portal users
3807 	if( needSecurityRestrictions() )
3808 	{
3809 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3810 		return;
3811 	}
3812 
3813 	rPar.Get(0)->PutEmpty();
3814 	int nArgs = (int)rPar.Count();
3815 	if ( nArgs != 4 )
3816 	{
3817 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3818 		return;
3819 	}
3820 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3821 	const String& rItem = rPar.Get(2)->GetString();
3822 	const String& rData = rPar.Get(3)->GetString();
3823 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3824 	SbError nDdeErr = pDDE->Poke( nChannel, rItem, rData );
3825 	if( nDdeErr )
3826 		StarBASIC::Error( nDdeErr );
3827 }
3828 
3829 
3830 RTLFUNC(FreeFile)
3831 {
3832     (void)pBasic;
3833     (void)bWrite;
3834 
3835 	if ( rPar.Count() != 1 )
3836 	{
3837 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3838 		return;
3839 	}
3840 	SbiIoSystem* pIO = pINST->GetIoSystem();
3841 	short nChannel = 1;
3842 	while( nChannel < CHANNELS )
3843 	{
3844 		SbiStream* pStrm = pIO->GetStream( nChannel );
3845 		if( !pStrm )
3846 		{
3847 			rPar.Get(0)->PutInteger( nChannel );
3848 			return;
3849 		}
3850 		nChannel++;
3851 	}
3852 	StarBASIC::Error( SbERR_TOO_MANY_FILES );
3853 }
3854 
3855 RTLFUNC(LBound)
3856 {
3857     (void)pBasic;
3858     (void)bWrite;
3859 
3860 	sal_uInt16 nParCount = rPar.Count();
3861 	if ( nParCount != 3 && nParCount != 2 )
3862 	{
3863 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3864 		return;
3865 	}
3866 	SbxBase* pParObj = rPar.Get(1)->GetObject();
3867 	SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
3868 	if( pArr )
3869 	{
3870 		sal_Int32 nLower, nUpper;
3871 		short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1;
3872 		if( !pArr->GetDim32( nDim, nLower, nUpper ) )
3873 			StarBASIC::Error( SbERR_OUT_OF_RANGE );
3874 		else
3875 			rPar.Get(0)->PutLong( nLower );
3876 	}
3877 	else
3878 		StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
3879 }
3880 
3881 RTLFUNC(UBound)
3882 {
3883     (void)pBasic;
3884     (void)bWrite;
3885 
3886 	sal_uInt16 nParCount = rPar.Count();
3887 	if ( nParCount != 3 && nParCount != 2 )
3888 	{
3889 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3890 		return;
3891 	}
3892 
3893 	SbxBase* pParObj = rPar.Get(1)->GetObject();
3894 	SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
3895 	if( pArr )
3896 	{
3897 		sal_Int32 nLower, nUpper;
3898 		short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1;
3899 		if( !pArr->GetDim32( nDim, nLower, nUpper ) )
3900 			StarBASIC::Error( SbERR_OUT_OF_RANGE );
3901 		else
3902 			rPar.Get(0)->PutLong( nUpper );
3903 	}
3904 	else
3905 		StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
3906 }
3907 
3908 RTLFUNC(RGB)
3909 {
3910     (void)pBasic;
3911     (void)bWrite;
3912 
3913 	if ( rPar.Count() != 4 )
3914 	{
3915 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3916 		return;
3917 	}
3918 
3919 	sal_uIntPtr nRed	 = rPar.Get(1)->GetInteger() & 0xFF;
3920 	sal_uIntPtr nGreen = rPar.Get(2)->GetInteger() & 0xFF;
3921 	sal_uIntPtr nBlue  = rPar.Get(3)->GetInteger() & 0xFF;
3922 	sal_uIntPtr nRGB;
3923 
3924 	SbiInstance* pInst = pINST;
3925 	bool bCompatibility = ( pInst && pInst->IsCompatibility() );
3926 	if( bCompatibility )
3927 	{
3928 		nRGB   = (nBlue << 16) | (nGreen << 8) | nRed;
3929 	}
3930 	else
3931 	{
3932 		nRGB   = (nRed << 16) | (nGreen << 8) | nBlue;
3933 	}
3934 	rPar.Get(0)->PutLong( nRGB );
3935 }
3936 
3937 RTLFUNC(QBColor)
3938 {
3939     (void)pBasic;
3940     (void)bWrite;
3941 
3942 	static const sal_Int32 pRGB[] =
3943 	{
3944 		0x000000,
3945 		0x800000,
3946 		0x008000,
3947 		0x808000,
3948 		0x000080,
3949 		0x800080,
3950 		0x008080,
3951 		0xC0C0C0,
3952 		0x808080,
3953 		0xFF0000,
3954 		0x00FF00,
3955 		0xFFFF00,
3956 		0x0000FF,
3957 		0xFF00FF,
3958 		0x00FFFF,
3959 		0xFFFFFF,
3960 	};
3961 
3962 	if ( rPar.Count() != 2 )
3963 	{
3964 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3965 		return;
3966 	}
3967 
3968 	sal_Int16 nCol = rPar.Get(1)->GetInteger();
3969 	if( nCol < 0 || nCol > 15 )
3970 	{
3971 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3972 		return;
3973 	}
3974 	sal_Int32 nRGB = pRGB[ nCol ];
3975 	rPar.Get(0)->PutLong( nRGB );
3976 }
3977 
3978 // StrConv(string, conversion, LCID)
3979 RTLFUNC(StrConv)
3980 {
3981     (void)pBasic;
3982     (void)bWrite;
3983 
3984 	sal_uIntPtr nArgCount = rPar.Count()-1;
3985 	if( nArgCount < 2 || nArgCount > 3 )
3986 	{
3987 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3988 		return;
3989 	}
3990 
3991 	String aOldStr = rPar.Get(1)->GetString();
3992 	sal_Int32 nConversion = rPar.Get(2)->GetLong();
3993 
3994 	sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
3995 	if( nArgCount == 3 )
3996 	{
3997 		// LCID not supported now
3998 		//nLanguage = rPar.Get(3)->GetInteger();
3999 	}
4000 
4001 	sal_uInt16 nOldLen = aOldStr.Len();
4002 	if( nOldLen == 0 )
4003 	{
4004 		// null string,return
4005 		rPar.Get(0)->PutString(aOldStr);
4006 		return;
4007 	}
4008 
4009 	sal_Int32 nType = 0;
4010 	if ( (nConversion & 0x03) == 3 ) //  vbProperCase
4011 	{
4012 		CharClass& rCharClass = GetCharClass();
4013 		aOldStr = rCharClass.toTitle( aOldStr.ToLowerAscii(), 0, nOldLen );
4014 	}
4015 	else if ( (nConversion & 0x01) == 1 ) // vbUpperCase
4016 		nType |= ::com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE;
4017 	else if ( (nConversion & 0x02) == 2 ) // vbLowerCase
4018 		nType |= ::com::sun::star::i18n::TransliterationModules_UPPERCASE_LOWERCASE;
4019 
4020 	if ( (nConversion & 0x04) == 4 ) // vbWide
4021 		nType |= ::com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
4022 	else if ( (nConversion & 0x08) == 8 ) // vbNarrow
4023 		nType |= ::com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
4024 
4025 	if ( (nConversion & 0x10) == 16) // vbKatakana
4026 		nType |= ::com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
4027 	else if ( (nConversion & 0x20) == 32 ) // vbHiragana
4028 		nType |= ::com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA;
4029 
4030 	String aNewStr( aOldStr );
4031 	if( nType != 0 )
4032 	{
4033 		com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
4034     	::utl::TransliterationWrapper aTransliterationWrapper( xSMgr,nType );
4035 		com::sun::star::uno::Sequence<sal_Int32> aOffsets;
4036 		aTransliterationWrapper.loadModuleIfNeeded( nLanguage );
4037 		aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
4038 	}
4039 
4040 	if ( (nConversion & 0x40) == 64 ) // vbUnicode
4041 	{
4042 		// convert the string to byte string, preserving unicode (2 bytes per character)
4043 		sal_uInt16 nSize = aNewStr.Len()*2;
4044 		const sal_Unicode* pSrc = aNewStr.GetBuffer();
4045 		sal_Char* pChar = new sal_Char[nSize+1];
4046 		for( sal_uInt16 i=0; i < nSize; i++ )
4047 		{
4048 			pChar[i] = static_cast< sal_Char >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
4049 			if( i%2 )
4050 				pSrc++;
4051 		}
4052 		pChar[nSize] = '\0';
4053 		::rtl::OString aOStr(pChar);
4054 
4055 		// there is no concept about default codepage in unix. so it is incorrectly in unix
4056 		::rtl::OUString aOUStr = ::rtl::OStringToOUString(aOStr, osl_getThreadTextEncoding());
4057 		aNewStr = String(aOUStr);
4058 		rPar.Get(0)->PutString( aNewStr );
4059 		return;
4060 	}
4061 	else if ( (nConversion & 0x80) == 128 ) // vbFromUnicode
4062 	{
4063 		::rtl::OUString aOUStr(aNewStr);
4064 		// there is no concept about default codepage in unix. so it is incorrectly in unix
4065 		::rtl::OString aOStr = ::rtl::OUStringToOString(aNewStr,osl_getThreadTextEncoding());
4066 		const sal_Char* pChar = aOStr.getStr();
4067 		sal_uInt16 nArraySize = static_cast< sal_uInt16 >( aOStr.getLength() );
4068 		SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
4069 		bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
4070 		if(nArraySize)
4071 		{
4072 			if( bIncIndex )
4073 				pArray->AddDim( 1, nArraySize );
4074 			else
4075 				pArray->AddDim( 0, nArraySize-1 );
4076 		}
4077 		else
4078 		{
4079 			pArray->unoAddDim( 0, -1 );
4080 		}
4081 
4082 		for( sal_uInt16	i=0; i< nArraySize; i++)
4083 		{
4084 			SbxVariable* pNew = new SbxVariable( SbxBYTE );
4085 			pNew->PutByte(*pChar);
4086 			pChar++;
4087 			pNew->SetFlag( SBX_WRITE );
4088 			short index = i;
4089 			if( bIncIndex )
4090 				++index;
4091 			pArray->Put( pNew, &index );
4092 		}
4093 
4094 		SbxVariableRef refVar = rPar.Get(0);
4095 		sal_uInt16 nFlags = refVar->GetFlags();
4096 		refVar->ResetFlag( SBX_FIXED );
4097 		refVar->PutObject( pArray );
4098 		refVar->SetFlags( nFlags );
4099 	    refVar->SetParameters( NULL );
4100    		return;
4101 	}
4102 
4103 	rPar.Get(0)->PutString(aNewStr);
4104 }
4105 
4106 
4107 RTLFUNC(Beep)
4108 {
4109     (void)pBasic;
4110     (void)bWrite;
4111 
4112 	if ( rPar.Count() != 1 )
4113 	{
4114 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4115 		return;
4116 	}
4117 	Sound::Beep();
4118 }
4119 
4120 RTLFUNC(Load)
4121 {
4122     (void)pBasic;
4123     (void)bWrite;
4124 
4125 	if( rPar.Count() != 2 )
4126 	{
4127 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4128 		return;
4129 	}
4130 
4131 	// Diesen Call einfach an das Object weiterreichen
4132 	SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
4133 	if ( pObj )
4134 	{
4135 		if( pObj->IsA( TYPE( SbUserFormModule ) ) )
4136 		{
4137 			((SbUserFormModule*)pObj)->Load();
4138 		}
4139 		else if( pObj->IsA( TYPE( SbxObject ) ) )
4140 		{
4141 			SbxVariable* pVar = ((SbxObject*)pObj)->
4142 				Find( String( RTL_CONSTASCII_USTRINGPARAM("Load") ), SbxCLASS_METHOD );
4143 			if( pVar )
4144 				pVar->GetInteger();
4145 		}
4146 	}
4147 }
4148 
4149 RTLFUNC(Unload)
4150 {
4151     (void)pBasic;
4152     (void)bWrite;
4153 
4154 	rPar.Get(0)->PutEmpty();
4155 	if( rPar.Count() != 2 )
4156 	{
4157 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4158 		return;
4159 	}
4160 
4161 	// Diesen Call einfach an das Object weitereichen
4162 	SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
4163 	if ( pObj )
4164 	{
4165 		if( pObj->IsA( TYPE( SbUserFormModule ) ) )
4166 		{
4167 			SbUserFormModule* pFormModule = ( SbUserFormModule* )pObj;
4168 			pFormModule->Unload();
4169 		}
4170 		else if( pObj->IsA( TYPE( SbxObject ) ) )
4171 		{
4172 			SbxVariable* pVar = ((SbxObject*)pObj)->
4173 				Find( String( RTL_CONSTASCII_USTRINGPARAM("Unload") ), SbxCLASS_METHOD );
4174 			if( pVar )
4175 				pVar->GetInteger();
4176 		}
4177 	}
4178 }
4179 
4180 RTLFUNC(LoadPicture)
4181 {
4182     (void)pBasic;
4183     (void)bWrite;
4184 
4185 	if( rPar.Count() != 2 )
4186 	{
4187 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4188 		return;
4189 	}
4190 
4191 	String aFileURL = getFullPath( rPar.Get(1)->GetString() );
4192 	SvStream* pStream = utl::UcbStreamHelper::CreateStream( aFileURL, STREAM_READ );
4193 	if( pStream != NULL )
4194 	{
4195 		Bitmap aBmp;
4196 		*pStream >> aBmp;
4197 		Graphic aGraphic( aBmp );
4198 
4199 		SbxObjectRef xRef = new SbStdPicture;
4200 		((SbStdPicture*)(SbxObject*)xRef)->SetGraphic( aGraphic );
4201 		rPar.Get(0)->PutObject( xRef );
4202 	}
4203 	delete pStream;
4204 }
4205 
4206 RTLFUNC(SavePicture)
4207 {
4208     (void)pBasic;
4209     (void)bWrite;
4210 
4211 	rPar.Get(0)->PutEmpty();
4212 	if( rPar.Count() != 3 )
4213 	{
4214 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4215 		return;
4216 	}
4217 
4218 	SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
4219 	if( pObj->IsA( TYPE( SbStdPicture ) ) )
4220 	{
4221 		SvFileStream aOStream( rPar.Get(2)->GetString(), STREAM_WRITE | STREAM_TRUNC );
4222 		Graphic aGraphic = ((SbStdPicture*)pObj)->GetGraphic();
4223 		aOStream << aGraphic;
4224 	}
4225 }
4226 
4227 
4228 //-----------------------------------------------------------------------------------------
4229 
4230 RTLFUNC(AboutStarBasic)
4231 {
4232     (void)pBasic;
4233     (void)bWrite;
4234     (void)rPar;
4235 }
4236 
4237 RTLFUNC(MsgBox)
4238 {
4239     (void)pBasic;
4240     (void)bWrite;
4241 
4242 	static const WinBits nStyleMap[] =
4243 	{
4244 		WB_OK,				// MB_OK
4245 		WB_OK_CANCEL,       // MB_OKCANCEL
4246 		WB_ABORT_RETRY_IGNORE,    // MB_ABORTRETRYIGNORE
4247 		WB_YES_NO_CANCEL,   // MB_YESNOCANCEL
4248 		WB_YES_NO,          // MB_YESNO
4249 		WB_RETRY_CANCEL     // MB_RETRYCANCEL
4250 	};
4251 	static const sal_Int16 nButtonMap[] =
4252 	{
4253 		2, // #define RET_CANCEL sal_False
4254 		1, // #define RET_OK     sal_True
4255 		6, // #define RET_YES    2
4256 		7, // #define RET_NO     3
4257 		4  // #define RET_RETRY  4
4258 	};
4259 
4260 
4261 	sal_uInt16 nArgCount = (sal_uInt16)rPar.Count();
4262 	if( nArgCount < 2 || nArgCount > 6 )
4263 	{
4264 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4265 		return;
4266 	}
4267 	WinBits nWinBits;
4268 	WinBits nType = 0; // MB_OK
4269 	if( nArgCount >= 3 )
4270 		nType = (WinBits)rPar.Get(2)->GetInteger();
4271 	WinBits nStyle = nType;
4272 	nStyle &= 15; // Bits 4-16 loeschen
4273 	if( nStyle > 5 )
4274 		nStyle = 0;
4275 
4276 	nWinBits = nStyleMap[ nStyle ];
4277 
4278 	WinBits nWinDefBits;
4279 	nWinDefBits = (WB_DEF_OK | WB_DEF_RETRY | WB_DEF_YES);
4280 	if( nType & 256 )
4281 	{
4282 		if( nStyle == 5 )
4283 			nWinDefBits = WB_DEF_CANCEL;
4284 		else if( nStyle == 2 )
4285 			nWinDefBits = WB_DEF_RETRY;
4286 		else
4287 			nWinDefBits = (WB_DEF_CANCEL | WB_DEF_RETRY | WB_DEF_NO);
4288 	}
4289 	else if( nType & 512 )
4290 	{
4291 		if( nStyle == 2)
4292 			nWinDefBits = WB_DEF_IGNORE;
4293 		else
4294 			nWinDefBits = WB_DEF_CANCEL;
4295 	}
4296 	else if( nStyle == 2)
4297 		nWinDefBits = WB_DEF_CANCEL;
4298     nWinBits |= nWinDefBits;
4299 
4300 	String aMsg = rPar.Get(1)->GetString();
4301 	String aTitle;
4302 	if( nArgCount >= 4 )
4303 		aTitle = rPar.Get(3)->GetString();
4304 	else
4305 		aTitle = GetpApp()->GetAppName();
4306 
4307 	nType &= (16+32+64);
4308 	MessBox* pBox = 0;
4309 	Window* pParent = GetpApp()->GetDefDialogParent();
4310 	switch( nType )
4311 	{
4312 		case 16:
4313 			pBox = new ErrorBox( pParent, nWinBits, aMsg );
4314 			break;
4315 		case 32:
4316 			pBox = new QueryBox( pParent, nWinBits, aMsg );
4317 			break;
4318 		case 48:
4319 			pBox = new WarningBox( pParent, nWinBits, aMsg );
4320 			break;
4321 		case 64:
4322 			pBox = new InfoBox( pParent, aMsg );
4323 			break;
4324 		default:
4325 			pBox = new MessBox( pParent, nWinBits, aTitle, aMsg );
4326 	}
4327 	pBox->SetText( aTitle );
4328 	sal_uInt16 nRet = (sal_uInt16)pBox->Execute();
4329 	if( nRet == sal_True )
4330 		nRet = 1;
4331 
4332 	sal_Int16 nMappedRet;
4333 	if( nStyle == 2 )
4334 	{
4335 		nMappedRet = nRet;
4336 		if( nMappedRet == 0 )
4337 			nMappedRet = 3;	// Abort
4338 	}
4339 	else
4340 		nMappedRet = nButtonMap[ nRet ];
4341 
4342 	rPar.Get(0)->PutInteger( nMappedRet );
4343 	delete pBox;
4344 }
4345 
4346 RTLFUNC(SetAttr) // JSM
4347 {
4348     (void)pBasic;
4349     (void)bWrite;
4350 
4351 	rPar.Get(0)->PutEmpty();
4352 	if ( rPar.Count() == 3 )
4353 	{
4354 		String aStr = rPar.Get(1)->GetString();
4355 		sal_Int16 nFlags = rPar.Get(2)->GetInteger();
4356 
4357 		// <-- UCB
4358 		if( hasUno() )
4359 		{
4360 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
4361 			if( xSFI.is() )
4362 			{
4363 				try
4364 				{
4365 					sal_Bool bReadOnly = (nFlags & 0x0001) != 0; // ATTR_READONLY
4366 					xSFI->setReadOnly( aStr, bReadOnly );
4367 					sal_Bool bHidden   = (nFlags & 0x0002) != 0; // ATTR_HIDDEN
4368 					xSFI->setHidden( aStr, bHidden );
4369 				}
4370 				catch( Exception & )
4371 				{
4372 					StarBASIC::Error( ERRCODE_IO_GENERAL );
4373 				}
4374 			}
4375 		}
4376 		else
4377 		// --> UCB
4378 		{
4379 #ifdef _OLD_FILE_IMPL
4380 			// #57064 Bei virtuellen URLs den Real-Path extrahieren
4381 			DirEntry aEntry( aStr );
4382 			String aFile = aEntry.GetFull();
4383 			ByteString aByteFile( aFile, gsl_getSystemTextEncoding() );
4384 	#ifdef WNT
4385 			if (!SetFileAttributes (aByteFile.GetBuffer(),(DWORD)nFlags))
4386 				StarBASIC::Error(SbERR_FILE_NOT_FOUND);
4387 	#endif
4388 	#ifdef OS2
4389 			FILESTATUS3 aFileStatus;
4390 			APIRET rc = DosQueryPathInfo(aByteFile.GetBuffer(),1,
4391 										 &aFileStatus,sizeof(FILESTATUS3));
4392 			if (!rc)
4393 			{
4394 				if (aFileStatus.attrFile != nFlags)
4395 				{
4396 					aFileStatus.attrFile = nFlags;
4397 					rc = DosSetPathInfo(aFile.GetStr(),1,
4398 										&aFileStatus,sizeof(FILESTATUS3),0);
4399 					if (rc)
4400 						StarBASIC::Error( SbERR_FILE_NOT_FOUND );
4401 				}
4402 			}
4403 			else
4404 				StarBASIC::Error( SbERR_FILE_NOT_FOUND );
4405 	#endif
4406 #else
4407 			// Not implemented
4408 #endif
4409 		}
4410 	}
4411 	else
4412 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4413 }
4414 
4415 RTLFUNC(Reset)  // JSM
4416 {
4417     (void)pBasic;
4418     (void)bWrite;
4419     (void)rPar;
4420 
4421 	SbiIoSystem* pIO = pINST->GetIoSystem();
4422 	if (pIO)
4423 		pIO->CloseAll();
4424 }
4425 
4426 RTLFUNC(DumpAllObjects)
4427 {
4428     (void)pBasic;
4429     (void)bWrite;
4430 
4431 	sal_uInt16 nArgCount = (sal_uInt16)rPar.Count();
4432 	if( nArgCount < 2 || nArgCount > 3 )
4433 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4434 	else if( !pBasic )
4435 		StarBASIC::Error( SbERR_INTERNAL_ERROR );
4436 	else
4437 	{
4438 		SbxObject* p = pBasic;
4439 		while( p->GetParent() )
4440 			p = p->GetParent();
4441 		SvFileStream aStrm( rPar.Get( 1 )->GetString(),
4442 							STREAM_WRITE | STREAM_TRUNC );
4443 		p->Dump( aStrm, rPar.Get( 2 )->GetBool() );
4444 		aStrm.Close();
4445 		if( aStrm.GetError() != SVSTREAM_OK )
4446 			StarBASIC::Error( SbERR_IO_ERROR );
4447 	}
4448 }
4449 
4450 
4451 RTLFUNC(FileExists)
4452 {
4453     (void)pBasic;
4454     (void)bWrite;
4455 
4456 	if ( rPar.Count() == 2 )
4457 	{
4458 		String aStr = rPar.Get(1)->GetString();
4459 		sal_Bool bExists = sal_False;
4460 
4461 		// <-- UCB
4462 		if( hasUno() )
4463 		{
4464 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
4465 			if( xSFI.is() )
4466 			{
4467 				try
4468 				{
4469 					bExists = xSFI->exists( aStr );
4470 				}
4471 				catch( Exception & )
4472 				{
4473 					StarBASIC::Error( ERRCODE_IO_GENERAL );
4474 				}
4475 			}
4476 		}
4477 		else
4478 		// --> UCB
4479 		{
4480 #ifdef _OLD_FILE_IMPL
4481 			DirEntry aEntry( aStr );
4482 			bExists = aEntry.Exists();
4483 #else
4484 			DirectoryItem aItem;
4485 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem );
4486 			bExists = (nRet == FileBase::E_None);
4487 #endif
4488 		}
4489 		rPar.Get(0)->PutBool( bExists );
4490 	}
4491 	else
4492 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4493 }
4494 
4495 RTLFUNC(Partition)
4496 {
4497     (void)pBasic;
4498     (void)bWrite;
4499 
4500 	if ( rPar.Count() != 5 )
4501 	{
4502 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4503 		return;
4504 	}
4505 
4506 	sal_Int32 nNumber = rPar.Get(1)->GetLong();
4507 	sal_Int32 nStart = rPar.Get(2)->GetLong();
4508 	sal_Int32 nStop = rPar.Get(3)->GetLong();
4509 	sal_Int32 nInterval = rPar.Get(4)->GetLong();
4510 
4511 	if( nStart < 0 || nStop <= nStart || nInterval < 1 )
4512 	{
4513 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4514 		return;
4515 	}
4516 
4517 	// the Partition function inserts leading spaces before lowervalue and uppervalue
4518     // so that they both have the same number of characters as the string
4519     // representation of the value (Stop + 1). This ensures that if you use the output
4520     // of the Partition function with several values of Number, the resulting text
4521 	// will be handled properly during any subsequent sort operation.
4522 
4523 	// calculate the  maximun number of characters before lowervalue and uppervalue
4524 	::rtl::OUString aBeforeStart = ::rtl::OUString::valueOf( nStart - 1 );
4525 	::rtl::OUString aAfterStop = ::rtl::OUString::valueOf( nStop + 1 );
4526 	sal_Int32 nLen1 = aBeforeStart.getLength();
4527 	sal_Int32 nLen2 = aAfterStop.getLength();
4528 	sal_Int32 nLen = nLen1 >= nLen2 ? nLen1:nLen2;
4529 
4530 	::rtl::OUStringBuffer aRetStr( nLen * 2 + 1);
4531 	::rtl::OUString aLowerValue;
4532 	::rtl::OUString aUpperValue;
4533 	if( nNumber < nStart )
4534 	{
4535 		aUpperValue = aBeforeStart;
4536 	}
4537 	else if( nNumber > nStop )
4538 	{
4539 		aLowerValue = aAfterStop;
4540 	}
4541 	else
4542 	{
4543 		sal_Int32 nLowerValue = nNumber;
4544 		sal_Int32 nUpperValue = nLowerValue;
4545 		if( nInterval > 1 )
4546 		{
4547 			nLowerValue = ((( nNumber - nStart ) / nInterval ) * nInterval ) + nStart;
4548 			nUpperValue = nLowerValue + nInterval - 1;
4549 		}
4550 
4551 		aLowerValue = ::rtl::OUString::valueOf( nLowerValue );
4552 		aUpperValue = ::rtl::OUString::valueOf( nUpperValue );
4553 	}
4554 
4555 	nLen1 = aLowerValue.getLength();
4556 	nLen2 = aUpperValue.getLength();
4557 
4558 	if( nLen > nLen1 )
4559 	{
4560 		// appending the leading spaces for the lowervalue
4561 		for ( sal_Int32 i= (nLen - nLen1) ; i > 0; --i )
4562 			aRetStr.appendAscii(" ");
4563 	}
4564 	aRetStr.append( aLowerValue ).appendAscii(":");
4565 	if( nLen > nLen2 )
4566 	{
4567 		// appending the leading spaces for the uppervalue
4568 		for ( sal_Int32 i= (nLen - nLen2) ; i > 0; --i )
4569 			aRetStr.appendAscii(" ");
4570 	}
4571 	aRetStr.append( aUpperValue );
4572 	rPar.Get(0)->PutString( String(aRetStr.makeStringAndClear()) );
4573 }
4574