Module: wine Branch: master Commit: 2ce799c4f6099625aad2f9cb958bb0402bbda648 URL: http://source.winehq.org/git/wine.git/?a=commit;h=2ce799c4f6099625aad2f9cb95...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Aug 8 20:35:24 2007 +0200
user32: Support for the magic WM_CHAR W->A conversion in Get/PeekMessage.
---
dlls/user32/message.c | 85 +++++++++++++++++++++++++++++++------------- dlls/user32/tests/msg.c | 68 +++++++++++++++++++++++++++++++++++ dlls/user32/user_private.h | 1 + 3 files changed, 129 insertions(+), 25 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index bd6c103..c89a7ff 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -307,6 +307,18 @@ static inline BOOL check_hwnd_filter( const MSG *msg, HWND hwnd_filter ) return (msg->hwnd == hwnd_filter || IsChild( hwnd_filter, msg->hwnd )); }
+/* check for pending WM_CHAR message with DBCS trailing byte */ +static inline BOOL get_pending_wmchar( MSG *msg, UINT first, UINT last, BOOL remove ) +{ + struct wm_char_mapping_data *data = get_user_thread_info()->wmchar_data; + + if (!data || !data->get_msg.message) return FALSE; + if ((first || last) && (first > WM_CHAR || last < WM_CHAR)) return FALSE; + if (!msg) return FALSE; + *msg = data->get_msg; + if (remove) data->get_msg.message = 0; + return TRUE; +}
/*********************************************************************** * broadcast_message_callback @@ -435,39 +447,60 @@ BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping * * Convert the wparam of a Unicode message to ASCII. */ -static WPARAM map_wparam_WtoA( UINT message, WPARAM wparam ) +static void map_wparam_WtoA( MSG *msg, BOOL remove ) { - switch(message) + BYTE ch[2]; + WCHAR wch[2]; + DWORD len; + + switch(msg->message) { + case WM_CHAR: + if (!HIWORD(msg->wParam)) + { + wch[0] = LOWORD(msg->wParam); + ch[0] = ch[1] = 0; + RtlUnicodeToMultiByteN( (LPSTR)ch, 2, &len, wch, sizeof(wch[0]) ); + if (len == 2) /* DBCS char */ + { + struct wm_char_mapping_data *data = get_user_thread_info()->wmchar_data; + if (!data) + { + if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return; + get_user_thread_info()->wmchar_data = data; + } + if (remove) + { + data->get_msg = *msg; + data->get_msg.wParam = ch[1]; + } + msg->wParam = ch[0]; + return; + } + } + /* else fall through */ case WM_CHARTOITEM: case EM_SETPASSWORDCHAR: - case WM_CHAR: case WM_DEADCHAR: case WM_SYSCHAR: case WM_SYSDEADCHAR: case WM_MENUCHAR: - { - WCHAR wch[2]; - BYTE ch[2]; - wch[0] = LOWORD(wparam); - wch[1] = HIWORD(wparam); - WideCharToMultiByte( CP_ACP, 0, wch, 2, (LPSTR)ch, 2, NULL, NULL ); - wparam = MAKEWPARAM( ch[0] | (ch[1] << 8), 0 ); - } + wch[0] = LOWORD(msg->wParam); + wch[1] = HIWORD(msg->wParam); + ch[0] = ch[1] = 0; + RtlUnicodeToMultiByteN( (LPSTR)ch, 2, NULL, wch, sizeof(wch) ); + msg->wParam = MAKEWPARAM( ch[0] | (ch[1] << 8), 0 ); break; case WM_IME_CHAR: - { - WCHAR wch = LOWORD(wparam); - BYTE ch[2]; - - if (WideCharToMultiByte( CP_ACP, 0, &wch, 1, (LPSTR)ch, 2, NULL, NULL ) == 2) - wparam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wparam) ); - else - wparam = MAKEWPARAM( ch[0], HIWORD(wparam) ); - } + wch[0] = LOWORD(msg->wParam); + ch[0] = ch[1] = 0; + RtlUnicodeToMultiByteN( (LPSTR)ch, 2, &len, wch, sizeof(wch[0]) ); + if (len == 2) + msg->wParam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(msg->wParam) ); + else + msg->wParam = MAKEWPARAM( ch[0], HIWORD(msg->wParam) ); break; } - return wparam; }
@@ -2876,9 +2909,10 @@ BOOL WINAPI PeekMessageW( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT f */ BOOL WINAPI PeekMessageA( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags ) { - BOOL ret = PeekMessageW( msg, hwnd, first, last, flags ); - if (ret) msg->wParam = map_wparam_WtoA( msg->message, msg->wParam ); - return ret; + if (get_pending_wmchar( msg, first, last, (flags & PM_REMOVE) )) return TRUE; + if (!PeekMessageW( msg, hwnd, first, last, flags )) return FALSE; + map_wparam_WtoA( msg, (flags & PM_REMOVE) ); + return TRUE; }
@@ -2940,8 +2974,9 @@ BOOL WINAPI GetMessageW( MSG *msg, HWND hwnd, UINT first, UINT last ) */ BOOL WINAPI GetMessageA( MSG *msg, HWND hwnd, UINT first, UINT last ) { + if (get_pending_wmchar( msg, first, last, TRUE )) return TRUE; GetMessageW( msg, hwnd, first, last ); - msg->wParam = map_wparam_WtoA( msg->message, msg->wParam ); + map_wparam_WtoA( msg, TRUE ); return (msg->message != WM_QUIT); }
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index d51cf91..336cdce 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -9281,6 +9281,8 @@ static void test_dbcs_wm_char(void) WCHAR wch, bad_wch; HWND hwnd, hwnd2; MSG msg; + DWORD time; + POINT pt; DWORD_PTR res; CPINFOEXA cpinfo; UINT i, j, k; @@ -9481,6 +9483,72 @@ static void test_dbcs_wm_char(void) ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
+ /* test retrieving messages */ + + PostMessageW( hwnd, WM_CHAR, wch, 0 ); + ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message ); + + /* message filters */ + PostMessageW( hwnd, WM_CHAR, wch, 0 ); + ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + /* message id is filtered, hwnd is not */ + ok( !PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ), "no message\n" ); + ok( PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message ); + + /* mixing GetMessage and PostMessage */ + PostMessageW( hwnd, WM_CHAR, wch, 0xbeef ); + ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); + time = msg.time; + pt = msg.pt; + ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time ); + ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); + ok( msg.time == time, "bad time %x/%x\n", msg.time, time ); + ok( msg.pt.x == pt.x && msg.pt.y == pt.y, "bad point %u,%u/%u,%u\n", msg.pt.x, msg.pt.y, pt.x, pt.y ); + ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message ); + + /* without PM_REMOVE */ + PostMessageW( hwnd, WM_CHAR, wch, 0 ); + ok( PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" ); + ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); + ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); + ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); + ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message ); + DestroyWindow(hwnd); }
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 85039fd..fd46832 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -185,6 +185,7 @@ enum wm_char_mapping struct wm_char_mapping_data { BYTE lead_byte[WMCHAR_MAP_COUNT]; + MSG get_msg; };
/* this is the structure stored in TEB->Win32ClientInfo */