From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53860 --- dlls/comctl32/edit.c | 181 +++++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 74 deletions(-)
diff --git a/dlls/comctl32/edit.c b/dlls/comctl32/edit.c index 883dd5d9145..cfb6b20069d 100644 --- a/dlls/comctl32/edit.c +++ b/dlls/comctl32/edit.c @@ -140,8 +140,8 @@ typedef struct /* * IME Data */ - UINT composition_len; /* length of composition, 0 == no composition */ - int composition_start; /* the character position for the composition */ + LPWSTR composition_text; /* the contents of the composition string */ + SCRIPT_STRING_ANALYSIS composition_ssa; UINT ime_status; /* IME status flag */ /* * Uniscribe Data @@ -318,6 +318,30 @@ static inline void EDIT_InvalidateUniscribeData(EDITSTATE *es) } }
+static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_composition(EDITSTATE *es, HDC dc, INT length) +{ + if (!es->composition_ssa) + { + HFONT old_font = NULL; + HDC udc = dc; + + if (!udc) + udc = GetDC(es->hwndSelf); + if (es->font) + old_font = SelectObject(udc, es->font); + + ScriptStringAnalyse(udc, es->composition_text, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS, + -1, NULL, NULL, NULL, NULL, NULL, &es->composition_ssa); + + if (es->font) + SelectObject(udc, old_font); + if (udc != dc) + ReleaseDC(es->hwndSelf, udc); + } + + return es->composition_ssa; +} + static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HDC dc, LINEDEF *line_def) { if (!line_def) @@ -2043,6 +2067,50 @@ static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend) }
+static INT EDIT_PaintComposition(EDITSTATE *es, HDC dc, INT x, INT y) +{ + LOGFONTW underline_font; + HFONT underline, old_font; + SCRIPT_ANALYSIS *ssa; + INT ret, count; + HFONT current; + SIZE size; + + if (!es->composition_text) + return 0; + count = wcslen(es->composition_text); + + ssa = EDIT_UpdateUniscribeData_composition(es, dc, count); + if (ssa) + { + ScriptStringOut(ssa, x, y, 0, &es->format_rect, 0, count, FALSE); + ScriptStringCPtoX(ssa, count - 1, TRUE, &ret); + return ret; + } + + current = GetCurrentObject(dc,OBJ_FONT); + GetObjectW(current,sizeof(LOGFONTW),&underline_font); + underline_font.lfUnderline = TRUE; + underline = CreateFontIndirectW(&underline_font); + old_font = SelectObject(dc,underline); + + if (es->style & ES_MULTILINE) { + ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->composition_text, count, + es->tabs_count, es->tabs, es->format_rect.left - es->x_offset)); + } else { + TextOutW(dc, x, y, es->composition_text, count); + GetTextExtentPoint32W(dc, es->composition_text, count, &size); + ret = size.cx; + } + + if (old_font) + SelectObject(dc,old_font); + if (underline) + DeleteObject(underline); + + return ret; +} + /********************************************************************* * * EDIT_PaintText @@ -2052,9 +2120,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; @@ -2066,20 +2131,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) { @@ -2091,19 +2145,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; } @@ -2176,14 +2220,24 @@ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev) }
if (ssa) + { ScriptStringOut(ssa, x, y, 0, &es->format_rect, s - li, e - li, FALSE); + ScriptStringCPtoX(ssa, s - li - 1, TRUE, &x); + EDIT_PaintComposition(es, dc, x, y); + } else if (rev && (s != e) && ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) { x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE); + x += EDIT_PaintComposition(es, dc, x, y); x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE); x += EDIT_PaintText(es, dc, x, y, line, e - li, li + ll - e, FALSE); - } else - x += EDIT_PaintText(es, dc, x, y, line, 0, ll, FALSE); + } + else + { + x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE); + x += EDIT_PaintComposition(es, dc, x, y); + x += EDIT_PaintText(es, dc, x, y, line, s - li, li + ll - s, FALSE); + }
if (es->cue_banner_text && es->text_length == 0 && (!(es->flags & EF_FOCUSED) || es->cue_banner_draw_focused)) { @@ -4258,14 +4312,21 @@ static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) LPSTR lpCompStrAttr = NULL; DWORD dwBufLenAttr;
- buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); + Free(es->composition_text); + es->composition_text = NULL; + if (es->composition_ssa) + { + ScriptStringFree(&es->composition_ssa); + es->composition_ssa = NULL; + }
+ buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); if (buflen < 0) { return; }
- lpCompStr = Alloc(buflen); + lpCompStr = Alloc(buflen + sizeof(WCHAR)); if (!lpCompStr) { ERR("Unable to allocate IME CompositionString\n"); @@ -4298,26 +4359,11 @@ static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) } }
- /* 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); + es->composition_text = lpCompStr; + + es->flags |= EF_UPDATE; + EDIT_UpdateText(es, NULL, TRUE); }
static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) @@ -4340,16 +4386,7 @@ 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); }
@@ -4358,11 +4395,8 @@ 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) - { + if (!es->composition_text && 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) @@ -5051,8 +5085,6 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR break;
case WM_IME_STARTCOMPOSITION: - es->composition_start = es->selection_end; - es->composition_len = 0; break;
case WM_IME_COMPOSITION: @@ -5066,11 +5098,12 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR break;
case WM_IME_ENDCOMPOSITION: - if (es->composition_len > 0) + Free(es->composition_text); + es->composition_text = NULL; + if (es->composition_ssa) { - EDIT_EM_ReplaceSel(es, TRUE, NULL, 0, TRUE, TRUE); - es->selection_end = es->selection_start; - es->composition_len= 0; + ScriptStringFree(&es->composition_ssa); + es->composition_ssa = NULL; } break;