xref: /trunk/main/basic/source/runtime/methods.cxx (revision 710acb7f)
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 
FilterWhiteSpace(String & rStr)118 static void FilterWhiteSpace( String& rStr )
119 {
120 	rStr.EraseAllChars( ' ' );
121 	rStr.EraseAllChars( '\t' );
122 	rStr.EraseAllChars( '\n' );
123 	rStr.EraseAllChars( '\r' );
124 }
125 
GetDayDiff(const Date & rDate)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 
GetCharClass(void)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 
isFolder(FileStatus::Type aType)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
getFullPath(const String & aRelPath)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
implChDir(const String & aDir)181 void implChDir( const String& aDir )
182 {
183     (void)aDir;
184 	// TODO
185 }
186 
187 // Sets (virtual) current drive for UCB file access
implChDrive(const String & aDrive)188 void implChDrive( const String& aDrive )
189 {
190     (void)aDrive;
191 	// TODO
192 }
193 
194 // Returns (virtual) current path for UCB file access
implGetCurDir(void)195 String implGetCurDir( void )
196 {
197 	String aRetStr;
198 
199 	return aRetStr;
200 }
201 
202 // TODO: -> SbiGlobals
getFileAccess(void)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 
RTLFUNC(CreateObject)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 
RTLFUNC(Error)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 
RTLFUNC(Sin)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 
RTLFUNC(Cos)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 
RTLFUNC(Atn)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 
RTLFUNC(Abs)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 
RTLFUNC(Asc)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 
implChr(SbxArray & rPar,bool bChrW)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 
RTLFUNC(Chr)406 RTLFUNC(Chr)
407 {
408     (void)pBasic;
409     (void)bWrite;
410 
411 	bool bChrW = false;
412 	implChr( rPar, bChrW );
413 }
414 
RTLFUNC(ChrW)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 
RTLFUNC(CurDir)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 
RTLFUNC(ChDir)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 
RTLFUNC(ChDrive)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
implStepRenameUCB(const String & aSource,const String & aDest)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
implStepRenameOSL(const String & aSource,const String & aDest)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 
RTLFUNC(FileCopy)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 
RTLFUNC(Kill)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 
RTLFUNC(MkDir)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
implRemoveDirRecursive(const String & aDirPath)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 
RTLFUNC(RmDir)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 
RTLFUNC(SendKeys)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 
RTLFUNC(Exp)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 
RTLFUNC(FileLen)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 
RTLFUNC(Hex)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 
RTLFUNC(InStr)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 
RTLFUNC(InStrRev)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 
RTLFUNC(Int)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 
RTLFUNC(Fix)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 
RTLFUNC(LCase)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 
RTLFUNC(Left)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 
RTLFUNC(Log)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 
RTLFUNC(LTrim)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 
RTLFUNC(Mid)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 
RTLFUNC(Oct)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 
RTLFUNC(Replace)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 + nReplaceStrLen;
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 
RTLFUNC(Right)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 
RTLFUNC(RTL)1484 RTLFUNC(RTL)
1485 {
1486     (void)pBasic;
1487     (void)bWrite;
1488 
1489 	rPar.Get( 0 )->PutObject( pBasic->getRTL() );
1490 }
1491 
RTLFUNC(RTrim)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 
RTLFUNC(Sgn)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 
RTLFUNC(Space)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 
RTLFUNC(Spc)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 
RTLFUNC(Sqr)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 
RTLFUNC(Str)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 
RTLFUNC(StrComp)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 
RTLFUNC(String)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 
RTLFUNC(Tab)1711 RTLFUNC(Tab)
1712 {
1713     (void)pBasic;
1714     (void)bWrite;
1715 
1716 	if ( rPar.Count() < 2 )
1717 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1718 	else
1719 	{
1720 		String aStr;
1721 		aStr.Fill( (sal_uInt16)(rPar.Get(1)->GetLong() ), '\t');
1722 		rPar.Get(0)->PutString( aStr );
1723 	}
1724 }
1725 
RTLFUNC(Tan)1726 RTLFUNC(Tan)
1727 {
1728     (void)pBasic;
1729     (void)bWrite;
1730 
1731 	if ( rPar.Count() < 2 )
1732 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1733 	else
1734 	{
1735 		SbxVariableRef pArg = rPar.Get( 1 );
1736 		rPar.Get( 0 )->PutDouble( tan( pArg->GetDouble() ) );
1737 	}
1738 }
1739 
RTLFUNC(UCase)1740 RTLFUNC(UCase)
1741 {
1742     (void)pBasic;
1743     (void)bWrite;
1744 
1745 	if ( rPar.Count() < 2 )
1746 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1747 	else
1748 	{
1749 		CharClass& rCharClass = GetCharClass();
1750 		String aStr( rPar.Get(1)->GetString() );
1751 		rCharClass.toUpper( aStr );
1752 		rPar.Get(0)->PutString( aStr );
1753 	}
1754 }
1755 
1756 
RTLFUNC(Val)1757 RTLFUNC(Val)
1758 {
1759     (void)pBasic;
1760     (void)bWrite;
1761 
1762 	if ( rPar.Count() < 2 )
1763 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1764 	else
1765 	{
1766 		double nResult = 0.0;
1767 		char* pEndPtr;
1768 
1769 		String aStr( rPar.Get(1)->GetString() );
1770 // lt. Mikkysoft bei Kommas abbrechen!
1771 //		for( sal_uInt16 n=0; n < aStr.Len(); n++ )
1772 //			if( aStr[n] == ',' ) aStr[n] = '.';
1773 
1774 		FilterWhiteSpace( aStr );
1775 		if ( aStr.GetBuffer()[0] == '&' && aStr.Len() > 1 )
1776 		{
1777 			int nRadix = 10;
1778 			char aChar = (char)aStr.GetBuffer()[1];
1779 			if ( aChar == 'h' || aChar == 'H' )
1780 				nRadix = 16;
1781 			else if ( aChar == 'o' || aChar == 'O' )
1782 				nRadix = 8;
1783 			if ( nRadix != 10 )
1784 			{
1785 				ByteString aByteStr( aStr, gsl_getSystemTextEncoding() );
1786 				sal_Int16 nlResult = (sal_Int16)strtol( aByteStr.GetBuffer()+2, &pEndPtr, nRadix);
1787 				nResult = (double)nlResult;
1788 			}
1789 		}
1790 		else
1791 		{
1792 			// #57844 Lokalisierte Funktion benutzen
1793 			nResult = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
1794             checkArithmeticOverflow( nResult );
1795 			// ATL: nResult = strtod( aStr.GetStr(), &pEndPtr );
1796 		}
1797 
1798 		rPar.Get(0)->PutDouble( nResult );
1799 	}
1800 }
1801 
1802 
1803 // Helper functions for date conversion
implGetDateDay(double aDate)1804 sal_Int16 implGetDateDay( double aDate )
1805 {
1806 	aDate -= 2.0; // normieren: 1.1.1900 => 0.0
1807 	aDate = floor( aDate );
1808 	Date aRefDate( 1, 1, 1900 );
1809 	aRefDate += (sal_uIntPtr)aDate;
1810 
1811     sal_Int16 nRet = (sal_Int16)( aRefDate.GetDay() );
1812     return nRet;
1813 }
1814 
implGetDateMonth(double aDate)1815 sal_Int16 implGetDateMonth( double aDate )
1816 {
1817 	Date aRefDate( 1,1,1900 );
1818 	long nDays = (long)aDate;
1819 	nDays -= 2; // normieren: 1.1.1900 => 0.0
1820 	aRefDate += nDays;
1821 	sal_Int16 nRet = (sal_Int16)( aRefDate.GetMonth() );
1822     return nRet;
1823 }
1824 
implGetDateYear(double aDate)1825 sal_Int16 implGetDateYear( double aDate )
1826 {
1827 	Date aRefDate( 1,1,1900 );
1828 	long nDays = (long) aDate;
1829 	nDays -= 2; // normieren: 1.1.1900 => 0.0
1830 	aRefDate += nDays;
1831 	sal_Int16 nRet = (sal_Int16)( aRefDate.GetYear() );
1832     return nRet;
1833 }
1834 
implDateSerial(sal_Int16 nYear,sal_Int16 nMonth,sal_Int16 nDay,double & rdRet)1835 sal_Bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, double& rdRet )
1836 {
1837 	if ( nYear < 30 && SbiRuntime::isVBAEnabled() )
1838 		nYear += 2000;
1839 	else if ( nYear < 100 )
1840 		nYear += 1900;
1841 	Date aCurDate( nDay, nMonth, nYear );
1842 	if ((nYear < 100 || nYear > 9999) )
1843 	{
1844 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1845 		return sal_False;
1846 	}
1847 	if ( !SbiRuntime::isVBAEnabled() )
1848 	{
1849 		if ( (nMonth < 1 || nMonth > 12 )||
1850 		(nDay < 1 || nDay > 31 ) )
1851 		{
1852 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
1853 			return sal_False;
1854 		}
1855 	}
1856 	else
1857 	{
1858 		// grab the year & month
1859 		aCurDate = Date( 1, (( nMonth % 12 ) > 0 ) ? ( nMonth % 12 ) : 12 + ( nMonth % 12 ), nYear );
1860 
1861 		// adjust year based on month value
1862 		// e.g. 2000, 0, xx = 1999, 12, xx ( or December of the previous year )
1863 		//		2000, 13, xx = 2001, 1, xx ( or January of the following year )
1864 		if( ( nMonth < 1 ) || ( nMonth > 12 ) )
1865 		{
1866 			// inacurrate around leap year, don't use days to calculate,
1867 			// just modify the months directory
1868 			sal_Int16 nYearAdj = ( nMonth /12 ); // default to positive months inputed
1869 			if ( nMonth <=0 )
1870 				nYearAdj = ( ( nMonth -12 ) / 12 );
1871 			aCurDate.SetYear( aCurDate.GetYear() + nYearAdj );
1872 		}
1873 
1874 		// adjust day value,
1875 		// e.g. 2000, 2, 0 = 2000, 1, 31 or the last day of the previous month
1876 		//		2000, 1, 32 = 2000, 2, 1 or the first day of the following month
1877 		if( ( nDay < 1 ) || ( nDay > aCurDate.GetDaysInMonth() ) )
1878 			aCurDate += nDay - 1;
1879 		else
1880 			aCurDate.SetDay( nDay );
1881 	}
1882 
1883 	long nDiffDays = GetDayDiff( aCurDate );
1884     rdRet = (double)nDiffDays;
1885     return sal_True;
1886 }
1887 
1888 // Function to convert date to ISO 8601 date format
RTLFUNC(CDateToIso)1889 RTLFUNC(CDateToIso)
1890 {
1891     (void)pBasic;
1892     (void)bWrite;
1893 
1894 	if ( rPar.Count() == 2 )
1895 	{
1896         double aDate = rPar.Get(1)->GetDate();
1897 
1898         char Buffer[9];
1899         snprintf( Buffer, sizeof( Buffer ), "%04d%02d%02d",
1900             implGetDateYear( aDate ),
1901             implGetDateMonth( aDate ),
1902             implGetDateDay( aDate ) );
1903 		String aRetStr = String::CreateFromAscii( Buffer );
1904         rPar.Get(0)->PutString( aRetStr );
1905 	}
1906 	else
1907 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1908 }
1909 
1910 // Function to convert date from ISO 8601 date format
RTLFUNC(CDateFromIso)1911 RTLFUNC(CDateFromIso)
1912 {
1913     (void)pBasic;
1914     (void)bWrite;
1915 
1916 	if ( rPar.Count() == 2 )
1917 	{
1918 		String aStr = rPar.Get(1)->GetString();
1919         sal_Int16 iMonthStart = aStr.Len() - 4;
1920         String aYearStr  = aStr.Copy( 0, iMonthStart );
1921         String aMonthStr = aStr.Copy( iMonthStart, 2 );
1922         String aDayStr   = aStr.Copy( iMonthStart+2, 2 );
1923 
1924         double dDate;
1925         if( implDateSerial( (sal_Int16)aYearStr.ToInt32(),
1926             (sal_Int16)aMonthStr.ToInt32(), (sal_Int16)aDayStr.ToInt32(), dDate ) )
1927         {
1928     	    rPar.Get(0)->PutDate( dDate );
1929         }
1930 	}
1931 	else
1932 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1933 }
1934 
RTLFUNC(DateSerial)1935 RTLFUNC(DateSerial)
1936 {
1937     (void)pBasic;
1938     (void)bWrite;
1939 
1940 	if ( rPar.Count() < 4 )
1941 	{
1942 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1943 		return;
1944 	}
1945 	sal_Int16 nYear = rPar.Get(1)->GetInteger();
1946 	sal_Int16 nMonth = rPar.Get(2)->GetInteger();
1947 	sal_Int16 nDay = rPar.Get(3)->GetInteger();
1948 
1949     double dDate;
1950     if( implDateSerial( nYear, nMonth, nDay, dDate ) )
1951     	rPar.Get(0)->PutDate( dDate );
1952 }
1953 
RTLFUNC(TimeSerial)1954 RTLFUNC(TimeSerial)
1955 {
1956     (void)pBasic;
1957     (void)bWrite;
1958 
1959 	if ( rPar.Count() < 4 )
1960 	{
1961 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1962 		return;
1963 	}
1964 	sal_Int16 nHour = rPar.Get(1)->GetInteger();
1965 	if ( nHour == 24 )
1966 		nHour = 0;                      // Wegen UNO DateTimes, die bis 24 Uhr gehen
1967 	sal_Int16 nMinute = rPar.Get(2)->GetInteger();
1968 	sal_Int16 nSecond = rPar.Get(3)->GetInteger();
1969 	if ((nHour < 0 || nHour > 23)   ||
1970 		(nMinute < 0 || nMinute > 59 )	||
1971 		(nSecond < 0 || nSecond > 59 ))
1972 	{
1973 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1974 		return;
1975 	}
1976 
1977 	sal_Int32 nSeconds = nHour;
1978 	nSeconds *= 3600;
1979 	nSeconds += nMinute * 60;
1980 	nSeconds += nSecond;
1981 	double nDays = ((double)nSeconds) / (double)(86400.0);
1982 	rPar.Get(0)->PutDate( nDays ); // JSM
1983 }
1984 
RTLFUNC(DateValue)1985 RTLFUNC(DateValue)
1986 {
1987     (void)pBasic;
1988     (void)bWrite;
1989 
1990 	if ( rPar.Count() < 2 )
1991 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
1992 	else
1993 	{
1994 		// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
1995 		SvNumberFormatter* pFormatter = NULL;
1996 		if( pINST )
1997 			pFormatter = pINST->GetNumberFormatter();
1998 		else
1999 		{
2000 			sal_uInt32 n;	// Dummy
2001 			SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
2002 		}
2003 
2004 		sal_uInt32 nIndex = 0;
2005 		double fResult;
2006 		String aStr( rPar.Get(1)->GetString() );
2007 		sal_Bool bSuccess = pFormatter->IsNumberFormat( aStr, nIndex, fResult );
2008 		short nType = pFormatter->GetType( nIndex );
2009 
2010 		// DateValue("February 12, 1969") raises error if the system locale is not en_US
2011 		// by using SbiInstance::GetNumberFormatter.
2012 		// It seems that both locale number formatter and English number formatter
2013 		// are supported in Visual Basic.
2014 		LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
2015         if( !bSuccess && ( eLangType != LANGUAGE_ENGLISH_US ) )
2016 		{
2017 			// Create a new SvNumberFormatter by using LANGUAGE_ENGLISH to get the date value;
2018 			com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
2019 				xFactory = comphelper::getProcessServiceFactory();
2020 			SvNumberFormatter aFormatter( xFactory, LANGUAGE_ENGLISH_US );
2021 			bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, fResult );
2022 			nType = aFormatter.GetType( nIndex );
2023 		}
2024 
2025 		if(bSuccess && (nType==NUMBERFORMAT_DATE || nType==NUMBERFORMAT_DATETIME))
2026 		{
2027 			if ( nType == NUMBERFORMAT_DATETIME )
2028 			{
2029 				// Zeit abschneiden
2030 				if ( fResult  > 0.0 )
2031 					fResult = floor( fResult );
2032 				else
2033 					fResult = ceil( fResult );
2034 			}
2035 			// fResult += 2.0; // Anpassung  StarCalcFormatter
2036 			rPar.Get(0)->PutDate( fResult ); // JSM
2037 		}
2038 		else
2039 			StarBASIC::Error( SbERR_CONVERSION );
2040 
2041 		// #39629 pFormatter kann selbst angefordert sein
2042 		if( !pINST )
2043 			delete pFormatter;
2044 	}
2045 }
2046 
RTLFUNC(TimeValue)2047 RTLFUNC(TimeValue)
2048 {
2049     (void)pBasic;
2050     (void)bWrite;
2051 
2052 	if ( rPar.Count() < 2 )
2053 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2054 	else
2055 	{
2056 		// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
2057 		SvNumberFormatter* pFormatter = NULL;
2058 		if( pINST )
2059 			pFormatter = pINST->GetNumberFormatter();
2060 		else
2061 		{
2062 			sal_uInt32 n;	// Dummy
2063 			SbiInstance::PrepareNumberFormatter( pFormatter, n, n, n );
2064 		}
2065 
2066 		sal_uInt32 nIndex = 0;
2067 		double fResult;
2068 		sal_Bool bSuccess = pFormatter->IsNumberFormat( rPar.Get(1)->GetString(),
2069 												   nIndex, fResult );
2070 		short nType = pFormatter->GetType(nIndex);
2071 		if(bSuccess && (nType==NUMBERFORMAT_TIME||nType==NUMBERFORMAT_DATETIME))
2072 		{
2073 			if ( nType == NUMBERFORMAT_DATETIME )
2074 				// Tage abschneiden
2075 				fResult = fmod( fResult, 1 );
2076 			rPar.Get(0)->PutDate( fResult ); // JSM
2077 		}
2078 		else
2079 			StarBASIC::Error( SbERR_CONVERSION );
2080 
2081 		// #39629 pFormatter kann selbst angefordert sein
2082 		if( !pINST )
2083 			delete pFormatter;
2084 	}
2085 }
2086 
RTLFUNC(Day)2087 RTLFUNC(Day)
2088 {
2089     (void)pBasic;
2090     (void)bWrite;
2091 
2092 	if ( rPar.Count() < 2 )
2093 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2094 	else
2095 	{
2096 		SbxVariableRef pArg = rPar.Get( 1 );
2097 		double aDate = pArg->GetDate();
2098 
2099         sal_Int16 nDay = implGetDateDay( aDate );
2100 		rPar.Get(0)->PutInteger( nDay );
2101 	}
2102 }
2103 
RTLFUNC(Year)2104 RTLFUNC(Year)
2105 {
2106     (void)pBasic;
2107     (void)bWrite;
2108 
2109 	if ( rPar.Count() < 2 )
2110 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2111 	else
2112 	{
2113         sal_Int16 nYear = implGetDateYear( rPar.Get(1)->GetDate() );
2114 		rPar.Get(0)->PutInteger( nYear );
2115 	}
2116 }
2117 
implGetHour(double dDate)2118 sal_Int16 implGetHour( double dDate )
2119 {
2120 	double nFrac = dDate - floor( dDate );
2121 	nFrac *= 86400.0;
2122 	sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
2123 	sal_Int16 nHour = (sal_Int16)(nSeconds / 3600);
2124     return nHour;
2125 }
2126 
RTLFUNC(Hour)2127 RTLFUNC(Hour)
2128 {
2129     (void)pBasic;
2130     (void)bWrite;
2131 
2132 	if ( rPar.Count() < 2 )
2133 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2134 	else
2135 	{
2136 		double nArg = rPar.Get(1)->GetDate();
2137 		sal_Int16 nHour = implGetHour( nArg );
2138 		rPar.Get(0)->PutInteger( nHour );
2139 	}
2140 }
2141 
implGetMinute(double dDate)2142 sal_Int16 implGetMinute( double dDate )
2143 {
2144 	double nFrac = dDate - floor( dDate );
2145 	nFrac *= 86400.0;
2146 	sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
2147 	sal_Int16 nTemp = (sal_Int16)(nSeconds % 3600);
2148 	sal_Int16 nMin = nTemp / 60;
2149     return nMin;
2150 }
2151 
RTLFUNC(Minute)2152 RTLFUNC(Minute)
2153 {
2154     (void)pBasic;
2155     (void)bWrite;
2156 
2157 	if ( rPar.Count() < 2 )
2158 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2159 	else
2160 	{
2161 		double nArg = rPar.Get(1)->GetDate();
2162 		sal_Int16 nMin = implGetMinute( nArg );
2163 		rPar.Get(0)->PutInteger( nMin );
2164 	}
2165 }
2166 
RTLFUNC(Month)2167 RTLFUNC(Month)
2168 {
2169     (void)pBasic;
2170     (void)bWrite;
2171 
2172 	if ( rPar.Count() < 2 )
2173 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2174 	else
2175 	{
2176         sal_Int16 nMonth = implGetDateMonth( rPar.Get(1)->GetDate() );
2177 		rPar.Get(0)->PutInteger( nMonth );
2178 	}
2179 }
2180 
implGetSecond(double dDate)2181 sal_Int16 implGetSecond( double dDate )
2182 {
2183 	double nFrac = dDate - floor( dDate );
2184 	nFrac *= 86400.0;
2185 	sal_Int32 nSeconds = (sal_Int32)(nFrac + 0.5);
2186 	sal_Int16 nTemp = (sal_Int16)(nSeconds / 3600);
2187 	nSeconds -= nTemp * 3600;
2188 	nTemp = (sal_Int16)(nSeconds / 60);
2189 	nSeconds -= nTemp * 60;
2190 
2191 	sal_Int16 nRet = (sal_Int16)nSeconds;
2192     return nRet;
2193 }
2194 
RTLFUNC(Second)2195 RTLFUNC(Second)
2196 {
2197     (void)pBasic;
2198     (void)bWrite;
2199 
2200 	if ( rPar.Count() < 2 )
2201 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2202 	else
2203 	{
2204 		double nArg = rPar.Get(1)->GetDate();
2205 		sal_Int16 nSecond = implGetSecond( nArg );
2206 		rPar.Get(0)->PutInteger( nSecond );
2207 	}
2208 }
2209 
Now_Impl()2210 double Now_Impl()
2211 {
2212 	Date aDate;
2213 	Time aTime;
2214 	double aSerial = (double)GetDayDiff( aDate );
2215 	long nSeconds = aTime.GetHour();
2216 	nSeconds *= 3600;
2217 	nSeconds += aTime.GetMin() * 60;
2218 	nSeconds += aTime.GetSec();
2219 	double nDays = ((double)nSeconds) / (double)(24.0*3600.0);
2220 	aSerial += nDays;
2221 	return aSerial;
2222 }
2223 
2224 // Date Now(void)
2225 
RTLFUNC(Now)2226 RTLFUNC(Now)
2227 {
2228     	(void)pBasic;
2229     	(void)bWrite;
2230 	rPar.Get(0)->PutDate( Now_Impl() );
2231 }
2232 
2233 // Date Time(void)
2234 
RTLFUNC(Time)2235 RTLFUNC(Time)
2236 {
2237     (void)pBasic;
2238 
2239 	if ( !bWrite )
2240 	{
2241 		Time aTime;
2242 		SbxVariable* pMeth = rPar.Get( 0 );
2243 		String aRes;
2244 		if( pMeth->IsFixed() )
2245 		{
2246 			// Time$: hh:mm:ss
2247 			char buf[ 20 ];
2248             snprintf( buf, sizeof(buf), "%02d:%02d:%02d",
2249 				aTime.GetHour(), aTime.GetMin(), aTime.GetSec() );
2250 			aRes = String::CreateFromAscii( buf );
2251 		}
2252 		else
2253 		{
2254 			// Time: system dependent
2255 			long nSeconds=aTime.GetHour();
2256 			nSeconds *= 3600;
2257 			nSeconds += aTime.GetMin() * 60;
2258 			nSeconds += aTime.GetSec();
2259 			double nDays = (double)nSeconds * ( 1.0 / (24.0*3600.0) );
2260 			Color* pCol;
2261 
2262 			// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
2263 			SvNumberFormatter* pFormatter = NULL;
2264 			sal_uInt32 nIndex;
2265 			if( pINST )
2266 			{
2267 				pFormatter = pINST->GetNumberFormatter();
2268 				nIndex = pINST->GetStdTimeIdx();
2269 			}
2270 			else
2271 			{
2272 				sal_uInt32 n;	// Dummy
2273 				SbiInstance::PrepareNumberFormatter( pFormatter, n, nIndex, n );
2274 			}
2275 
2276 			pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
2277 
2278 			// #39629 pFormatter kann selbst angefordert sein
2279 			if( !pINST )
2280 				delete pFormatter;
2281 		}
2282 		pMeth->PutString( aRes );
2283 	}
2284 	else
2285 	{
2286 		StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
2287 	}
2288 }
2289 
RTLFUNC(Timer)2290 RTLFUNC(Timer)
2291 {
2292     (void)pBasic;
2293     (void)bWrite;
2294 
2295 	Time aTime;
2296 	long nSeconds = aTime.GetHour();
2297 	nSeconds *= 3600;
2298 	nSeconds += aTime.GetMin() * 60;
2299 	nSeconds += aTime.GetSec();
2300 	rPar.Get(0)->PutDate( (double)nSeconds );
2301 }
2302 
2303 
RTLFUNC(Date)2304 RTLFUNC(Date)
2305 {
2306     (void)pBasic;
2307     (void)bWrite;
2308 
2309 	if ( !bWrite )
2310 	{
2311 		Date aToday;
2312 		double nDays = (double)GetDayDiff( aToday );
2313 		SbxVariable* pMeth = rPar.Get( 0 );
2314 		if( pMeth->IsString() )
2315 		{
2316 			String aRes;
2317 			Color* pCol;
2318 
2319 			// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
2320 			SvNumberFormatter* pFormatter = NULL;
2321 			sal_uInt32 nIndex;
2322 			if( pINST )
2323 			{
2324 				pFormatter = pINST->GetNumberFormatter();
2325 				nIndex = pINST->GetStdDateIdx();
2326 			}
2327 			else
2328 			{
2329 				sal_uInt32 n;	// Dummy
2330 				SbiInstance::PrepareNumberFormatter( pFormatter, nIndex, n, n );
2331 			}
2332 
2333 			pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
2334 			pMeth->PutString( aRes );
2335 
2336 			// #39629 pFormatter kann selbst angefordert sein
2337 			if( !pINST )
2338 				delete pFormatter;
2339 		}
2340 		else
2341 			pMeth->PutDate( nDays );
2342 	}
2343 	else
2344 	{
2345 		StarBASIC::Error( SbERR_NOT_IMPLEMENTED );
2346 	}
2347 }
2348 
RTLFUNC(IsArray)2349 RTLFUNC(IsArray)
2350 {
2351     (void)pBasic;
2352     (void)bWrite;
2353 
2354 	if ( rPar.Count() < 2 )
2355 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2356 	else
2357 		rPar.Get(0)->PutBool((rPar.Get(1)->GetType() & SbxARRAY) ? sal_True : sal_False );
2358 }
2359 
RTLFUNC(IsObject)2360 RTLFUNC(IsObject)
2361 {
2362     (void)pBasic;
2363     (void)bWrite;
2364 
2365 	if ( rPar.Count() < 2 )
2366 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2367 	else
2368     {
2369     	SbxVariable* pVar = rPar.Get(1);
2370 	    SbxBase* pObj = (SbxBase*)pVar->GetObject();
2371 
2372 		// #100385: GetObject can result in an error, so reset it
2373 		SbxBase::ResetError();
2374 
2375         SbUnoClass* pUnoClass;
2376         sal_Bool bObject;
2377 	    if( pObj &&  NULL != ( pUnoClass=PTR_CAST(SbUnoClass,pObj) ) )
2378         {
2379             bObject = pUnoClass->getUnoClass().is();
2380         }
2381         else
2382         {
2383             bObject = pVar->IsObject();
2384         }
2385 		rPar.Get( 0 )->PutBool( bObject );
2386     }
2387 }
2388 
RTLFUNC(IsDate)2389 RTLFUNC(IsDate)
2390 {
2391     (void)pBasic;
2392     (void)bWrite;
2393 
2394 	if ( rPar.Count() < 2 )
2395 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2396 	else
2397 	{
2398 		// #46134 Nur String wird konvertiert, andere Typen ergeben sal_False
2399 		SbxVariableRef xArg = rPar.Get( 1 );
2400 		SbxDataType eType = xArg->GetType();
2401 		sal_Bool bDate = sal_False;
2402 
2403 		if( eType == SbxDATE )
2404 		{
2405 			bDate = sal_True;
2406 		}
2407 		else if( eType == SbxSTRING )
2408 		{
2409 			// Error loeschen
2410 			SbxError nPrevError = SbxBase::GetError();
2411 			SbxBase::ResetError();
2412 
2413 			// Konvertierung des Parameters nach SbxDATE erzwingen
2414 			xArg->SbxValue::GetDate();
2415 
2416 			// Bei Fehler ist es kein Date
2417 			bDate = !SbxBase::IsError();
2418 
2419 			// Error-Situation wiederherstellen
2420 			SbxBase::ResetError();
2421 			SbxBase::SetError( nPrevError );
2422 		}
2423 		rPar.Get( 0 )->PutBool( bDate );
2424 	}
2425 }
2426 
RTLFUNC(IsEmpty)2427 RTLFUNC(IsEmpty)
2428 {
2429     (void)pBasic;
2430     (void)bWrite;
2431 
2432 	if ( rPar.Count() < 2 )
2433 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2434 	else
2435 		rPar.Get( 0 )->PutBool( rPar.Get(1)->IsEmpty() );
2436 }
2437 
RTLFUNC(IsError)2438 RTLFUNC(IsError)
2439 {
2440     (void)pBasic;
2441     (void)bWrite;
2442 
2443 	if ( rPar.Count() < 2 )
2444 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2445 	else
2446 		rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
2447 }
2448 
RTLFUNC(IsNull)2449 RTLFUNC(IsNull)
2450 {
2451     (void)pBasic;
2452     (void)bWrite;
2453 
2454 	if ( rPar.Count() < 2 )
2455 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2456 	else
2457 	{
2458 		// #51475 Wegen Uno-Objekten auch true liefern,
2459 		// wenn der pObj-Wert NULL ist
2460 		SbxVariableRef pArg = rPar.Get( 1 );
2461 		sal_Bool bNull = rPar.Get(1)->IsNull();
2462 		if( !bNull && pArg->GetType() == SbxOBJECT )
2463 		{
2464 			SbxBase* pObj = pArg->GetObject();
2465 			if( !pObj )
2466 				bNull = sal_True;
2467 		}
2468 		rPar.Get( 0 )->PutBool( bNull );
2469 	}
2470 }
2471 
RTLFUNC(IsNumeric)2472 RTLFUNC(IsNumeric)
2473 {
2474     (void)pBasic;
2475     (void)bWrite;
2476 
2477 	if ( rPar.Count() < 2 )
2478 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2479 	else
2480 		rPar.Get( 0 )->PutBool( rPar.Get( 1 )->IsNumericRTL() );
2481 }
2482 
2483 // Das machen wir auf die billige Tour
2484 
RTLFUNC(IsMissing)2485 RTLFUNC(IsMissing)
2486 {
2487     (void)pBasic;
2488     (void)bWrite;
2489 
2490 	if ( rPar.Count() < 2 )
2491 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2492 	else
2493 		// #57915 Missing wird durch Error angezeigt
2494 		rPar.Get( 0 )->PutBool( rPar.Get(1)->IsErr() );
2495 }
2496 
2497 // Dir( [Maske] [,Attrs] )
2498 // ToDo: Library-globaler Datenbereich fuer Dir-Objekt und Flags
2499 
2500 
getDirectoryPath(String aPathStr)2501 String getDirectoryPath( String aPathStr )
2502 {
2503     String aRetStr;
2504 
2505     DirectoryItem aItem;
2506     FileBase::RC nRet = DirectoryItem::get( aPathStr, aItem );
2507 	if( nRet == FileBase::E_None )
2508 	{
2509 		FileStatus aFileStatus( FileStatusMask_Type );
2510 		nRet = aItem.getFileStatus( aFileStatus );
2511 		if( nRet == FileBase::E_None )
2512 		{
2513 			FileStatus::Type aType = aFileStatus.getFileType();
2514 			if( isFolder( aType ) )
2515             {
2516         		aRetStr = aPathStr;
2517             }
2518             else if( aType == FileStatus::Link )
2519             {
2520         		FileStatus aFileStatus2( FileStatusMask_LinkTargetURL );
2521         		nRet = aItem.getFileStatus( aFileStatus2 );
2522 		        if( nRet == FileBase::E_None )
2523                     aRetStr = getDirectoryPath( aFileStatus2.getLinkTargetURL() );
2524             }
2525 		}
2526     }
2527     return aRetStr;
2528 }
2529 
2530 // Function looks for wildcards, removes them and always returns the pure path
implSetupWildcard(const String & rFileParam,SbiRTLData * pRTLData)2531 String implSetupWildcard( const String& rFileParam, SbiRTLData* pRTLData )
2532 {
2533     static String aAsterisk = String::CreateFromAscii( "*" );
2534 	static sal_Char cDelim1 = (sal_Char)'/';
2535 	static sal_Char cDelim2 = (sal_Char)'\\';
2536 	static sal_Char cWild1 = '*';
2537 	static sal_Char cWild2 = '?';
2538 
2539 	delete pRTLData->pWildCard;
2540 	pRTLData->pWildCard = NULL;
2541 	pRTLData->sFullNameToBeChecked = String();
2542 
2543 	String aFileParam = rFileParam;
2544 	xub_StrLen nLastWild = aFileParam.SearchBackward( cWild1 );
2545 	if( nLastWild == STRING_NOTFOUND )
2546 		nLastWild = aFileParam.SearchBackward( cWild2 );
2547 	sal_Bool bHasWildcards = ( nLastWild != STRING_NOTFOUND );
2548 
2549 
2550 	xub_StrLen nLastDelim = aFileParam.SearchBackward( cDelim1 );
2551 	if( nLastDelim == STRING_NOTFOUND )
2552 		nLastDelim = aFileParam.SearchBackward( cDelim2 );
2553 
2554     if( bHasWildcards )
2555     {
2556         // Wildcards in path?
2557         if( nLastDelim != STRING_NOTFOUND && nLastDelim > nLastWild )
2558             return aFileParam;
2559     }
2560     else
2561     {
2562 	    String aPathStr = getFullPath( aFileParam );
2563         if( nLastDelim != aFileParam.Len() - 1 )
2564             pRTLData->sFullNameToBeChecked = aPathStr;
2565         return aPathStr;
2566     }
2567 
2568 	String aPureFileName;
2569 	if( nLastDelim == STRING_NOTFOUND )
2570 	{
2571 		aPureFileName = aFileParam;
2572 		aFileParam = String();
2573 	}
2574 	else
2575 	{
2576 		aPureFileName = aFileParam.Copy( nLastDelim + 1 );
2577 		aFileParam = aFileParam.Copy( 0, nLastDelim );
2578 	}
2579 
2580 	// Try again to get a valid URL/UNC-path with only the path
2581 	String aPathStr = getFullPath( aFileParam );
2582 	xub_StrLen nPureLen = aPureFileName.Len();
2583 
2584 	// Is there a pure file name left? Otherwise the path is
2585 	// invalid anyway because it was not accepted by OSL before
2586 	if( nPureLen && aPureFileName != aAsterisk )
2587 	{
2588 		pRTLData->pWildCard = new WildCard( aPureFileName );
2589 	}
2590 	return aPathStr;
2591 }
2592 
implCheckWildcard(const String & rName,SbiRTLData * pRTLData)2593 inline sal_Bool implCheckWildcard( const String& rName, SbiRTLData* pRTLData )
2594 {
2595 	sal_Bool bMatch = sal_True;
2596 
2597 	if( pRTLData->pWildCard )
2598 		bMatch = pRTLData->pWildCard->Matches( rName );
2599 	return bMatch;
2600 }
2601 
2602 
isRootDir(String aDirURLStr)2603 bool isRootDir( String aDirURLStr )
2604 {
2605 	INetURLObject aDirURLObj( aDirURLStr );
2606 	sal_Bool bRoot = sal_False;
2607 
2608 	// Check if it's a root directory
2609 	sal_Int32 nCount = aDirURLObj.getSegmentCount();
2610 
2611 	// No segment means Unix root directory "file:///"
2612 	if( nCount == 0 )
2613 	{
2614 		bRoot = sal_True;
2615 	}
2616 	// Exactly one segment needs further checking, because it
2617 	// can be Unix "file:///foo/" -> no root
2618 	// or Windows  "file:///c:/"  -> root
2619 	else if( nCount == 1 )
2620 	{
2621 		::rtl::OUString aSeg1 = aDirURLObj.getName( 0, sal_True,
2622 			INetURLObject::DECODE_WITH_CHARSET );
2623 		if( aSeg1.getStr()[1] == (sal_Unicode)':' )
2624 		{
2625 			bRoot = sal_True;
2626 		}
2627 	}
2628 	// More than one segments can never be root
2629 	// so bRoot remains sal_False
2630 
2631     return bRoot;
2632 }
2633 
RTLFUNC(Dir)2634 RTLFUNC(Dir)
2635 {
2636     (void)pBasic;
2637     (void)bWrite;
2638 
2639 	String aPath;
2640 
2641 	sal_uInt16 nParCount = rPar.Count();
2642 	if( nParCount > 3 )
2643 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
2644 	else
2645 	{
2646 		SbiRTLData* pRTLData = pINST->GetRTLData();
2647 
2648 		// #34645: Kann auch von der URL-Zeile ueber 'macro: Dir' aufgerufen werden
2649 		// dann existiert kein pRTLData und die Methode muss verlassen werden
2650 		if( !pRTLData )
2651 			return;
2652 
2653 		// <-- UCB
2654 		if( hasUno() )
2655 		{
2656 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
2657 			if( xSFI.is() )
2658 			{
2659 				if ( nParCount >= 2 )
2660 				{
2661 					String aFileParam = rPar.Get(1)->GetString();
2662 
2663 					String aFileURLStr = implSetupWildcard( aFileParam, pRTLData );
2664                     if( pRTLData->sFullNameToBeChecked.Len() > 0 )
2665                     {
2666 						sal_Bool bExists = sal_False;
2667 						try	{ bExists = xSFI->exists( aFileURLStr ); }
2668 						catch( Exception & ) {}
2669 
2670                         String aNameOnlyStr;
2671 						if( bExists )
2672                         {
2673 							INetURLObject aFileURL( aFileURLStr );
2674 							aNameOnlyStr = aFileURL.getName( INetURLObject::LAST_SEGMENT,
2675 								true, INetURLObject::DECODE_WITH_CHARSET );
2676                         }
2677 						rPar.Get(0)->PutString( aNameOnlyStr );
2678 						return;
2679                     }
2680 
2681 					try
2682 					{
2683 						String aDirURLStr;
2684 						sal_Bool bFolder = xSFI->isFolder( aFileURLStr );
2685 
2686 						if( bFolder )
2687 						{
2688 							aDirURLStr = aFileURLStr;
2689 						}
2690 						else
2691 						{
2692                             String aEmptyStr;
2693 							rPar.Get(0)->PutString( aEmptyStr );
2694 						}
2695 
2696 						sal_uInt16 nFlags = 0;
2697 						if ( nParCount > 2 )
2698 							pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
2699 						else
2700 							pRTLData->nDirFlags = 0;
2701 
2702 						// Read directory
2703 						sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0);
2704 						pRTLData->aDirSeq = xSFI->getFolderContents( aDirURLStr, bIncludeFolders );
2705 						pRTLData->nCurDirPos = 0;
2706 
2707 						// #78651 Add "." and ".." directories for VB compatibility
2708 						if( bIncludeFolders )
2709 						{
2710 							sal_Bool bRoot = isRootDir( aDirURLStr );
2711 
2712 							// If it's no root directory we flag the need for
2713 							// the "." and ".." directories by the value -2
2714 							// for the actual position. Later for -2 will be
2715 							// returned "." and for -1 ".."
2716 							if( !bRoot )
2717 							{
2718 								pRTLData->nCurDirPos = -2;
2719 							}
2720 						}
2721 					}
2722 					catch( Exception & )
2723 					{
2724 						//StarBASIC::Error( ERRCODE_IO_GENERAL );
2725 					}
2726 				}
2727 
2728 
2729 				if( pRTLData->aDirSeq.getLength() > 0 )
2730 				{
2731 					sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
2732 
2733 					SbiInstance* pInst = pINST;
2734 					bool bCompatibility = ( pInst && pInst->IsCompatibility() );
2735 					for( ;; )
2736 					{
2737 						if( pRTLData->nCurDirPos < 0 )
2738 						{
2739 							if( pRTLData->nCurDirPos == -2 )
2740 							{
2741 								aPath = ::rtl::OUString::createFromAscii( "." );
2742 							}
2743 							else if( pRTLData->nCurDirPos == -1 )
2744 							{
2745 								aPath = ::rtl::OUString::createFromAscii( ".." );
2746 							}
2747 							pRTLData->nCurDirPos++;
2748 						}
2749 						else if( pRTLData->nCurDirPos >= pRTLData->aDirSeq.getLength() )
2750 						{
2751 							pRTLData->aDirSeq.realloc( 0 );
2752 							aPath.Erase();
2753 							break;
2754 						}
2755 						else
2756 						{
2757 							::rtl::OUString aFile = pRTLData->aDirSeq.getConstArray()[pRTLData->nCurDirPos++];
2758 
2759 							if( bCompatibility )
2760 							{
2761 								if( !bFolderFlag )
2762 								{
2763 									sal_Bool bFolder = xSFI->isFolder( aFile );
2764 									if( bFolder )
2765 										continue;
2766 								}
2767 							}
2768 							else
2769 							{
2770 								// Only directories
2771 								if( bFolderFlag )
2772 								{
2773 									sal_Bool bFolder = xSFI->isFolder( aFile );
2774 									if( !bFolder )
2775 										continue;
2776 								}
2777 							}
2778 
2779 							INetURLObject aURL( aFile );
2780 							aPath = aURL.getName( INetURLObject::LAST_SEGMENT, sal_True,
2781 								INetURLObject::DECODE_WITH_CHARSET );
2782 						}
2783 
2784 						sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
2785 						if( !bMatch )
2786 							continue;
2787 
2788 						break;
2789 					}
2790 				}
2791 				rPar.Get(0)->PutString( aPath );
2792 			}
2793 		}
2794 		else
2795 		// --> UCB
2796 		{
2797 #ifdef _OLD_FILE_IMPL
2798 			if ( nParCount >= 2 )
2799 			{
2800 				delete pRTLData->pDir;
2801 				pRTLData->pDir = 0; // wg. Sonderbehandlung Sb_ATTR_VOLUME
2802 				DirEntry aEntry( rPar.Get(1)->GetString() );
2803 				FileStat aStat( aEntry );
2804 				if(!aStat.GetError() && (aStat.GetKind() & FSYS_KIND_FILE))
2805 				{
2806 					// ah ja, ist nur ein dateiname
2807 					// Pfad abschneiden (wg. VB4)
2808 					rPar.Get(0)->PutString( aEntry.GetName() );
2809 					return;
2810 				}
2811 				sal_uInt16 nFlags = 0;
2812 				if ( nParCount > 2 )
2813 					pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
2814 				else
2815 					pRTLData->nDirFlags = 0;
2816 
2817 				// Sb_ATTR_VOLUME wird getrennt gehandelt
2818 				if( pRTLData->nDirFlags & Sb_ATTR_VOLUME )
2819 					aPath = aEntry.GetVolume();
2820 				else
2821 				{
2822 					// Die richtige Auswahl treffen
2823 					sal_uInt16 nMode = FSYS_KIND_FILE;
2824 					if( nFlags & Sb_ATTR_DIRECTORY )
2825 						nMode |= FSYS_KIND_DIR;
2826 					if( nFlags == Sb_ATTR_DIRECTORY )
2827 						nMode = FSYS_KIND_DIR;
2828 					pRTLData->pDir = new Dir( aEntry, (DirEntryKind) nMode );
2829 					pRTLData->nCurDirPos = 0;
2830 				}
2831 			}
2832 
2833 			if( pRTLData->pDir )
2834 			{
2835 				for( ;; )
2836 				{
2837 					if( pRTLData->nCurDirPos >= pRTLData->pDir->Count() )
2838 					{
2839 						delete pRTLData->pDir;
2840 						pRTLData->pDir = 0;
2841 						aPath.Erase();
2842 						break;
2843 					}
2844 					DirEntry aNextEntry=(*(pRTLData->pDir))[pRTLData->nCurDirPos++];
2845 					aPath = aNextEntry.GetName(); //Full();
2846 					break;
2847 				}
2848 			}
2849 			rPar.Get(0)->PutString( aPath );
2850 #else
2851 			// TODO: OSL
2852 			if ( nParCount >= 2 )
2853 			{
2854 				String aFileParam = rPar.Get(1)->GetString();
2855 
2856 				String aDirURL = implSetupWildcard( aFileParam, pRTLData );
2857 
2858 				sal_uInt16 nFlags = 0;
2859 				if ( nParCount > 2 )
2860 					pRTLData->nDirFlags = nFlags = rPar.Get(2)->GetInteger();
2861 				else
2862 					pRTLData->nDirFlags = 0;
2863 
2864 				// Read directory
2865 				sal_Bool bIncludeFolders = ((nFlags & Sb_ATTR_DIRECTORY) != 0);
2866 				pRTLData->pDir = new Directory( aDirURL );
2867 				FileBase::RC nRet = pRTLData->pDir->open();
2868 				if( nRet != FileBase::E_None )
2869 				{
2870 					delete pRTLData->pDir;
2871 					pRTLData->pDir = NULL;
2872 					rPar.Get(0)->PutString( String() );
2873 					return;
2874 				}
2875 
2876 				// #86950 Add "." and ".." directories for VB compatibility
2877 				pRTLData->nCurDirPos = 0;
2878 				if( bIncludeFolders )
2879 				{
2880 					sal_Bool bRoot = isRootDir( aDirURL );
2881 
2882 					// If it's no root directory we flag the need for
2883 					// the "." and ".." directories by the value -2
2884 					// for the actual position. Later for -2 will be
2885 					// returned "." and for -1 ".."
2886 					if( !bRoot )
2887 					{
2888 						pRTLData->nCurDirPos = -2;
2889 					}
2890 				}
2891 
2892 			}
2893 
2894 			if( pRTLData->pDir )
2895 			{
2896 				sal_Bool bFolderFlag = ((pRTLData->nDirFlags & Sb_ATTR_DIRECTORY) != 0);
2897 				for( ;; )
2898 				{
2899 					if( pRTLData->nCurDirPos < 0 )
2900 					{
2901 						if( pRTLData->nCurDirPos == -2 )
2902 						{
2903 							aPath = ::rtl::OUString::createFromAscii( "." );
2904 						}
2905 						else if( pRTLData->nCurDirPos == -1 )
2906 						{
2907 							aPath = ::rtl::OUString::createFromAscii( ".." );
2908 						}
2909 						pRTLData->nCurDirPos++;
2910 					}
2911                     else
2912                     {
2913 					    DirectoryItem aItem;
2914 				        FileBase::RC nRet = pRTLData->pDir->getNextItem( aItem );
2915 					    if( nRet != FileBase::E_None )
2916 					    {
2917 						    delete pRTLData->pDir;
2918 						    pRTLData->pDir = NULL;
2919 						    aPath.Erase();
2920 						    break;
2921 					    }
2922 
2923 					    // Handle flags
2924 					    FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileName );
2925 					    nRet = aItem.getFileStatus( aFileStatus );
2926 
2927 					    // Only directories?
2928 					    if( bFolderFlag )
2929 					    {
2930 						    FileStatus::Type aType = aFileStatus.getFileType();
2931 						    sal_Bool bFolder = isFolder( aType );
2932 						    if( !bFolder )
2933 							    continue;
2934 					    }
2935 
2936 					    aPath = aFileStatus.getFileName();
2937                     }
2938 
2939 					sal_Bool bMatch = implCheckWildcard( aPath, pRTLData );
2940 					if( !bMatch )
2941 						continue;
2942 
2943 					break;
2944 				}
2945 			}
2946 			rPar.Get(0)->PutString( aPath );
2947 #endif
2948 		}
2949 	}
2950 }
2951 
2952 
RTLFUNC(GetAttr)2953 RTLFUNC(GetAttr)
2954 {
2955     (void)pBasic;
2956     (void)bWrite;
2957 
2958 	if ( rPar.Count() == 2 )
2959 	{
2960 		sal_Int16 nFlags = 0;
2961 
2962 		// In Windows, We want to use Windows API to get the file attributes
2963 		// for VBA interoperability.
2964 	#if defined( WNT )
2965 		if( SbiRuntime::isVBAEnabled() )
2966 		{
2967 			DirEntry aEntry( rPar.Get(1)->GetString() );
2968 			aEntry.ToAbs();
2969 
2970 			// #57064 Bei virtuellen URLs den Real-Path extrahieren
2971 			ByteString aByteStrFullPath( aEntry.GetFull(), gsl_getSystemTextEncoding() );
2972 			DWORD nRealFlags = GetFileAttributes (aByteStrFullPath.GetBuffer());
2973 			if (nRealFlags != 0xffffffff)
2974 			{
2975 				if (nRealFlags == FILE_ATTRIBUTE_NORMAL)
2976 					nRealFlags = 0;
2977 				nFlags = (sal_Int16) (nRealFlags);
2978 			}
2979 			else
2980 				StarBASIC::Error( SbERR_FILE_NOT_FOUND );
2981 
2982 			rPar.Get(0)->PutInteger( nFlags );
2983 
2984 			return;
2985 		}
2986 	#endif
2987 
2988 		// <-- UCB
2989 		if( hasUno() )
2990 		{
2991 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
2992 			if( xSFI.is() )
2993 			{
2994 				try
2995 				{
2996 					String aPath = getFullPath( rPar.Get(1)->GetString() );
2997 					sal_Bool bExists = sal_False;
2998 					try { bExists = xSFI->exists( aPath ); }
2999 					catch( Exception & ) {}
3000 					if( !bExists )
3001 					{
3002 						StarBASIC::Error( SbERR_FILE_NOT_FOUND );
3003 						return;
3004 					}
3005 
3006 					sal_Bool bReadOnly = xSFI->isReadOnly( aPath );
3007 					sal_Bool bHidden = xSFI->isHidden( aPath );
3008 					sal_Bool bDirectory = xSFI->isFolder( aPath );
3009 					if( bReadOnly )
3010 						nFlags |= 0x0001; // ATTR_READONLY
3011 					if( bHidden )
3012 						nFlags |= 0x0002; // ATTR_HIDDEN
3013 					if( bDirectory )
3014 						nFlags |= 0x0010; // ATTR_DIRECTORY
3015 				}
3016 				catch( Exception & )
3017 				{
3018 					StarBASIC::Error( ERRCODE_IO_GENERAL );
3019 				}
3020 			}
3021 		}
3022 		else
3023 		// --> UCB
3024 		{
3025 			DirectoryItem aItem;
3026 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( rPar.Get(1)->GetString() ), aItem );
3027 			FileStatus aFileStatus( FileStatusMask_Attributes | FileStatusMask_Type );
3028 			nRet = aItem.getFileStatus( aFileStatus );
3029 			sal_uInt64 nAttributes = aFileStatus.getAttributes();
3030 			sal_Bool bReadOnly = (nAttributes & Attribute_ReadOnly) != 0;
3031 
3032 			FileStatus::Type aType = aFileStatus.getFileType();
3033 			sal_Bool bDirectory = isFolder( aType );
3034 			if( bReadOnly )
3035 				nFlags |= 0x0001; // ATTR_READONLY
3036 			if( bDirectory )
3037 				nFlags |= 0x0010; // ATTR_DIRECTORY
3038 		}
3039 		rPar.Get(0)->PutInteger( nFlags );
3040 	}
3041 	else
3042 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3043 }
3044 
3045 
RTLFUNC(FileDateTime)3046 RTLFUNC(FileDateTime)
3047 {
3048     (void)pBasic;
3049     (void)bWrite;
3050 
3051 	if ( rPar.Count() != 2 )
3052 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3053 	else
3054 	{
3055 		// <-- UCB
3056 		String aPath = rPar.Get(1)->GetString();
3057 		Time aTime;
3058 		Date aDate;
3059 		if( hasUno() )
3060 		{
3061 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
3062 			if( xSFI.is() )
3063 			{
3064 				try
3065 				{
3066 					com::sun::star::util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath );
3067 					aTime = Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds );
3068 					aDate = Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year );
3069 				}
3070 				catch( Exception & )
3071 				{
3072 					StarBASIC::Error( ERRCODE_IO_GENERAL );
3073 				}
3074 			}
3075 		}
3076 		else
3077 		// --> UCB
3078 		{
3079 #ifdef _OLD_FILE_IMPL
3080 			DirEntry aEntry( aPath );
3081 			FileStat aStat( aEntry );
3082 			aTime = Time( aStat.TimeModified() );
3083 			aDate = Date( aStat.DateModified() );
3084 #else
3085 			DirectoryItem aItem;
3086 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aPath ), aItem );
3087 			FileStatus aFileStatus( FileStatusMask_ModifyTime );
3088 		    nRet = aItem.getFileStatus( aFileStatus );
3089 		    TimeValue aTimeVal = aFileStatus.getModifyTime();
3090 			oslDateTime aDT;
3091 			osl_getDateTimeFromTimeValue( &aTimeVal, &aDT );
3092 
3093 			aTime = Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 10000000*aDT.NanoSeconds );
3094 			aDate = Date( aDT.Day, aDT.Month, aDT.Year );
3095 #endif
3096 		}
3097 
3098 		double fSerial = (double)GetDayDiff( aDate );
3099 		long nSeconds = aTime.GetHour();
3100 		nSeconds *= 3600;
3101 		nSeconds += aTime.GetMin() * 60;
3102 		nSeconds += aTime.GetSec();
3103 		double nDays = ((double)nSeconds) / (double)(24.0*3600.0);
3104 		fSerial += nDays;
3105 
3106 		Color* pCol;
3107 
3108 		// #39629 pINST pruefen, kann aus URL-Zeile gerufen werden
3109 		SvNumberFormatter* pFormatter = NULL;
3110 		sal_uInt32 nIndex;
3111 		if( pINST )
3112 		{
3113 			pFormatter = pINST->GetNumberFormatter();
3114 			nIndex = pINST->GetStdDateTimeIdx();
3115 		}
3116 		else
3117 		{
3118 			sal_uInt32 n;	// Dummy
3119 			SbiInstance::PrepareNumberFormatter( pFormatter, n, n, nIndex );
3120 		}
3121 
3122 		String aRes;
3123 		pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol );
3124 		rPar.Get(0)->PutString( aRes );
3125 
3126 		// #39629 pFormatter kann selbst angefordert sein
3127 		if( !pINST )
3128 			delete pFormatter;
3129 	}
3130 }
3131 
3132 
RTLFUNC(EOF)3133 RTLFUNC(EOF)
3134 {
3135     (void)pBasic;
3136     (void)bWrite;
3137 
3138 	// AB 08/16/2000: No changes for UCB
3139 	if ( rPar.Count() != 2 )
3140 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3141 	else
3142 	{
3143 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3144 		// nChannel--;  // macht MD beim Oeffnen auch nicht
3145 		SbiIoSystem* pIO = pINST->GetIoSystem();
3146 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3147 		if ( !pSbStrm )
3148 		{
3149 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3150 			return;
3151 		}
3152 		sal_Bool bIsEof;
3153 		SvStream* pSvStrm = pSbStrm->GetStrm();
3154 		if ( pSbStrm->IsText() )
3155 		{
3156 			char cBla;
3157 			(*pSvStrm) >> cBla;	// koennen wir noch ein Zeichen lesen
3158 			bIsEof = pSvStrm->IsEof();
3159 			if ( !bIsEof )
3160 				pSvStrm->SeekRel( -1 );
3161 		}
3162 		else
3163 			bIsEof = pSvStrm->IsEof();  // fuer binaerdateien!
3164 		rPar.Get(0)->PutBool( bIsEof );
3165 	}
3166 }
3167 
RTLFUNC(FileAttr)3168 RTLFUNC(FileAttr)
3169 {
3170     (void)pBasic;
3171     (void)bWrite;
3172 
3173 	// AB 08/16/2000: No changes for UCB
3174 
3175 	// #57064 Obwohl diese Funktion nicht mit DirEntry arbeitet, ist sie von
3176 	// der Anpassung an virtuelle URLs nich betroffen, da sie nur auf bereits
3177 	// geoeffneten Dateien arbeitet und der Name hier keine Rolle spielt.
3178 
3179 	if ( rPar.Count() != 3 )
3180 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3181 	else
3182 	{
3183 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3184 //		nChannel--;
3185 		SbiIoSystem* pIO = pINST->GetIoSystem();
3186 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3187 		if ( !pSbStrm )
3188 		{
3189 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3190 			return;
3191 		}
3192 		sal_Int16 nRet;
3193 		if ( rPar.Get(2)->GetInteger() == 1 )
3194 			nRet = (sal_Int16)(pSbStrm->GetMode());
3195 		else
3196 			nRet = 0; // System file handle not supported
3197 
3198 		rPar.Get(0)->PutInteger( nRet );
3199 	}
3200 }
RTLFUNC(Loc)3201 RTLFUNC(Loc)
3202 {
3203     (void)pBasic;
3204     (void)bWrite;
3205 
3206 	// AB 08/16/2000: No changes for UCB
3207 	if ( rPar.Count() != 2 )
3208 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3209 	else
3210 	{
3211 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3212 		SbiIoSystem* pIO = pINST->GetIoSystem();
3213 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3214 		if ( !pSbStrm )
3215 		{
3216 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3217 			return;
3218 		}
3219 		SvStream* pSvStrm = pSbStrm->GetStrm();
3220 		sal_uIntPtr nPos;
3221 		if( pSbStrm->IsRandom())
3222 		{
3223 			short nBlockLen = pSbStrm->GetBlockLen();
3224 			nPos = nBlockLen ? (pSvStrm->Tell() / nBlockLen) : 0;
3225 			nPos++; // Blockpositionen beginnen bei 1
3226 		}
3227 		else if ( pSbStrm->IsText() )
3228 			nPos = pSbStrm->GetLine();
3229 		else if( pSbStrm->IsBinary() )
3230 			nPos = pSvStrm->Tell();
3231 		else if ( pSbStrm->IsSeq() )
3232 			nPos = ( pSvStrm->Tell()+1 ) / 128;
3233 		else
3234 			nPos = pSvStrm->Tell();
3235 		rPar.Get(0)->PutLong( (sal_Int32)nPos );
3236 	}
3237 }
3238 
RTLFUNC(Lof)3239 RTLFUNC(Lof)
3240 {
3241     (void)pBasic;
3242     (void)bWrite;
3243 
3244 	// AB 08/16/2000: No changes for UCB
3245 	if ( rPar.Count() != 2 )
3246 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3247 	else
3248 	{
3249 		sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3250 		SbiIoSystem* pIO = pINST->GetIoSystem();
3251 		SbiStream* pSbStrm = pIO->GetStream( nChannel );
3252 		if ( !pSbStrm )
3253 		{
3254 			StarBASIC::Error( SbERR_BAD_CHANNEL );
3255 			return;
3256 		}
3257 		SvStream* pSvStrm = pSbStrm->GetStrm();
3258 		sal_uIntPtr nOldPos = pSvStrm->Tell();
3259 		sal_uIntPtr nLen = pSvStrm->Seek( STREAM_SEEK_TO_END );
3260 		pSvStrm->Seek( nOldPos );
3261 		rPar.Get(0)->PutLong( (sal_Int32)nLen );
3262 	}
3263 }
3264 
3265 
RTLFUNC(Seek)3266 RTLFUNC(Seek)
3267 {
3268     (void)pBasic;
3269     (void)bWrite;
3270 
3271 	// AB 08/16/2000: No changes for UCB
3272 	int nArgs = (int)rPar.Count();
3273 	if ( nArgs < 2 || nArgs > 3 )
3274 	{
3275 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3276 		return;
3277 	}
3278 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3279 //	nChannel--;
3280 	SbiIoSystem* pIO = pINST->GetIoSystem();
3281 	SbiStream* pSbStrm = pIO->GetStream( nChannel );
3282 	if ( !pSbStrm )
3283 	{
3284 		StarBASIC::Error( SbERR_BAD_CHANNEL );
3285 		return;
3286 	}
3287 	SvStream* pStrm = pSbStrm->GetStrm();
3288 
3289 	if ( nArgs == 2 )   // Seek-Function
3290 	{
3291 		sal_uIntPtr nPos = pStrm->Tell();
3292 		if( pSbStrm->IsRandom() )
3293 			nPos = nPos / pSbStrm->GetBlockLen();
3294 		nPos++;	// Basic zaehlt ab 1
3295 		rPar.Get(0)->PutLong( (sal_Int32)nPos );
3296 	}
3297 	else                // Seek-Statement
3298 	{
3299 		sal_Int32 nPos = rPar.Get(2)->GetLong();
3300 		if ( nPos < 1 )
3301 		{
3302 			StarBASIC::Error( SbERR_BAD_ARGUMENT );
3303 			return;
3304 		}
3305 		nPos--; // Basic zaehlt ab 1, SvStreams zaehlen ab 0
3306 		pSbStrm->SetExpandOnWriteTo( 0 );
3307 		if ( pSbStrm->IsRandom() )
3308 			nPos *= pSbStrm->GetBlockLen();
3309 		pStrm->Seek( (sal_uIntPtr)nPos );
3310 		pSbStrm->SetExpandOnWriteTo( nPos );
3311 	}
3312 }
3313 
RTLFUNC(Format)3314 RTLFUNC(Format)
3315 {
3316     (void)pBasic;
3317     (void)bWrite;
3318 
3319 	sal_uInt16 nArgCount = (sal_uInt16)rPar.Count();
3320 	if ( nArgCount < 2 || nArgCount > 3 )
3321 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3322 	else
3323 	{
3324 		String aResult;
3325 		if( nArgCount == 2 )
3326 			rPar.Get(1)->Format( aResult );
3327 		else
3328 		{
3329 			String aFmt( rPar.Get(2)->GetString() );
3330 		    rPar.Get(1)->Format( aResult, &aFmt );
3331 		}
3332 		rPar.Get(0)->PutString( aResult );
3333 	}
3334 }
3335 
RTLFUNC(Randomize)3336 RTLFUNC(Randomize)
3337 {
3338     (void)pBasic;
3339     (void)bWrite;
3340 
3341 	if ( rPar.Count() > 2 )
3342 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3343 	sal_Int16 nSeed;
3344 	if( rPar.Count() == 2 )
3345 		nSeed = (sal_Int16)rPar.Get(1)->GetInteger();
3346 	else
3347 		nSeed = (sal_Int16)rand();
3348 	srand( nSeed );
3349 }
3350 
RTLFUNC(Rnd)3351 RTLFUNC(Rnd)
3352 {
3353     (void)pBasic;
3354     (void)bWrite;
3355 
3356 	if ( rPar.Count() > 2 )
3357 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3358 	else
3359 	{
3360 		double nRand = (double)rand();
3361 		nRand = ( nRand / (double)RAND_MAX );
3362 		rPar.Get(0)->PutDouble( nRand );
3363 	}
3364 }
3365 
3366 
3367 //
3368 //  Syntax: Shell("Path",[ Window-Style,[ "Params", [ bSync = sal_False ]]])
3369 //
3370 //  WindowStyles (VBA-kompatibel):
3371 //      2 == Minimized
3372 //	    3 == Maximized
3373 //     10 == Full-Screen (Textmodus-Anwendungen OS/2, WIN95, WNT)
3374 //
3375 // !!!HACK der WindowStyle wird im Creator an Application::StartApp
3376 //         uebergeben. Format: "xxxx2"
3377 //
3378 
3379 
RTLFUNC(Shell)3380 RTLFUNC(Shell)
3381 {
3382     (void)pBasic;
3383     (void)bWrite;
3384 
3385 	// No shell command for "virtual" portal users
3386 	if( needSecurityRestrictions() )
3387 	{
3388 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3389 		return;
3390 	}
3391 
3392 	sal_uIntPtr nArgCount = rPar.Count();
3393 	if ( nArgCount < 2 || nArgCount > 5 )
3394 	{
3395 		rPar.Get(0)->PutLong(0);
3396 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3397 	}
3398 	else
3399 	{
3400 		sal_uInt16 nOptions = vos::OProcess::TOption_SearchPath|
3401 						  vos::OProcess::TOption_Detached;
3402 		String aCmdLine = rPar.Get(1)->GetString();
3403 		// Zusaetzliche Parameter anhaengen, es muss eh alles geparsed werden
3404 		if( nArgCount >= 4 )
3405 		{
3406 			aCmdLine.AppendAscii( " " );
3407 			aCmdLine += rPar.Get(3)->GetString();
3408 		}
3409 		else if( !aCmdLine.Len() )
3410 		{
3411 			// Spezial-Behandlung (leere Liste) vermeiden
3412 			aCmdLine.AppendAscii( " " );
3413 		}
3414 		sal_uInt16 nLen = aCmdLine.Len();
3415 
3416 		// #55735 Wenn Parameter dabei sind, muessen die abgetrennt werden
3417 		// #72471 Auch die einzelnen Parameter trennen
3418 		std::list<String> aTokenList;
3419 		String aToken;
3420 		sal_uInt16 i = 0;
3421 		sal_Unicode c;
3422 		while( i < nLen )
3423 		{
3424 			// Spaces weg
3425             for ( ;; ++i )
3426             {
3427                 c = aCmdLine.GetBuffer()[ i ];
3428                 if ( c != ' ' && c != '\t' )
3429                     break;
3430             }
3431 
3432 			if( c == '\"' || c == '\'' )
3433 			{
3434 				sal_uInt16 iFoundPos = aCmdLine.Search( c, i + 1 );
3435 
3436 				// Wenn nichts gefunden wurde, Rest kopieren
3437 				if( iFoundPos == STRING_NOTFOUND )
3438 				{
3439 					aToken = aCmdLine.Copy( i, STRING_LEN );
3440 					i = nLen;
3441 				}
3442 				else
3443 				{
3444 					aToken = aCmdLine.Copy( i + 1, (iFoundPos - i - 1) );
3445 					i = iFoundPos + 1;
3446 				}
3447 			}
3448 			else
3449 			{
3450 				sal_uInt16 iFoundSpacePos = aCmdLine.Search( ' ', i );
3451 				sal_uInt16 iFoundTabPos = aCmdLine.Search( '\t', i );
3452 				sal_uInt16 iFoundPos = Min( iFoundSpacePos, iFoundTabPos );
3453 
3454 				// Wenn nichts gefunden wurde, Rest kopieren
3455 				if( iFoundPos == STRING_NOTFOUND )
3456 				{
3457 					aToken = aCmdLine.Copy( i, STRING_LEN );
3458 					i = nLen;
3459 				}
3460 				else
3461 				{
3462 					aToken = aCmdLine.Copy( i, (iFoundPos - i) );
3463 					i = iFoundPos;
3464 				}
3465 			}
3466 
3467 			// In die Liste uebernehmen
3468 			aTokenList.push_back( aToken );
3469 		}
3470 		// #55735 / #72471 Ende
3471 
3472 		sal_Int16 nWinStyle = 0;
3473 		if( nArgCount >= 3 )
3474 		{
3475 			nWinStyle = rPar.Get(2)->GetInteger();
3476 			switch( nWinStyle )
3477 			{
3478 				case 2:
3479 					nOptions |= vos::OProcess::TOption_Minimized;
3480 					break;
3481 				case 3:
3482 					nOptions |= vos::OProcess::TOption_Maximized;
3483 					break;
3484 				case 10:
3485 					nOptions |= vos::OProcess::TOption_FullScreen;
3486 					break;
3487 			}
3488 
3489 			sal_Bool bSync = sal_False;
3490 			if( nArgCount >= 5 )
3491 				bSync = rPar.Get(4)->GetBool();
3492 			if( bSync )
3493 				nOptions |= vos::OProcess::TOption_Wait;
3494 		}
3495 		vos::OProcess::TProcessOption eOptions =
3496 			(vos::OProcess::TProcessOption)nOptions;
3497 
3498 
3499 		// #72471 Parameter aufbereiten
3500 		std::list<String>::const_iterator iter = aTokenList.begin();
3501 		const String& rStr = *iter;
3502 		::rtl::OUString aOUStrProg( rStr.GetBuffer(), rStr.Len() );
3503 		String aOUStrProgUNC = getFullPathUNC( aOUStrProg );
3504 
3505 		iter++;
3506 
3507 		sal_uInt16 nParamCount = sal::static_int_cast< sal_uInt16 >(
3508             aTokenList.size() - 1 );
3509 		::rtl::OUString* pArgumentList = NULL;
3510 		//const char** pParamList = NULL;
3511 		if( nParamCount )
3512 		{
3513 			pArgumentList = new ::rtl::OUString[ nParamCount ];
3514 			//pParamList = new const char*[ nParamCount ];
3515 			sal_uInt16 iList = 0;
3516 			while( iter != aTokenList.end() )
3517 			{
3518 				const String& rParamStr = (*iter);
3519 				pArgumentList[iList++] = ::rtl::OUString( rParamStr.GetBuffer(), rParamStr.Len() );
3520 				//pParamList[iList++] = (*iter).GetStr();
3521 				iter++;
3522 			}
3523 		}
3524 
3525 		//const char* pParams = aParams.Len() ? aParams.GetStr() : 0;
3526 		vos::OProcess* pApp;
3527 		pApp = new vos::OProcess( aOUStrProgUNC );
3528 		sal_Bool bSucc;
3529 		if( nParamCount == 0 )
3530 		{
3531 			bSucc = pApp->execute( eOptions ) == vos::OProcess::E_None;
3532 		}
3533 		else
3534 		{
3535 		    vos::OArgumentList aArgList( pArgumentList, nParamCount );
3536 			bSucc = pApp->execute( eOptions, aArgList ) == vos::OProcess::E_None;
3537 		}
3538 
3539 		/*
3540 		if( nParamCount == 0 )
3541 			pApp = new vos::OProcess( pProg );
3542 		else
3543 			pApp = new vos::OProcess( pProg, pParamList, nParamCount );
3544 		sal_Bool bSucc = pApp->execute( eOptions ) == vos::OProcess::E_None;
3545 		*/
3546 
3547 		delete pApp;
3548 		delete[] pArgumentList;
3549 		if( !bSucc )
3550 			StarBASIC::Error( SbERR_FILE_NOT_FOUND );
3551 		else
3552 			rPar.Get(0)->PutLong( 0 );
3553 	}
3554 }
3555 
RTLFUNC(VarType)3556 RTLFUNC(VarType)
3557 {
3558     (void)pBasic;
3559     (void)bWrite;
3560 
3561 	if ( rPar.Count() != 2 )
3562 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3563 	else
3564 	{
3565 		SbxDataType eType = rPar.Get(1)->GetType();
3566 		rPar.Get(0)->PutInteger( (sal_Int16)eType );
3567 	}
3568 }
3569 
3570 // Exported function
getBasicTypeName(SbxDataType eType)3571 String getBasicTypeName( SbxDataType eType )
3572 {
3573 	static const char* pTypeNames[] =
3574 	{
3575 		"Empty",            // SbxEMPTY
3576 		"Null",             // SbxNULL
3577 		"Integer",          // SbxINTEGER
3578 		"Long",             // SbxLONG
3579 		"Single",           // SbxSINGLE
3580 		"Double",           // SbxDOUBLE
3581 		"Currency",         // SbxCURRENCY
3582 		"Date",             // SbxDATE
3583 		"String",           // SbxSTRING
3584 		"Object",           // SbxOBJECT
3585 		"Error",            // SbxERROR
3586 		"Boolean",          // SbxBOOL
3587 		"Variant",          // SbxVARIANT
3588 		"DataObject",       // SbxDATAOBJECT
3589 		"Unknown Type",     //
3590 		"Unknown Type",     //
3591 		"Char",             // SbxCHAR
3592 		"Byte",             // SbxBYTE
3593 		"UShort",           // SbxUSHORT
3594 		"ULong",            // SbxULONG
3595 		"Long64",           // SbxLONG64
3596 		"ULong64",          // SbxULONG64
3597 		"Int",              // SbxINT
3598 		"UInt",             // SbxUINT
3599 		"Void",             // SbxVOID
3600 		"HResult",          // SbxHRESULT
3601 		"Pointer",          // SbxPOINTER
3602 		"DimArray",         // SbxDIMARRAY
3603 		"CArray",           // SbxCARRAY
3604 		"Userdef",          // SbxUSERDEF
3605 		"Lpstr",            // SbxLPSTR
3606 		"Lpwstr",           // SbxLPWSTR
3607 		"Unknown Type",     // SbxCoreSTRING
3608 		"WString",          // SbxWSTRING
3609 		"WChar",            // SbxWCHAR
3610 		"Int64",            // SbxSALINT64
3611 		"UInt64",           // SbxSALUINT64
3612 		"Decimal",          // SbxDECIMAL
3613 	};
3614 
3615 	int nPos = ((int)eType) & 0x0FFF;
3616 	sal_uInt16 nTypeNameCount = sizeof( pTypeNames ) / sizeof( char* );
3617 	if ( nPos < 0 || nPos >= nTypeNameCount )
3618 		nPos = nTypeNameCount - 1;
3619 	String aRetStr = String::CreateFromAscii( pTypeNames[nPos] );
3620 	return aRetStr;
3621 }
3622 
RTLFUNC(TypeName)3623 RTLFUNC(TypeName)
3624 {
3625     (void)pBasic;
3626     (void)bWrite;
3627 
3628 	if ( rPar.Count() != 2 )
3629 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3630 	else
3631 	{
3632 		SbxDataType eType = rPar.Get(1)->GetType();
3633 		sal_Bool bIsArray = ( ( eType & SbxARRAY ) != 0 );
3634 		String aRetStr = getBasicTypeName( eType );
3635 		if( bIsArray )
3636 			aRetStr.AppendAscii( "()" );
3637 		rPar.Get(0)->PutString( aRetStr );
3638 	}
3639 }
3640 
RTLFUNC(Len)3641 RTLFUNC(Len)
3642 {
3643     (void)pBasic;
3644     (void)bWrite;
3645 
3646 	if ( rPar.Count() != 2 )
3647 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3648 	else
3649 	{
3650 		const String& rStr = rPar.Get(1)->GetString();
3651 		rPar.Get(0)->PutLong( (sal_Int32)rStr.Len() );
3652 	}
3653 }
3654 
RTLFUNC(DDEInitiate)3655 RTLFUNC(DDEInitiate)
3656 {
3657     (void)pBasic;
3658     (void)bWrite;
3659 
3660 	// No DDE for "virtual" portal users
3661 	if( needSecurityRestrictions() )
3662 	{
3663 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3664 		return;
3665 	}
3666 
3667 	int nArgs = (int)rPar.Count();
3668 	if ( nArgs != 3 )
3669 	{
3670 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3671 		return;
3672 	}
3673 	const String& rApp = rPar.Get(1)->GetString();
3674 	const String& rTopic = rPar.Get(2)->GetString();
3675 
3676 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3677 	sal_Int16 nChannel;
3678 	SbError nDdeErr = pDDE->Initiate( rApp, rTopic, nChannel );
3679 	if( nDdeErr )
3680 		StarBASIC::Error( nDdeErr );
3681 	else
3682 		rPar.Get(0)->PutInteger( nChannel );
3683 }
3684 
RTLFUNC(DDETerminate)3685 RTLFUNC(DDETerminate)
3686 {
3687     (void)pBasic;
3688     (void)bWrite;
3689 
3690 	// No DDE for "virtual" portal users
3691 	if( needSecurityRestrictions() )
3692 	{
3693 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3694 		return;
3695 	}
3696 
3697 	rPar.Get(0)->PutEmpty();
3698 	int nArgs = (int)rPar.Count();
3699 	if ( nArgs != 2 )
3700 	{
3701 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3702 		return;
3703 	}
3704 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3705 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3706 	SbError nDdeErr = pDDE->Terminate( nChannel );
3707 	if( nDdeErr )
3708 		StarBASIC::Error( nDdeErr );
3709 }
3710 
RTLFUNC(DDETerminateAll)3711 RTLFUNC(DDETerminateAll)
3712 {
3713     (void)pBasic;
3714     (void)bWrite;
3715 
3716 	// No DDE for "virtual" portal users
3717 	if( needSecurityRestrictions() )
3718 	{
3719 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3720 		return;
3721 	}
3722 
3723 	rPar.Get(0)->PutEmpty();
3724 	int nArgs = (int)rPar.Count();
3725 	if ( nArgs != 1 )
3726 	{
3727 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3728 		return;
3729 	}
3730 
3731 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3732 	SbError nDdeErr = pDDE->TerminateAll();
3733 	if( nDdeErr )
3734 		StarBASIC::Error( nDdeErr );
3735 
3736 }
3737 
RTLFUNC(DDERequest)3738 RTLFUNC(DDERequest)
3739 {
3740     (void)pBasic;
3741     (void)bWrite;
3742 
3743 	// No DDE for "virtual" portal users
3744 	if( needSecurityRestrictions() )
3745 	{
3746 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3747 		return;
3748 	}
3749 
3750 	int nArgs = (int)rPar.Count();
3751 	if ( nArgs != 3 )
3752 	{
3753 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3754 		return;
3755 	}
3756 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3757 	const String& rItem = rPar.Get(2)->GetString();
3758 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3759 	String aResult;
3760 	SbError nDdeErr = pDDE->Request( nChannel, rItem, aResult );
3761 	if( nDdeErr )
3762 		StarBASIC::Error( nDdeErr );
3763 	else
3764 		rPar.Get(0)->PutString( aResult );
3765 }
3766 
RTLFUNC(DDEExecute)3767 RTLFUNC(DDEExecute)
3768 {
3769     (void)pBasic;
3770     (void)bWrite;
3771 
3772 	// No DDE for "virtual" portal users
3773 	if( needSecurityRestrictions() )
3774 	{
3775 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3776 		return;
3777 	}
3778 
3779 	rPar.Get(0)->PutEmpty();
3780 	int nArgs = (int)rPar.Count();
3781 	if ( nArgs != 3 )
3782 	{
3783 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3784 		return;
3785 	}
3786 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3787 	const String& rCommand = rPar.Get(2)->GetString();
3788 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3789 	SbError nDdeErr = pDDE->Execute( nChannel, rCommand );
3790 	if( nDdeErr )
3791 		StarBASIC::Error( nDdeErr );
3792 }
3793 
RTLFUNC(DDEPoke)3794 RTLFUNC(DDEPoke)
3795 {
3796     (void)pBasic;
3797     (void)bWrite;
3798 
3799 	// No DDE for "virtual" portal users
3800 	if( needSecurityRestrictions() )
3801 	{
3802 		StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
3803 		return;
3804 	}
3805 
3806 	rPar.Get(0)->PutEmpty();
3807 	int nArgs = (int)rPar.Count();
3808 	if ( nArgs != 4 )
3809 	{
3810 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3811 		return;
3812 	}
3813 	sal_Int16 nChannel = rPar.Get(1)->GetInteger();
3814 	const String& rItem = rPar.Get(2)->GetString();
3815 	const String& rData = rPar.Get(3)->GetString();
3816 	SbiDdeControl* pDDE = pINST->GetDdeControl();
3817 	SbError nDdeErr = pDDE->Poke( nChannel, rItem, rData );
3818 	if( nDdeErr )
3819 		StarBASIC::Error( nDdeErr );
3820 }
3821 
3822 
RTLFUNC(FreeFile)3823 RTLFUNC(FreeFile)
3824 {
3825     (void)pBasic;
3826     (void)bWrite;
3827 
3828 	if ( rPar.Count() != 1 )
3829 	{
3830 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3831 		return;
3832 	}
3833 	SbiIoSystem* pIO = pINST->GetIoSystem();
3834 	short nChannel = 1;
3835 	while( nChannel < CHANNELS )
3836 	{
3837 		SbiStream* pStrm = pIO->GetStream( nChannel );
3838 		if( !pStrm )
3839 		{
3840 			rPar.Get(0)->PutInteger( nChannel );
3841 			return;
3842 		}
3843 		nChannel++;
3844 	}
3845 	StarBASIC::Error( SbERR_TOO_MANY_FILES );
3846 }
3847 
RTLFUNC(LBound)3848 RTLFUNC(LBound)
3849 {
3850     (void)pBasic;
3851     (void)bWrite;
3852 
3853 	sal_uInt16 nParCount = rPar.Count();
3854 	if ( nParCount != 3 && nParCount != 2 )
3855 	{
3856 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3857 		return;
3858 	}
3859 	SbxBase* pParObj = rPar.Get(1)->GetObject();
3860 	SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
3861 	if( pArr )
3862 	{
3863 		sal_Int32 nLower, nUpper;
3864 		short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1;
3865 		if( !pArr->GetDim32( nDim, nLower, nUpper ) )
3866 			StarBASIC::Error( SbERR_OUT_OF_RANGE );
3867 		else
3868 			rPar.Get(0)->PutLong( nLower );
3869 	}
3870 	else
3871 		StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
3872 }
3873 
RTLFUNC(UBound)3874 RTLFUNC(UBound)
3875 {
3876     (void)pBasic;
3877     (void)bWrite;
3878 
3879 	sal_uInt16 nParCount = rPar.Count();
3880 	if ( nParCount != 3 && nParCount != 2 )
3881 	{
3882 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3883 		return;
3884 	}
3885 
3886 	SbxBase* pParObj = rPar.Get(1)->GetObject();
3887 	SbxDimArray* pArr = PTR_CAST(SbxDimArray,pParObj);
3888 	if( pArr )
3889 	{
3890 		sal_Int32 nLower, nUpper;
3891 		short nDim = (nParCount == 3) ? (short)rPar.Get(2)->GetInteger() : 1;
3892 		if( !pArr->GetDim32( nDim, nLower, nUpper ) )
3893 			StarBASIC::Error( SbERR_OUT_OF_RANGE );
3894 		else
3895 			rPar.Get(0)->PutLong( nUpper );
3896 	}
3897 	else
3898 		StarBASIC::Error( SbERR_MUST_HAVE_DIMS );
3899 }
3900 
RTLFUNC(RGB)3901 RTLFUNC(RGB)
3902 {
3903     (void)pBasic;
3904     (void)bWrite;
3905 
3906 	if ( rPar.Count() != 4 )
3907 	{
3908 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3909 		return;
3910 	}
3911 
3912 	sal_uIntPtr nRed	 = rPar.Get(1)->GetInteger() & 0xFF;
3913 	sal_uIntPtr nGreen = rPar.Get(2)->GetInteger() & 0xFF;
3914 	sal_uIntPtr nBlue  = rPar.Get(3)->GetInteger() & 0xFF;
3915 	sal_uIntPtr nRGB;
3916 
3917 	SbiInstance* pInst = pINST;
3918 	bool bCompatibility = ( pInst && pInst->IsCompatibility() );
3919 	if( bCompatibility )
3920 	{
3921 		nRGB   = (nBlue << 16) | (nGreen << 8) | nRed;
3922 	}
3923 	else
3924 	{
3925 		nRGB   = (nRed << 16) | (nGreen << 8) | nBlue;
3926 	}
3927 	rPar.Get(0)->PutLong( nRGB );
3928 }
3929 
RTLFUNC(QBColor)3930 RTLFUNC(QBColor)
3931 {
3932     (void)pBasic;
3933     (void)bWrite;
3934 
3935 	static const sal_Int32 pRGB[] =
3936 	{
3937 		0x000000,
3938 		0x800000,
3939 		0x008000,
3940 		0x808000,
3941 		0x000080,
3942 		0x800080,
3943 		0x008080,
3944 		0xC0C0C0,
3945 		0x808080,
3946 		0xFF0000,
3947 		0x00FF00,
3948 		0xFFFF00,
3949 		0x0000FF,
3950 		0xFF00FF,
3951 		0x00FFFF,
3952 		0xFFFFFF,
3953 	};
3954 
3955 	if ( rPar.Count() != 2 )
3956 	{
3957 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3958 		return;
3959 	}
3960 
3961 	sal_Int16 nCol = rPar.Get(1)->GetInteger();
3962 	if( nCol < 0 || nCol > 15 )
3963 	{
3964 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3965 		return;
3966 	}
3967 	sal_Int32 nRGB = pRGB[ nCol ];
3968 	rPar.Get(0)->PutLong( nRGB );
3969 }
3970 
3971 // StrConv(string, conversion, LCID)
RTLFUNC(StrConv)3972 RTLFUNC(StrConv)
3973 {
3974     (void)pBasic;
3975     (void)bWrite;
3976 
3977 	sal_uIntPtr nArgCount = rPar.Count()-1;
3978 	if( nArgCount < 2 || nArgCount > 3 )
3979 	{
3980 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
3981 		return;
3982 	}
3983 
3984 	String aOldStr = rPar.Get(1)->GetString();
3985 	sal_Int32 nConversion = rPar.Get(2)->GetLong();
3986 
3987 	sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
3988 	if( nArgCount == 3 )
3989 	{
3990 		// LCID not supported now
3991 		//nLanguage = rPar.Get(3)->GetInteger();
3992 	}
3993 
3994 	sal_uInt16 nOldLen = aOldStr.Len();
3995 	if( nOldLen == 0 )
3996 	{
3997 		// null string,return
3998 		rPar.Get(0)->PutString(aOldStr);
3999 		return;
4000 	}
4001 
4002 	sal_Int32 nType = 0;
4003 	if ( (nConversion & 0x03) == 3 ) //  vbProperCase
4004 	{
4005 		CharClass& rCharClass = GetCharClass();
4006 		aOldStr = rCharClass.toTitle( aOldStr.ToLowerAscii(), 0, nOldLen );
4007 	}
4008 	else if ( (nConversion & 0x01) == 1 ) // vbUpperCase
4009 		nType |= ::com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE;
4010 	else if ( (nConversion & 0x02) == 2 ) // vbLowerCase
4011 		nType |= ::com::sun::star::i18n::TransliterationModules_UPPERCASE_LOWERCASE;
4012 
4013 	if ( (nConversion & 0x04) == 4 ) // vbWide
4014 		nType |= ::com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
4015 	else if ( (nConversion & 0x08) == 8 ) // vbNarrow
4016 		nType |= ::com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
4017 
4018 	if ( (nConversion & 0x10) == 16) // vbKatakana
4019 		nType |= ::com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
4020 	else if ( (nConversion & 0x20) == 32 ) // vbHiragana
4021 		nType |= ::com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA;
4022 
4023 	String aNewStr( aOldStr );
4024 	if( nType != 0 )
4025 	{
4026 		com::sun::star::uno::Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
4027     	::utl::TransliterationWrapper aTransliterationWrapper( xSMgr,nType );
4028 		com::sun::star::uno::Sequence<sal_Int32> aOffsets;
4029 		aTransliterationWrapper.loadModuleIfNeeded( nLanguage );
4030 		aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
4031 	}
4032 
4033 	if ( (nConversion & 0x40) == 64 ) // vbUnicode
4034 	{
4035 		// convert the string to byte string, preserving unicode (2 bytes per character)
4036 		sal_uInt16 nSize = aNewStr.Len()*2;
4037 		const sal_Unicode* pSrc = aNewStr.GetBuffer();
4038 		sal_Char* pChar = new sal_Char[nSize+1];
4039 		for( sal_uInt16 i=0; i < nSize; i++ )
4040 		{
4041 			pChar[i] = static_cast< sal_Char >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
4042 			if( i%2 )
4043 				pSrc++;
4044 		}
4045 		pChar[nSize] = '\0';
4046 		::rtl::OString aOStr(pChar);
4047 
4048 		// there is no concept about default codepage in unix. so it is incorrectly in unix
4049 		::rtl::OUString aOUStr = ::rtl::OStringToOUString(aOStr, osl_getThreadTextEncoding());
4050 		aNewStr = String(aOUStr);
4051 		rPar.Get(0)->PutString( aNewStr );
4052 		return;
4053 	}
4054 	else if ( (nConversion & 0x80) == 128 ) // vbFromUnicode
4055 	{
4056 		::rtl::OUString aOUStr(aNewStr);
4057 		// there is no concept about default codepage in unix. so it is incorrectly in unix
4058 		::rtl::OString aOStr = ::rtl::OUStringToOString(aNewStr,osl_getThreadTextEncoding());
4059 		const sal_Char* pChar = aOStr.getStr();
4060 		sal_uInt16 nArraySize = static_cast< sal_uInt16 >( aOStr.getLength() );
4061 		SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
4062 		bool bIncIndex = (IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
4063 		if(nArraySize)
4064 		{
4065 			if( bIncIndex )
4066 				pArray->AddDim( 1, nArraySize );
4067 			else
4068 				pArray->AddDim( 0, nArraySize-1 );
4069 		}
4070 		else
4071 		{
4072 			pArray->unoAddDim( 0, -1 );
4073 		}
4074 
4075 		for( sal_uInt16	i=0; i< nArraySize; i++)
4076 		{
4077 			SbxVariable* pNew = new SbxVariable( SbxBYTE );
4078 			pNew->PutByte(*pChar);
4079 			pChar++;
4080 			pNew->SetFlag( SBX_WRITE );
4081 			short index = i;
4082 			if( bIncIndex )
4083 				++index;
4084 			pArray->Put( pNew, &index );
4085 		}
4086 
4087 		SbxVariableRef refVar = rPar.Get(0);
4088 		sal_uInt16 nFlags = refVar->GetFlags();
4089 		refVar->ResetFlag( SBX_FIXED );
4090 		refVar->PutObject( pArray );
4091 		refVar->SetFlags( nFlags );
4092 	    refVar->SetParameters( NULL );
4093    		return;
4094 	}
4095 
4096 	rPar.Get(0)->PutString(aNewStr);
4097 }
4098 
4099 
RTLFUNC(Beep)4100 RTLFUNC(Beep)
4101 {
4102     (void)pBasic;
4103     (void)bWrite;
4104 
4105 	if ( rPar.Count() != 1 )
4106 	{
4107 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4108 		return;
4109 	}
4110 	Sound::Beep();
4111 }
4112 
RTLFUNC(Load)4113 RTLFUNC(Load)
4114 {
4115     (void)pBasic;
4116     (void)bWrite;
4117 
4118 	if( rPar.Count() != 2 )
4119 	{
4120 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4121 		return;
4122 	}
4123 
4124 	// Diesen Call einfach an das Object weiterreichen
4125 	SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
4126 	if ( pObj )
4127 	{
4128 		if( pObj->IsA( TYPE( SbUserFormModule ) ) )
4129 		{
4130 			((SbUserFormModule*)pObj)->Load();
4131 		}
4132 		else if( pObj->IsA( TYPE( SbxObject ) ) )
4133 		{
4134 			SbxVariable* pVar = ((SbxObject*)pObj)->
4135 				Find( String( RTL_CONSTASCII_USTRINGPARAM("Load") ), SbxCLASS_METHOD );
4136 			if( pVar )
4137 				pVar->GetInteger();
4138 		}
4139 	}
4140 }
4141 
RTLFUNC(Unload)4142 RTLFUNC(Unload)
4143 {
4144     (void)pBasic;
4145     (void)bWrite;
4146 
4147 	rPar.Get(0)->PutEmpty();
4148 	if( rPar.Count() != 2 )
4149 	{
4150 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4151 		return;
4152 	}
4153 
4154 	// Diesen Call einfach an das Object weitereichen
4155 	SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
4156 	if ( pObj )
4157 	{
4158 		if( pObj->IsA( TYPE( SbUserFormModule ) ) )
4159 		{
4160 			SbUserFormModule* pFormModule = ( SbUserFormModule* )pObj;
4161 			pFormModule->Unload();
4162 		}
4163 		else if( pObj->IsA( TYPE( SbxObject ) ) )
4164 		{
4165 			SbxVariable* pVar = ((SbxObject*)pObj)->
4166 				Find( String( RTL_CONSTASCII_USTRINGPARAM("Unload") ), SbxCLASS_METHOD );
4167 			if( pVar )
4168 				pVar->GetInteger();
4169 		}
4170 	}
4171 }
4172 
RTLFUNC(LoadPicture)4173 RTLFUNC(LoadPicture)
4174 {
4175     (void)pBasic;
4176     (void)bWrite;
4177 
4178 	if( rPar.Count() != 2 )
4179 	{
4180 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4181 		return;
4182 	}
4183 
4184 	String aFileURL = getFullPath( rPar.Get(1)->GetString() );
4185 	SvStream* pStream = utl::UcbStreamHelper::CreateStream( aFileURL, STREAM_READ );
4186 	if( pStream != NULL )
4187 	{
4188 		Bitmap aBmp;
4189         ReadDIB(aBmp, *pStream, true);
4190 		Graphic aGraphic(aBmp);
4191 
4192 		SbxObjectRef xRef = new SbStdPicture;
4193 		((SbStdPicture*)(SbxObject*)xRef)->SetGraphic( aGraphic );
4194 		rPar.Get(0)->PutObject( xRef );
4195 	}
4196 	delete pStream;
4197 }
4198 
RTLFUNC(SavePicture)4199 RTLFUNC(SavePicture)
4200 {
4201     (void)pBasic;
4202     (void)bWrite;
4203 
4204 	rPar.Get(0)->PutEmpty();
4205 	if( rPar.Count() != 3 )
4206 	{
4207 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4208 		return;
4209 	}
4210 
4211 	SbxBase* pObj = (SbxObject*)rPar.Get(1)->GetObject();
4212 	if( pObj->IsA( TYPE( SbStdPicture ) ) )
4213 	{
4214 		SvFileStream aOStream( rPar.Get(2)->GetString(), STREAM_WRITE | STREAM_TRUNC );
4215 		Graphic aGraphic = ((SbStdPicture*)pObj)->GetGraphic();
4216 		aOStream << aGraphic;
4217 	}
4218 }
4219 
4220 
4221 //-----------------------------------------------------------------------------------------
4222 
RTLFUNC(AboutStarBasic)4223 RTLFUNC(AboutStarBasic)
4224 {
4225     (void)pBasic;
4226     (void)bWrite;
4227     (void)rPar;
4228 }
4229 
RTLFUNC(MsgBox)4230 RTLFUNC(MsgBox)
4231 {
4232     (void)pBasic;
4233     (void)bWrite;
4234 
4235 	static const WinBits nStyleMap[] =
4236 	{
4237 		WB_OK,				// MB_OK
4238 		WB_OK_CANCEL,       // MB_OKCANCEL
4239 		WB_ABORT_RETRY_IGNORE,    // MB_ABORTRETRYIGNORE
4240 		WB_YES_NO_CANCEL,   // MB_YESNOCANCEL
4241 		WB_YES_NO,          // MB_YESNO
4242 		WB_RETRY_CANCEL     // MB_RETRYCANCEL
4243 	};
4244 	static const sal_Int16 nButtonMap[] =
4245 	{
4246 		2, // #define RET_CANCEL sal_False
4247 		1, // #define RET_OK     sal_True
4248 		6, // #define RET_YES    2
4249 		7, // #define RET_NO     3
4250 		4  // #define RET_RETRY  4
4251 	};
4252 
4253 
4254 	sal_uInt16 nArgCount = (sal_uInt16)rPar.Count();
4255 	if( nArgCount < 2 || nArgCount > 6 )
4256 	{
4257 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4258 		return;
4259 	}
4260 	WinBits nWinBits;
4261 	WinBits nType = 0; // MB_OK
4262 	if( nArgCount >= 3 )
4263 		nType = (WinBits)rPar.Get(2)->GetInteger();
4264 	WinBits nStyle = nType;
4265 	nStyle &= 15; // Bits 4-16 loeschen
4266 	if( nStyle > 5 )
4267 		nStyle = 0;
4268 
4269 	nWinBits = nStyleMap[ nStyle ];
4270 
4271 	WinBits nWinDefBits;
4272 	nWinDefBits = (WB_DEF_OK | WB_DEF_RETRY | WB_DEF_YES);
4273 	if( nType & 256 )
4274 	{
4275 		if( nStyle == 5 )
4276 			nWinDefBits = WB_DEF_CANCEL;
4277 		else if( nStyle == 2 )
4278 			nWinDefBits = WB_DEF_RETRY;
4279 		else
4280 			nWinDefBits = (WB_DEF_CANCEL | WB_DEF_RETRY | WB_DEF_NO);
4281 	}
4282 	else if( nType & 512 )
4283 	{
4284 		if( nStyle == 2)
4285 			nWinDefBits = WB_DEF_IGNORE;
4286 		else
4287 			nWinDefBits = WB_DEF_CANCEL;
4288 	}
4289 	else if( nStyle == 2)
4290 		nWinDefBits = WB_DEF_CANCEL;
4291     nWinBits |= nWinDefBits;
4292 
4293 	String aMsg = rPar.Get(1)->GetString();
4294 	String aTitle;
4295 	if( nArgCount >= 4 )
4296 		aTitle = rPar.Get(3)->GetString();
4297 	else
4298 		aTitle = GetpApp()->GetDisplayName();
4299 
4300 	nType &= (16+32+64);
4301 	MessBox* pBox = 0;
4302 	Window* pParent = GetpApp()->GetDefDialogParent();
4303 	switch( nType )
4304 	{
4305 		case 16:
4306 			pBox = new ErrorBox( pParent, nWinBits, aMsg );
4307 			break;
4308 		case 32:
4309 			pBox = new QueryBox( pParent, nWinBits, aMsg );
4310 			break;
4311 		case 48:
4312 			pBox = new WarningBox( pParent, nWinBits, aMsg );
4313 			break;
4314 		case 64:
4315 			pBox = new InfoBox( pParent, nWinBits, aMsg );
4316 			break;
4317 		default:
4318 			pBox = new MessBox( pParent, nWinBits, aTitle, aMsg );
4319 	}
4320 	pBox->SetText( aTitle );
4321 	sal_uInt16 nRet = (sal_uInt16)pBox->Execute();
4322 	if( nRet == sal_True )
4323 		nRet = 1;
4324 
4325 	sal_Int16 nMappedRet;
4326 	if( nStyle == 2 )
4327 	{
4328 		nMappedRet = nRet;
4329 		if( nMappedRet == 0 )
4330 			nMappedRet = 3;	// Abort
4331 	}
4332 	else
4333 		nMappedRet = nButtonMap[ nRet ];
4334 
4335 	rPar.Get(0)->PutInteger( nMappedRet );
4336 	delete pBox;
4337 }
4338 
RTLFUNC(SetAttr)4339 RTLFUNC(SetAttr) // JSM
4340 {
4341     (void)pBasic;
4342     (void)bWrite;
4343 
4344 	rPar.Get(0)->PutEmpty();
4345 	if ( rPar.Count() == 3 )
4346 	{
4347 		String aStr = rPar.Get(1)->GetString();
4348 		sal_Int16 nFlags = rPar.Get(2)->GetInteger();
4349 
4350 		// <-- UCB
4351 		if( hasUno() )
4352 		{
4353 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
4354 			if( xSFI.is() )
4355 			{
4356 				try
4357 				{
4358 					sal_Bool bReadOnly = (nFlags & 0x0001) != 0; // ATTR_READONLY
4359 					xSFI->setReadOnly( aStr, bReadOnly );
4360 					sal_Bool bHidden   = (nFlags & 0x0002) != 0; // ATTR_HIDDEN
4361 					xSFI->setHidden( aStr, bHidden );
4362 				}
4363 				catch( Exception & )
4364 				{
4365 					StarBASIC::Error( ERRCODE_IO_GENERAL );
4366 				}
4367 			}
4368 		}
4369 		else
4370 		// --> UCB
4371 		{
4372 #ifdef _OLD_FILE_IMPL
4373 			// #57064 Bei virtuellen URLs den Real-Path extrahieren
4374 			DirEntry aEntry( aStr );
4375 			String aFile = aEntry.GetFull();
4376 			ByteString aByteFile( aFile, gsl_getSystemTextEncoding() );
4377 	#ifdef WNT
4378 			if (!SetFileAttributes (aByteFile.GetBuffer(),(DWORD)nFlags))
4379 				StarBASIC::Error(SbERR_FILE_NOT_FOUND);
4380 	#endif
4381 	#ifdef OS2
4382 			FILESTATUS3 aFileStatus;
4383 			APIRET rc = DosQueryPathInfo(aByteFile.GetBuffer(),1,
4384 										 &aFileStatus,sizeof(FILESTATUS3));
4385 			if (!rc)
4386 			{
4387 				if (aFileStatus.attrFile != nFlags)
4388 				{
4389 					aFileStatus.attrFile = nFlags;
4390 					rc = DosSetPathInfo(aFile.GetStr(),1,
4391 										&aFileStatus,sizeof(FILESTATUS3),0);
4392 					if (rc)
4393 						StarBASIC::Error( SbERR_FILE_NOT_FOUND );
4394 				}
4395 			}
4396 			else
4397 				StarBASIC::Error( SbERR_FILE_NOT_FOUND );
4398 	#endif
4399 #else
4400 			// Not implemented
4401 #endif
4402 		}
4403 	}
4404 	else
4405 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4406 }
4407 
RTLFUNC(Reset)4408 RTLFUNC(Reset)  // JSM
4409 {
4410     (void)pBasic;
4411     (void)bWrite;
4412     (void)rPar;
4413 
4414 	SbiIoSystem* pIO = pINST->GetIoSystem();
4415 	if (pIO)
4416 		pIO->CloseAll();
4417 }
4418 
RTLFUNC(DumpAllObjects)4419 RTLFUNC(DumpAllObjects)
4420 {
4421     (void)pBasic;
4422     (void)bWrite;
4423 
4424 	sal_uInt16 nArgCount = (sal_uInt16)rPar.Count();
4425 	if( nArgCount < 2 || nArgCount > 3 )
4426 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4427 	else if( !pBasic )
4428 		StarBASIC::Error( SbERR_INTERNAL_ERROR );
4429 	else
4430 	{
4431 		SbxObject* p = pBasic;
4432 		while( p->GetParent() )
4433 			p = p->GetParent();
4434 		SvFileStream aStrm( rPar.Get( 1 )->GetString(),
4435 							STREAM_WRITE | STREAM_TRUNC );
4436 		p->Dump( aStrm, rPar.Get( 2 )->GetBool() );
4437 		aStrm.Close();
4438 		if( aStrm.GetError() != SVSTREAM_OK )
4439 			StarBASIC::Error( SbERR_IO_ERROR );
4440 	}
4441 }
4442 
4443 
RTLFUNC(FileExists)4444 RTLFUNC(FileExists)
4445 {
4446     (void)pBasic;
4447     (void)bWrite;
4448 
4449 	if ( rPar.Count() == 2 )
4450 	{
4451 		String aStr = rPar.Get(1)->GetString();
4452 		sal_Bool bExists = sal_False;
4453 
4454 		// <-- UCB
4455 		if( hasUno() )
4456 		{
4457 			com::sun::star::uno::Reference< XSimpleFileAccess3 > xSFI = getFileAccess();
4458 			if( xSFI.is() )
4459 			{
4460 				try
4461 				{
4462 					bExists = xSFI->exists( aStr );
4463 				}
4464 				catch( Exception & )
4465 				{
4466 					StarBASIC::Error( ERRCODE_IO_GENERAL );
4467 				}
4468 			}
4469 		}
4470 		else
4471 		// --> UCB
4472 		{
4473 #ifdef _OLD_FILE_IMPL
4474 			DirEntry aEntry( aStr );
4475 			bExists = aEntry.Exists();
4476 #else
4477 			DirectoryItem aItem;
4478 			FileBase::RC nRet = DirectoryItem::get( getFullPathUNC( aStr ), aItem );
4479 			bExists = (nRet == FileBase::E_None);
4480 #endif
4481 		}
4482 		rPar.Get(0)->PutBool( bExists );
4483 	}
4484 	else
4485 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4486 }
4487 
RTLFUNC(Partition)4488 RTLFUNC(Partition)
4489 {
4490     (void)pBasic;
4491     (void)bWrite;
4492 
4493 	if ( rPar.Count() != 5 )
4494 	{
4495 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4496 		return;
4497 	}
4498 
4499 	sal_Int32 nNumber = rPar.Get(1)->GetLong();
4500 	sal_Int32 nStart = rPar.Get(2)->GetLong();
4501 	sal_Int32 nStop = rPar.Get(3)->GetLong();
4502 	sal_Int32 nInterval = rPar.Get(4)->GetLong();
4503 
4504 	if( nStart < 0 || nStop <= nStart || nInterval < 1 )
4505 	{
4506 		StarBASIC::Error( SbERR_BAD_ARGUMENT );
4507 		return;
4508 	}
4509 
4510 	// the Partition function inserts leading spaces before lowervalue and uppervalue
4511     // so that they both have the same number of characters as the string
4512     // representation of the value (Stop + 1). This ensures that if you use the output
4513     // of the Partition function with several values of Number, the resulting text
4514 	// will be handled properly during any subsequent sort operation.
4515 
4516 	// calculate the  maximun number of characters before lowervalue and uppervalue
4517 	::rtl::OUString aBeforeStart = ::rtl::OUString::valueOf( nStart - 1 );
4518 	::rtl::OUString aAfterStop = ::rtl::OUString::valueOf( nStop + 1 );
4519 	sal_Int32 nLen1 = aBeforeStart.getLength();
4520 	sal_Int32 nLen2 = aAfterStop.getLength();
4521 	sal_Int32 nLen = nLen1 >= nLen2 ? nLen1:nLen2;
4522 
4523 	::rtl::OUStringBuffer aRetStr( nLen * 2 + 1);
4524 	::rtl::OUString aLowerValue;
4525 	::rtl::OUString aUpperValue;
4526 	if( nNumber < nStart )
4527 	{
4528 		aUpperValue = aBeforeStart;
4529 	}
4530 	else if( nNumber > nStop )
4531 	{
4532 		aLowerValue = aAfterStop;
4533 	}
4534 	else
4535 	{
4536 		sal_Int32 nLowerValue = nNumber;
4537 		sal_Int32 nUpperValue = nLowerValue;
4538 		if( nInterval > 1 )
4539 		{
4540 			nLowerValue = ((( nNumber - nStart ) / nInterval ) * nInterval ) + nStart;
4541 			nUpperValue = nLowerValue + nInterval - 1;
4542 		}
4543 
4544 		aLowerValue = ::rtl::OUString::valueOf( nLowerValue );
4545 		aUpperValue = ::rtl::OUString::valueOf( nUpperValue );
4546 	}
4547 
4548 	nLen1 = aLowerValue.getLength();
4549 	nLen2 = aUpperValue.getLength();
4550 
4551 	if( nLen > nLen1 )
4552 	{
4553 		// appending the leading spaces for the lowervalue
4554 		for ( sal_Int32 i= (nLen - nLen1) ; i > 0; --i )
4555 			aRetStr.appendAscii(" ");
4556 	}
4557 	aRetStr.append( aLowerValue ).appendAscii(":");
4558 	if( nLen > nLen2 )
4559 	{
4560 		// appending the leading spaces for the uppervalue
4561 		for ( sal_Int32 i= (nLen - nLen2) ; i > 0; --i )
4562 			aRetStr.appendAscii(" ");
4563 	}
4564 	aRetStr.append( aUpperValue );
4565 	rPar.Get(0)->PutString( String(aRetStr.makeStringAndClear()) );
4566 }
4567