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