-- v2: winex11: Use the new helper to set COMPOSITIONSTRING text. winex11: Use EM_REPLACESEL to set IME composition strings. winex11: Always zero terminate XIM composition string. winex11: Compute preedit text buffer sizes in WCHAR units. winex11: Use an IME UI message to set composition status. winex11: Use an IME UI message to set cursor pos. winex11: Use an IME UI message to get cursor pos. winex11: Use an IME UI message to set open status. win32u: Keep the IME UI window in win32u struct imc.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 35 ++++++++++++++++++++++++++--------- dlls/win32u/imm.c | 10 ++++++++++ include/ntuser.h | 1 + 3 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index d29684f34a2..42a6a568c1a 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -87,8 +87,6 @@ struct imc
struct ime *ime; UINT lastVK; - - HWND ui_hwnd; /* IME UI window, on the default input context */ };
#define WINE_IMC_VALID_MAGIC 0x56434D49 @@ -623,12 +621,25 @@ static INPUTCONTEXT *ime_find_input_context( struct ime *ime, HIMC himc ) return &entry->context; }
+static BOOL CALLBACK enum_set_ui_window( HIMC himc, LPARAM lparam ) +{ + NtUserUpdateInputContext( himc, NtUserInputContextUIHwnd, lparam ); + return TRUE; +} + static void imc_release_ime( struct imc *imc, struct ime *ime ) { + HIMC default_himc = UlongToHandle( NtUserGetThreadInfo()->default_imc ); INPUTCONTEXT *ctx; + HWND hwnd; + + if (imc->handle != default_himc) NtUserUpdateInputContext( imc->handle, NtUserInputContextUIHwnd, 0 ); + else if ((hwnd = (HWND)NtUserQueryInputContext( default_himc, NtUserInputContextUIHwnd ))) + { + DestroyWindow( hwnd ); + ImmEnumInputContext( 0, enum_set_ui_window, 0 ); + }
- if (imc->ui_hwnd) DestroyWindow( imc->ui_hwnd ); - imc->ui_hwnd = NULL; ime->pImeSelect( imc->handle, FALSE );
if ((ctx = ime_find_input_context( ime, imc->handle ))) *ctx = imc->IMC; @@ -651,11 +662,14 @@ static struct ime *imc_select_ime( struct imc *imc ) WARN( "Failed to acquire IME for HKL %p\n", hkl ); else { + HIMC default_himc = UlongToHandle( NtUserGetThreadInfo()->default_imc ); + HWND hwnd = (HWND)NtUserQueryInputContext( default_himc, NtUserInputContextUIHwnd ); INPUTCONTEXT *ctx;
if ((ctx = ime_find_input_context( imc->ime, imc->handle ))) imc->IMC = *ctx; else ime_save_input_context( imc->ime, imc->handle, &imc->IMC );
+ NtUserUpdateInputContext( imc->handle, NtUserInputContextUIHwnd, (LPARAM)hwnd ); imc->ime->pImeSelect( imc->handle, TRUE ); }
@@ -1010,16 +1024,19 @@ static HWND get_ime_ui_window(void) { struct imc *imc = default_input_context(); struct ime *ime; + HWND hwnd;
if (!(ime = imc_select_ime( imc ))) return 0;
- if (!imc->ui_hwnd) + if (!(hwnd = (HWND)NtUserQueryInputContext( imc->handle, NtUserInputContextUIHwnd ))) { - imc->ui_hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, ime->ui_class, NULL, WS_POPUP, 0, 0, 1, 1, - ImmGetDefaultIMEWnd( 0 ), 0, ime->module, 0 ); - SetWindowLongPtrW( imc->ui_hwnd, IMMGWL_IMC, (LONG_PTR)imc->handle ); + hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, ime->ui_class, NULL, WS_POPUP, 0, 0, 1, 1, + ImmGetDefaultIMEWnd( 0 ), 0, ime->module, 0 ); + SetWindowLongPtrW( hwnd, IMMGWL_IMC, (LONG_PTR)imc->handle ); + ImmEnumInputContext( 0, enum_set_ui_window, (LPARAM)hwnd ); } - return imc->ui_hwnd; + + return hwnd; }
/*********************************************************************** diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 7dee4912e27..7be44306dda 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -40,6 +40,7 @@ struct imc struct user_object obj; DWORD thread_id; UINT_PTR client_ptr; + HWND ui_hwnd; };
struct imm_thread_data @@ -80,6 +81,7 @@ HIMC WINAPI NtUserCreateInputContext( UINT_PTR client_ptr ) if (!(imc = malloc( sizeof(*imc) ))) return 0; imc->client_ptr = client_ptr; imc->thread_id = GetCurrentThreadId(); + imc->ui_hwnd = 0; if (!(handle = alloc_user_handle( &imc->obj, NTUSER_OBJ_IMC ))) { free( imc ); @@ -127,6 +129,10 @@ BOOL WINAPI NtUserUpdateInputContext( HIMC handle, UINT attr, UINT_PTR value ) imc->client_ptr = value; break;
+ case NtUserInputContextUIHwnd: + imc->ui_hwnd = (HWND)value; + break; + default: FIXME( "unknown attr %u\n", attr ); ret = FALSE; @@ -156,6 +162,10 @@ UINT_PTR WINAPI NtUserQueryInputContext( HIMC handle, UINT attr ) ret = imc->thread_id; break;
+ case NtUserInputContextUIHwnd: + ret = (UINT_PTR)imc->ui_hwnd; + break; + default: FIXME( "unknown attr %u\n", attr ); ret = 0; diff --git a/include/ntuser.h b/include/ntuser.h index 3d43eb476e4..7356c6096e9 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -453,6 +453,7 @@ struct draw_scroll_bar_params /* NtUserUpdateInputContext param, not compatible with Window */ enum input_context_attr { + NtUserInputContextUIHwnd = -1, NtUserInputContextClientPtr, NtUserInputContextThreadId, };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 3 +++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 9 --------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 25 +++++++++++++++++-------- include/ntuser.h | 3 +++ 8 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 3c4550c3cd9..35edcfe7f46 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -291,6 +291,9 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_wm_ime(msg), debugstr_imc(wparam), lparam ); return 1; + + case WM_WINE_IME_SET_OPEN_STATUS: + return ImmSetOpenStatus( himc, wparam ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 8a957494ce9..eccfd223ac3 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -61,6 +61,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_IME_REQUEST: return "WM_IME_REQUEST"; case WM_IME_KEYDOWN: return "WM_IME_KEYDOWN"; case WM_IME_KEYUP: return "WM_IME_KEYUP"; + case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 500a4a6bc44..54093d36b6e 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -33,7 +33,6 @@ static const callback_func callback_funcs[] = x11drv_ime_get_cursor_pos, x11drv_ime_set_composition_status, x11drv_ime_set_cursor_pos, - x11drv_ime_set_open_status, x11drv_ime_update_association, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 55485bfbfcf..72ada45f774 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -755,15 +755,6 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
/* Interfaces to XIM and other parts of winex11drv */
-NTSTATUS x11drv_ime_set_open_status( UINT open ) -{ - HIMC imc; - - imc = RealIMC(FROM_X11); - ImmSetOpenStatus(imc, open); - return 0; -} - NTSTATUS x11drv_ime_set_composition_status( UINT open ) { HIMC imc; diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 7dc1d9f0ca7..ed5dbac6535 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -99,7 +99,6 @@ enum client_callback client_ime_get_cursor_pos, client_ime_set_composition_status, client_ime_set_cursor_pos, - client_ime_set_open_status, client_ime_update_association, client_funcs_count }; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 047bb430d39..80fe9ab2a3d 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -39,7 +39,6 @@ extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_set_open_status( UINT open ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index b7f5f696ba5..f4c75d653cf 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -72,6 +72,21 @@ static const char *debugstr_xim_style( XIMStyle style ) return wine_dbg_sprintf( "%s", buffer ); }
+/* sends a message to the IME UI window */ +static LRESULT send_ime_ui_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + static const WCHAR WINE_IME_UI_CLASS[] = {'W','i','n','e',' ','I','M','E',0}; + WCHAR buffer[64]; + UNICODE_STRING name = {.Buffer = buffer, .MaximumLength = sizeof(buffer)}; + HIMC himc; + + if (!(himc = NtUserGetWindowInputContext( hwnd ))) return 0; + if (!(hwnd = (HWND)NtUserQueryInputContext( himc, NtUserInputContextUIHwnd ))) return 0; + if (!NtUserGetClassName( hwnd, 0, &name ) || wcscmp( buffer, WINE_IME_UI_CLASS )) return 0; + + return send_message( hwnd, msg, wparam, lparam ); +} + static void X11DRV_ImmSetInternalString(UINT offset, UINT selLength, LPWSTR lpComp, UINT len) { /* Composition strings are edited in chunks */ @@ -130,14 +145,8 @@ static BOOL xic_preedit_state_notify( XIC xic, XPointer user, XPointer arg )
switch (state) { - case XIMPreeditEnable: - x11drv_client_call( client_ime_set_open_status, TRUE ); - break; - case XIMPreeditDisable: - x11drv_client_call( client_ime_set_open_status, FALSE ); - break; - default: - break; + case XIMPreeditEnable: send_ime_ui_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, TRUE, 0 ); break; + case XIMPreeditDisable: send_ime_ui_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, FALSE, 0 ); break; }
return TRUE; diff --git a/include/ntuser.h b/include/ntuser.h index 7356c6096e9..f54a0eb902a 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -491,6 +491,9 @@ enum wine_internal_message #define IME_INTERNAL_HKL_ACTIVATE 0x19 #define IME_INTERNAL_HKL_DEACTIVATE 0x20
+/* default IME UI messages */ +#define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) + /* internal IME private */ typedef struct ime_private {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 21 +++++++++++++++++++++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 20 -------------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 2 +- include/ntuser.h | 1 + 8 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 35edcfe7f46..86834546a58 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -242,6 +242,25 @@ static void ime_ui_start_composition( HIMC himc, HWND hwnd ) ImmUnlockIMC( himc ); }
+static UINT ime_get_cursor_pos( HIMC himc ) +{ + COMPOSITIONSTRING *string; + INPUTCONTEXT *ctx; + UINT pos = 0; + + TRACE( "himc %p\n", himc ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((string = ImmLockIMCC( ctx->hCompStr ))) + { + pos = string->dwCursorPos; + ImmUnlockIMCC( ctx->hCompStr ); + } + ImmUnlockIMC( himc ); + + return pos; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -294,6 +313,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP
case WM_WINE_IME_SET_OPEN_STATUS: return ImmSetOpenStatus( himc, wparam ); + case WM_WINE_IME_GET_CURSOR_POS: + return ime_get_cursor_pos( himc ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index eccfd223ac3..4a3afce09ba 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -62,6 +62,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_IME_KEYDOWN: return "WM_IME_KEYDOWN"; case WM_IME_KEYUP: return "WM_IME_KEYUP"; case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; + case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 54093d36b6e..a3375e60957 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -30,7 +30,6 @@ static const callback_func callback_funcs[] = { x11drv_dnd_drop_event, x11drv_dnd_leave_event, - x11drv_ime_get_cursor_pos, x11drv_ime_set_composition_status, x11drv_ime_set_cursor_pos, x11drv_ime_update_association, diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 72ada45f774..b92c13ff08a 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -786,26 +786,6 @@ NTSTATUS x11drv_ime_set_composition_status( UINT open ) return 0; }
-NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) -{ - LPINPUTCONTEXT lpIMC; - INT rc = 0; - LPCOMPOSITIONSTRING compstr; - - if (!hSelectedFrom) - return rc; - - lpIMC = LockRealIMC(FROM_X11); - if (lpIMC) - { - compstr = ImmLockIMCC(lpIMC->hCompStr); - rc = compstr->dwCursorPos; - ImmUnlockIMCC(lpIMC->hCompStr); - } - UnlockRealIMC(FROM_X11); - return rc; -} - NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) { LPINPUTCONTEXT lpIMC; diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index ed5dbac6535..332c4e4b3fa 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -96,7 +96,6 @@ enum client_callback { client_dnd_drop_event, client_dnd_leave_event, - client_ime_get_cursor_pos, client_ime_set_composition_status, client_ime_set_cursor_pos, client_ime_update_association, diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 80fe9ab2a3d..2cc27abd362 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -36,7 +36,6 @@ extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) D
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index f4c75d653cf..46ec8680eb8 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -232,7 +232,7 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg )
if (!params) return 0;
- pos = x11drv_client_call( client_ime_get_cursor_pos, 0 ); + pos = send_ime_ui_message( hwnd, WM_WINE_IME_GET_CURSOR_POS, 0, 0 ); switch (params->direction) { case XIMForwardChar: diff --git a/include/ntuser.h b/include/ntuser.h index f54a0eb902a..b3824bec7a5 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -493,6 +493,7 @@ enum wine_internal_message
/* default IME UI messages */ #define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) +#define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1)
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 42 +++++++++++++++++++++++++++++++++++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 26 ---------------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 5 ++--- include/ntuser.h | 1 + 8 files changed, 46 insertions(+), 32 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 86834546a58..77c485a2e83 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -93,6 +93,25 @@ static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) return font; }
+static void ime_send_message( HIMC himc, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + TRANSMSG *messages = NULL, message = {.message = msg, .wParam = wparam, .lParam = lparam}; + INPUTCONTEXT *ctx; + HIMCC tmp; + + TRACE( "himc %p, msg %#x, wparam %#Ix, lparam %#Ix\n", himc, msg, wparam, lparam ); + + if (!(ctx = ImmLockIMC( himc ))) return; + if (!(tmp = ImmReSizeIMCC( ctx->hMsgBuf, (ctx->dwNumMsgBuf + 1) * sizeof(message) ))) goto done; + if (!(messages = ImmLockIMCC( (ctx->hMsgBuf = tmp) ))) goto done; + messages[ctx->dwNumMsgBuf++] = message; + ImmUnlockIMCC( ctx->hMsgBuf ); + +done: + ImmUnlockIMC( himc ); + if (!messages || !ImmGenerateMessage( himc )) WARN( "Failed to generate himc %p messages, error %lu\n", himc, GetLastError() ); +} + static void ime_ui_paint( HIMC himc, HWND hwnd ) { PAINTSTRUCT ps; @@ -261,6 +280,27 @@ static UINT ime_get_cursor_pos( HIMC himc ) return pos; }
+static UINT ime_set_cursor_pos( HIMC himc, UINT new_pos ) +{ + COMPOSITIONSTRING *string; + INPUTCONTEXT *ctx; + UINT pos = 0; + + TRACE( "himc %p, new_pos %u\n", himc, new_pos ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((string = ImmLockIMCC( ctx->hCompStr ))) + { + pos = string->dwCursorPos; + string->dwCursorPos = new_pos; + ImmUnlockIMCC( ctx->hCompStr ); + } + ImmUnlockIMC( himc ); + + if (pos != new_pos) ime_send_message( himc, WM_IME_COMPOSITION, new_pos, GCS_CURSORPOS ); + return pos; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -315,6 +355,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return ImmSetOpenStatus( himc, wparam ); case WM_WINE_IME_GET_CURSOR_POS: return ime_get_cursor_pos( himc ); + case WM_WINE_IME_SET_CURSOR_POS: + return ime_set_cursor_pos( himc, wparam ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 4a3afce09ba..b10d04d77ff 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -63,6 +63,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_IME_KEYUP: return "WM_IME_KEYUP"; case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; + case WM_WINE_IME_SET_CURSOR_POS: return "WM_WINE_IME_SET_CURSOR_POS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index a3375e60957..71fddfe4449 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -31,7 +31,6 @@ static const callback_func callback_funcs[] = x11drv_dnd_drop_event, x11drv_dnd_leave_event, x11drv_ime_set_composition_status, - x11drv_ime_set_cursor_pos, x11drv_ime_update_association, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index b92c13ff08a..cbf9c488f3a 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -786,32 +786,6 @@ NTSTATUS x11drv_ime_set_composition_status( UINT open ) return 0; }
-NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) -{ - LPINPUTCONTEXT lpIMC; - LPCOMPOSITIONSTRING compstr; - - if (!hSelectedFrom) - return 0; - - lpIMC = LockRealIMC(FROM_X11); - if (!lpIMC) - return 0; - - compstr = ImmLockIMCC(lpIMC->hCompStr); - if (!compstr) - { - UnlockRealIMC(FROM_X11); - return 0; - } - - compstr->dwCursorPos = pos; - ImmUnlockIMCC(lpIMC->hCompStr); - UnlockRealIMC(FROM_X11); - GenerateIMEMessage(FROM_X11, WM_IME_COMPOSITION, pos, GCS_CURSORPOS); - return 0; -} - NTSTATUS x11drv_ime_update_association( UINT arg ) { HWND focus = UlongToHandle( arg ); diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 332c4e4b3fa..e48a2c61669 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -97,7 +97,6 @@ enum client_callback client_dnd_drop_event, client_dnd_leave_event, client_ime_set_composition_status, - client_ime_set_cursor_pos, client_ime_update_association, client_funcs_count }; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 2cc27abd362..5180969eeb7 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -37,7 +37,6 @@ extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) D extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 46ec8680eb8..0e8c1d1293a 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -217,8 +217,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if (str != text->string.multi_byte) free( str ); }
- x11drv_client_call( client_ime_set_cursor_pos, params->caret ); - + send_ime_ui_message( hwnd, WM_WINE_IME_SET_CURSOR_POS, params->caret, 0 ); return 0; }
@@ -260,7 +259,7 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg ) FIXME( "Not implemented\n" ); break; } - x11drv_client_call( client_ime_set_cursor_pos, pos ); + send_ime_ui_message( hwnd, WM_WINE_IME_SET_CURSOR_POS, pos, 0 ); params->position = pos;
return 0; diff --git a/include/ntuser.h b/include/ntuser.h index b3824bec7a5..6f7e206be86 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -494,6 +494,7 @@ enum wine_internal_message /* default IME UI messages */ #define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) #define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1) +#define WM_WINE_IME_SET_CURSOR_POS (WM_USER + 2)
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 39 +++++++++++++++++++++++++++++++++++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 31 ---------------------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 5 +++-- include/ntuser.h | 1 + 8 files changed, 44 insertions(+), 36 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 77c485a2e83..762d1e29190 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -301,6 +301,43 @@ static UINT ime_set_cursor_pos( HIMC himc, UINT new_pos ) return pos; }
+static BOOL ime_set_composition_status( HIMC himc, HWND hwnd, BOOL new_status ) +{ + COMPOSITIONSTRING *string; + struct ime_private *priv; + BOOL old_status = FALSE; + INPUTCONTEXT *ctx; + HIMCC tmp; + + TRACE( "himc %p, hwnd %p, new_status %u\n", himc, hwnd, new_status ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((priv = ImmLockIMCC( ctx->hPrivate ))) + { + old_status = priv->bInComposition; + priv->bInComposition = new_status; + ImmUnlockIMCC( ctx->hPrivate ); + } + ImmUnlockIMC( himc ); + + if (new_status == old_status) return old_status; + if (old_status) ShowWindow( hwnd, SW_HIDE ); + + if (!(ctx = ImmLockIMC( himc ))) return old_status; + if (!new_status && (string = ImmLockIMCC( ctx->hCompStr ))) + { + memset( string, 0, sizeof(COMPOSITIONSTRING) ); + string->dwSize = sizeof(COMPOSITIONSTRING); + ImmUnlockIMCC( ctx->hCompStr ); + if ((tmp = ImmReSizeIMCC( ctx->hCompStr, sizeof(COMPOSITIONSTRING) ))) ctx->hCompStr = tmp; + else WARN( "Failed to shrink composition string for himc %p\n", himc ); + } + ImmUnlockIMC( himc ); + + ime_send_message( himc, new_status ? WM_IME_STARTCOMPOSITION : WM_IME_ENDCOMPOSITION, 0, 0 ); + return old_status; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -357,6 +394,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return ime_get_cursor_pos( himc ); case WM_WINE_IME_SET_CURSOR_POS: return ime_set_cursor_pos( himc, wparam ); + case WM_WINE_IME_SET_COMP_STATUS: + return ime_set_composition_status( himc, hwnd, wparam ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index b10d04d77ff..876d92d4aa2 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -64,6 +64,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; case WM_WINE_IME_SET_CURSOR_POS: return "WM_WINE_IME_SET_CURSOR_POS"; + case WM_WINE_IME_SET_COMP_STATUS: return "WM_WINE_IME_SET_COMP_STATUS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 71fddfe4449..8445c21470e 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -30,7 +30,6 @@ static const callback_func callback_funcs[] = { x11drv_dnd_drop_event, x11drv_dnd_leave_event, - x11drv_ime_set_composition_status, x11drv_ime_update_association, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index cbf9c488f3a..09440140568 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -755,37 +755,6 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
/* Interfaces to XIM and other parts of winex11drv */
-NTSTATUS x11drv_ime_set_composition_status( UINT open ) -{ - HIMC imc; - LPINPUTCONTEXT lpIMC; - LPIMEPRIVATE myPrivate; - - imc = RealIMC(FROM_X11); - lpIMC = ImmLockIMC(imc); - if (lpIMC == NULL) - return 0; - - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - - if (open && !myPrivate->bInComposition) - { - GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0); - } - else if (!open && myPrivate->bInComposition) - { - ShowWindow(myPrivate->hwndDefault, SW_HIDE); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = ImeCreateBlankCompStr(); - GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0); - } - myPrivate->bInComposition = open; - - ImmUnlockIMCC(lpIMC->hPrivate); - ImmUnlockIMC(imc); - return 0; -} - NTSTATUS x11drv_ime_update_association( UINT arg ) { HWND focus = UlongToHandle( arg ); diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index e48a2c61669..484ed4e5725 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -96,7 +96,6 @@ enum client_callback { client_dnd_drop_event, client_dnd_leave_event, - client_ime_set_composition_status, client_ime_update_association, client_funcs_count }; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 5180969eeb7..a96e286ae83 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -36,7 +36,6 @@ extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) D
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 0e8c1d1293a..a7e2a0a2c26 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -158,7 +158,7 @@ static int xic_preedit_start( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
- x11drv_client_call( client_ime_set_composition_status, TRUE ); + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, TRUE, 0 ); ximInComposeMode = TRUE; return -1; } @@ -175,7 +175,8 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg ) dwCompStringSize = 0; dwCompStringLength = 0; CompositionString = NULL; - x11drv_client_call( client_ime_set_composition_status, FALSE ); + + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, FALSE, 0 ); return 0; }
diff --git a/include/ntuser.h b/include/ntuser.h index 6f7e206be86..77f383d12ac 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -495,6 +495,7 @@ enum wine_internal_message #define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) #define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1) #define WM_WINE_IME_SET_CURSOR_POS (WM_USER + 2) +#define WM_WINE_IME_SET_COMP_STATUS (WM_USER + 3)
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/xim.c | 54 ++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 31 deletions(-)
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index a7e2a0a2c26..61998c22ad2 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -44,10 +44,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim);
BOOL ximInComposeMode=FALSE;
-/* moved here from imm32 for dll separation */ -static DWORD dwCompStringLength = 0; -static LPBYTE CompositionString = NULL; -static DWORD dwCompStringSize = 0; +static DWORD preedit_len = 0; +static DWORD preedit_max = 0; +static WCHAR *preedit_buf = NULL;
static XIMStyle input_style = 0; static XIMStyle input_style_req = XIMPreeditCallbacks | XIMStatusCallbacks; @@ -87,38 +86,32 @@ static LRESULT send_ime_ui_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l return send_message( hwnd, msg, wparam, lparam ); }
-static void X11DRV_ImmSetInternalString(UINT offset, UINT selLength, LPWSTR lpComp, UINT len) +static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, UINT new_len ) { - /* Composition strings are edited in chunks */ - unsigned int byte_length = len * sizeof(WCHAR); - unsigned int byte_offset = offset * sizeof(WCHAR); - unsigned int byte_selection = selLength * sizeof(WCHAR); - int byte_expansion = byte_length - byte_selection; - LPBYTE ptr_new; + int diff = new_len - old_len;
- TRACE("( %i, %i, %p, %d):\n", offset, selLength, lpComp, len ); + TRACE( "offset %u, old_len %u, text %s\n", offset, old_len, debugstr_wn(text, new_len) );
- if (byte_expansion + dwCompStringLength >= dwCompStringSize) + if (preedit_len + diff >= preedit_max) { - ptr_new = realloc( CompositionString, dwCompStringSize + byte_expansion ); - if (ptr_new == NULL) + WCHAR *tmp; + + if (!(tmp = realloc( preedit_buf, (preedit_max + diff) * sizeof(WCHAR) ))) { ERR("Couldn't expand composition string buffer\n"); return; }
- CompositionString = ptr_new; - dwCompStringSize += byte_expansion; + preedit_buf = tmp; + preedit_max += diff; }
- ptr_new = CompositionString + byte_offset; - memmove(ptr_new + byte_length, ptr_new + byte_selection, - dwCompStringLength - byte_offset - byte_selection); - if (lpComp) memcpy(ptr_new, lpComp, byte_length); - dwCompStringLength += byte_expansion; + memmove( preedit_buf + offset + new_len, preedit_buf + offset + old_len, + (preedit_len - offset - old_len) * sizeof(WCHAR) ); + if (text) memcpy( preedit_buf + offset, text, new_len * sizeof(WCHAR) ); + preedit_len += diff;
- x11drv_client_func( client_func_ime_set_composition_string, - CompositionString, dwCompStringLength ); + x11drv_client_func( client_func_ime_set_composition_string, preedit_buf, preedit_len * sizeof(WCHAR) ); }
void X11DRV_XIMLookupChars( const char *str, UINT count ) @@ -170,11 +163,10 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg ) TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
ximInComposeMode = FALSE; - if (dwCompStringSize) - free( CompositionString ); - dwCompStringSize = 0; - dwCompStringLength = 0; - CompositionString = NULL; + free( preedit_buf ); + preedit_max = 0; + preedit_len = 0; + preedit_buf = NULL;
send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, FALSE, 0 ); return 0; @@ -191,7 +183,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if (!params) return 0;
if (!(text = params->text)) - X11DRV_ImmSetInternalString( params->chg_first, params->chg_length, NULL, 0 ); + xim_update_preedit_string( params->chg_first, params->chg_length, NULL, 0 ); else { size_t text_len; @@ -211,7 +203,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if ((output = malloc( text_len * sizeof(WCHAR) ))) { text_len = ntdll_umbstowcs( str, text_len, output, text_len ); - X11DRV_ImmSetInternalString( params->chg_first, params->chg_length, output, text_len ); + xim_update_preedit_string( params->chg_first, params->chg_length, output, text_len ); free( output ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/xim.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 61998c22ad2..500d2924d77 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -92,11 +92,11 @@ static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, U
TRACE( "offset %u, old_len %u, text %s\n", offset, old_len, debugstr_wn(text, new_len) );
- if (preedit_len + diff >= preedit_max) + if (!preedit_buf || preedit_len + diff >= preedit_max) { WCHAR *tmp;
- if (!(tmp = realloc( preedit_buf, (preedit_max + diff) * sizeof(WCHAR) ))) + if (!(tmp = realloc( preedit_buf, (preedit_max + diff + 1) * sizeof(WCHAR) ))) { ERR("Couldn't expand composition string buffer\n"); return; @@ -110,6 +110,7 @@ static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, U (preedit_len - offset - old_len) * sizeof(WCHAR) ); if (text) memcpy( preedit_buf + offset, text, new_len * sizeof(WCHAR) ); preedit_len += diff; + preedit_buf[preedit_len] = 0;
x11drv_client_func( client_func_ime_set_composition_string, preedit_buf, preedit_len * sizeof(WCHAR) ); } @@ -121,8 +122,9 @@ void X11DRV_XIMLookupChars( const char *str, UINT count )
TRACE("%p %u\n", str, count);
- if (!(output = malloc( count * sizeof(WCHAR) ))) return; + if (!(output = malloc( (count + 1) * sizeof(WCHAR) ))) return; len = ntdll_umbstowcs( str, count, output, count ); + output[len] = 0;
x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); free( output );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 111 +++++++++++++++++++++++++++++++++- dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 2 - dlls/winex11.drv/ime.c | 54 ----------------- dlls/winex11.drv/keyboard.c | 2 +- dlls/winex11.drv/unixlib.h | 2 - dlls/winex11.drv/x11drv.h | 2 +- dlls/winex11.drv/x11drv_dll.h | 2 - dlls/winex11.drv/xim.c | 17 +++--- include/ntuser.h | 1 + 10 files changed, 122 insertions(+), 72 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 762d1e29190..9c80c05121d 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -83,6 +83,86 @@ static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT * return text; }
+static DWORD input_context_set_comp_str( INPUTCONTEXT *ctx, BOOL result, const WCHAR *str, SIZE_T len ) +{ + DWORD flags = result ? GCS_RESULTSTR : GCS_COMPSTR; + UINT new_size = sizeof(COMPOSITIONSTRING); + COMPOSITIONSTRING old, *comp; + BYTE *dst; + + TRACE( "ctx %p, result %u, str %s\n", ctx, result, debugstr_wn(str, len) ); + + new_size += len * sizeof(WCHAR); + if (len) new_size += 2 * sizeof(DWORD); + if (!result) new_size += len; + + if (!(comp = ImmLockIMCC( ctx->hCompStr ))) goto error; + old = *comp; + ImmUnlockIMCC( ctx->hCompStr ); + + if (new_size > old.dwSize && !(ctx->hCompStr = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; + + if (!(comp = ImmLockIMCC( ctx->hCompStr ))) goto error; + memset( comp, 0, sizeof(COMPOSITIONSTRING) ); + comp->dwSize = sizeof(COMPOSITIONSTRING); + + if (!result && len) + { + comp->dwCursorPos = min( len, old.dwCursorPos ); + + comp->dwCompStrLen = len; + comp->dwCompStrOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwCompStrOffset; + memcpy( dst, str, len * sizeof(WCHAR) ); + comp->dwSize += len * sizeof(WCHAR); + + comp->dwCompClauseLen = 2 * sizeof(DWORD); + comp->dwCompClauseOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwCompClauseOffset; + *(DWORD *)(dst + 0 * sizeof(DWORD)) = 0; + *(DWORD *)(dst + 1 * sizeof(DWORD)) = len; + comp->dwSize += 2 * sizeof(DWORD); + + comp->dwCompAttrLen = len; + comp->dwCompAttrOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwCompAttrOffset; + memset( dst, ATTR_INPUT, len ); + comp->dwSize += len; + } + else if (len) + { + comp->dwResultStrLen = len; + comp->dwResultStrOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwResultStrOffset; + memcpy( dst, str, len * sizeof(WCHAR) ); + comp->dwSize += len * sizeof(WCHAR); + + comp->dwResultClauseLen = 2 * sizeof(DWORD); + comp->dwResultClauseOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwResultClauseOffset; + *(DWORD *)(dst + 0 * sizeof(DWORD)) = 0; + *(DWORD *)(dst + 1 * sizeof(DWORD)) = len; + comp->dwSize += 2 * sizeof(DWORD); + } + + if (comp->dwCursorPos != old.dwCursorPos) flags |= GCS_CURSORPOS; + if (comp->dwDeltaStart != old.dwDeltaStart) flags |= GCS_DELTASTART; + if (comp->dwCompStrLen != old.dwCompStrLen) flags |= GCS_COMPSTR; + if (comp->dwCompAttrLen != old.dwCompAttrLen) flags |= GCS_COMPATTR; + if (comp->dwCompClauseLen != old.dwCompClauseLen) flags |= GCS_COMPCLAUSE; + if (comp->dwResultStrLen != old.dwResultStrLen) flags |= GCS_RESULTSTR; + if (comp->dwResultClauseLen != old.dwResultClauseLen) flags |= GCS_RESULTCLAUSE; + + ImmUnlockIMCC( ctx->hCompStr ); + + if (new_size < old.dwSize && !(ctx->hCompStr = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; + return flags; + +error: + WARN( "Failed to update result string, error %lu\n", GetLastError() ); + return 0; +} + static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) { struct ime_private *priv; @@ -338,6 +418,33 @@ static BOOL ime_set_composition_status( HIMC himc, HWND hwnd, BOOL new_status ) return old_status; }
+static BOOL ime_set_composition_text( HIMC himc, HWND hwnd, BOOL result, const WCHAR *str, UINT len ) +{ + struct ime_private *priv; + BOOL old_status = FALSE; + INPUTCONTEXT *ctx; + DWORD flags; + + TRACE( "old_status %u, himc %p, result %u, str %s\n", old_status, himc, result, debugstr_wn(str, len) ); + + if (!(ctx = ImmLockIMC( himc ))) return FALSE; + if ((priv = ImmLockIMCC( ctx->hPrivate ))) + { + old_status = priv->bInComposition; + ImmUnlockIMCC( ctx->hPrivate ); + } + flags = input_context_set_comp_str( ctx, result, str, len ); + ImmUnlockIMC( himc ); + + if (!old_status) ImmSetOpenStatus( himc, TRUE ); + if (!result || !old_status) ime_set_composition_status( himc, hwnd, TRUE ); + ime_send_message( himc, WM_IME_COMPOSITION, len ? str[0] : 0, flags ); + if (result || !old_status) ime_set_composition_status( himc, hwnd, FALSE ); + if (!old_status) ImmSetOpenStatus( himc, FALSE ); + + return TRUE; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -352,8 +459,6 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP { struct ime_private *priv;
- SetWindowTextA( hwnd, "Wine Ime Active" ); - if (!(ctx = ImmLockIMC( himc ))) return TRUE; if ((priv = ImmLockIMCC( ctx->hPrivate ))) { @@ -396,6 +501,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return ime_set_cursor_pos( himc, wparam ); case WM_WINE_IME_SET_COMP_STATUS: return ime_set_composition_status( himc, hwnd, wparam ); + case WM_WINE_IME_SET_COMP_TEXT: + return ime_set_composition_text( himc, hwnd, !wparam, (const WCHAR *)lparam, wcslen( (const WCHAR *)lparam ) ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 876d92d4aa2..8ea40e1fb27 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -65,6 +65,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; case WM_WINE_IME_SET_CURSOR_POS: return "WM_WINE_IME_SET_CURSOR_POS"; case WM_WINE_IME_SET_COMP_STATUS: return "WM_WINE_IME_SET_COMP_STATUS"; + case WM_WINE_IME_SET_COMP_TEXT: return "WM_WINE_IME_SET_COMP_TEXT"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 8445c21470e..7c463d4e401 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -48,8 +48,6 @@ static const kernel_callback kernel_callbacks[] = x11drv_dnd_enter_event, x11drv_dnd_position_event, x11drv_dnd_post_drop, - x11drv_ime_set_composition_string, - x11drv_ime_set_result, x11drv_systray_change_owner, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 09440140568..a69ad81eff5 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -765,57 +765,3 @@ NTSTATUS x11drv_ime_update_association( UINT arg ) ImmAssociateContext(focus,RealIMC(FROM_X11)); return 0; } - - -NTSTATUS WINAPI x11drv_ime_set_composition_string( void *param, ULONG size ) -{ - return ImeSetCompositionString(FROM_X11, SCS_SETSTR, param, size, NULL, 0); -} - -NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG len ) -{ - WCHAR *lpResult = params; - HIMC imc; - LPINPUTCONTEXT lpIMC; - HIMCC newCompStr; - LPIMEPRIVATE myPrivate; - BOOL inComp; - HWND focus; - - len /= sizeof(WCHAR); - if ((focus = GetFocus())) - x11drv_ime_update_association( HandleToUlong( focus )); - - imc = RealIMC(FROM_X11); - lpIMC = ImmLockIMC(imc); - if (lpIMC == NULL) - return 0; - - newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, len); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - inComp = myPrivate->bInComposition; - ImmUnlockIMCC(lpIMC->hPrivate); - - if (!inComp) - { - ImmSetOpenStatus(imc, TRUE); - GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0); - } - - GenerateIMEMessage(imc, WM_IME_COMPOSITION, 0, GCS_COMPSTR); - GenerateIMEMessage(imc, WM_IME_COMPOSITION, lpResult[0], GCS_RESULTSTR|GCS_RESULTCLAUSE); - GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0); - - if (!inComp) - ImmSetOpenStatus(imc, FALSE); - - ImmUnlockIMC(imc); - 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/unixlib.h b/dlls/winex11.drv/unixlib.h index 484ed4e5725..de044a9416c 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -83,8 +83,6 @@ enum x11drv_client_funcs client_func_dnd_enter_event, client_func_dnd_position_event, client_func_dnd_post_drop, - client_func_ime_set_composition_string, - client_func_ime_set_result, client_func_systray_change_owner, client_func_last }; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9efaae3465b..d4581e21298 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; /* XIM support */ extern BOOL xim_init( const WCHAR *input_style ) DECLSPEC_HIDDEN; extern void xim_thread_attach( struct x11drv_thread_data *data ) 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/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index a96e286ae83..fbd2a3e74b2 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -30,8 +30,6 @@ extern NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; -extern NTSTATUS WINAPI x11drv_ime_set_composition_string( void *params, ULONG size ) DECLSPEC_HIDDEN; -extern NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 500d2924d77..c62fce18c80 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -86,11 +86,11 @@ static LRESULT send_ime_ui_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l return send_message( hwnd, msg, wparam, lparam ); }
-static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, UINT new_len ) +static void xim_update_preedit_string( HWND hwnd, UINT offset, UINT old_len, WCHAR *text, UINT new_len ) { int diff = new_len - old_len;
- TRACE( "offset %u, old_len %u, text %s\n", offset, old_len, debugstr_wn(text, new_len) ); + TRACE( "hwnd %p, offset %u, old_len %u, text %s\n", hwnd, offset, old_len, debugstr_wn(text, new_len) );
if (!preedit_buf || preedit_len + diff >= preedit_max) { @@ -112,21 +112,22 @@ static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, U preedit_len += diff; preedit_buf[preedit_len] = 0;
- x11drv_client_func( client_func_ime_set_composition_string, preedit_buf, preedit_len * sizeof(WCHAR) ); + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, TRUE, (LPARAM)preedit_buf ); }
-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, str %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;
- x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, FALSE, (LPARAM)output ); + free( output ); }
@@ -185,7 +186,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if (!params) return 0;
if (!(text = params->text)) - xim_update_preedit_string( params->chg_first, params->chg_length, NULL, 0 ); + xim_update_preedit_string( hwnd, params->chg_first, params->chg_length, NULL, 0 ); else { size_t text_len; @@ -205,7 +206,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if ((output = malloc( text_len * sizeof(WCHAR) ))) { text_len = ntdll_umbstowcs( str, text_len, output, text_len ); - xim_update_preedit_string( params->chg_first, params->chg_length, output, text_len ); + xim_update_preedit_string( hwnd, params->chg_first, params->chg_length, output, text_len ); free( output ); }
diff --git a/include/ntuser.h b/include/ntuser.h index 77f383d12ac..3926b6d633d 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -496,6 +496,7 @@ enum wine_internal_message #define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1) #define WM_WINE_IME_SET_CURSOR_POS (WM_USER + 2) #define WM_WINE_IME_SET_COMP_STATUS (WM_USER + 3) +#define WM_WINE_IME_SET_COMP_TEXT EM_REPLACESEL
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/ime.c | 435 +++++++++-------------------------------- 1 file changed, 90 insertions(+), 345 deletions(-)
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index a69ad81eff5..f8d4a6a64c3 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -73,6 +73,86 @@ static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT * return text; }
+static DWORD input_context_set_comp_str( INPUTCONTEXT *ctx, BOOL result, const WCHAR *str, SIZE_T len ) +{ + DWORD flags = result ? GCS_RESULTSTR : GCS_COMPSTR; + UINT new_size = sizeof(COMPOSITIONSTRING); + COMPOSITIONSTRING old, *comp; + BYTE *dst; + + TRACE( "ctx %p, result %u, str %s\n", ctx, result, debugstr_wn(str, len) ); + + new_size += len * sizeof(WCHAR); + if (len) new_size += 2 * sizeof(DWORD); + if (!result) new_size += len; + + if (!(comp = ImmLockIMCC( ctx->hCompStr ))) goto error; + old = *comp; + ImmUnlockIMCC( ctx->hCompStr ); + + if (new_size > old.dwSize && !(ctx->hCompStr = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; + + if (!(comp = ImmLockIMCC( ctx->hCompStr ))) goto error; + memset( comp, 0, sizeof(COMPOSITIONSTRING) ); + comp->dwSize = sizeof(COMPOSITIONSTRING); + + if (!result && len) + { + comp->dwCursorPos = min( len, old.dwCursorPos ); + + comp->dwCompStrLen = len; + comp->dwCompStrOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwCompStrOffset; + memcpy( dst, str, len * sizeof(WCHAR) ); + comp->dwSize += len * sizeof(WCHAR); + + comp->dwCompClauseLen = 2 * sizeof(DWORD); + comp->dwCompClauseOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwCompClauseOffset; + *(DWORD *)(dst + 0 * sizeof(DWORD)) = 0; + *(DWORD *)(dst + 1 * sizeof(DWORD)) = len; + comp->dwSize += 2 * sizeof(DWORD); + + comp->dwCompAttrLen = len; + comp->dwCompAttrOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwCompAttrOffset; + memset( dst, ATTR_INPUT, len ); + comp->dwSize += len; + } + else if (len) + { + comp->dwResultStrLen = len; + comp->dwResultStrOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwResultStrOffset; + memcpy( dst, str, len * sizeof(WCHAR) ); + comp->dwSize += len * sizeof(WCHAR); + + comp->dwResultClauseLen = 2 * sizeof(DWORD); + comp->dwResultClauseOffset = comp->dwSize; + dst = (BYTE *)comp + comp->dwResultClauseOffset; + *(DWORD *)(dst + 0 * sizeof(DWORD)) = 0; + *(DWORD *)(dst + 1 * sizeof(DWORD)) = len; + comp->dwSize += 2 * sizeof(DWORD); + } + + if (comp->dwCursorPos != old.dwCursorPos) flags |= GCS_CURSORPOS; + if (comp->dwDeltaStart != old.dwDeltaStart) flags |= GCS_DELTASTART; + if (comp->dwCompStrLen != old.dwCompStrLen) flags |= GCS_COMPSTR; + if (comp->dwCompAttrLen != old.dwCompAttrLen) flags |= GCS_COMPATTR; + if (comp->dwCompClauseLen != old.dwCompClauseLen) flags |= GCS_COMPCLAUSE; + if (comp->dwResultStrLen != old.dwResultStrLen) flags |= GCS_RESULTSTR; + if (comp->dwResultClauseLen != old.dwResultClauseLen) flags |= GCS_RESULTCLAUSE; + + ImmUnlockIMCC( ctx->hCompStr ); + + if (new_size < old.dwSize && !(ctx->hCompStr = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; + return flags; + +error: + WARN( "Failed to update result string, error %lu\n", GetLastError() ); + return 0; +} + static HIMC RealIMC(HIMC hIMC) { if (hIMC == FROM_X11) @@ -119,309 +199,6 @@ static HIMCC ImeCreateBlankCompStr(void) return rc; }
-static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset, - LPBYTE target, LPBYTE source, DWORD* lenParam, - DWORD* offsetParam, BOOL wchars ) -{ - if (origLen > 0 && origOffset > 0) - { - int truelen = origLen; - if (wchars) - truelen *= sizeof(WCHAR); - - memcpy(&target[currentOffset], &source[origOffset], truelen); - - *lenParam = origLen; - *offsetParam = currentOffset; - currentOffset += truelen; - } - return currentOffset; -} - -static HIMCC updateCompStr(HIMCC old, LPCWSTR compstr, DWORD len) -{ - /* We need to make sure the CompStr, CompClause and CompAttr fields are all - * set and correct. */ - int needed_size; - HIMCC rc; - LPBYTE newdata = NULL; - LPBYTE olddata = NULL; - LPCOMPOSITIONSTRING new_one; - LPCOMPOSITIONSTRING lpcs = NULL; - INT current_offset = 0; - - TRACE("%s, %li\n",debugstr_wn(compstr,len),len); - - if (old == NULL && compstr == NULL && len == 0) - return NULL; - - if (compstr == NULL && len != 0) - { - ERR("compstr is NULL however we have a len! Please report\n"); - len = 0; - } - - if (old != NULL) - { - olddata = ImmLockIMCC(old); - lpcs = (LPCOMPOSITIONSTRING)olddata; - } - - needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) + - len + sizeof(DWORD) * 2; - - if (lpcs != NULL) - { - needed_size += lpcs->dwCompReadAttrLen; - needed_size += lpcs->dwCompReadClauseLen; - needed_size += lpcs->dwCompReadStrLen * sizeof(WCHAR); - needed_size += lpcs->dwResultReadClauseLen; - needed_size += lpcs->dwResultReadStrLen * sizeof(WCHAR); - needed_size += lpcs->dwResultClauseLen; - needed_size += lpcs->dwResultStrLen * sizeof(WCHAR); - needed_size += lpcs->dwPrivateSize; - } - rc = ImmCreateIMCC(needed_size); - newdata = ImmLockIMCC(rc); - new_one = (LPCOMPOSITIONSTRING)newdata; - - new_one->dwSize = needed_size; - current_offset = sizeof(COMPOSITIONSTRING); - if (lpcs != NULL) - { - current_offset = updateField(lpcs->dwCompReadAttrLen, - lpcs->dwCompReadAttrOffset, - current_offset, newdata, olddata, - &new_one->dwCompReadAttrLen, - &new_one->dwCompReadAttrOffset, FALSE); - - current_offset = updateField(lpcs->dwCompReadClauseLen, - lpcs->dwCompReadClauseOffset, - current_offset, newdata, olddata, - &new_one->dwCompReadClauseLen, - &new_one->dwCompReadClauseOffset, FALSE); - - current_offset = updateField(lpcs->dwCompReadStrLen, - lpcs->dwCompReadStrOffset, - current_offset, newdata, olddata, - &new_one->dwCompReadStrLen, - &new_one->dwCompReadStrOffset, TRUE); - - /* new CompAttr, CompClause, CompStr, dwCursorPos */ - new_one->dwDeltaStart = 0; - - current_offset = updateField(lpcs->dwResultReadClauseLen, - lpcs->dwResultReadClauseOffset, - current_offset, newdata, olddata, - &new_one->dwResultReadClauseLen, - &new_one->dwResultReadClauseOffset, FALSE); - - current_offset = updateField(lpcs->dwResultReadStrLen, - lpcs->dwResultReadStrOffset, - current_offset, newdata, olddata, - &new_one->dwResultReadStrLen, - &new_one->dwResultReadStrOffset, TRUE); - - current_offset = updateField(lpcs->dwResultClauseLen, - lpcs->dwResultClauseOffset, - current_offset, newdata, olddata, - &new_one->dwResultClauseLen, - &new_one->dwResultClauseOffset, FALSE); - - current_offset = updateField(lpcs->dwResultStrLen, - lpcs->dwResultStrOffset, - current_offset, newdata, olddata, - &new_one->dwResultStrLen, - &new_one->dwResultStrOffset, TRUE); - - current_offset = updateField(lpcs->dwPrivateSize, - lpcs->dwPrivateOffset, - current_offset, newdata, olddata, - &new_one->dwPrivateSize, - &new_one->dwPrivateOffset, FALSE); - } - - /* set new data */ - /* CompAttr */ - new_one->dwCompAttrLen = len; - if (len > 0) - { - new_one->dwCompAttrOffset = current_offset; - memset(&newdata[current_offset],ATTR_INPUT,len); - current_offset += len; - } - - /* CompClause */ - if (len > 0) - { - new_one->dwCompClauseLen = sizeof(DWORD) * 2; - new_one->dwCompClauseOffset = current_offset; - *(DWORD*)(&newdata[current_offset]) = 0; - current_offset += sizeof(DWORD); - *(DWORD*)(&newdata[current_offset]) = len; - current_offset += sizeof(DWORD); - } - else - new_one->dwCompClauseLen = 0; - - /* CompStr */ - new_one->dwCompStrLen = len; - if (len > 0) - { - new_one->dwCompStrOffset = current_offset; - memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR)); - } - - /* CursorPos */ - new_one->dwCursorPos = len; - - ImmUnlockIMCC(rc); - if (lpcs) - ImmUnlockIMCC(old); - - return rc; -} - -static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len) -{ - /* we need to make sure the ResultStr and ResultClause fields are all - * set and correct */ - int needed_size; - HIMCC rc; - LPBYTE newdata = NULL; - LPBYTE olddata = NULL; - LPCOMPOSITIONSTRING new_one; - LPCOMPOSITIONSTRING lpcs = NULL; - INT current_offset = 0; - - TRACE("%s, %li\n",debugstr_wn(resultstr,len),len); - - if (old == NULL && resultstr == NULL && len == 0) - return NULL; - - if (resultstr == NULL && len != 0) - { - ERR("resultstr is NULL however we have a len! Please report\n"); - len = 0; - } - - if (old != NULL) - { - olddata = ImmLockIMCC(old); - lpcs = (LPCOMPOSITIONSTRING)olddata; - } - - needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) + - sizeof(DWORD) * 2; - - if (lpcs != NULL) - { - needed_size += lpcs->dwCompReadAttrLen; - needed_size += lpcs->dwCompReadClauseLen; - needed_size += lpcs->dwCompReadStrLen * sizeof(WCHAR); - needed_size += lpcs->dwCompAttrLen; - needed_size += lpcs->dwCompClauseLen; - needed_size += lpcs->dwCompStrLen * sizeof(WCHAR); - needed_size += lpcs->dwResultReadClauseLen; - needed_size += lpcs->dwResultReadStrLen * sizeof(WCHAR); - needed_size += lpcs->dwPrivateSize; - } - rc = ImmCreateIMCC(needed_size); - newdata = ImmLockIMCC(rc); - new_one = (LPCOMPOSITIONSTRING)newdata; - - new_one->dwSize = needed_size; - current_offset = sizeof(COMPOSITIONSTRING); - if (lpcs != NULL) - { - current_offset = updateField(lpcs->dwCompReadAttrLen, - lpcs->dwCompReadAttrOffset, - current_offset, newdata, olddata, - &new_one->dwCompReadAttrLen, - &new_one->dwCompReadAttrOffset, FALSE); - - current_offset = updateField(lpcs->dwCompReadClauseLen, - lpcs->dwCompReadClauseOffset, - current_offset, newdata, olddata, - &new_one->dwCompReadClauseLen, - &new_one->dwCompReadClauseOffset, FALSE); - - current_offset = updateField(lpcs->dwCompReadStrLen, - lpcs->dwCompReadStrOffset, - current_offset, newdata, olddata, - &new_one->dwCompReadStrLen, - &new_one->dwCompReadStrOffset, TRUE); - - current_offset = updateField(lpcs->dwCompAttrLen, - lpcs->dwCompAttrOffset, - current_offset, newdata, olddata, - &new_one->dwCompAttrLen, - &new_one->dwCompAttrOffset, FALSE); - - current_offset = updateField(lpcs->dwCompClauseLen, - lpcs->dwCompClauseOffset, - current_offset, newdata, olddata, - &new_one->dwCompClauseLen, - &new_one->dwCompClauseOffset, FALSE); - - current_offset = updateField(lpcs->dwCompStrLen, - lpcs->dwCompStrOffset, - current_offset, newdata, olddata, - &new_one->dwCompStrLen, - &new_one->dwCompStrOffset, TRUE); - - new_one->dwCursorPos = lpcs->dwCursorPos; - new_one->dwDeltaStart = 0; - - current_offset = updateField(lpcs->dwResultReadClauseLen, - lpcs->dwResultReadClauseOffset, - current_offset, newdata, olddata, - &new_one->dwResultReadClauseLen, - &new_one->dwResultReadClauseOffset, FALSE); - - current_offset = updateField(lpcs->dwResultReadStrLen, - lpcs->dwResultReadStrOffset, - current_offset, newdata, olddata, - &new_one->dwResultReadStrLen, - &new_one->dwResultReadStrOffset, TRUE); - - /* new ResultClause , ResultStr */ - - current_offset = updateField(lpcs->dwPrivateSize, - lpcs->dwPrivateOffset, - current_offset, newdata, olddata, - &new_one->dwPrivateSize, - &new_one->dwPrivateOffset, FALSE); - } - - /* set new data */ - /* ResultClause */ - if (len > 0) - { - new_one->dwResultClauseLen = sizeof(DWORD) * 2; - new_one->dwResultClauseOffset = current_offset; - *(DWORD*)(&newdata[current_offset]) = 0; - current_offset += sizeof(DWORD); - *(DWORD*)(&newdata[current_offset]) = len; - current_offset += sizeof(DWORD); - } - else - new_one->dwResultClauseLen = 0; - - /* ResultStr */ - new_one->dwResultStrLen = len; - if (len > 0) - { - new_one->dwResultStrOffset = current_offset; - memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR)); - } - ImmUnlockIMCC(rc); - if (lpcs) - ImmUnlockIMCC(old); - - return rc; -} - static void GenerateIMEMessage(HIMC hIMC, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -601,42 +378,25 @@ BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { case CPS_COMPLETE: { - HIMCC newCompStr; LPIMEPRIVATE myPrivate; WCHAR *str; UINT len;
TRACE("CPS_COMPLETE\n");
- /* clear existing result */ - newCompStr = updateResultStr(lpIMC->hCompStr, NULL, 0); - - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - myPrivate = ImmLockIMCC(lpIMC->hPrivate); if ((str = input_context_get_comp_str( lpIMC, FALSE, &len ))) { - WCHAR param = str[0]; - - newCompStr = updateResultStr( lpIMC->hCompStr, str, len ); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, 0, - GCS_COMPSTR); - - GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, param, - GCS_RESULTSTR|GCS_RESULTCLAUSE); - + DWORD flags = input_context_set_comp_str( lpIMC, TRUE, str, len ); + GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, str[0], flags ); GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION, 0, 0); free( str ); } - else if (myPrivate->bInComposition) - GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION, 0, 0); + else + { + input_context_set_comp_str( lpIMC, TRUE, NULL, 0 ); + if (myPrivate->bInComposition) GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION, 0, 0); + }
myPrivate->bInComposition = FALSE; ImmUnlockIMCC(lpIMC->hPrivate); @@ -714,35 +474,20 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
if (dwIndex == SCS_SETSTR) { - HIMCC newCompStr; - if (!myPrivate->bInComposition) { GenerateIMEMessage(hIMC, WM_IME_STARTCOMPOSITION, 0, 0); myPrivate->bInComposition = TRUE; }
- /* clear existing result */ - newCompStr = updateResultStr(lpIMC->hCompStr, NULL, 0); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - flags = GCS_COMPSTR; - if (dwCompLen && lpComp) { - newCompStr = updateCompStr(lpIMC->hCompStr, (LPCWSTR)lpComp, dwCompLen / sizeof(WCHAR)); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - wParam = ((const WCHAR*)lpComp)[0]; - flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART; + flags = input_context_set_comp_str( lpIMC, FALSE, lpComp, dwCompLen / sizeof(WCHAR) ); + wParam = ((const WCHAR*)lpComp)[0]; } else { - newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; + flags = input_context_set_comp_str( lpIMC, FALSE, NULL, 0 ); } }
v2: Use -1 for `NtUserInputContextUIHwnd` to avoid failing win32u tests.
I understand that there's something wrong about this, anything in particular?
Byeongsik Jeon (@bsjeon) commented about dlls/imm32/ime.c:
- TRACE( "old_status %u, himc %p, result %u, str %s\n", old_status, himc, result, debugstr_wn(str, len) );
- if (!(ctx = ImmLockIMC( himc ))) return FALSE;
- if ((priv = ImmLockIMCC( ctx->hPrivate )))
- {
old_status = priv->bInComposition;
ImmUnlockIMCC( ctx->hPrivate );
- }
- flags = input_context_set_comp_str( ctx, result, str, len );
- ImmUnlockIMC( himc );
- if (!old_status) ImmSetOpenStatus( himc, TRUE );
- if (!result || !old_status) ime_set_composition_status( himc, hwnd, TRUE );
- ime_send_message( himc, WM_IME_COMPOSITION, len ? str[0] : 0, flags );
- if (result || !old_status) ime_set_composition_status( himc, hwnd, FALSE );
- if (!old_status) ImmSetOpenStatus( himc, FALSE );
In x11drv_time_set_result() and in this code, WM_IME_COMPOSITION(GCS_RESULTSTR) is always followed by WM_IME_ENDCOMPOSITION. And, in this code, WM_IME_COMPOSITION(GCS_COMPSTR) is always preceded by WM_IME_STARTCOMPOSITION.
Is this intended?
Overall, the IME message sequences are too dirty. In particular, for Korean input, preedit_string and result_string need to co-operate organically, which leads to a bad situation. Of course, this is an inherited problem from the old code.
In my opinion, it makes sense that the x11drv_ime_set_result() code is for case where the input_style is not XIMPreditcallbacks. How about moving some code to xim_set_result_string()?
For example,
``` +++ b/dlls/winex11.drv/xim.c @@ -126,7 +126,20 @@ void xim_set_result_string( HWND hwnd, const char *str, UINT count ) len = ntdll_umbstowcs( str, count, output, count ); output[len] = 0;
- send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, FALSE, (LPARAM)output ); + if (input_style & XIMPreeditCallbacks) + { + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, FALSE, (LPARAM)output ); + } + else + { + send_ime_ui_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, TRUE, 0 ); + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, TRUE, 0 ); + + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, FALSE, (LPARAM)output ); + + send_ime_ui_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, FALSE, 0 ); + send_ime_ui_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, FALSE, 0 ); + } ```
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131878
Your paranoid android.
=== debian11 (build log) ===
Task: Patch failed to apply
=== debian11b (build log) ===
Task: Patch failed to apply
In x11drv_ime_set_result() and in this code, WM_IME_COMPOSITION(GCS_RESULTSTR) is always followed by WM_IME_ENDCOMPOSITION. And, in this code, WM_IME_COMPOSITION(GCS_COMPSTR) is always preceded by WM_IME_STARTCOMPOSITION.
Is this intended?
Kind of, composition string updates are indeed preceded by WM_IME_STARTCOMPOSITION but only if the composition status indicates that we were not composing already. I think that wasn't done before and I added it as I think WM_IME_COMPOSITION messages are only supposed to be sent between WM_IME_STARTCOMPOSITION and WM_IME_ENDCOMPOSITION.
Overall, the IME message sequences are too dirty. In particular, for Korean input, preedit_string and result_string need to co-operate organically, which leads to a bad situation. Of course, this is an inherited problem from the old code.
I'm not completely sure to see what is wrong here. Usually I think this should get you this kind of message sequence: WM_IME_STARTCOMPOSITION > WM_IME_COMPOSITION(GCS_COMPSTR) (* n) > WM_IME_COMPOSITION(GCS_RESULTSTR) > WM_IME_ENDCOMPOSITION, is this wrong in any way?
In my opinion, it makes sense that the x11drv_ime_set_result() code is for case where the input_style is not XIMPreditcallbacks. How about moving some code to xim_set_result_string()?
I think we may be missing a reliable open/composing status at this level, and we may end up sending `WM_WINE_IME_SET_COMP_TEXT` messages with a closed IME. Maybe in this case the message should be dropped.