📄 rtfwrit.cpp
字号:
/*
* CRTFWrite::printF(szFmt, ...)
*
* @mfunc
* Provide formatted output
*
* @rdesc
* TRUE if successful
*/
BOOL _cdecl CRTFWrite::printF(
CONST CHAR * szFmt, // @parm Format string for printf()
...) // @parmvar Parameter list
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::printF");
va_list marker;
const INT c_chT = 60;
CHAR szT[c_chT];
int cb;
va_start(marker, szFmt);
cb = W32->WvsprintfA(c_chT, szT, szFmt, marker);
va_end(marker);
// Truncate if needed
cb = min(cb, c_chT);
return Puts(szT, cb);
}
/*
* CRTFWrite::sprintF(szBuf, szFmt, ...)
*
* @mfunc
* Provide formatted output to a string buffer
*
* @rdesc
* number of bytes written
*/
LONG _cdecl CRTFWrite::sprintF(
LONG cbBuf,
CHAR *szBuf,
CONST CHAR * szFmt, // @parm Format string for printf()
...) // @parmvar Parameter list
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::printF");
va_list marker;
int cb;
va_start(marker, szFmt);
cb = W32->WvsprintfA(cbBuf, szBuf, szFmt, marker);
va_end(marker);
return cb;
}
/*
* CRTFWrite::WritePcData(szData, nCodePage, fIsDBCS)
*
* @mfunc
* Write out the string <p szData> as #PCDATA where any special chars
* are protected by leading '\\'.
*
* @rdesc
* EC (_ecParseError)
*/
EC CRTFWrite::WritePcData(
const TCHAR * szData, // @parm #PCDATA string to write
INT nCodePage, // @parm code page default value CP_ACP
BOOL fIsDBCS) // @parm szData is a DBCS string stuffed into Unicode buffer
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::WritePcData");
BYTE ch;
BOOL fMissingCodePage;
BOOL fMultiByte;
const BYTE *pch;
const char *pchToDBCSDefault = NULL;
BOOL * pfUsedDefault = NULL;
if(_dwFlags & SFF_UTF8) // Use UTF-8 for all conversions
nCodePage = CP_UTF8; // (doesn't work for unknown cpg's
// i.e., if fIsDBCS is TRUE...)
if(!*szData)
{
return _ecParseError;
}
int DataSize = wcslen(szData) + 1;
int BufferSize = DataSize * 2;
#ifdef PWD_JUPITER
// GuyBark JupiterJ 51164:
// Yes, well, "* 2" may be ok for Unicode to DBCS. but it's too small to
// cope with conversion to UTF8. So bump it up to always be big enough.
BufferSize *= 3;
#endif // PWD_JUPITER
char *pBuffer = (char *)PvAlloc(BufferSize * 2, GMEM_ZEROINIT);
if(!pBuffer)
{
return ecNoMemory;
}
#ifdef DEBUG
// When WCTMB fails to convert a char, the following default
// char is used as a placeholder in the string being converted
const char chToDBCSDefault = 0;
BOOL fUsedDefault;
pchToDBCSDefault = &chToDBCSDefault;
pfUsedDefault = &fUsedDefault;
#endif
int cchRet = WCTMB(fIsDBCS ? INVALID_CODEPAGE : nCodePage, 0,
szData, -1, pBuffer, BufferSize,
pchToDBCSDefault, pfUsedDefault,
&fMissingCodePage);
Assert(cchRet > 0);
if(!fIsDBCS && fMissingCodePage && nCodePage != CP_ACP)
{
// Here, the system could not convert the Unicode string because the
// code page is not installed on the system. Fallback to CP_ACP.
cchRet = WCTMB(CP_ACP, 0,
szData, -1, pBuffer, BufferSize,
pchToDBCSDefault, pfUsedDefault,
&fMissingCodePage);
Assert(cchRet > 0);
nCodePage = CP_ACP;
}
AssertSz(!fUsedDefault, "CRTFWrite::WritePcData(): Found character in "
"control text which cannot be converted from "
"Unicode");
if(cchRet <= 0)
{
_ecParseError = ecCantUnicode;
goto CleanUp;
}
BufferSize = cchRet;
fMultiByte = (BufferSize > DataSize) || fIsDBCS || fMissingCodePage;
pch = (BYTE *)pBuffer;
ch = *pch;
// If _fNeedDelimeter, may need to PutChar(' ')
CheckDelimeter();
while (!_ecParseError && (ch = *pch++))
{
if(fMultiByte && *pch && IsLeadByte(ch, nCodePage))
{
printF(szEscape2CharFmt, ch, *pch++);
}
else
{
if(ch == LBRACE || ch == RBRACE || ch == BSLASH)
{
printF(szLiteralCharFmt, ch);
}
else if(ch < 32 || ch == ';' || ch > 127)
{
printF(szEscapeCharFmt, ch);
}
else
{
PutChar(ch);
}
}
}
CleanUp:
FreePv(pBuffer);
return _ecParseError;
}
/*
* CRTFWrite::LookupColor(colorref)
*
* @mfunc
* Return color-table index for color referred to by <p colorref>.
* If a match isn't found, an entry is added.
*
* @rdesc
* LONG Index into colortable
* <lt> 0 on error
*/
LONG CRTFWrite::LookupColor(
COLORREF colorref) // @parm colorref to look for
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::LookupColor");
LONG Count = _colors.Count();
LONG iclrf;
COLORREF * pclrf;
for(iclrf = 0; iclrf < Count; iclrf++) // Look for color
if(_colors.GetAt(iclrf) == colorref)
return iclrf;
pclrf = _colors.Add(1, NULL); // If we couldn't find it,
if(!pclrf) // add it to color table
return -1;
*pclrf = colorref;
return iclrf;
}
/*
* CRTFWrite::LookupFont(pCF)
*
* @mfunc
* Returns index into font table for font referred to by
* CCharFormat *<p pCF>. If a match isn't found, an entry is added.
*
* @rdesc
* SHORT Index into fonttable
* <lt> 0 on error
*/
LONG CRTFWrite::LookupFont(
CCharFormat const * pCF) // @parm CCharFormat holding font name
{ // to look up
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::LookupFont");
LONG Count = _fonts.Count();
LONG itf;
TEXTFONT * ptf;
for(itf = 0; itf < Count; itf++)
{ // Look for font
ptf = _fonts.Elem(itf);
if (ptf->bPitchAndFamily == pCF->bPitchAndFamily && // of same pitch,
ptf->bCharSet == pCF->bCharSet && // char set, and
!wcscmp(ptf->szName, pCF->szFaceName)) // name
{
return itf; // Found it
}
}
ptf = _fonts.Add(1, NULL); // Didn't find it:
if(!ptf) // add to table
return -1;
ptf->bPitchAndFamily = pCF->bPitchAndFamily;
ptf->bCharSet = pCF->bCharSet;
ptf->sCodePage = GetCodePage (ptf->bCharSet);
wcscpy(ptf->szName, pCF->szFaceName);
ptf->fNameIsDBCS = (pCF->bInternalEffects & CFEI_FACENAMEISDBCS);
#if 0
// Bug1523 - (BradO) I removed this section of code so that a /fN tag is always
// emitted for the first run of text. In theory, we should be able to
// assume that the first run of text would carry the default font.
// It turns out that when reading RTF, Word doesn't use anything predictable
// for the font of the first run of text in the absence of an explicit /fN,
// thus, we have to explicitly emit a /fN tag for the first run of text.
if(!Count) // 0th font is
{ // default \deff0
_CF.bPitchAndFamily = pCF->bPitchAndFamily; // Set "previous"
_CF.bCharSet = pCF->bCharSet; // CF accordingly
wcscpy(_CF.szFaceName, pCF->szFaceName);
}
#endif
return itf;
}
/*
* CRTFWrite::BuildTables(prp, cch)
*
* @mfunc
* Build font and color tables for write range of length <p cch> and
* charformat run ptr <p prp>
*
* @rdesc
* EC The error code
*/
EC CRTFWrite::BuildTables(
CFormatRunPtr& rpCF, // @parm CF run ptr for start of write range
CFormatRunPtr& rpPF, // @parm PF run ptr for start of write range
LONG cch) // @parm # chars in write range
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::BuildTables");
LONG i;
LONG ifmt = 0;
const CCharFormat * pCF = NULL;
const CParaFormat * pPF = NULL;
CFormatRunPtr rp(rpCF);
CFormatRunPtr rpPFtemp(rpPF);
LONG cchTotal = cch;
while(cch > 0)
{
ifmt = rp.GetFormat(); // _iFormat for next CF run
pCF = _ped->GetCharFormat(ifmt);
if( !pCF )
goto CacheError;
// Look up character-format *pCF's font and color. If either isn't
// found, it is added to appropriate table. Don't lookup color
// for CCharFormats with auto-color
if (LookupFont(pCF) < 0 ||
(!(pCF->dwEffects & CFE_AUTOCOLOR) &&
LookupColor(pCF->crTextColor) < 0) ||
(!(pCF->dwEffects & CFE_AUTOBACKCOLOR) &&
LookupColor(pCF->crBackColor) < 0))
{
break;
}
if(!rp.IsValid())
break;
cch -= rp.GetCchLeft();
rp.NextRun();
}
// now look for bullets; if found, then we need to include
// the "Symbol" font
cch = cchTotal;
_symbolFont = 0;
while( cch > 0 )
{
ifmt = rpPFtemp.GetFormat();
pPF = _ped->GetParaFormat(ifmt);
if( !pPF )
{
goto CacheError;
}
if( pPF->wNumbering == PFN_BULLET )
{
// Save the Font index for Symbol.
// Reset it to 0 if LookupFont return error.
if ( (_symbolFont = LookupFont((CCharFormat *)&cfBullet)) < 0 )
_symbolFont = 0;
// We don't need to bother looking for more bullets, since
// in RichEdit 2.0, all bullets either have the same font or
// have their formatting information in the character format
// for the EOP mark.
// GuyBark: That may be true, but we still need to keep looping
// through the paragraghs for things like the stylesheet below.
// break;
}
WORD Widths = pPF->wBorderWidth;
DWORD Colors = pPF->dwBorderColor & 0xFFFFF;
while(Widths && Colors)
{
i = Colors & 0x1F;
if(i && (Widths & 0xF))
LookupColor(g_Colors[i - 1]);
Widths >>= 4;
Colors >>= 5;
}
i = (pPF->wShadingStyle >> 6) & 31; // Shading forecolor
if(i)
LookupColor(g_Colors[i - 1]);
i = pPF->wShadingStyle >> 11; // Shading backcolor
if(i)
LookupColor(g_Colors[i - 1]);
if(IsHeadingStyle(pPF->sStyle) && pPF->sStyle < _nHeadingStyle)
_nHeadingStyle = pPF->sStyle;
if(!rpPFtemp.IsValid())
break;
cch -= rpPFtemp.GetCchLeft();
rpPFtemp.NextRun();
}
return _ecParseError;
CacheError:
_ecParseError = ecFormatCache;
return ecFormatCache; // Access to CF/PF cache failed
}
/*
* CRTFWrite::WriteFontTable()
*
* @mfunc
* Write out font table
*
* @rdesc
* EC The error code
*/
EC CRTFWrite::WriteFontTable()
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::WriteFontTable");
LONG Count = _fonts.Count();
int itf;
int m;
int pitch;
TEXTFONT *ptf;
char * szFamily;
TCHAR * szTaggedName;
if(!Count || !PutCtrlWord(CWF_GRP, i_fonttbl)) // Start font table group
goto CleanUp;
for (itf = 0; itf < Count; itf++)
{
ptf = _fonts.Elem(itf);
// if (ptf->sCodePage)
// if (! PutCtrlWord(CWF_VAL, i_cpg, ptf->sCodePage ) )
// goto CleanUp;
// Define font family
m = ptf->bPitchAndFamily >> 4;
szFamily = rgKeyword[rgiszFamily[m < 6 ? m : 0]].szKeyword;
szTaggedName = NULL;
// check to see if this is a tagged font
if (!ptf->bCharSet ||
!FindTaggedFont(ptf->szName, ptf->bCharSet, &szTaggedName))
{
szTaggedName = NULL;
}
pitch = ptf->bPitchAndFamily & 0xF; // Write font
if (!printF(szBeginFontEntryFmt, itf, szFamily)) // entry, family,
goto CleanUp;
_fNeedDelimeter = TRUE;
if (pitch && !PutCtrlWord(CWF_VAL, i_fprq, pitch)) // and pitch
goto CleanUp;
if (!ptf->sCodePage && ptf->bCharSet)
{
ptf->sCodePage = GetCodePage(ptf->bCharSet);
}
#ifdef PWD_JUPITER
// GuyBark: If this is a J font, then store the id here so we can
// select it later if necessary when outputting J text chunks.
if((_pwdDefaultJFont == -1) && (ptf->sCodePage == 932))
{
_pwdDefaultJFont = itf;
}
#endif // PWD_JUPITER
// Write charset. Win32 uses ANSI_CHARSET to mean the default Windows
// character set, so find out what it really is
extern BYTE bCharSetANSI;
if(ptf->bCharSet != DEFAULT_CHARSET)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -