[2/2] riched20: Split unicode and ansi window procs, handle messages depending on the unicode flag. Add a hack for WM_GETTEXT in RichEdit20W class when running in win9x emulation mode

Dmitry Timoshkov dmitry at codeweavers.com
Thu Mar 22 06:09:43 CDT 2007


Hello,

this patch should fix the problem reported in the bug xxxx.

Changelog:
    riched20: Split unicode and ansi window procs, handle messages depending
    on the unicode flag. Add a hack for WM_GETTEXT in RichEdit20W class when
    running in win9x emulation mode.

---
 dlls/riched20/editor.c       |   91 +++++++++++++++++++++++++++--------------
 dlls/riched20/editor.h       |    6 +--
 dlls/riched20/string.c       |   27 ++-----------
 dlls/riched20/tests/editor.c |   32 +++++++++++----
 4 files changed, 90 insertions(+), 66 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 6b09b26..2e2c549 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1413,17 +1413,16 @@ get_msg_name(UINT msg)
   return "";
 }
 
-/******************************************************************
- *        RichEditANSIWndProc (RICHED20.10)
- */
-LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
+                                      LPARAM lParam, BOOL unicode)
+{
   ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0);
   
-  TRACE("hWnd %p msg %04x (%s) %08x %08lx\n",
-        hWnd, msg, get_msg_name(msg), wParam, lParam);
+  TRACE("hwnd %p msg %04x (%s) %x %lx, unicode %d\n",
+        hWnd, msg, get_msg_name(msg), wParam, lParam, unicode);
   
   if (!editor && msg != WM_NCCREATE && msg != WM_NCDESTROY) {
-    ERR("RichEditANSIWndProc called with invalid hWnd %p - application bug?\n", hWnd);
+    ERR("called with invalid hWnd %p - application bug?\n", hWnd);
     return 0; 
   }
 
@@ -1490,7 +1489,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     TRACE("WM_NCCREATE: style 0x%08x\n", pcs->style);
     editor = ME_MakeEditor(hWnd);
     SetWindowLongPtrW(hWnd, 0, (LONG_PTR)editor);
-    pcs = 0; /* ignore */
     return TRUE;
   }
   case EM_EMPTYUNDOBUFFER:
@@ -1817,7 +1815,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   {
     int from, to;
     ME_Style *style;
-    LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
+    LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
     size_t len = lstrlenW(wszText);
     TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
 
@@ -1833,7 +1831,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
      */
     if (len>0 && wszText[len-1] == '\n')
       ME_ClearTempStyle(editor);
-    ME_EndToUnicode(hWnd, wszText);
+    ME_EndToUnicode(unicode, wszText);
     ME_CommitUndo(editor);
     if (!wParam)
       ME_EmptyUndoStack(editor);
@@ -1885,21 +1883,21 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     if (lParam)
     {
       TRACE("WM_SETTEXT lParam==%lx\n",lParam);
-      if (!IsWindowUnicode(hWnd) && !strncmp((char *)lParam, "{\\rtf", 5))
+      if (!unicode && !strncmp((char *)lParam, "{\\rtf", 5))
       {
         /* Undocumented: WM_SETTEXT supports RTF text */
         ME_StreamInRTFString(editor, 0, (char *)lParam);
       }
       else
       {
-        LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
+        LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
         TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */
         if (lstrlenW(wszText) > 0)
         {
           /* uses default style! */
           ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
         }
-        ME_EndToUnicode(hWnd, wszText);
+        ME_EndToUnicode(unicode, wszText);
       }
     }
     else
@@ -1980,9 +1978,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   {
     TEXTRANGEW tr; /* W and A differ only by rng->lpstrText */
     tr.chrg.cpMin = 0;
-    tr.chrg.cpMax = wParam-1;
+    tr.chrg.cpMax = wParam ? (wParam - 1) : 0;
     tr.lpstrText = (WCHAR *)lParam;
-    return RichEditANSIWndProc(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
+    return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode);
   }
   case EM_GETTEXTEX:
   {
@@ -2003,7 +2001,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
       nStart = 0;
       nCount = ex->cb - 1;
     }
-    if (ex->codepage == 1200 || IsWindowUnicode(hWnd))
+    if (ex->codepage == 1200 || unicode)
     {
       nCount = min(nCount, ex->cb / sizeof(WCHAR) - 1);
       return ME_GetTextW(editor, (LPWSTR)lParam, nStart, nCount, ex->flags & GT_USECRLF);
@@ -2033,7 +2031,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     tr.chrg.cpMin = from;
     tr.chrg.cpMax = to;
     tr.lpstrText = (WCHAR *)lParam;
-    return RichEditANSIWndProc(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
+    return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode);
   }
   case EM_GETSCROLLPOS:
   {
@@ -2046,9 +2044,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   {
     TEXTRANGEW *rng = (TEXTRANGEW *)lParam;
     TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d emul1.0=%d length=%d\n",
-      rng->chrg.cpMin, rng->chrg.cpMax, IsWindowUnicode(hWnd), 
+      rng->chrg.cpMin, rng->chrg.cpMax, unicode,
       editor->bEmulateVersion10, ME_GetTextLength(editor));
-    if (IsWindowUnicode(hWnd))
+    if (unicode)
       return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, editor->bEmulateVersion10);
     else
     {
@@ -2066,7 +2064,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   case EM_GETLINE:
   {
     ME_DisplayItem *run;
-    const BOOL bUnicode = IsWindowUnicode(hWnd);
     const unsigned int nMaxChars = *(WORD *) lParam;
     unsigned int nEndChars, nCharsLeft = nMaxChars;
     char *dest = (char *) lParam;
@@ -2075,7 +2072,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     int nLF = editor->bEmulateVersion10;
 
     TRACE("EM_GETLINE: row=%d, nMaxChars=%d (%s)\n", (int) wParam, nMaxChars,
-          bUnicode ? "Unicode" : "Ansi");
+          unicode ? "Unicode" : "Ansi");
 
     run = ME_FindRowWithNumber(editor, wParam);
     if (run == NULL)
@@ -2091,19 +2088,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
       strText = run->member.run.strText;
       nCopy = min(nCharsLeft, strText->nLen);
 
-      if (bUnicode)
+      if (unicode)
         lstrcpynW((LPWSTR) dest, strText->szData, nCopy);
       else
         nCopy = WideCharToMultiByte(CP_ACP, 0, strText->szData, nCopy, dest,
                                     nCharsLeft, NULL, NULL);
-      dest += nCopy * (bUnicode ? sizeof(WCHAR) : 1);
+      dest += nCopy * (unicode ? sizeof(WCHAR) : 1);
       nCharsLeft -= nCopy;
     }
 
     /* append \r\0 (or \r\n\0 in 1.0), space allowing */
     nEndChars = min(nCharsLeft, 2 + nLF);
     nCharsLeft -= nEndChars;
-    if (bUnicode)
+    if (unicode)
     {
       const WCHAR src[] = {'\r', '\0'};
       const WCHAR src10[] = {'\r', '\n', '\0'};
@@ -2362,7 +2359,15 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     goto do_default;
   case WM_CHAR: 
   {
-    WCHAR wstr = LOWORD(wParam);
+    WCHAR wstr;
+
+    if (unicode)
+        wstr = (WCHAR)wParam;
+    else
+    {
+        CHAR charA = wParam;
+        MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1);
+    }
     if (editor->AutoURLDetect_bEnable)
       ME_AutoURLDetect(editor, wstr);
         
@@ -2532,7 +2537,8 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     LRESULT ret;
     int mask = 0;
     int changes = 0;
-    if ((ret = RichEditANSIWndProc(hWnd, WM_GETTEXTLENGTH, 0, 0)) == 0)
+    ret = RichEditWndProc_common(hWnd, WM_GETTEXTLENGTH, 0, 0, unicode);
+    if (!ret)
     {
       /*Check for valid wParam*/
       if ((((wParam & TM_RICHTEXT) && ((wParam & TM_PLAINTEXT) << 1))) ||
@@ -2566,6 +2572,29 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   return 0L;
 }
 
+static LRESULT WINAPI RichEditWndProcW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    BOOL unicode = TRUE;
+
+    /* Under Win9x RichEdit20W returns ANSI strings, see the tests. */
+    if (msg == WM_GETTEXT && (GetVersion() & 0x80000000))
+        unicode = FALSE;
+
+    return RichEditWndProc_common(hWnd, msg, wParam, lParam, unicode);
+}
+
+static LRESULT WINAPI RichEditWndProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    return RichEditWndProc_common(hWnd, msg, wParam, lParam, FALSE);
+}
+
+/******************************************************************
+ *        RichEditANSIWndProc (RICHED20.10)
+ */
+LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    return RichEditWndProcA(hWnd, msg, wParam, lParam);
+}
 
 /******************************************************************
  *        RichEdit10ANSIWndProc (RICHED20.9)
@@ -2648,7 +2677,7 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
   WCHAR *pStart = buffer;
   
   if (!item) {
-    *buffer = L'\0';
+    *buffer = 0;
     return 0;
   }
   
@@ -2700,12 +2729,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
     if (!nChars)
     {
       TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart);
-      *buffer = L'\0';
+      *buffer = 0;
       return nWritten;
     }
     item = ME_FindItemFwd(item, diRun);
   }
-  *buffer = L'\0';
+  *buffer = 0;
   TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart);
   return nWritten;  
 }
@@ -2716,7 +2745,7 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance)
   WNDCLASSA wcA;
   
   wcW.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
-  wcW.lpfnWndProc = RichEditANSIWndProc;
+  wcW.lpfnWndProc = RichEditWndProcW;
   wcW.cbClsExtra = 0;
   wcW.cbWndExtra = sizeof(ME_TextEditor *);
   wcW.hInstance = NULL; /* hInstance would register DLL-local class */
@@ -2742,7 +2771,7 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance)
   }
 
   wcA.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
-  wcA.lpfnWndProc = RichEditANSIWndProc;
+  wcA.lpfnWndProc = RichEditWndProcA;
   wcA.cbClsExtra = 0;
   wcA.cbWndExtra = sizeof(ME_TextEditor *);
   wcA.hInstance = NULL; /* hInstance would register DLL-local class */
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 8329203..f71842b 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -115,10 +115,8 @@ int ME_VPosToPos(ME_String *s, int nVPos);
 int ME_PosToVPos(ME_String *s, int nPos);
 void ME_StrDeleteV(ME_String *s, int nVChar, int nChars);
 /* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */
-LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz);
-void ME_EndToUnicode(HWND hWnd, LPVOID psz);
-LPSTR ME_ToAnsi(HWND hWnd, LPVOID psz);
-void ME_EndToAnsi(HWND hWnd, LPVOID psz);
+LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz);
+void ME_EndToUnicode(BOOL unicode, LPVOID psz);
 
 static inline int ME_IsWSpace(WCHAR ch)
 {
diff --git a/dlls/riched20/string.c b/dlls/riched20/string.c
index fd65252..4c44911 100644
--- a/dlls/riched20/string.c
+++ b/dlls/riched20/string.c
@@ -345,9 +345,9 @@ ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code)
     return editor->pfnWordBreak(str->szData, start, str->nLen, code);
 }
 
-LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
+LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
 {
-  if (IsWindowUnicode(hWnd))
+  if (unicode)
     return (LPWSTR)psz;
   else {
     WCHAR *tmp;
@@ -358,27 +358,8 @@ LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
   }
 }
 
-void ME_EndToUnicode(HWND hWnd, LPVOID psz)
+void ME_EndToUnicode(BOOL unicode, LPVOID psz)
 {
-  if (!IsWindowUnicode(hWnd))
-    FREE_OBJ(psz);
-}
-
-LPSTR ME_ToAnsi(HWND hWnd, LPVOID psz)
-{
-  if (!IsWindowUnicode(hWnd))
-    return (LPSTR)psz;
-  else {
-    char *tmp;
-    int nChars = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)psz, -1, NULL, 0, NULL, NULL);
-    if((tmp = ALLOC_N_OBJ(char, nChars)) != NULL)
-      WideCharToMultiByte(CP_ACP, 0, (WCHAR *)psz, -1, tmp, nChars, NULL, NULL);
-    return tmp;
-  }
-}
-
-void ME_EndToAnsi(HWND hWnd, LPVOID psz)
-{
-  if (!IsWindowUnicode(hWnd))
+  if (!unicode)
     FREE_OBJ(psz);
 }
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 2d66f74..71e82cb 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -1578,16 +1578,13 @@ static void test_unicode_conversions(void)
         ret = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)txt); \
         ok(ret, "SendMessageA(WM_SETTEXT) error %u\n", GetLastError()); \
     } while(0)
-#define expect_textA(hwnd, txt, todo) \
+#define expect_textA(hwnd, txt) \
     do { \
         memset(bufA, 0xAA, sizeof(bufA)); \
         ret = SendMessageA(hwnd, WM_GETTEXT, 64, (LPARAM)bufA); \
         ok(ret, "SendMessageA(WM_GETTEXT) error %u\n", GetLastError()); \
         ret = lstrcmpA(bufA, txt); \
-        if (todo) \
-            todo_wine ok(!ret, "strings not match: expected %s got %s\n", txt, bufA); \
-        else \
-            ok(!ret, "strings not match: expected %s got %s\n", txt, bufA); \
+        ok(!ret, "strings not match: expected %s got %s\n", txt, bufA); \
     } while(0)
 
 #define set_textW(hwnd, txt) \
@@ -1601,7 +1598,7 @@ static void test_unicode_conversions(void)
         ret = SendMessageW(hwnd, WM_GETTEXT, 64, (LPARAM)bufW); \
         ok(ret, "SendMessageW(WM_GETTEXT) error %u\n", GetLastError()); \
         ret = lstrcmpW(bufW, txt); \
-        ok(!ret, "strings not match\n"); \
+        ok(!ret, "strings not match expected[0] %x got[0] %x\n", txt[0], bufW[0]); \
     } while(0)
 
     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
@@ -1614,11 +1611,30 @@ static void test_unicode_conversions(void)
     else
         ok(ret, "RichEdit20W should be unicode under NT\n");
 
+    memset(bufA, 0xAA, sizeof(bufA));
+    ret = SendMessageA(hwnd, WM_GETTEXT, 64, (LPARAM)bufA);
+    ok(!ret, "empty richedit should return 0, got %d\n", ret);
+    ok(!*bufA, "empty richedit should return empty string, got %s\n", bufA);
+
+    ret = SendMessageA(hwnd, WM_CHAR, (WPARAM)textW[0], 0);
+    ok(!ret, "SendMessageA(WM_CHAR) should return 0, got %d\n", ret);
+    expect_textA(hwnd, "t");
+
+    ret = SendMessageA(hwnd, WM_CHAR, (WPARAM)textA[1], 0);
+    ok(!ret, "SendMessageA(WM_CHAR) should return 0, got %d\n", ret);
+    expect_textA(hwnd, "te");
+
+    set_textA(hwnd, NULL);
+    memset(bufA, 0xAA, sizeof(bufA));
+    ret = SendMessageA(hwnd, WM_GETTEXT, 64, (LPARAM)bufA);
+    ok(!ret, "empty richedit should return 0, got %d\n", ret);
+    ok(!*bufA, "empty richedit should return empty string, got %s\n", bufA);
+
     if (is_win9x)
         set_textA(hwnd, textW);
     else
         set_textA(hwnd, textA);
-    expect_textA(hwnd, textA, is_win9x);
+    expect_textA(hwnd, textA);
 
     if (!is_win9x)
     {
@@ -1635,7 +1651,7 @@ static void test_unicode_conversions(void)
     ok(!ret, "RichEdit20A should NOT be unicode\n");
 
     set_textA(hwnd, textA);
-    expect_textA(hwnd, textA, FALSE);
+    expect_textA(hwnd, textA);
 
     if (!is_win9x)
     {
-- 
1.5.0.5






More information about the wine-patches mailing list