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 <string.h> 21 #include <vcl/svapp.hxx> 22 #include <vcl/weld.hxx> 23 #include <osl/file.hxx> 24 #include <tools/urlobj.hxx> 25 26 #include <runtime.hxx> 27 28 #include <rtl/byteseq.hxx> 29 #include <rtl/textenc.h> 30 #include <rtl/strbuf.hxx> 31 #include <rtl/ustrbuf.hxx> 32 #include <sal/log.hxx> 33 34 #include <comphelper/processfactory.hxx> 35 #include <comphelper/string.hxx> 36 37 #include <com/sun/star/bridge/BridgeFactory.hpp> 38 #include <com/sun/star/bridge/XBridge.hpp> 39 #include <com/sun/star/uno/Sequence.hxx> 40 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 41 #include <com/sun/star/ucb/SimpleFileAccess.hpp> 42 #include <com/sun/star/ucb/UniversalContentBroker.hpp> 43 #include <com/sun/star/ucb/XContentProvider.hpp> 44 #include <com/sun/star/ucb/XContentProviderManager.hpp> 45 #include <com/sun/star/io/XInputStream.hpp> 46 #include <com/sun/star/io/XOutputStream.hpp> 47 #include <com/sun/star/io/XStream.hpp> 48 #include <com/sun/star/io/XSeekable.hpp> 49 50 using namespace com::sun::star::uno; 51 using namespace com::sun::star::lang; 52 using namespace com::sun::star::ucb; 53 using namespace com::sun::star::io; 54 using namespace com::sun::star::bridge; 55 56 #include <iosys.hxx> 57 #include <sbintern.hxx> 58 59 60 class SbiInputDialog : public weld::GenericDialogController 61 { 62 std::unique_ptr<weld::Entry> m_xInput; 63 std::unique_ptr<weld::Button> m_xOk; 64 std::unique_ptr<weld::Button> m_xCancel; 65 std::unique_ptr<weld::Label> m_xPromptText; 66 OUString m_aText; 67 DECL_LINK(Ok, weld::Button&, void); 68 DECL_LINK(Cancel, weld::Button&, void); 69 public: 70 SbiInputDialog(weld::Window*, const OUString&); 71 const OUString& GetInput() { return m_aText; } 72 }; 73 74 SbiInputDialog::SbiInputDialog(weld::Window* pParent, const OUString& rPrompt) 75 : GenericDialogController(pParent, "svt/ui/inputbox.ui", "InputBox") 76 , m_xInput(m_xBuilder->weld_entry("entry")) 77 , m_xOk(m_xBuilder->weld_button("ok")) 78 , m_xCancel(m_xBuilder->weld_button("cancel")) 79 , m_xPromptText(m_xBuilder->weld_label("prompt")) 80 { 81 m_xDialog->set_title(rPrompt); 82 m_xPromptText->set_label(rPrompt); 83 m_xOk->connect_clicked( LINK( this, SbiInputDialog, Ok ) ); 84 m_xCancel->connect_clicked( LINK( this, SbiInputDialog, Cancel ) ); 85 } 86 87 IMPL_LINK_NOARG( SbiInputDialog, Ok, weld::Button&, void ) 88 { 89 m_aText = m_xInput->get_text(); 90 m_xDialog->response(RET_OK); 91 } 92 93 IMPL_LINK_NOARG( SbiInputDialog, Cancel, weld::Button&, void ) 94 { 95 m_xDialog->response(RET_CANCEL); 96 } 97 98 SbiStream::SbiStream() 99 : pStrm(nullptr) 100 , nExpandOnWriteTo(0) 101 , nLine(0) 102 , nLen(0) 103 , nMode(SbiStreamFlags::NONE) 104 , nError(0) 105 { 106 } 107 108 SbiStream::~SbiStream() 109 { 110 } 111 112 // map an SvStream-error to StarBASIC-code 113 114 void SbiStream::MapError() 115 { 116 if( pStrm ) 117 { 118 ErrCode nEC = pStrm->GetError(); 119 if (nEC == ERRCODE_NONE) 120 nError = ERRCODE_NONE; 121 else if (nEC == SVSTREAM_FILE_NOT_FOUND) 122 nError = ERRCODE_BASIC_FILE_NOT_FOUND; 123 else if (nEC ==SVSTREAM_PATH_NOT_FOUND) 124 nError = ERRCODE_BASIC_PATH_NOT_FOUND; 125 else if (nEC ==SVSTREAM_TOO_MANY_OPEN_FILES) 126 nError = ERRCODE_BASIC_TOO_MANY_FILES; 127 else if (nEC ==SVSTREAM_ACCESS_DENIED) 128 nError = ERRCODE_BASIC_ACCESS_DENIED; 129 else if (nEC ==SVSTREAM_INVALID_PARAMETER) 130 nError = ERRCODE_BASIC_BAD_ARGUMENT; 131 else if (nEC ==SVSTREAM_OUTOFMEMORY) 132 nError = ERRCODE_BASIC_NO_MEMORY; 133 else 134 nError = ERRCODE_BASIC_IO_ERROR; 135 } 136 } 137 138 // Returns sal_True if UNO is available, otherwise the old file 139 // system implementation has to be used 140 // #89378 New semantic: Don't just ask for UNO but for UCB 141 bool hasUno() 142 { 143 static bool bNeedInit = true; 144 static bool bRetVal = true; 145 146 if( bNeedInit ) 147 { 148 bNeedInit = false; 149 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); 150 if( !xContext.is() ) 151 { 152 // No service manager at all 153 bRetVal = false; 154 } 155 else 156 { 157 Reference< XUniversalContentBroker > xManager = UniversalContentBroker::create(xContext); 158 159 if ( !( xManager->queryContentProvider( "file:///" ).is() ) ) 160 { 161 // No UCB 162 bRetVal = false; 163 } 164 } 165 } 166 return bRetVal; 167 } 168 169 170 class OslStream : public SvStream 171 { 172 osl::File maFile; 173 174 public: 175 OslStream( const OUString& rName, StreamMode nStrmMode ); 176 virtual ~OslStream() override; 177 virtual std::size_t GetData(void* pData, std::size_t nSize) override; 178 virtual std::size_t PutData(const void* pData, std::size_t nSize) override; 179 virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override; 180 virtual void FlushData() override; 181 virtual void SetSize( sal_uInt64 nSize) override; 182 }; 183 184 OslStream::OslStream( const OUString& rName, StreamMode nStrmMode ) 185 : maFile( rName ) 186 { 187 sal_uInt32 nFlags; 188 189 if( (nStrmMode & (StreamMode::READ | StreamMode::WRITE)) == (StreamMode::READ | StreamMode::WRITE) ) 190 { 191 nFlags = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write; 192 } 193 else if( nStrmMode & StreamMode::WRITE ) 194 { 195 nFlags = osl_File_OpenFlag_Write; 196 } 197 else //if( nStrmMode & StreamMode::READ ) 198 { 199 nFlags = osl_File_OpenFlag_Read; 200 } 201 202 osl::FileBase::RC nRet = maFile.open( nFlags ); 203 if( nRet == osl::FileBase::E_NOENT && nFlags != osl_File_OpenFlag_Read ) 204 { 205 nFlags |= osl_File_OpenFlag_Create; 206 nRet = maFile.open( nFlags ); 207 } 208 209 if( nRet != osl::FileBase::E_None ) 210 { 211 SetError( ERRCODE_IO_GENERAL ); 212 } 213 } 214 215 216 OslStream::~OslStream() 217 { 218 maFile.close(); 219 } 220 221 std::size_t OslStream::GetData(void* pData, std::size_t nSize) 222 { 223 sal_uInt64 nBytesRead = nSize; 224 maFile.read( pData, nBytesRead, nBytesRead ); 225 return nBytesRead; 226 } 227 228 std::size_t OslStream::PutData(const void* pData, std::size_t nSize) 229 { 230 sal_uInt64 nBytesWritten; 231 maFile.write( pData, nSize, nBytesWritten ); 232 return nBytesWritten; 233 } 234 235 sal_uInt64 OslStream::SeekPos( sal_uInt64 nPos ) 236 { 237 ::osl::FileBase::RC rc = ::osl::FileBase::E_None; 238 // check if a truncated STREAM_SEEK_TO_END was passed 239 assert(nPos != SAL_MAX_UINT32); 240 if( nPos == STREAM_SEEK_TO_END ) 241 { 242 rc = maFile.setPos( osl_Pos_End, 0 ); 243 } 244 else 245 { 246 rc = maFile.setPos( osl_Pos_Absolut, nPos ); 247 } 248 OSL_VERIFY(rc == ::osl::FileBase::E_None); 249 sal_uInt64 nRealPos(0); 250 maFile.getPos( nRealPos ); 251 return nRealPos; 252 } 253 254 void OslStream::FlushData() 255 { 256 } 257 258 void OslStream::SetSize( sal_uInt64 nSize ) 259 { 260 maFile.setSize( nSize ); 261 } 262 263 264 class UCBStream : public SvStream 265 { 266 Reference< XInputStream > xIS; 267 Reference< XStream > xS; 268 Reference< XSeekable > xSeek; 269 public: 270 explicit UCBStream( Reference< XInputStream > const & xIS ); 271 explicit UCBStream( Reference< XStream > const & xS ); 272 virtual ~UCBStream() override; 273 virtual std::size_t GetData( void* pData, std::size_t nSize ) override; 274 virtual std::size_t PutData( const void* pData, std::size_t nSize ) override; 275 virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override; 276 virtual void FlushData() override; 277 virtual void SetSize( sal_uInt64 nSize ) override; 278 }; 279 280 UCBStream::UCBStream( Reference< XInputStream > const & rStm ) 281 : xIS( rStm ) 282 , xSeek( rStm, UNO_QUERY ) 283 { 284 } 285 286 UCBStream::UCBStream( Reference< XStream > const & rStm ) 287 : xS( rStm ) 288 , xSeek( rStm, UNO_QUERY ) 289 { 290 } 291 292 293 UCBStream::~UCBStream() 294 { 295 try 296 { 297 if( xIS.is() ) 298 { 299 xIS->closeInput(); 300 } 301 else if( xS.is() ) 302 { 303 Reference< XInputStream > xIS_ = xS->getInputStream(); 304 if( xIS_.is() ) 305 { 306 xIS_->closeInput(); 307 } 308 } 309 } 310 catch(const Exception & ) 311 { 312 SetError( ERRCODE_IO_GENERAL ); 313 } 314 } 315 316 std::size_t UCBStream::GetData(void* pData, std::size_t nSize) 317 { 318 try 319 { 320 Reference< XInputStream > xISFromS; 321 if( xIS.is() ) 322 { 323 Sequence<sal_Int8> aData; 324 nSize = xIS->readBytes( aData, nSize ); 325 memcpy( pData, aData.getConstArray(), nSize ); 326 return nSize; 327 } 328 else if( xS.is() && (xISFromS = xS->getInputStream()).is() ) 329 { 330 Sequence<sal_Int8> aData; 331 nSize = xISFromS->readBytes( aData, nSize ); 332 memcpy(pData, aData.getConstArray(), nSize ); 333 return nSize; 334 } 335 else 336 { 337 SetError( ERRCODE_IO_GENERAL ); 338 } 339 } 340 catch(const Exception & ) 341 { 342 SetError( ERRCODE_IO_GENERAL ); 343 } 344 return 0; 345 } 346 347 std::size_t UCBStream::PutData(const void* pData, std::size_t nSize) 348 { 349 try 350 { 351 Reference< XOutputStream > xOSFromS; 352 if( xS.is() && (xOSFromS = xS->getOutputStream()).is() ) 353 { 354 Sequence<sal_Int8> aData( static_cast<const sal_Int8 *>(pData), nSize ); 355 xOSFromS->writeBytes( aData ); 356 return nSize; 357 } 358 else 359 { 360 SetError( ERRCODE_IO_GENERAL ); 361 } 362 } 363 catch(const Exception & ) 364 { 365 SetError( ERRCODE_IO_GENERAL ); 366 } 367 return 0; 368 } 369 370 sal_uInt64 UCBStream::SeekPos( sal_uInt64 nPos ) 371 { 372 try 373 { 374 if( xSeek.is() ) 375 { 376 sal_uInt64 nLen = static_cast<sal_uInt64>( xSeek->getLength() ); 377 if( nPos > nLen ) 378 { 379 nPos = nLen; 380 } 381 xSeek->seek( nPos ); 382 return nPos; 383 } 384 else 385 { 386 SetError( ERRCODE_IO_GENERAL ); 387 } 388 } 389 catch(const Exception & ) 390 { 391 SetError( ERRCODE_IO_GENERAL ); 392 } 393 return 0; 394 } 395 396 void UCBStream::FlushData() 397 { 398 try 399 { 400 Reference< XOutputStream > xOSFromS; 401 if( xS.is() && (xOSFromS = xS->getOutputStream()).is() ) 402 { 403 xOSFromS->flush(); 404 } 405 else 406 { 407 SetError( ERRCODE_IO_GENERAL ); 408 } 409 } 410 catch(const Exception & ) 411 { 412 SetError( ERRCODE_IO_GENERAL ); 413 } 414 } 415 416 void UCBStream::SetSize( sal_uInt64 ) 417 { 418 SAL_WARN("basic", "UCBStream::SetSize not allowed to call from basic" ); 419 SetError( ERRCODE_IO_GENERAL ); 420 } 421 422 423 ErrCode const & SbiStream::Open 424 ( const OString& rName, StreamMode nStrmMode, SbiStreamFlags nFlags, short nL ) 425 { 426 nMode = nFlags; 427 nLen = nL; 428 nLine = 0; 429 nExpandOnWriteTo = 0; 430 if( ( nStrmMode & ( StreamMode::READ|StreamMode::WRITE ) ) == StreamMode::READ ) 431 { 432 nStrmMode |= StreamMode::NOCREATE; 433 } 434 OUString aStr(OStringToOUString(rName, osl_getThreadTextEncoding())); 435 OUString aNameStr = getFullPath( aStr ); 436 437 if( hasUno() ) 438 { 439 Reference< XSimpleFileAccess3 > xSFI( SimpleFileAccess::create( comphelper::getProcessComponentContext() ) ); 440 try 441 { 442 443 // #??? For write access delete file if it already exists (not for appending) 444 if( (nStrmMode & StreamMode::WRITE) && !IsAppend() && !IsBinary() && !IsRandom() && 445 xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) ) 446 { 447 xSFI->kill( aNameStr ); 448 } 449 450 if( (nStrmMode & (StreamMode::READ | StreamMode::WRITE)) == (StreamMode::READ | StreamMode::WRITE) ) 451 { 452 Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr ); 453 pStrm.reset( new UCBStream( xIS ) ); 454 } 455 else if( nStrmMode & StreamMode::WRITE ) 456 { 457 Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr ); 458 pStrm.reset( new UCBStream( xIS ) ); 459 } 460 else //if( nStrmMode & StreamMode::READ ) 461 { 462 Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr ); 463 pStrm.reset( new UCBStream( xIS ) ); 464 } 465 466 } 467 catch(const Exception & ) 468 { 469 nError = ERRCODE_IO_GENERAL; 470 } 471 } 472 473 if( !pStrm ) 474 { 475 pStrm.reset( new OslStream( aNameStr, nStrmMode ) ); 476 } 477 if( IsAppend() ) 478 { 479 pStrm->Seek( STREAM_SEEK_TO_END ); 480 } 481 MapError(); 482 if( nError ) 483 { 484 pStrm.reset(); 485 } 486 return nError; 487 } 488 489 ErrCode const & SbiStream::Close() 490 { 491 if( pStrm ) 492 { 493 MapError(); 494 pStrm.reset(); 495 } 496 return nError; 497 } 498 499 ErrCode SbiStream::Read(OString& rBuf, sal_uInt16 n, bool bForceReadingPerByte) 500 { 501 nExpandOnWriteTo = 0; 502 if( !bForceReadingPerByte && IsText() ) 503 { 504 pStrm->ReadLine(rBuf); 505 nLine++; 506 } 507 else 508 { 509 if( !n ) 510 { 511 n = nLen; 512 } 513 if( !n ) 514 { 515 return nError = ERRCODE_BASIC_BAD_RECORD_LENGTH; 516 } 517 OStringBuffer aBuffer(read_uInt8s_ToOString(*pStrm, n)); 518 //Pad it out with ' ' to the requested length on short read 519 sal_Int32 nRequested = sal::static_int_cast<sal_Int32>(n); 520 comphelper::string::padToLength(aBuffer, nRequested, ' '); 521 rBuf = aBuffer.makeStringAndClear(); 522 } 523 MapError(); 524 if( !nError && pStrm->eof() ) 525 { 526 nError = ERRCODE_BASIC_READ_PAST_EOF; 527 } 528 return nError; 529 } 530 531 ErrCode const & SbiStream::Read( char& ch ) 532 { 533 nExpandOnWriteTo = 0; 534 if (aLine.isEmpty()) 535 { 536 Read( aLine ); 537 aLine = aLine + OString('\n'); 538 } 539 ch = aLine[0]; 540 aLine = aLine.copy(1); 541 return nError; 542 } 543 544 void SbiStream::ExpandFile() 545 { 546 if ( nExpandOnWriteTo ) 547 { 548 sal_uInt64 nCur = pStrm->Seek(STREAM_SEEK_TO_END); 549 if( nCur < nExpandOnWriteTo ) 550 { 551 sal_uInt64 nDiff = nExpandOnWriteTo - nCur; 552 while( nDiff-- ) 553 { 554 pStrm->WriteChar( 0 ); 555 } 556 } 557 else 558 { 559 pStrm->Seek( nExpandOnWriteTo ); 560 } 561 nExpandOnWriteTo = 0; 562 } 563 } 564 565 namespace 566 { 567 void WriteLines(SvStream &rStream, const OString& rStr) 568 { 569 OString aStr(convertLineEnd(rStr, rStream.GetLineDelimiter()) ); 570 write_uInt8s_FromOString(rStream, aStr); 571 endl( rStream ); 572 } 573 } 574 575 ErrCode SbiStream::Write( const OString& rBuf ) 576 { 577 ExpandFile(); 578 if( IsAppend() ) 579 { 580 pStrm->Seek( STREAM_SEEK_TO_END ); 581 } 582 if( IsText() ) 583 { 584 aLine = aLine + rBuf; 585 // Get it out, if the end is an LF, but strip CRLF before, 586 // because the SvStream adds a CRLF! 587 sal_Int32 nLineLen = aLine.getLength(); 588 if (nLineLen && aLine[--nLineLen] == 0x0A) 589 { 590 aLine = aLine.copy(0, nLineLen); 591 if (nLineLen && aLine[--nLineLen] == 0x0D) 592 { 593 aLine = aLine.copy(0, nLineLen); 594 } 595 WriteLines(*pStrm, aLine); 596 aLine.clear(); 597 } 598 } 599 else 600 { 601 if( !nLen ) 602 { 603 return nError = ERRCODE_BASIC_BAD_RECORD_LENGTH; 604 } 605 pStrm->WriteBytes(rBuf.getStr(), nLen); 606 MapError(); 607 } 608 return nError; 609 } 610 611 612 SbiIoSystem::SbiIoSystem() 613 { 614 for(SbiStream* & i : pChan) 615 { 616 i = nullptr; 617 } 618 nChan = 0; 619 nError = ERRCODE_NONE; 620 } 621 622 SbiIoSystem::~SbiIoSystem() COVERITY_NOEXCEPT_FALSE 623 { 624 Shutdown(); 625 } 626 627 ErrCode SbiIoSystem::GetError() 628 { 629 ErrCode n = nError; 630 nError = ERRCODE_NONE; 631 return n; 632 } 633 634 void SbiIoSystem::Open(short nCh, const OString& rName, StreamMode nMode, SbiStreamFlags nFlags, short nLen) 635 { 636 nError = ERRCODE_NONE; 637 if( nCh >= CHANNELS || !nCh ) 638 { 639 nError = ERRCODE_BASIC_BAD_CHANNEL; 640 } 641 else if( pChan[ nCh ] ) 642 { 643 nError = ERRCODE_BASIC_FILE_ALREADY_OPEN; 644 } 645 else 646 { 647 pChan[ nCh ] = new SbiStream; 648 nError = pChan[ nCh ]->Open( rName, nMode, nFlags, nLen ); 649 if( nError ) 650 { 651 delete pChan[ nCh ]; 652 pChan[ nCh ] = nullptr; 653 } 654 } 655 nChan = 0; 656 } 657 658 659 void SbiIoSystem::Close() 660 { 661 if( !nChan ) 662 { 663 nError = ERRCODE_BASIC_BAD_CHANNEL; 664 } 665 else if( !pChan[ nChan ] ) 666 { 667 nError = ERRCODE_BASIC_BAD_CHANNEL; 668 } 669 else 670 { 671 nError = pChan[ nChan ]->Close(); 672 delete pChan[ nChan ]; 673 pChan[ nChan ] = nullptr; 674 } 675 nChan = 0; 676 } 677 678 679 void SbiIoSystem::Shutdown() 680 { 681 for( short i = 1; i < CHANNELS; i++ ) 682 { 683 if( pChan[ i ] ) 684 { 685 ErrCode n = pChan[ i ]->Close(); 686 delete pChan[ i ]; 687 pChan[ i ] = nullptr; 688 if( n && !nError ) 689 { 690 nError = n; 691 } 692 } 693 } 694 nChan = 0; 695 // anything left to PRINT? 696 if( !aOut.isEmpty() ) 697 { 698 vcl::Window* pParent = Application::GetDefDialogParent(); 699 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent ? pParent->GetFrameWeld() : nullptr, VclMessageType::Warning, 700 VclButtonsType::Ok, aOut)); 701 xBox->run(); 702 } 703 aOut.clear(); 704 } 705 706 707 void SbiIoSystem::Read(OString& rBuf) 708 { 709 if( !nChan ) 710 { 711 ReadCon( rBuf ); 712 } 713 else if( !pChan[ nChan ] ) 714 { 715 nError = ERRCODE_BASIC_BAD_CHANNEL; 716 } 717 else 718 { 719 nError = pChan[ nChan ]->Read( rBuf ); 720 } 721 } 722 723 char SbiIoSystem::Read() 724 { 725 char ch = ' '; 726 if( !nChan ) 727 { 728 if( aIn.isEmpty() ) 729 { 730 ReadCon( aIn ); 731 aIn = aIn + OString('\n'); 732 } 733 ch = aIn[0]; 734 aIn = aIn.copy(1); 735 } 736 else if( !pChan[ nChan ] ) 737 { 738 nError = ERRCODE_BASIC_BAD_CHANNEL; 739 } 740 else 741 { 742 nError = pChan[ nChan ]->Read( ch ); 743 } 744 return ch; 745 } 746 747 void SbiIoSystem::Write(const OUString& rBuf) 748 { 749 if( !nChan ) 750 { 751 WriteCon( rBuf ); 752 } 753 else if( !pChan[ nChan ] ) 754 { 755 nError = ERRCODE_BASIC_BAD_CHANNEL; 756 } 757 else 758 { 759 nError = pChan[ nChan ]->Write( OUStringToOString(rBuf, osl_getThreadTextEncoding()) ); 760 } 761 } 762 763 // nChannel == 0..CHANNELS-1 764 765 SbiStream* SbiIoSystem::GetStream( short nChannel ) const 766 { 767 SbiStream* pRet = nullptr; 768 if( nChannel >= 0 && nChannel < CHANNELS ) 769 { 770 pRet = pChan[ nChannel ]; 771 } 772 return pRet; 773 } 774 775 void SbiIoSystem::CloseAll() 776 { 777 for( short i = 1; i < CHANNELS; i++ ) 778 { 779 if( pChan[ i ] ) 780 { 781 ErrCode n = pChan[ i ]->Close(); 782 delete pChan[ i ]; 783 pChan[ i ] = nullptr; 784 if( n && !nError ) 785 { 786 nError = n; 787 } 788 } 789 } 790 } 791 792 void SbiIoSystem::ReadCon(OString& rIn) 793 { 794 OUString aPromptStr(OStringToOUString(aPrompt, osl_getThreadTextEncoding())); 795 SbiInputDialog aDlg(nullptr, aPromptStr); 796 if (aDlg.run() == RET_OK) 797 { 798 rIn = OUStringToOString(aDlg.GetInput(), osl_getThreadTextEncoding()); 799 } 800 else 801 { 802 nError = ERRCODE_BASIC_USER_ABORT; 803 } 804 aPrompt.clear(); 805 } 806 807 // output of a MessageBox, if there's a CR in the console-buffer 808 809 void SbiIoSystem::WriteCon(const OUString& rText) 810 { 811 aOut += rText; 812 sal_Int32 n1 = aOut.indexOf('\n'); 813 sal_Int32 n2 = aOut.indexOf('\r'); 814 if( n1 != -1 || n2 != -1 ) 815 { 816 if( n1 == -1 ) 817 { 818 n1 = n2; 819 } 820 else if( n2 == -1 ) 821 { 822 n2 = n1; 823 } 824 if( n1 > n2 ) 825 { 826 n1 = n2; 827 } 828 OUString s(aOut.copy(0, n1)); 829 aOut = aOut.copy(n1); 830 while ( !aOut.isEmpty() && (aOut[0] == '\n' || aOut[0] == '\r') ) 831 { 832 aOut = aOut.copy(1); 833 } 834 { 835 SolarMutexGuard aSolarGuard; 836 837 vcl::Window* pParent = Application::GetDefDialogParent(); 838 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent ? pParent->GetFrameWeld() : nullptr, VclMessageType::Warning, 839 VclButtonsType::OkCancel, s)); 840 xBox->set_default_response(RET_OK); 841 if (!xBox->run()) 842 { 843 nError = ERRCODE_BASIC_USER_ABORT; 844 } 845 } 846 } 847 } 848 849 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 850
