/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// #pragma unmanaged #include "CharBuffer.h" #include "StringStream.h" #include "CharsStorage.h" #include "guard.h" #include "RCPtrDef.h" #include #include template RCPtr; StringStream::StringStream( LPSTREAM lpStream ) : _charsStorage( TypeFactory::CreateCharsStorage() ) { _lpStream = lpStream; _buff_size = BUFF_SIZE; //Debug::WriteLine( "StringStream::StringStream" ); } bool StringStream::IsHtml( const char* buf, unsigned int len ) { // We look for the words "\fromhtml" somewhere in the file. // If the rtf encodes text rather than html, then instead // it will only find "\fromtext". for (const char *c = buf; c < buf + len; c++ ) { if (strncmp(c,"\\from",5)==0) { return strncmp(c,"\\fromhtml",9)==0; } } return false; } bool StringStream::IsPlain( const char* buf, unsigned int len ) { // We look for the words "\fromhtml" somewhere in the file. // If the rtf encodes text rather than html, then instead // it will only find "\fromtext". for (const char *c = buf; c < buf + len; c++ ) { if (strncmp(c,"\\from",5)==0) { return strncmp(c,"\\fromtext",9)==0; } } return false; } StringStream::Format StringStream::GetStreamFormat() { const char* buf = _charsStorage->GetBuffer( 0 ); if ( IsHtml( buf, BUFF_SIZE ) ) { return Format::HTML; } else if ( IsPlain( buf, BUFF_SIZE ) ) { return Format::PlainText; } return Format::RTF; } StringStreamSPtr StringStream::GetWrapCompressedRTFStream( int flags ) { LPSTREAM lpStreamRTFSrc = NULL; // Get IStream pointer for uncompressed RTF, from which we will read HRESULT hr = WrapCompressedRTFStream( _lpStream, flags, &lpStreamRTFSrc ); if ( hr == S_OK ) { return TypeFactory::CreateStringStream( lpStreamRTFSrc ); } return StringStreamSPtr( NULL ); } void StringStream::ReadToEnd() { while ( Read() ); } bool StringStream::Read( int sizeToRead ) { _buff_size = sizeToRead; return Read(); } bool StringStream::Read() { ULONG red; CharBufferSPtr buf = TypeFactory::CreateCharBuffer( _buff_size ); HRESULT hr = _lpStream->Read( buf->Get(), _buff_size, &red ); if ( hr == S_OK && red > 0 ) { buf->SetLength( red ); _charsStorage->Add( buf ); if ( red < BUFF_SIZE ) { return false; } _buff_size += BUFF_SIZE; return true; } return false; } bool StringStream::Write( const void* pv, int cb ) { ULONG written = 0; HRESULT hr = _lpStream->Write( pv, cb, &written ); if ( hr == S_OK ) { return false; } return false; } void StringStream::Commit() { HRESULT hr = _lpStream->Commit( STGC_OVERWRITE ); hr = hr; } CharBufferSPtr StringStream::GetBuffer( ) { return _charsStorage->Concatenate(); } int StringStream::GetRealCodePage( ) { return Guard::GetRealCodePage( _charsStorage ); } CharBufferSPtr StringStream::DecodeRTF2HTML() { CharBufferSPtr charsBuffer = _charsStorage->Concatenate(); unsigned int length = charsBuffer->Length(); DecodeRTF2HTMLInternal( (char*)charsBuffer->GetRawChars(), &length ); charsBuffer->SetLength( length ); return charsBuffer; } bool Html2Rtf1( const std::string& sHtml, int iCodePage, std::string& sRtf ) { int i, p, j; std::string strTag, strExtra; char ch; const char *pCmp; bool bInTag=false; sRtf=sHtml; if(iCodePage==CP_UTF8) iCodePage=0; for(i=(int)sRtf.length()-1; i>=0; --i) { switch(ch=sRtf[i]) { case '>': { bInTag=true; break; } case '<': { bInTag=false; break; } case '\t': { sRtf.erase(i, 1); sRtf.insert(i, "\\tab"); break; } case '{': case '}': case '\\': { sRtf.insert(i, "\\"); break; } case '\r': { if( i<(int)sRtf.length()-1 && sRtf[i+1]=='\n' ) sRtf.insert(i, " "); break; } } if( ch & 0x80 ) { //sprintf(sz, "\\'%02X", ch); //sRtf.erase(i, 1); //sRtf.insert(i, sz ); } } for(i=(int)sRtf.length()-2; i>=0; --i) { if(sRtf[i]=='<') { p=0; for(j=i+1; j<(int)sRtf.length(); ++j) { if(sRtf[j]=='>') { p=j; break; } } if(!p) { sRtf=sHtml; return false; } strTag=std::string(sRtf.begin()+i, sRtf.begin()+p+1); pCmp=strTag.c_str()+1; if( !strncmp(pCmp, "P>", 2) || !strncmp(pCmp, "P ", 2) || !strncmp(pCmp, "BR>", 3) || !strncmp(pCmp, "BR ", 3) ) strExtra="\\par "; else strExtra=""; if(strTag[1]=='/') strTag="{\\*\\htmltag8 "+strExtra+strTag+"}"; else strTag="{\\*\\htmltag0 "+strExtra+strTag+"}"; sRtf.erase(i, p-i+1); sRtf.insert(i, strTag.c_str()); } } sRtf = std::string( "{\\rtf1\\ansi\\ansicpg" ) + "1" + "\\fromhtml1\\deff0{\\fonttbl\r\n" + "{\\f0\\fswiss\\fcharset" + "1" + " Arial;}\r\n" + "{\\f1\\fmodern\\fcharset" + "1" + " Courier New;}\r\n" + "{\\f2\\fnil\\fcharset" + "1" + " Symbol;}\r\n" + "{\\f3\\fmodern\\fcharset" + "1" + " Courier New;}}\r\n" + "\\uc1\\pard\\plain\\deftab360 \\f0\\fs24\r\n" + sRtf + "}"; return true; } CharBufferSPtr StringStream::Html2Rtf( char* buffer ) { std::string strHTML( buffer ); std::string strRTF; Html2Rtf1( strHTML, 1251, strRTF ); CharBufferSPtr charBuffer = TypeFactory::CreateCharBuffer( (int)strRTF.length() + 1 ); charBuffer->strcopy( strRTF.c_str() ); return charBuffer; } void StringStream::DecodeRTF2HTMLInternal( char *buf, unsigned int *len ) { // c -- pointer to where we're reading from // d -- pointer to where we're writing to. Invariant: d='0' && *c<='9') {tag=tag*10+*c-'0'; c++;} if (*c==' ') c++; if (tag==ignore_tag) {while (c='0' && *c<='9') {tag=tag*10+*c-'0'; c++;} if (*c==' ') c++; ignore_tag=tag; } else if (strncmp(c,"\\par",4)==0) {strcpy(d,"\r\n"); d+=2; c+=4; if (*c==' ') c++;} else if (strncmp(c,"\\tab",4)==0) {strcpy(d," "); d+=3; c+=4; if (*c==' ') c++;} else if (strncmp(c,"\\line",5)==0) {strcpy(d,"\r\n"); d+=2; c+=5; if (*c==' ') c++;} else if (strncmp(c,"\\li",3)==0) { c+=3; while (*c>='0' && *c<='9') c++; if (*c==' ') c++; } else if (strncmp(c,"\\fi-",4)==0) { c+=4; while (*c>='0' && *c<='9') c++; if (*c==' ') c++; } else if (strncmp(c,"\\'",2)==0) { unsigned int hi=c[2], lo=c[3]; if (hi>='0' && hi<='9') hi-='0'; else if (hi>='A' && hi<='Z') hi-='A'-10; else if (hi>='a' && hi<='z') hi-='a'-10; if (lo>='0' && lo<='9') lo-='0'; else if (lo>='A' && lo<='Z') lo-='A'-10; else if (lo>='a' && lo<='z') lo-='a'-10; *((unsigned char*)d) = (unsigned char)(hi*16+lo); c+=4; d++; } else if (strncmp(c,"\\pntext",7)==0) {c+=7; while (c