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