From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 58 +++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/keyboard.c | 2 +- dlls/winex11.drv/x11drv.h | 2 +- dlls/winex11.drv/xim.c | 23 +++++++++++++-- include/ntuser.h | 1 + 5 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 472407e7e7a..5ddc8973c2d 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -42,6 +42,7 @@ static const char *debugstr_imn( WPARAM wparam ) case IMN_SETSTATUSWINDOWPOS: return "IMN_SETSTATUSWINDOWPOS"; case IMN_WINE_SET_OPEN_STATUS: return "IMN_WINE_SET_OPEN_STATUS"; case IMN_WINE_GET_CURSOR_POS: return "IMN_WINE_GET_CURSOR_POS"; + case IMN_WINE_SET_COMP_STRING: return "IMN_WINE_SET_COMP_STRING"; default: return wine_dbg_sprintf( "%#Ix", wparam ); } } @@ -263,6 +264,61 @@ static UINT ime_get_cursor_pos( HIMC himc ) return pos; }
+static UINT ime_set_comp_string( HIMC himc, LPARAM lparam ) +{ + union + { + struct + { + UINT uMsgCount; + TRANSMSG TransMsg[10]; + }; + TRANSMSGLIST list; + } buffer = {.uMsgCount = ARRAY_SIZE(buffer.TransMsg)}; + COMPOSITIONSTRING *compstr; + INPUTCONTEXT *ctx; + TRANSMSG *msgs; + HIMCC himcc; + UINT count; + + TRACE( "himc %p\n", himc ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + + if (!(himcc = ImmReSizeIMCC( ctx->hCompStr, sizeof(*compstr) + sizeof(lparam) ))) + WARN( "Failed to resize input context composition string\n" ); + else if (!(compstr = ImmLockIMCC( (ctx->hCompStr = himcc) ))) + WARN( "Failed to lock input context composition string\n" ); + else + { + memset( compstr, 0, sizeof(*compstr) ); + compstr->dwSize = sizeof(*compstr) + sizeof(lparam); + compstr->dwPrivateSize = sizeof(lparam); + compstr->dwPrivateOffset = compstr->dwSize - sizeof(lparam); + memcpy( (BYTE *)compstr + compstr->dwPrivateOffset, &lparam, sizeof(lparam) ); + ImmUnlockIMCC( ctx->hCompStr ); + } + + count = ImeToAsciiEx( VK_PROCESSKEY, 0, NULL, &buffer.list, 0, himc ); + if (count >= buffer.uMsgCount) + WARN( "ImeToAsciiEx returned %#x messages\n", count ); + else if (!(himcc = ImmReSizeIMCC( ctx->hMsgBuf, (ctx->dwNumMsgBuf + count) * sizeof(*msgs) ))) + WARN( "Failed to resize input context message buffer\n" ); + else if (!(msgs = ImmLockIMCC( (ctx->hMsgBuf = himcc) ))) + WARN( "Failed to lock input context message buffer\n" ); + else + { + memcpy( msgs + ctx->dwNumMsgBuf, buffer.TransMsg, count * sizeof(*msgs) ); + ImmUnlockIMCC( ctx->hMsgBuf ); + ctx->dwNumMsgBuf += count; + } + + ImmUnlockIMC( himc ); + ImmGenerateMessage( himc ); + + return 0; +} + static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam ) { TRACE( "himc %p, hwnd %p, wparam %s, lparam %#Ix\n", hwnd, himc, debugstr_imn(wparam), lparam ); @@ -273,6 +329,8 @@ static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam return ImmSetOpenStatus( himc, lparam ); case IMN_WINE_GET_CURSOR_POS: return ime_get_cursor_pos( himc ); + case IMN_WINE_SET_COMP_STRING: + return ime_set_comp_string( himc, lparam ); default: FIXME( "himc %p, hwnd %p, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_imn(wparam), lparam ); return 0; diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index b1c47d5258e..195cc65eddb 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1347,7 +1347,7 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
if (status == XLookupChars) { - X11DRV_XIMLookupChars( Str, ascii_chars ); + xim_set_result_string( hwnd, Str, ascii_chars ); if (buf != Str) free( Str ); return TRUE; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 05f576b8fb5..9768aea9f11 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -823,7 +823,7 @@ extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN; extern BOOL xim_init( const WCHAR *input_style ) DECLSPEC_HIDDEN; extern void xim_thread_attach( struct x11drv_thread_data *data ) DECLSPEC_HIDDEN; extern BOOL xim_in_compose_mode(void) DECLSPEC_HIDDEN; -extern void X11DRV_XIMLookupChars( const char *str, UINT count ) DECLSPEC_HIDDEN; +extern void xim_set_result_string( HWND hwnd, const char *str, UINT count ) DECLSPEC_HIDDEN; extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;
#define XEMBED_MAPPED (1 << 0) diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 5e5cac0026d..ae596e83662 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -42,6 +42,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim); #define XICProc XIMProc #endif
+struct ime_update +{ + DWORD cursor_pos; + WCHAR *comp_str; + WCHAR *result_str; +}; + static WCHAR *ime_comp_buf;
static XIMStyle input_style = 0; @@ -72,6 +79,12 @@ BOOL xim_in_compose_mode(void) return !!ime_comp_buf; }
+static void send_ime_composition_update( HWND hwnd, UINT cursor_pos, WCHAR *comp_str, WCHAR *result_str ) +{ + struct ime_update update = {.cursor_pos = cursor_pos, .comp_str = comp_str, .result_str = result_str}; + send_message( hwnd, WM_IME_NOTIFY, IMN_WINE_SET_COMP_STRING, (LPARAM)&update ); +} + static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text, UINT new_len ) { UINT len = ime_comp_buf ? wcslen( ime_comp_buf ) : 0; @@ -96,18 +109,20 @@ static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text x11drv_client_func( client_func_ime_set_composition_string, ime_comp_buf, len * sizeof(WCHAR) ); }
-void X11DRV_XIMLookupChars( const char *str, UINT count ) +void xim_set_result_string( HWND hwnd, const char *str, UINT count ) { WCHAR *output; DWORD len;
- TRACE("%p %u\n", str, count); + TRACE( "hwnd %p, string %s\n", hwnd, debugstr_an(str, count) );
if (!(output = malloc( (count + 1) * sizeof(WCHAR) ))) return; len = ntdll_umbstowcs( str, count, output, count ); output[len] = 0;
+ send_ime_composition_update( hwnd, -1, ime_comp_buf, output ); x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); + free( output ); }
@@ -141,6 +156,7 @@ static int xic_preedit_start( XIC xic, XPointer user, XPointer arg ) x11drv_client_call( client_ime_set_composition_status, TRUE ); if ((ime_comp_buf = realloc( ime_comp_buf, sizeof(WCHAR) ))) *ime_comp_buf = 0; else ERR( "Failed to allocate preedit buffer\n" ); + send_ime_composition_update( hwnd, -1, ime_comp_buf, NULL );
return -1; } @@ -151,6 +167,7 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
+ send_ime_composition_update( hwnd, -1, NULL, NULL ); free( ime_comp_buf ); ime_comp_buf = NULL;
@@ -192,6 +209,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg )
if (text && str != text->string.multi_byte) free( str );
+ send_ime_composition_update( hwnd, params->caret, ime_comp_buf, NULL ); x11drv_client_call( client_ime_set_cursor_pos, params->caret );
return 0; @@ -236,6 +254,7 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg ) break; } x11drv_client_call( client_ime_set_cursor_pos, pos ); + send_ime_composition_update( hwnd, pos, ime_comp_buf, NULL ); params->position = pos;
return 0; diff --git a/include/ntuser.h b/include/ntuser.h index db3d98e1315..1727350c891 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -493,6 +493,7 @@ enum wine_internal_message /* internal WM_IME_NOTIFY wparams, not compatible with Windows */ #define IMN_WINE_SET_OPEN_STATUS 0x000f #define IMN_WINE_GET_CURSOR_POS 0x0010 +#define IMN_WINE_SET_COMP_STRING 0x0011
/* internal IME private */ typedef struct ime_private