Made RTF reader and writer handle codepages mostly similar to the
original riched20.dll.
This commit is contained in:
parent
aa6367400a
commit
0fdbec319b
|
@ -336,7 +336,8 @@ void ME_RTFCharAttrHook(RTF_Info *info)
|
||||||
{
|
{
|
||||||
MultiByteToWideChar(CP_ACP, 0, f->rtfFName, -1, fmt.szFaceName, sizeof(fmt.szFaceName)/sizeof(WCHAR));
|
MultiByteToWideChar(CP_ACP, 0, f->rtfFName, -1, fmt.szFaceName, sizeof(fmt.szFaceName)/sizeof(WCHAR));
|
||||||
fmt.szFaceName[sizeof(fmt.szFaceName)/sizeof(WCHAR)-1] = '\0';
|
fmt.szFaceName[sizeof(fmt.szFaceName)/sizeof(WCHAR)-1] = '\0';
|
||||||
fmt.dwMask = CFM_FACE;
|
fmt.bCharSet = f->rtfFCharSet;
|
||||||
|
fmt.dwMask = CFM_FACE | CFM_CHARSET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -211,6 +211,7 @@ typedef struct tagME_OutStream {
|
||||||
UINT nColorTblLen;
|
UINT nColorTblLen;
|
||||||
COLORREF colortbl[STREAMOUT_COLORTBL_SIZE];
|
COLORREF colortbl[STREAMOUT_COLORTBL_SIZE];
|
||||||
UINT nDefaultFont;
|
UINT nDefaultFont;
|
||||||
|
UINT nDefaultCodePage;
|
||||||
} ME_OutStream;
|
} ME_OutStream;
|
||||||
|
|
||||||
typedef struct tagME_FontCacheItem
|
typedef struct tagME_FontCacheItem
|
||||||
|
|
|
@ -260,8 +260,7 @@ void RTFInit(RTF_Info *info)
|
||||||
|
|
||||||
RTFDestroyAttrs(info);
|
RTFDestroyAttrs(info);
|
||||||
|
|
||||||
info->ansiCodePage = 1252; /* Latin-1 */
|
info->ansiCodePage = 1252; /* Latin-1; actually unused */
|
||||||
|
|
||||||
info->unicodeLength = 1; /* \uc1 is the default */
|
info->unicodeLength = 1; /* \uc1 is the default */
|
||||||
info->codePage = info->ansiCodePage;
|
info->codePage = info->ansiCodePage;
|
||||||
|
|
||||||
|
@ -555,14 +554,15 @@ static void _RTFGetToken(RTF_Info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
int
|
||||||
RTFCharSetToCodePage(RTF_Info *info, int charset)
|
RTFCharSetToCodePage(RTF_Info *info, int charset)
|
||||||
{
|
{
|
||||||
switch (charset)
|
switch (charset)
|
||||||
{
|
{
|
||||||
case ANSI_CHARSET:
|
case ANSI_CHARSET:
|
||||||
|
return 1252;
|
||||||
case DEFAULT_CHARSET:
|
case DEFAULT_CHARSET:
|
||||||
return info->ansiCodePage;
|
return CP_ACP;
|
||||||
case SYMBOL_CHARSET:
|
case SYMBOL_CHARSET:
|
||||||
return CP_SYMBOL;
|
return CP_SYMBOL;
|
||||||
case MAC_CHARSET:
|
case MAC_CHARSET:
|
||||||
|
@ -605,7 +605,7 @@ RTFCharSetToCodePage(RTF_Info *info, int charset)
|
||||||
/* FIXME: TranslateCharsetInfo does not work as good as it
|
/* FIXME: TranslateCharsetInfo does not work as good as it
|
||||||
* should, so let's use it only when all else fails */
|
* should, so let's use it only when all else fails */
|
||||||
if (!TranslateCharsetInfo(&n, &csi, TCI_SRCCHARSET))
|
if (!TranslateCharsetInfo(&n, &csi, TCI_SRCCHARSET))
|
||||||
RTFMsg(info,"%s: unknown charset %u\n", __FUNCTION__, charset);
|
RTFMsg(info, "%s: unknown charset %u\n", __FUNCTION__, charset);
|
||||||
else
|
else
|
||||||
return csi.ciACP;
|
return csi.ciACP;
|
||||||
}
|
}
|
||||||
|
@ -915,10 +915,10 @@ static void ReadFontTbl(RTF_Info *info)
|
||||||
fp->rtfFAltName = NULL;
|
fp->rtfFAltName = NULL;
|
||||||
fp->rtfFNum = -1;
|
fp->rtfFNum = -1;
|
||||||
fp->rtfFFamily = 0;
|
fp->rtfFFamily = 0;
|
||||||
fp->rtfFCharSet = 0;
|
fp->rtfFCharSet = DEFAULT_CHARSET; /* 1 */
|
||||||
fp->rtfFPitch = 0;
|
fp->rtfFPitch = 0;
|
||||||
fp->rtfFType = 0;
|
fp->rtfFType = 0;
|
||||||
fp->rtfFCodePage = 0;
|
fp->rtfFCodePage = CP_ACP;
|
||||||
|
|
||||||
while (info->rtfClass != rtfEOF
|
while (info->rtfClass != rtfEOF
|
||||||
&& !RTFCheckCM (info, rtfText, ';')
|
&& !RTFCheckCM (info, rtfText, ';')
|
||||||
|
@ -2407,13 +2407,9 @@ int RTFHexToChar(int i)
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print message. Default is to send message to stderr
|
* Print message.
|
||||||
* but this may be overridden with RTFSetMsgProc().
|
|
||||||
*
|
*
|
||||||
* Message should include linefeeds as necessary. If the default
|
* Message should include linefeeds as necessary.
|
||||||
* function is overridden, the overriding function may want to
|
|
||||||
* map linefeeds to another line ending character or sequence if
|
|
||||||
* the host system doesn't use linefeeds.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -2549,7 +2545,10 @@ CharAttr(RTF_Info *info)
|
||||||
case rtfFontNum:
|
case rtfFontNum:
|
||||||
font = RTFGetFont(info, info->rtfParam);
|
font = RTFGetFont(info, info->rtfParam);
|
||||||
if (font)
|
if (font)
|
||||||
|
{
|
||||||
|
if (info->ansiCodePage != CP_UTF8)
|
||||||
info->codePage = font->rtfFCodePage;
|
info->codePage = font->rtfFCodePage;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
RTFMsg(info, "unknown font %d\n", info->rtfParam);
|
RTFMsg(info, "unknown font %d\n", info->rtfParam);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1160,4 +1160,6 @@ void RTFSetEditStream(RTF_Info *, EDITSTREAM *es);
|
||||||
void WriterInit (RTF_Info *);
|
void WriterInit (RTF_Info *);
|
||||||
int BeginFile (RTF_Info *);
|
int BeginFile (RTF_Info *);
|
||||||
|
|
||||||
|
int RTFCharSetToCodePage(RTF_Info *info, int charset);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
#include "rtf.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||||
|
|
||||||
|
@ -149,6 +150,10 @@ ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cCharSet = "ansi";
|
cCharSet = "ansi";
|
||||||
|
/* TODO: If the original document contained an \ansicpg value, retain it.
|
||||||
|
* Otherwise, M$ richedit emits a codepage number determined from the
|
||||||
|
* charset of the default font here. Anyway, this value is not used by
|
||||||
|
* the reader... */
|
||||||
nCodePage = GetACP();
|
nCodePage = GetACP();
|
||||||
}
|
}
|
||||||
if (nCodePage == CP_UTF8)
|
if (nCodePage == CP_UTF8)
|
||||||
|
@ -159,7 +164,7 @@ ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat)
|
||||||
if (!success)
|
if (!success)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
editor->pStream->nCodePage = nCodePage;
|
editor->pStream->nDefaultCodePage = nCodePage;
|
||||||
|
|
||||||
/* FIXME: This should be a document property */
|
/* FIXME: This should be a document property */
|
||||||
/* TODO: handle SFF_PLAINRTF */
|
/* TODO: handle SFF_PLAINRTF */
|
||||||
|
@ -187,7 +192,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun,
|
||||||
|
|
||||||
if (fmt->dwMask & CFM_FACE) {
|
if (fmt->dwMask & CFM_FACE) {
|
||||||
WCHAR *face = fmt->szFaceName;
|
WCHAR *face = fmt->szFaceName;
|
||||||
BYTE bCharSet = fmt->bCharSet;
|
BYTE bCharSet = (fmt->dwMask & CFM_CHARSET) ? fmt->bCharSet : DEFAULT_CHARSET;
|
||||||
|
|
||||||
for (i = 0; i < editor->pStream->nFontTblLen; i++)
|
for (i = 0; i < editor->pStream->nFontTblLen; i++)
|
||||||
if (table[i].bCharSet == bCharSet
|
if (table[i].bCharSet == bCharSet
|
||||||
|
@ -230,7 +235,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEditor *editor, ME_DisplayItem *pFirstRun,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < editor->pStream->nFontTblLen; i++) {
|
for (i = 0; i < editor->pStream->nFontTblLen; i++) {
|
||||||
if (table[i].bCharSet) {
|
if (table[i].bCharSet != DEFAULT_CHARSET) {
|
||||||
if (!ME_StreamOutPrint(editor, "{\\f%u\\fcharset%u ", i, table[i].bCharSet))
|
if (!ME_StreamOutPrint(editor, "{\\f%u\\fcharset%u ", i, table[i].bCharSet))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -520,7 +525,19 @@ ME_StreamOutRTFCharProps(ME_TextEditor *editor, CHARFORMAT2W *fmt)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i < editor->pStream->nFontTblLen && i != editor->pStream->nDefaultFont)
|
if (i < editor->pStream->nFontTblLen && i != editor->pStream->nDefaultFont)
|
||||||
|
{
|
||||||
sprintf(props + strlen(props), "\\f%u", i);
|
sprintf(props + strlen(props), "\\f%u", i);
|
||||||
|
|
||||||
|
/* In UTF-8 mode, charsets/codepages are not used */
|
||||||
|
if (editor->pStream->nDefaultCodePage != CP_UTF8)
|
||||||
|
{
|
||||||
|
if (editor->pStream->fonttbl[i].bCharSet == DEFAULT_CHARSET)
|
||||||
|
editor->pStream->nCodePage = editor->pStream->nDefaultCodePage;
|
||||||
|
else
|
||||||
|
editor->pStream->nCodePage = RTFCharSetToCodePage(NULL,
|
||||||
|
editor->pStream->fonttbl[i].bCharSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (*props)
|
if (*props)
|
||||||
strcat(props, " ");
|
strcat(props, " ");
|
||||||
|
@ -541,7 +558,8 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
||||||
nChars = lstrlenW(text);
|
nChars = lstrlenW(text);
|
||||||
|
|
||||||
while (nChars) {
|
while (nChars) {
|
||||||
if (editor->pStream->nCodePage == CP_UTF8) {
|
/* In UTF-8 mode, font charsets are not used. */
|
||||||
|
if (editor->pStream->nDefaultCodePage == CP_UTF8) {
|
||||||
/* 6 is the maximum character length in UTF-8 */
|
/* 6 is the maximum character length in UTF-8 */
|
||||||
fit = min(nChars, STREAMOUT_BUFFER_SIZE / 6);
|
fit = min(nChars, STREAMOUT_BUFFER_SIZE / 6);
|
||||||
WideCharToMultiByte(CP_UTF8, 0, text, fit, buffer, STREAMOUT_BUFFER_SIZE,
|
WideCharToMultiByte(CP_UTF8, 0, text, fit, buffer, STREAMOUT_BUFFER_SIZE,
|
||||||
|
@ -565,22 +583,25 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
|
||||||
nChars--;
|
nChars--;
|
||||||
} else {
|
} else {
|
||||||
BOOL unknown;
|
BOOL unknown;
|
||||||
BYTE letter[2];
|
BYTE letter[3];
|
||||||
|
int nBytes, i;
|
||||||
|
|
||||||
WideCharToMultiByte(editor->pStream->nCodePage, 0, text, 1, letter, 2,
|
nBytes = WideCharToMultiByte(editor->pStream->nCodePage, 0, text, 1,
|
||||||
NULL, &unknown);
|
letter, 3, NULL, &unknown);
|
||||||
if (unknown)
|
if (unknown)
|
||||||
pos += sprintf(buffer + pos, "\\u%d?", (int)*text);
|
pos += sprintf(buffer + pos, "\\u%d?", (int)*text);
|
||||||
else if (*letter < 128) {
|
else if (*letter < 128) {
|
||||||
if (*letter == '{' || *letter == '}' || *letter == '\\')
|
if (*letter == '{' || *letter == '}' || *letter == '\\')
|
||||||
buffer[pos++] = '\\';
|
buffer[pos++] = '\\';
|
||||||
buffer[pos++] = *letter;
|
buffer[pos++] = *letter;
|
||||||
} else
|
} else {
|
||||||
pos += sprintf(buffer + pos, "\\'%02x", *letter);
|
for (i = 0; i < nBytes; i++)
|
||||||
|
pos += sprintf(buffer + pos, "\\'%02x", letter[i]);
|
||||||
|
}
|
||||||
text++;
|
text++;
|
||||||
nChars--;
|
nChars--;
|
||||||
}
|
}
|
||||||
if (pos >= STREAMOUT_BUFFER_SIZE - 10) {
|
if (pos >= STREAMOUT_BUFFER_SIZE - 11) {
|
||||||
if (!ME_StreamOutMove(editor, buffer, pos))
|
if (!ME_StreamOutMove(editor, buffer, pos))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
Loading…
Reference in New Issue