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

📄 rtfread.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 *	@rdesc
 *		Standard color index corresponding to the color associated with _iParam
 */
LONG CRTFRead::GetStandardColorIndex()
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::GetColorIndex");

	if((DWORD)_iParam >= _colors.Count())		// Illegal _iParam:
		return 0;								//  use autocolor

	COLORREF Color = *_colors.Elem(_iParam);
	LONG	 i;

	for(i = 0; i < 16; i++)
	{
		if(Color == g_Colors[i])
			return i + 1;
	}
	return 0;									// Not there: use autocolor
}

/*
 *	CRTFRead::HandleChar(ch)
 *
 *	@mfunc
 *		Handle single Unicode character <p ch>
 *
 *	@rdesc
 *		EC			The error code
 */
EC CRTFRead::HandleChar(
	WORD ch)			// @parm char token to be handled
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleChar");

	if(!_ped->TxGetMultiLine() && IsASCIIEOP(ch))
	{
		_ecParseError = ecTruncateAtCRLF;
	}
 	else
	{
		Assert(ch <= 0x7F || ch > 0xFF || FTokIsSymbol(ch));
		_CF.bInternalMask |= CFMI_RUNISDBCS;
		_CF.bInternalEffects &= ~CFEI_RUNISDBCS;
		AddText(&ch, 1, CharGetsNumbering(ch));
	}

	TRACEERRSZSC("HandleChar()", - _ecParseError);

	return _ecParseError;
}

/*
 *	CRTFRead::HandleEndOfPara()
 *
 *	@mfunc
 *		Insert EOP and apply current paraformat
 *
 *	@rdesc
 *		EC	the error code
 */
EC CRTFRead::HandleEndOfPara()
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleEndOfPara");

	if(_pstateStackTop->fInTable)			// Our simple table model can't
	{										//  have numbering
		_PF.wNumbering = 0;	
		_PF.dwMask |= PFM_NUMBERING;
	}

	if(!_ped->TxGetMultiLine())				// No EOPs permitted in single-
	{										//  line controls
		Apply_PF();							// Apply any paragraph formatting
		_ecParseError = ecTruncateAtCRLF;	// Cause RTF reader to finish up
		return ecTruncateAtCRLF;
	}

	Apply_CF();								// Apply _CF and save iCF, since
	LONG iFormat = _prg->Get_iCF();			//  it may get changed to iCF
											//  that follows EOP
	EC ec  = _ped->Get10Mode()				// If RichEdit 1.0 compatibility
			? HandleText((BYTE *)szaCRLF, ALL_ASCII)	//  mode, use CRLF; else CR or VT
			: HandleChar((unsigned)(_token == tokenLineBreak ? VT : CR));

	if(ec == ecNoError)
	{
		Apply_PF();
		_cpThisPara = _prg->GetCp();		// New para starts after CRLF
	}
	_prg->Set_iCF(iFormat);					// Restore iFormat if changed
	ReleaseFormats(iFormat, -1);			// Release iFormat (AddRef'd by
											//  Get_iCF())
	return _ecParseError;
}

/*
 *	CRTFRead::HandleText(szText, iAllASCII)
 *
 *	@mfunc
 *		Handle the string of Unicode characters <p szText>
 *
 *	@rdesc
 *		EC			The error code
 */
EC CRTFRead::HandleText(
	BYTE * szText,			// @parm string to be handled
	int iAllASCII)			// @parm enum indicating if string is all ASCII chars
							// 	(<= 0x7F)
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleText");

	LONG	cch;
       LONG     cch_szUnicode = cachTextMax;
	TCHAR *	pch;
	STATE *	pstate = _pstateStackTop;

	// TODO: what if szText cuts off in middle of DBCS?

	if(!*szText)
	{
		goto CleanUp;
	}

	if(iAllASCII == ALL_ASCII || pstate->nCodePage == SYMBOL_CODEPAGE)
	{
		// Don't use MBTWC() in cases where text contains
		// only ASCII chars (which don't require conversion)
		for(cch = 0, pch = _szUnicode; *szText && (cch < cch_szUnicode); cch++)
		{
			Assert(*szText <= 0x7F || _CF.bCharSet == SYMBOL_CHARSET);
			*pch++ = (TCHAR)*szText++;
		}
              *pch = 0;

		_CF.bInternalMask |= CFMI_RUNISDBCS;
		_CF.bInternalEffects &= ~CFEI_RUNISDBCS;

		// fall through to AddText at end of HandleText()
	}
	else
	{
		TEXTFONT *ptf;
		BOOL fMissingCodePage;

		ptf = pstate->ptf;

		// Run of text contains bytes > 0x7F.
		// Ensure that we have the correct codepage with which to interpret 
		// these (possibly DBCS) bytes.

		if(ptf->sCodePage == INVALID_CODEPAGE && !ptf->fCpgFromSystem)
		{
			// Determine codepage from the font name
			if(CpgInfoFromFaceName(pstate->ptf))
			{
				SelectCurrentFont(pstate->ptf->sHandle);
				Assert(ptf->sCodePage != INVALID_CODEPAGE);
			}
			else
			{
				// Here, we were not able to determine a cpg/charset value
				// from the font name.  We have two choices: (1) either choose
				// some fallback value like 1252/0 or (2) rely on the 
				// document-level cpg value.
				//
				// I think choosing the document-level cpg value will give
				// us the best results.  In FE cases, it will likely err
				// on the side of tagging too many runs as CFEI_RUNISDBCS, but
				// that is safer than using a western cpg and potentially missing
				// runs which should be CFEI_RUNISDBCS.
			}

			Assert(ptf->fCpgFromSystem);
		}

		Assert(!(_dwFlags & SFF_UTF8) || pstate->nCodePage == CP_UTF8);

#ifdef PWD_JUPITER
		// GuyBark JupiterJ:
		// Always treat a MBCS string which is invalid for the code page
		// as something that should generate an error. Otherwise we lose
		// the text. At least when the error is trapped we take action 
		// to try to compensate.
		cch = MBTWC(pstate->nCodePage, MB_ERR_INVALID_CHARS,
#else
		cch = MBTWC(pstate->nCodePage, 0,
#endif // PWD_JUPITER
					(char *)szText,	-1, 
					_szUnicode, cachTextMax, &fMissingCodePage);

		AssertSz(cch > 0, "CRTFRead::HandleText():  MBTWC implementation changed"
							" such that it returned a value <= 0");

        if(!fMissingCodePage || pstate->nCodePage == INVALID_CODEPAGE)
		{
			// Use result of MBTWC if:
			//	(1) we converted some chars and did the conversion with the codepage
			//		provided.
			//	(2) we converted some chars but couldn't use the codepage provided,
			//		but the codepage is invalid.  Since the codepage is invalid,
			//		we can't do anything more sophisticated with the text before
			//		adding to the backing store

			cch--;  // don't want char count to including terminating NULL

			_CF.bInternalMask |= CFMI_RUNISDBCS;
			if(fMissingCodePage)
			{
				_CF.bInternalEffects |= CFEI_RUNISDBCS;
			}
			else
			{
				_CF.bInternalEffects &= ~CFEI_RUNISDBCS;
			}

			// fall through to AddText at end of HandleText()
		}
		else
		{
			// Conversion to Unicode failed.  Break up the string of
			// text into runs of ASCII and non-ASCII characters.

			// FUTURE(BradO):  Here, I am saving dwMask and restoring it before
			//		each AddText.  I'm not sure this is neccessary.  When I have
			//		the time, I should revisit this save/restoring and 
			//		determine that it is indeed neccessary.

			BOOL fPrevIsASCII = ((*szText <= 0x7F) ? TRUE : FALSE);
			BOOL fCurrentIsASCII = FALSE;
			BOOL fLastChunk = FALSE;
			DWORD dwMaskSave = _CF.dwMask;
#ifdef DEBUG
			CCharFormat cfSave = _CF;
#endif

			pch = _szUnicode;
			cch = 0;

			// (!*szText && *pch) is the case where we do the AddText for the
			//	last chunk of text
			while((*szText || fLastChunk) && (cch<cch_szUnicode))
			{
				// fCurrentIsASCII assumes that no byte <= 0x7F is a 
				//	DBCS lead-byte
				if(fLastChunk ||
					(fPrevIsASCII != (fCurrentIsASCII = ((*szText <= 0x7F) ? 
															TRUE : FALSE))))
				{
					_CF.dwMask = dwMaskSave;
#ifdef DEBUG
					_CF = cfSave;
#endif

					*pch = 0;

					_CF.bInternalMask |= CFMI_RUNISDBCS;
					if( fPrevIsASCII )
					{
						_CF.bInternalEffects &= ~CFEI_RUNISDBCS;
					}
					else
					{
						_CF.bInternalEffects |= CFEI_RUNISDBCS;
					}

					Assert(cch);
					pch = _szUnicode;

					AddText(pch, cch, TRUE);

					cch = 0;
					fPrevIsASCII = fCurrentIsASCII;

					// My assumption in saving _CF.dwMask is that the remainder
					// of the _CF is unchanged by AddText.  This assert verifies
					// this assumption.
					AssertSz(!memcmp(&cfSave.dwEffects, &_CF.dwEffects,
										((BYTE *)((CHARFORMAT2 *)&_CF + 1)) - 
											(BYTE *)&_CF.dwEffects),
						"CRTFRead::HandleText():  AddText has been changed "
						"and now alters the _CF structure.");

					if(fLastChunk)
					{
						// Last chunk of text was AddText'd
						break;
					}
				}

				// Not the last chunck of text.
				Assert(*szText);

				// Advance szText pointer
				if(!fCurrentIsASCII && *(szText + 1) && 
						IsLeadByte(*szText, pstate->nCodePage))
				{
					// current byte is a lead-byte of a DBCS character
					*pch++ = *szText++;
					++cch;
				}
                            if (cch<cch_szUnicode)
                            {
                                *pch++ = *szText++;
				    ++cch;
                            }
				// Must do an AddText for the last chunk of text.
				if(!*szText)
				{
					fLastChunk = TRUE;
				}
			}
			goto CleanUp;
		}
	}

	if(cch > 0)
	{
		pch = _szUnicode;
		AddText(pch, cch, TRUE);
	}

CleanUp:
	TRACEERRSZSC("HandleText()", - _ecParseError);
	return _ecParseError;
}

/*
 *	CRTFRead::AddText(pch, cch, fNumber)
 *	
 *	@mfunc
 *		Add <p cch> chars of the string <p pch> to the range _prg
 *
 *	@rdesc
 *		error code placed in _ecParseError
 */
EC CRTFRead::AddText(
	TCHAR *	pch,		// @parm text to add
	LONG	cch,		// @parm count of chars to add
	BOOL	fNumber)	// @parm indicates whether or not to prepend numbering
{
	TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::AddText");

	LONG			cchAdded;
	LONG			cchT;
	STATE *	const	pstate = _pstateStackTop;
	TCHAR *			szDst;
	DWORD			cchLen = _ped->GetAdjustedTextLength();

	// AROO: No saving state before this point (other than pstate)
	// AROO: This would mess up recursion below

	AssertSz(pstate, "CRTFRead::AddText: no state");

	if((DWORD)cch > _cchMax)
	{
		cch = (LONG)_cchMax;
		_ecParseError = ecTextMax;
	}

	if (!cch)
		return _ecParseError;

	// FUTURE(BradO):  This strategy for \pntext is prone to bugs, I believe.
	// The recursive call to AddText to add the \pntext will trounce the 
	// accumulated _CF diffs associated with the text for which AddText is
	// called.  I believe we should save and restore _CF before and after
	// the recursive call to AddText below.  Also, it isn't sufficient to
	// accumulate bits of \pntext as below, since each bit might be formatted
	// with different _CF properties.  Instead, we should accumulate a mini-doc
	// complete with multiple text, char and para runs (or some stripped down
	// version of this strategy).

	if (pstate->sDest == destParaNumText)
	{
		szDst = _szNumText + _cchUsedNumText;
		cch = min(cch, cchMaxNumText - 1 - _cchUsedNumText);
		if (cch > 0)
		{
			MoveMemory((BYTE *)szDst, (BYTE *)pch, cch*2);
			szDst[cch] = TEXT('\0');		// HandleText() takes sz
			_cchUsedNumText += cch;
		}
		return ecNoError;
	}

	if(_cchUsedNumText && fNumber)			// Some \pntext available
	{
		// Bug 3496 - The fNumber flag is an ugly hack to work around RTF 
		//	commonly written by Word.  Often, to separate a numbered list
		// 	by page breaks, Word will write:
		//		<NUMBERING INFO> \page <PARAGRAPH TEXT>
		// 	The paragraph numbering should precede the paragraph text rather
		//	than the page break.  The fNumber flag is set to FALSE when the
		//	the text being added should not be prepended with the para-numbering,
		//	as is the case with \page (mapped to FF).

		cchT = _cchUsedNumText;
		_cchUsedNumText = 0;				// Prevent infinite recursion

		if(!pstate->fBullet)
		{
			// If there are any _CF diffs to be injected, they will be trounced
			// by this recursive call (see FUTURE comment above).

			// Since we didn't save _CF data from calls to AddText with
			// pstate->sDest == destParaNumText, we have no way of setting up
			// CFEI_RUNISDBCS and CFMI_RUNISDBCS (see FUTURE comment above).

			AddText(_szNumText, cchT, FALSE);
		}
		else if(_PF.IsListNumbered() && _szNumText[cchT - 1] == TAB)
		{
			WCHAR ch = _szNumText[cchT - 2];

			_wNumberingStyle = (_wNumberingStyle & ~0xF00)
				 | (ch == '.' ? PFNS_PERIOD : 
					ch != ')' ? PFNS_PLAIN  :
					_szNumText[0] == '(' ? PFNS_PARENS : PFNS_PAREN);

		}
	}

	if (_cpFirst && _prg->GetCp() == _cpFirst && _prg->GetPF()->InTable() &&
		_cCell && !_prg->_rpTX.IsAfterEOP())
	{
		// FUTURE: handle more general table insertions into other tables
		return _ecParseError = ecGeneralFailure;
	}

	Apply_CF();								// Apply formatting changes in _CF

	// BUGS 1577 & 1565 - 
	// CTxtRange::ReplaceRange will change the character formatting
	// and possibly adjust the _rpCF forward if the current char
	// formatting includes protection.  The changes affected by 
	// CTxtRange::ReplaceRange are necessary only for non-streaming 
	// input, so we save state before and restore it after the call 
	// to CTxtRange::ReplaceRange

	LONG iFormatSave = _prg->Get_iCF();		// Save state

	cchAdded = _prg->ReplaceRange(cch, pch, NULL, SELRR_IGNORE);

	_prg->Set_iCF(iFormatSave);				// Restore state 
	ReleaseFormats(iFormatSave, -1);
	Assert(_prg->GetCch() == 0);

	if (cchAdded != cch)

⌨️ 快捷键说明

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