bump product version to 5.0.4.1
[LibreOffice.git] / basic / source / runtime / iosys.cxx
blob321630c8f23a02df278dad81563f08d39244185d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <string.h>
21 #include <vcl/dialog.hxx>
22 #include <vcl/edit.hxx>
23 #include <vcl/button.hxx>
24 #include <vcl/msgbox.hxx>
25 #include <vcl/svapp.hxx>
26 #include <osl/security.h>
27 #include <osl/file.hxx>
28 #include <tools/urlobj.hxx>
29 #include <osl/mutex.hxx>
31 #include "runtime.hxx"
33 #include <sal/alloca.h>
35 #include <ctype.h>
36 #include <rtl/byteseq.hxx>
37 #include <rtl/textenc.h>
38 #include <rtl/strbuf.hxx>
39 #include <rtl/ustrbuf.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/string.hxx>
44 #include <com/sun/star/bridge/BridgeFactory.hpp>
45 #include <com/sun/star/bridge/XBridge.hpp>
46 #include <com/sun/star/uno/Sequence.hxx>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
49 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
50 #include <com/sun/star/ucb/XContentProvider.hpp>
51 #include <com/sun/star/ucb/XContentProviderManager.hpp>
52 #include <com/sun/star/io/XInputStream.hpp>
53 #include <com/sun/star/io/XOutputStream.hpp>
54 #include <com/sun/star/io/XStream.hpp>
55 #include <com/sun/star/io/XSeekable.hpp>
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::lang;
59 using namespace com::sun::star::ucb;
60 using namespace com::sun::star::io;
61 using namespace com::sun::star::bridge;
63 #include "iosys.hxx"
64 #include "sbintern.hxx"
68 class SbiInputDialog : public ModalDialog {
69 VclPtr<Edit> aInput;
70 VclPtr<OKButton> aOk;
71 VclPtr<CancelButton> aCancel;
72 OUString aText;
73 DECL_LINK( Ok, vcl::Window * );
74 DECL_LINK( Cancel, vcl::Window * );
75 public:
76 SbiInputDialog( vcl::Window*, const OUString& );
77 virtual ~SbiInputDialog() { disposeOnce(); }
78 virtual void dispose() SAL_OVERRIDE;
79 const OUString& GetInput() { return aText; }
82 SbiInputDialog::SbiInputDialog( vcl::Window* pParent, const OUString& rPrompt )
83 :ModalDialog( pParent, WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ),
84 aInput( VclPtr<Edit>::Create(this, WB_3DLOOK | WB_LEFT | WB_BORDER) ),
85 aOk( VclPtr<OKButton>::Create(this) ), aCancel( VclPtr<CancelButton>::Create(this) )
87 SetText( rPrompt );
88 aOk->SetClickHdl( LINK( this, SbiInputDialog, Ok ) );
89 aCancel->SetClickHdl( LINK( this, SbiInputDialog, Cancel ) );
90 SetMapMode( MapMode( MAP_APPFONT ) );
92 Point aPt = LogicToPixel( Point( 50, 50 ) );
93 Size aSz = LogicToPixel( Size( 145, 65 ) );
94 SetPosSizePixel( aPt, aSz );
95 aPt = LogicToPixel( Point( 10, 10 ) );
96 aSz = LogicToPixel( Size( 120, 12 ) );
97 aInput->SetPosSizePixel( aPt, aSz );
98 aPt = LogicToPixel( Point( 15, 30 ) );
99 aSz = LogicToPixel( Size( 45, 15) );
100 aOk->SetPosSizePixel( aPt, aSz );
101 aPt = LogicToPixel( Point( 80, 30 ) );
102 aSz = LogicToPixel( Size( 45, 15) );
103 aCancel->SetPosSizePixel( aPt, aSz );
105 aInput->Show();
106 aOk->Show();
107 aCancel->Show();
110 void SbiInputDialog::dispose()
112 aInput.disposeAndClear();
113 aOk.disposeAndClear();
114 aCancel.disposeAndClear();
115 ModalDialog::dispose();
118 IMPL_LINK( SbiInputDialog, Ok, vcl::Window *, pWindow )
120 (void)pWindow;
122 aText = aInput->GetText();
123 EndDialog( 1 );
124 return 0;
127 IMPL_LINK( SbiInputDialog, Cancel, vcl::Window *, pWindow )
129 (void)pWindow;
131 EndDialog( 0 );
132 return 0;
135 SbiStream::SbiStream()
136 : pStrm(0)
137 , nExpandOnWriteTo(0)
138 , nLine(0)
139 , nLen(0)
140 , nMode(0)
141 , nChan(0)
142 , nError(0)
146 SbiStream::~SbiStream()
148 delete pStrm;
151 // map an SvStream-error to StarBASIC-code
153 void SbiStream::MapError()
155 if( pStrm )
157 switch( pStrm->GetError() )
159 case SVSTREAM_OK:
160 nError = 0;
161 break;
162 case SVSTREAM_FILE_NOT_FOUND:
163 nError = SbERR_FILE_NOT_FOUND;
164 break;
165 case SVSTREAM_PATH_NOT_FOUND:
166 nError = SbERR_PATH_NOT_FOUND;
167 break;
168 case SVSTREAM_TOO_MANY_OPEN_FILES:
169 nError = SbERR_TOO_MANY_FILES;
170 break;
171 case SVSTREAM_ACCESS_DENIED:
172 nError = SbERR_ACCESS_DENIED;
173 break;
174 case SVSTREAM_INVALID_PARAMETER:
175 nError = SbERR_BAD_ARGUMENT;
176 break;
177 case SVSTREAM_OUTOFMEMORY:
178 nError = SbERR_NO_MEMORY;
179 break;
180 default:
181 nError = SbERR_IO_ERROR;
182 break;
187 // TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx
189 OUString findUserInDescription( const OUString& aDescription )
191 OUString user;
193 sal_Int32 index;
194 sal_Int32 lastIndex = 0;
198 index = aDescription.indexOf((sal_Unicode) ',', lastIndex);
199 OUString token = (index == -1) ? aDescription.copy(lastIndex) : aDescription.copy(lastIndex, index - lastIndex);
201 lastIndex = index + 1;
203 sal_Int32 eindex = token.indexOf((sal_Unicode)'=');
204 OUString left = token.copy(0, eindex).toAsciiLowerCase().trim();
205 OUString right = INetURLObject::decode( token.copy(eindex + 1).trim(),
206 INetURLObject::DECODE_WITH_CHARSET );
208 if( left == "user" )
210 user = right;
211 break;
214 while(index != -1);
216 return user;
219 bool needSecurityRestrictions()
221 static bool bNeedInit = true;
222 static bool bRetVal = true;
224 if( bNeedInit )
226 bNeedInit = false;
228 // Get system user to compare to portal user
229 oslSecurity aSecurity = osl_getCurrentSecurity();
230 OUString aSystemUser;
231 bool bRet = osl_getUserName( aSecurity, &aSystemUser.pData );
232 osl_freeSecurityHandle(aSecurity);
233 if( !bRet )
235 // No valid security! -> Secure mode!
236 return true;
239 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
240 Reference< XBridgeFactory2 > xBridgeFac( BridgeFactory::create(xContext) );
242 Sequence< Reference< XBridge > > aBridgeSeq = xBridgeFac->getExistingBridges();
243 sal_Int32 nBridgeCount = aBridgeSeq.getLength();
245 if( nBridgeCount == 0 )
247 // No bridges -> local
248 bRetVal = false;
249 return bRetVal;
252 // Iterate through all bridges to find (portal) user property
253 const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray();
254 bRetVal = false; // Now only sal_True if user different from portal user is found
255 sal_Int32 i;
256 for( i = 0 ; i < nBridgeCount ; i++ )
258 const Reference< XBridge >& rxBridge = pBridges[ i ];
259 OUString aDescription = rxBridge->getDescription();
260 OUString aPortalUser = findUserInDescription( aDescription );
261 if( !aPortalUser.isEmpty() )
263 // User Found, compare to system user
264 if( aPortalUser == aSystemUser )
266 // Same user -> system security is ok, bRetVal stays FALSE
267 break;
269 else
271 // Different user -> Secure mode!
272 bRetVal = true;
273 break;
277 // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
280 return bRetVal;
283 // Returns sal_True if UNO is available, otherwise the old file
284 // system implementation has to be used
285 // #89378 New semantic: Don't just ask for UNO but for UCB
286 bool hasUno()
288 static bool bNeedInit = true;
289 static bool bRetVal = true;
291 if( bNeedInit )
293 bNeedInit = false;
294 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
295 if( !xContext.is() )
297 // No service manager at all
298 bRetVal = false;
300 else
302 Reference< XUniversalContentBroker > xManager = UniversalContentBroker::create(xContext);
304 if ( !( xManager->queryContentProvider( OUString("file:///" ) ).is() ) )
306 // No UCB
307 bRetVal = false;
311 return bRetVal;
316 class OslStream : public SvStream
318 osl::File maFile;
320 public:
321 OslStream( const OUString& rName, StreamMode nStrmMode );
322 virtual ~OslStream();
323 virtual sal_Size GetData( void* pData, sal_Size nSize ) SAL_OVERRIDE;
324 virtual sal_Size PutData( const void* pData, sal_Size nSize ) SAL_OVERRIDE;
325 virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) SAL_OVERRIDE;
326 virtual void FlushData() SAL_OVERRIDE;
327 virtual void SetSize( sal_uInt64 nSize) SAL_OVERRIDE;
330 OslStream::OslStream( const OUString& rName, StreamMode nStrmMode )
331 : maFile( rName )
333 sal_uInt32 nFlags;
335 if( (nStrmMode & (StreamMode::READ | StreamMode::WRITE)) == (StreamMode::READ | StreamMode::WRITE) )
337 nFlags = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write;
339 else if( nStrmMode & StreamMode::WRITE )
341 nFlags = osl_File_OpenFlag_Write;
343 else //if( nStrmMode & StreamMode::READ )
345 nFlags = osl_File_OpenFlag_Read;
348 osl::FileBase::RC nRet = maFile.open( nFlags );
349 if( nRet == osl::FileBase::E_NOENT && nFlags != osl_File_OpenFlag_Read )
351 nFlags |= osl_File_OpenFlag_Create;
352 nRet = maFile.open( nFlags );
355 if( nRet != osl::FileBase::E_None )
357 SetError( ERRCODE_IO_GENERAL );
362 OslStream::~OslStream()
364 maFile.close();
367 sal_Size OslStream::GetData(void* pData, sal_Size nSize)
369 sal_uInt64 nBytesRead = nSize;
370 maFile.read( pData, nBytesRead, nBytesRead );
371 return nBytesRead;
374 sal_Size OslStream::PutData(const void* pData, sal_Size nSize)
376 sal_uInt64 nBytesWritten;
377 maFile.write( pData, nSize, nBytesWritten );
378 return nBytesWritten;
381 sal_uInt64 OslStream::SeekPos( sal_uInt64 nPos )
383 ::osl::FileBase::RC rc = ::osl::FileBase::E_None;
384 // check if a truncated STREAM_SEEK_TO_END was passed
385 assert(nPos != SAL_MAX_UINT32);
386 if( nPos == STREAM_SEEK_TO_END )
388 rc = maFile.setPos( osl_Pos_End, 0 );
390 else
392 rc = maFile.setPos( osl_Pos_Absolut, (sal_uInt64)nPos );
394 OSL_VERIFY(rc == ::osl::FileBase::E_None);
395 sal_uInt64 nRealPos(0);
396 maFile.getPos( nRealPos );
397 return nRealPos;
400 void OslStream::FlushData()
404 void OslStream::SetSize( sal_uInt64 nSize )
406 maFile.setSize( nSize );
410 class UCBStream : public SvStream
412 Reference< XInputStream > xIS;
413 Reference< XStream > xS;
414 Reference< XSeekable > xSeek;
415 public:
416 UCBStream( Reference< XInputStream > & xIS );
417 UCBStream( Reference< XStream > & xS );
418 virtual ~UCBStream();
419 virtual sal_Size GetData( void* pData, sal_Size nSize ) SAL_OVERRIDE;
420 virtual sal_Size PutData( const void* pData, sal_Size nSize ) SAL_OVERRIDE;
421 virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) SAL_OVERRIDE;
422 virtual void FlushData() SAL_OVERRIDE;
423 virtual void SetSize( sal_uInt64 nSize ) SAL_OVERRIDE;
426 UCBStream::UCBStream( Reference< XInputStream > & rStm )
427 : xIS( rStm )
428 , xSeek( rStm, UNO_QUERY )
432 UCBStream::UCBStream( Reference< XStream > & rStm )
433 : xS( rStm )
434 , xSeek( rStm, UNO_QUERY )
439 UCBStream::~UCBStream()
443 if( xIS.is() )
445 xIS->closeInput();
447 else if( xS.is() )
449 Reference< XInputStream > xIS_ = xS->getInputStream();
450 if( xIS_.is() )
452 xIS_->closeInput();
456 catch(const Exception & )
458 SetError( ERRCODE_IO_GENERAL );
462 sal_Size UCBStream::GetData(void* pData, sal_Size nSize)
466 Reference< XInputStream > xISFromS;
467 if( xIS.is() )
469 Sequence<sal_Int8> aData;
470 nSize = xIS->readBytes( aData, nSize );
471 memcpy( pData, aData.getConstArray(), nSize );
472 return nSize;
474 else if( xS.is() && (xISFromS = xS->getInputStream()).is() )
476 Sequence<sal_Int8> aData;
477 nSize = xISFromS->readBytes( aData, nSize );
478 memcpy(pData, aData.getConstArray(), nSize );
479 return nSize;
481 else
483 SetError( ERRCODE_IO_GENERAL );
486 catch(const Exception & )
488 SetError( ERRCODE_IO_GENERAL );
490 return 0;
493 sal_Size UCBStream::PutData(const void* pData, sal_Size nSize)
497 Reference< XOutputStream > xOSFromS;
498 if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
500 Sequence<sal_Int8> aData( static_cast<const sal_Int8 *>(pData), nSize );
501 xOSFromS->writeBytes( aData );
502 return nSize;
504 else
506 SetError( ERRCODE_IO_GENERAL );
509 catch(const Exception & )
511 SetError( ERRCODE_IO_GENERAL );
513 return 0;
516 sal_uInt64 UCBStream::SeekPos( sal_uInt64 nPos )
520 if( xSeek.is() )
522 sal_uInt64 nLen = static_cast<sal_uInt64>( xSeek->getLength() );
523 if( nPos > nLen )
525 nPos = nLen;
527 xSeek->seek( nPos );
528 return nPos;
530 else
532 SetError( ERRCODE_IO_GENERAL );
535 catch(const Exception & )
537 SetError( ERRCODE_IO_GENERAL );
539 return 0;
542 void UCBStream::FlushData()
546 Reference< XOutputStream > xOSFromS;
547 if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
549 xOSFromS->flush();
551 else
553 SetError( ERRCODE_IO_GENERAL );
556 catch(const Exception & )
558 SetError( ERRCODE_IO_GENERAL );
562 void UCBStream::SetSize( sal_uInt64 nSize )
564 (void)nSize;
566 SAL_WARN("basic", "UCBStream::SetSize not allowed to call from basic" );
567 SetError( ERRCODE_IO_GENERAL );
571 SbError SbiStream::Open
572 ( short nCh, const OString& rName, StreamMode nStrmMode, short nFlags, short nL )
574 nMode = nFlags;
575 nLen = nL;
576 nChan = nCh;
577 nLine = 0;
578 nExpandOnWriteTo = 0;
579 if( ( nStrmMode & ( StreamMode::READ|StreamMode::WRITE ) ) == StreamMode::READ )
581 nStrmMode |= StreamMode::NOCREATE;
583 OUString aStr(OStringToOUString(rName, osl_getThreadTextEncoding()));
584 OUString aNameStr = getFullPath( aStr );
586 if( hasUno() )
588 Reference< XSimpleFileAccess3 > xSFI( SimpleFileAccess::create( comphelper::getProcessComponentContext() ) );
592 // #??? For write access delete file if it already exists (not for appending)
593 if( (nStrmMode & StreamMode::WRITE) && !IsAppend() && !IsBinary() &&
594 xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) )
596 xSFI->kill( aNameStr );
599 if( (nStrmMode & (StreamMode::READ | StreamMode::WRITE)) == (StreamMode::READ | StreamMode::WRITE) )
601 Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
602 pStrm = new UCBStream( xIS );
604 else if( nStrmMode & StreamMode::WRITE )
606 Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
607 pStrm = new UCBStream( xIS );
609 else //if( nStrmMode & StreamMode::READ )
611 Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr );
612 pStrm = new UCBStream( xIS );
616 catch(const Exception & )
618 nError = ERRCODE_IO_GENERAL;
622 if( !pStrm )
624 pStrm = new OslStream( aNameStr, nStrmMode );
626 if( IsAppend() )
628 pStrm->Seek( STREAM_SEEK_TO_END );
630 MapError();
631 if( nError )
633 delete pStrm, pStrm = NULL;
635 return nError;
638 SbError SbiStream::Close()
640 if( pStrm )
642 MapError();
643 delete pStrm;
644 pStrm = NULL;
646 nChan = 0;
647 return nError;
650 SbError SbiStream::Read(OString& rBuf, sal_uInt16 n, bool bForceReadingPerByte)
652 nExpandOnWriteTo = 0;
653 if( !bForceReadingPerByte && IsText() )
655 pStrm->ReadLine(rBuf);
656 nLine++;
658 else
660 if( !n )
662 n = nLen;
664 if( !n )
666 return nError = SbERR_BAD_RECORD_LENGTH;
668 OStringBuffer aBuffer(read_uInt8s_ToOString(*pStrm, n));
669 //Pad it out with ' ' to the requested length on short read
670 sal_Int32 nRequested = sal::static_int_cast<sal_Int32>(n);
671 comphelper::string::padToLength(aBuffer, nRequested, ' ');
672 rBuf = aBuffer.makeStringAndClear();
674 MapError();
675 if( !nError && pStrm->IsEof() )
677 nError = SbERR_READ_PAST_EOF;
679 return nError;
682 SbError SbiStream::Read( char& ch )
684 nExpandOnWriteTo = 0;
685 if (aLine.isEmpty())
687 Read( aLine, 0 );
688 aLine = aLine + OString('\n');
690 ch = aLine[0];
691 aLine = aLine.copy(1);
692 return nError;
695 void SbiStream::ExpandFile()
697 if ( nExpandOnWriteTo )
699 sal_uInt64 nCur = pStrm->Seek(STREAM_SEEK_TO_END);
700 if( nCur < nExpandOnWriteTo )
702 sal_uInt64 nDiff = nExpandOnWriteTo - nCur;
703 char c = 0;
704 while( nDiff-- )
706 pStrm->WriteChar( c );
709 else
711 pStrm->Seek( nExpandOnWriteTo );
713 nExpandOnWriteTo = 0;
717 namespace
719 void WriteLines(SvStream &rStream, const OString& rStr)
721 OString aStr(convertLineEnd(rStr, rStream.GetLineDelimiter()) );
722 write_uInt8s_FromOString(rStream, aStr);
723 endl( rStream );
727 SbError SbiStream::Write( const OString& rBuf, sal_uInt16 n )
729 ExpandFile();
730 if( IsAppend() )
732 pStrm->Seek( STREAM_SEEK_TO_END );
734 if( IsText() )
736 aLine = aLine + rBuf;
737 // Get it out, if the end is an LF, but strip CRLF before,
738 // because the SvStrm adds a CRLF!
739 sal_Int32 nLineLen = aLine.getLength();
740 if (nLineLen && aLine[--nLineLen] == 0x0A)
742 aLine = aLine.copy(0, nLineLen);
743 if (nLineLen && aLine[--nLineLen] == 0x0D)
745 aLine = aLine.copy(0, nLineLen);
747 WriteLines(*pStrm, aLine);
748 aLine.clear();
751 else
753 if( !n )
755 n = nLen;
757 if( !n )
759 return nError = SbERR_BAD_RECORD_LENGTH;
761 pStrm->Write(rBuf.getStr(), n);
762 MapError();
764 return nError;
769 SbiIoSystem* SbGetIoSystem()
771 SbiInstance* pInst = GetSbData()->pInst;
772 return pInst ? pInst->GetIoSystem() : NULL;
776 SbiIoSystem::SbiIoSystem()
778 for( short i = 0; i < CHANNELS; i++ )
780 pChan[ i ] = NULL;
782 nChan = 0;
783 nError = 0;
786 SbiIoSystem::~SbiIoSystem()
788 Shutdown();
791 SbError SbiIoSystem::GetError()
793 SbError n = nError; nError = 0;
794 return n;
797 void SbiIoSystem::Open(short nCh, const OString& rName, StreamMode nMode, short nFlags, short nLen)
799 nError = 0;
800 if( nCh >= CHANNELS || !nCh )
802 nError = SbERR_BAD_CHANNEL;
804 else if( pChan[ nCh ] )
806 nError = SbERR_FILE_ALREADY_OPEN;
808 else
810 pChan[ nCh ] = new SbiStream;
811 nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen );
812 if( nError )
814 delete pChan[ nCh ], pChan[ nCh ] = NULL;
817 nChan = 0;
821 void SbiIoSystem::Close()
823 if( !nChan )
825 nError = SbERR_BAD_CHANNEL;
827 else if( !pChan[ nChan ] )
829 nError = SbERR_BAD_CHANNEL;
831 else
833 nError = pChan[ nChan ]->Close();
834 delete pChan[ nChan ];
835 pChan[ nChan ] = NULL;
837 nChan = 0;
841 void SbiIoSystem::Shutdown()
843 for( short i = 1; i < CHANNELS; i++ )
845 if( pChan[ i ] )
847 SbError n = pChan[ i ]->Close();
848 delete pChan[ i ];
849 pChan[ i ] = NULL;
850 if( n && !nError )
852 nError = n;
856 nChan = 0;
857 // anything left to PRINT?
858 if( !aOut.isEmpty() )
860 #if defined __GNUC__
861 vcl::Window* pParent = Application::GetDefDialogParent();
862 ScopedVclPtrInstance<MessBox>::Create( pParent, WinBits( WB_OK ), OUString(), aOut )->Execute();
863 #else
864 ScopedVclPtrInstance<MessBox>::Create( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), OUString(), aOut )->Execute();
865 #endif
867 aOut.clear();
871 void SbiIoSystem::Read(OString& rBuf, short n)
873 if( !nChan )
875 ReadCon( rBuf );
877 else if( !pChan[ nChan ] )
879 nError = SbERR_BAD_CHANNEL;
881 else
883 nError = pChan[ nChan ]->Read( rBuf, n );
887 char SbiIoSystem::Read()
889 char ch = ' ';
890 if( !nChan )
892 if( aIn.isEmpty() )
894 ReadCon( aIn );
895 aIn = aIn + OString('\n');
897 ch = aIn[0];
898 aIn = aIn.copy(1);
900 else if( !pChan[ nChan ] )
902 nError = SbERR_BAD_CHANNEL;
904 else
906 nError = pChan[ nChan ]->Read( ch );
908 return ch;
911 void SbiIoSystem::Write(const OUString& rBuf, short n)
913 if( !nChan )
915 WriteCon( rBuf );
917 else if( !pChan[ nChan ] )
919 nError = SbERR_BAD_CHANNEL;
921 else
923 nError = pChan[ nChan ]->Write( OUStringToOString(rBuf, osl_getThreadTextEncoding()), n );
927 // nChannel == 0..CHANNELS-1
929 SbiStream* SbiIoSystem::GetStream( short nChannel ) const
931 SbiStream* pRet = 0;
932 if( nChannel >= 0 && nChannel < CHANNELS )
934 pRet = pChan[ nChannel ];
936 return pRet;
939 void SbiIoSystem::CloseAll()
941 for( short i = 1; i < CHANNELS; i++ )
943 if( pChan[ i ] )
945 SbError n = pChan[ i ]->Close();
946 delete pChan[ i ];
947 pChan[ i ] = NULL;
948 if( n && !nError )
950 nError = n;
956 /***************************************************************************
958 * Console Support
960 ***************************************************************************/
963 void SbiIoSystem::ReadCon(OString& rIn)
965 OUString aPromptStr(OStringToOUString(aPrompt, osl_getThreadTextEncoding()));
966 ScopedVclPtrInstance< SbiInputDialog > aDlg(nullptr, aPromptStr);
967 if( aDlg->Execute() )
969 rIn = OUStringToOString(aDlg->GetInput(), osl_getThreadTextEncoding());
971 else
973 nError = SbERR_USER_ABORT;
975 aPrompt.clear();
978 // output of a MessageBox, if theres a CR in the console-buffer
980 void SbiIoSystem::WriteCon(const OUString& rText)
982 aOut += rText;
983 sal_Int32 n1 = aOut.indexOf('\n');
984 sal_Int32 n2 = aOut.indexOf('\r');
985 if( n1 != -1 || n2 != -1 )
987 if( n1 == -1 )
989 n1 = n2;
991 else if( n2 == -1 )
993 n2 = n1;
995 if( n1 > n2 )
997 n1 = n2;
999 OUString s(aOut.copy(0, n1));
1000 aOut = aOut.copy(n1);
1001 while ( !aOut.isEmpty() && (aOut[0] == '\n' || aOut[0] == '\r') )
1003 aOut = aOut.copy(1);
1006 SolarMutexGuard aSolarGuard;
1007 if( !ScopedVclPtr<MessBox>::Create(
1008 Application::GetDefDialogParent(),
1009 WinBits( WB_OK_CANCEL | WB_DEF_OK ),
1010 OUString(), s )->Execute() )
1012 nError = SbERR_USER_ABORT;
1018 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */