📄 rtfread.cpp
字号:
}
// Adjust the PF for the new _pstateStackTop and delete unused PF's.
if(pstate->sDest == destParaNumbering || pstate->sDest == destParaNumText)
{
if(pstatePrev && pstate->pPF != pstatePrev->pPF)
{
// Bleed the PF of the current state into the previous state for
// paragraph numbering groups
Assert(pstatePrev->pPF);
pstatePrev->DeletePF();
pstatePrev->pPF = pstate->pPF;
pstate->pPF = NULL;
}
else
pstate->DeletePF();
// N.B. Here, we retain the _PF diffs since they apply to the
// enclosing group along with the PF of the group we are leaving
}
else
{
// We're popping the state, so delete its PF and discard the _PF diffs
Assert(pstate->pPF);
pstate->DeletePF();
// If !pstatePrev, we're ending the parse, in which case the _PF
// structure contains final PF (so don't toast it).
if(pstatePrev)
{
_PF.dwMask = 0;
}
}
if(pstatePrev)
{
_CF.dwMask = 0; // Discard any CF deltas
switch(pstate->sDest)
{
case destParaNumbering:
// {\pn ...}
pstatePrev->sIndentNumbering = pstate->sIndentNumbering;
pstatePrev->fBullet = pstate->fBullet;
break;
case destObject:
// clear our object flags just in case we have corrupt RTF
if(_fNeedPres)
{
_fNeedPres = FALSE;
_fNeedIcon = FALSE;
_pobj = NULL;
}
break;
case destFontTable:
if(pstatePrev->sDest == destFontTable)
{
// We're actually leaving a sub-group within the \fonttbl
// group.
break;
}
// We're leaving the {\fonttbl...} group.
#ifdef DEBUG
_fSeenFontTable = TRUE;
#endif
// Default font should now be defined, so select it
// (this creates CF deltas)
SetPlain(pstate);
// Ensure that a document-level codepage has been determined and
// then scan the font names and retry the conversion to Unicode,
// if necessary.
if(_nCodePage == INVALID_CODEPAGE)
{
// We haven't determined a document-level codepage
// from the \ansicpgN tag, nor from the font table
// \fcharsetN and \cpgN values. As a last resort,
// let's use the \deflangN and \deflangfeN tags
LANGID langid;
if(_sDefaultLanguageFE != INVALID_LANGUAGE)
{
langid = _sDefaultLanguageFE;
}
else if(_sDefaultLanguage != INVALID_LANGUAGE &&
_sDefaultLanguage != sLanguageEnglishUS)
{
// _sDefaultLanguage == sLanguageEnglishUS is inreliable
// in the absence of \deflangfeN. Many FE RTF writers
// write \deflang1033 (sLanguageEnglishUS).
langid = _sDefaultLanguage;
}
else
{
goto NoLanguageInfo;
}
_nCodePage = ConvertLanguageIDtoCodePage(langid);
}
NoLanguageInfo:
if(_nCodePage == INVALID_CODEPAGE)
{
break;
}
// Fixup mis-converted font face names
TEXTFONT *ptf;
UINT i;
for(i = 0; i < _fonts.Count(); i++)
{
ptf = _fonts.Elem(i);
if(ptf->sCodePage == INVALID_CODEPAGE ||
ptf->sCodePage == SYMBOL_CODEPAGE)
{
if(ptf->fNameIsDBCS)
{
char szaTemp[LF_FACESIZE];
BOOL fMissingCodePage;
// un-convert mis-converted face name
SideAssert(WCTMB(ptf->sCodePage, 0,
ptf->szName, -1,
szaTemp, sizeof(szaTemp),
NULL, NULL, &fMissingCodePage) > 0);
Assert(ptf->sCodePage == SYMBOL_CODEPAGE ||
fMissingCodePage);
// re-convert face name using new codepage info
SideAssert(MBTWC(_nCodePage, 0,
szaTemp, -1,
ptf->szName, sizeof(ptf->szName) / sizeof(ptf->szName[0]),
&fMissingCodePage) > 0);
if(!fMissingCodePage)
{
ptf->fNameIsDBCS = FALSE;
}
}
}
}
break;
default:;
// nothing
}
_prg->Set_iCF(pstatePrev->iCF); // Restore previous CharFormat
ReleaseFormats(pstatePrev->iCF, -1);
}
done:
TRACEERRSZSC("HandleEndGroup()", - _ecParseError);
return _ecParseError;
}
/*
* CRTFRead::SelectCurrentFont(iFont)
*
* @mfunc
* Set active font to that with index <p iFont>. Take into account
* bad font numbers.
*/
void CRTFRead::SelectCurrentFont(
INT iFont) // @parm font handle of font to select
{
TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::SelectCurrentFont");
LONG i = _fonts.Count();
STATE * pstate = _pstateStackTop;
TEXTFONT * ptf = _fonts.Elem(0);
AssertSz(i, "CRTFRead::SelectCurrentFont: bad font collection");
if (NULL == pstate)
{
AssertSz(pstate, "CRTFRead::SelectCurrentFont: bad state pointer");
return;
}
for(; i-- && iFont != ptf->sHandle; ptf++) // Search for font with handle
; // iFont
// Font handle not found: use default, which is valid
// since \rtf copied _prg's
if(i < 0)
ptf = _fonts.Elem(0);
BOOL fDefFontFromSystem = (i == (LONG)_fonts.Count() - 1 || i < 0) &&
!_fReadDefFont;
StringCchCopy(_CF.szFaceName, sizeof(_CF.szFaceName) / sizeof(_CF.szFaceName[0]), ptf->szName);
_CF.bInternalMask |= CFMI_FACENAMEISDBCS;
_CF.bInternalEffects &= ~CFEI_FACENAMEISDBCS;
if( ptf->fNameIsDBCS )
_CF.bInternalEffects |= CFEI_FACENAMEISDBCS;
if(pstate->sDest != destFontTable)
{
_CF.bCharSet = ptf->bCharSet;
_CF.bPitchAndFamily = ptf->bPitchAndFamily;
_CF.dwMask |= CFM_FACE | CFM_CHARSET;
}
// Ensure that the state's codepage is not supplied by the system.
// That is, if we are using the codepage info from the default font,
// be sure that the default font info was read from the RTF file.
pstate->SetCodePage(((fDefFontFromSystem || ptf->sCodePage == INVALID_CODEPAGE)
? _nCodePage : ptf->sCodePage));
pstate->ptf = ptf;
#ifdef CHICAGO
// Win95c 1719: try to match a language to the char set when RTF
// doesn't explicitly set a language
if (!pstate->fExplicitLang && ptf->bCharSet != ANSI_CHARSET &&
(!pstate->sLanguage || pstate->sLanguage == sLanguageEnglishUS))
{
i = AttIkliFromCharset(_ped, ptf->bCharSet);
if (i >= 0)
pstate->sLanguage = LOWORD(rgkli[i].hkl);
}
#endif // CHICAGO
}
/*
* CRTFRead::SetPlain()
*
* @mfunc
* Setup _CF for \plain
*/
void CRTFRead::SetPlain(STATE *pstate)
{
ZeroMemory(&_CF, _CF.cbSize);
_CF.cbSize = sizeof(CHARFORMAT2);
_CF.dwMask = CFM_ALL2;
_CF.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; // Set default effects
_CF.yHeight = PointsToFontHeight(yDefaultFontSize);
if(_sDefaultLanguage == INVALID_LANGUAGE)
{
_CF.dwMask &= ~CFM_LCID;
}
else
{
_CF.lcid = MAKELCID((WORD)_sDefaultLanguage, SORT_DEFAULT);
}
_CF.bUnderlineType = CFU_UNDERLINE;
SelectCurrentFont(_sDefaultFont);
// TODO: get rid of pstate->sLanguage, since CHARFORMAT2 has lcid
pstate->sLanguage = _sDefaultLanguage;
pstate->fExplicitLang = FALSE;
#ifdef BIDI
// Character inherits para's direction
//$ REVIEW: What happens on \rtlpar\ltrch\plain ? Is this even legal ?
FlushDirection();
pstate->fRightToLeft = pstate->fRightToLeftPara;
#endif
}
/*
* CRTFRead::ReadFontName(pstate)
*
* @mfunc
* read font name _szText into <p pstate>->ptf->szName and deal with
* tagged fonts
*/
void CRTFRead::ReadFontName(
STATE * pstate, // @parm state whose font name is to be read into
int iAllASCII) // @parm indicates that _szText is all ASCII chars
{
TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::ReadFontName");
if (pstate->ptf)
{
INT cchName = LF_FACESIZE - 1;
TCHAR * pchDst = pstate->ptf->szName;
char * pachName = (char *)_szText ;
// Append additional text from _szText to TEXTFONT::szName
// We need to append here since some RTF writers decide
// to break up a font name with other RTF groups
while(*pchDst && cchName > 0)
{
pchDst++;
cchName--;
}
INT cchLimit = cchName;
while (*pachName &&
*pachName != ';' &&
cchLimit) // Remove semicolons
{
pachName++;
cchLimit--;
}
*pachName = '\0';
#ifdef PWD_JUPITER
// GuyBark:
// The Office converters can output font decorations to the font names. PWord does
// not want these decorations, as the fonts on the device are capable of displaying
// characters from multiple character sets. So strip the decorations from the font
// names if there are any. Note: this is not the same action as RichEdit does later
// with the font substitution, that looks in the .ini files for replacing some
// fonts with other fonts.
// We don't need to do this if the font's charset is plain ol' Western ANSI.
if(pstate->ptf->bCharSet)
{
int i = 0, cchFont, cchDecoration;
// Get the length of the incoming font name. All font names here are MBCS.
cchFont = strlen((LPSTR)_szText);
// For all the decorations we can expect...
while(fontDec[i].pszName)
{
// Get the length of this decoration. Assume that the decoration is always preceded
// by a space. This reduces the chance of doing something the user doesn't expect.
cchDecoration = strlen(fontDec[i].pszName);
// If this charset of the incoming font and the decoration match,
// check for the decoration in the font name.
if((pstate->ptf->bCharSet == fontDec[i].charset) &&
(cchFont > cchDecoration) &&
!strcmp((LPSTR)&_szText[cchFont - cchDecoration], fontDec[i].pszName))
{
// It has the decoration! So chop it off.
_szText[cchFont - cchDecoration] = '\0';
break;
}
// Oh well, try the next font decoration.
++i;
}
}
#endif // PWD_JUPITER
// Use the codepage of the font in all cases except where the font uses
// the symbol charset (and the codepage has been mapped from the charset)
// and UTF-8 isn't being used
LONG nCodePage = pstate->nCodePage != SYMBOL_CODEPAGE
? pstate->nCodePage : _nCodePage;
BOOL fMissingCodePage;
Assert(!(_dwFlags & SFF_UTF8) || nCodePage == CP_UTF8);
INT cch = MBTWC(nCodePage, 0,
(char *)_szText, -1,
pchDst, cchName, &fMissingCodePage);
if(cch > 0 && fMissingCodePage && iAllASCII == CONTAINS_NONASCII)
pstate->ptf->fNameIsDBCS = TRUE;
// Make sure destination is null terminated
if(cch > 0)
pchDst[cch] = 0;
// Fall through even if MBTWC <= 0, since we may be appending text to an
// existing font name.
if (pstate->ptf == _fonts.Elem(0)) // If it's the default font,
SelectCurrentFont(_sDefaultFont); // update _CF accordingly
TCHAR * szNormalName;
if (pstate->ptf->bCharSet && pstate->fRealFontName)
{
// if we don't know about this font don't use the real name
if (!FindTaggedFont(pstate->ptf->szName,
pstate->ptf->bCharSet, &szNormalName))
{
pstate->fRealFontName = FALSE;
pstate->ptf->szName[0] = 0;
}
}
else if (IsTaggedFont(pstate->ptf->szName,
&pstate->ptf->bCharSet, &szNormalName))
{
wcscpy(pstate->ptf->szName, szNormalName);
pstate->ptf->sCodePage = GetCodePage(pstate->ptf->bCharSet);
pstate->SetCodePage(pstate->ptf->sCodePage);
}
}
}
/*
* CRTFRead::GetColor (dwMask)
*
* @mfunc
* Store the autocolor or autobackcolor effect bit and return the
* COLORREF for color _iParam
*
* @rdesc
* COLORREF for color _iParam
*
* @devnote
* If the entry in _colors corresponds to tomAutoColor, gets the value
* RGB(0,0,0) (since no \red, \green, and \blue fields are used), but
* isn't used by the RichEdit engine. Entry 1 corresponds to the first
* explicit entry in the \colortbl and is usually RGB(0,0,0). The _colors
* table is built by HandleToken() when it handles the token tokenText
* for text consisting of a ';' for a destination destColorTable.
*/
COLORREF CRTFRead::GetColor(
DWORD dwMask) //@parm Color mask bit
{
TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::GetColor");
if((DWORD)_iParam >= _colors.Count()) // Illegal _iParam
return RGB(0,0,0);
_CF.dwMask |= dwMask; // Turn on appropriate mask bit
_CF.dwEffects &= ~dwMask; // auto(back)color off: color is to be used
COLORREF Color = *_colors.Elem(_iParam);
if(Color == tomAutoColor)
{
_CF.dwEffects |= dwMask; // auto(back)color on
Color = RGB(0,0,0);
}
return Color;
}
/*
* CRTFRead::GetStandardColorIndex ()
*
* @mfunc
* Return the color index into the standard 16-entry Word \colortbl
* corresponding to the color index _iParam for the current \colortbl
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -