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) {