📄 rtfread.cpp
字号:
{
Tracef(TRCSEVERR, "AddText(): Only added %d out of %d", cchAdded, cch);
_ecParseError = ecGeneralFailure;
if (cchAdded <= 0)
return _ecParseError;
}
_cchMax -= cchAdded;
return _ecParseError;
}
/*
* CRTFRead::Apply_CF()
*
* @mfunc
* Apply character formatting changes collected in _CF
*/
void CRTFRead::Apply_CF()
{
// If any CF changes, update range's _iFormat
if( _CF.dwMask || _CF.bInternalMask )
{
AssertSz(_prg->GetCch() == 0,
"CRTFRead::Apply_CF: nondegenerate range");
_prg->SetCharFormat(&_CF, FALSE, NULL); // Note: nothing here to undo
_CF.dwMask = 0; // i.e., only changed char
// format of insertion point
_CF.bInternalMask = 0;
}
}
/*
* CRTFRead::Apply_PF()
*
* @mfunc
* Apply paragraph format given by _PF
*/
void CRTFRead::Apply_PF()
{
LONG cp;
if(_pstateStackTop)
{
Assert(_pstateStackTop->pPF);
// Add PF diffs to *_pstateStackTop->pPF
if(!_pstateStackTop->AddPF(_PF, _sDefaultTabWidth, _bDocType))
{
_ped->GetCallMgr()->SetOutOfMemory();
_ecParseError = ecNoMemory;
return;
}
_PF.dwMask = 0; // _PF contains delta's from *_pstateStackTop->pPF
CParaFormat *pPF = _pstateStackTop->pPF;
Assert(pPF->dwMask == PFM_ALLRTF);
if(pPF->wNumbering)
{
pPF->wNumberingTab = _pstateStackTop->sIndentNumbering;
pPF->wNumberingStyle = _wNumberingStyle;
}
}
cp = _prg->GetCp();
_prg->Set(cp, cp - _cpThisPara); // Select back to _cpThisPara
_prg->SetParaFormat(_pstateStackTop ? _pstateStackTop->pPF : &_PF, NULL);
_prg->Set(cp, 0); // Restore _prg to an IP
}
/*
* CRTFRead::SetBorderParm(&Parm, Value)
*
* @mfunc
* Set the border pen width in half points for the current border
* (_bBorder)
*/
void CRTFRead::SetBorderParm(
WORD& Parm,
LONG Value)
{
Assert(_bBorder <= 3);
Value = min(Value, 15);
Value = max(Value, 0);
Parm &= ~(0xF << 4*_bBorder);
Parm |= Value << 4*_bBorder;
_PF.dwMask |= PFM_BORDER;
}
/*
* CRTFRead::HandleToken()
*
* @mfunc
* Grand switch board that handles all tokens. Switches on _token
*
* @rdesc
* EC The error code
*
* @comm
* Token values are chosen contiguously (see tokens.h and tokens.c) to
* encourage the compiler to use a jump table. The lite-RTF keywords
* come first, so that an optimized OLE-free version works well. Some
* groups of keyword tokens are ordered so as to simplify the code, e.g,
* those for font family names, CF effects, and paragraph alignment.
*/
EC CRTFRead::HandleToken()
{
TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleToken");
BYTE bT; // Temporary BYTE
DWORD dwT; // Temporary DWORD
LONG dy, i;
LONG iParam = _iParam;
const CCharFormat * pcf;
COLORREF * pclrf;
STATE * pstate = _pstateStackTop;
TEXTFONT * ptf;
WORD wT; // Temporary WORD
#if defined(DEBUG)
if(!_fTestingParserCoverage)
#endif
{
if(_cbSkipForUnicode &&
_token != tokenText &&
_token != tokenStartGroup &&
_token != tokenEndGroup &&
_token != tokenBinaryData)
{
_cbSkipForUnicode--;
goto done;
}
}
switch (_token)
{
case tokenPocketWord: // \pwd
_dwFlags |= SFF_PWD;
case tokenRtf: // \rtf
PARSERCOVERAGE_CASE();
pstate->sDest = destRTF;
if (!_fonts.Count() && !_fonts.Add(1, NULL)) // If can't add a font,
goto OutOfRAM; // report the bad news
_sDefaultFont = 0; // Set up valid default font
ptf = _fonts.Elem(0);
pstate->ptf = ptf; // Get char set, pitch, family
pcf = _prg->GetCF(); // from current range font
ptf->bCharSet = pcf->bCharSet; // These are guaranteed OK
ptf->bPitchAndFamily = pcf->bPitchAndFamily;
ptf->sCodePage = GetCodePage(pcf->bCharSet);
Assert(pstate->nCodePage == INVALID_CODEPAGE);
wcscpy(ptf->szName, pcf->szFaceName);
ptf->fNameIsDBCS = (pcf->bInternalEffects & CFEI_FACENAMEISDBCS);
pstate->cbSkipForUnicodeMax = iUnicodeCChDefault;
break;
case tokenViewKind: // \viewkind N
if(!(_dwFlags & SFF_SELECTION)) // RTF applies to document:
_ped->SetViewKind(iParam);
break;
case tokenViewScale: // \viewscale N
if(!(_dwFlags & SFF_SELECTION)) // RTF applies to document:
_ped->SetViewScale(iParam);
break;
case tokenCharacterDefault: // \plain
PARSERCOVERAGE_CASE();
dy = _CF.yOffset;
SetPlain(pstate);
// GuyBark JupiterJ: Special case the offset to preserve it in a field equation.
if(_fEquationField)
{
_CF.yOffset = dy;
}
break;
case tokenCharSetAnsi: // \ansi
PARSERCOVERAGE_CASE();
_bCharSet = 0;
break;
case tokenUTF: // \utf
PARSERCOVERAGE_CASE();
if(iParam == 8)
{
_dwFlags |= SFF_UTF8; // Save bit for Asserts
pstate->SetCodePage(CP_UTF8);
}
break;
case tokenDefaultLanguage: // \deflang
PARSERCOVERAGE_CASE();
_sDefaultLanguage = (SHORT)iParam;
if (!pstate->sLanguage)
pstate->sLanguage = _sDefaultLanguage;
break;
case tokenDefaultLanguageFE: // \deflangfe
PARSERCOVERAGE_CASE();
_sDefaultLanguageFE = (SHORT)iParam;
break;
case tokenDefaultTabWidth: // \deftab
PARSERCOVERAGE_CASE();
_sDefaultTabWidth = (SHORT)iParam;
if (!pstate->sDefaultTabWidth)
pstate->sDefaultTabWidth = _sDefaultTabWidth;
break;
//--------------------------- Font Control Words -------------------------------
case tokenDefaultFont: // \deff n
PARSERCOVERAGE_CASE();
if(iParam >= 0)
_fonts.Elem(0)->sHandle = _sDefaultFont = (SHORT)iParam;
TRACEERRSZSC("tokenDefaultFont: Negative value", iParam);
break;
case tokenFontTable: // \fonttbl
PARSERCOVERAGE_CASE();
pstate->sDest = destFontTable;
pstate->ptf = NULL;
break;
case tokenFontFamilyBidi: // \fbidi
case tokenFontFamilyTechnical: // \ftech
case tokenFontFamilyDecorative: // \fdecor
case tokenFontFamilyScript: // \fscript
case tokenFontFamilyModern: // \fmodern
case tokenFontFamilySwiss: // \fswiss
case tokenFontFamilyRoman: // \froman
case tokenFontFamilyDefault: // \fnil
PARSERCOVERAGE_CASE();
AssertSz(tokenFontFamilyRoman - tokenFontFamilyDefault == 1,
"CRTFRead::HandleToken: invalid token definition");
if (pstate->ptf)
{
pstate->ptf->bPitchAndFamily
= (_token - tokenFontFamilyDefault) << 4
| (pstate->ptf->bPitchAndFamily & 0xF);
// setup SYMBOL_CHARSET charset for \ftech if there isn't any chaset info
if ( tokenFontFamilyTechnical == _token && pstate->ptf->bCharSet == DEFAULT_CHARSET )
{
pstate->ptf->bCharSet = SYMBOL_CHARSET;
}
}
break;
case tokenPitch: // \fprq
PARSERCOVERAGE_CASE();
if(pstate->ptf)
pstate->ptf->bPitchAndFamily
= iParam | (pstate->ptf->bPitchAndFamily & 0xF0);
break;
case tokenAnsiCodePage: // \ansicpg
PARSERCOVERAGE_CASE();
#ifdef DEBUG
if(_fSeenFontTable && _nCodePage == INVALID_CODEPAGE)
TRACEWARNSZ("CRTFRead::HandleToken(): Found an \ansicpgN tag after "
"the font table. Should have code to fix-up "
"converted font names and document text.");
#endif
_nCodePage = iParam;
Assert(!(_dwFlags & SFF_UTF8) || pstate->nCodePage == CP_UTF8);
pstate->SetCodePage(iParam);
break;
case tokenCodePage: // \cpg
PARSERCOVERAGE_CASE();
pstate->SetCodePage(iParam);
if(pstate->sDest == destFontTable && pstate->ptf)
{
pstate->ptf->sCodePage = (SHORT)iParam;
pstate->ptf->bCharSet = GetCharSet(iParam);
// also, if a document-level code page has not been specified
// grab this from the first font table entry containing a
// \fcharsetN or \cpgN
if(_nCodePage == INVALID_CODEPAGE)
{
_nCodePage = (SHORT)iParam;
}
}
break;
case tokenCharSet: // \fcharset n
PARSERCOVERAGE_CASE();
if(pstate->sDest == destFontTable && pstate->ptf)
{
pstate->ptf->bCharSet = (BYTE) iParam;
pstate->ptf->sCodePage = GetCodePage((BYTE)iParam);
pstate->SetCodePage(pstate->ptf->sCodePage);
// also, if a document-level code page has not been specified
// grab this from the first font table entry containing a
// \fcharsetN or \cpgN
if (pstate->nCodePage != SYMBOL_CODEPAGE &&
_nCodePage == INVALID_CODEPAGE)
{
_nCodePage = pstate->nCodePage;
}
}
break;
case tokenRealFontName: // \fname
PARSERCOVERAGE_CASE();
pstate->sDest = destRealFontName;
break;
case tokenFontSelect: // \f n
PARSERCOVERAGE_CASE();
if (pstate->sDest == destFontTable) // Building font table
{
if (iParam == _sDefaultFont)
{
_fReadDefFont = TRUE;
ptf = _fonts.Elem(0);
}
else if (!(ptf =_fonts.Add(1,NULL)))// Make room in font table for
{ // font to be parsed
OutOfRAM:
_ped->GetCallMgr()->SetOutOfMemory();
_ecParseError = ecNoMemory;
break;
}
pstate->ptf = ptf;
ptf->sHandle = (SHORT)iParam; // Save handle
ptf->szName[0] = '\0'; // Start with null string so
ptf->bPitchAndFamily = 0;
ptf->fNameIsDBCS = FALSE;
ptf->sCodePage = INVALID_CODEPAGE;
ptf->fCpgFromSystem = FALSE;
bT = DEFAULT_CHARSET; // appending works right
#ifdef DBCS
switch(HIWORD(UlGGetLang()) // TODO: use table lookup
{
case LangJpn:
bT = SHIFTJIS_CHARSET;
break;
case LangKor:
bT = HANGEUL_CHARSET;
break;
case LangCht:
bT = CHINESEBIG5_CHARSET;
break;
case LangPrc:
bT = GB2312_CHARSET;
break;
default:
bT = DEFAULT_CHARSET;
}
#endif
ptf->bCharSet = bT;
#ifdef PWD_JUPITER
// GuyBark JupiterJ 50029: Some RTF we get has no character set info
// in the font table. This will mess up the text handling later. So
// assume that the character set is the default system one. This will
// get overridden later if we find the true character set info the
// the font table later. Note: All we need to do is set the code page
// in the font data here. This will get used later in the text handling
// and it doesn't matter that the character set is still set to default.
// We're using the default system locale here, so we're not guaranteed
// to get the correct code page, but we guessing at what the missing
// info is anyway.
ptf->sCodePage = ConvertLanguageIDtoCodePage( GetSystemDefaultLCID());
ptf->bCharSet = GetCharSet(ptf->sCodePage);
pstate->SetCodePage(ptf->sCodePage);
#endif // PWD_JUPITER
}
else // Font switch in text
SelectCurrentFont(iParam);
break;
case tokenFontSize: // \fs
PARSERCOVERAGE_CASE();
_CF.yHeight = PointsToFontHeight(iParam); // Convert font size in
_CF.dwMask |= CFM_SIZE; // half points to logical
break; // units
// NOTE: \*\fontemb and \*\fontfile are discarded. The font mapper will
// have to do the best it can given font name, family, and pitch.
// Embedded fonts are particularly nasty because legal use should
// only support read-only which parser cannot enforce.
case tokenLanguage: // \lang
PARSERCOVERAGE_CASE();
pstate->sLanguage = (SHORT)iParam; // These 2 lines may not be
pstate->fExplicitLang = TRUE; // needed with the new lcid
_CF.lcid = MAKELCID(iParam, SORT_DEFAULT);
_CF.dwMask |= CFM_LCID;
break;
//-------------------------- Color Control Words ------------------------------
case tokenColorTable: // \colortbl
PARSERCOVERAGE_CASE();
pstate->sDest = destColorTable;
_fGetColorYet = FALSE;
break;
case tokenColorRed: // \red
PARSERCOVERAGE_CASE();
#ifdef PWD_JUPITER
// GuyBark Jupiter 37275: Special case output from the Office converters.
pstate->bRed = (iParam == 127 ? 128 : (BYTE)iParam);
#else
pstate->bRed = (BYTE)iParam;
#endif // PWD_JUPITER
_fGetColorYet = TRUE;
break;
case tokenColorGreen: // \green
PARSERCOVERAGE_CASE();
#ifdef PWD_JUPITER
pstate->bGreen = (iParam == 127 ? 128 : (BYTE)iParam);
#else
pstate->bGreen = (BYTE)iParam;
#endif // PWD_JUPITER
_fGetColorYet = TRUE;
break;
case tokenColorBlue: // \blue
PARSERCOVERAGE_CASE();
#ifdef PWD_JUPITER
pstate->bBlue = (iParam == 127 ? 128 : (BYTE)iParam);
#else
pstate->bBlue = (BYTE)iParam;
#endif // PWD_JUPITER
_fGetColorYet = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -