/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ // Created 10/14/96 hardts // input and output streams as well as ITapeFileSystem #ifdef EDITOR // Work-around for Win16 precompiled header bug -- all .cpp files in // lib/layout have to include editor.h first. This file // doesn't even need editor.h. #include "editor.h" #include "rosetta.h" #include "streams.h" #include "secnav.h" //----------------------------------------------------------------------------- // Streams, Implementation //----------------------------------------------------------------------------- // // LTNOTE: // There is some uglyness on different platforms to make this work. We'll // cross that bridge when we come to it. // IStreamOut::IStreamOut(){ stream_buffer = 0; } IStreamOut::~IStreamOut(){ XP_FREE(stream_buffer); } int IStreamOut::Printf( char * pFormat, ... ){ va_list stack; int32 len; // if the buffer has been allocated, resize it. if( stream_buffer ){ stream_buffer[0] = 0; } va_start (stack, pFormat); stream_buffer = PR_vsprintf_append( stream_buffer, pFormat, stack ); va_end (stack); len = XP_STRLEN( stream_buffer ); Write( stream_buffer, len ); return len; } void IStreamOut::WriteZString(char* pString){ if( pString ){ int32 iLen = XP_STRLEN( pString )+1; WriteInt( iLen ); Write( pString, iLen ); } else { WriteInt(0); } } void IStreamOut::WritePartialZString(char* pString, int32 start, int32 end){ int32 iLen = end - start; XP_ASSERT(iLen >= 0); if( pString && iLen > 0 ){ WriteInt( iLen + 1 ); // Account for the '\0' Write( pString + start, iLen ); Write( "", 1 ); // write the '\0' } else { WriteInt(0); } } char* IStreamIn::ReadZString(){ char *pRet = 0; int32 iLen = ReadInt(); if( iLen ){ pRet = (char*)XP_ALLOC(iLen); Read( pRet, iLen ); } return pRet; } //----------------------------------------------------------------------------- // File Stream //----------------------------------------------------------------------------- //CM: For better cross-platform use, call with file handle already open CStreamOutFile::CStreamOutFile( XP_File hFile, XP_Bool bBinary ){ m_status = EOS_NoError; m_outputFile = hFile; m_bBinary = bBinary; } CStreamOutFile::~CStreamOutFile(){ XP_FileClose( m_outputFile ); } void CStreamOutFile::Write( char *pBuffer, int32 iCount ){ if( m_status != EOS_NoError ){ return; } // this code doesn't work and it probably should be done at the other end // it is designed to fix CR's showing up in the text. int iWrote; if( !m_bBinary ){ int i = 0; int iLast = 0; int iWrite; while( i < iCount ){ if( pBuffer[i] == '\n' ){ iWrite = i - iLast; if( iWrite ){ iWrote = XP_FileWrite( &pBuffer[iLast], iWrite, m_outputFile ); if( iWrote != iWrite ){ m_status = EOS_DeviceFull; } } #ifdef XP_MAC iWrote = XP_FileWrite("\r", 1, m_outputFile ); #else iWrote = XP_FileWrite("\n", 1, m_outputFile ); #endif if( iWrote != 1 ){ m_status = EOS_DeviceFull; } iLast = i+1; } i++; } iWrite = i - iLast; if( iWrite ){ iWrote = XP_FileWrite( &pBuffer[iLast], iWrite, m_outputFile ); if( iWrote != iWrite ){ m_status = EOS_DeviceFull; } } return; } else { iWrote = XP_FileWrite( pBuffer, iCount, m_outputFile ); if( iWrote != iCount ){ m_status = EOS_DeviceFull; } } } //----------------------------------------------------------------------------- // NetStream //----------------------------------------------------------------------------- CStreamOutNet::CStreamOutNet( MWContext* pContext ) { URL_Struct * URL_s; Chrome chrome; XP_BZERO( &chrome, sizeof( Chrome ) ); chrome.allow_close = TRUE; chrome.allow_resize = TRUE; chrome.show_scrollbar = TRUE; #ifndef XP_WIN // NOTE: need to verify this change on XP_WIN and remove the // ifndef... [ works on XP_UNIX & XP_MAC ] // chrome.type = MWContextDialog; #endif // // LTNOTE: Ownership of the 'chrome' struct isn't documented in the interface. // The windows implementation doesn't appear to keep pointers to the struct. // MWContext *pNewContext = FE_MakeNewWindow(pContext, NULL, "view-source", &chrome ); pNewContext->edit_view_source_hack = TRUE; URL_s = NET_CreateURLStruct(XP_GetString(EDT_VIEW_SOURCE_WINDOW_TITLE), NET_DONT_RELOAD); URL_s->content_type = XP_STRDUP(TEXT_PLAIN); m_pStream = NET_StreamBuilder(FO_PRESENT, URL_s, pNewContext); if(!m_pStream){ XP_ASSERT( FALSE ); m_status = EOS_FileError; } m_status = EOS_NoError; } // // constructor for children // CStreamOutNet::CStreamOutNet(void){ m_pStream = NULL; m_status = EOS_NoError; } //----------------------------------------------------------------------------- // GenNetStream // // This is what NetStream out should have been! A generalized net function. // //----------------------------------------------------------------------------- CStreamOutAnyNet::CStreamOutAnyNet(MWContext* pContext, URL_Struct *URL_s, FO_Present_Types type ){ NET_StreamClass *stream; //URL_s->content_type = XP_STRDUP(TEXT_PLAIN); stream = NET_StreamBuilder(type, URL_s, pContext); if(!stream){ XP_ASSERT( FALSE ); } else { SetStream(stream); } } CNetStreamToTapeFS::CNetStreamToTapeFS(MWContext* pContext, ITapeFileSystem *tapeFS ){ NET_StreamClass *stream = NULL; if(!stream){ XP_ASSERT( FALSE ); } else { SetStream(stream); } } // // Do't forget to free the stream as well... // CStreamOutNet::~CStreamOutNet(){ if (m_pStream == NULL) return; (*m_pStream->complete)(m_pStream); XP_FREE(m_pStream); } void CStreamOutNet::SetStream(NET_StreamClass *stream){ m_pStream = stream; } void CStreamOutNet::Write( char *pBuffer, int32 iCount ){ // Buffer the output. // pBuffer may be a const string, even a ROM string. // (e.g. string constants on a Mac with VM.) // But networking does in-place transformations on the // data to convert it into other character sets. const int32 kBufferSize = 128; char buffer[kBufferSize]; if (m_pStream == NULL) { // if we're trying to write with a null stream, we have definately // tripped over an error m_status = EOS_FileError; return; } while ( iCount > 0 ) { int32 iChunkSize = iCount; if ( iChunkSize > kBufferSize ) { iChunkSize = kBufferSize; } XP_MEMCPY(buffer, pBuffer, iChunkSize); int status = (*m_pStream->put_block)(m_pStream, buffer, iChunkSize ); if(status < 0){ m_status = EOS_FileError; (*m_pStream->abort)(m_pStream, status); XP_FREE(m_pStream); m_pStream = NULL; break; } // status?? iCount -= iChunkSize; } } //----------------------------------------------------------------------------- // Memory Streams //----------------------------------------------------------------------------- #define MEMBUF_GROW 10 #define MEMBUF_START 32 // CStreamOutMemory::CStreamOutMemory(): m_bufferSize(MEMBUF_START), m_bufferEnd(0), m_pBuffer(0) { m_pBuffer = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC( m_bufferSize ); m_pBuffer[m_bufferEnd] = '\0'; } // // This implementation intenttionally does not destroy the buffer. The buffer // is kept and destroyed by the stream user. // CStreamOutMemory::~CStreamOutMemory(){ } // // void CStreamOutMemory::Write( char *pSrc, int32 iCount ){ int32 neededSize = iCount + m_bufferEnd + 1; /* Extra byte for '\0' */ // // Grow the buffer if need be. // if( neededSize > m_bufferSize ){ int32 iNewSize = (neededSize * 5 / 4) + MEMBUF_GROW; XP_HUGE_CHAR_PTR pBuf = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC(iNewSize); if( pBuf ){ XP_HUGE_MEMCPY(pBuf, m_pBuffer, m_bufferSize ); XP_HUGE_FREE(m_pBuffer); m_pBuffer = pBuf; m_bufferSize = iNewSize; } else { // LTNOTE: throw an out of memory exception XP_ASSERT(FALSE); return; } } XP_HUGE_MEMCPY( &m_pBuffer[m_bufferEnd], pSrc, iCount ); m_bufferEnd += iCount; m_pBuffer[m_bufferEnd] = '\0'; } // class CConvertCSIDStreamOut CConvertCSIDStreamOut::CConvertCSIDStreamOut(int16 oldCSID, int16 newCSID, IStreamOut* pStream){ m_oldCSID = oldCSID; m_newCSID = newCSID; m_bNullConversion = oldCSID == newCSID; m_pStream = pStream; if ( ! m_bNullConversion ){ m_Converter = INTL_CreateCharCodeConverter(); if ( ! INTL_GetCharCodeConverter(oldCSID, newCSID, m_Converter) ){ INTL_DestroyCharCodeConverter(m_Converter); m_bNullConversion = TRUE; } } } CConvertCSIDStreamOut::~CConvertCSIDStreamOut(){ if ( ! m_bNullConversion ) { INTL_DestroyCharCodeConverter(m_Converter); } delete m_pStream; m_pStream = 0; } int16 CConvertCSIDStreamOut::GetOldCSID() { return m_oldCSID; } int16 CConvertCSIDStreamOut::GetNewCSID() { return m_newCSID; } void CConvertCSIDStreamOut::Write( char* pBuffer, int32 iCount ){ if ( ! m_pStream ) { return; } if ( m_bNullConversion ) { m_pStream->Write(pBuffer, iCount); } else { // INTL_CallCharaCodeConverter has a pecuilar calling convention. // if the converion is a no-op, the argument is returned. // if pToData hasn't changed it won't be null-terminated // else it **MUST** be NULL-terminated so we can get the new length // The character code converter will trash the input string under // some circumstances, as for example if a Mac is transcoding to // ISO-Latin-1. Therefore we must copy the input stream. char* pCopy = (char*) XP_ALLOC(iCount); if ( pCopy == NULL) { XP_ASSERT(FALSE); return; } XP_MEMCPY(pCopy, pBuffer, iCount); char* pToData = (char*) INTL_CallCharCodeConverter(m_Converter, (const unsigned char*) pCopy, iCount); if ( pToData ) { if ( pToData != pCopy ) iCount = XP_STRLEN(pToData); m_pStream->Write(pToData, iCount); if ( pToData != pCopy ) { XP_FREE(pToData); } } else { // Some sort of error. XP_ASSERT(FALSE); m_pStream->Write(pCopy, iCount); } XP_FREE(pCopy); } } IStreamOut* CConvertCSIDStreamOut::ForgetStream(){ IStreamOut* result = m_pStream; m_pStream = NULL; return result; } // class CStreamInMemory void CStreamInMemory::Read( char *pBuffer, int32 iCount ){ XP_HUGE_MEMCPY( pBuffer, &m_pBuffer[m_iCurrentPos], iCount ); m_iCurrentPos += iCount; } #endif // EDITOR