home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / streams.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  12.1 KB  |  430 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. // Created 10/14/96 hardts
  21. // input and output streams as well as ITapeFileSystem
  22.  
  23. #ifdef EDITOR
  24. // Work-around for Win16 precompiled header bug -- all .cpp files in
  25. // lib/layout have to include editor.h first. This file
  26. // doesn't even need editor.h.
  27. #include "editor.h"
  28. #include "rosetta.h"
  29.  
  30. #include "streams.h"
  31. #include "secnav.h"
  32.  
  33. //-----------------------------------------------------------------------------
  34. //  Streams, Implementation
  35. //-----------------------------------------------------------------------------
  36.  
  37. //
  38. // LTNOTE:
  39. // There is some uglyness on different platforms to make this work.  We'll 
  40. //  cross that bridge when we come to it.
  41. //
  42.  
  43. IStreamOut::IStreamOut(){
  44.     stream_buffer = 0;
  45. }
  46.  
  47. IStreamOut::~IStreamOut(){
  48.     XP_FREE(stream_buffer);
  49. }
  50.  
  51. int IStreamOut::Printf( char * pFormat, ... ){
  52.     va_list stack;
  53.     int32 len;
  54.  
  55.     // if the buffer has been allocated, resize it.
  56.     if( stream_buffer ){
  57.         stream_buffer[0] = 0;
  58.     }
  59.     va_start (stack, pFormat);
  60.     stream_buffer = PR_vsprintf_append( stream_buffer, pFormat, stack );
  61.     va_end (stack);
  62.  
  63.     len = XP_STRLEN( stream_buffer ); 
  64.     Write( stream_buffer, len );
  65.     return len;
  66. }
  67.  
  68. void IStreamOut::WriteZString(char* pString){
  69.     if( pString ){
  70.         int32 iLen = XP_STRLEN( pString )+1;
  71.         WriteInt( iLen );
  72.         Write( pString, iLen );
  73.     }
  74.     else {
  75.         WriteInt(0);
  76.     }
  77. }
  78.  
  79. void IStreamOut::WritePartialZString(char* pString, int32 start, int32 end){
  80.     int32 iLen = end - start;
  81.     XP_ASSERT(iLen >= 0);
  82.     if( pString && iLen > 0 ){
  83.         WriteInt( iLen + 1 ); // Account for the '\0'
  84.         Write( pString + start, iLen );
  85.         Write( "", 1 ); // write the '\0'
  86.     }
  87.     else {
  88.         WriteInt(0);
  89.     }
  90. }
  91.  
  92. char* IStreamIn::ReadZString(){
  93.     char *pRet = 0;
  94.     int32 iLen = ReadInt();
  95.     if( iLen ){
  96.         pRet = (char*)XP_ALLOC(iLen);
  97.         Read( pRet, iLen );
  98.     }
  99.     return pRet;
  100. }
  101.  
  102.  
  103. //-----------------------------------------------------------------------------
  104. // File Stream
  105. //-----------------------------------------------------------------------------
  106. //CM: For better cross-platform use, call with file handle already open
  107. CStreamOutFile::CStreamOutFile( XP_File hFile, XP_Bool bBinary ){
  108.     m_status = EOS_NoError;
  109.     m_outputFile = hFile;
  110.     m_bBinary = bBinary;
  111. }
  112.  
  113. CStreamOutFile::~CStreamOutFile(){
  114.     XP_FileClose( m_outputFile );
  115. }
  116.  
  117. void CStreamOutFile::Write( char *pBuffer, int32 iCount ){
  118.  
  119.     if( m_status != EOS_NoError ){
  120.         return;
  121.     }
  122.  
  123.     // this code doesn't work and it probably should be done at the other end
  124.     //  it is designed to fix CR's showing up in the text.
  125.  
  126.     int iWrote;
  127.  
  128.     if( !m_bBinary ){
  129.         int i = 0;
  130.         int iLast = 0;
  131.         int iWrite;
  132.         while( i < iCount ){
  133.             if( pBuffer[i] == '\n' ){
  134.                 iWrite = i - iLast;
  135.                 if( iWrite ){
  136.                     iWrote = XP_FileWrite( &pBuffer[iLast], iWrite, m_outputFile );
  137.                     if( iWrote != iWrite ){ m_status = EOS_DeviceFull; }
  138.                 }
  139. #ifdef XP_MAC
  140.                 iWrote = XP_FileWrite("\r", 1, m_outputFile );
  141. #else
  142.                 iWrote = XP_FileWrite("\n", 1, m_outputFile );
  143. #endif
  144.                 if( iWrote != 1 ){ m_status = EOS_DeviceFull; }
  145.                 iLast = i+1;
  146.             }
  147.             i++;
  148.         }
  149.         iWrite = i - iLast;
  150.         if( iWrite ){
  151.             iWrote = XP_FileWrite( &pBuffer[iLast], iWrite, m_outputFile );
  152.             if( iWrote != iWrite ){ m_status = EOS_DeviceFull; }
  153.         }
  154.         return;
  155.     }
  156.     else {
  157.         iWrote = XP_FileWrite( pBuffer, iCount, m_outputFile );
  158.         if( iWrote != iCount ){ m_status = EOS_DeviceFull; }
  159.     }
  160. }
  161.  
  162. //-----------------------------------------------------------------------------
  163. // NetStream
  164. //-----------------------------------------------------------------------------
  165. CStreamOutNet::CStreamOutNet( MWContext* pContext )
  166. {
  167.     URL_Struct * URL_s;
  168.     Chrome chrome;
  169.  
  170.     XP_BZERO( &chrome, sizeof( Chrome ) );
  171.     chrome.allow_close = TRUE;
  172.     chrome.allow_resize = TRUE;
  173.     chrome.show_scrollbar = TRUE;
  174. #ifndef XP_WIN
  175.     // NOTE:  need to verify this change on XP_WIN and remove the
  176.     //        ifndef... [ works on XP_UNIX & XP_MAC ]
  177.     //
  178.     chrome.type = MWContextDialog;
  179. #endif
  180.  
  181.     //
  182.     // LTNOTE: Ownership of the 'chrome' struct isn't documented in the interface.
  183.     //  The windows implementation doesn't appear to keep pointers to the struct.
  184.     //
  185.     MWContext *pNewContext = FE_MakeNewWindow(pContext, NULL, "view-source",
  186.                     &chrome );
  187.     pNewContext->edit_view_source_hack = TRUE;
  188.  
  189.     URL_s = NET_CreateURLStruct(XP_GetString(EDT_VIEW_SOURCE_WINDOW_TITLE), NET_DONT_RELOAD);  
  190.  
  191.     URL_s->content_type = XP_STRDUP(TEXT_PLAIN);
  192.  
  193.     m_pStream = NET_StreamBuilder(FO_PRESENT, URL_s, pNewContext);
  194.  
  195.     if(!m_pStream){
  196.         XP_ASSERT( FALSE );
  197.         m_status = EOS_FileError;
  198.     } 
  199.     m_status = EOS_NoError;
  200. }
  201.  
  202. //
  203. // constructor for children
  204. //
  205. CStreamOutNet::CStreamOutNet(void){
  206.     m_pStream = NULL;
  207.     m_status = EOS_NoError;
  208. }
  209.  
  210. //-----------------------------------------------------------------------------
  211. // GenNetStream
  212. //
  213. // This is what NetStream out should have been! A generalized net function.
  214. // 
  215. //-----------------------------------------------------------------------------
  216. CStreamOutAnyNet::CStreamOutAnyNet(MWContext* pContext, URL_Struct *URL_s, FO_Present_Types type ){
  217.     NET_StreamClass *stream;
  218.     //URL_s->content_type = XP_STRDUP(TEXT_PLAIN);
  219.  
  220.     stream = NET_StreamBuilder(type, URL_s, pContext);
  221.  
  222.     if(!stream){
  223.         XP_ASSERT( FALSE );
  224.     }
  225.     else {
  226.     SetStream(stream);
  227.     }
  228. }
  229.  
  230. CNetStreamToTapeFS::CNetStreamToTapeFS(MWContext* pContext, ITapeFileSystem *tapeFS ){
  231.     NET_StreamClass *stream = NULL;
  232.  
  233.     if(!stream){
  234.         XP_ASSERT( FALSE );
  235.     }
  236.     else {
  237.     SetStream(stream);
  238.     }
  239. }
  240.  
  241. //
  242. // Do't forget to free the stream as well...
  243. //
  244. CStreamOutNet::~CStreamOutNet(){
  245.     if (m_pStream == NULL) return;
  246.     (*m_pStream->complete)(m_pStream);
  247.     XP_FREE(m_pStream);
  248. }
  249.  
  250. void CStreamOutNet::SetStream(NET_StreamClass *stream){
  251.     m_pStream = stream;
  252. }
  253.  
  254.  
  255. void CStreamOutNet::Write( char *pBuffer, int32 iCount ){
  256.  
  257.     // Buffer the output.
  258.     // pBuffer may be a const string, even a ROM string.
  259.     // (e.g. string constants on a Mac with VM.)
  260.     // But networking does in-place transformations on the
  261.     // data to convert it into other character sets.
  262.     
  263.     const int32 kBufferSize = 128;
  264.     char buffer[kBufferSize];
  265.  
  266.     if (m_pStream == NULL) {
  267.     // if we're trying to write with a null stream, we have definately
  268.     // tripped over an error
  269.     m_status = EOS_FileError;
  270.         return;
  271.     }
  272.  
  273.     while ( iCount > 0 ) {
  274.         int32 iChunkSize = iCount;
  275.         if ( iChunkSize > kBufferSize ) {
  276.             iChunkSize = kBufferSize;
  277.         }
  278.         XP_MEMCPY(buffer, pBuffer, iChunkSize);
  279.  
  280.         int status = (*m_pStream->put_block)(m_pStream, buffer, iChunkSize );
  281.     
  282.         if(status < 0){
  283.         m_status = EOS_FileError;
  284.             (*m_pStream->abort)(m_pStream, status);
  285.         XP_FREE(m_pStream);
  286.         m_pStream = NULL;
  287.         break;
  288.         }
  289.         // status??
  290.  
  291.         iCount -= iChunkSize;
  292.     }
  293. }
  294.  
  295. //-----------------------------------------------------------------------------
  296. // Memory Streams
  297. //-----------------------------------------------------------------------------
  298.  
  299. #define MEMBUF_GROW 10
  300. #define MEMBUF_START 32
  301. //
  302. CStreamOutMemory::CStreamOutMemory(): m_bufferSize(MEMBUF_START),
  303.         m_bufferEnd(0), m_pBuffer(0) {
  304.     m_pBuffer = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC( m_bufferSize );
  305.     m_pBuffer[m_bufferEnd] = '\0';
  306. }
  307.   
  308. //
  309. // This implementation intenttionally does not destroy the buffer.  The buffer
  310. //  is kept and destroyed by the stream user.
  311. //   
  312. CStreamOutMemory::~CStreamOutMemory(){
  313. }
  314.  
  315. //
  316. //
  317. void CStreamOutMemory::Write( char *pSrc, int32 iCount ){
  318.     int32 neededSize = iCount + m_bufferEnd + 1; /* Extra byte for '\0' */
  319.  
  320.     //
  321.     // Grow the buffer if need be.
  322.     //
  323.     if( neededSize  > m_bufferSize ){
  324.         int32 iNewSize = (neededSize * 5 / 4) + MEMBUF_GROW;
  325.         XP_HUGE_CHAR_PTR pBuf = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC(iNewSize);
  326.         if( pBuf ){
  327.             XP_HUGE_MEMCPY(pBuf, m_pBuffer, m_bufferSize );
  328.             XP_HUGE_FREE(m_pBuffer);
  329.             m_pBuffer = pBuf;
  330.             m_bufferSize = iNewSize;
  331.         }
  332.         else {
  333.             // LTNOTE: throw an out of memory exception
  334.             XP_ASSERT(FALSE);
  335.             return;
  336.         }
  337.     }
  338.  
  339.     XP_HUGE_MEMCPY( &m_pBuffer[m_bufferEnd], pSrc, iCount );
  340.     m_bufferEnd += iCount;
  341.     m_pBuffer[m_bufferEnd] = '\0';
  342. }
  343.  
  344. // class CConvertCSIDStreamOut
  345.  
  346. CConvertCSIDStreamOut::CConvertCSIDStreamOut(int16 oldCSID, int16 newCSID, IStreamOut* pStream){
  347.     m_oldCSID = oldCSID;
  348.     m_newCSID = newCSID;
  349.     m_bNullConversion = oldCSID == newCSID;
  350.     m_pStream = pStream;
  351.     if ( ! m_bNullConversion ){
  352.         m_Converter = INTL_CreateCharCodeConverter();
  353.         if ( ! INTL_GetCharCodeConverter(oldCSID, newCSID, m_Converter) ){
  354.             INTL_DestroyCharCodeConverter(m_Converter);
  355.             m_bNullConversion = TRUE;
  356.         }
  357.     }
  358. }
  359.  
  360. CConvertCSIDStreamOut::~CConvertCSIDStreamOut(){
  361.     if ( ! m_bNullConversion ) {
  362.         INTL_DestroyCharCodeConverter(m_Converter);
  363.     }
  364.     delete m_pStream;
  365.     m_pStream = 0;
  366. }
  367.  
  368. int16 CConvertCSIDStreamOut::GetOldCSID() {
  369.     return m_oldCSID;
  370. }
  371.  
  372. int16 CConvertCSIDStreamOut::GetNewCSID() {
  373.     return m_newCSID;
  374. }
  375.  
  376. void CConvertCSIDStreamOut::Write( char* pBuffer, int32 iCount ){
  377.     if ( ! m_pStream ) {
  378.         return;
  379.     }
  380.     if ( m_bNullConversion ) {
  381.         m_pStream->Write(pBuffer, iCount);
  382.     }
  383.     else {
  384.         // INTL_CallCharaCodeConverter has a pecuilar calling convention.
  385.         // if the converion is a no-op, the argument is returned.
  386.         // if pToData hasn't changed it won't be null-terminated
  387.         // else it **MUST** be NULL-terminated so we can get the new length
  388.         
  389.         // The character code converter will trash the input string under
  390.         // some circumstances, as for example if a Mac is transcoding to
  391.         // ISO-Latin-1. Therefore we must copy the input stream.
  392.         char* pCopy = (char*) XP_ALLOC(iCount);
  393.         if ( pCopy == NULL) {
  394.             XP_ASSERT(FALSE);
  395.             return;
  396.             }
  397.         XP_MEMCPY(pCopy, pBuffer, iCount);
  398.         char* pToData = (char*) INTL_CallCharCodeConverter(m_Converter, (const unsigned char*) pCopy, iCount);
  399.         if ( pToData ) {
  400.             if ( pToData != pCopy )
  401.                  iCount = XP_STRLEN(pToData);
  402.             m_pStream->Write(pToData, iCount);
  403.             if ( pToData != pCopy ) {
  404.                 XP_FREE(pToData);
  405.             }
  406.         }
  407.         else {
  408.             // Some sort of error.
  409.             XP_ASSERT(FALSE);
  410.             m_pStream->Write(pCopy, iCount);
  411.         }
  412.         XP_FREE(pCopy);
  413.     }
  414. }
  415.  
  416. IStreamOut* CConvertCSIDStreamOut::ForgetStream(){
  417.     IStreamOut* result = m_pStream;
  418.     m_pStream = NULL;
  419.     return result;
  420. }
  421.  
  422. // class CStreamInMemory
  423.  
  424. void CStreamInMemory::Read( char *pBuffer, int32 iCount ){
  425.     XP_HUGE_MEMCPY( pBuffer, &m_pBuffer[m_iCurrentPos], iCount );
  426.     m_iCurrentPos += iCount;
  427. }
  428.  
  429. #endif // EDITOR
  430.