Files
core/ASCOfficeRtfFile/RtfReader.h

372 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "RtfLex.h"
#include "RtfProperty.h"
#include "RtfDocument.h"
#include "../Common/OfficeFileTemplate.h"
[ event_source(native), event_receiver(native)]
class RtfReader
{
public: __event void OnCompleteItem();
public: class ReaderState;
typedef boost::shared_ptr<ReaderState> ReaderStatePtr;
public: class ReaderState
{
public: int m_nUD; // êîëè÷åñòâî ñèìâîëîâ èãíîðèðóåìûõ çà þíèêîäîì
public: RtfCharProperty m_oCharProp;
public: RtfParagraphProperty m_oParagraphProp;
public: RtfRowProperty m_oRowProperty;
public: RtfCellProperty m_oCellProperty;
public: RtfOldList m_oCurOldList;
//public: RtfSectionProperty m_oSectionProp;
public: ReaderStatePtr psave;
ReaderState()
{
m_nUD = 1;
m_oCharProp.SetDefaultRtf();
m_oParagraphProp.SetDefaultRtf();
m_oRowProperty.SetDefaultRtf();
m_oCellProperty.SetDefaultRtf();
m_oCurOldList.SetDefault();
//m_oSectionProp.SetDefaultOOX();
}
};
//---------------------------------TextParser----------------------------------
public: ReaderStatePtr m_oState;
public: RtfSectionProperty m_oCurSectionProp;
public: RtfLex m_oLex;
private: RtfDocument& m_oDocument;
private: CString m_sFilename;
public: int m_nFootnote; //òîëêî äëÿ ñèìîâîëà chftn. îñíîâàíî íà òîì ÷òî âëîæåííûõ footnote áûòü íå ìîæåò
public: int m_nDefFont;
public: CString m_sTempFolder;
public: short m_shCancel;
public: RtfReader(RtfDocument& oDocument, CString sFilename );
public: ~RtfReader()
{
}
public: void PushState();
public: void PopState();
public: bool Load();
public: long GetProgress()
{
return (long)( g_cdMaxPercent * m_oLex.GetProgress());
}
public: void Stop()
{
m_oLex.CloseSource();
}
};
class RtfAbstractReader
{
private: RtfToken m_oTok;
private: bool m_bCanStartNewReader;
private: bool m_bStop;
private: int m_nSkipChars;
protected: int m_nCurGroups;
private: bool m_bSkip;
private: int m_nLeading;
public: bool m_bUseDoubleByte;
public: NFileWriter::CBufferedFileWriter* m_oFileWriter;
public: RtfAbstractReader()
{
m_bCanStartNewReader = false;
m_bStop = false;
m_bSkip = false;
m_nSkipChars = 0;
m_nCurGroups = 1;
m_bUseDoubleByte = true;
m_oFileWriter = NULL;
m_nLeading = PROP_DEF;
}
public: bool Parse(RtfDocument& oDocument, RtfReader& oReader )
{
NFileWriter::CBufferedFileWriter* poOldWriter = oReader.m_oLex.m_oFileWriter;
oReader.m_oLex.m_oFileWriter = m_oFileWriter;// „u„ƒ„|„y „~„u NULL, „„„€ „„„u„{„ƒ„„ „<>„y„Š„u„} „ƒ„„p„x„… „r „†„p„z„|
int res = 0;
m_oTok = oReader.m_oLex.NextCurToken();
if( m_oTok.Type == m_oTok.None )
m_oTok = oReader.m_oLex.NextToken();
//bool bSkip = false;
while (m_oTok.Type != RtfToken::Eof && false == m_bStop && c_shProgressCancel != oReader.m_shCancel)
{
switch (m_oTok.Type)
{
case RtfToken::GroupStart:
EndSHIFTJIS_CHARSET( oDocument, oReader );
PushState(oReader);
break;
case RtfToken::GroupEnd:
EndSHIFTJIS_CHARSET( oDocument, oReader );
PopState(oDocument, oReader);
break;
case RtfToken::Keyword:
EndSHIFTJIS_CHARSET( oDocument, oReader );
if( _T("u") == m_oTok.Key )
{
ExecuteText( oDocument, oReader, ExecuteTextInternal( oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars, m_bUseDoubleByte, &m_nLeading ) );
break;
}
else
{
if( true == m_bSkip )
{
if( false == ExecuteCommand( oDocument, oReader, (CStringW)m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter ) )
Skip( oDocument, oReader );
m_bSkip = false;
}
else
ExecuteCommand( oDocument, oReader, (CStringW)m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter );
}
if( true == m_bCanStartNewReader )
m_bCanStartNewReader = false;
break;
case RtfToken::Control:
if( m_oTok.Key == _T("42") )
m_bSkip = true;
if( m_oTok.Key == _T("39") )
ExecuteText( oDocument, oReader, ExecuteTextInternal( oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars, m_bUseDoubleByte, &m_nLeading ));
break;
case RtfToken::Text:
ExecuteText( oDocument, oReader, ExecuteTextInternal( oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars, m_bUseDoubleByte, &m_nLeading ));
break;
}
if( false == m_bStop )
m_oTok = oReader.m_oLex.NextToken();
}
oReader.m_oLex.m_oFileWriter = poOldWriter;
return true;
}
public: virtual void PushState(RtfReader& oReader)
{
oReader.PushState();
m_nCurGroups++;
m_bCanStartNewReader = true;
}
public: virtual void PopState(RtfDocument& oDocument, RtfReader& oReader)
{
if( m_nCurGroups > 0 )
m_nCurGroups--;
else
;//ATLASSERT(false);
if( m_nCurGroups == 0 )
{
m_bStop = true;
ExitReader( oDocument, oReader );
}
oReader.PopState();
if( m_nCurGroups == 0 )
ExitReader2( oDocument, oReader );
}
public: bool StartSubReader( RtfAbstractReader& poNewReader, RtfDocument& oDocument, RtfReader& oReader )
{
if( true == m_bCanStartNewReader )
{
m_bCanStartNewReader = false;
m_nCurGroups--;
//poNewReader.PushState( oReader );
poNewReader.m_bSkip = m_bSkip;
return poNewReader.Parse(oDocument, oReader);
}
return false;
}
public: void Skip( RtfDocument& oDocument, RtfReader& oReader )
{
int cGroup = 1;
while( cGroup >= 1 )
{
m_oTok = oReader.m_oLex.NextToken();
if(m_oTok.Type == RtfToken::GroupStart)
cGroup++;
else if(m_oTok.Type == RtfToken::GroupEnd)
cGroup--;
else if(m_oTok.Type == RtfToken::Eof)
break;
}
PopState( oDocument, oReader );
}
public: virtual bool ExecuteCommand( RtfDocument& oDocument, RtfReader& oReader, CString sKey, bool bHasPar, int nPar )
{
return true;
}
public: virtual void ExecuteText( RtfDocument& oDocument, RtfReader& oReader, CString oText )
{
}
public: virtual void ExitReader( RtfDocument& oDocument, RtfReader& oReade )
{
}
public: virtual void ExitReader2( RtfDocument& oDocument, RtfReader& oReader )
{
}
public: void EndSHIFTJIS_CHARSET( RtfDocument& oDocument, RtfReader& oReader )// 128 - SHIFTJIS_CHARSET; 932 - codepage
{
if( PROP_DEF != m_nLeading )
{
ExecuteText( oDocument, oReader, ExecuteTextInternal( oDocument, oReader, "39", true, m_nLeading, m_nSkipChars ) );
m_nLeading = PROP_DEF;
}
}
public: static CString ExecuteTextInternal( RtfDocument& oDocument, RtfReader& oReader, CStringA sKey, bool bHasPar, int nPar, int& nSkipChars, bool bUseDoubleByte = false, int* nLeading = NULL )
{
CString sResult;
if( _T("u") == sKey )
{
if( true == bHasPar )
sResult.AppendChar( nPar );
}
else
{
CStringA sCharString;
if( _T("39") == sKey )
{
if( true == bHasPar )
sCharString.AppendChar( nPar );
}
else
sCharString = sKey;
if( false == sCharString.IsEmpty() )
{
int nCodepage = -1;
//ïðèìåíÿåì ïàðàìåòðû codepage îò òåêóùåãî øðèôòà todo associated fonts.
RtfFont oFont;
if( true == oDocument.m_oFontTable.GetFont( oReader.m_oState->m_oCharProp.m_nFont, oFont ) )
{
if( PROP_DEF != oFont.m_nCharset )
nCodepage = RtfUtility::CharsetToCodepage( oFont.m_nCharset );
else if( PROP_DEF != oFont.m_nCodePage )
nCodepage = oFont.m_nCodePage;
}
//îò íàñòðîåê äîêóìåíòà
if( -1 == nCodepage && RtfDocumentProperty::cp_none != oDocument.m_oProperty.m_eCodePage )
{
switch ( oDocument.m_oProperty.m_eCodePage )
{
case RtfDocumentProperty::cp_ansi:
{
if( PROP_DEF != oDocument.m_oProperty.m_nAnsiCodePage )
nCodepage = oDocument.m_oProperty.m_nAnsiCodePage;
else
nCodepage = CP_ACP;
break;
}
case RtfDocumentProperty::cp_mac: nCodepage = CP_MACCP;break;
case RtfDocumentProperty::cp_pc: nCodepage = 437;break;
case RtfDocumentProperty::cp_pca: nCodepage = 850;break;
}
}
//åñëè íè÷åãî íåò ñòàâèì ANSI
if( -1 == nCodepage )
nCodepage = CP_ACP;
if( 932 == nCodepage && true == bUseDoubleByte )// 128 - SHIFTJIS_CHARSET; 932 - codepage
{
int nStartIndex = 0;
if( NULL != nLeading && PROP_DEF != *nLeading )
{
int nTralingChar = sCharString[0];
nStartIndex = 1;
CStringA sMultyChar;
sMultyChar.AppendChar( *nLeading );
sMultyChar.AppendChar( nTralingChar );
CString sTempRes;
if( true == Convert::MultybyteToUnicode( sMultyChar, sTempRes, nCodepage ) )
{
sResult.Append( sTempRes );
*nLeading = PROP_DEF;
}
else
{
CStringA sFirstChar;
sFirstChar.AppendChar( *nLeading );
sTempRes = _T("");
Convert::MultybyteToUnicode( sFirstChar, sTempRes, CP_ACP );
sResult.Append( sTempRes );
*nLeading = nTralingChar;
}
}
int nTargetLen = sCharString.GetLength();
if( nTargetLen > nStartIndex )
{
int nCurLeading = *nLeading;
for( int i = nStartIndex; i < nTargetLen; i++ )
{
if( PROP_DEF == nCurLeading )
nCurLeading = sCharString[ i ];
else
{
int nFirstChar = nCurLeading;
int nSecondChar = sCharString[ i ];
CStringA sMultyChar;
sMultyChar.AppendChar( nFirstChar );
sMultyChar.AppendChar( nSecondChar );
CString sTempRes;
if( true == Convert::MultybyteToUnicode( sMultyChar, sTempRes, nCodepage ) )
{
sResult.Append( sTempRes );
nCurLeading = PROP_DEF;
}
else
{
CStringA sFirstChar;
sFirstChar.AppendChar( nFirstChar );
sTempRes = _T("");
Convert::MultybyteToUnicode( sFirstChar, sTempRes, CP_ACP );
sResult.Append( sTempRes );
nCurLeading = nSecondChar;
}
}
}
*nLeading = nCurLeading;
}
}
else
{
int nLengthW ;
nLengthW = MultiByteToWideChar(nCodepage, 0, sCharString, -1, NULL, NULL);
MultiByteToWideChar(nCodepage, 0, sCharString, -1, sResult.GetBuffer( nLengthW ), nLengthW);
sResult.ReleaseBuffer();
//sResult = sKey;
}
}
}
//óäàëÿåì ñèìâîëû âñëåä çà þíèêîäîì
if( nSkipChars > 0 )
{
int nLength = sResult.GetLength();
if( nSkipChars >= nLength )
{
nSkipChars -= nLength;
sResult.Empty();
}
else
{
sResult = sResult.Right( nLength - nSkipChars );
nSkipChars = 0;
}
}
if( _T("u") == sKey )
{
//íàäî ïðàâèëüíî óñòàíîâèòü m_nSkipChars ïî çíà÷åíèþ \ucN
nSkipChars = oReader.m_oState->m_nUD;
}
return sResult;
}
};