📄 rtfwrit2.cpp
字号:
//
// 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.
//
/*
* rtfwrit2.cpp
*
* Description:
* This file contains the embedded-object implementation of the RTF
* writer for the RICHEDIT subsystem.
*
* Authors:
* Original RichEdit 1.0 RTF converter: Anthony Francisco
* Conversion to C++ and RichEdit 2.0: Murray Sargent
*/
#include "_common.h"
#include "_rtfwrit.h"
#include "_coleobj.h"
ASSERTDATA
// ************** V-GUYB: Add this for converting pictures to 2bpp during stream out.
#if defined(CONVERT2BPP)
#define PWDV1_BPP 2
typedef struct
{
BITMAPINFOHEADER bmih;
RGBQUAD colors[4];
}
BMI2BPP;
const BYTE ColorTable2bpp[] =
{
0x00, 0x00, 0x00, 0x00,
0x55, 0x55, 0x55, 0x00,
0xAA, 0xAA, 0xAA, 0x00,
0xFF, 0xFF, 0xFF, 0x00
};
#endif // CONVERT2BPP
// ************** V-GUYB: End of conversion stuff.
static const CHAR szHexDigits[] = "0123456789abcdef";
static const CHAR szLineBreak[] = "\r\n";
const WORD ObjectKeyWordIndexes [] =
{
i_objw,i_objh,i_objscalex, i_objscaley, i_objcropl, i_objcropt, i_objcropr, i_objcropb
} ;
const WORD PictureKeyWordIndexes [] =
{
i_picw,i_pich,i_picscalex, i_picscaley, i_piccropl, i_piccropt, i_piccropr, i_piccropb
} ;
// TODO join with rtfwrit.cpp
// Most control-word output is done with the following printf formats
static const CHAR * rgszCtrlWordFormat[] =
{
"\\%s", "\\%s%d", "{\\%s", "{\\*\\%s"
};
static const WORD IndexROT[] =
{
i_wbitmap,
i_wmetafile,
i_dibitmap,
i_objemb,
i_objlink,
i_objautlink
};
TFI *CRTFConverter::_rgtfi = NULL; // @cmember Pointer to the first font substitute record
INT CRTFConverter::_ctfi = 0; // @cmember Number of the font substitute records
TCHAR *CRTFConverter::_pchFontSubInfo = NULL; // @cmember Font name information
// internal table to insert charset into _rgtfi under winNT
typedef struct
{
TCHAR* szLocaleName;
BYTE bCharSet;
} NTCSENTRY;
const NTCSENTRY mpszcs[] =
{
{ TEXT("cyr"), 204 }, // all lower case so we don't have to waste time
{ TEXT("ce"), 238 }, // doing a tolower below - Exchange2 800
{ TEXT("greek"), 161 },
{ NULL, 0 } // sentinel
};
#define cszcs (sizeof(mpszcs)/sizeof(mpszcs[0]))
/*
* Service RemoveAdditionalSpace (sz)
*
* Purpose:
* Remove first and last space from the string
* Only one space will remain between words
*
* Argument
* sz characters string
*/
void RemoveAdditionalSpace(TCHAR *sz)
{
TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "RemoveAdditionalSpace");
TCHAR *szSource = sz;
TCHAR *szDestination = sz;
while(*szSource == TEXT(' ') || *szSource == TAB)
{
*szSource++;
}
while(*szSource)
{
if(*szSource != TEXT(' ') && *szSource != TAB)
{
*szDestination++ = *szSource++;
}
else
{
*szDestination++ = TEXT(' ');
szSource++;
while(*szSource == TEXT(' ') || *szSource == TAB)
{
*szSource++;
}
}
}
*szDestination = TEXT('\0');
}
/*
* CRTFConverter::FreeFontSubInfo(void)
*
* @mfunc release any allocated memory for font substitutions
*
* @rdesc void
*/
void CRTFConverter::FreeFontSubInfo()
{
FreePv(_pchFontSubInfo);
FreePv(_rgtfi);
_pchFontSubInfo = NULL;
_rgtfi = NULL;
}
/*
* CRTFConverter::ReadFontSubInfo(void)
*
* Purpose:
* Read the table of Font Substitutes and parse out the tagged fonts
*
* Returns:
* BOOL TRUE if OK
*/
void CRTFConverter::ReadFontSubInfo()
{
#ifndef NOFONTSUBINFO
CLock clock;
int cchBuffer = 4096; // random number that seems about right
int cch;
static const TCHAR szFontSubSection[] = TEXT("FontSubstitutes");
TCHAR *pchTMax;
if(_ctfi)
{
return;
}
AssertSz(!_rgtfi, "CRTFConverter::ReadFontSubInfo(): Who donated the rgtfi?");
_pchFontSubInfo = (TCHAR *)PvAlloc(cchBuffer * sizeof(TCHAR), GMEM_FIXED);
if(!_pchFontSubInfo)
{
goto Cleanup;
}
next_try:
cch = GetProfileSection(szFontSubSection, _pchFontSubInfo, cchBuffer);
if(cch >= cchBuffer - 2) // GetProfileSection() magic number 2
{
// didn't fit, double the buffer size
const INT cchT = cchBuffer * 2;
if(cchT < cchBuffer) // >32k
{
goto Cleanup;
}
cchBuffer = cchT;
_pchFontSubInfo = (TCHAR *)PvReAlloc(_pchFontSubInfo, cchT * sizeof(TCHAR));
if(!_pchFontSubInfo)
{
goto Cleanup;
}
goto next_try;
}
else if(!cch)
{
*_pchFontSubInfo = 0;
}
_ctfi = cszcs; // a preliminary guess
// cszcs is used here only as a step in alloc
_rgtfi = (TFI *)PvAlloc(_ctfi * sizeof(TFI), GMEM_FIXED);
if(!_rgtfi)
{
goto Cleanup;
}
TFI *ptfi;
TCHAR *pchT;
pchT = _pchFontSubInfo;
pchTMax = _pchFontSubInfo + cch;
ptfi = &_rgtfi[0];
TCHAR *szTaggedName;
TCHAR *szNonTaggedName;
BOOL fGotTaggedCharSet;
BOOL fGotNonTaggedCharSet;
BYTE bTaggedCharSet;
BYTE bNonTaggedCharSet;
PARSEFONTNAME iParseLeft;
PARSEFONTNAME iParseRight;
// parse the entries
// we are interested in the following strings:
//
// <tagged font name> = <nontagged font name>
// (where <nontagged font name> = <tagged font name> - <tag>
// <font1 name>,<font1 charset> = <font2 name>
// <tagged font name> = <nontagged font name>,<nontagged font charset>
// (where <nontagged font charset> = <tag>)
// <font1 name>,<font1 charset> = <font2 name>,<font2 charset>
// (where <font1 charset> == <font2 charset>)
iParseLeft = iParseRight = PFN_SUCCESS;
while(pchT < pchTMax && iParseLeft != PFN_EOF
&& iParseRight != PFN_EOF)
{
fGotTaggedCharSet = FALSE;
fGotNonTaggedCharSet = FALSE;
if((iParseLeft = ParseFontName(pchT,
pchTMax,
TEXT('='),
&szTaggedName,
bTaggedCharSet,
fGotTaggedCharSet,
&pchT)) == PFN_SUCCESS &&
(iParseRight = ParseFontName(pchT,
pchTMax,
TEXT('\0'),
&szNonTaggedName,
bNonTaggedCharSet,
fGotNonTaggedCharSet,
&pchT)) == PFN_SUCCESS)
{
Assert(szTaggedName && szNonTaggedName);
BYTE bCharSet;
if(!fGotTaggedCharSet)
{
if(!FontSubstitute(szTaggedName, szNonTaggedName, &bCharSet))
{
continue;
}
}
else
{
bCharSet = bTaggedCharSet;
}
if(fGotNonTaggedCharSet && bCharSet != bNonTaggedCharSet)
{
continue;
}
// We have a legitimate tagged/nontagged pair, so save it.
ptfi->szTaggedName = szTaggedName;
ptfi->szNormalName = szNonTaggedName;
ptfi->bCharSet = bCharSet;
ptfi++;
if(DiffPtrs(ptfi, &_rgtfi[0], TFI) >= (UINT)_ctfi)
{
// allocate some more
_rgtfi = (TFI *)PvReAlloc(_rgtfi, (_ctfi + cszcs) * sizeof(TFI));
if(!_rgtfi)
{
goto Cleanup;
}
ptfi = _rgtfi + _ctfi;
_ctfi += cszcs;
}
}
}
_ctfi = DiffPtrs(ptfi, &_rgtfi[0], TFI);
if (!_ctfi)
{
goto Cleanup; // to cleanup alloc'd memory
}
return;
Cleanup:
if(_pchFontSubInfo)
{
FreePv(_pchFontSubInfo);
_pchFontSubInfo = NULL;
}
if(_rgtfi)
{
FreePv(_rgtfi);
_rgtfi = NULL;
}
_ctfi = 0;
return;
#endif // NOFONTSUBINFO
}
/*
* CRTFConverter::ParseFontName(pchBuf, pchBufMax, pszName, bCharSet, fSetCharSet, ppchBufNew, chDelimiter)
*
* Purpose:
* Parses from the input buffer, pchBuf, a string of the form:
* {WS}*<font_name>{WS}*[,{WS}*<char_set>{WS}*]
* and sets:
* pszName = <font_name>
* bCharSet = <char_set>
* fSetCharSet = (bCharSet set by proc) ? TRUE : FALSE
* ppchBufNew = pointer to point in pchBuf after parsed font name
*
* Returns:
* BOOL TRUE if OK
*/
CRTFConverter::PARSEFONTNAME CRTFConverter::ParseFontName(TCHAR *pchBuf, //@parm IN: buffer
TCHAR *pchBufMax, //@parm IN: last char in buffer
TCHAR chDelimiter, //@parm IN: char which delimits font name
TCHAR **pszName, //@parm OUT: parsed font name
BYTE &bCharSet, //@parm OUT: parsed char set
BOOL &fSetCharSet, //@parm OUT: char set parsed?
TCHAR **ppchBufNew //@parm OUT: ptr to next font name in input buffer
) const
{
PARSEFONTNAME iRet = PFN_SUCCESS;
Assert(pchBuf);
Assert(pchBufMax);
Assert(pchBufMax >= pchBuf);
Assert(pszName);
Assert(ppchBufNew);
fSetCharSet = FALSE;
*pszName = pchBuf;
if(pchBuf > pchBufMax)
{
return PFN_EOF;
}
while(*pchBuf && *pchBuf != TEXT(',') && *pchBuf != chDelimiter)
{
pchBuf++;
if(pchBuf > pchBufMax)
{
return PFN_EOF;
}
}
TCHAR chTemp = *pchBuf;
*pchBuf = TEXT('\0');
RemoveAdditionalSpace(*pszName);
if(chTemp == TEXT(','))
{
TCHAR *szCharSet = ++pchBuf;
while(*pchBuf && *pchBuf != chDelimiter)
{
pchBuf++;
if(pchBuf > pchBufMax)
{
return PFN_EOF;
}
}
chTemp = *pchBuf;
if(chTemp != chDelimiter)
{
goto UnexpectedChar;
}
*pchBuf = TEXT('\0');
RemoveAdditionalSpace(szCharSet);
bCharSet = 0;
while(*szCharSet >= TEXT('0') && *szCharSet <= TEXT('9'))
{
bCharSet *= 10;
bCharSet += *szCharSet++ - TEXT('0');
}
fSetCharSet = TRUE;
// iRet = PFN_SUCCESS; (done above)
}
else if(chTemp == chDelimiter)
{
// fSetCharSet = FALSE; (done above)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -