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