This fixes the behavior in notepad, with Japanese ibus-mozc IME, when typing "NIHONGO-SPACE-NO", or with Korean ibus-hangul when typing "GA-NA-DA". The latter still has an issue with the last character not appearing in the a composition but I believe it is unrelated to comctl32 and will be fixed by some future imm32 changes.
-- v4: user32/edit: Delegate composition string rendering to the IME UI. user32/edit: Notify IME on position, format_rect and font changes. comctl32/edit: Delegate composition string rendering to the IME UI. comctl32/edit: Notify IME on caret position, format_rect and font changes. imm32: Use DrawTextW to wrap IME composition string. imm32: Update the IME composition window position after drawing.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 3c4550c3cd9..8774e714365 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -96,7 +96,7 @@ static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) static void ime_ui_paint( HIMC himc, HWND hwnd ) { PAINTSTRUCT ps; - RECT rect; + RECT rect, new_rect; HDC hdc; HMONITOR monitor; MONITORINFO mon_info; @@ -111,6 +111,7 @@ static void ime_ui_paint( HIMC himc, HWND hwnd )
GetClientRect( hwnd, &rect ); FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) ); + new_rect = rect;
if ((str = input_context_get_comp_str( ctx, FALSE, &len ))) { @@ -143,6 +144,7 @@ static void ime_ui_paint( HIMC himc, HWND hwnd ) rect.top = cpt.y; rect.right = rect.left + pt.x; rect.bottom = rect.top + pt.y; + offset.x = offset.y = 0; monitor = MonitorFromPoint( cpt, MONITOR_DEFAULTTOPRIMARY ); } else /* CFS_DEFAULT */ @@ -193,8 +195,7 @@ static void ime_ui_paint( HIMC himc, HWND hwnd ) } }
- SetWindowPos( hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, SWP_NOACTIVATE ); + new_rect = rect; TextOutW( hdc, offset.x, offset.y, str, len );
if (font) SelectObject( hdc, font ); @@ -203,6 +204,10 @@ static void ime_ui_paint( HIMC himc, HWND hwnd )
EndPaint( hwnd, &ps ); ImmUnlockIMC( himc ); + + if (!EqualRect( &rect, &new_rect )) + SetWindowPos( hwnd, HWND_TOPMOST, new_rect.left, new_rect.top, new_rect.right - new_rect.left, + new_rect.bottom - new_rect.top, SWP_NOACTIVATE ); }
static void ime_ui_update_window( INPUTCONTEXT *ctx, HWND hwnd )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 8774e714365..8866f8f28f6 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -163,11 +163,10 @@ static void ime_ui_paint( HIMC himc, HWND hwnd )
if (ctx->cfCompForm.dwStyle == CFS_RECT) { - RECT client; - client = ctx->cfCompForm.rcArea; + RECT client = ctx->cfCompForm.rcArea; MapWindowPoints( ctx->hWnd, 0, (POINT *)&client, 2 ); IntersectRect( &rect, &rect, &client ); - /* TODO: Wrap the input if needed */ + DrawTextW( hdc, str, len, &rect, DT_WORDBREAK | DT_CALCRECT ); }
if (ctx->cfCompForm.dwStyle == CFS_DEFAULT) @@ -196,7 +195,8 @@ static void ime_ui_paint( HIMC himc, HWND hwnd ) }
new_rect = rect; - TextOutW( hdc, offset.x, offset.y, str, len ); + OffsetRect( &rect, offset.x - rect.left, offset.y - rect.top ); + DrawTextW( hdc, str, len, &rect, DT_WORDBREAK );
if (font) SelectObject( hdc, font ); free( str );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/comctl32/edit.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/dlls/comctl32/edit.c b/dlls/comctl32/edit.c index 883dd5d9145..352143f8159 100644 --- a/dlls/comctl32/edit.c +++ b/dlls/comctl32/edit.c @@ -38,6 +38,7 @@ #include "windef.h" #include "winbase.h" #include "winnt.h" +#include "wingdi.h" #include "imm.h" #include "usp10.h" #include "commctrl.h" @@ -1697,6 +1698,20 @@ static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action) }
+static void EDIT_UpdateImmCompositionWindow(EDITSTATE *es, UINT x, UINT y) +{ + COMPOSITIONFORM form = + { + .dwStyle = CFS_RECT, + .ptCurrentPos = {.x = x, .y = y}, + .rcArea = es->format_rect, + }; + HIMC himc = ImmGetContext(es->hwndSelf); + ImmSetCompositionWindow(himc, &form); + ImmReleaseContext(es->hwndSelf, himc); +} + + /********************************************************************* * * EDIT_SetCaretPos @@ -1712,6 +1727,7 @@ static void EDIT_SetCaretPos(EDITSTATE *es, INT pos, res = EDIT_EM_PosFromChar(es, pos, after_wrap); TRACE("%d - %dx%d\n", pos, (short)LOWORD(res), (short)HIWORD(res)); SetCaretPos((short)LOWORD(res), (short)HIWORD(res)); + EDIT_UpdateImmCompositionWindow(es, (short)LOWORD(res), (short)HIWORD(res)); } }
@@ -3728,6 +3744,15 @@ static DWORD get_font_margins(HDC hdc, const TEXTMETRICW *tm) return MAKELONG(left, right); }
+static void EDIT_UpdateImmCompositionFont(EDITSTATE *es) +{ + LOGFONTW composition_font; + HIMC himc = ImmGetContext(es->hwndSelf); + GetObjectW(es->font, sizeof(LOGFONTW), &composition_font); + ImmSetCompositionFontW(himc, &composition_font); + ImmReleaseContext(es->hwndSelf, himc); +} + /********************************************************************* * * WM_SETFONT @@ -3779,6 +3804,8 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw) es->flags & EF_AFTER_WRAP); ShowCaret(es->hwndSelf); } + + EDIT_UpdateImmCompositionFont(es); }
@@ -4593,6 +4620,7 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR EDITSTATE *es = (EDITSTATE *)GetWindowLongPtrW(hwnd, 0); LRESULT result = 0; RECT *rect; + POINT pt;
TRACE("hwnd %p, msg %#x, wparam %Ix, lparam %Ix\n", hwnd, msg, wParam, lParam);
@@ -5048,6 +5076,9 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
/* IME messages to make the edit control IME aware */ case WM_IME_SETCONTEXT: + GetCaretPos(&pt); + EDIT_UpdateImmCompositionWindow(es, pt.x, pt.y); + EDIT_UpdateImmCompositionFont(es); break;
case WM_IME_STARTCOMPOSITION:
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/comctl32/edit.c | 167 ++++--------------------------------------- 1 file changed, 13 insertions(+), 154 deletions(-)
diff --git a/dlls/comctl32/edit.c b/dlls/comctl32/edit.c index 352143f8159..5746370d536 100644 --- a/dlls/comctl32/edit.c +++ b/dlls/comctl32/edit.c @@ -141,9 +141,8 @@ typedef struct /* * IME Data */ - UINT composition_len; /* length of composition, 0 == no composition */ - int composition_start; /* the character position for the composition */ - UINT ime_status; /* IME status flag */ + UINT ime_status; /* IME status flag */ + /* * Uniscribe Data */ @@ -2068,9 +2067,6 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col { COLORREF BkColor; COLORREF TextColor; - LOGFONTW underline_font; - HFONT hUnderline = 0; - HFONT old_font = 0; INT ret; INT li; INT BkMode; @@ -2082,20 +2078,9 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col BkColor = GetBkColor(dc); TextColor = GetTextColor(dc); if (rev) { - if (es->composition_len == 0) - { - SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); - SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkMode( dc, OPAQUE); - } - else - { - HFONT current = GetCurrentObject(dc,OBJ_FONT); - GetObjectW(current,sizeof(LOGFONTW),&underline_font); - underline_font.lfUnderline = TRUE; - hUnderline = CreateFontIndirectW(&underline_font); - old_font = SelectObject(dc,hUnderline); - } + SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); + SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkMode( dc, OPAQUE); } li = EDIT_EM_LineIndex(es, line); if (es->style & ES_MULTILINE) { @@ -2107,19 +2092,9 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col ret = size.cx; } if (rev) { - if (es->composition_len == 0) - { - SetBkColor(dc, BkColor); - SetTextColor(dc, TextColor); - SetBkMode( dc, BkMode); - } - else - { - if (old_font) - SelectObject(dc,old_font); - if (hUnderline) - DeleteObject(hUnderline); - } + SetBkColor(dc, BkColor); + SetTextColor(dc, TextColor); + SetBkMode( dc, BkMode); } return ret; } @@ -4278,75 +4253,6 @@ static BOOL EDIT_EM_GetCueBanner(EDITSTATE *es, WCHAR *buf, DWORD size) * The Following code is to handle inline editing from IMEs */
-static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) -{ - LONG buflen; - LPWSTR lpCompStr; - LPSTR lpCompStrAttr = NULL; - DWORD dwBufLenAttr; - - buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); - - if (buflen < 0) - { - return; - } - - lpCompStr = Alloc(buflen); - if (!lpCompStr) - { - ERR("Unable to allocate IME CompositionString\n"); - return; - } - - if (buflen) - ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, buflen); - - if (CompFlag & GCS_COMPATTR) - { - /* - * We do not use the attributes yet. it would tell us what characters - * are in transition and which are converted or decided upon - */ - dwBufLenAttr = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0); - if (dwBufLenAttr) - { - dwBufLenAttr ++; - lpCompStrAttr = Alloc(dwBufLenAttr + 1); - if (!lpCompStrAttr) - { - ERR("Unable to allocate IME Attribute String\n"); - Free(lpCompStr); - return; - } - ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr, - dwBufLenAttr); - lpCompStrAttr[dwBufLenAttr] = 0; - } - } - - /* check for change in composition start */ - if (es->selection_end < es->composition_start) - es->composition_start = es->selection_end; - - /* replace existing selection string */ - es->selection_start = es->composition_start; - - if (es->composition_len > 0) - es->selection_end = es->composition_start + es->composition_len; - else - es->selection_end = es->selection_start; - - EDIT_EM_ReplaceSel(es, FALSE, lpCompStr, buflen / sizeof(WCHAR), TRUE, TRUE); - es->composition_len = abs(es->composition_start - es->selection_end); - - es->selection_start = es->composition_start; - es->selection_end = es->selection_start + es->composition_len; - - Free(lpCompStrAttr); - Free(lpCompStr); -} - static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) { LONG buflen; @@ -4366,48 +4272,22 @@ static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) }
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, buflen); - - /* check for change in composition start */ - if (es->selection_end < es->composition_start) - es->composition_start = es->selection_end; - - es->selection_start = es->composition_start; - es->selection_end = es->composition_start + es->composition_len; EDIT_EM_ReplaceSel(es, TRUE, lpResultStr, buflen / sizeof(WCHAR), TRUE, TRUE); - es->composition_start = es->selection_end; - es->composition_len = 0; - Free(lpResultStr); }
static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es) { HIMC hIMC; - int cursor; - - if (es->composition_len == 0 && es->selection_start != es->selection_end) - { - EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); - es->composition_start = es->selection_end; - }
hIMC = ImmGetContext(hwnd); if (!hIMC) return;
if (CompFlag & GCS_RESULTSTR) - { EDIT_GetResultStr(hIMC, es); - cursor = 0; - } - else - { - if (CompFlag & GCS_COMPSTR) - EDIT_GetCompositionStr(hIMC, CompFlag, es); - cursor = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, 0, 0); - } + ImmReleaseContext(hwnd, hIMC); - EDIT_SetCaretPos(es, es->selection_start + cursor, es->flags & EF_AFTER_WRAP); }
@@ -5081,32 +4961,11 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR EDIT_UpdateImmCompositionFont(es); break;
- case WM_IME_STARTCOMPOSITION: - es->composition_start = es->selection_end; - es->composition_len = 0; - break; - case WM_IME_COMPOSITION: - if (lParam & GCS_RESULTSTR && !(es->ime_status & EIMES_GETCOMPSTRATONCE)) - { - DefWindowProcW(hwnd, msg, wParam, lParam); - break; - } - - EDIT_ImeComposition(hwnd, lParam, es); - break; - - case WM_IME_ENDCOMPOSITION: - if (es->composition_len > 0) - { - EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); - es->selection_end = es->selection_start; - es->composition_len= 0; - } - break; - - case WM_IME_COMPOSITIONFULL: - break; + EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); + if ((lParam & GCS_RESULTSTR) && (es->ime_status & EIMES_GETCOMPSTRATONCE)) + EDIT_ImeComposition(hwnd, lParam, es); + return DefWindowProcW(hwnd, msg, wParam, lParam);
case WM_IME_SELECT: break;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/edit.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index 47c61f59c24..dc5660dd6c7 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -1779,6 +1779,20 @@ static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action) }
+static void EDIT_UpdateImmCompositionWindow(EDITSTATE *es, UINT x, UINT y) +{ + COMPOSITIONFORM form = + { + .dwStyle = CFS_RECT, + .ptCurrentPos = {.x = x, .y = y}, + .rcArea = es->format_rect, + }; + HIMC himc = ImmGetContext(es->hwndSelf); + ImmSetCompositionWindow(himc, &form); + ImmReleaseContext(es->hwndSelf, himc); +} + + /********************************************************************* * * EDIT_SetCaretPos @@ -1794,6 +1808,7 @@ static void EDIT_SetCaretPos(EDITSTATE *es, INT pos, res = EDIT_EM_PosFromChar(es, pos, after_wrap); TRACE("%d - %dx%d\n", pos, (short)LOWORD(res), (short)HIWORD(res)); SetCaretPos((short)LOWORD(res), (short)HIWORD(res)); + EDIT_UpdateImmCompositionWindow(es, (short)LOWORD(res), (short)HIWORD(res)); } }
@@ -3841,6 +3856,15 @@ static DWORD get_font_margins(HDC hdc, const TEXTMETRICW *tm, BOOL unicode) return MAKELONG(left, right); }
+static void EDIT_UpdateImmCompositionFont(EDITSTATE *es) +{ + LOGFONTW composition_font; + HIMC himc = ImmGetContext(es->hwndSelf); + GetObjectW(es->font, sizeof(LOGFONTW), &composition_font); + ImmSetCompositionFontW(himc, &composition_font); + ImmReleaseContext(es->hwndSelf, himc); +} + /********************************************************************* * * WM_SETFONT @@ -3892,6 +3916,8 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw) es->flags & EF_AFTER_WRAP); NtUserShowCaret( es->hwndSelf ); } + + EDIT_UpdateImmCompositionFont(es); }
@@ -4687,6 +4713,7 @@ LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, B { EDITSTATE *es = (EDITSTATE *)GetWindowLongPtrW( hwnd, 0 ); LRESULT result = 0; + POINT pt;
TRACE("hwnd=%p msg=%x (%s) wparam=%Ix lparam=%Ix\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), wParam, lParam);
@@ -5198,6 +5225,9 @@ LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, B
/* IME messages to make the edit control IME aware */ case WM_IME_SETCONTEXT: + NtUserGetCaretPos(&pt); + EDIT_UpdateImmCompositionWindow(es, pt.x, pt.y); + EDIT_UpdateImmCompositionFont(es); break;
case WM_IME_STARTCOMPOSITION:
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/edit.c | 167 ++++----------------------------------------- 1 file changed, 13 insertions(+), 154 deletions(-)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index dc5660dd6c7..6ce53983b6f 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -128,9 +128,8 @@ typedef struct /* * IME Data */ - UINT composition_len; /* length of composition, 0 == no composition */ - int composition_start; /* the character position for the composition */ - UINT ime_status; /* IME status flag */ + UINT ime_status; /* IME status flag */ + /* * Uniscribe Data */ @@ -2149,9 +2148,6 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col { COLORREF BkColor; COLORREF TextColor; - LOGFONTW underline_font; - HFONT hUnderline = 0; - HFONT old_font = 0; INT ret; INT li; INT BkMode; @@ -2163,20 +2159,9 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col BkColor = GetBkColor(dc); TextColor = GetTextColor(dc); if (rev) { - if (es->composition_len == 0) - { - SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); - SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkMode( dc, OPAQUE); - } - else - { - HFONT current = GetCurrentObject(dc,OBJ_FONT); - GetObjectW(current,sizeof(LOGFONTW),&underline_font); - underline_font.lfUnderline = TRUE; - hUnderline = CreateFontIndirectW(&underline_font); - old_font = SelectObject(dc,hUnderline); - } + SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); + SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkMode( dc, OPAQUE); } li = EDIT_EM_LineIndex(es, line); if (es->style & ES_MULTILINE) { @@ -2188,19 +2173,9 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col ret = size.cx; } if (rev) { - if (es->composition_len == 0) - { - SetBkColor(dc, BkColor); - SetTextColor(dc, TextColor); - SetBkMode( dc, BkMode); - } - else - { - if (old_font) - SelectObject(dc,old_font); - if (hUnderline) - DeleteObject(hUnderline); - } + SetBkColor(dc, BkColor); + SetTextColor(dc, TextColor); + SetBkMode( dc, BkMode); } return ret; } @@ -4362,75 +4337,6 @@ static LRESULT EDIT_EM_GetThumb(EDITSTATE *es) * The Following code is to handle inline editing from IMEs */
-static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) -{ - LONG buflen; - LPWSTR lpCompStr; - LPSTR lpCompStrAttr = NULL; - DWORD dwBufLenAttr; - - buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); - - if (buflen < 0) - { - return; - } - - lpCompStr = HeapAlloc(GetProcessHeap(),0,buflen); - if (!lpCompStr) - { - ERR("Unable to allocate IME CompositionString\n"); - return; - } - - if (buflen) - ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, buflen); - - if (CompFlag & GCS_COMPATTR) - { - /* - * We do not use the attributes yet. it would tell us what characters - * are in transition and which are converted or decided upon - */ - dwBufLenAttr = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0); - if (dwBufLenAttr) - { - dwBufLenAttr ++; - lpCompStrAttr = HeapAlloc(GetProcessHeap(),0,dwBufLenAttr+1); - if (!lpCompStrAttr) - { - ERR("Unable to allocate IME Attribute String\n"); - HeapFree(GetProcessHeap(),0,lpCompStr); - return; - } - ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr, - dwBufLenAttr); - lpCompStrAttr[dwBufLenAttr] = 0; - } - } - - /* check for change in composition start */ - if (es->selection_end < es->composition_start) - es->composition_start = es->selection_end; - - /* replace existing selection string */ - es->selection_start = es->composition_start; - - if (es->composition_len > 0) - es->selection_end = es->composition_start + es->composition_len; - else - es->selection_end = es->selection_start; - - EDIT_EM_ReplaceSel(es, FALSE, lpCompStr, buflen / sizeof(WCHAR), TRUE, TRUE); - es->composition_len = abs(es->composition_start - es->selection_end); - - es->selection_start = es->composition_start; - es->selection_end = es->selection_start + es->composition_len; - - HeapFree(GetProcessHeap(),0,lpCompStrAttr); - HeapFree(GetProcessHeap(),0,lpCompStr); -} - static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) { LONG buflen; @@ -4450,48 +4356,22 @@ static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) }
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, buflen); - - /* check for change in composition start */ - if (es->selection_end < es->composition_start) - es->composition_start = es->selection_end; - - es->selection_start = es->composition_start; - es->selection_end = es->composition_start + es->composition_len; EDIT_EM_ReplaceSel(es, TRUE, lpResultStr, buflen / sizeof(WCHAR), TRUE, TRUE); - es->composition_start = es->selection_end; - es->composition_len = 0; - HeapFree(GetProcessHeap(),0,lpResultStr); }
static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es) { HIMC hIMC; - int cursor; - - if (es->composition_len == 0 && es->selection_start != es->selection_end) - { - EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); - es->composition_start = es->selection_end; - }
hIMC = ImmGetContext(hwnd); if (!hIMC) return;
if (CompFlag & GCS_RESULTSTR) - { EDIT_GetResultStr(hIMC, es); - cursor = 0; - } - else - { - if (CompFlag & GCS_COMPSTR) - EDIT_GetCompositionStr(hIMC, CompFlag, es); - cursor = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, 0, 0); - } + ImmReleaseContext(hwnd, hIMC); - EDIT_SetCaretPos(es, es->selection_start + cursor, es->flags & EF_AFTER_WRAP); }
@@ -5230,32 +5110,11 @@ LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, B EDIT_UpdateImmCompositionFont(es); break;
- case WM_IME_STARTCOMPOSITION: - es->composition_start = es->selection_end; - es->composition_len = 0; - break; - case WM_IME_COMPOSITION: - if (lParam & GCS_RESULTSTR && !(es->ime_status & EIMES_GETCOMPSTRATONCE)) - { - DefWindowProcT(hwnd, msg, wParam, lParam, unicode); - break; - } - - EDIT_ImeComposition(hwnd, lParam, es); - break; - - case WM_IME_ENDCOMPOSITION: - if (es->composition_len > 0) - { - EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); - es->selection_end = es->selection_start; - es->composition_len= 0; - } - break; - - case WM_IME_COMPOSITIONFULL: - break; + EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); + if ((lParam & GCS_RESULTSTR) && (es->ime_status & EIMES_GETCOMPSTRATONCE)) + EDIT_ImeComposition(hwnd, lParam, es); + return DefWindowProcW(hwnd, msg, wParam, lParam);
case WM_IME_SELECT: break;
I've changed the implementation to delegate the IME composition string rendering to the IME UI. Windows does the same for some IME, though not when using the Korean IME somehow. I'm not sure how the edit control decides that, but it's maybe not worth worrying too much for now, and factoring the rendering in imm32 makes the code simpler.
I have implemented a simple text wrapping support, using `DrawTextW`, which should hopefully be good enough. The display could be later improved in imm32, using uniscribe or something else, but I have no idea what would be a good choice.
The composition string is displayed on top of the edit control, and doesn't move the underlying text. This is a little bit similar to Windows, but it still looks like it manages to shift some text there, though it's not clear how and it's also not very accurate either, so hopefully also something that could be improved later.
Lastly, because imm32 is not using uniscribe, the font looks very slightly different. Again, hopefully not a big deal. I think in some cases the display is also a bit redundant with the host IME display.
The composition string is displayed on top of the edit control, and doesn't move the underlying text. This is a little bit similar to Windows, but it still looks like it manages to shift some text there, though it's not clear how and it's also not very accurate either, so hopefully also something that could be improved later.
Actually I misremembered, and MS Japanese IME doesn't move the edit text while compositing. It overlaps the edit control just like it's done here.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/edit.c:
{
SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
SetBkMode( dc, OPAQUE);
}
else
{
HFONT current = GetCurrentObject(dc,OBJ_FONT);
GetObjectW(current,sizeof(LOGFONTW),&underline_font);
underline_font.lfUnderline = TRUE;
hUnderline = CreateFontIndirectW(&underline_font);
old_font = SelectObject(dc,hUnderline);
}
SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
SetBkMode( dc, OPAQUE);
Remove the space after SetBkMode( while you're at it.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/edit.c:
if (es->composition_len == 0)
{
SetBkColor(dc, BkColor);
SetTextColor(dc, TextColor);
SetBkMode( dc, BkMode);
}
else
{
if (old_font)
SelectObject(dc,old_font);
if (hUnderline)
DeleteObject(hUnderline);
}
SetBkColor(dc, BkColor);
SetTextColor(dc, TextColor);
SetBkMode( dc, BkMode);
Same here.
I am having trouble using a Japanese IME. Bug 53860 is fixed by this, right? The new revision is missing a Wine-Bug.
On Thu May 11 04:43:10 2023 +0000, Zhiyi Zhang wrote:
I am having trouble using a Japanese IME. Bug 53860 is fixed by this, right? The new revision is missing a Wine-Bug.
Here we will need the name, version, and test key sequences of the Japanese IME you tested.
On Thu May 11 04:43:09 2023 +0000, Byeongsik Jeon wrote:
Here we will need the name, version, and test key sequences of the Japanese IME you tested.
Sorry, misread.
The new patch is not a direct fix for the old code. It's a fix to make the edit control follow the behaviour of the MS native edit control. This structural modification will not cause the EIMES_GETCOMPSTRATONCE issue.