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