update dev300-m58
[ooovba.git] / basic / source / runtime / iosys.cxx
blobe4d667ecc01888580ed7391720214cdfecb01da2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: iosys.cxx,v $
10 * $Revision: 1.30 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
33 #include <vcl/dialog.hxx>
34 #include <vcl/edit.hxx>
35 #ifndef _SV_BUTTON_HXX //autogen
36 #include <vcl/button.hxx>
37 #endif
38 #include <vcl/msgbox.hxx>
39 #include <vcl/svapp.hxx>
40 #include <osl/security.h>
41 #include <osl/file.hxx>
42 #include <tools/urlobj.hxx>
43 #include <vos/mutex.hxx>
45 #include "runtime.hxx"
47 #ifdef _USE_UNO
49 // <-- encoding
50 #include <sal/alloca.h>
52 #include <ctype.h>
53 #include <rtl/byteseq.hxx>
54 #include <rtl/textenc.h>
55 #include <rtl/ustrbuf.hxx>
56 #include <rtl/textenc.h>
57 #include <rtl/ustrbuf.hxx>
58 // encoding -->
59 #include <comphelper/processfactory.hxx>
61 #include <com/sun/star/uno/Sequence.hxx>
62 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
63 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
64 #include <com/sun/star/ucb/XContentProvider.hpp>
65 #include <com/sun/star/ucb/XContentProviderManager.hpp>
66 #include <com/sun/star/io/XInputStream.hpp>
67 #include <com/sun/star/io/XOutputStream.hpp>
68 #include <com/sun/star/io/XStream.hpp>
69 #include <com/sun/star/io/XSeekable.hpp>
70 #include <com/sun/star/bridge/XBridge.hpp>
71 #include <com/sun/star/bridge/XBridgeFactory.hpp>
73 using namespace comphelper;
74 using namespace osl;
75 using namespace com::sun::star::uno;
76 using namespace com::sun::star::lang;
77 using namespace com::sun::star::ucb;
78 using namespace com::sun::star::io;
79 using namespace com::sun::star::bridge;
81 #endif /* _USE_UNO */
83 #include "iosys.hxx"
84 #include "sbintern.hxx"
86 // Der Input-Dialog:
88 class SbiInputDialog : public ModalDialog {
89 Edit aInput;
90 OKButton aOk;
91 CancelButton aCancel;
92 String aText;
93 DECL_LINK( Ok, Window * );
94 DECL_LINK( Cancel, Window * );
95 public:
96 SbiInputDialog( Window*, const String& );
97 const String& GetInput() { return aText; }
100 SbiInputDialog::SbiInputDialog( Window* pParent, const String& rPrompt )
101 :ModalDialog( pParent, WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ),
102 aInput( this, WB_3DLOOK | WB_LEFT | WB_BORDER ),
103 aOk( this ), aCancel( this )
105 SetText( rPrompt );
106 aOk.SetClickHdl( LINK( this, SbiInputDialog, Ok ) );
107 aCancel.SetClickHdl( LINK( this, SbiInputDialog, Cancel ) );
108 SetMapMode( MapMode( MAP_APPFONT ) );
110 Point aPt = LogicToPixel( Point( 50, 50 ) );
111 Size aSz = LogicToPixel( Size( 145, 65 ) );
112 SetPosSizePixel( aPt, aSz );
113 aPt = LogicToPixel( Point( 10, 10 ) );
114 aSz = LogicToPixel( Size( 120, 12 ) );
115 aInput.SetPosSizePixel( aPt, aSz );
116 aPt = LogicToPixel( Point( 15, 30 ) );
117 aSz = LogicToPixel( Size( 45, 15) );
118 aOk.SetPosSizePixel( aPt, aSz );
119 aPt = LogicToPixel( Point( 80, 30 ) );
120 aSz = LogicToPixel( Size( 45, 15) );
121 aCancel.SetPosSizePixel( aPt, aSz );
123 aInput.Show();
124 aOk.Show();
125 aCancel.Show();
128 IMPL_LINK_INLINE_START( SbiInputDialog, Ok, Window *, pWindow )
130 (void)pWindow;
132 aText = aInput.GetText();
133 EndDialog( 1 );
134 return 0;
136 IMPL_LINK_INLINE_END( SbiInputDialog, Ok, Window *, pWindow )
138 IMPL_LINK_INLINE_START( SbiInputDialog, Cancel, Window *, pWindow )
140 (void)pWindow;
142 EndDialog( 0 );
143 return 0;
145 IMPL_LINK_INLINE_END( SbiInputDialog, Cancel, Window *, pWindow )
147 //////////////////////////////////////////////////////////////////////////
149 SbiStream::SbiStream()
150 : pStrm( 0 )
154 SbiStream::~SbiStream()
156 delete pStrm;
159 // Ummappen eines SvStream-Fehlers auf einen StarBASIC-Code
161 void SbiStream::MapError()
163 if( pStrm )
164 switch( pStrm->GetError() )
166 case SVSTREAM_OK:
167 nError = 0; break;
168 case SVSTREAM_FILE_NOT_FOUND:
169 nError = SbERR_FILE_NOT_FOUND; break;
170 case SVSTREAM_PATH_NOT_FOUND:
171 nError = SbERR_PATH_NOT_FOUND; break;
172 case SVSTREAM_TOO_MANY_OPEN_FILES:
173 nError = SbERR_TOO_MANY_FILES; break;
174 case SVSTREAM_ACCESS_DENIED:
175 nError = SbERR_ACCESS_DENIED; break;
176 case SVSTREAM_INVALID_PARAMETER:
177 nError = SbERR_BAD_ARGUMENT; break;
178 case SVSTREAM_OUTOFMEMORY:
179 nError = SbERR_NO_MEMORY; break;
180 default:
181 nError = SbERR_IO_ERROR; break;
185 #ifdef _USE_UNO
187 // TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx
189 ::rtl::OUString findUserInDescription( const ::rtl::OUString& aDescription )
191 ::rtl::OUString user;
193 sal_Int32 index;
194 sal_Int32 lastIndex = 0;
198 index = aDescription.indexOf((sal_Unicode) ',', lastIndex);
199 ::rtl::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 ::rtl::OUString left = token.copy(0, eindex).toAsciiLowerCase().trim();
205 ::rtl::OUString right = INetURLObject::decode( token.copy(eindex + 1).trim(), '%',
206 INetURLObject::DECODE_WITH_CHARSET );
208 if(left.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user"))))
210 user = right;
211 break;
214 while(index != -1);
216 return user;
219 #endif
222 // Hack for #83750
223 BOOL runsInSetup( void );
225 BOOL needSecurityRestrictions( void )
227 #ifdef _USE_UNO
228 static BOOL bNeedInit = TRUE;
229 static BOOL bRetVal = TRUE;
231 if( bNeedInit )
233 // Hack for #83750, use internal flag until
234 // setup provides own service manager
235 if( runsInSetup() )
237 // Setup is not critical
238 bRetVal = FALSE;
239 return bRetVal;
242 bNeedInit = FALSE;
244 // Get system user to compare to portal user
245 oslSecurity aSecurity = osl_getCurrentSecurity();
246 ::rtl::OUString aSystemUser;
247 sal_Bool bRet = osl_getUserName( aSecurity, &aSystemUser.pData );
248 if( !bRet )
250 // No valid security! -> Secure mode!
251 return TRUE;
254 Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
255 if( !xSMgr.is() )
256 return TRUE;
257 Reference< XBridgeFactory > xBridgeFac( xSMgr->createInstance
258 ( ::rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" ) ), UNO_QUERY );
260 Sequence< Reference< XBridge > > aBridgeSeq;
261 sal_Int32 nBridgeCount = 0;
262 if( xBridgeFac.is() )
264 aBridgeSeq = xBridgeFac->getExistingBridges();
265 nBridgeCount = aBridgeSeq.getLength();
268 if( nBridgeCount == 0 )
270 // No bridges -> local
271 bRetVal = FALSE;
272 return bRetVal;
275 // Iterate through all bridges to find (portal) user property
276 const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray();
277 bRetVal = FALSE; // Now only TRUE if user different from portal user is found
278 sal_Int32 i;
279 for( i = 0 ; i < nBridgeCount ; i++ )
281 const Reference< XBridge >& rxBridge = pBridges[ i ];
282 ::rtl::OUString aDescription = rxBridge->getDescription();
283 ::rtl::OUString aPortalUser = findUserInDescription( aDescription );
284 if( aPortalUser.getLength() > 0 )
286 // User Found, compare to system user
287 if( aPortalUser == aSystemUser )
289 // Same user -> system security is ok, bRetVal stays FALSE
290 break;
292 else
294 // Different user -> Secure mode!
295 bRetVal = TRUE;
296 break;
300 // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
303 return bRetVal;
304 #else
305 return FALSE;
306 #endif
309 // Returns TRUE if UNO is available, otherwise the old file
310 // system implementation has to be used
311 // #89378 New semantic: Don't just ask for UNO but for UCB
312 BOOL hasUno( void )
314 #ifdef _USE_UNO
315 static BOOL bNeedInit = TRUE;
316 static BOOL bRetVal = TRUE;
318 if( bNeedInit )
320 bNeedInit = FALSE;
321 Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
322 if( !xSMgr.is() )
324 // No service manager at all
325 bRetVal = FALSE;
327 else
329 Reference< XContentProviderManager > xManager( xSMgr->createInstance( ::rtl::OUString::createFromAscii
330 ( "com.sun.star.ucb.UniversalContentBroker" ) ), UNO_QUERY );
332 if ( !( xManager.is() && xManager->queryContentProvider( ::rtl::OUString::createFromAscii( "file:///" ) ).is() ) )
334 // No UCB
335 bRetVal = FALSE;
339 return bRetVal;
340 #else
341 return FALSE;
342 #endif
347 #ifndef _OLD_FILE_IMPL
349 class OslStream : public SvStream
351 File maFile;
352 short mnStrmMode;
354 public:
355 OslStream( const String& rName, short nStrmMode );
356 ~OslStream();
357 virtual ULONG GetData( void* pData, ULONG nSize );
358 virtual ULONG PutData( const void* pData, ULONG nSize );
359 virtual ULONG SeekPos( ULONG nPos );
360 virtual void FlushData();
361 virtual void SetSize( ULONG nSize );
364 OslStream::OslStream( const String& rName, short nStrmMode )
365 : maFile( rName )
366 , mnStrmMode( nStrmMode )
368 sal_uInt32 nFlags;
370 if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
372 nFlags = OpenFlag_Read | OpenFlag_Write;
374 else if( nStrmMode & STREAM_WRITE )
376 nFlags = OpenFlag_Write;
378 else //if( nStrmMode & STREAM_READ )
380 nFlags = OpenFlag_Read;
383 FileBase::RC nRet = maFile.open( nFlags );
384 if( nRet == FileBase::E_NOENT && nFlags != OpenFlag_Read )
386 nFlags |= OpenFlag_Create;
387 nRet = maFile.open( nFlags );
390 if( nRet != FileBase::E_None )
392 SetError( ERRCODE_IO_GENERAL );
397 OslStream::~OslStream()
399 maFile.close();
402 ULONG OslStream::GetData( void* pData, ULONG nSize )
404 sal_uInt64 nBytesRead = nSize;
405 FileBase::RC nRet = FileBase::E_None;
406 nRet = maFile.read( pData, nBytesRead, nBytesRead );
407 return (ULONG)nBytesRead;
410 ULONG OslStream::PutData( const void* pData, ULONG nSize )
412 sal_uInt64 nBytesWritten;
413 FileBase::RC nRet = FileBase::E_None;
414 nRet = maFile.write( pData, (sal_uInt64)nSize, nBytesWritten );
415 return (ULONG)nBytesWritten;
418 ULONG OslStream::SeekPos( ULONG nPos )
420 FileBase::RC nRet;
421 if( nPos == STREAM_SEEK_TO_END )
423 nRet = maFile.setPos( Pos_End, 0 );
425 else
427 nRet = maFile.setPos( Pos_Absolut, (sal_uInt64)nPos );
429 sal_uInt64 nRealPos;
430 nRet = maFile.getPos( nRealPos );
431 return sal::static_int_cast<ULONG>(nRealPos);
434 void OslStream::FlushData()
438 void OslStream::SetSize( ULONG nSize )
440 FileBase::RC nRet = FileBase::E_None;
441 nRet = maFile.setSize( (sal_uInt64)nSize );
444 #endif
447 #ifdef _USE_UNO
449 class UCBStream : public SvStream
451 Reference< XInputStream > xIS;
452 Reference< XOutputStream > xOS;
453 Reference< XStream > xS;
454 Reference< XSeekable > xSeek;
455 public:
456 UCBStream( Reference< XInputStream > & xIS );
457 UCBStream( Reference< XOutputStream > & xOS );
458 UCBStream( Reference< XStream > & xS );
459 ~UCBStream();
460 virtual ULONG GetData( void* pData, ULONG nSize );
461 virtual ULONG PutData( const void* pData, ULONG nSize );
462 virtual ULONG SeekPos( ULONG nPos );
463 virtual void FlushData();
464 virtual void SetSize( ULONG nSize );
468 ULONG UCBErrorToSvStramError( ucb::IOErrorCode nError )
470 ULONG eReturn = ERRCODE_IO_GENERAL;
471 switch( nError )
473 case ucb::IOErrorCode_ABORT: eReturn = SVSTREAM_GENERALERROR; break;
474 case ucb::IOErrorCode_NOT_EXISTING: eReturn = SVSTREAM_FILE_NOT_FOUND; break;
475 case ucb::IOErrorCode_NOT_EXISTING_PATH: eReturn = SVSTREAM_PATH_NOT_FOUND; break;
476 case ucb::IOErrorCode_OUT_OF_FILE_HANDLES: eReturn = SVSTREAM_TOO_MANY_OPEN_FILES; break;
477 case ucb::IOErrorCode_ACCESS_DENIED: eReturn = SVSTREAM_ACCESS_DENIED; break;
478 case ucb::IOErrorCode_LOCKING_VIOLATION: eReturn = SVSTREAM_SHARING_VIOLATION; break;
480 case ucb::IOErrorCode_INVALID_ACCESS: eReturn = SVSTREAM_INVALID_ACCESS; break;
481 case ucb::IOErrorCode_CANT_CREATE: eReturn = SVSTREAM_CANNOT_MAKE; break;
482 case ucb::IOErrorCode_INVALID_PARAMETER: eReturn = SVSTREAM_INVALID_PARAMETER; break;
484 case ucb::IOErrorCode_CANT_READ: eReturn = SVSTREAM_READ_ERROR; break;
485 case ucb::IOErrorCode_CANT_WRITE: eReturn = SVSTREAM_WRITE_ERROR; break;
486 case ucb::IOErrorCode_CANT_SEEK: eReturn = SVSTREAM_SEEK_ERROR; break;
487 case ucb::IOErrorCode_CANT_TELL: eReturn = SVSTREAM_TELL_ERROR; break;
489 case ucb::IOErrorCode_OUT_OF_MEMORY: eReturn = SVSTREAM_OUTOFMEMORY; break;
491 case SVSTREAM_FILEFORMAT_ERROR: eReturn = SVSTREAM_FILEFORMAT_ERROR; break;
492 case ucb::IOErrorCode_WRONG_VERSION: eReturn = SVSTREAM_WRONGVERSION;
493 case ucb::IOErrorCode_OUT_OF_DISK_SPACE: eReturn = SVSTREAM_DISK_FULL; break;
495 case ucb::IOErrorCode_BAD_CRC: eReturn = ERRCODE_IO_BADCRC; break;
497 return eReturn;
501 UCBStream::UCBStream( Reference< XInputStream > & rStm )
502 : xIS( rStm )
503 , xSeek( rStm, UNO_QUERY )
507 UCBStream::UCBStream( Reference< XOutputStream > & rStm )
508 : xOS( rStm )
509 , xSeek( rStm, UNO_QUERY )
513 UCBStream::UCBStream( Reference< XStream > & rStm )
514 : xS( rStm )
515 , xSeek( rStm, UNO_QUERY )
520 UCBStream::~UCBStream()
524 if( xIS.is() )
525 xIS->closeInput();
526 else if( xOS.is() )
527 xOS->closeOutput();
528 else if( xS.is() )
530 Reference< XInputStream > xIS_ = xS->getInputStream();
531 if( xIS_.is() )
532 xIS_->closeInput();
535 catch( Exception & )
537 SetError( ERRCODE_IO_GENERAL );
541 ULONG UCBStream::GetData( void* pData, ULONG nSize )
545 Reference< XInputStream > xISFromS;
546 if( xIS.is() )
548 Sequence<sal_Int8> aData;
549 nSize = xIS->readBytes( aData, nSize );
550 rtl_copyMemory( pData, aData.getConstArray(), nSize );
551 return nSize;
553 else if( xS.is() && (xISFromS = xS->getInputStream()).is() )
555 Sequence<sal_Int8> aData;
556 nSize = xISFromS->readBytes( aData, nSize );
557 rtl_copyMemory( pData, aData.getConstArray(), nSize );
558 return nSize;
560 else
561 SetError( ERRCODE_IO_GENERAL );
563 catch( Exception & )
565 SetError( ERRCODE_IO_GENERAL );
567 return 0;
570 ULONG UCBStream::PutData( const void* pData, ULONG nSize )
574 Reference< XOutputStream > xOSFromS;
575 if( xOS.is() )
577 Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
578 xOS->writeBytes( aData );
579 return nSize;
581 else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
583 Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
584 xOSFromS->writeBytes( aData );
585 return nSize;
587 else
588 SetError( ERRCODE_IO_GENERAL );
590 catch( Exception & )
592 SetError( ERRCODE_IO_GENERAL );
594 return 0;
597 ULONG UCBStream::SeekPos( ULONG nPos )
601 if( xSeek.is() )
603 ULONG nLen = sal::static_int_cast<ULONG>( xSeek->getLength() );
604 if( nPos > nLen )
605 nPos = nLen;
606 xSeek->seek( nPos );
607 return nPos;
609 else
610 SetError( ERRCODE_IO_GENERAL );
612 catch( Exception & )
614 SetError( ERRCODE_IO_GENERAL );
616 return 0;
619 void UCBStream::FlushData()
623 Reference< XOutputStream > xOSFromS;
624 if( xOS.is() )
625 xOS->flush();
626 else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
627 xOSFromS->flush();
628 else
629 SetError( ERRCODE_IO_GENERAL );
631 catch( Exception & )
633 SetError( ERRCODE_IO_GENERAL );
637 void UCBStream::SetSize( ULONG nSize )
639 (void)nSize;
641 DBG_ERROR( "not allowed to call from basic" );
642 SetError( ERRCODE_IO_GENERAL );
645 #endif
647 // Oeffnen eines Streams
648 SbError SbiStream::Open
649 ( short nCh, const ByteString& rName, short nStrmMode, short nFlags, short nL )
651 nMode = nFlags;
652 nLen = nL;
653 nChan = nCh;
654 nLine = 0;
655 nExpandOnWriteTo = 0;
656 if( ( nStrmMode & ( STREAM_READ|STREAM_WRITE ) ) == STREAM_READ )
657 nStrmMode |= STREAM_NOCREATE;
658 String aStr( rName, gsl_getSystemTextEncoding() );
659 String aNameStr = getFullPath( aStr );
661 #ifdef _USE_UNO
662 if( hasUno() )
664 Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
665 if( xSMgr.is() )
667 Reference< XSimpleFileAccess >
668 xSFI( xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY );
669 if( xSFI.is() )
674 // #??? For write access delete file if it already exists (not for appending)
675 if( (nStrmMode & STREAM_WRITE) != 0 && !IsAppend() && !IsBinary() &&
676 xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) )
678 xSFI->kill( aNameStr );
681 if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
683 Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
684 pStrm = new UCBStream( xIS );
686 else if( nStrmMode & STREAM_WRITE )
688 Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
689 pStrm = new UCBStream( xIS );
690 // Open for writing is not implemented in ucb yet!!!
691 //Reference< XOutputStream > xIS = xSFI->openFileWrite( aNameStr );
692 //pStrm = new UCBStream( xIS );
694 else //if( nStrmMode & STREAM_READ )
696 Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr );
697 pStrm = new UCBStream( xIS );
701 catch( Exception & )
703 nError = ERRCODE_IO_GENERAL;
709 #endif
710 if( !pStrm )
712 #ifdef _OLD_FILE_IMPL
713 pStrm = new SvFileStream( aNameStr, nStrmMode );
714 #else
715 pStrm = new OslStream( aNameStr, nStrmMode );
716 #endif
718 if( IsAppend() )
719 pStrm->Seek( STREAM_SEEK_TO_END );
720 MapError();
721 if( nError )
722 delete pStrm, pStrm = NULL;
723 return nError;
726 SbError SbiStream::Close()
728 if( pStrm )
730 if( !hasUno() )
732 #ifdef _OLD_FILE_IMPL
733 ((SvFileStream *)pStrm)->Close();
734 #endif
736 MapError();
737 delete pStrm;
738 pStrm = NULL;
740 nChan = 0;
741 return nError;
744 SbError SbiStream::Read( ByteString& rBuf, USHORT n, bool bForceReadingPerByte )
746 nExpandOnWriteTo = 0;
747 if( !bForceReadingPerByte && IsText() )
749 pStrm->ReadLine( rBuf );
750 nLine++;
752 else
754 if( !n ) n = nLen;
755 if( !n )
756 return nError = SbERR_BAD_RECORD_LENGTH;
757 rBuf.Fill( n, ' ' );
758 pStrm->Read( (void*)rBuf.GetBuffer(), n );
760 MapError();
761 if( !nError && pStrm->IsEof() )
762 nError = SbERR_READ_PAST_EOF;
763 return nError;
766 SbError SbiStream::Read( char& ch )
768 nExpandOnWriteTo = 0;
769 if( !aLine.Len() )
771 Read( aLine, 0 );
772 aLine += '\n';
774 ch = aLine.GetBuffer()[0];
775 aLine.Erase( 0, 1 );
776 return nError;
779 void SbiStream::ExpandFile()
781 if ( nExpandOnWriteTo )
783 ULONG nCur = pStrm->Seek(STREAM_SEEK_TO_END);
784 if( nCur < nExpandOnWriteTo )
786 ULONG nDiff = nExpandOnWriteTo - nCur;
787 char c = 0;
788 while( nDiff-- )
789 *pStrm << c;
791 else
793 pStrm->Seek( nExpandOnWriteTo );
795 nExpandOnWriteTo = 0;
799 SbError SbiStream::Write( const ByteString& rBuf, USHORT n )
801 ExpandFile();
802 if( IsAppend() )
803 pStrm->Seek( STREAM_SEEK_TO_END );
805 if( IsText() )
807 aLine += rBuf;
808 // Raus damit, wenn das Ende ein LF ist, aber CRLF vorher
809 // strippen, da der SvStrm ein CRLF anfuegt!
810 USHORT nLineLen = aLine.Len();
811 if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0A )
813 aLine.Erase( nLineLen );
814 if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0D )
815 aLine.Erase( nLineLen );
816 pStrm->WriteLines( aLine );
817 aLine.Erase();
820 else
822 if( !n ) n = nLen;
823 if( !n )
824 return nError = SbERR_BAD_RECORD_LENGTH;
825 pStrm->Write( rBuf.GetBuffer(), n );
826 MapError();
828 return nError;
831 //////////////////////////////////////////////////////////////////////////
833 // Zugriff auf das aktuelle I/O-System:
835 SbiIoSystem* SbGetIoSystem()
837 SbiInstance* pInst = pINST;
838 return pInst ? pInst->GetIoSystem() : NULL;
841 //////////////////////////////////////////////////////////////////////////
843 SbiIoSystem::SbiIoSystem()
845 for( short i = 0; i < CHANNELS; i++ )
846 pChan[ i ] = NULL;
847 nChan = 0;
848 nError = 0;
851 SbiIoSystem::~SbiIoSystem()
853 Shutdown();
856 SbError SbiIoSystem::GetError()
858 SbError n = nError; nError = 0;
859 return n;
862 void SbiIoSystem::Open
863 ( short nCh, const ByteString& rName, short nMode, short nFlags, short nLen )
865 nError = 0;
866 if( nCh >= CHANNELS || !nCh )
867 nError = SbERR_BAD_CHANNEL;
868 else if( pChan[ nCh ] )
869 nError = SbERR_FILE_ALREADY_OPEN;
870 else
872 pChan[ nCh ] = new SbiStream;
873 nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen );
874 if( nError )
875 delete pChan[ nCh ], pChan[ nCh ] = NULL;
877 nChan = 0;
880 // Aktuellen Kanal schliessen
882 void SbiIoSystem::Close()
884 if( !nChan )
885 nError = SbERR_BAD_CHANNEL;
886 else if( !pChan[ nChan ] )
887 nError = SbERR_BAD_CHANNEL;
888 else
890 nError = pChan[ nChan ]->Close();
891 delete pChan[ nChan ];
892 pChan[ nChan ] = NULL;
894 nChan = 0;
897 // Shutdown nach Programmlauf
899 void SbiIoSystem::Shutdown()
901 for( short i = 1; i < CHANNELS; i++ )
903 if( pChan[ i ] )
905 SbError n = pChan[ i ]->Close();
906 delete pChan[ i ];
907 pChan[ i ] = NULL;
908 if( n && !nError )
909 nError = n;
912 nChan = 0;
913 // Noch was zu PRINTen?
914 if( aOut.Len() )
916 String aOutStr( aOut, gsl_getSystemTextEncoding() );
917 #if defined GCC
918 Window* pParent = Application::GetDefDialogParent();
919 MessBox( pParent, WinBits( WB_OK ), String(), aOutStr ).Execute();
920 #else
921 MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), String(), aOutStr ).Execute();
922 #endif
924 aOut.Erase();
927 // Aus aktuellem Kanal lesen
929 void SbiIoSystem::Read( ByteString& rBuf, short n )
931 if( !nChan )
932 ReadCon( rBuf );
933 else if( !pChan[ nChan ] )
934 nError = SbERR_BAD_CHANNEL;
935 else
936 nError = pChan[ nChan ]->Read( rBuf, n );
939 char SbiIoSystem::Read()
941 char ch = ' ';
942 if( !nChan )
944 if( !aIn.Len() )
946 ReadCon( aIn );
947 aIn += '\n';
949 ch = aIn.GetBuffer()[0];
950 aIn.Erase( 0, 1 );
952 else if( !pChan[ nChan ] )
953 nError = SbERR_BAD_CHANNEL;
954 else
955 nError = pChan[ nChan ]->Read( ch );
956 return ch;
959 void SbiIoSystem::Write( const ByteString& rBuf, short n )
961 if( !nChan )
962 WriteCon( rBuf );
963 else if( !pChan[ nChan ] )
964 nError = SbERR_BAD_CHANNEL;
965 else
966 nError = pChan[ nChan ]->Write( rBuf, n );
969 short SbiIoSystem::NextChannel()
971 for( short i = 1; i < CHANNELS; i++ )
973 if( !pChan[ i ] )
974 return i;
976 nError = SbERR_TOO_MANY_FILES;
977 return CHANNELS;
980 // nChannel == 0..CHANNELS-1
982 SbiStream* SbiIoSystem::GetStream( short nChannel ) const
984 SbiStream* pRet = 0;
985 if( nChannel >= 0 && nChannel < CHANNELS )
986 pRet = pChan[ nChannel ];
987 return pRet;
990 void SbiIoSystem::CloseAll(void)
992 for( short i = 1; i < CHANNELS; i++ )
994 if( pChan[ i ] )
996 SbError n = pChan[ i ]->Close();
997 delete pChan[ i ];
998 pChan[ i ] = NULL;
999 if( n && !nError )
1000 nError = n;
1005 /***************************************************************************
1007 * Console Support
1009 ***************************************************************************/
1011 // Einlesen einer Zeile von der Console
1013 void SbiIoSystem::ReadCon( ByteString& rIn )
1015 String aPromptStr( aPrompt, gsl_getSystemTextEncoding() );
1016 SbiInputDialog aDlg( NULL, aPromptStr );
1017 if( aDlg.Execute() )
1018 rIn = ByteString( aDlg.GetInput(), gsl_getSystemTextEncoding() );
1019 else
1020 nError = SbERR_USER_ABORT;
1021 aPrompt.Erase();
1024 // Ausgabe einer MessageBox, wenn im Console-Puffer ein CR ist
1026 void SbiIoSystem::WriteCon( const ByteString& rText )
1028 aOut += rText;
1029 USHORT n1 = aOut.Search( '\n' );
1030 USHORT n2 = aOut.Search( '\r' );
1031 if( n1 != STRING_NOTFOUND || n2 != STRING_NOTFOUND )
1033 if( n1 == STRING_NOTFOUND ) n1 = n2;
1034 else
1035 if( n2 == STRING_NOTFOUND ) n2 = n1;
1036 if( n1 > n2 ) n1 = n2;
1037 ByteString s( aOut.Copy( 0, n1 ) );
1038 aOut.Erase( 0, n1 );
1039 while( aOut.GetBuffer()[0] == '\n' || aOut.GetBuffer()[0] == '\r' )
1040 aOut.Erase( 0, 1 );
1041 String aStr( s, gsl_getSystemTextEncoding() );
1043 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1044 if( !MessBox( GetpApp()->GetDefDialogParent(),
1045 WinBits( WB_OK_CANCEL | WB_DEF_OK ),
1046 String(), aStr ).Execute() )
1047 nError = SbERR_USER_ABORT;