RICHEDIT: RTF codepage handling fixes

Phil Krylov phil at newstar.rinet.ru
Mon Mar 21 15:28:23 CST 2005


ChangeLog:

Made RTF reader and writer handle codepages mostly similar to the original
riched20.dll.

Patch:

Index: dlls/riched20/editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.c,v
retrieving revision 1.19
diff -p -u -r1.19 editor.c
--- dlls/riched20/editor.c	21 Mar 2005 10:52:26 -0000	1.19
+++ dlls/riched20/editor.c	21 Mar 2005 21:14:40 -0000
@@ -336,7 +336,8 @@ void ME_RTFCharAttrHook(RTF_Info *info)
         {
           MultiByteToWideChar(CP_ACP, 0, f->rtfFName, -1, fmt.szFaceName, sizeof(fmt.szFaceName)/sizeof(WCHAR));
           fmt.szFaceName[sizeof(fmt.szFaceName)/sizeof(WCHAR)-1] = '\0';
-          fmt.dwMask = CFM_FACE;
+          fmt.bCharSet = f->rtfFCharSet;
+          fmt.dwMask = CFM_FACE | CFM_CHARSET;
         }
       }
       break;
Index: dlls/riched20/editstr.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editstr.h,v
retrieving revision 1.7
diff -p -u -r1.7 editstr.h
--- dlls/riched20/editstr.h	21 Mar 2005 10:27:24 -0000	1.7
+++ dlls/riched20/editstr.h	21 Mar 2005 21:14:41 -0000
@@ -211,6 +211,7 @@ typedef struct tagME_OutStream {
   UINT nColorTblLen;
   COLORREF colortbl[STREAMOUT_COLORTBL_SIZE];
   UINT nDefaultFont;
+  UINT nDefaultCodePage;
 } ME_OutStream;
 
 typedef struct tagME_FontCacheItem
Index: dlls/riched20/reader.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/reader.c,v
retrieving revision 1.10
diff -p -u -r1.10 reader.c
--- dlls/riched20/reader.c	21 Mar 2005 11:24:38 -0000	1.10
+++ dlls/riched20/reader.c	21 Mar 2005 21:14:42 -0000
@@ -260,8 +260,7 @@ void RTFInit(RTF_Info *info)
 
 	RTFDestroyAttrs(info);
 
-	info->ansiCodePage = 1252; /* Latin-1 */
-
+        info->ansiCodePage = 1252; /* Latin-1; actually unused */
 	info->unicodeLength = 1; /* \uc1 is the default */
 	info->codePage = info->ansiCodePage;
 
@@ -555,14 +554,15 @@ static void _RTFGetToken(RTF_Info *info)
 }
 
 
-static int
+int
 RTFCharSetToCodePage(RTF_Info *info, int charset)
 {
 	switch (charset)
         {
                 case ANSI_CHARSET:
+                        return 1252;
                 case DEFAULT_CHARSET:
-                        return info->ansiCodePage;
+                        return CP_ACP;
                 case SYMBOL_CHARSET:
                         return CP_SYMBOL;
                 case MAC_CHARSET:
@@ -605,7 +605,7 @@ RTFCharSetToCodePage(RTF_Info *info, int
                         /* FIXME: TranslateCharsetInfo does not work as good as it
                          * should, so let's use it only when all else fails */
                         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
                                 return csi.ciACP;
 		}
@@ -915,10 +915,10 @@ static void ReadFontTbl(RTF_Info *info)
 		fp->rtfFAltName = NULL;
 		fp->rtfFNum = -1;
 		fp->rtfFFamily = 0;
-		fp->rtfFCharSet = 0;
+		fp->rtfFCharSet = DEFAULT_CHARSET; /* 1 */
 		fp->rtfFPitch = 0;
 		fp->rtfFType = 0;
-		fp->rtfFCodePage = 0;
+		fp->rtfFCodePage = CP_ACP;
 
 		while (info->rtfClass != rtfEOF
 		       && !RTFCheckCM (info, rtfText, ';')
@@ -2407,13 +2407,9 @@ int RTFHexToChar(int i)
 /* ---------------------------------------------------------------------- */
 
 /*
- * Print message.  Default is to send message to stderr
- * but this may be overridden with RTFSetMsgProc().
+ * Print message.
  *
- * Message should include linefeeds as necessary.  If the default
- * 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.
+ * Message should include linefeeds as necessary.
  */
 
 
@@ -2549,7 +2545,10 @@ CharAttr(RTF_Info *info)
         case rtfFontNum:
                 font = RTFGetFont(info, info->rtfParam);
                 if (font)
-                        info->codePage = font->rtfFCodePage;
+                {
+                        if (info->ansiCodePage != CP_UTF8)
+                                info->codePage = font->rtfFCodePage;
+                }
                 else
                         RTFMsg(info, "unknown font %d\n", info->rtfParam);
                 break;
Index: dlls/riched20/rtf.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/rtf.h,v
retrieving revision 1.8
diff -p -u -r1.8 rtf.h
--- dlls/riched20/rtf.h	21 Mar 2005 11:24:38 -0000	1.8
+++ dlls/riched20/rtf.h	21 Mar 2005 21:14:42 -0000
@@ -1160,4 +1160,6 @@ void	RTFSetEditStream(RTF_Info *, EDITST
 void	WriterInit (RTF_Info *);
 int	BeginFile (RTF_Info *);
 
+int	RTFCharSetToCodePage(RTF_Info *info, int charset);
+
 #endif
Index: dlls/riched20/writer.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/writer.c,v
retrieving revision 1.3
diff -p -u -r1.3 writer.c
--- dlls/riched20/writer.c	16 Mar 2005 20:18:11 -0000	1.3
+++ dlls/riched20/writer.c	21 Mar 2005 21:14:43 -0000
@@ -19,6 +19,7 @@
  */
 
 #include "editor.h"
+#include "rtf.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
@@ -149,6 +150,10 @@ ME_StreamOutRTFHeader(ME_TextEditor *edi
     }
   } else {
     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();
   }
   if (nCodePage == CP_UTF8)
@@ -159,7 +164,7 @@ ME_StreamOutRTFHeader(ME_TextEditor *edi
   if (!success)
     return FALSE;
 
-  editor->pStream->nCodePage = nCodePage;
+  editor->pStream->nDefaultCodePage = nCodePage;
   
   /* FIXME: This should be a document property */
   /* TODO: handle SFF_PLAINRTF */
@@ -187,7 +192,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEd
 
     if (fmt->dwMask & CFM_FACE) {
       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++)
         if (table[i].bCharSet == bCharSet
@@ -230,7 +235,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_TextEd
     return FALSE;
   
   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))
         return FALSE;
     } else {
@@ -520,7 +525,19 @@ ME_StreamOutRTFCharProps(ME_TextEditor *
           break;
     }
     if (i < editor->pStream->nFontTblLen && i != editor->pStream->nDefaultFont)
+    {
       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)
     strcat(props, " ");
@@ -541,7 +558,8 @@ ME_StreamOutRTFText(ME_TextEditor *edito
     nChars = lstrlenW(text);
   
   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 */
       fit = min(nChars, STREAMOUT_BUFFER_SIZE / 6);
       WideCharToMultiByte(CP_UTF8, 0, text, fit, buffer, STREAMOUT_BUFFER_SIZE,
@@ -565,22 +583,25 @@ ME_StreamOutRTFText(ME_TextEditor *edito
       nChars--;
     } else {
       BOOL unknown;
-      BYTE letter[2];
+      BYTE letter[3];
+      int nBytes, i;
       
-      WideCharToMultiByte(editor->pStream->nCodePage, 0, text, 1, letter, 2,
-                          NULL, &unknown);
+      nBytes = WideCharToMultiByte(editor->pStream->nCodePage, 0, text, 1,
+                                   letter, 3, NULL, &unknown);
       if (unknown)
         pos += sprintf(buffer + pos, "\\u%d?", (int)*text);
       else if (*letter < 128) {
         if (*letter == '{' || *letter == '}' || *letter == '\\')
           buffer[pos++] = '\\';
         buffer[pos++] = *letter;
-      } else
-        pos += sprintf(buffer + pos, "\\'%02x", *letter);
+      } else {
+         for (i = 0; i < nBytes; i++)
+           pos += sprintf(buffer + pos, "\\'%02x", letter[i]);
+      }
       text++;
       nChars--;
     }
-    if (pos >= STREAMOUT_BUFFER_SIZE - 10) {
+    if (pos >= STREAMOUT_BUFFER_SIZE - 11) {
       if (!ME_StreamOutMove(editor, buffer, pos))
         return FALSE;
       pos = 0;



More information about the wine-patches mailing list