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