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