From 02c15ae9f730671e7596b3e4063fec31a72d37de Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Mon, 12 Jan 2009 22:03:00 +0000 Subject: [PATCH] Sync edit.c with wine head (Wine-1_1_12) Reduces failures from 18 to 13 and test doesn't keep a window open anymore. (Partly) revert 29649, 33848, 33909, 33910 as it's now implemented by wine 1.4 Francois Gouget Don't put single quotes around '%s' when using the debugstr_*() functions. 1.5 Huw Davies user32: Keep track of whether the app has asked for the text buffer handle. 1.9 Dmitry Timoshkov user32: Fix some compilation warnings in 64-bit mode. 1.15 Alexandre Julliard user32: Store the builtin class names in Unicode. 1.16 Andrew Talbot user32: Constify some variables. 1.17 Gerald Pfeifer user32: Factor in EDIT_WM_EraseBkGnd(). 1.18 Andrew Talbot user32: Remove unneeded casts. 1.19 Marcus Meissner user32: Handle error returns from ImmGetCompositionString. 1.20 Lei Zhang user32: Tweak how the edit control handles WM_GETDLGCODE. 1.21 Lei Zhang user32: Handle WM_CHAR messages better in edit controls. 1.22 Lei Zhang user32: Correctly handle VK_RETURN for edit controls with ES_WANTRETURN style. 1.23 Lei Zhang user32: Fix WM_CHAR return value for edit controls. 1.24 Lei Zhang user32: Handle ES_MULTILINE correctly for WM_KEYDOWN/VK_RETURN. 1.25 Lei Zhang user32: Handle VK_ESCAPE correctly in EDIT_WM_KeyDown. 1.26 Lei Zhang user32: Add edit control check to see if its in a dialog on WM_CHAR/VK_RETURN. 1.27 Lei Zhang user32: Add edit control check to see if its in a dialog on WM_CHAR/VK_TAB. 1.28 Lei Zhang user32: Fix a typo. 1.29 Lei Zhang user32: Handle VK_TAB in EDIT_WM_KeyDown. 1.30 Lei Zhang user32: Do checks in the right order in EDIT_BuildLineDefs_ML. 1.31 Lei Zhang user32: Handle ctrl + home in edit control. 1.32 Lei Zhang user32: Handle ctrl + end in edit control. 1.33 Alexandre Julliard user32: Added support for WS_EX_RIGHT in the edit control. 1.34 Kusanagi Kouichi user32: Handle IME messages more gracefully. 1.35 Alexandre Julliard user32: Remove redundant LocalUnlock calls. 1.36 Austin English Spelling fixes. 1.37 Lei Zhang user32: Handle VK_RETURN WM_KEYDOWN events better in edit controls. Elias Benali wrote the initial version of this patch. 1.38 Lei Zhang user32: Edit controls should ignore WM_KEYDOWN on control + enter. 1.39 Andrew Talbot user32: Remove unused variables. 1.40 Hongbo Ni user32: Implement WM_UNICHAR for edit control. 1.41 Lei Zhang user32: Send messages for edit control context menu operations. 1.42 Aric Stewart user32: Make sure our vertical line count is at least 1 even if there is an oversized font in the edit control. 1.43 Michael Stefaniuc user32: Remove superfluous casts of void pointers. 1.44 Francois Gouget user32: Remove WINAPI/CALLBACK on static functions where not needed. svn path=/trunk/; revision=38739 --- reactos/dll/win32/user32/controls/edit.c | 784 +++++++++++---------- reactos/dll/win32/user32/include/user32p.h | 6 + 2 files changed, 414 insertions(+), 376 deletions(-) diff --git a/reactos/dll/win32/user32/controls/edit.c b/reactos/dll/win32/user32/controls/edit.c index 5ab69c2d2b3..3cd74c2a8a2 100644 --- a/reactos/dll/win32/user32/controls/edit.c +++ b/reactos/dll/win32/user32/controls/edit.c @@ -24,7 +24,7 @@ * * This code was audited for completeness against the documented features * of Comctl32.dll version 6.0 on Oct. 8, 2004, by Dimitrie O. Paun. - * + * * Unless otherwise noted, we believe this code to be complete, as per * the specification mentioned above. * If you discover missing features, or bugs, please note them below. @@ -171,12 +171,12 @@ typedef struct /* * These functions have trivial implementations * We still like to call them internally - * "static __inline" makes them more like macro's + * "static inline" makes them more like macro's */ -static __inline BOOL EDIT_EM_CanUndo(EDITSTATE *es); -static __inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es); -static __inline void EDIT_WM_Clear(EDITSTATE *es); -static __inline void EDIT_WM_Cut(EDITSTATE *es); +static inline BOOL EDIT_EM_CanUndo(const EDITSTATE *es); +static inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es); +static inline void EDIT_WM_Clear(EDITSTATE *es); +static inline void EDIT_WM_Cut(EDITSTATE *es); /* * Helper functions only valid for one type of control @@ -193,28 +193,26 @@ static void EDIT_MoveUp_ML(EDITSTATE *es, BOOL extend); */ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action); static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap); -static void EDIT_ConfinePoint(EDITSTATE *es, LPINT x, LPINT y); +static void EDIT_ConfinePoint(const EDITSTATE *es, LPINT x, LPINT y); static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc); static void EDIT_InvalidateText(EDITSTATE *es, INT start, INT end); static void EDIT_LockBuffer(EDITSTATE *es); static BOOL EDIT_MakeFit(EDITSTATE *es, UINT size); static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size); static void EDIT_MoveBackward(EDITSTATE *es, BOOL extend); -static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend); -static void EDIT_MoveEndOfText(EDITSTATE *es, BOOL extend); +static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend, BOOL ctrl); static void EDIT_MoveForward(EDITSTATE *es, BOOL extend); -static void EDIT_MoveStartOfText(EDITSTATE *es, BOOL extend); -static void EDIT_MoveHome(EDITSTATE *es, BOOL extend); +static void EDIT_MoveHome(EDITSTATE *es, BOOL extend, BOOL ctrl); static void EDIT_MoveWordBackward(EDITSTATE *es, BOOL extend); static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend); static void EDIT_PaintLine(EDITSTATE *es, HDC hdc, INT line, BOOL rev); static INT EDIT_PaintText(EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev); static void EDIT_SetCaretPos(EDITSTATE *es, INT pos, BOOL after_wrap); static void EDIT_AdjustFormatRect(EDITSTATE *es); -static void EDIT_SetRectNP(EDITSTATE *es, LPRECT lprc); +static void EDIT_SetRectNP(EDITSTATE *es, const RECT *lprc); static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force); static void EDIT_UpdateScrollInfo(EDITSTATE *es); -static INT CALLBACK EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action); +static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action); /* * EM_XXX message handlers */ @@ -225,10 +223,10 @@ static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es); static HLOCAL16 EDIT_EM_GetHandle16(EDITSTATE *es); #endif static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR dst, BOOL unicode); -static LRESULT EDIT_EM_GetSel(EDITSTATE *es, PUINT start, PUINT end); +static LRESULT EDIT_EM_GetSel(const EDITSTATE *es, PUINT start, PUINT end); static LRESULT EDIT_EM_GetThumb(EDITSTATE *es); static INT EDIT_EM_LineFromChar(EDITSTATE *es, INT index); -static INT EDIT_EM_LineIndex(EDITSTATE *es, INT line); +static INT EDIT_EM_LineIndex(const EDITSTATE *es, INT line); static INT EDIT_EM_LineLength(EDITSTATE *es, INT index); static BOOL EDIT_EM_LineScroll(EDITSTATE *es, INT dx, INT dy); static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy); @@ -244,9 +242,9 @@ static void EDIT_EM_SetLimitText(EDITSTATE *es, UINT limit); static void EDIT_EM_SetMargins(EDITSTATE *es, INT action, WORD left, WORD right, BOOL repaint); static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c); static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap); -static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs); +static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs); #ifndef __REACTOS__ -static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs); +static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, const INT16 *tabs); #endif static void EDIT_EM_SetWordBreakProc(EDITSTATE *es, void *wbp); #ifndef __REACTOS__ @@ -256,14 +254,13 @@ static BOOL EDIT_EM_Undo(EDITSTATE *es); /* * WM_XXX message handlers */ -static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c); +static LRESULT EDIT_WM_Char(EDITSTATE *es, WCHAR c); static void EDIT_WM_Command(EDITSTATE *es, INT code, INT id, HWND conrtol); static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y); static void EDIT_WM_Copy(EDITSTATE *es); static LRESULT EDIT_WM_Create(EDITSTATE *es, LPCWSTR name); static LRESULT EDIT_WM_Destroy(EDITSTATE *es); -static LRESULT EDIT_WM_EraseBkGnd(EDITSTATE *es, HDC dc); -static INT EDIT_WM_GetText(EDITSTATE *es, INT count, LPWSTR dst, BOOL unicode); +static INT EDIT_WM_GetText(const EDITSTATE *es, INT count, LPWSTR dst, BOOL unicode); static LRESULT EDIT_WM_HScroll(EDITSTATE *es, INT action, INT pos); static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key); static LRESULT EDIT_WM_KillFocus(EDITSTATE *es); @@ -283,7 +280,7 @@ static LRESULT EDIT_WM_StyleChanged(EDITSTATE *es, WPARAM which, const STYLESTR static LRESULT EDIT_WM_SysKeyDown(EDITSTATE *es, INT key, DWORD key_data); static void EDIT_WM_Timer(EDITSTATE *es); static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos); -static void EDIT_UpdateText(EDITSTATE *es, LPRECT rc, BOOL bErase); +static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase); static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase); static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es); @@ -293,9 +290,10 @@ LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); /********************************************************************* * edit class descriptor */ +static const WCHAR editW[] = {'E','d','i','t',0}; const struct builtin_class_descr EDIT_builtin_class = { - L"Edit", /* name */ + editW, /* name */ CS_DBLCLKS | CS_PARENTDC, /* style */ EditWndProcA, /* procA */ EditWndProcW, /* procW */ @@ -310,7 +308,7 @@ const struct builtin_class_descr EDIT_builtin_class = * EM_CANUNDO * */ -static __inline BOOL EDIT_EM_CanUndo(EDITSTATE *es) +static inline BOOL EDIT_EM_CanUndo(const EDITSTATE *es) { return (es->undo_insert_count || strlenW(es->undo_text)); } @@ -321,7 +319,7 @@ static __inline BOOL EDIT_EM_CanUndo(EDITSTATE *es) * EM_EMPTYUNDOBUFFER * */ -static __inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es) +static inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es) { es->undo_insert_count = 0; *es->undo_text = '\0'; @@ -333,7 +331,7 @@ static __inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es) * WM_CLEAR * */ -static __inline void EDIT_WM_Clear(EDITSTATE *es) +static inline void EDIT_WM_Clear(EDITSTATE *es) { static const WCHAR empty_stringW[] = {0}; @@ -350,7 +348,7 @@ static __inline void EDIT_WM_Clear(EDITSTATE *es) * WM_CUT * */ -static __inline void EDIT_WM_Cut(EDITSTATE *es) +static inline void EDIT_WM_Cut(EDITSTATE *es) { EDIT_WM_Copy(es); EDIT_WM_Clear(es); @@ -392,14 +390,14 @@ static DWORD get_app_version(void) return version; } -static __inline UINT get_text_length(EDITSTATE *es) +static inline UINT get_text_length(EDITSTATE *es) { if(es->text_length == (UINT)-1) es->text_length = strlenW(es->text); return es->text_length; } -static __inline void text_buffer_changed(EDITSTATE *es) +static inline void text_buffer_changed(EDITSTATE *es) { es->text_length = (UINT)-1; } @@ -421,7 +419,7 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc) return hbrush; } -static __inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode) +static inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode) { if(unicode) return DefWindowProcW(hwnd, msg, wParam, lParam); @@ -429,6 +427,12 @@ static __inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARA return DefWindowProcA(hwnd, msg, wParam, lParam); } +static inline INT get_vertical_line_count(EDITSTATE *es) +{ + INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + return max(1,vlc); +} + /********************************************************************* * * EditWndProc_common @@ -442,14 +446,14 @@ static __inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARA * names). * */ -static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, - WPARAM wParam, LPARAM lParam, BOOL unicode ) +static LRESULT EditWndProc_common( HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam, BOOL unicode ) { EDITSTATE *es = (EDITSTATE *)GetWindowLongPtrW( hwnd, 0 ); LRESULT result = 0; - TRACE("hwnd=%p msg=%x (%s) wparam=%lx lparam=%lx\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), wParam, lParam); - + TRACE("hwnd=%p msg=%x (%s) wparam=%lx lparam=%lx\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), wParam, lParam); + if (!es && msg != WM_NCCREATE) return DefWindowProcT(hwnd, msg, wParam, lParam, unicode); @@ -486,7 +490,13 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, #ifndef __REACTOS__ case EM_GETRECT16: if (lParam) - CONV_RECT32TO16(&es->format_rect, MapSL(lParam)); + { + RECT16 *r16 = MapSL(lParam); + r16->left = es->format_rect.left; + r16->top = es->format_rect.top; + r16->right = es->format_rect.right; + r16->bottom = es->format_rect.bottom; + } break; #endif case EM_GETRECT: @@ -498,7 +508,11 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, case EM_SETRECT16: if ((es->style & ES_MULTILINE) && lParam) { RECT rc; - CONV_RECT16TO32(MapSL(lParam), &rc); + RECT16 *r16 = MapSL(lParam); + rc.left = r16->left; + rc.top = r16->top; + rc.right = r16->right; + rc.bottom = r16->bottom; EDIT_SetRectNP(es, &rc); EDIT_UpdateText(es, NULL, TRUE); } @@ -515,7 +529,11 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, case EM_SETRECTNP16: if ((es->style & ES_MULTILINE) && lParam) { RECT rc; - CONV_RECT16TO32(MapSL(lParam), &rc); + RECT16 *r16 = MapSL(lParam); + rc.left = r16->left; + rc.top = r16->top; + rc.right = r16->right; + rc.bottom = r16->bottom; EDIT_SetRectNP(es, &rc); } break; @@ -646,7 +664,7 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, LPSTR textA = (LPSTR)lParam; INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0); if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR)))) - MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW); + MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW); } EDIT_EM_ReplaceSel(es, (BOOL)wParam, textW, TRUE, TRUE); @@ -817,7 +835,7 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, break; case EM_POSFROMCHAR: - if ((INT)wParam >= get_text_length(es)) result = -1; + if ((INT)wParam >= get_text_length(es)) result = -1; else result = EDIT_EM_PosFromChar(es, (INT)wParam, FALSE); break; @@ -840,39 +858,48 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, case WM_GETDLGCODE: result = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS; - + if (es->style & ES_MULTILINE) - { result |= DLGC_WANTALLKEYS; - break; - } if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN)) { int vk = (int)((LPMSG)lParam)->wParam; - if (es->hwndListBox && (vk == VK_RETURN || vk == VK_ESCAPE)) - { - if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0)) - result |= DLGC_WANTMESSAGE; - } - } + if (es->hwndListBox) + { + if (vk == VK_RETURN || vk == VK_ESCAPE) + if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0)) + result |= DLGC_WANTMESSAGE; + } + else + { + switch (vk) + { + case VK_ESCAPE: + SendMessageW(GetParent(hwnd), WM_CLOSE, 0, 0); + break; + default: + break; + } + } + } break; - case WM_IME_CHAR: - if (!unicode) - { - WCHAR charW; - CHAR strng[2]; + case WM_IME_CHAR: + if (!unicode) + { + WCHAR charW; + CHAR strng[2]; - strng[0] = wParam >> 8; - strng[1] = wParam & 0xff; - if (strng[0]) MultiByteToWideChar(CP_ACP, 0, strng, 2, &charW, 1); - else MultiByteToWideChar(CP_ACP, 0, &strng[1], 1, &charW, 1); - result = EDIT_WM_Char(es, charW); - break; - } - /* fall through */ + strng[0] = wParam >> 8; + strng[1] = wParam & 0xff; + if (strng[0]) MultiByteToWideChar(CP_ACP, 0, strng, 2, &charW, 1); + else MultiByteToWideChar(CP_ACP, 0, &strng[1], 1, &charW, 1); + result = EDIT_WM_Char(es, charW); + break; + } + /* fall through */ case WM_CHAR: { WCHAR charW; @@ -885,16 +912,37 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1); } - if ((charW == VK_RETURN || charW == VK_ESCAPE) && es->hwndListBox) - { - if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0)) - SendMessageW(GetParent(hwnd), WM_KEYDOWN, charW, 0); - break; - } + if (es->hwndListBox) + { + if (charW == VK_RETURN || charW == VK_ESCAPE) + { + if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0)) + SendMessageW(GetParent(hwnd), WM_KEYDOWN, charW, 0); + break; + } + } result = EDIT_WM_Char(es, charW); break; } + case WM_UNICHAR: + if (unicode) + { + if (wParam == UNICODE_NOCHAR) return TRUE; + if (wParam <= 0x000fffff) + { + if(wParam > 0xffff) /* convert to surrogates */ + { + wParam -= 0x10000; + EDIT_WM_Char(es, (wParam >> 10) + 0xd800); + EDIT_WM_Char(es, (wParam & 0x03ff) + 0xdc00); + } + else EDIT_WM_Char(es, wParam); + } + return 0; + } + break; + case WM_CLEAR: EDIT_WM_Clear(es); break; @@ -920,12 +968,12 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, LPWSTR nameW = NULL; if(nameA) { - INT countW = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0); - if((nameW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR)))) - MultiByteToWideChar(CP_ACP, 0, nameA, -1, nameW, countW); + INT countW = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0); + if((nameW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR)))) + MultiByteToWideChar(CP_ACP, 0, nameA, -1, nameW, countW); } result = EDIT_WM_Create(es, nameW); - HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, nameW); } break; @@ -939,7 +987,8 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, break; case WM_ERASEBKGND: - result = EDIT_WM_EraseBkGnd(es, (HDC)wParam); + /* we do the proper erase in EDIT_WM_Paint */ + result = 1; break; case WM_GETFONT: @@ -1058,44 +1107,28 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, } break; - - /* IME messages to make the edit control IME aware */ + + /* IME messages to make the edit control IME aware */ case WM_IME_SETCONTEXT: break; case WM_IME_STARTCOMPOSITION: - /* - * FIXME in IME: This message is not always sent like it should be - */ - if (es->selection_start != es->selection_end) - { - static const WCHAR empty_stringW[] = {0}; - EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE); - } es->composition_start = es->selection_end; es->composition_len = 0; break; case WM_IME_COMPOSITION: - { - int caret_pos = es->selection_end; - if (es->composition_len == 0) - { - if (es->selection_start != es->selection_end) - { - static const WCHAR empty_stringW[] = {0}; - EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE); - } - - es->composition_start = es->selection_end; - } - EDIT_ImeComposition(hwnd,lParam,es); - EDIT_SetCaretPos(es, caret_pos, es->flags & EF_AFTER_WRAP); + EDIT_ImeComposition(hwnd, lParam, es); break; - } case WM_IME_ENDCOMPOSITION: - es->composition_len= 0; + if (es->composition_len > 0) + { + static const WCHAR empty_stringW[] = {0}; + EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE); + es->selection_end = es->selection_start; + es->composition_len= 0; + } break; case WM_IME_COMPOSITIONFULL: @@ -1106,15 +1139,15 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, case WM_IME_CONTROL: break; - + default: result = DefWindowProcT(hwnd, msg, wParam, lParam, unicode); break; } - + if (es) EDIT_UnlockBuffer(es, FALSE); - TRACE("hwnd=%p msg=%x (%s) -- 0x%08lx\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), result); + TRACE("hwnd=%p msg=%x (%s) -- 0x%08lx\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), result); return result; } @@ -1232,7 +1265,7 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta { if (current_position - es->text > iend) break; /* We reached end of line modifications */ - /* else recalulate this line */ + /* else recalculate this line */ } } @@ -1313,9 +1346,9 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc, current_position, current_line->net_length, es->tabs_count, es->tabs)); } - else if (orig_net_length < current_line->net_length && - current_line == start_line && - current_line->index != nstart_index) { + else if (current_line == start_line && + current_line->index != nstart_index && + orig_net_length < current_line->net_length) { /* The previous line expanded but it's still not as wide as the client rect */ /* The expansion is due to an upwards line wrap so we must partially include it in the update region */ @@ -1464,7 +1497,7 @@ static void EDIT_CalcLineWidth_SL(EDITSTATE *es) */ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action) { - INT ret; + INT ret; #ifndef __REACTOS__ if (es->word_break_proc16) { @@ -1476,7 +1509,7 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL); hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA); - segptr = K32WOWGlobalLock16(hglob16); + segptr = WOWGlobalLock16(hglob16); WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL); args[4] = SELECTOROF(segptr); args[3] = OFFSETOF(segptr); @@ -1521,7 +1554,7 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count else ret = EDIT_WordBreakProc(es->text + start, index, count, action); - return ret; + return ret; } @@ -1676,7 +1709,7 @@ static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap) * (so CharFromPos returns the nearest _visible_ character) * */ -static void EDIT_ConfinePoint(EDITSTATE *es, LPINT x, LPINT y) +static void EDIT_ConfinePoint(const EDITSTATE *es, LPINT x, LPINT y) { *x = min(max(*x, es->format_rect.left), es->format_rect.right - 1); *y = min(max(*y, es->format_rect.top), es->format_rect.bottom - 1); @@ -1731,10 +1764,10 @@ static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es) * * EDIT_LockBuffer * - * This acts as a LOCAL_Lock(), but it locks only once. This way + * This acts as a LocalLock16(), but it locks only once. This way * you can call it whenever you like, without unlocking. * - * Initially the edit control allocates a HLOCAL32 buffer + * Initially the edit control allocates a HLOCAL32 buffer * (32 bit linear memory handler). However, 16 bit application * might send an EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF * handler). From that moment on we have to keep using this 16 bit memory @@ -1746,7 +1779,8 @@ static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es) static void EDIT_LockBuffer(EDITSTATE *es) { #ifndef __REACTOS__ - HINSTANCE16 hInstance = GetWindowLongW( es->hwndSelf, GWL_HINSTANCE ); + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HINSTANCE16 hInstance = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); #endif if (!es->text) { CHAR *textA = NULL; @@ -1766,8 +1800,11 @@ static void EDIT_LockBuffer(EDITSTATE *es) #ifndef __REACTOS__ else if(es->hloc16) { + HANDLE16 oldDS = stack16->ds; TRACE("Synchronizing with 16-bit ANSI buffer\n"); - textA = LOCAL_Lock(hInstance, es->hloc16); + stack16->ds = hInstance; + textA = MapSL(LocalLock16(es->hloc16)); + stack16->ds = oldDS; countA = strlen(textA) + 1; _16bit = TRUE; } @@ -1807,7 +1844,12 @@ static void EDIT_LockBuffer(EDITSTATE *es) MultiByteToWideChar(CP_ACP, 0, textA, countA, es->text, es->buffer_size + 1); #ifndef __REACTOS__ if(_16bit) - LOCAL_Unlock(hInstance, es->hloc16); + { + HANDLE16 oldDS = stack16->ds; + stack16->ds = hInstance; + LocalUnlock16(es->hloc16); + stack16->ds = oldDS; + } else #endif LocalUnlock(es->hloc32A); @@ -1847,7 +1889,7 @@ static void EDIT_SL_InvalidateText(EDITSTATE *es, INT start, INT end) */ static void EDIT_ML_InvalidateText(EDITSTATE *es, INT start, INT end) { - INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + INT vlc = get_vertical_line_count(es); INT sl = EDIT_EM_LineFromChar(es, start); INT el = EDIT_EM_LineFromChar(es, end); INT sc; @@ -2054,13 +2096,13 @@ static void EDIT_MoveDown_ML(EDITSTATE *es, BOOL extend) * EDIT_MoveEnd * */ -static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend) +static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend, BOOL ctrl) { BOOL after_wrap = FALSE; INT e; /* Pass a high value in x to make sure of receiving the end of the line */ - if (es->style & ES_MULTILINE) + if (!ctrl && (es->style & ES_MULTILINE)) e = EDIT_CharFromPos(es, 0x3fffffff, HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap); else @@ -2070,28 +2112,6 @@ static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend) } -/********************************************************************* - * - * EDIT_MoveEndOfText - * - * Handler for Ctrl+End. Move to end of text. Only for multiline. - * - */ -static void EDIT_MoveEndOfText(EDITSTATE *es, BOOL extend) -{ - BOOL after_wrap = FALSE; - INT e; - - assert(es->style & ES_MULTILINE); - - /* Just give it impossible high x&y to get the index of the last char */ - e = EDIT_CharFromPos(es, 0x3fffffff, 0x3fffffff, &after_wrap); - - EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, after_wrap); - EDIT_EM_ScrollCaret(es); -} - - /********************************************************************* * * EDIT_MoveForward @@ -2115,28 +2135,6 @@ static void EDIT_MoveForward(EDITSTATE *es, BOOL extend) } -/********************************************************************* - * - * EDIT_MoveStartOfText - * - * Handler for Ctr+Home. Move to start of text. Only for multiline. - * - */ -static void EDIT_MoveStartOfText(EDITSTATE *es, BOOL extend) -{ - BOOL after_wrap = FALSE; - - assert(es->style & ES_MULTILINE); - - /* use CharFromPos instead of just plain zero, to get the wrap_flag */ - EDIT_CharFromPos(es, 0, 0, &after_wrap); - - - EDIT_EM_SetSel(es, 0, extend ? es->selection_end : 0, FALSE); - EDIT_EM_ScrollCaret(es); -} - - /********************************************************************* * * EDIT_MoveHome @@ -2144,12 +2142,12 @@ static void EDIT_MoveStartOfText(EDITSTATE *es, BOOL extend) * Home key: move to beginning of line. * */ -static void EDIT_MoveHome(EDITSTATE *es, BOOL extend) +static void EDIT_MoveHome(EDITSTATE *es, BOOL extend, BOOL ctrl) { INT e; /* Pass the x_offset in x to make sure of receiving the first position of the line */ - if (es->style & ES_MULTILINE) + if (!ctrl && (es->style & ES_MULTILINE)) e = EDIT_CharFromPos(es, -es->x_offset, HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL); else @@ -2263,8 +2261,7 @@ static void EDIT_MoveWordBackward(EDITSTATE *es, BOOL extend) e = li + EDIT_EM_LineLength(es, li); } } else { - e = li + (INT)EDIT_CallWordBreakProc(es, - li, e - li, ll, WB_LEFT); + e = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_LEFT); } if (!extend) s = e; @@ -2319,7 +2316,8 @@ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev) LRESULT pos; if (es->style & ES_MULTILINE) { - INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + INT vlc = get_vertical_line_count(es); + if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count)) return; } else if (line) @@ -2371,10 +2369,10 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col if (rev) { if (es->composition_len == 0) { - SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); - SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkMode( dc, OPAQUE); - } + SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); + SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkMode( dc, OPAQUE); + } else { HFONT current = GetCurrentObject(dc,OBJ_FONT); @@ -2399,10 +2397,10 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col if (rev) { if (es->composition_len == 0) { - SetBkColor(dc, BkColor); - SetTextColor(dc, TextColor); - SetBkMode( dc, BkMode); - } + SetBkColor(dc, BkColor); + SetTextColor(dc, TextColor); + SetBkMode( dc, BkMode); + } else { if (old_font) @@ -2446,8 +2444,8 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) { INT fw, vlc, max_x_offset, max_y_offset; - vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; - es->format_rect.bottom = es->format_rect.top + max(1, vlc) * es->line_height; + vlc = get_vertical_line_count(es); + es->format_rect.bottom = es->format_rect.top + vlc * es->line_height; /* correct es->x_offset */ fw = es->format_rect.right - es->format_rect.left; @@ -2475,7 +2473,7 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) EDIT_BuildLineDefs_ML(es, 0, get_text_length(es), 0, NULL); - + EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP); } @@ -2488,18 +2486,18 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) * it is also used to set the rect of a single line control * */ -static void EDIT_SetRectNP(EDITSTATE *es, LPRECT rc) +static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc) { LONG_PTR ExStyle; INT bw, bh; ExStyle = GetWindowLongPtrW(es->hwndSelf, GWL_EXSTYLE); - + CopyRect(&es->format_rect, rc); - + if (ExStyle & WS_EX_CLIENTEDGE) { es->format_rect.left++; es->format_rect.right--; - + if (es->format_rect.bottom - es->format_rect.top >= es->line_height + 2) { @@ -2519,7 +2517,7 @@ static void EDIT_SetRectNP(EDITSTATE *es, LPRECT rc) es->format_rect.bottom -= bh; } } - + es->format_rect.left += es->left_margin; es->format_rect.right -= es->right_margin; EDIT_AdjustFormatRect(es); @@ -2587,26 +2585,31 @@ static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force) else if(es->hloc16) { UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL); + TRACE("Synchronizing with 16-bit ANSI buffer\n"); TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new); - countA = LOCAL_Size(hInstance, es->hloc16); + + stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + oldDS = stack16->ds; + stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); + + countA = LocalSize16(es->hloc16); if(countA_new > countA) { HLOCAL16 hloc16_new; UINT alloc_size = ROUND_TO_GROW(countA_new); TRACE("Resizing 16-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size); - hloc16_new = LOCAL_ReAlloc(hInstance, es->hloc16, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT); + hloc16_new = LocalReAlloc16(es->hloc16, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT); if(hloc16_new) { es->hloc16 = hloc16_new; - countA = LOCAL_Size(hInstance, hloc16_new); + countA = LocalSize16(hloc16_new); TRACE("Real new size %d bytes\n", countA); } else WARN("FAILED! Will synchronize partially\n"); } - textA = LOCAL_Lock(hInstance, es->hloc16); - _16bit = TRUE; + textA = MapSL(LocalLock16(es->hloc16)); } #endif @@ -2614,13 +2617,16 @@ static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force) { WideCharToMultiByte(CP_ACP, 0, es->text, countW, textA, countA, NULL, NULL); #ifndef __REACTOS__ - if(_16bit) - LOCAL_Unlock(hInstance, es->hloc16); + if(stack16) + LocalUnlock16(es->hloc16); else #endif LocalUnlock(es->hloc32A); } +#ifndef __REACTOS__ + if (stack16) stack16->ds = oldDS; +#endif LocalUnlock(es->hloc32W); es->text = NULL; } @@ -2680,7 +2686,7 @@ static void EDIT_UpdateScrollInfo(EDITSTATE *es) * internally, so we can decide this for ourselves. * */ -static INT CALLBACK EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action) +static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action) { INT ret = 0; @@ -2769,11 +2775,11 @@ static LRESULT EDIT_EM_CharFromPos(EDITSTATE *es, INT x, INT y) * EM_FMTLINES * * Enable or disable soft breaks. - * + * * This means: insert or remove the soft linebreak character (\r\r\n). * Take care to check if the text still fits the buffer after insertion. * If not, notify with EN_ERRSPACE. - * + * */ static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol) { @@ -2827,6 +2833,7 @@ static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es) hLocal = es->hloc32A; } + es->flags |= EF_APP_HAS_HANDLE; TRACE("Returning %p, LocalSize() = %ld\n", hLocal, LocalSize(hLocal)); return hLocal; } @@ -2850,9 +2857,10 @@ static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es) */ static HLOCAL16 EDIT_EM_GetHandle16(EDITSTATE *es) { - HINSTANCE16 hInstance = GetWindowLongW( es->hwndSelf, GWL_HINSTANCE ); CHAR *textA; UINT countA, alloc_size; + STACK16FRAME* stack16; + HANDLE16 oldDS; if (!(es->style & ES_MULTILINE)) return 0; @@ -2860,11 +2868,15 @@ static HLOCAL16 EDIT_EM_GetHandle16(EDITSTATE *es) if (es->hloc16) return es->hloc16; - if (!LOCAL_HeapSize(hInstance)) { - if (!LocalInit16(hInstance, 0, - GlobalSize16(hInstance))) { + stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + oldDS = stack16->ds; + stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); + + if (!LocalHeapSize16()) { + + if (!LocalInit16(stack16->ds, 0, GlobalSize16(stack16->ds))) { ERR("could not initialize local heap\n"); - return 0; + goto done; } TRACE("local heap initialized\n"); } @@ -2873,22 +2885,26 @@ static HLOCAL16 EDIT_EM_GetHandle16(EDITSTATE *es) alloc_size = ROUND_TO_GROW(countA); TRACE("Allocating 16-bit ANSI alias buffer\n"); - if (!(es->hloc16 = LOCAL_Alloc(hInstance, LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size))) { + if (!(es->hloc16 = LocalAlloc16(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size))) { ERR("could not allocate new 16 bit buffer\n"); - return 0; + goto done; } - if (!(textA = (LPSTR)LOCAL_Lock(hInstance, es->hloc16))) { + if (!(textA = MapSL(LocalLock16( es->hloc16)))) { ERR("could not lock new 16 bit buffer\n"); - LOCAL_Free(hInstance, es->hloc16); + LocalFree16(es->hloc16); es->hloc16 = 0; - return 0; + goto done; } WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, countA, NULL, NULL); - LOCAL_Unlock(hInstance, es->hloc16); + LocalUnlock16(es->hloc16); + es->flags |= EF_APP_HAS_HANDLE; - TRACE("Returning %04X, LocalSize() = %d\n", es->hloc16, LOCAL_Size(hInstance, es->hloc16)); + TRACE("Returning %04X, LocalSize() = %d\n", es->hloc16, LocalSize16(es->hloc16)); + +done: + stack16->ds = oldDS; return es->hloc16; } #endif @@ -2945,7 +2961,7 @@ static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR dst, BOOL unicode) * EM_GETSEL * */ -static LRESULT EDIT_EM_GetSel(EDITSTATE *es, PUINT start, PUINT end) +static LRESULT EDIT_EM_GetSel(const EDITSTATE *es, PUINT start, PUINT end) { UINT s = es->selection_start; UINT e = es->selection_end; @@ -3015,10 +3031,10 @@ static INT EDIT_EM_LineFromChar(EDITSTATE *es, INT index) * EM_LINEINDEX * */ -static INT EDIT_EM_LineIndex(EDITSTATE *es, INT line) +static INT EDIT_EM_LineIndex(const EDITSTATE *es, INT line) { INT line_index; - LINEDEF *line_def; + const LINEDEF *line_def; if (!(es->style & ES_MULTILINE)) return 0; @@ -3299,11 +3315,11 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac * such that buffer limit is honored. */ if ((honor_limit) && (size > es->buffer_limit)) { EDIT_NOTIFY_PARENT(es, EN_MAXTEXT); - /* Buffer limit can be smaller than the actual length of text in combobox */ - if (es->buffer_limit < (tl - (e-s))) - strl = 0; - else - strl = es->buffer_limit - (tl - (e-s)); + /* Buffer limit can be smaller than the actual length of text in combobox */ + if (es->buffer_limit < (tl - (e-s))) + strl = 0; + else + strl = es->buffer_limit - (tl - (e-s)); } if (!EDIT_MakeFit(es, tl - (e - s) + strl)) @@ -3324,7 +3340,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac if (strl) { /* there is an insertion */ tl = get_text_length(es); - TRACE("inserting stuff (tl %d, strl %d, selstart %d ('%s'), text '%s')\n", tl, strl, s, debugstr_w(es->text + s), debugstr_w(es->text)); + TRACE("inserting stuff (tl %d, strl %d, selstart %d (%s), text %s)\n", tl, strl, s, debugstr_w(es->text + s), debugstr_w(es->text)); for (p = es->text + tl ; p >= es->text + s ; p--) p[strl] = p[0]; for (i = 0 , p = es->text + s ; i < strl ; i++) @@ -3338,7 +3354,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac if (es->style & ES_MULTILINE) { INT st = min(es->selection_start, es->selection_end); - INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + INT vlc = get_vertical_line_count(es); hrgn = CreateRectRgn(0, 0, 0, 0); EDIT_BuildLineDefs_ML(es, st, st + strl, @@ -3351,7 +3367,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac for (i = 0 , p = es->text ; i < e - s ; i++) p[i + s] = buf[i]; text_buffer_changed(es); - EDIT_BuildLineDefs_ML(es, s, e, + EDIT_BuildLineDefs_ML(es, s, e, abs(es->selection_end - es->selection_start) - strl, hrgn); strl = 0; e = s; @@ -3369,11 +3385,11 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac strl--; EDIT_CalcLineWidth_SL(es); } - text_buffer_changed(es); + text_buffer_changed(es); EDIT_NOTIFY_PARENT(es, EN_MAXTEXT); } } - + if (e != s) { if (can_undo) { utl = strlenW(es->undo_text); @@ -3425,7 +3441,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac if (bufl) HeapFree(GetProcessHeap(), 0, buf); - + s += strl; /* If text has been deleted and we're right or center aligned then scroll rightward */ @@ -3502,7 +3518,7 @@ static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action) return (LRESULT)FALSE; } if (dy) { - INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + INT vlc = get_vertical_line_count(es); /* check if we are going to move too far */ if(es->y_offset + dy > es->line_count - vlc) dy = es->line_count - vlc - es->y_offset; @@ -3528,7 +3544,6 @@ static void EDIT_EM_ScrollCaret(EDITSTATE *es) { if (es->style & ES_MULTILINE) { INT l; - INT li; INT vlc; INT ww; INT cw = es->char_width; @@ -3537,9 +3552,8 @@ static void EDIT_EM_ScrollCaret(EDITSTATE *es) INT dx = 0; l = EDIT_EM_LineFromChar(es, es->selection_end); - li = EDIT_EM_LineIndex(es, l); x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)); - vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + vlc = get_vertical_line_count(es); if (l >= es->y_offset + vlc) dy = l - vlc + 1 - es->y_offset; if (l < es->y_offset) @@ -3613,8 +3627,13 @@ static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc) #ifndef __REACTOS__ if(es->hloc16) { - LOCAL_Free(hInstance, es->hloc16); - es->hloc16 = (HLOCAL16)NULL; + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HANDLE16 oldDS = stack16->ds; + + stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); + LocalFree16(es->hloc16); + stack16->ds = oldDS; + es->hloc16 = 0; } #endif @@ -3682,7 +3701,9 @@ static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc) */ static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc) { - HINSTANCE16 hInstance = GetWindowLongW( es->hwndSelf, GWL_HINSTANCE ); + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HINSTANCE16 hInstance = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); + HANDLE16 oldDS = stack16->ds; INT countW, countA; HLOCAL hloc32W_new; WCHAR *textW; @@ -3704,8 +3725,9 @@ static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc) es->hloc32A = NULL; } - countA = LOCAL_Size(hInstance, hloc); - textA = LOCAL_Lock(hInstance, hloc); + stack16->ds = hInstance; + countA = LocalSize16(hloc); + textA = MapSL(LocalLock16(hloc)); countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0); if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR)))) { @@ -3715,7 +3737,8 @@ static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc) textW = LocalLock(hloc32W_new); MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW); LocalUnlock(hloc32W_new); - LOCAL_Unlock(hInstance, hloc); + LocalUnlock16(hloc); + stack16->ds = oldDS; if(es->hloc32W) LocalFree(es->hloc32W); @@ -3725,6 +3748,7 @@ static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc) es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1; + es->flags |= EF_APP_HAS_HANDLE; EDIT_LockBuffer(es); es->x_offset = es->y_offset = 0; @@ -3745,7 +3769,7 @@ static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc) * * EM_SETLIMITTEXT * - * NOTE: this version currently implements WinNT limits + * NOTE: this version currently implements WinNT limits * */ static void EDIT_EM_SetLimitText(EDITSTATE *es, UINT limit) @@ -3831,12 +3855,12 @@ static void EDIT_EM_SetMargins(EDITSTATE *es, INT action, es->right_margin = default_right_margin; es->format_rect.right -= es->right_margin; } - + if (action & (EC_LEFTMARGIN | EC_RIGHTMARGIN)) { EDIT_AdjustFormatRect(es); if (repaint) EDIT_UpdateText(es, NULL, TRUE); } - + TRACE("left=%d, right=%d\n", es->left_margin, es->right_margin); } @@ -3905,8 +3929,8 @@ static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap) * *sorting* the interval endpoints. Let's assume that we sort them * in this order: * start <= end <= old_start <= old_end - * Knuth 5.3.1 (p 183) asssures us that this can be done optimally - * in 5 comparisons; ie it's impossible to do better than the + * Knuth 5.3.1 (p 183) assures us that this can be done optimally + * in 5 comparisons; i.e. it is impossible to do better than the * following: */ ORDER_UINT(end, old_end); ORDER_UINT(start, old_start); @@ -3944,11 +3968,11 @@ static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap) * EM_SETTABSTOPS * */ -static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs) +static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs) { if (!(es->style & ES_MULTILINE)) return FALSE; - HeapFree(GetProcessHeap(), 0, es->tabs); + HeapFree(GetProcessHeap(), 0, es->tabs); es->tabs_count = count; if (!count) es->tabs = NULL; @@ -3971,12 +3995,11 @@ static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs) * EM_SETTABSTOPS16 * */ -static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs) +static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, const INT16 *tabs) { if (!(es->style & ES_MULTILINE)) return FALSE; - if (es->tabs) - HeapFree(GetProcessHeap(), 0, es->tabs); + HeapFree(GetProcessHeap(), 0, es->tabs); es->tabs_count = count; if (!count) es->tabs = NULL; @@ -4074,6 +4097,7 @@ static BOOL EDIT_EM_Undo(EDITSTATE *es) return TRUE; } + /* Helper function for WM_CHAR * * According to an MSDN blog article titled "Just because you're a control @@ -4083,20 +4107,38 @@ static BOOL EDIT_EM_Undo(EDITSTATE *es) */ static BOOL EDIT_IsInsideDialog(EDITSTATE *es) { +#ifdef __REACTOS__ if (es->hwndParent && es->hwndParent != GetDesktopWindow()) { if (GetClassLongW (es->hwndParent, GCW_ATOM) == (DWORD)MAKEINTATOM(32770)) return TRUE; } return FALSE; +#else + WND *pParent; + BOOL r = FALSE; + + if (es->hwndParent) + { + pParent = WIN_GetPtr(es->hwndParent); + if (pParent && pParent != WND_OTHER_PROCESS && pParent != WND_DESKTOP) + { + if (pParent->flags & WIN_ISDIALOG) + r = TRUE; + WIN_ReleasePtr(pParent); + } + } + return r; +#endif } + /********************************************************************* * * WM_CHAR * */ -static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c) +static LRESULT EDIT_WM_Char(EDITSTATE *es, WCHAR c) { BOOL control; @@ -4104,13 +4146,17 @@ static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c) switch (c) { case '\r': - /* If the edit doesn't want the return and it's not a multiline edit, do nothing */ - if(!(es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN)) - break; + /* If it's not a multiline edit box, it would be ignored below. + * For multiline edit without ES_WANTRETURN, we have to make a + * special case. + */ + if ((es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN)) + if (EDIT_IsInsideDialog(es)) + break; case '\n': if (es->style & ES_MULTILINE) { if (es->style & ES_READONLY) { - EDIT_MoveHome(es, FALSE); + EDIT_MoveHome(es, FALSE, FALSE); EDIT_MoveDown_ML(es, FALSE); } else { static const WCHAR cr_lfW[] = {'\r','\n',0}; @@ -4122,8 +4168,8 @@ static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c) if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY)) { static const WCHAR tabW[] = {'\t',0}; - if (EDIT_IsInsideDialog(es)) - break; + if (EDIT_IsInsideDialog(es)) + break; EDIT_EM_ReplaceSel(es, TRUE, tabW, TRUE, TRUE); } break; @@ -4140,7 +4186,7 @@ static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c) } break; case 0x03: /* ^C */ - if (!(es->style & ES_PASSWORD)) + if (!(es->style & ES_PASSWORD)) SendMessageW(es->hwndSelf, WM_COPY, 0, 0); break; case 0x16: /* ^V */ @@ -4151,16 +4197,16 @@ static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c) if (!((es->style & ES_READONLY) || (es->style & ES_PASSWORD))) SendMessageW(es->hwndSelf, WM_CUT, 0, 0); break; - case 0x1A: /* ^Z */ - if (!(es->style & ES_READONLY)) - SendMessageW(es->hwndSelf, WM_UNDO, 0, 0); - break; + case 0x1A: /* ^Z */ + if (!(es->style & ES_READONLY)) + SendMessageW(es->hwndSelf, WM_UNDO, 0, 0); + break; default: - /*If Edit control style is ES_NUMBER allow users to key in only numeric values*/ - if( (es->style & ES_NUMBER) && !( c >= '0' && c <= '9') ) - break; - + /*If Edit control style is ES_NUMBER allow users to key in only numeric values*/ + if( (es->style & ES_NUMBER) && !( c >= '0' && c <= '9') ) + break; + if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127)) { WCHAR str[2]; str[0] = c; @@ -4169,8 +4215,7 @@ static BOOL EDIT_WM_Char(EDITSTATE *es, WCHAR c) } break; } - - return TRUE; + return 1; } @@ -4186,19 +4231,19 @@ static void EDIT_WM_Command(EDITSTATE *es, INT code, INT id, HWND control) switch (id) { case EM_UNDO: - EDIT_EM_Undo(es); + SendMessageW(es->hwndSelf, WM_UNDO, 0, 0); break; case WM_CUT: - EDIT_WM_Cut(es); + SendMessageW(es->hwndSelf, WM_CUT, 0, 0); break; case WM_COPY: - EDIT_WM_Copy(es); + SendMessageW(es->hwndSelf, WM_COPY, 0, 0); break; case WM_PASTE: - EDIT_WM_Paste(es); + SendMessageW(es->hwndSelf, WM_PASTE, 0, 0); break; case WM_CLEAR: - EDIT_WM_Clear(es); + SendMessageW(es->hwndSelf, WM_CLEAR, 0, 0); break; case EM_SETSEL: EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE); @@ -4305,7 +4350,7 @@ static void EDIT_WM_Copy(EDITSTATE *es) static LRESULT EDIT_WM_Create(EDITSTATE *es, LPCWSTR name) { RECT clientRect; - + TRACE("%s\n", debugstr_w(name)); /* * To initialize some final structure members, we call some helper @@ -4315,7 +4360,7 @@ static LRESULT EDIT_WM_Create(EDITSTATE *es, LPCWSTR name) */ EDIT_WM_SetFont(es, 0, FALSE); EDIT_EM_EmptyUndoBuffer(es); - + /* We need to calculate the format rect (applications may send EM_SETMARGINS before the control gets visible) */ GetClientRect(es->hwndSelf, &clientRect); @@ -4357,18 +4402,20 @@ static LRESULT EDIT_WM_Destroy(EDITSTATE *es) LINEDEF *pc, *pp; if (es->hloc32W) { - while (LocalUnlock(es->hloc32W)) ; LocalFree(es->hloc32W); } if (es->hloc32A) { - while (LocalUnlock(es->hloc32A)) ; LocalFree(es->hloc32A); } #ifndef __REACTOS__ if (es->hloc16) { - HINSTANCE16 hInstance = GetWindowWord( es->hwndSelf, GWL_HINSTANCE ); - while (LOCAL_Unlock(hInstance, es->hloc16)) ; - LOCAL_Free(hInstance, es->hloc16); + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HANDLE16 oldDS = stack16->ds; + + stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); + while (LocalUnlock16(es->hloc16)) ; + LocalFree16(es->hloc16); + stack16->ds = oldDS; } #endif @@ -4387,24 +4434,12 @@ static LRESULT EDIT_WM_Destroy(EDITSTATE *es) } -/********************************************************************* - * - * WM_ERASEBKGND - * - */ -static LRESULT EDIT_WM_EraseBkGnd(EDITSTATE *es, HDC dc) -{ - /* we do the proper erase in EDIT_WM_Paint */ - return 1; -} - - /********************************************************************* * * WM_GETTEXT * */ -static INT EDIT_WM_GetText(EDITSTATE *es, INT count, LPWSTR dst, BOOL unicode) +static INT EDIT_WM_GetText(const EDITSTATE *es, INT count, LPWSTR dst, BOOL unicode) { if(!count) return 0; @@ -4666,18 +4701,10 @@ static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key) EDIT_MoveForward(es, shift); break; case VK_HOME: - if (control && (es->style & ES_MULTILINE)) { - EDIT_MoveStartOfText(es, shift); - } else { - EDIT_MoveHome(es, shift); /* start of line */ - } + EDIT_MoveHome(es, shift, control); break; case VK_END: - if (control && (es->style & ES_MULTILINE)) { - EDIT_MoveEndOfText(es, shift); - } else { - EDIT_MoveEnd(es, shift); /* end of line */ - } + EDIT_MoveEnd(es, shift, control); break; case VK_PRIOR: if (es->style & ES_MULTILINE) @@ -4707,7 +4734,7 @@ static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key) } else if (control) { /* delete to end of line */ EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE); - EDIT_MoveEnd(es, TRUE); + EDIT_MoveEnd(es, TRUE, FALSE); EDIT_WM_Clear(es); } else { /* delete character right of caret */ @@ -4725,36 +4752,36 @@ static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key) } else if (control) EDIT_WM_Copy(es); break; - case VK_RETURN: - /* If the edit doesn't want the return send a message to the default object */ - if(!(es->style & ES_MULTILINE) || !(es->style & ES_WANTRETURN)) + case VK_RETURN: + /* If the edit doesn't want the return send a message to the default object */ + if(!(es->style & ES_MULTILINE) || !(es->style & ES_WANTRETURN)) { - HWND hwndParent; - DWORD dw; + HWND hwndParent; + DWORD dw; - if (!EDIT_IsInsideDialog(es)) return 1; - if (control) break; + if (!EDIT_IsInsideDialog(es)) return 1; + if (control) break; - hwndParent = GetParent(es->hwndSelf); - dw = SendMessageW( hwndParent, DM_GETDEFID, 0, 0 ); - if (HIWORD(dw) == DC_HASDEFID) - { - SendMessageW( hwndParent, WM_COMMAND, - MAKEWPARAM( LOWORD(dw), BN_CLICKED ), - (LPARAM)GetDlgItem( hwndParent, LOWORD(dw) ) ); - } - else - SendMessageW( hwndParent, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hwndParent, IDOK ) ); - } - break; - case VK_ESCAPE: - if (!(es->style & ES_MULTILINE)) - SendMessageW(GetParent(es->hwndSelf), WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( GetParent(es->hwndSelf), IDCANCEL ) ); - break; - case VK_TAB: - SendMessageW(es->hwndParent, WM_NEXTDLGCTL, shift, 0); - break; - } + hwndParent = GetParent(es->hwndSelf); + dw = SendMessageW( hwndParent, DM_GETDEFID, 0, 0 ); + if (HIWORD(dw) == DC_HASDEFID) + { + SendMessageW( hwndParent, WM_COMMAND, + MAKEWPARAM( LOWORD(dw), BN_CLICKED ), + (LPARAM)GetDlgItem( hwndParent, LOWORD(dw) ) ); + } + else + SendMessageW( hwndParent, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hwndParent, IDOK ) ); + } + break; + case VK_ESCAPE: + if (!(es->style & ES_MULTILINE)) + SendMessageW(GetParent(es->hwndSelf), WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( GetParent(es->hwndSelf), IDCANCEL ) ); + break; + case VK_TAB: + SendMessageW(es->hwndParent, WM_NEXTDLGCTL, shift, 0); + break; + } return 0; } @@ -4904,7 +4931,7 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode) EDITSTATE *es; UINT alloc_size; - TRACE("Creating %s edit control, style = %08lx\n", + TRACE("Creating %s edit control, style = %08x\n", unicode ? "Unicode" : "ANSI", lpcs->style); if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es)))) @@ -4929,6 +4956,9 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode) if (es->style & ES_COMBO) es->hwndListBox = GetDlgItem(es->hwndParent, ID_CB_LISTBOX); + /* FIXME: should we handle changes to WS_EX_RIGHT style after creation? */ + if (lpcs->dwExStyle & WS_EX_RIGHT) es->style |= ES_RIGHT; + /* Number overrides lowercase overrides uppercase (at least it * does in Win95). However I'll bet that ES_NUMBER would be * invalid under Win 3.1. @@ -4983,7 +5013,7 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode) * If WS_BORDER without WS_EX_CLIENTEDGE is specified we shouldn't have * a nonclient area and we should handle painting the border ourselves. * - * When making modifications please ensure that the code still works + * When making modifications please ensure that the code still works * for edit controls created directly with style 0x50800000, exStyle 0 * (which should have a single pixel border) */ @@ -5025,7 +5055,7 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc) /* paint the border and the background */ IntersectClipRect(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - + if(es->style & WS_BORDER) { bw = GetSystemMetrics(SM_CXBORDER); bh = GetSystemMetrics(SM_CYBORDER); @@ -5034,7 +5064,7 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc) if(es->style & WS_HSCROLL) rc.bottom+=bh; if(es->style & WS_VSCROLL) rc.right+=bw; } - + /* Draw the frame. Same code as in nonclient.c */ old_brush = SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME)); PatBlt(dc, rc.left, rc.top, rc.right - rc.left, bh, PATCOPY); @@ -5042,12 +5072,12 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc) PatBlt(dc, rc.left, rc.bottom - 1, rc.right - rc.left, -bw, PATCOPY); PatBlt(dc, rc.right - 1, rc.top, -bw, rc.bottom - rc.top, PATCOPY); SelectObject(dc, old_brush); - + /* Keep the border clean */ IntersectClipRect(dc, rc.left+bw, rc.top+bh, max(rc.right-bw, rc.left+bw), max(rc.bottom-bh, rc.top+bh)); } - + GetClipBox(dc, &rc); FillRect(dc, &rc, brush); @@ -5066,7 +5096,7 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc) SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT)); GetClipBox(dc, &rcRgn); if (es->style & ES_MULTILINE) { - INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + INT vlc = get_vertical_line_count(es); for (i = es->y_offset ; i <= min(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++) { EDIT_GetLineRect(es, i, 0, -1, &rcLine); if (IntersectRect(&rc, &rcRgn, &rcLine)) @@ -5101,14 +5131,14 @@ static void EDIT_WM_Paste(EDITSTATE *es) OpenClipboard(es->hwndSelf); if ((hsrc = GetClipboardData(CF_UNICODETEXT))) { - src = (LPWSTR)GlobalLock(hsrc); + src = GlobalLock(hsrc); EDIT_EM_ReplaceSel(es, TRUE, src, TRUE, TRUE); GlobalUnlock(hsrc); } else if (es->style & ES_PASSWORD) { - /* clear selected text in password edit box even with empty clipboard */ - const WCHAR empty_strW[] = { 0 }; - EDIT_EM_ReplaceSel(es, TRUE, empty_strW, TRUE, TRUE); + /* clear selected text in password edit box even with empty clipboard */ + const WCHAR empty_strW[] = { 0 }; + EDIT_EM_ReplaceSel(es, TRUE, empty_strW, TRUE, TRUE); } CloseClipboard(); } @@ -5168,7 +5198,7 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw) if (font) SelectObject(dc, old_font); ReleaseDC(es->hwndSelf, dc); - + /* Reset the format rect and the margins */ GetClientRect(es->hwndSelf, &clientRect); EDIT_SetRectNP(es, &clientRect); @@ -5223,14 +5253,14 @@ static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text, BOOL unicode) "selection.\n"); EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE); - if (text) + if (text) { TRACE("%s\n", debugstr_w(text)); EDIT_EM_ReplaceSel(es, FALSE, text, FALSE, FALSE); if(!unicode) HeapFree(GetProcessHeap(), 0, textW); - } - else + } + else { static const WCHAR empty_stringW[] = {0}; TRACE("\n"); @@ -5250,7 +5280,7 @@ static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text, BOOL unicode) EDIT_NOTIFY_PARENT(es, EN_CHANGE); } EDIT_EM_ScrollCaret(es); - EDIT_UpdateScrollInfo(es); + EDIT_UpdateScrollInfo(es); } @@ -5411,7 +5441,7 @@ static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos) INT vlc, new_y; /* Sanity check */ if(pos < 0 || pos > 100) return 0; - vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + vlc = get_vertical_line_count(es); new_y = pos * (es->line_count - vlc) / 100; dy = es->line_count ? (new_y - es->y_offset) : 0; TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n", @@ -5429,7 +5459,7 @@ static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos) INT vlc, new_y; /* Sanity check */ if(pos < 0 || pos > 100) return 0; - vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + vlc = get_vertical_line_count(es); new_y = pos * (es->line_count - vlc) / 100; dy = es->line_count ? (new_y - es->y_offset) : 0; TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n", @@ -5462,7 +5492,7 @@ static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos) else { /* Assume default scroll range 0-100 */ - INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + INT vlc = get_vertical_line_count(es); ret = es->line_count ? es->y_offset * 100 / (es->line_count - vlc) : 0; } TRACE("EM_GETTHUMB: returning %ld\n", ret); @@ -5505,7 +5535,7 @@ static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase) * EDIT_UpdateText * */ -static void EDIT_UpdateText(EDITSTATE *es, LPRECT rc, BOOL bErase) +static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase) { if (es->flags & EF_UPDATE) { es->flags &= ~EF_UPDATE; @@ -5515,44 +5545,38 @@ static void EDIT_UpdateText(EDITSTATE *es, LPRECT rc, BOOL bErase) } /******************************************************************** - * + * * The Following code is to handle inline editing from IMEs */ -static void EDIT_GetCompositionStr(HWND hwnd, LPARAM CompFlag, EDITSTATE *es) +static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es) { - DWORD dwBufLen; + LONG buflen; LPWSTR lpCompStr = NULL; - HIMC hIMC; LPSTR lpCompStrAttr = NULL; DWORD dwBufLenAttr; - if (!(hIMC = ImmGetContext(hwnd))) - return; + buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); - dwBufLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); - - if (dwBufLen <= 0) + if (buflen < 0) { - ImmReleaseContext(hwnd, hIMC); return; } - lpCompStr = HeapAlloc(GetProcessHeap(),0,dwBufLen); + lpCompStr = HeapAlloc(GetProcessHeap(),0,buflen + sizeof(WCHAR)); if (!lpCompStr) { ERR("Unable to allocate IME CompositionString\n"); - ImmReleaseContext(hwnd,hIMC); return; } - if (dwBufLen) - ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, dwBufLen); - lpCompStr[dwBufLen/sizeof(WCHAR)] = 0; + if (buflen) + ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, buflen); + lpCompStr[buflen/sizeof(WCHAR)] = 0; 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 */ @@ -5560,15 +5584,14 @@ static void EDIT_GetCompositionStr(HWND hwnd, LPARAM CompFlag, EDITSTATE *es) if (dwBufLenAttr) { dwBufLenAttr ++; - lpCompStrAttr = HeapAlloc(GetProcessHeap(),0,dwBufLenAttr); + lpCompStrAttr = HeapAlloc(GetProcessHeap(),0,dwBufLenAttr+1); if (!lpCompStrAttr) { ERR("Unable to allocate IME Attribute String\n"); HeapFree(GetProcessHeap(),0,lpCompStr); - ImmReleaseContext(hwnd,hIMC); return; } - ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr, + ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr, dwBufLenAttr); lpCompStrAttr[dwBufLenAttr] = 0; } @@ -5579,7 +5602,7 @@ static void EDIT_GetCompositionStr(HWND hwnd, 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; @@ -5596,35 +5619,28 @@ static void EDIT_GetCompositionStr(HWND hwnd, LPARAM CompFlag, EDITSTATE *es) HeapFree(GetProcessHeap(),0,lpCompStrAttr); HeapFree(GetProcessHeap(),0,lpCompStr); - ImmReleaseContext(hwnd,hIMC); } -static void EDIT_GetResultStr(HWND hwnd, EDITSTATE *es) +static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es) { - DWORD dwBufLen; + LONG buflen; LPWSTR lpResultStr; - HIMC hIMC; - if ( !(hIMC = ImmGetContext(hwnd))) - return; - - dwBufLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0); - if (dwBufLen <= 0) + buflen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0); + if (buflen <= 0) { - ImmReleaseContext(hwnd, hIMC); return; } - lpResultStr = HeapAlloc(GetProcessHeap(),0, dwBufLen); + lpResultStr = HeapAlloc(GetProcessHeap(),0, buflen+sizeof(WCHAR)); if (!lpResultStr) { ERR("Unable to alloc buffer for IME string\n"); - ImmReleaseContext(hwnd, hIMC); return; } - ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, dwBufLen); - lpResultStr[dwBufLen/sizeof(WCHAR)] = 0; + ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, buflen); + lpResultStr[buflen/sizeof(WCHAR)] = 0; /* check for change in composition start */ if (es->selection_end < es->composition_start) @@ -5637,13 +5653,29 @@ static void EDIT_GetResultStr(HWND hwnd, EDITSTATE *es) es->composition_len = 0; HeapFree(GetProcessHeap(),0,lpResultStr); - ImmReleaseContext(hwnd, hIMC); } 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) + { + static const WCHAR empty_stringW[] = {0}; + EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE); + es->composition_start = es->selection_end; + } + + hIMC = ImmGetContext(hwnd); + if (!hIMC) + return; + if (CompFlag & GCS_RESULTSTR) - EDIT_GetResultStr(hwnd,es); + EDIT_GetResultStr(hIMC, es); if (CompFlag & GCS_COMPSTR) - EDIT_GetCompositionStr(hwnd, CompFlag, es); + 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); } diff --git a/reactos/dll/win32/user32/include/user32p.h b/reactos/dll/win32/user32/include/user32p.h index 80ac4d63a29..ff9a46d0273 100644 --- a/reactos/dll/win32/user32/include/user32p.h +++ b/reactos/dll/win32/user32/include/user32p.h @@ -243,5 +243,11 @@ PVOID FASTCALL ValidateHandle(HANDLE, UINT); # endif #endif +#ifdef _MSC_VER +#ifndef inline +#define inline __inline +#endif +#endif + #endif /* EOF */