From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53860 --- dlls/user32/edit.c | 201 +++++++++++++++++++++++++-------------------- 1 file changed, 114 insertions(+), 87 deletions(-)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index 47c61f59c24..df9e184e408 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -128,8 +128,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 @@ -367,6 +367,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 = NtUserGetDC(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) + NtUserReleaseDC(es->hwndSelf, udc); + } + + return es->composition_ssa; +} + static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HDC dc, LINEDEF *line_def) { if (!line_def) @@ -2125,6 +2149,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 @@ -2134,9 +2202,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; @@ -2148,20 +2213,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) { @@ -2173,19 +2227,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; } @@ -2198,6 +2242,7 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col */ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev) { + BOOL comp = FALSE; INT s = 0; INT e = 0; INT li = 0; @@ -2253,19 +2298,30 @@ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev) ll = EDIT_EM_LineLength(es, li); s = min(es->selection_start, es->selection_end); e = max(es->selection_start, es->selection_end); + if (s >= li && s <= li + ll) comp = TRUE; s = min(li + ll, max(li, s)); e = min(li + ll, max(li, e)); }
if (ssa) + { ScriptStringOut(ssa, x, y, 0, &es->format_rect, s - li, e - li, FALSE); + ScriptStringCPtoX(ssa, s - li - 1, TRUE, &x); + if (comp) 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); + if (comp) 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); + if (comp) x += EDIT_PaintComposition(es, dc, x, y); + x += EDIT_PaintText(es, dc, x, y, line, s - li, li + ll - s, FALSE); + } }
@@ -4343,6 +4399,14 @@ static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) LPSTR lpCompStrAttr = NULL; DWORD dwBufLenAttr;
+ HeapFree(GetProcessHeap(), 0, 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) @@ -4350,7 +4414,7 @@ static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) return; }
- lpCompStr = HeapAlloc(GetProcessHeap(),0,buflen); + lpCompStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen + sizeof(WCHAR)); if (!lpCompStr) { ERR("Unable to allocate IME CompositionString\n"); @@ -4383,26 +4447,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; - HeapFree(GetProcessHeap(),0,lpCompStrAttr); - HeapFree(GetProcessHeap(),0,lpCompStr); + es->composition_text = lpCompStr; + + es->flags |= EF_UPDATE; + EDIT_UpdateText(es, NULL, TRUE); }
static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) @@ -4425,47 +4474,26 @@ 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) - { + 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) 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); - } + else if (CompFlag & GCS_COMPSTR) + EDIT_GetCompositionStr(hIMC, CompFlag, es); ImmReleaseContext(hwnd, hIMC); - EDIT_SetCaretPos(es, es->selection_start + cursor, es->flags & EF_AFTER_WRAP); }
@@ -5201,8 +5229,6 @@ LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, B break;
case WM_IME_STARTCOMPOSITION: - es->composition_start = es->selection_end; - es->composition_len = 0; break;
case WM_IME_COMPOSITION: @@ -5216,13 +5242,14 @@ LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, B 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; + HeapFree(GetProcessHeap(), 0, es->composition_text); + es->composition_text = NULL; + if (es->composition_ssa) + { + ScriptStringFree(&es->composition_ssa); + es->composition_ssa = NULL; + } + break;
case WM_IME_COMPOSITIONFULL: break;