[PATCH 0/1] MR7827: imm32: Fix the WM_IME_COMPOSITION messages to be between the WM_IME_{START|END}COMPOSITION message.
This patch fixes a Japanese input issue in MS Office Visual Basic and Mery text editor ime inline mode. The following was considered: 1. Japanese ime: the result string message is always placed between WM_IME_STARTCOMPOSITION and WM_IME_ENDCOMPOSITION. Currently in Wine, the result string message follows WM_IME_ENDCOMPOSITION. dlls/imm32/tests/imm32.c::test_nihongo_no(). 2. Chinese ime: same as Japanese ime. 3. Korean ime: mostly the same, but there are some cases where it is not (e.g. CPS_COMPLETE, 'r-k-RETURN'). However, I haven't found any problem even if it behave like Japanese ime message order. 3. zero-length preedit string: as in MR !3115 commit d1f9aae, the message followed by WM_IME_ENDCOMPOSITION. Currently in Wine, it is associated with WM_IME_STARTCOMPOSITION. 4. zero-length result string: ignore. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7827
From: Byeongsik Jeon <bsjeon(a)hanmail.net> This patch fixes a Japanese input issue in MS Office Visual Basic and Mery text editor ime inline mode. The following was considered: 1. Japanese ime: the result string message is always placed between WM_IME_STARTCOMPOSITION and WM_IME_ENDCOMPOSITION. Currently in Wine, the result string message follows WM_IME_ENDCOMPOSITION. dlls/imm32/tests/imm32.c::test_nihongo_no(). 2. Chinese ime: same as Japanese ime. 3. Korean ime: mostly the same, but there are some cases where it is not (e.g. CPS_COMPLETE, 'r-k-RETURN'). However, I haven't found any problem even if it behave like Japanese ime message order. 3. zero-length preedit string: as in MR !3115 commit d1f9aae, the message followed by WM_IME_ENDCOMPOSITION. Currently in Wine, it is associated with WM_IME_STARTCOMPOSITION. 4. zero-length result string: ignore. --- dlls/imm32/ime.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index d7ffc3de115..5d4c92f99c9 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -561,14 +561,17 @@ UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, if (status) WARN( "WINE_IME_TO_ASCII_EX returned status %#lx\n", status ); else { - TRANSMSG status_msg = {.message = ime_set_composition_status( himc, !!compstr->dwCompStrOffset )}; - if (status_msg.message) msgs->TransMsg[count++] = status_msg; + if (compstr->dwCompStrLen || compstr->dwResultStrLen) + { + TRANSMSG msg = {.message = ime_set_composition_status( himc, TRUE )}; + if (msg.message == WM_IME_STARTCOMPOSITION) msgs->TransMsg[count++] = msg; + } - if (compstr->dwResultStrOffset) + if (compstr->dwResultStrLen) { const WCHAR *result = (WCHAR *)((BYTE *)compstr + compstr->dwResultStrOffset); TRANSMSG msg = {.message = WM_IME_COMPOSITION, .wParam = result[0], .lParam = GCS_RESULTSTR}; - if (compstr->dwResultClauseOffset) msg.lParam |= GCS_RESULTCLAUSE; + if (compstr->dwResultClauseLen) msg.lParam |= GCS_RESULTCLAUSE; msgs->TransMsg[count++] = msg; } @@ -582,6 +585,12 @@ UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, msgs->TransMsg[count++] = msg; } + if (!compstr->dwCompStrLen) + { + TRANSMSG msg = {.message = ime_set_composition_status( himc, FALSE )}; + if (msg.message == WM_IME_ENDCOMPOSITION) msgs->TransMsg[count++] = msg; + } + if (!key_consumed) { TRANSMSG msg = {.message = WM_IME_KEYDOWN, .wParam = vkey, .lParam = vsc}; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7827
To switch on ime inline mode in [Mery](https://www.haijin-boys.com/software/mery/mery-3-7-0#41) text editor, press "Alt+t-o" and tick "変換中の文字列を挿入モードで入力する".  -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7827#note_100929
Rémi Bernon (@rbernon) commented about dlls/imm32/ime.c:
+ { + TRANSMSG msg = {.message = ime_set_composition_status( himc, TRUE )}; + if (msg.message == WM_IME_STARTCOMPOSITION) msgs->TransMsg[count++] = msg; + }
- if (compstr->dwResultStrOffset) + if (compstr->dwResultStrLen) { const WCHAR *result = (WCHAR *)((BYTE *)compstr + compstr->dwResultStrOffset); TRANSMSG msg = {.message = WM_IME_COMPOSITION, .wParam = result[0], .lParam = GCS_RESULTSTR}; - if (compstr->dwResultClauseOffset) msg.lParam |= GCS_RESULTCLAUSE; + if (compstr->dwResultClauseLen) msg.lParam |= GCS_RESULTCLAUSE; msgs->TransMsg[count++] = msg; }
if (compstr->dwCompStrOffset) Shouldn't this be changed to dwCompStrLen as well to match the if on line [564](https://gitlab.winehq.org/wine/wine/-/merge_requests/7827/diffs?commit_id=74...) (and [588](https://gitlab.winehq.org/wine/wine/-/merge_requests/7827/diffs?commit_id=74...) changed to an else)?
Otherwise if dwCompStrOffset > 0 and dwCompStrLen == 0 we could send an (empty) WM_IME_COMPOSITION message outside of WM_IME_STARTCOMPOSITION/WM_IME_STARTCOMPOSITION? It's purely hypothetical as I don't think it's possible, but I think it's good to keep the conditions consistent. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7827#note_101016
On Wed Apr 16 08:13:29 2025 +0000, Rémi Bernon wrote:
Shouldn't this be changed to dwCompStrLen as well to match the if on line [564](https://gitlab.winehq.org/wine/wine/-/merge_requests/7827/diffs?commit_id=74...) (and [588](https://gitlab.winehq.org/wine/wine/-/merge_requests/7827/diffs?commit_id=74...) changed to an else)? Otherwise if dwCompStrOffset > 0 and dwCompStrLen == 0 we could send an (empty) WM_IME_COMPOSITION message outside of WM_IME_STARTCOMPOSITION/WM_IME_STARTCOMPOSITION? It's purely hypothetical as I don't think it's possible, but I think it's good to keep the conditions consistent. Yes. This is possible if we handle the empty WM_IME_COMPOSITION handling in the WM_IME_ENDCOMPOSITION part.
As in d1f9aae5, the empty WM_IME_COMPOSITION is wparam==0x1b, lparam==0x1bf, but I left the code in because it was ambiguous. If ime_to_tascii_ex doesn't update 'compstr' for empty string, I think it should be fine for lparam==0x1lbf. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/7827#note_101024
On Wed Apr 16 09:04:11 2025 +0000, Byeongsik Jeon wrote:
Yes. This is possible if we handle the empty WM_IME_COMPOSITION handling in the WM_IME_ENDCOMPOSITION part. As in d1f9aae5, the empty WM_IME_COMPOSITION is wparam==0x1b, lparam==0x1bf, but I left the code in because it was ambiguous. If ime_to_tascii_ex doesn't update 'compstr' for empty string, I think it should be fine for lparam==0x1lbf. Hmm... Then maybe we should check for dwCompStrOffset instead of dwCompStrLen when sending WM_IME_STARTCOMPOSITION/WM_IME_ENDCOMPOSITION on lines 564 and 588?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/7827#note_101025
participants (3)
-
Byeongsik Jeon -
Byeongsik Jeon (@bsjeon) -
Rémi Bernon