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.
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 @@
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 @@
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 @@
{
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 @@
*/
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 @@
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 @@
{
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
WCHAR *pStart = buffer;
if (!item) {
- *buffer = L'\0';
+ *buffer = 0;
return 0;
}
@@ -2700,12 +2729,12 @@
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 @@
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 @@
}
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_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 @@
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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
ok(!ret, "RichEdit20A should NOT be unicode\n");
set_textA(hwnd, textA);
- expect_textA(hwnd, textA, FALSE);
+ expect_textA(hwnd, textA);
if (!is_win9x)
{