⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtfread.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
 *	@doc INTERNAL
 *
 *	@module	RTFREAD.CPP - RichEdit RTF reader (w/o objects) |
 *
 *		This file contains the nonobject code of RichEdit RTF reader.
 *		See rtfread2.cpp for embedded-object code.
 *
 *	Authors:<nl>
 *		Original RichEdit 1.0 RTF converter: Anthony Francisco <nl>
 *		Conversion to C++ and RichEdit 2.0 w/o objects:  Murray Sargent
 *		Lots of enhancements/maintenance: Brad Olenick
 *
 *	@devnote
 *		All sz's in the RTF*.? files refer to a LPSTRs, not LPTSTRs, unless
 *		noted as a szW.
 *
 *	@todo
 *		1. Unrecognized RTF. Also some recognized won't round trip <nl>
 *		2. In font.c, add overstrike for CFE_DELETED and underscore for
 *			CFE_REVISED.  Would also be good to change color for CF.bRevAuthor
 *
 */
#include "_common.h"

#ifdef PWD_JUPITER
// GuyBark JupiterJ 49674: Must be able to select and remove equation field text.
#include "_select.h"
#endif // PWD_JUPITER

#include "_rtfread.h"
#include "_util.h"


ASSERTDATA

/*
 *		Global Variables
 */

#define	PFM_ALLRTF		(PFM_ALL2 | PFM_COLLAPSED | PFM_OUTLINELEVEL | PFM_BOX)
#pragma BEGIN_CODESPACE_DATA

// for object attachment placeholder list
#define cobPosInitial 8
#define cobPosChunk 8

#pragma END_CODESPACE_DATA

#ifdef PWD_JUPITER
// GuyBark: Strip font decorations during stream in, and add them again on stream out.
// PWord on the device doesn't need the decorations as the font can display text from
// multiple character sets. But we must stream out the decorated fonts as Word95 uses 
// them in determining the character set of the font.
FontDecorations const fontDec[] = { {" Baltic",  BALTIC_CHARSET},
                                    {" CE",      EASTEUROPE_CHARSET},
                                    {" Cyr",     RUSSIAN_CHARSET},
                                    {" Greek",   GREEK_CHARSET},
                                    {" Tur",     TURKISH_CHARSET},
                                    {" Turkish", TURKISH_CHARSET},
                                    {NULL, 0}    }; // <- This indicates the end of the array.                    
#endif // PWD_JUPITER

#if CFE_SMALLCAPS != 0x40 || CFE_ALLCAPS != 0x80 || CFE_HIDDEN != 0x100 \
 || CFE_OUTLINE != 0x200  || CFE_SHADOW != 0x400
#error "Need to change RTF char effect conversion routines
#endif

// for RTF tag coverage testing
#if defined(DEBUG)
#define TESTPARSERCOVERAGE() \
	{ \
		if(GetProfileIntA("RICHEDIT DEBUG", "RTFCOVERAGE", 0)) \
		{ \
			TestParserCoverage(); \
		} \
	}
#define PARSERCOVERAGE_CASE() \
	{ \
		if(_fTestingParserCoverage) \
		{ \
			return ecNoError; \
		} \
	}
#define PARSERCOVERAGE_DEFAULT() \
	{ \
		if(_fTestingParserCoverage) \
		{ \
			return ecStackOverflow; /* some bogus error */ \
		} \
	}
#else
#define TESTPARSERCOVERAGE()
#define PARSERCOVERAGE_CASE()
#define PARSERCOVERAGE_DEFAULT()
#endif


// FF's should not have paragraph number prepended to them
inline BOOL CharGetsNumbering(WORD ch) { return ch != FF; }

// V-GUYB: PWord Converter requires loss notification.
#ifdef REPORT_LOSSAGE
typedef struct
{
    IStream *pstm;
    BOOL     bFirstCallback;
    LPVOID  *ppwdPWData;
    BOOL     bLoss;
} LOST_COOKIE;
#endif


//======================== OLESTREAM functions =======================================

DWORD CALLBACK RTFGetFromStream (
	RTFREADOLESTREAM *OLEStream,	//@parm OleStream
	void FAR *		  pvBuffer,		//@parm Buffer to read 
	DWORD			  cb)			//@parm Bytes to read
{
	return OLEStream->Reader->ReadData ((BYTE *)pvBuffer, cb);
}

DWORD CALLBACK RTFGetBinaryDataFromStream (
	RTFREADOLESTREAM *OLEStream,	//@parm OleStream
	void FAR *		  pvBuffer,		//@parm Buffer to read 
	DWORD			  cb)			//@parm Bytes to read
{
	return OLEStream->Reader->ReadBinaryData ((BYTE *)pvBuffer, cb);
}


//============================ STATE Structure =================================
/*
 *	STATE::AddPF(PF, lDefTab, lDocType)
 *
 *	@mfunc
 *		If the PF contains new info, this info is applied to the PF for the
 *		state.  If this state was sharing a PF with a previous state, a new
 *		PF is created for the state, and the new info is applied to it.
 *
 *	@rdesc
 *		TRUE unless needed new PF and couldn't allocate it 
 */
BOOL STATE::AddPF(
	const CParaFormat &PF,	//@parm Current RTFRead _PF
	LONG lDefTab,			//@parm	Default tab to use if no previous state
	LONG lDocType)			//@parm	Default doc type to use if no prev state
{
	// Create a new PF if:  
	//	1.  The state doesn't have one yet
	//	2.  The state has one, but it is shared by the previous state and
	//		there are PF deltas to apply to the state's PF
	if(!pPF || (PF.dwMask && pstatePrev && pPF == pstatePrev->pPF))
	{
		Assert(!pstatePrev || pPF);

		pPF = new CParaFormat;
		if(!pPF)
			return FALSE;

		// Give the new PF some initial values - either from the previous
		// state's PF or by CParaFormat initialization
		if(pstatePrev)
		{
			// Copy the PF from the previous state
			*pPF = *pstatePrev->pPF;
		}
		else
		{
			// We've just created a new PF for the state - there is no
			// previous state to copy from.  Use default values.
			pPF->InitDefault(lDefTab, lDocType == DT_RTLDOC ? PFE_RTLPARA : 0);
			pPF->dwMask	= PFM_ALLRTF;
		}
	}

	// Apply the new PF deltas to the state's PF
	if(PF.dwMask)
		pPF->Apply(&PF);

	return TRUE;
}

/*
 *	STATE::DeletePF()
 *
 *	@mfunc
 *		If the state's PF is not shared by the previous state, the PF for this
 *		state is deleted.
 *
 */
void STATE::DeletePF()
{
	if(pPF && (!pstatePrev || (pPF != pstatePrev->pPF)))
	{
		delete pPF;
	}
	pPF = NULL;
}

/*
 *	STATE::SetCodePage(CodePage, ansicpg)
 *
 *	@mfunc
 *		If N of \ansicpgN is CP_UTF8, use it for all conversions (yes, even
 *		for SYMBOL_CHARSET). Else use CodePage.
 */
void STATE::SetCodePage(
	LONG CodePage)
{
	if(nCodePage != CP_UTF8)
		nCodePage = CodePage;
}

//============================ CRTFRead Class ==================================
/*
 *	CRTFRead::CRTFRead()
 *
 *	@mfunc
 *		Constructor for RTF reader
 */
CRTFRead::CRTFRead (
	CTxtRange *		prg,			// @parm CTxtRange to read into
	EDITSTREAM *	pes,			// @parm Edit stream to read from
	DWORD			dwFlags			// @parm Read flags
)
	: CRTFConverter(prg, pes, dwFlags, TRUE)
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::CRTFRead");

	Assert(prg->GetCch() == 0);

	//TODO(BradO):  We should examine the member data in the constructor
	//	and determine which data we want initialized on construction and
	//	which at the beginning of every read (in CRTFRead::ReadRtf()).

#ifdef BIDI
	_cpThisDirection = _cpThisJoiner = prg->GetCp();
#endif
	_sDefaultFont	= -1;					// No \deff n control word yet
	_sDefaultLanguage = INVALID_LANGUAGE;
	_sDefaultLanguageFE = INVALID_LANGUAGE;
	_sDefaultTabWidth = 0;
	_CF.dwMask		= 0;					// No char format changes yet
	_FieldCF.dwMask = 0;
	_nFieldCodePage = 0;
	_ptfField 		= NULL;
	_fRestoreFieldFormat = FALSE;
	_dwFlagsUnion	= 0;					// No flags yet
	_pes->dwError	= 0;					// No error yet
	_cchUsedNumText	= 0;					// No numbering text yet
	_cCell			= 0;					// No table cells yet
	_iCell			= 0;
	_pstateStackTop	= NULL;
	_pstateLast		= NULL;
	_szText			=
	_pchRTFBuffer	=						// No input buffer yet
	_pchRTFCurrent	=
	_szSymbolFieldResult  = 
	_pchRTFEnd		= NULL;
	_prtfObject		= NULL;
	_pcpObPos		= NULL;
	_bTabLeader		= 0;
	_bTabType		= 0;
	_pobj			= 0;
	_wAlignment		= PFA_LEFT;

	_szHyperlinkFldinst	= NULL;
	_szHyperlinkFldrslt	= NULL;

	// Does story size exceed the maximum text size?
	_cchMax = _ped->TxGetMaxLength() - _ped->GetAdjustedTextLength();
	_cchMax = max((LONG)_cchMax, 0);

	ZeroMemory(_rgStyles, sizeof(_rgStyles)); // No style levels yet

	_bBiDiCharSet = (g_wLang == sLanguageHebrew) ? HEBREW_CHARSET : ARABIC_CHARSET;

#ifdef PWD_JUPITER
	// GuyBark Jupiter 31960: We haven't found any collappsed text yet.
	_fFoundCollapsedText = FALSE;
#endif // PWD_JUPITER
	
	// init OleStream
	RTFReadOLEStream.Reader = this;
    
    if (NULL == RTFReadOLEStream.lpstbl)
    {
        //something very bizarre happened during init of this object
        TRACEWARNSZ("RTFReadOLEStream.lpstbl is NOT initialized");
        Assert(RTFReadOLEStream.lpstbl);  //bad news to do this in the constructor - debug this
    }
    else
    {
    	RTFReadOLEStream.lpstbl->Get = (DWORD (CALLBACK* )(LPOLESTREAM, void FAR*, DWORD))
    							   RTFGetFromStream;
    	RTFReadOLEStream.lpstbl->Put = NULL;
    }	

#ifdef DEBUG

// TODO: Implement RTF tag logging for the Mac
#if !defined(MACPORT)
	_fTestingParserCoverage = FALSE;
	_prtflg = NULL;

	if(GetProfileIntA("RICHEDIT DEBUG", "RTFLOG", 0))
	{
		_prtflg = new CRTFLog;
	
		if(_prtflg)
		{
			if(!_prtflg->FInit())
			{
				delete _prtflg;
				_prtflg = NULL;
			}
		}

		AssertSz(_prtflg, "CRTFRead::CRTFRead:  Error creating RTF log");
	}
#endif
#endif // DEBUG
}

/*
 *	CRTFRead::HandleStartGroup()
 *	
 *	@mfunc
 *		Handle start of new group. Alloc and push new state onto state
 *		stack
 *
 *	@rdesc
 *		EC					The error code
 */
EC CRTFRead::HandleStartGroup()
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleStartGroup");

	STATE *	pstate	   = _pstateStackTop;
	STATE *	pstateNext = NULL;

	if (pstate)									// At least one STATE already
	{											//  allocated
		Apply_CF();								// Apply any collected char
		// Note (igorzv) we don't Apply_PF() here so as not to change para 
		// properties before we run into \par i.e. not to use paragraph 
		// properties if we copy only one word from paragraph. We can use an
		// assertion here that neither we nor Word use end of group for
		// restoring paragraph properties. So everything will be OK with stack
		pstate->iCF = _prg->Get_iCF();			// Save current CF
		pstate = pstate->pstateNext;			// Use previously allocated
		if(pstate)								//  STATE frame if it exists
			pstateNext = pstate->pstateNext;	// It does; save its forward
	}											//  link for restoration below

	if(!pstate)									// No new STATE yet: alloc one
	{
		pstate = new STATE(_dwFlags & SFF_UTF8 ? CP_UTF8 : _nCodePage);
		if (!pstate)							// Couldn't alloc new STATE
			goto memerror;

		_pstateLast = pstate;					// Update ptr to last STATE
	}											//  alloc'd

	STATE *pstateGetsPF;

	// Apply the accumulated PF delta's to the old current state or, if there
	//	is no current state, to the newly created state.
	pstateGetsPF = _pstateStackTop ? _pstateStackTop : pstate;
	if(!pstateGetsPF->AddPF(_PF, _sDefaultTabWidth, _bDocType))
	{
		goto memerror;
	}
	_PF.dwMask = 0;  // _PF contains delta's from *_pstateStackTop->pPF

	if(_pstateStackTop)							// There's a previous STATE
	{
		*pstate = *_pstateStackTop;				// Copy current state info
		// N.B.  This will cause the current and previous state to share
		// 	the same PF.  PF delta's are accumulated in _PF.  A new PF
		// 	is created for _pstateStackTop when the _PF deltas are applied.

		_pstateStackTop->pstateNext = pstate;
#ifdef BIDI
		pstate->fModDirection = FALSE;
		pstate->fModJoiner = FALSE;
#endif
	}

	pstate->pstatePrev = _pstateStackTop;		// Link STATEs both ways
	pstate->pstateNext = pstateNext;
	_pstateStackTop = pstate;					// Push stack

done:
	TRACEERRSZSC("HandleStartGroup()", -_ecParseError);
	return _ecParseError;

memerror:
	_ped->GetCallMgr()->SetOutOfMemory();
	_ecParseError = ecStackOverflow;
	goto done;
}

/*
 *	CRTFRead::HandleEndGroup()
 *
 *	@mfunc
 *		Handle end of new group
 *
 *	@rdesc
 *		EC					The error code
 */
EC CRTFRead::HandleEndGroup()
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleEndGroup");

	STATE *	pstate = _pstateStackTop;
	STATE *	pstatePrev;

	if (!pstate)								// No stack to pop
	{
		_ecParseError = ecStackUnderflow;
		goto done;
	}

	_pstateStackTop =							// Pop stack
	pstatePrev		= pstate->pstatePrev;

	if(!pstatePrev)
	{
		Assert(pstate->pPF);

		// We're ending the parse.  Copy the final PF into _PF so that 
		// 	subsequent calls to Apply_PF will have a PF to apply.
		_PF = *pstate->pPF;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -