[2/3] user32: Reorder some functions to avoid forward declarations in edit.c.
Francois Gouget
fgouget at free.fr
Sat Feb 7 09:05:33 CST 2009
---
dlls/user32/edit.c | 4078 +++++++++++++++++++++++++---------------------------
1 files changed, 1998 insertions(+), 2080 deletions(-)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c
index d37cec8..636b957 100644
--- a/dlls/user32/edit.c
+++ b/dlls/user32/edit.c
@@ -173,107 +173,6 @@ typedef struct
(LPARAM)(es->hwndSelf)); \
} while(0)
-/*********************************************************************
- *
- * Declarations
- *
- */
-
-/*
- * Helper functions only valid for one type of control
- */
-static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es);
-/*
- * Helper functions valid for both single line _and_ multi line controls
- */
-static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action);
-static void EDIT_LockBuffer(EDITSTATE *es);
-static INT EDIT_PaintText(EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
-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 EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action);
-/*
- * EM_XXX message handlers
- */
-static LRESULT EDIT_EM_CharFromPos(EDITSTATE *es, INT x, INT y);
-static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol);
-static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es);
-static HLOCAL16 EDIT_EM_GetHandle16(EDITSTATE *es);
-static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR dst, BOOL unicode);
-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(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);
-static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap);
-static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update, BOOL honor_limit);
-static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action);
-static void EDIT_EM_ScrollCaret(EDITSTATE *es);
-static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc);
-static void EDIT_EM_SetHandle16(EDITSTATE *es, HLOCAL16 hloc);
-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, const INT *tabs);
-static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, const INT16 *tabs);
-static void EDIT_EM_SetWordBreakProc(EDITSTATE *es, void *wbp);
-static void EDIT_EM_SetWordBreakProc16(EDITSTATE *es, EDITWORDBREAKPROC16 wbp);
-static BOOL EDIT_EM_Undo(EDITSTATE *es);
-/*
- * WM_XXX message handlers
- */
-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 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);
-static LRESULT EDIT_WM_LButtonDblClk(EDITSTATE *es);
-static LRESULT EDIT_WM_LButtonDown(EDITSTATE *es, DWORD keys, INT x, INT y);
-static LRESULT EDIT_WM_LButtonUp(EDITSTATE *es);
-static LRESULT EDIT_WM_MButtonDown(EDITSTATE *es);
-static LRESULT EDIT_WM_MouseMove(EDITSTATE *es, INT x, INT y);
-static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode);
-static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc);
-static void EDIT_WM_Paste(EDITSTATE *es);
-static void EDIT_WM_SetFocus(EDITSTATE *es);
-static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw);
-static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text, BOOL unicode);
-static void EDIT_WM_Size(EDITSTATE *es, UINT action, INT width, INT height);
-static LRESULT EDIT_WM_StyleChanged(EDITSTATE *es, WPARAM which, const STYLESTRUCT *style);
-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, 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);
-
-LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-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 =
-{
- editW, /* name */
- CS_DBLCLKS | CS_PARENTDC, /* style */
- EditWndProcA, /* procA */
- EditWndProcW, /* procW */
- sizeof(EDITSTATE *), /* extra */
- IDC_IBEAM, /* cursor */
- 0 /* brush */
-};
-
/*********************************************************************
*
@@ -298,35 +197,6 @@ static inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es)
}
-/*********************************************************************
- *
- * WM_CLEAR
- *
- */
-static inline void EDIT_WM_Clear(EDITSTATE *es)
-{
- static const WCHAR empty_stringW[] = {0};
-
- /* Protect read-only edit control from modification */
- if(es->style & ES_READONLY)
- return;
-
- EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE);
-}
-
-
-/*********************************************************************
- *
- * WM_CUT
- *
- */
-static inline void EDIT_WM_Cut(EDITSTATE *es)
-{
- EDIT_WM_Copy(es);
- EDIT_WM_Clear(es);
-}
-
-
/**********************************************************************
* get_app_version
*
@@ -362,18 +232,6 @@ static DWORD get_app_version(void)
return version;
}
-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)
-{
- es->text_length = (UINT)-1;
-}
-
static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
{
HBRUSH hbrush;
@@ -391,693 +249,141 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
return hbrush;
}
-static inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode)
-{
- if(unicode)
- return DefWindowProcW(hwnd, msg, wParam, lParam);
- else
- 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
+ * EDIT_WordBreakProc
*
- * The messages are in the order of the actual integer values
- * (which can be found in include/windows.h)
- * Wherever possible the 16 bit versions are converted to
- * the 32 bit ones, so that we can 'fall through' to the
- * helper functions. These are mostly 32 bit (with a few
- * exceptions, clearly indicated by a '16' extension to their
- * names).
+ * Find the beginning of words.
+ * Note: unlike the specs for a WordBreakProc, this function only
+ * allows to be called without linebreaks between s[0] up to
+ * s[count - 1]. Remember it is only called
+ * internally, so we can decide this for ourselves.
*
*/
-static LRESULT EditWndProc_common( HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam, BOOL unicode )
+static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
{
- 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);
-
- if (!es && msg != WM_NCCREATE)
- return DefWindowProcT(hwnd, msg, wParam, lParam, unicode);
-
- if (es && (msg != WM_DESTROY)) EDIT_LockBuffer(es);
-
- switch (msg) {
- case EM_GETSEL16:
- wParam = 0;
- lParam = 0;
- /* fall through */
- case EM_GETSEL:
- result = EDIT_EM_GetSel(es, (PUINT)wParam, (PUINT)lParam);
- break;
-
- case EM_SETSEL16:
- if ((short)LOWORD(lParam) == -1)
- EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
- else
- EDIT_EM_SetSel(es, LOWORD(lParam), HIWORD(lParam), FALSE);
- if (!wParam)
- EDIT_EM_ScrollCaret(es);
- result = 1;
- break;
- case EM_SETSEL:
- EDIT_EM_SetSel(es, wParam, lParam, FALSE);
- EDIT_EM_ScrollCaret(es);
- result = 1;
- break;
-
- case EM_GETRECT16:
- if (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;
- case EM_GETRECT:
- if (lParam)
- CopyRect((LPRECT)lParam, &es->format_rect);
- break;
-
- case EM_SETRECT16:
- if ((es->style & ES_MULTILINE) && lParam) {
- RECT 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);
- }
- break;
- case EM_SETRECT:
- if ((es->style & ES_MULTILINE) && lParam) {
- EDIT_SetRectNP(es, (LPRECT)lParam);
- EDIT_UpdateText(es, NULL, TRUE);
- }
- break;
-
- case EM_SETRECTNP16:
- if ((es->style & ES_MULTILINE) && lParam) {
- RECT 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;
- case EM_SETRECTNP:
- if ((es->style & ES_MULTILINE) && lParam)
- EDIT_SetRectNP(es, (LPRECT)lParam);
- break;
-
- case EM_SCROLL16:
- case EM_SCROLL:
- result = EDIT_EM_Scroll(es, (INT)wParam);
- break;
-
- case EM_LINESCROLL16:
- wParam = (WPARAM)(INT)(SHORT)HIWORD(lParam);
- lParam = (LPARAM)(INT)(SHORT)LOWORD(lParam);
- /* fall through */
- case EM_LINESCROLL:
- result = (LRESULT)EDIT_EM_LineScroll(es, (INT)wParam, (INT)lParam);
- break;
-
- case EM_SCROLLCARET16:
- case EM_SCROLLCARET:
- EDIT_EM_ScrollCaret(es);
- result = 1;
- break;
-
- case EM_GETMODIFY16:
- case EM_GETMODIFY:
- result = ((es->flags & EF_MODIFIED) != 0);
- break;
-
- case EM_SETMODIFY16:
- case EM_SETMODIFY:
- if (wParam)
- es->flags |= EF_MODIFIED;
- else
- es->flags &= ~(EF_MODIFIED | EF_UPDATE); /* reset pending updates */
- break;
-
- case EM_GETLINECOUNT16:
- case EM_GETLINECOUNT:
- result = (es->style & ES_MULTILINE) ? es->line_count : 1;
- break;
-
- case EM_LINEINDEX16:
- if ((INT16)wParam == -1)
- wParam = (WPARAM)-1;
- /* fall through */
- case EM_LINEINDEX:
- result = (LRESULT)EDIT_EM_LineIndex(es, (INT)wParam);
- break;
-
- case EM_SETHANDLE16:
- EDIT_EM_SetHandle16(es, (HLOCAL16)wParam);
- break;
- case EM_SETHANDLE:
- EDIT_EM_SetHandle(es, (HLOCAL)wParam);
- break;
-
- case EM_GETHANDLE16:
- result = (LRESULT)EDIT_EM_GetHandle16(es);
- break;
- case EM_GETHANDLE:
- result = (LRESULT)EDIT_EM_GetHandle(es);
- break;
-
- case EM_GETTHUMB16:
- case EM_GETTHUMB:
- result = EDIT_EM_GetThumb(es);
- break;
-
- /* these messages missing from specs */
- case WM_USER+15:
- case 0x00bf:
- case WM_USER+16:
- case 0x00c0:
- case WM_USER+19:
- case 0x00c3:
- case WM_USER+26:
- case 0x00ca:
- FIXME("undocumented message 0x%x, please report\n", msg);
- result = DefWindowProcW(hwnd, msg, wParam, lParam);
- break;
-
- case EM_LINELENGTH16:
- case EM_LINELENGTH:
- result = (LRESULT)EDIT_EM_LineLength(es, (INT)wParam);
- break;
-
- case EM_REPLACESEL16:
- lParam = (LPARAM)MapSL(lParam);
- unicode = FALSE; /* 16-bit message is always ascii */
- /* fall through */
- case EM_REPLACESEL:
- {
- LPWSTR textW;
-
- if(unicode)
- textW = (LPWSTR)lParam;
- else
- {
- 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);
- }
-
- EDIT_EM_ReplaceSel(es, (BOOL)wParam, textW, TRUE, TRUE);
- result = 1;
-
- if(!unicode)
- HeapFree(GetProcessHeap(), 0, textW);
- break;
- }
-
- case EM_GETLINE16:
- lParam = (LPARAM)MapSL(lParam);
- unicode = FALSE; /* 16-bit message is always ascii */
- /* fall through */
- case EM_GETLINE:
- result = (LRESULT)EDIT_EM_GetLine(es, (INT)wParam, (LPWSTR)lParam, unicode);
- break;
-
- case EM_LIMITTEXT16:
- case EM_SETLIMITTEXT:
- EDIT_EM_SetLimitText(es, wParam);
- break;
-
- case EM_CANUNDO16:
- case EM_CANUNDO:
- result = (LRESULT)EDIT_EM_CanUndo(es);
- break;
-
- case EM_UNDO16:
- case EM_UNDO:
- case WM_UNDO:
- result = (LRESULT)EDIT_EM_Undo(es);
- break;
-
- case EM_FMTLINES16:
- case EM_FMTLINES:
- result = (LRESULT)EDIT_EM_FmtLines(es, (BOOL)wParam);
- break;
-
- case EM_LINEFROMCHAR16:
- case EM_LINEFROMCHAR:
- result = (LRESULT)EDIT_EM_LineFromChar(es, (INT)wParam);
- break;
-
- case EM_SETTABSTOPS16:
- result = (LRESULT)EDIT_EM_SetTabStops16(es, (INT)wParam, MapSL(lParam));
- break;
- case EM_SETTABSTOPS:
- result = (LRESULT)EDIT_EM_SetTabStops(es, (INT)wParam, (LPINT)lParam);
- break;
-
- case EM_SETPASSWORDCHAR16:
- unicode = FALSE; /* 16-bit message is always ascii */
- /* fall through */
- case EM_SETPASSWORDCHAR:
- {
- WCHAR charW = 0;
-
- if(unicode)
- charW = (WCHAR)wParam;
- else
- {
- CHAR charA = wParam;
- MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
- }
-
- EDIT_EM_SetPasswordChar(es, charW);
- break;
- }
+ INT ret = 0;
- case EM_EMPTYUNDOBUFFER16:
- case EM_EMPTYUNDOBUFFER:
- EDIT_EM_EmptyUndoBuffer(es);
- break;
+ TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
- case EM_GETFIRSTVISIBLELINE16:
- result = es->y_offset;
- break;
- case EM_GETFIRSTVISIBLELINE:
- result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
- break;
+ if(!s) return 0;
- case EM_SETREADONLY16:
- case EM_SETREADONLY:
- if (wParam) {
- SetWindowLongW( hwnd, GWL_STYLE,
- GetWindowLongW( hwnd, GWL_STYLE ) | ES_READONLY );
- es->style |= ES_READONLY;
+ switch (action) {
+ case WB_LEFT:
+ if (!count)
+ break;
+ if (index)
+ index--;
+ if (s[index] == ' ') {
+ while (index && (s[index] == ' '))
+ index--;
+ if (index) {
+ while (index && (s[index] != ' '))
+ index--;
+ if (s[index] == ' ')
+ index++;
+ }
} else {
- SetWindowLongW( hwnd, GWL_STYLE,
- GetWindowLongW( hwnd, GWL_STYLE ) & ~ES_READONLY );
- es->style &= ~ES_READONLY;
- }
- result = 1;
- break;
-
- case EM_SETWORDBREAKPROC16:
- EDIT_EM_SetWordBreakProc16(es, (EDITWORDBREAKPROC16)lParam);
- break;
- case EM_SETWORDBREAKPROC:
- EDIT_EM_SetWordBreakProc(es, (void *)lParam);
- break;
-
- case EM_GETWORDBREAKPROC16:
- result = (LRESULT)es->word_break_proc16;
- break;
- case EM_GETWORDBREAKPROC:
- result = (LRESULT)es->word_break_proc;
- break;
-
- case EM_GETPASSWORDCHAR16:
- unicode = FALSE; /* 16-bit message is always ascii */
- /* fall through */
- case EM_GETPASSWORDCHAR:
- {
- if(unicode)
- result = es->password_char;
- else
- {
- WCHAR charW = es->password_char;
- CHAR charA = 0;
- WideCharToMultiByte(CP_ACP, 0, &charW, 1, &charA, 1, NULL, NULL);
- result = charA;
- }
- break;
- }
-
- /* The following EM_xxx are new to win95 and don't exist for 16 bit */
-
- case EM_SETMARGINS:
- EDIT_EM_SetMargins(es, (INT)wParam, LOWORD(lParam), HIWORD(lParam), TRUE);
- break;
-
- case EM_GETMARGINS:
- result = MAKELONG(es->left_margin, es->right_margin);
- break;
-
- case EM_GETLIMITTEXT:
- result = es->buffer_limit;
- break;
-
- case EM_POSFROMCHAR:
- if ((INT)wParam >= get_text_length(es)) result = -1;
- else result = EDIT_EM_PosFromChar(es, (INT)wParam, FALSE);
- break;
-
- case EM_CHARFROMPOS:
- result = EDIT_EM_CharFromPos(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
- break;
-
- /* End of the EM_ messages which were in numerical order; what order
- * are these in? vaguely alphabetical?
- */
-
- case WM_NCCREATE:
- result = EDIT_WM_NCCreate(hwnd, (LPCREATESTRUCTW)lParam, unicode);
- break;
-
- case WM_DESTROY:
- result = EDIT_WM_Destroy(es);
- es = NULL;
- break;
-
- case WM_GETDLGCODE:
- result = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
-
- if (es->style & ES_MULTILINE)
- result |= DLGC_WANTALLKEYS;
-
- if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
- {
- int vk = (int)((LPMSG)lParam)->wParam;
-
- 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];
-
- 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;
-
- if(unicode)
- charW = wParam;
- else
- {
- CHAR charA = wParam;
- MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
+ while (index && (s[index] != ' '))
+ index--;
+ if (s[index] == ' ')
+ index++;
}
-
- 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;
-
- case WM_COMMAND:
- EDIT_WM_Command(es, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
- break;
-
- case WM_CONTEXTMENU:
- EDIT_WM_ContextMenu(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
- break;
-
- case WM_COPY:
- EDIT_WM_Copy(es);
+ ret = index;
break;
-
- case WM_CREATE:
- if(unicode)
- result = EDIT_WM_Create(es, ((LPCREATESTRUCTW)lParam)->lpszName);
- else
- {
- LPCSTR nameA = ((LPCREATESTRUCTA)lParam)->lpszName;
- 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);
- }
- result = EDIT_WM_Create(es, nameW);
- HeapFree(GetProcessHeap(), 0, nameW);
+ case WB_RIGHT:
+ if (!count)
+ break;
+ if (index)
+ index--;
+ if (s[index] == ' ')
+ while ((index < count) && (s[index] == ' ')) index++;
+ else {
+ while (s[index] && (s[index] != ' ') && (index < count))
+ index++;
+ while ((s[index] == ' ') && (index < count)) index++;
}
+ ret = index;
break;
-
- case WM_CUT:
- EDIT_WM_Cut(es);
- break;
-
- case WM_ENABLE:
- es->bEnableState = (BOOL) wParam;
- EDIT_UpdateText(es, NULL, TRUE);
- break;
-
- case WM_ERASEBKGND:
- /* we do the proper erase in EDIT_WM_Paint */
- result = 1;
- break;
-
- case WM_GETFONT:
- result = (LRESULT)es->font;
- break;
-
- case WM_GETTEXT:
- result = (LRESULT)EDIT_WM_GetText(es, (INT)wParam, (LPWSTR)lParam, unicode);
- break;
-
- case WM_GETTEXTLENGTH:
- if (unicode) result = get_text_length(es);
- else result = WideCharToMultiByte( CP_ACP, 0, es->text, get_text_length(es),
- NULL, 0, NULL, NULL );
- break;
-
- case WM_HSCROLL:
- result = EDIT_WM_HScroll(es, LOWORD(wParam), (short)HIWORD(wParam));
- break;
-
- case WM_KEYDOWN:
- result = EDIT_WM_KeyDown(es, (INT)wParam);
- break;
-
- case WM_KILLFOCUS:
- result = EDIT_WM_KillFocus(es);
- break;
-
- case WM_LBUTTONDBLCLK:
- result = EDIT_WM_LButtonDblClk(es);
- break;
-
- case WM_LBUTTONDOWN:
- result = EDIT_WM_LButtonDown(es, wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
- break;
-
- case WM_LBUTTONUP:
- result = EDIT_WM_LButtonUp(es);
- break;
-
- case WM_MBUTTONDOWN:
- result = EDIT_WM_MButtonDown(es);
- break;
-
- case WM_MOUSEMOVE:
- result = EDIT_WM_MouseMove(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
- break;
-
- case WM_PRINTCLIENT:
- case WM_PAINT:
- EDIT_WM_Paint(es, (HDC)wParam);
- break;
-
- case WM_PASTE:
- EDIT_WM_Paste(es);
- break;
-
- case WM_SETFOCUS:
- EDIT_WM_SetFocus(es);
- break;
-
- case WM_SETFONT:
- EDIT_WM_SetFont(es, (HFONT)wParam, LOWORD(lParam) != 0);
- break;
-
- case WM_SETREDRAW:
- /* FIXME: actually set an internal flag and behave accordingly */
- break;
-
- case WM_SETTEXT:
- EDIT_WM_SetText(es, (LPCWSTR)lParam, unicode);
- result = TRUE;
- break;
-
- case WM_SIZE:
- EDIT_WM_Size(es, (UINT)wParam, LOWORD(lParam), HIWORD(lParam));
- break;
-
- case WM_STYLECHANGED:
- result = EDIT_WM_StyleChanged(es, wParam, (const STYLESTRUCT *)lParam);
- break;
-
- case WM_STYLECHANGING:
- result = 0; /* See EDIT_WM_StyleChanged */
- break;
-
- case WM_SYSKEYDOWN:
- result = EDIT_WM_SysKeyDown(es, (INT)wParam, (DWORD)lParam);
- break;
-
- case WM_TIMER:
- EDIT_WM_Timer(es);
- break;
-
- case WM_VSCROLL:
- result = EDIT_WM_VScroll(es, LOWORD(wParam), (short)HIWORD(wParam));
- break;
-
- case WM_MOUSEWHEEL:
- {
- int gcWheelDelta = 0;
- UINT pulScrollLines = 3;
- SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
-
- if (wParam & (MK_SHIFT | MK_CONTROL)) {
- result = DefWindowProcW(hwnd, msg, wParam, lParam);
- break;
- }
- gcWheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
- if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
- {
- int cLineScroll= (int) min((UINT) es->line_count, pulScrollLines);
- cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
- result = EDIT_EM_LineScroll(es, 0, cLineScroll);
- }
- }
- break;
-
-
- /* IME messages to make the edit control IME aware */
- case WM_IME_SETCONTEXT:
- break;
-
- case WM_IME_STARTCOMPOSITION:
- es->composition_start = es->selection_end;
- es->composition_len = 0;
- break;
-
- case WM_IME_COMPOSITION:
- EDIT_ImeComposition(hwnd, lParam, es);
- break;
-
- case WM_IME_ENDCOMPOSITION:
- 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:
- break;
-
- case WM_IME_SELECT:
- break;
-
- case WM_IME_CONTROL:
+ case WB_ISDELIMITER:
+ ret = (s[index] == ' ');
break;
-
default:
- result = DefWindowProcT(hwnd, msg, wParam, lParam, unicode);
+ ERR("unknown action code, please report !\n");
break;
}
-
- if (es) EDIT_UnlockBuffer(es, FALSE);
-
- TRACE("hwnd=%p msg=%x (%s) -- 0x%08lx\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), result);
-
- return result;
+ return ret;
}
-/*********************************************************************
- *
- * EditWndProcW (USER32.@)
- */
-LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- return EditWndProc_common(hWnd, uMsg, wParam, lParam, TRUE);
-}
/*********************************************************************
*
- * EditWndProc (USER32.@)
+ * EDIT_CallWordBreakProc
+ *
+ * Call appropriate WordBreakProc (internal or external).
+ *
+ * Note: The "start" argument should always be an index referring
+ * to es->text. The actual wordbreak proc might be
+ * 16 bit, so we can't always pass any 32 bit LPSTR.
+ * Hence we assume that es->text is the buffer that holds
+ * the string under examination (we can decide this for ourselves).
+ *
*/
-LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action)
{
- return EditWndProc_common(hWnd, uMsg, wParam, lParam, FALSE);
+ INT ret;
+
+ if (es->word_break_proc16) {
+ HGLOBAL16 hglob16;
+ SEGPTR segptr;
+ INT countA;
+ WORD args[5];
+ DWORD result;
+
+ countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
+ hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
+ segptr = WOWGlobalLock16(hglob16);
+ WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
+ args[4] = SELECTOROF(segptr);
+ args[3] = OFFSETOF(segptr);
+ args[2] = index;
+ args[1] = countA;
+ args[0] = action;
+ WOWCallback16Ex((DWORD)es->word_break_proc16, WCB16_PASCAL, sizeof(args), args, &result);
+ ret = LOWORD(result);
+ GlobalUnlock16(hglob16);
+ GlobalFree16(hglob16);
+ }
+ else if (es->word_break_proc)
+ {
+ if(es->is_unicode)
+ {
+ EDITWORDBREAKPROCW wbpW = (EDITWORDBREAKPROCW)es->word_break_proc;
+
+ TRACE_(relay)("(UNICODE wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
+ es->word_break_proc, debugstr_wn(es->text + start, count), index, count, action);
+ ret = wbpW(es->text + start, index, count, action);
+ }
+ else
+ {
+ EDITWORDBREAKPROCA wbpA = (EDITWORDBREAKPROCA)es->word_break_proc;
+ INT countA;
+ CHAR *textA;
+
+ countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
+ textA = HeapAlloc(GetProcessHeap(), 0, countA);
+ WideCharToMultiByte(CP_ACP, 0, es->text + start, count, textA, countA, NULL, NULL);
+ TRACE_(relay)("(ANSI wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
+ es->word_break_proc, debugstr_an(textA, countA), index, countA, action);
+ ret = wbpA(textA, index, countA, action);
+ HeapFree(GetProcessHeap(), 0, textA);
+ }
+ }
+ else
+ ret = EDIT_WordBreakProc(es->text + start, index, count, action);
+
+ return ret;
}
/*********************************************************************
@@ -1360,6 +666,34 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
ReleaseDC(es->hwndSelf, dc);
}
+
+static inline UINT get_text_length(EDITSTATE *es)
+{
+ if(es->text_length == (UINT)-1)
+ es->text_length = strlenW(es->text);
+ return es->text_length;
+}
+
+/*********************************************************************
+ *
+ * EDIT_GetPasswordPointer_SL
+ *
+ * note: caller should free the (optionally) allocated buffer
+ *
+ */
+static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
+{
+ if (es->style & ES_PASSWORD) {
+ INT len = get_text_length(es);
+ LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
+ text[len] = '\0';
+ while(len) text[--len] = es->password_char;
+ return text;
+ } else
+ return es->text;
+}
+
+
/*********************************************************************
*
* EDIT_CalcLineWidth_SL
@@ -1392,76 +726,6 @@ static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
/*********************************************************************
*
- * EDIT_CallWordBreakProc
- *
- * Call appropriate WordBreakProc (internal or external).
- *
- * Note: The "start" argument should always be an index referring
- * to es->text. The actual wordbreak proc might be
- * 16 bit, so we can't always pass any 32 bit LPSTR.
- * Hence we assume that es->text is the buffer that holds
- * the string under examination (we can decide this for ourselves).
- *
- */
-static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action)
-{
- INT ret;
-
- if (es->word_break_proc16) {
- HGLOBAL16 hglob16;
- SEGPTR segptr;
- INT countA;
- WORD args[5];
- DWORD result;
-
- countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
- hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
- segptr = WOWGlobalLock16(hglob16);
- WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
- args[4] = SELECTOROF(segptr);
- args[3] = OFFSETOF(segptr);
- args[2] = index;
- args[1] = countA;
- args[0] = action;
- WOWCallback16Ex((DWORD)es->word_break_proc16, WCB16_PASCAL, sizeof(args), args, &result);
- ret = LOWORD(result);
- GlobalUnlock16(hglob16);
- GlobalFree16(hglob16);
- }
- else if (es->word_break_proc)
- {
- if(es->is_unicode)
- {
- EDITWORDBREAKPROCW wbpW = (EDITWORDBREAKPROCW)es->word_break_proc;
-
- TRACE_(relay)("(UNICODE wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
- es->word_break_proc, debugstr_wn(es->text + start, count), index, count, action);
- ret = wbpW(es->text + start, index, count, action);
- }
- else
- {
- EDITWORDBREAKPROCA wbpA = (EDITWORDBREAKPROCA)es->word_break_proc;
- INT countA;
- CHAR *textA;
-
- countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
- textA = HeapAlloc(GetProcessHeap(), 0, countA);
- WideCharToMultiByte(CP_ACP, 0, es->text + start, count, textA, countA, NULL, NULL);
- TRACE_(relay)("(ANSI wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
- es->word_break_proc, debugstr_an(textA, countA), index, countA, action);
- ret = wbpA(textA, index, countA, action);
- HeapFree(GetProcessHeap(), 0, textA);
- }
- }
- else
- ret = EDIT_WordBreakProc(es->text + start, index, count, action);
-
- return ret;
-}
-
-
-/*********************************************************************
- *
* EDIT_CharFromPos
*
* Beware: This is not the function called on EM_CHARFROMPOS
@@ -1620,6 +884,209 @@ static void EDIT_ConfinePoint(const EDITSTATE *es, LPINT x, LPINT y)
/*********************************************************************
*
+ * EM_LINEFROMCHAR
+ *
+ */
+static INT EDIT_EM_LineFromChar(EDITSTATE *es, INT index)
+{
+ INT line;
+ LINEDEF *line_def;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+ if (index > (INT)get_text_length(es))
+ return es->line_count - 1;
+ if (index == -1)
+ index = min(es->selection_start, es->selection_end);
+
+ line = 0;
+ line_def = es->first_line_def;
+ index -= line_def->length;
+ while ((index >= 0) && line_def->next) {
+ line++;
+ line_def = line_def->next;
+ index -= line_def->length;
+ }
+ return line;
+}
+
+
+/*********************************************************************
+ *
+ * EM_LINEINDEX
+ *
+ */
+static INT EDIT_EM_LineIndex(const EDITSTATE *es, INT line)
+{
+ INT line_index;
+ const LINEDEF *line_def;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+ if (line >= es->line_count)
+ return -1;
+
+ line_index = 0;
+ line_def = es->first_line_def;
+ if (line == -1) {
+ INT index = es->selection_end - line_def->length;
+ while ((index >= 0) && line_def->next) {
+ line_index += line_def->length;
+ line_def = line_def->next;
+ index -= line_def->length;
+ }
+ } else {
+ while (line > 0) {
+ line_index += line_def->length;
+ line_def = line_def->next;
+ line--;
+ }
+ }
+ return line_index;
+}
+
+
+/*********************************************************************
+ *
+ * EM_LINELENGTH
+ *
+ */
+static INT EDIT_EM_LineLength(EDITSTATE *es, INT index)
+{
+ LINEDEF *line_def;
+
+ if (!(es->style & ES_MULTILINE))
+ return get_text_length(es);
+
+ if (index == -1) {
+ /* get the number of remaining non-selected chars of selected lines */
+ INT32 l; /* line number */
+ INT32 li; /* index of first char in line */
+ INT32 count;
+ l = EDIT_EM_LineFromChar(es, es->selection_start);
+ /* # chars before start of selection area */
+ count = es->selection_start - EDIT_EM_LineIndex(es, l);
+ l = EDIT_EM_LineFromChar(es, es->selection_end);
+ /* # chars after end of selection */
+ li = EDIT_EM_LineIndex(es, l);
+ count += li + EDIT_EM_LineLength(es, li) - es->selection_end;
+ return count;
+ }
+ line_def = es->first_line_def;
+ index -= line_def->length;
+ while ((index >= 0) && line_def->next) {
+ line_def = line_def->next;
+ index -= line_def->length;
+ }
+ return line_def->net_length;
+}
+
+
+/*********************************************************************
+ *
+ * EM_POSFROMCHAR
+ *
+ */
+static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
+{
+ INT len = get_text_length(es);
+ INT l;
+ INT li;
+ INT x;
+ INT y = 0;
+ INT w;
+ INT lw = 0;
+ INT ll = 0;
+ HDC dc;
+ HFONT old_font = 0;
+ SIZE size;
+ LINEDEF *line_def;
+
+ index = min(index, len);
+ dc = GetDC(es->hwndSelf);
+ if (es->font)
+ old_font = SelectObject(dc, es->font);
+ if (es->style & ES_MULTILINE) {
+ l = EDIT_EM_LineFromChar(es, index);
+ y = (l - es->y_offset) * es->line_height;
+ li = EDIT_EM_LineIndex(es, l);
+ if (after_wrap && (li == index) && l) {
+ INT l2 = l - 1;
+ line_def = es->first_line_def;
+ while (l2) {
+ line_def = line_def->next;
+ l2--;
+ }
+ if (line_def->ending == END_WRAP) {
+ l--;
+ y -= es->line_height;
+ li = EDIT_EM_LineIndex(es, l);
+ }
+ }
+
+ line_def = es->first_line_def;
+ while (line_def->index != li)
+ line_def = line_def->next;
+
+ ll = line_def->net_length;
+ lw = line_def->width;
+
+ w = es->format_rect.right - es->format_rect.left;
+ if (es->style & ES_RIGHT)
+ {
+ x = LOWORD(GetTabbedTextExtentW(dc, es->text + li + (index - li), ll - (index - li),
+ es->tabs_count, es->tabs)) - es->x_offset;
+ x = w - x;
+ }
+ else if (es->style & ES_CENTER)
+ {
+ x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
+ es->tabs_count, es->tabs)) - es->x_offset;
+ x += (w - lw) / 2;
+ }
+ else /* ES_LEFT */
+ {
+ x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
+ es->tabs_count, es->tabs)) - es->x_offset;
+ }
+ } else {
+ LPWSTR text = EDIT_GetPasswordPointer_SL(es);
+ if (index < es->x_offset) {
+ GetTextExtentPoint32W(dc, text + index,
+ es->x_offset - index, &size);
+ x = -size.cx;
+ } else {
+ GetTextExtentPoint32W(dc, text + es->x_offset,
+ index - es->x_offset, &size);
+ x = size.cx;
+
+ if (!es->x_offset && (es->style & (ES_RIGHT | ES_CENTER)))
+ {
+ w = es->format_rect.right - es->format_rect.left;
+ if (w > es->text_width)
+ {
+ if (es->style & ES_RIGHT)
+ x += w - es->text_width;
+ else if (es->style & ES_CENTER)
+ x += (w - es->text_width) / 2;
+ }
+ }
+ }
+ y = 0;
+ if (es->style & ES_PASSWORD)
+ HeapFree(GetProcessHeap(), 0, text);
+ }
+ x += es->format_rect.left;
+ y += es->format_rect.top;
+ if (es->font)
+ SelectObject(dc, old_font);
+ ReleaseDC(es->hwndSelf, dc);
+ return MAKELONG((INT16)x, (INT16)y);
+}
+
+
+/*********************************************************************
+ *
* EDIT_GetLineRect
*
* Calculates the bounding rectangle for a line from a starting
@@ -1640,26 +1107,11 @@ static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT
}
-/*********************************************************************
- *
- * EDIT_GetPasswordPointer_SL
- *
- * note: caller should free the (optionally) allocated buffer
- *
- */
-static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
+static inline void text_buffer_changed(EDITSTATE *es)
{
- if (es->style & ES_PASSWORD) {
- INT len = get_text_length(es);
- LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
- text[len] = '\0';
- while(len) text[--len] = es->password_char;
- return text;
- } else
- return es->text;
+ es->text_length = (UINT)-1;
}
-
/*********************************************************************
*
* EDIT_LockBuffer
@@ -1755,6 +1207,211 @@ static void EDIT_LockBuffer(EDITSTATE *es)
/*********************************************************************
*
+ * EDIT_UnlockBuffer
+ *
+ */
+static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force)
+{
+
+ /* Edit window might be already destroyed */
+ if(!IsWindow(es->hwndSelf))
+ {
+ WARN("edit hwnd %p already destroyed\n", es->hwndSelf);
+ return;
+ }
+
+ if (!es->lock_count) {
+ ERR("lock_count == 0 ... please report\n");
+ return;
+ }
+ if (!es->text) {
+ ERR("es->text == 0 ... please report\n");
+ return;
+ }
+
+ if (force || (es->lock_count == 1)) {
+ if (es->hloc32W) {
+ CHAR *textA = NULL;
+ UINT countA = 0;
+ UINT countW = get_text_length(es) + 1;
+ STACK16FRAME* stack16 = NULL;
+ HANDLE16 oldDS = 0;
+
+ if(es->hloc32A)
+ {
+ UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL);
+ TRACE("Synchronizing with 32-bit ANSI buffer\n");
+ TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new);
+ countA = LocalSize(es->hloc32A);
+ if(countA_new > countA)
+ {
+ HLOCAL hloc32A_new;
+ UINT alloc_size = ROUND_TO_GROW(countA_new);
+ TRACE("Resizing 32-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size);
+ hloc32A_new = LocalReAlloc(es->hloc32A, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
+ if(hloc32A_new)
+ {
+ es->hloc32A = hloc32A_new;
+ countA = LocalSize(hloc32A_new);
+ TRACE("Real new size %d bytes\n", countA);
+ }
+ else
+ WARN("FAILED! Will synchronize partially\n");
+ }
+ textA = LocalLock(es->hloc32A);
+ }
+ 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);
+
+ 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 = LocalReAlloc16(es->hloc16, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
+ if(hloc16_new)
+ {
+ es->hloc16 = hloc16_new;
+ countA = LocalSize16(hloc16_new);
+ TRACE("Real new size %d bytes\n", countA);
+ }
+ else
+ WARN("FAILED! Will synchronize partially\n");
+ }
+ textA = MapSL(LocalLock16(es->hloc16));
+ }
+
+ if(textA)
+ {
+ WideCharToMultiByte(CP_ACP, 0, es->text, countW, textA, countA, NULL, NULL);
+ if(stack16)
+ LocalUnlock16(es->hloc16);
+ else
+ LocalUnlock(es->hloc32A);
+ }
+
+ if (stack16) stack16->ds = oldDS;
+ LocalUnlock(es->hloc32W);
+ es->text = NULL;
+ }
+ else {
+ ERR("no buffer ... please report\n");
+ return;
+ }
+ }
+ es->lock_count--;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MakeFit
+ *
+ * Try to fit size + 1 characters in the buffer.
+ */
+static BOOL EDIT_MakeFit(EDITSTATE *es, UINT size)
+{
+ HLOCAL hNew32W;
+
+ if (size <= es->buffer_size)
+ return TRUE;
+
+ TRACE("trying to ReAlloc to %d+1 characters\n", size);
+
+ /* Force edit to unlock it's buffer. es->text now NULL */
+ EDIT_UnlockBuffer(es, TRUE);
+
+ if (es->hloc32W) {
+ UINT alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
+ if ((hNew32W = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT))) {
+ TRACE("Old 32 bit handle %p, new handle %p\n", es->hloc32W, hNew32W);
+ es->hloc32W = hNew32W;
+ es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
+ }
+ }
+
+ EDIT_LockBuffer(es);
+
+ if (es->buffer_size < size) {
+ WARN("FAILED ! We now have %d+1\n", es->buffer_size);
+ EDIT_NOTIFY_PARENT(es, EN_ERRSPACE);
+ return FALSE;
+ } else {
+ TRACE("We now have %d+1\n", es->buffer_size);
+ return TRUE;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MakeUndoFit
+ *
+ * Try to fit size + 1 bytes in the undo buffer.
+ *
+ */
+static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size)
+{
+ UINT alloc_size;
+
+ if (size <= es->undo_buffer_size)
+ return TRUE;
+
+ TRACE("trying to ReAlloc to %d+1\n", size);
+
+ alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
+ if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, alloc_size))) {
+ es->undo_buffer_size = alloc_size/sizeof(WCHAR) - 1;
+ return TRUE;
+ }
+ else
+ {
+ WARN("FAILED ! We now have %d+1\n", es->undo_buffer_size);
+ return FALSE;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_UpdateTextRegion
+ *
+ */
+static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase)
+{
+ if (es->flags & EF_UPDATE) {
+ es->flags &= ~EF_UPDATE;
+ EDIT_NOTIFY_PARENT(es, EN_UPDATE);
+ }
+ InvalidateRgn(es->hwndSelf, hrgn, bErase);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_UpdateText
+ *
+ */
+static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase)
+{
+ if (es->flags & EF_UPDATE) {
+ es->flags &= ~EF_UPDATE;
+ EDIT_NOTIFY_PARENT(es, EN_UPDATE);
+ }
+ InvalidateRect(es->hwndSelf, rc, bErase);
+}
+
+/*********************************************************************
+ *
* EDIT_SL_InvalidateText
*
* Called from EDIT_InvalidateText().
@@ -1772,6 +1429,12 @@ static void EDIT_SL_InvalidateText(EDITSTATE *es, INT start, INT end)
}
+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);
+}
+
/*********************************************************************
*
* EDIT_ML_InvalidateText
@@ -1868,70 +1531,315 @@ static void EDIT_InvalidateText(EDITSTATE *es, INT start, INT end)
/*********************************************************************
*
- * EDIT_MakeFit
+ * EDIT_EM_SetSel
+ *
+ * note: unlike the specs say: the order of start and end
+ * _is_ preserved in Windows. (i.e. start can be > end)
+ * In other words: this handler is OK
*
- * Try to fit size + 1 characters in the buffer.
*/
-static BOOL EDIT_MakeFit(EDITSTATE *es, UINT size)
+static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
{
- HLOCAL hNew32W;
+ UINT old_start = es->selection_start;
+ UINT old_end = es->selection_end;
+ UINT len = get_text_length(es);
- if (size <= es->buffer_size)
- return TRUE;
+ if (start == (UINT)-1) {
+ start = es->selection_end;
+ end = es->selection_end;
+ } else {
+ start = min(start, len);
+ end = min(end, len);
+ }
+ es->selection_start = start;
+ es->selection_end = end;
+ if (after_wrap)
+ es->flags |= EF_AFTER_WRAP;
+ else
+ es->flags &= ~EF_AFTER_WRAP;
+ /* Compute the necessary invalidation region. */
+ /* Note that we don't need to invalidate regions which have
+ * "never" been selected, or those which are "still" selected.
+ * In fact, every time we hit a selection boundary, we can
+ * *toggle* whether we need to invalidate. Thus we can optimize by
+ * *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) 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);
+ ORDER_UINT(old_start, old_end);
+ ORDER_UINT(start, end);
+ /* Note that at this point 'end' and 'old_start' are not in order, but
+ * start is definitely the min. and old_end is definitely the max. */
+ if (end != old_start)
+ {
+/*
+ * One can also do
+ * ORDER_UINT32(end, old_start);
+ * EDIT_InvalidateText(es, start, end);
+ * EDIT_InvalidateText(es, old_start, old_end);
+ * in place of the following if statement.
+ * (That would complete the optimal five-comparison four-element sort.)
+ */
+ if (old_start > end )
+ {
+ EDIT_InvalidateText(es, start, end);
+ EDIT_InvalidateText(es, old_start, old_end);
+ }
+ else
+ {
+ EDIT_InvalidateText(es, start, old_start);
+ EDIT_InvalidateText(es, end, old_end);
+ }
+ }
+ else EDIT_InvalidateText(es, start, old_end);
+}
- TRACE("trying to ReAlloc to %d+1 characters\n", size);
- /* Force edit to unlock it's buffer. es->text now NULL */
- EDIT_UnlockBuffer(es, TRUE);
+/*********************************************************************
+ *
+ * EDIT_UpdateScrollInfo
+ *
+ */
+static void EDIT_UpdateScrollInfo(EDITSTATE *es)
+{
+ if ((es->style & WS_VSCROLL) && !(es->flags & EF_VSCROLL_TRACK))
+ {
+ SCROLLINFO si;
+ si.cbSize = sizeof(SCROLLINFO);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
+ si.nMin = 0;
+ si.nMax = es->line_count - 1;
+ si.nPage = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ si.nPos = es->y_offset;
+ TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
+ si.nMin, si.nMax, si.nPage, si.nPos);
+ SetScrollInfo(es->hwndSelf, SB_VERT, &si, TRUE);
+ }
- if (es->hloc32W) {
- UINT alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
- if ((hNew32W = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT))) {
- TRACE("Old 32 bit handle %p, new handle %p\n", es->hloc32W, hNew32W);
- es->hloc32W = hNew32W;
- es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
- }
+ if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
+ {
+ SCROLLINFO si;
+ si.cbSize = sizeof(SCROLLINFO);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
+ si.nMin = 0;
+ si.nMax = es->text_width - 1;
+ si.nPage = es->format_rect.right - es->format_rect.left;
+ si.nPos = es->x_offset;
+ TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
+ si.nMin, si.nMax, si.nPage, si.nPos);
+ SetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE);
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_EM_LineScroll_internal
+ *
+ * Version of EDIT_EM_LineScroll for internal use.
+ * It doesn't refuse if ES_MULTILINE is set and assumes that
+ * dx is in pixels, dy - in lines.
+ *
+ */
+static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy)
+{
+ INT nyoff;
+ INT x_offset_in_pixels;
+ INT lines_per_page = (es->format_rect.bottom - es->format_rect.top) /
+ es->line_height;
+
+ if (es->style & ES_MULTILINE)
+ {
+ x_offset_in_pixels = es->x_offset;
+ }
+ else
+ {
+ dy = 0;
+ x_offset_in_pixels = (short)LOWORD(EDIT_EM_PosFromChar(es, es->x_offset, FALSE));
}
- EDIT_LockBuffer(es);
+ if (-dx > x_offset_in_pixels)
+ dx = -x_offset_in_pixels;
+ if (dx > es->text_width - x_offset_in_pixels)
+ dx = es->text_width - x_offset_in_pixels;
+ nyoff = max(0, es->y_offset + dy);
+ if (nyoff >= es->line_count - lines_per_page)
+ nyoff = max(0, es->line_count - lines_per_page);
+ dy = (es->y_offset - nyoff) * es->line_height;
+ if (dx || dy) {
+ RECT rc1;
+ RECT rc;
- if (es->buffer_size < size) {
- WARN("FAILED ! We now have %d+1\n", es->buffer_size);
- EDIT_NOTIFY_PARENT(es, EN_ERRSPACE);
- return FALSE;
- } else {
- TRACE("We now have %d+1\n", es->buffer_size);
- return TRUE;
+ es->y_offset = nyoff;
+ if(es->style & ES_MULTILINE)
+ es->x_offset += dx;
+ else
+ es->x_offset += dx / es->char_width;
+
+ GetClientRect(es->hwndSelf, &rc1);
+ IntersectRect(&rc, &rc1, &es->format_rect);
+ ScrollWindowEx(es->hwndSelf, -dx, dy,
+ NULL, &rc, NULL, NULL, SW_INVALIDATE);
+ /* force scroll info update */
+ EDIT_UpdateScrollInfo(es);
}
+ if (dx && !(es->flags & EF_HSCROLL_TRACK))
+ EDIT_NOTIFY_PARENT(es, EN_HSCROLL);
+ if (dy && !(es->flags & EF_VSCROLL_TRACK))
+ EDIT_NOTIFY_PARENT(es, EN_VSCROLL);
+ return TRUE;
}
-
/*********************************************************************
*
- * EDIT_MakeUndoFit
+ * EM_LINESCROLL
*
- * Try to fit size + 1 bytes in the undo buffer.
+ * NOTE: dx is in average character widths, dy - in lines;
*
*/
-static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size)
+static BOOL EDIT_EM_LineScroll(EDITSTATE *es, INT dx, INT dy)
{
- UINT alloc_size;
+ if (!(es->style & ES_MULTILINE))
+ return FALSE;
- if (size <= es->undo_buffer_size)
- return TRUE;
+ dx *= es->char_width;
+ return EDIT_EM_LineScroll_internal(es, dx, dy);
+}
- TRACE("trying to ReAlloc to %d+1\n", size);
- alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
- if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, alloc_size))) {
- es->undo_buffer_size = alloc_size/sizeof(WCHAR) - 1;
- return TRUE;
+/*********************************************************************
+ *
+ * EM_SCROLL
+ *
+ */
+static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action)
+{
+ INT dy;
+
+ if (!(es->style & ES_MULTILINE))
+ return (LRESULT)FALSE;
+
+ dy = 0;
+
+ switch (action) {
+ case SB_LINEUP:
+ if (es->y_offset)
+ dy = -1;
+ break;
+ case SB_LINEDOWN:
+ if (es->y_offset < es->line_count - 1)
+ dy = 1;
+ break;
+ case SB_PAGEUP:
+ if (es->y_offset)
+ dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ break;
+ case SB_PAGEDOWN:
+ if (es->y_offset < es->line_count - 1)
+ dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ break;
+ default:
+ return (LRESULT)FALSE;
}
- else
- {
- WARN("FAILED ! We now have %d+1\n", es->undo_buffer_size);
- return FALSE;
+ if (dy) {
+ 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;
+
+ /* Notification is done in EDIT_EM_LineScroll */
+ if(dy)
+ EDIT_EM_LineScroll(es, 0, dy);
}
+ return MAKELONG((INT16)dy, (BOOL16)TRUE);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_SetCaretPos
+ *
+ */
+static void EDIT_SetCaretPos(EDITSTATE *es, INT pos,
+ BOOL after_wrap)
+{
+ LRESULT 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));
+}
+
+
+/*********************************************************************
+ *
+ * EM_SCROLLCARET
+ *
+ */
+static void EDIT_EM_ScrollCaret(EDITSTATE *es)
+{
+ if (es->style & ES_MULTILINE) {
+ INT l;
+ INT vlc;
+ INT ww;
+ INT cw = es->char_width;
+ INT x;
+ INT dy = 0;
+ INT dx = 0;
+
+ l = EDIT_EM_LineFromChar(es, es->selection_end);
+ x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP));
+ vlc = get_vertical_line_count(es);
+ if (l >= es->y_offset + vlc)
+ dy = l - vlc + 1 - es->y_offset;
+ if (l < es->y_offset)
+ dy = l - es->y_offset;
+ ww = es->format_rect.right - es->format_rect.left;
+ if (x < es->format_rect.left)
+ dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
+ if (x > es->format_rect.right)
+ dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
+ if (dy || dx || (es->y_offset && (es->line_count - es->y_offset < vlc)))
+ {
+ /* check if we are going to move too far */
+ if(es->x_offset + dx + ww > es->text_width)
+ dx = es->text_width - ww - es->x_offset;
+ if(dx || dy || (es->y_offset && (es->line_count - es->y_offset < vlc)))
+ EDIT_EM_LineScroll_internal(es, dx, dy);
+ }
+ } else {
+ INT x;
+ INT goal;
+ INT format_width;
+
+ x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
+ format_width = es->format_rect.right - es->format_rect.left;
+ if (x < es->format_rect.left) {
+ goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
+ do {
+ es->x_offset--;
+ x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
+ } while ((x < goal) && es->x_offset);
+ /* FIXME: use ScrollWindow() somehow to improve performance */
+ EDIT_UpdateText(es, NULL, TRUE);
+ } else if (x > es->format_rect.right) {
+ INT x_last;
+ INT len = get_text_length(es);
+ goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
+ do {
+ es->x_offset++;
+ x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
+ x_last = (short)LOWORD(EDIT_EM_PosFromChar(es, len, FALSE));
+ } while ((x > goal) && (x_last > es->format_rect.right));
+ /* FIXME: use ScrollWindow() somehow to improve performance */
+ EDIT_UpdateText(es, NULL, TRUE);
+ }
+ }
+
+ if(es->flags & EF_FOCUSED)
+ EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
}
@@ -2195,50 +2103,6 @@ static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend)
/*********************************************************************
*
- * EDIT_PaintLine
- *
- */
-static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
-{
- INT s = es->selection_start;
- INT e = es->selection_end;
- INT li;
- INT ll;
- INT x;
- INT y;
- LRESULT pos;
-
- if (es->style & ES_MULTILINE) {
- 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)
- return;
-
- TRACE("line=%d\n", line);
-
- pos = EDIT_EM_PosFromChar(es, EDIT_EM_LineIndex(es, line), FALSE);
- x = (short)LOWORD(pos);
- y = (short)HIWORD(pos);
- li = EDIT_EM_LineIndex(es, line);
- ll = EDIT_EM_LineLength(es, li);
- s = min(es->selection_start, es->selection_end);
- e = max(es->selection_start, es->selection_end);
- s = min(li + ll, max(li, s));
- e = min(li + ll, max(li, e));
- 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_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);
-}
-
-
-/*********************************************************************
- *
* EDIT_PaintText
*
*/
@@ -2308,15 +2172,45 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
/*********************************************************************
*
- * EDIT_SetCaretPos
+ * EDIT_PaintLine
*
*/
-static void EDIT_SetCaretPos(EDITSTATE *es, INT pos,
- BOOL after_wrap)
+static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
{
- LRESULT 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));
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ INT li;
+ INT ll;
+ INT x;
+ INT y;
+ LRESULT pos;
+
+ if (es->style & ES_MULTILINE) {
+ 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)
+ return;
+
+ TRACE("line=%d\n", line);
+
+ pos = EDIT_EM_PosFromChar(es, EDIT_EM_LineIndex(es, line), FALSE);
+ x = (short)LOWORD(pos);
+ y = (short)HIWORD(pos);
+ li = EDIT_EM_LineIndex(es, line);
+ ll = EDIT_EM_LineLength(es, li);
+ s = min(es->selection_start, es->selection_end);
+ e = max(es->selection_start, es->selection_end);
+ s = min(li + ll, max(li, s));
+ e = min(li + ll, max(li, e));
+ 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_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);
}
@@ -2419,216 +2313,6 @@ static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc)
/*********************************************************************
*
- * EDIT_UnlockBuffer
- *
- */
-static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force)
-{
-
- /* Edit window might be already destroyed */
- if(!IsWindow(es->hwndSelf))
- {
- WARN("edit hwnd %p already destroyed\n", es->hwndSelf);
- return;
- }
-
- if (!es->lock_count) {
- ERR("lock_count == 0 ... please report\n");
- return;
- }
- if (!es->text) {
- ERR("es->text == 0 ... please report\n");
- return;
- }
-
- if (force || (es->lock_count == 1)) {
- if (es->hloc32W) {
- CHAR *textA = NULL;
- UINT countA = 0;
- UINT countW = get_text_length(es) + 1;
- STACK16FRAME* stack16 = NULL;
- HANDLE16 oldDS = 0;
-
- if(es->hloc32A)
- {
- UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL);
- TRACE("Synchronizing with 32-bit ANSI buffer\n");
- TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new);
- countA = LocalSize(es->hloc32A);
- if(countA_new > countA)
- {
- HLOCAL hloc32A_new;
- UINT alloc_size = ROUND_TO_GROW(countA_new);
- TRACE("Resizing 32-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size);
- hloc32A_new = LocalReAlloc(es->hloc32A, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
- if(hloc32A_new)
- {
- es->hloc32A = hloc32A_new;
- countA = LocalSize(hloc32A_new);
- TRACE("Real new size %d bytes\n", countA);
- }
- else
- WARN("FAILED! Will synchronize partially\n");
- }
- textA = LocalLock(es->hloc32A);
- }
- 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);
-
- 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 = LocalReAlloc16(es->hloc16, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
- if(hloc16_new)
- {
- es->hloc16 = hloc16_new;
- countA = LocalSize16(hloc16_new);
- TRACE("Real new size %d bytes\n", countA);
- }
- else
- WARN("FAILED! Will synchronize partially\n");
- }
- textA = MapSL(LocalLock16(es->hloc16));
- }
-
- if(textA)
- {
- WideCharToMultiByte(CP_ACP, 0, es->text, countW, textA, countA, NULL, NULL);
- if(stack16)
- LocalUnlock16(es->hloc16);
- else
- LocalUnlock(es->hloc32A);
- }
-
- if (stack16) stack16->ds = oldDS;
- LocalUnlock(es->hloc32W);
- es->text = NULL;
- }
- else {
- ERR("no buffer ... please report\n");
- return;
- }
- }
- es->lock_count--;
-}
-
-
-/*********************************************************************
- *
- * EDIT_UpdateScrollInfo
- *
- */
-static void EDIT_UpdateScrollInfo(EDITSTATE *es)
-{
- if ((es->style & WS_VSCROLL) && !(es->flags & EF_VSCROLL_TRACK))
- {
- SCROLLINFO si;
- si.cbSize = sizeof(SCROLLINFO);
- si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = es->line_count - 1;
- si.nPage = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
- si.nPos = es->y_offset;
- TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
- si.nMin, si.nMax, si.nPage, si.nPos);
- SetScrollInfo(es->hwndSelf, SB_VERT, &si, TRUE);
- }
-
- if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
- {
- SCROLLINFO si;
- si.cbSize = sizeof(SCROLLINFO);
- si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = es->text_width - 1;
- si.nPage = es->format_rect.right - es->format_rect.left;
- si.nPos = es->x_offset;
- TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
- si.nMin, si.nMax, si.nPage, si.nPos);
- SetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE);
- }
-}
-
-/*********************************************************************
- *
- * EDIT_WordBreakProc
- *
- * Find the beginning of words.
- * Note: unlike the specs for a WordBreakProc, this function only
- * allows to be called without linebreaks between s[0] up to
- * s[count - 1]. Remember it is only called
- * internally, so we can decide this for ourselves.
- *
- */
-static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
-{
- INT ret = 0;
-
- TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
-
- if(!s) return 0;
-
- switch (action) {
- case WB_LEFT:
- if (!count)
- break;
- if (index)
- index--;
- if (s[index] == ' ') {
- while (index && (s[index] == ' '))
- index--;
- if (index) {
- while (index && (s[index] != ' '))
- index--;
- if (s[index] == ' ')
- index++;
- }
- } else {
- while (index && (s[index] != ' '))
- index--;
- if (s[index] == ' ')
- index++;
- }
- ret = index;
- break;
- case WB_RIGHT:
- if (!count)
- break;
- if (index)
- index--;
- if (s[index] == ' ')
- while ((index < count) && (s[index] == ' ')) index++;
- else {
- while (s[index] && (s[index] != ' ') && (index < count))
- index++;
- while ((s[index] == ' ') && (index < count)) index++;
- }
- ret = index;
- break;
- case WB_ISDELIMITER:
- ret = (s[index] == ' ');
- break;
- default:
- ERR("unknown action code, please report !\n");
- break;
- }
- return ret;
-}
-
-
-/*********************************************************************
- *
* EM_CHARFROMPOS
*
* returns line number (not index) in high-order word of result.
@@ -2860,301 +2544,6 @@ static LRESULT EDIT_EM_GetSel(const EDITSTATE *es, PUINT start, PUINT end)
/*********************************************************************
*
- * EM_GETTHUMB
- *
- * FIXME: is this right ? (or should it be only VSCROLL)
- * (and maybe only for edit controls that really have their
- * own scrollbars) (and maybe only for multiline controls ?)
- * All in all: very poorly documented
- *
- */
-static LRESULT EDIT_EM_GetThumb(EDITSTATE *es)
-{
- return MAKELONG(EDIT_WM_VScroll(es, EM_GETTHUMB16, 0),
- EDIT_WM_HScroll(es, EM_GETTHUMB16, 0));
-}
-
-
-/*********************************************************************
- *
- * EM_LINEFROMCHAR
- *
- */
-static INT EDIT_EM_LineFromChar(EDITSTATE *es, INT index)
-{
- INT line;
- LINEDEF *line_def;
-
- if (!(es->style & ES_MULTILINE))
- return 0;
- if (index > (INT)get_text_length(es))
- return es->line_count - 1;
- if (index == -1)
- index = min(es->selection_start, es->selection_end);
-
- line = 0;
- line_def = es->first_line_def;
- index -= line_def->length;
- while ((index >= 0) && line_def->next) {
- line++;
- line_def = line_def->next;
- index -= line_def->length;
- }
- return line;
-}
-
-
-/*********************************************************************
- *
- * EM_LINEINDEX
- *
- */
-static INT EDIT_EM_LineIndex(const EDITSTATE *es, INT line)
-{
- INT line_index;
- const LINEDEF *line_def;
-
- if (!(es->style & ES_MULTILINE))
- return 0;
- if (line >= es->line_count)
- return -1;
-
- line_index = 0;
- line_def = es->first_line_def;
- if (line == -1) {
- INT index = es->selection_end - line_def->length;
- while ((index >= 0) && line_def->next) {
- line_index += line_def->length;
- line_def = line_def->next;
- index -= line_def->length;
- }
- } else {
- while (line > 0) {
- line_index += line_def->length;
- line_def = line_def->next;
- line--;
- }
- }
- return line_index;
-}
-
-
-/*********************************************************************
- *
- * EM_LINELENGTH
- *
- */
-static INT EDIT_EM_LineLength(EDITSTATE *es, INT index)
-{
- LINEDEF *line_def;
-
- if (!(es->style & ES_MULTILINE))
- return get_text_length(es);
-
- if (index == -1) {
- /* get the number of remaining non-selected chars of selected lines */
- INT32 l; /* line number */
- INT32 li; /* index of first char in line */
- INT32 count;
- l = EDIT_EM_LineFromChar(es, es->selection_start);
- /* # chars before start of selection area */
- count = es->selection_start - EDIT_EM_LineIndex(es, l);
- l = EDIT_EM_LineFromChar(es, es->selection_end);
- /* # chars after end of selection */
- li = EDIT_EM_LineIndex(es, l);
- count += li + EDIT_EM_LineLength(es, li) - es->selection_end;
- return count;
- }
- line_def = es->first_line_def;
- index -= line_def->length;
- while ((index >= 0) && line_def->next) {
- line_def = line_def->next;
- index -= line_def->length;
- }
- return line_def->net_length;
-}
-
-
-/*********************************************************************
- *
- * EM_LINESCROLL
- *
- * NOTE: dx is in average character widths, dy - in lines;
- *
- */
-static BOOL EDIT_EM_LineScroll(EDITSTATE *es, INT dx, INT dy)
-{
- if (!(es->style & ES_MULTILINE))
- return FALSE;
-
- dx *= es->char_width;
- return EDIT_EM_LineScroll_internal(es, dx, dy);
-}
-
-/*********************************************************************
- *
- * EDIT_EM_LineScroll_internal
- *
- * Version of EDIT_EM_LineScroll for internal use.
- * It doesn't refuse if ES_MULTILINE is set and assumes that
- * dx is in pixels, dy - in lines.
- *
- */
-static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy)
-{
- INT nyoff;
- INT x_offset_in_pixels;
- INT lines_per_page = (es->format_rect.bottom - es->format_rect.top) /
- es->line_height;
-
- if (es->style & ES_MULTILINE)
- {
- x_offset_in_pixels = es->x_offset;
- }
- else
- {
- dy = 0;
- x_offset_in_pixels = (short)LOWORD(EDIT_EM_PosFromChar(es, es->x_offset, FALSE));
- }
-
- if (-dx > x_offset_in_pixels)
- dx = -x_offset_in_pixels;
- if (dx > es->text_width - x_offset_in_pixels)
- dx = es->text_width - x_offset_in_pixels;
- nyoff = max(0, es->y_offset + dy);
- if (nyoff >= es->line_count - lines_per_page)
- nyoff = max(0, es->line_count - lines_per_page);
- dy = (es->y_offset - nyoff) * es->line_height;
- if (dx || dy) {
- RECT rc1;
- RECT rc;
-
- es->y_offset = nyoff;
- if(es->style & ES_MULTILINE)
- es->x_offset += dx;
- else
- es->x_offset += dx / es->char_width;
-
- GetClientRect(es->hwndSelf, &rc1);
- IntersectRect(&rc, &rc1, &es->format_rect);
- ScrollWindowEx(es->hwndSelf, -dx, dy,
- NULL, &rc, NULL, NULL, SW_INVALIDATE);
- /* force scroll info update */
- EDIT_UpdateScrollInfo(es);
- }
- if (dx && !(es->flags & EF_HSCROLL_TRACK))
- EDIT_NOTIFY_PARENT(es, EN_HSCROLL);
- if (dy && !(es->flags & EF_VSCROLL_TRACK))
- EDIT_NOTIFY_PARENT(es, EN_VSCROLL);
- return TRUE;
-}
-
-
-/*********************************************************************
- *
- * EM_POSFROMCHAR
- *
- */
-static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
-{
- INT len = get_text_length(es);
- INT l;
- INT li;
- INT x;
- INT y = 0;
- INT w;
- INT lw = 0;
- INT ll = 0;
- HDC dc;
- HFONT old_font = 0;
- SIZE size;
- LINEDEF *line_def;
-
- index = min(index, len);
- dc = GetDC(es->hwndSelf);
- if (es->font)
- old_font = SelectObject(dc, es->font);
- if (es->style & ES_MULTILINE) {
- l = EDIT_EM_LineFromChar(es, index);
- y = (l - es->y_offset) * es->line_height;
- li = EDIT_EM_LineIndex(es, l);
- if (after_wrap && (li == index) && l) {
- INT l2 = l - 1;
- line_def = es->first_line_def;
- while (l2) {
- line_def = line_def->next;
- l2--;
- }
- if (line_def->ending == END_WRAP) {
- l--;
- y -= es->line_height;
- li = EDIT_EM_LineIndex(es, l);
- }
- }
-
- line_def = es->first_line_def;
- while (line_def->index != li)
- line_def = line_def->next;
-
- ll = line_def->net_length;
- lw = line_def->width;
-
- w = es->format_rect.right - es->format_rect.left;
- if (es->style & ES_RIGHT)
- {
- x = LOWORD(GetTabbedTextExtentW(dc, es->text + li + (index - li), ll - (index - li),
- es->tabs_count, es->tabs)) - es->x_offset;
- x = w - x;
- }
- else if (es->style & ES_CENTER)
- {
- x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
- es->tabs_count, es->tabs)) - es->x_offset;
- x += (w - lw) / 2;
- }
- else /* ES_LEFT */
- {
- x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
- es->tabs_count, es->tabs)) - es->x_offset;
- }
- } else {
- LPWSTR text = EDIT_GetPasswordPointer_SL(es);
- if (index < es->x_offset) {
- GetTextExtentPoint32W(dc, text + index,
- es->x_offset - index, &size);
- x = -size.cx;
- } else {
- GetTextExtentPoint32W(dc, text + es->x_offset,
- index - es->x_offset, &size);
- x = size.cx;
-
- if (!es->x_offset && (es->style & (ES_RIGHT | ES_CENTER)))
- {
- w = es->format_rect.right - es->format_rect.left;
- if (w > es->text_width)
- {
- if (es->style & ES_RIGHT)
- x += w - es->text_width;
- else if (es->style & ES_CENTER)
- x += (w - es->text_width) / 2;
- }
- }
- }
- y = 0;
- if (es->style & ES_PASSWORD)
- HeapFree(GetProcessHeap(), 0, text);
- }
- x += es->format_rect.left;
- y += es->format_rect.top;
- if (es->font)
- SelectObject(dc, old_font);
- ReleaseDC(es->hwndSelf, dc);
- return MAKELONG((INT16)x, (INT16)y);
-}
-
-
-/*********************************************************************
- *
* EM_REPLACESEL
*
* FIXME: handle ES_NUMBER and ES_OEMCONVERT here
@@ -3363,124 +2752,6 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
/*********************************************************************
*
- * EM_SCROLL
- *
- */
-static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action)
-{
- INT dy;
-
- if (!(es->style & ES_MULTILINE))
- return (LRESULT)FALSE;
-
- dy = 0;
-
- switch (action) {
- case SB_LINEUP:
- if (es->y_offset)
- dy = -1;
- break;
- case SB_LINEDOWN:
- if (es->y_offset < es->line_count - 1)
- dy = 1;
- break;
- case SB_PAGEUP:
- if (es->y_offset)
- dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
- break;
- case SB_PAGEDOWN:
- if (es->y_offset < es->line_count - 1)
- dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
- break;
- default:
- return (LRESULT)FALSE;
- }
- if (dy) {
- 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;
-
- /* Notification is done in EDIT_EM_LineScroll */
- if(dy)
- EDIT_EM_LineScroll(es, 0, dy);
- }
- return MAKELONG((INT16)dy, (BOOL16)TRUE);
-}
-
-
-/*********************************************************************
- *
- * EM_SCROLLCARET
- *
- */
-static void EDIT_EM_ScrollCaret(EDITSTATE *es)
-{
- if (es->style & ES_MULTILINE) {
- INT l;
- INT vlc;
- INT ww;
- INT cw = es->char_width;
- INT x;
- INT dy = 0;
- INT dx = 0;
-
- l = EDIT_EM_LineFromChar(es, es->selection_end);
- x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP));
- vlc = get_vertical_line_count(es);
- if (l >= es->y_offset + vlc)
- dy = l - vlc + 1 - es->y_offset;
- if (l < es->y_offset)
- dy = l - es->y_offset;
- ww = es->format_rect.right - es->format_rect.left;
- if (x < es->format_rect.left)
- dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
- if (x > es->format_rect.right)
- dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
- if (dy || dx || (es->y_offset && (es->line_count - es->y_offset < vlc)))
- {
- /* check if we are going to move too far */
- if(es->x_offset + dx + ww > es->text_width)
- dx = es->text_width - ww - es->x_offset;
- if(dx || dy || (es->y_offset && (es->line_count - es->y_offset < vlc)))
- EDIT_EM_LineScroll_internal(es, dx, dy);
- }
- } else {
- INT x;
- INT goal;
- INT format_width;
-
- x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
- format_width = es->format_rect.right - es->format_rect.left;
- if (x < es->format_rect.left) {
- goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
- do {
- es->x_offset--;
- x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
- } while ((x < goal) && es->x_offset);
- /* FIXME: use ScrollWindow() somehow to improve performance */
- EDIT_UpdateText(es, NULL, TRUE);
- } else if (x > es->format_rect.right) {
- INT x_last;
- INT len = get_text_length(es);
- goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
- do {
- es->x_offset++;
- x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
- x_last = (short)LOWORD(EDIT_EM_PosFromChar(es, len, FALSE));
- } while ((x > goal) && (x_last > es->format_rect.right));
- /* FIXME: use ScrollWindow() somehow to improve performance */
- EDIT_UpdateText(es, NULL, TRUE);
- }
- }
-
- if(es->flags & EF_FOCUSED)
- EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
-}
-
-
-/*********************************************************************
- *
* EM_SETHANDLE
*
* FIXME: ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
@@ -3765,76 +3036,6 @@ static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c)
/*********************************************************************
*
- * EDIT_EM_SetSel
- *
- * note: unlike the specs say: the order of start and end
- * _is_ preserved in Windows. (i.e. start can be > end)
- * In other words: this handler is OK
- *
- */
-static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
-{
- UINT old_start = es->selection_start;
- UINT old_end = es->selection_end;
- UINT len = get_text_length(es);
-
- if (start == (UINT)-1) {
- start = es->selection_end;
- end = es->selection_end;
- } else {
- start = min(start, len);
- end = min(end, len);
- }
- es->selection_start = start;
- es->selection_end = end;
- if (after_wrap)
- es->flags |= EF_AFTER_WRAP;
- else
- es->flags &= ~EF_AFTER_WRAP;
- /* Compute the necessary invalidation region. */
- /* Note that we don't need to invalidate regions which have
- * "never" been selected, or those which are "still" selected.
- * In fact, every time we hit a selection boundary, we can
- * *toggle* whether we need to invalidate. Thus we can optimize by
- * *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) 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);
- ORDER_UINT(old_start, old_end);
- ORDER_UINT(start, end);
- /* Note that at this point 'end' and 'old_start' are not in order, but
- * start is definitely the min. and old_end is definitely the max. */
- if (end != old_start)
- {
-/*
- * One can also do
- * ORDER_UINT32(end, old_start);
- * EDIT_InvalidateText(es, start, end);
- * EDIT_InvalidateText(es, old_start, old_end);
- * in place of the following if statement.
- * (That would complete the optimal five-comparison four-element sort.)
- */
- if (old_start > end )
- {
- EDIT_InvalidateText(es, start, end);
- EDIT_InvalidateText(es, old_start, old_end);
- }
- else
- {
- EDIT_InvalidateText(es, start, old_start);
- EDIT_InvalidateText(es, end, old_end);
- }
- }
- else EDIT_InvalidateText(es, start, old_end);
-}
-
-
-/*********************************************************************
- *
* EM_SETTABSTOPS
*
*/
@@ -3983,6 +3184,93 @@ static BOOL EDIT_IsInsideDialog(EDITSTATE *es)
/*********************************************************************
*
+ * WM_PASTE
+ *
+ */
+static void EDIT_WM_Paste(EDITSTATE *es)
+{
+ HGLOBAL hsrc;
+ LPWSTR src;
+
+ /* Protect read-only edit control from modification */
+ if(es->style & ES_READONLY)
+ return;
+
+ OpenClipboard(es->hwndSelf);
+ if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
+ 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);
+ }
+ CloseClipboard();
+}
+
+
+/*********************************************************************
+ *
+ * WM_COPY
+ *
+ */
+static void EDIT_WM_Copy(EDITSTATE *es)
+{
+ INT s = min(es->selection_start, es->selection_end);
+ INT e = max(es->selection_start, es->selection_end);
+ HGLOBAL hdst;
+ LPWSTR dst;
+ DWORD len;
+
+ if (e == s) return;
+
+ len = e - s;
+ hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (len + 1) * sizeof(WCHAR));
+ dst = GlobalLock(hdst);
+ memcpy(dst, es->text + s, len * sizeof(WCHAR));
+ dst[len] = 0; /* ensure 0 termination */
+ TRACE("%s\n", debugstr_w(dst));
+ GlobalUnlock(hdst);
+ OpenClipboard(es->hwndSelf);
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, hdst);
+ CloseClipboard();
+}
+
+
+/*********************************************************************
+ *
+ * WM_CLEAR
+ *
+ */
+static inline void EDIT_WM_Clear(EDITSTATE *es)
+{
+ static const WCHAR empty_stringW[] = {0};
+
+ /* Protect read-only edit control from modification */
+ if(es->style & ES_READONLY)
+ return;
+
+ EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE);
+}
+
+
+/*********************************************************************
+ *
+ * WM_CUT
+ *
+ */
+static inline void EDIT_WM_Cut(EDITSTATE *es)
+{
+ EDIT_WM_Copy(es);
+ EDIT_WM_Clear(es);
+}
+
+
+/*********************************************************************
+ *
* WM_CHAR
*
*/
@@ -4159,125 +3447,6 @@ static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
/*********************************************************************
*
- * WM_COPY
- *
- */
-static void EDIT_WM_Copy(EDITSTATE *es)
-{
- INT s = min(es->selection_start, es->selection_end);
- INT e = max(es->selection_start, es->selection_end);
- HGLOBAL hdst;
- LPWSTR dst;
- DWORD len;
-
- if (e == s) return;
-
- len = e - s;
- hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (len + 1) * sizeof(WCHAR));
- dst = GlobalLock(hdst);
- memcpy(dst, es->text + s, len * sizeof(WCHAR));
- dst[len] = 0; /* ensure 0 termination */
- TRACE("%s\n", debugstr_w(dst));
- GlobalUnlock(hdst);
- OpenClipboard(es->hwndSelf);
- EmptyClipboard();
- SetClipboardData(CF_UNICODETEXT, hdst);
- CloseClipboard();
-}
-
-
-/*********************************************************************
- *
- * WM_CREATE
- *
- */
-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
- * functions. However, since the EDITSTATE is not consistent (i.e.
- * not fully initialized), we should be very careful which
- * functions can be called, and in what order.
- */
- 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);
- EDIT_SetRectNP(es, &clientRect);
-
- if (name && *name) {
- EDIT_EM_ReplaceSel(es, FALSE, name, FALSE, FALSE);
- /* if we insert text to the editline, the text scrolls out
- * of the window, as the caret is placed after the insert
- * pos normally; thus we reset es->selection... to 0 and
- * update caret
- */
- es->selection_start = es->selection_end = 0;
- /* Adobe Photoshop does NOT like this. and MSDN says that EN_CHANGE
- * Messages are only to be sent when the USER does something to
- * change the contents. So I am removing this EN_CHANGE
- *
- * EDIT_NOTIFY_PARENT(es, EN_CHANGE);
- */
- EDIT_EM_ScrollCaret(es);
- }
- /* force scroll info update */
- EDIT_UpdateScrollInfo(es);
- /* The rule seems to return 1 here for success */
- /* Power Builder masked edit controls will crash */
- /* if not. */
- /* FIXME: is that in all cases so ? */
- return 1;
-}
-
-
-/*********************************************************************
- *
- * WM_DESTROY
- *
- */
-static LRESULT EDIT_WM_Destroy(EDITSTATE *es)
-{
- LINEDEF *pc, *pp;
-
- if (es->hloc32W) {
- LocalFree(es->hloc32W);
- }
- if (es->hloc32A) {
- LocalFree(es->hloc32A);
- }
- if (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;
- }
-
- pc = es->first_line_def;
- while (pc)
- {
- pp = pc->next;
- HeapFree(GetProcessHeap(), 0, pc);
- pc = pp;
- }
-
- SetWindowLongPtrW( es->hwndSelf, 0, 0 );
- HeapFree(GetProcessHeap(), 0, es);
-
- return 0;
-}
-
-
-/*********************************************************************
- *
* WM_GETTEXT
*
*/
@@ -4301,139 +3470,6 @@ static INT EDIT_WM_GetText(const EDITSTATE *es, INT count, LPWSTR dst, BOOL unic
/*********************************************************************
*
- * WM_HSCROLL
- *
- */
-static LRESULT EDIT_WM_HScroll(EDITSTATE *es, INT action, INT pos)
-{
- INT dx;
- INT fw;
-
- if (!(es->style & ES_MULTILINE))
- return 0;
-
- if (!(es->style & ES_AUTOHSCROLL))
- return 0;
-
- dx = 0;
- fw = es->format_rect.right - es->format_rect.left;
- switch (action) {
- case SB_LINELEFT:
- TRACE("SB_LINELEFT\n");
- if (es->x_offset)
- dx = -es->char_width;
- break;
- case SB_LINERIGHT:
- TRACE("SB_LINERIGHT\n");
- if (es->x_offset < es->text_width)
- dx = es->char_width;
- break;
- case SB_PAGELEFT:
- TRACE("SB_PAGELEFT\n");
- if (es->x_offset)
- dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
- break;
- case SB_PAGERIGHT:
- TRACE("SB_PAGERIGHT\n");
- if (es->x_offset < es->text_width)
- dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
- break;
- case SB_LEFT:
- TRACE("SB_LEFT\n");
- if (es->x_offset)
- dx = -es->x_offset;
- break;
- case SB_RIGHT:
- TRACE("SB_RIGHT\n");
- if (es->x_offset < es->text_width)
- dx = es->text_width - es->x_offset;
- break;
- case SB_THUMBTRACK:
- TRACE("SB_THUMBTRACK %d\n", pos);
- es->flags |= EF_HSCROLL_TRACK;
- if(es->style & WS_HSCROLL)
- dx = pos - es->x_offset;
- else
- {
- INT fw, new_x;
- /* Sanity check */
- if(pos < 0 || pos > 100) return 0;
- /* Assume default scroll range 0-100 */
- fw = es->format_rect.right - es->format_rect.left;
- new_x = pos * (es->text_width - fw) / 100;
- dx = es->text_width ? (new_x - es->x_offset) : 0;
- }
- break;
- case SB_THUMBPOSITION:
- TRACE("SB_THUMBPOSITION %d\n", pos);
- es->flags &= ~EF_HSCROLL_TRACK;
- if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
- dx = pos - es->x_offset;
- else
- {
- INT fw, new_x;
- /* Sanity check */
- if(pos < 0 || pos > 100) return 0;
- /* Assume default scroll range 0-100 */
- fw = es->format_rect.right - es->format_rect.left;
- new_x = pos * (es->text_width - fw) / 100;
- dx = es->text_width ? (new_x - es->x_offset) : 0;
- }
- if (!dx) {
- /* force scroll info update */
- EDIT_UpdateScrollInfo(es);
- EDIT_NOTIFY_PARENT(es, EN_HSCROLL);
- }
- break;
- case SB_ENDSCROLL:
- TRACE("SB_ENDSCROLL\n");
- break;
- /*
- * FIXME : the next two are undocumented !
- * Are we doing the right thing ?
- * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
- * although it's also a regular control message.
- */
- case EM_GETTHUMB: /* this one is used by NT notepad */
- case EM_GETTHUMB16:
- {
- LRESULT ret;
- if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
- ret = GetScrollPos(es->hwndSelf, SB_HORZ);
- else
- {
- /* Assume default scroll range 0-100 */
- INT fw = es->format_rect.right - es->format_rect.left;
- ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0;
- }
- TRACE("EM_GETTHUMB: returning %ld\n", ret);
- return ret;
- }
- case EM_LINESCROLL16:
- TRACE("EM_LINESCROLL16\n");
- dx = pos;
- break;
-
- default:
- ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n",
- action, action);
- return 0;
- }
- if (dx)
- {
- INT fw = es->format_rect.right - es->format_rect.left;
- /* check if we are going to move too far */
- if(es->x_offset + dx + fw > es->text_width)
- dx = es->text_width - fw - es->x_offset;
- if(dx)
- EDIT_EM_LineScroll_internal(es, dx, 0);
- }
- return 0;
-}
-
-
-/*********************************************************************
- *
* EDIT_CheckCombo
*
*/
@@ -4758,111 +3794,6 @@ static LRESULT EDIT_WM_MouseMove(EDITSTATE *es, INT x, INT y)
/*********************************************************************
*
- * WM_NCCREATE
- *
- * See also EDIT_WM_StyleChanged
- */
-static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode)
-{
- EDITSTATE *es;
- UINT alloc_size;
-
- TRACE("Creating %s edit control, style = %08x\n",
- unicode ? "Unicode" : "ANSI", lpcs->style);
-
- if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
- return FALSE;
- SetWindowLongPtrW( hwnd, 0, (LONG_PTR)es );
-
- /*
- * Note: since the EDITSTATE has not been fully initialized yet,
- * we can't use any API calls that may send
- * WM_XXX messages before WM_NCCREATE is completed.
- */
-
- es->is_unicode = unicode;
- es->style = lpcs->style;
-
- es->bEnableState = !(es->style & WS_DISABLED);
-
- es->hwndSelf = hwnd;
- /* Save parent, which will be notified by EN_* messages */
- es->hwndParent = lpcs->hwndParent;
-
- 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.
- */
- if (es->style & ES_NUMBER) {
- ; /* do not override the ES_NUMBER */
- } else if (es->style & ES_LOWERCASE) {
- es->style &= ~ES_UPPERCASE;
- }
- if (es->style & ES_MULTILINE) {
- es->buffer_limit = BUFLIMIT_INITIAL;
- if (es->style & WS_VSCROLL)
- es->style |= ES_AUTOVSCROLL;
- if (es->style & WS_HSCROLL)
- es->style |= ES_AUTOHSCROLL;
- es->style &= ~ES_PASSWORD;
- if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
- /* Confirmed - RIGHT overrides CENTER */
- if (es->style & ES_RIGHT)
- es->style &= ~ES_CENTER;
- es->style &= ~WS_HSCROLL;
- es->style &= ~ES_AUTOHSCROLL;
- }
- } else {
- es->buffer_limit = BUFLIMIT_INITIAL;
- if ((es->style & ES_RIGHT) && (es->style & ES_CENTER))
- es->style &= ~ES_CENTER;
- es->style &= ~WS_HSCROLL;
- es->style &= ~WS_VSCROLL;
- if (es->style & ES_PASSWORD)
- es->password_char = '*';
- }
-
- alloc_size = ROUND_TO_GROW((es->buffer_size + 1) * sizeof(WCHAR));
- if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
- return FALSE;
- es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
-
- if (!(es->undo_text = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (es->buffer_size + 1) * sizeof(WCHAR))))
- return FALSE;
- es->undo_buffer_size = es->buffer_size;
-
- if (es->style & ES_MULTILINE)
- if (!(es->first_line_def = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
- return FALSE;
- es->line_count = 1;
-
- /*
- * In Win95 look and feel, the WS_BORDER style is replaced by the
- * WS_EX_CLIENTEDGE style for the edit control. This gives the edit
- * control a nonclient area so we don't need to draw the border.
- * 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
- * for edit controls created directly with style 0x50800000, exStyle 0
- * (which should have a single pixel border)
- */
- if (lpcs->dwExStyle & WS_EX_CLIENTEDGE)
- es->style &= ~WS_BORDER;
- else if (es->style & WS_BORDER)
- SetWindowLongW(hwnd, GWL_STYLE, es->style & ~WS_BORDER);
-
- return TRUE;
-}
-
-/*********************************************************************
- *
* WM_PAINT
*
*/
@@ -4953,35 +3884,6 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
/*********************************************************************
*
- * WM_PASTE
- *
- */
-static void EDIT_WM_Paste(EDITSTATE *es)
-{
- HGLOBAL hsrc;
- LPWSTR src;
-
- /* Protect read-only edit control from modification */
- if(es->style & ES_READONLY)
- return;
-
- OpenClipboard(es->hwndSelf);
- if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
- 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);
- }
- CloseClipboard();
-}
-
-
-/*********************************************************************
- *
* WM_SETFOCUS
*
*/
@@ -5233,6 +4135,139 @@ static void EDIT_WM_Timer(EDITSTATE *es)
/*********************************************************************
*
+ * WM_HSCROLL
+ *
+ */
+static LRESULT EDIT_WM_HScroll(EDITSTATE *es, INT action, INT pos)
+{
+ INT dx;
+ INT fw;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+
+ if (!(es->style & ES_AUTOHSCROLL))
+ return 0;
+
+ dx = 0;
+ fw = es->format_rect.right - es->format_rect.left;
+ switch (action) {
+ case SB_LINELEFT:
+ TRACE("SB_LINELEFT\n");
+ if (es->x_offset)
+ dx = -es->char_width;
+ break;
+ case SB_LINERIGHT:
+ TRACE("SB_LINERIGHT\n");
+ if (es->x_offset < es->text_width)
+ dx = es->char_width;
+ break;
+ case SB_PAGELEFT:
+ TRACE("SB_PAGELEFT\n");
+ if (es->x_offset)
+ dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
+ break;
+ case SB_PAGERIGHT:
+ TRACE("SB_PAGERIGHT\n");
+ if (es->x_offset < es->text_width)
+ dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
+ break;
+ case SB_LEFT:
+ TRACE("SB_LEFT\n");
+ if (es->x_offset)
+ dx = -es->x_offset;
+ break;
+ case SB_RIGHT:
+ TRACE("SB_RIGHT\n");
+ if (es->x_offset < es->text_width)
+ dx = es->text_width - es->x_offset;
+ break;
+ case SB_THUMBTRACK:
+ TRACE("SB_THUMBTRACK %d\n", pos);
+ es->flags |= EF_HSCROLL_TRACK;
+ if(es->style & WS_HSCROLL)
+ dx = pos - es->x_offset;
+ else
+ {
+ INT fw, new_x;
+ /* Sanity check */
+ if(pos < 0 || pos > 100) return 0;
+ /* Assume default scroll range 0-100 */
+ fw = es->format_rect.right - es->format_rect.left;
+ new_x = pos * (es->text_width - fw) / 100;
+ dx = es->text_width ? (new_x - es->x_offset) : 0;
+ }
+ break;
+ case SB_THUMBPOSITION:
+ TRACE("SB_THUMBPOSITION %d\n", pos);
+ es->flags &= ~EF_HSCROLL_TRACK;
+ if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
+ dx = pos - es->x_offset;
+ else
+ {
+ INT fw, new_x;
+ /* Sanity check */
+ if(pos < 0 || pos > 100) return 0;
+ /* Assume default scroll range 0-100 */
+ fw = es->format_rect.right - es->format_rect.left;
+ new_x = pos * (es->text_width - fw) / 100;
+ dx = es->text_width ? (new_x - es->x_offset) : 0;
+ }
+ if (!dx) {
+ /* force scroll info update */
+ EDIT_UpdateScrollInfo(es);
+ EDIT_NOTIFY_PARENT(es, EN_HSCROLL);
+ }
+ break;
+ case SB_ENDSCROLL:
+ TRACE("SB_ENDSCROLL\n");
+ break;
+ /*
+ * FIXME : the next two are undocumented !
+ * Are we doing the right thing ?
+ * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
+ * although it's also a regular control message.
+ */
+ case EM_GETTHUMB: /* this one is used by NT notepad */
+ case EM_GETTHUMB16:
+ {
+ LRESULT ret;
+ if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
+ ret = GetScrollPos(es->hwndSelf, SB_HORZ);
+ else
+ {
+ /* Assume default scroll range 0-100 */
+ INT fw = es->format_rect.right - es->format_rect.left;
+ ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0;
+ }
+ TRACE("EM_GETTHUMB: returning %ld\n", ret);
+ return ret;
+ }
+ case EM_LINESCROLL16:
+ TRACE("EM_LINESCROLL16\n");
+ dx = pos;
+ break;
+
+ default:
+ ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n",
+ action, action);
+ return 0;
+ }
+ if (dx)
+ {
+ INT fw = es->format_rect.right - es->format_rect.left;
+ /* check if we are going to move too far */
+ if(es->x_offset + dx + fw > es->text_width)
+ dx = es->text_width - fw - es->x_offset;
+ if(dx)
+ EDIT_EM_LineScroll_internal(es, dx, 0);
+ }
+ return 0;
+}
+
+
+/*********************************************************************
+ *
* WM_VSCROLL
*
*/
@@ -5349,33 +4384,21 @@ static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos)
/*********************************************************************
*
- * EDIT_UpdateText
- *
- */
-static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase)
-{
- if (es->flags & EF_UPDATE) {
- es->flags &= ~EF_UPDATE;
- EDIT_NOTIFY_PARENT(es, EN_UPDATE);
- }
- InvalidateRgn(es->hwndSelf, hrgn, bErase);
-}
-
-
-/*********************************************************************
+ * EM_GETTHUMB
*
- * EDIT_UpdateText
+ * FIXME: is this right ? (or should it be only VSCROLL)
+ * (and maybe only for edit controls that really have their
+ * own scrollbars) (and maybe only for multiline controls ?)
+ * All in all: very poorly documented
*
*/
-static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase)
+static LRESULT EDIT_EM_GetThumb(EDITSTATE *es)
{
- if (es->flags & EF_UPDATE) {
- es->flags &= ~EF_UPDATE;
- EDIT_NOTIFY_PARENT(es, EN_UPDATE);
- }
- InvalidateRect(es->hwndSelf, rc, bErase);
+ return MAKELONG(EDIT_WM_VScroll(es, EM_GETTHUMB16, 0),
+ EDIT_WM_HScroll(es, EM_GETTHUMB16, 0));
}
+
/********************************************************************
*
* The Following code is to handle inline editing from IMEs
@@ -5511,3 +4534,898 @@ static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es)
ImmReleaseContext(hwnd, hIMC);
EDIT_SetCaretPos(es, es->selection_start + cursor, es->flags & EF_AFTER_WRAP);
}
+
+
+/*********************************************************************
+ *
+ * WM_NCCREATE
+ *
+ * See also EDIT_WM_StyleChanged
+ */
+static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode)
+{
+ EDITSTATE *es;
+ UINT alloc_size;
+
+ TRACE("Creating %s edit control, style = %08x\n",
+ unicode ? "Unicode" : "ANSI", lpcs->style);
+
+ if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
+ return FALSE;
+ SetWindowLongPtrW( hwnd, 0, (LONG_PTR)es );
+
+ /*
+ * Note: since the EDITSTATE has not been fully initialized yet,
+ * we can't use any API calls that may send
+ * WM_XXX messages before WM_NCCREATE is completed.
+ */
+
+ es->is_unicode = unicode;
+ es->style = lpcs->style;
+
+ es->bEnableState = !(es->style & WS_DISABLED);
+
+ es->hwndSelf = hwnd;
+ /* Save parent, which will be notified by EN_* messages */
+ es->hwndParent = lpcs->hwndParent;
+
+ 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.
+ */
+ if (es->style & ES_NUMBER) {
+ ; /* do not override the ES_NUMBER */
+ } else if (es->style & ES_LOWERCASE) {
+ es->style &= ~ES_UPPERCASE;
+ }
+ if (es->style & ES_MULTILINE) {
+ es->buffer_limit = BUFLIMIT_INITIAL;
+ if (es->style & WS_VSCROLL)
+ es->style |= ES_AUTOVSCROLL;
+ if (es->style & WS_HSCROLL)
+ es->style |= ES_AUTOHSCROLL;
+ es->style &= ~ES_PASSWORD;
+ if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
+ /* Confirmed - RIGHT overrides CENTER */
+ if (es->style & ES_RIGHT)
+ es->style &= ~ES_CENTER;
+ es->style &= ~WS_HSCROLL;
+ es->style &= ~ES_AUTOHSCROLL;
+ }
+ } else {
+ es->buffer_limit = BUFLIMIT_INITIAL;
+ if ((es->style & ES_RIGHT) && (es->style & ES_CENTER))
+ es->style &= ~ES_CENTER;
+ es->style &= ~WS_HSCROLL;
+ es->style &= ~WS_VSCROLL;
+ if (es->style & ES_PASSWORD)
+ es->password_char = '*';
+ }
+
+ alloc_size = ROUND_TO_GROW((es->buffer_size + 1) * sizeof(WCHAR));
+ if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
+ return FALSE;
+ es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
+
+ if (!(es->undo_text = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (es->buffer_size + 1) * sizeof(WCHAR))))
+ return FALSE;
+ es->undo_buffer_size = es->buffer_size;
+
+ if (es->style & ES_MULTILINE)
+ if (!(es->first_line_def = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
+ return FALSE;
+ es->line_count = 1;
+
+ /*
+ * In Win95 look and feel, the WS_BORDER style is replaced by the
+ * WS_EX_CLIENTEDGE style for the edit control. This gives the edit
+ * control a nonclient area so we don't need to draw the border.
+ * 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
+ * for edit controls created directly with style 0x50800000, exStyle 0
+ * (which should have a single pixel border)
+ */
+ if (lpcs->dwExStyle & WS_EX_CLIENTEDGE)
+ es->style &= ~WS_BORDER;
+ else if (es->style & WS_BORDER)
+ SetWindowLongW(hwnd, GWL_STYLE, es->style & ~WS_BORDER);
+
+ return TRUE;
+}
+
+
+/*********************************************************************
+ *
+ * WM_CREATE
+ *
+ */
+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
+ * functions. However, since the EDITSTATE is not consistent (i.e.
+ * not fully initialized), we should be very careful which
+ * functions can be called, and in what order.
+ */
+ 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);
+ EDIT_SetRectNP(es, &clientRect);
+
+ if (name && *name) {
+ EDIT_EM_ReplaceSel(es, FALSE, name, FALSE, FALSE);
+ /* if we insert text to the editline, the text scrolls out
+ * of the window, as the caret is placed after the insert
+ * pos normally; thus we reset es->selection... to 0 and
+ * update caret
+ */
+ es->selection_start = es->selection_end = 0;
+ /* Adobe Photoshop does NOT like this. and MSDN says that EN_CHANGE
+ * Messages are only to be sent when the USER does something to
+ * change the contents. So I am removing this EN_CHANGE
+ *
+ * EDIT_NOTIFY_PARENT(es, EN_CHANGE);
+ */
+ EDIT_EM_ScrollCaret(es);
+ }
+ /* force scroll info update */
+ EDIT_UpdateScrollInfo(es);
+ /* The rule seems to return 1 here for success */
+ /* Power Builder masked edit controls will crash */
+ /* if not. */
+ /* FIXME: is that in all cases so ? */
+ return 1;
+}
+
+
+/*********************************************************************
+ *
+ * WM_DESTROY
+ *
+ */
+static LRESULT EDIT_WM_Destroy(EDITSTATE *es)
+{
+ LINEDEF *pc, *pp;
+
+ if (es->hloc32W) {
+ LocalFree(es->hloc32W);
+ }
+ if (es->hloc32A) {
+ LocalFree(es->hloc32A);
+ }
+ if (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;
+ }
+
+ pc = es->first_line_def;
+ while (pc)
+ {
+ pp = pc->next;
+ HeapFree(GetProcessHeap(), 0, pc);
+ pc = pp;
+ }
+
+ SetWindowLongPtrW( es->hwndSelf, 0, 0 );
+ HeapFree(GetProcessHeap(), 0, es);
+
+ return 0;
+}
+
+
+static inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode)
+{
+ if(unicode)
+ return DefWindowProcW(hwnd, msg, wParam, lParam);
+ else
+ return DefWindowProcA(hwnd, msg, wParam, lParam);
+}
+
+/*********************************************************************
+ *
+ * EditWndProc_common
+ *
+ * The messages are in the order of the actual integer values
+ * (which can be found in include/windows.h)
+ * Wherever possible the 16 bit versions are converted to
+ * the 32 bit ones, so that we can 'fall through' to the
+ * helper functions. These are mostly 32 bit (with a few
+ * exceptions, clearly indicated by a '16' extension to their
+ * names).
+ *
+ */
+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);
+
+ if (!es && msg != WM_NCCREATE)
+ return DefWindowProcT(hwnd, msg, wParam, lParam, unicode);
+
+ if (es && (msg != WM_DESTROY)) EDIT_LockBuffer(es);
+
+ switch (msg) {
+ case EM_GETSEL16:
+ wParam = 0;
+ lParam = 0;
+ /* fall through */
+ case EM_GETSEL:
+ result = EDIT_EM_GetSel(es, (PUINT)wParam, (PUINT)lParam);
+ break;
+
+ case EM_SETSEL16:
+ if ((short)LOWORD(lParam) == -1)
+ EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
+ else
+ EDIT_EM_SetSel(es, LOWORD(lParam), HIWORD(lParam), FALSE);
+ if (!wParam)
+ EDIT_EM_ScrollCaret(es);
+ result = 1;
+ break;
+ case EM_SETSEL:
+ EDIT_EM_SetSel(es, wParam, lParam, FALSE);
+ EDIT_EM_ScrollCaret(es);
+ result = 1;
+ break;
+
+ case EM_GETRECT16:
+ if (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;
+ case EM_GETRECT:
+ if (lParam)
+ CopyRect((LPRECT)lParam, &es->format_rect);
+ break;
+
+ case EM_SETRECT16:
+ if ((es->style & ES_MULTILINE) && lParam) {
+ RECT 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);
+ }
+ break;
+ case EM_SETRECT:
+ if ((es->style & ES_MULTILINE) && lParam) {
+ EDIT_SetRectNP(es, (LPRECT)lParam);
+ EDIT_UpdateText(es, NULL, TRUE);
+ }
+ break;
+
+ case EM_SETRECTNP16:
+ if ((es->style & ES_MULTILINE) && lParam) {
+ RECT 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;
+ case EM_SETRECTNP:
+ if ((es->style & ES_MULTILINE) && lParam)
+ EDIT_SetRectNP(es, (LPRECT)lParam);
+ break;
+
+ case EM_SCROLL16:
+ case EM_SCROLL:
+ result = EDIT_EM_Scroll(es, (INT)wParam);
+ break;
+
+ case EM_LINESCROLL16:
+ wParam = (WPARAM)(INT)(SHORT)HIWORD(lParam);
+ lParam = (LPARAM)(INT)(SHORT)LOWORD(lParam);
+ /* fall through */
+ case EM_LINESCROLL:
+ result = (LRESULT)EDIT_EM_LineScroll(es, (INT)wParam, (INT)lParam);
+ break;
+
+ case EM_SCROLLCARET16:
+ case EM_SCROLLCARET:
+ EDIT_EM_ScrollCaret(es);
+ result = 1;
+ break;
+
+ case EM_GETMODIFY16:
+ case EM_GETMODIFY:
+ result = ((es->flags & EF_MODIFIED) != 0);
+ break;
+
+ case EM_SETMODIFY16:
+ case EM_SETMODIFY:
+ if (wParam)
+ es->flags |= EF_MODIFIED;
+ else
+ es->flags &= ~(EF_MODIFIED | EF_UPDATE); /* reset pending updates */
+ break;
+
+ case EM_GETLINECOUNT16:
+ case EM_GETLINECOUNT:
+ result = (es->style & ES_MULTILINE) ? es->line_count : 1;
+ break;
+
+ case EM_LINEINDEX16:
+ if ((INT16)wParam == -1)
+ wParam = (WPARAM)-1;
+ /* fall through */
+ case EM_LINEINDEX:
+ result = (LRESULT)EDIT_EM_LineIndex(es, (INT)wParam);
+ break;
+
+ case EM_SETHANDLE16:
+ EDIT_EM_SetHandle16(es, (HLOCAL16)wParam);
+ break;
+ case EM_SETHANDLE:
+ EDIT_EM_SetHandle(es, (HLOCAL)wParam);
+ break;
+
+ case EM_GETHANDLE16:
+ result = (LRESULT)EDIT_EM_GetHandle16(es);
+ break;
+ case EM_GETHANDLE:
+ result = (LRESULT)EDIT_EM_GetHandle(es);
+ break;
+
+ case EM_GETTHUMB16:
+ case EM_GETTHUMB:
+ result = EDIT_EM_GetThumb(es);
+ break;
+
+ /* these messages missing from specs */
+ case WM_USER+15:
+ case 0x00bf:
+ case WM_USER+16:
+ case 0x00c0:
+ case WM_USER+19:
+ case 0x00c3:
+ case WM_USER+26:
+ case 0x00ca:
+ FIXME("undocumented message 0x%x, please report\n", msg);
+ result = DefWindowProcW(hwnd, msg, wParam, lParam);
+ break;
+
+ case EM_LINELENGTH16:
+ case EM_LINELENGTH:
+ result = (LRESULT)EDIT_EM_LineLength(es, (INT)wParam);
+ break;
+
+ case EM_REPLACESEL16:
+ lParam = (LPARAM)MapSL(lParam);
+ unicode = FALSE; /* 16-bit message is always ascii */
+ /* fall through */
+ case EM_REPLACESEL:
+ {
+ LPWSTR textW;
+
+ if(unicode)
+ textW = (LPWSTR)lParam;
+ else
+ {
+ 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);
+ }
+
+ EDIT_EM_ReplaceSel(es, (BOOL)wParam, textW, TRUE, TRUE);
+ result = 1;
+
+ if(!unicode)
+ HeapFree(GetProcessHeap(), 0, textW);
+ break;
+ }
+
+ case EM_GETLINE16:
+ lParam = (LPARAM)MapSL(lParam);
+ unicode = FALSE; /* 16-bit message is always ascii */
+ /* fall through */
+ case EM_GETLINE:
+ result = (LRESULT)EDIT_EM_GetLine(es, (INT)wParam, (LPWSTR)lParam, unicode);
+ break;
+
+ case EM_LIMITTEXT16:
+ case EM_SETLIMITTEXT:
+ EDIT_EM_SetLimitText(es, wParam);
+ break;
+
+ case EM_CANUNDO16:
+ case EM_CANUNDO:
+ result = (LRESULT)EDIT_EM_CanUndo(es);
+ break;
+
+ case EM_UNDO16:
+ case EM_UNDO:
+ case WM_UNDO:
+ result = (LRESULT)EDIT_EM_Undo(es);
+ break;
+
+ case EM_FMTLINES16:
+ case EM_FMTLINES:
+ result = (LRESULT)EDIT_EM_FmtLines(es, (BOOL)wParam);
+ break;
+
+ case EM_LINEFROMCHAR16:
+ case EM_LINEFROMCHAR:
+ result = (LRESULT)EDIT_EM_LineFromChar(es, (INT)wParam);
+ break;
+
+ case EM_SETTABSTOPS16:
+ result = (LRESULT)EDIT_EM_SetTabStops16(es, (INT)wParam, MapSL(lParam));
+ break;
+ case EM_SETTABSTOPS:
+ result = (LRESULT)EDIT_EM_SetTabStops(es, (INT)wParam, (LPINT)lParam);
+ break;
+
+ case EM_SETPASSWORDCHAR16:
+ unicode = FALSE; /* 16-bit message is always ascii */
+ /* fall through */
+ case EM_SETPASSWORDCHAR:
+ {
+ WCHAR charW = 0;
+
+ if(unicode)
+ charW = (WCHAR)wParam;
+ else
+ {
+ CHAR charA = wParam;
+ MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
+ }
+
+ EDIT_EM_SetPasswordChar(es, charW);
+ break;
+ }
+
+ case EM_EMPTYUNDOBUFFER16:
+ case EM_EMPTYUNDOBUFFER:
+ EDIT_EM_EmptyUndoBuffer(es);
+ break;
+
+ case EM_GETFIRSTVISIBLELINE16:
+ result = es->y_offset;
+ break;
+ case EM_GETFIRSTVISIBLELINE:
+ result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
+ break;
+
+ case EM_SETREADONLY16:
+ case EM_SETREADONLY:
+ if (wParam) {
+ SetWindowLongW( hwnd, GWL_STYLE,
+ GetWindowLongW( hwnd, GWL_STYLE ) | ES_READONLY );
+ es->style |= ES_READONLY;
+ } else {
+ SetWindowLongW( hwnd, GWL_STYLE,
+ GetWindowLongW( hwnd, GWL_STYLE ) & ~ES_READONLY );
+ es->style &= ~ES_READONLY;
+ }
+ result = 1;
+ break;
+
+ case EM_SETWORDBREAKPROC16:
+ EDIT_EM_SetWordBreakProc16(es, (EDITWORDBREAKPROC16)lParam);
+ break;
+ case EM_SETWORDBREAKPROC:
+ EDIT_EM_SetWordBreakProc(es, (void *)lParam);
+ break;
+
+ case EM_GETWORDBREAKPROC16:
+ result = (LRESULT)es->word_break_proc16;
+ break;
+ case EM_GETWORDBREAKPROC:
+ result = (LRESULT)es->word_break_proc;
+ break;
+
+ case EM_GETPASSWORDCHAR16:
+ unicode = FALSE; /* 16-bit message is always ascii */
+ /* fall through */
+ case EM_GETPASSWORDCHAR:
+ {
+ if(unicode)
+ result = es->password_char;
+ else
+ {
+ WCHAR charW = es->password_char;
+ CHAR charA = 0;
+ WideCharToMultiByte(CP_ACP, 0, &charW, 1, &charA, 1, NULL, NULL);
+ result = charA;
+ }
+ break;
+ }
+
+ /* The following EM_xxx are new to win95 and don't exist for 16 bit */
+
+ case EM_SETMARGINS:
+ EDIT_EM_SetMargins(es, (INT)wParam, LOWORD(lParam), HIWORD(lParam), TRUE);
+ break;
+
+ case EM_GETMARGINS:
+ result = MAKELONG(es->left_margin, es->right_margin);
+ break;
+
+ case EM_GETLIMITTEXT:
+ result = es->buffer_limit;
+ break;
+
+ case EM_POSFROMCHAR:
+ if ((INT)wParam >= get_text_length(es)) result = -1;
+ else result = EDIT_EM_PosFromChar(es, (INT)wParam, FALSE);
+ break;
+
+ case EM_CHARFROMPOS:
+ result = EDIT_EM_CharFromPos(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
+ break;
+
+ /* End of the EM_ messages which were in numerical order; what order
+ * are these in? vaguely alphabetical?
+ */
+
+ case WM_NCCREATE:
+ result = EDIT_WM_NCCreate(hwnd, (LPCREATESTRUCTW)lParam, unicode);
+ break;
+
+ case WM_DESTROY:
+ result = EDIT_WM_Destroy(es);
+ es = NULL;
+ break;
+
+ case WM_GETDLGCODE:
+ result = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
+
+ if (es->style & ES_MULTILINE)
+ result |= DLGC_WANTALLKEYS;
+
+ if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
+ {
+ int vk = (int)((LPMSG)lParam)->wParam;
+
+ 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];
+
+ 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;
+
+ if(unicode)
+ charW = wParam;
+ else
+ {
+ CHAR charA = wParam;
+ MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
+ }
+
+ 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;
+
+ case WM_COMMAND:
+ EDIT_WM_Command(es, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
+ break;
+
+ case WM_CONTEXTMENU:
+ EDIT_WM_ContextMenu(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
+ break;
+
+ case WM_COPY:
+ EDIT_WM_Copy(es);
+ break;
+
+ case WM_CREATE:
+ if(unicode)
+ result = EDIT_WM_Create(es, ((LPCREATESTRUCTW)lParam)->lpszName);
+ else
+ {
+ LPCSTR nameA = ((LPCREATESTRUCTA)lParam)->lpszName;
+ 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);
+ }
+ result = EDIT_WM_Create(es, nameW);
+ HeapFree(GetProcessHeap(), 0, nameW);
+ }
+ break;
+
+ case WM_CUT:
+ EDIT_WM_Cut(es);
+ break;
+
+ case WM_ENABLE:
+ es->bEnableState = (BOOL) wParam;
+ EDIT_UpdateText(es, NULL, TRUE);
+ break;
+
+ case WM_ERASEBKGND:
+ /* we do the proper erase in EDIT_WM_Paint */
+ result = 1;
+ break;
+
+ case WM_GETFONT:
+ result = (LRESULT)es->font;
+ break;
+
+ case WM_GETTEXT:
+ result = (LRESULT)EDIT_WM_GetText(es, (INT)wParam, (LPWSTR)lParam, unicode);
+ break;
+
+ case WM_GETTEXTLENGTH:
+ if (unicode) result = get_text_length(es);
+ else result = WideCharToMultiByte( CP_ACP, 0, es->text, get_text_length(es),
+ NULL, 0, NULL, NULL );
+ break;
+
+ case WM_HSCROLL:
+ result = EDIT_WM_HScroll(es, LOWORD(wParam), (short)HIWORD(wParam));
+ break;
+
+ case WM_KEYDOWN:
+ result = EDIT_WM_KeyDown(es, (INT)wParam);
+ break;
+
+ case WM_KILLFOCUS:
+ result = EDIT_WM_KillFocus(es);
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ result = EDIT_WM_LButtonDblClk(es);
+ break;
+
+ case WM_LBUTTONDOWN:
+ result = EDIT_WM_LButtonDown(es, wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
+ break;
+
+ case WM_LBUTTONUP:
+ result = EDIT_WM_LButtonUp(es);
+ break;
+
+ case WM_MBUTTONDOWN:
+ result = EDIT_WM_MButtonDown(es);
+ break;
+
+ case WM_MOUSEMOVE:
+ result = EDIT_WM_MouseMove(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
+ break;
+
+ case WM_PRINTCLIENT:
+ case WM_PAINT:
+ EDIT_WM_Paint(es, (HDC)wParam);
+ break;
+
+ case WM_PASTE:
+ EDIT_WM_Paste(es);
+ break;
+
+ case WM_SETFOCUS:
+ EDIT_WM_SetFocus(es);
+ break;
+
+ case WM_SETFONT:
+ EDIT_WM_SetFont(es, (HFONT)wParam, LOWORD(lParam) != 0);
+ break;
+
+ case WM_SETREDRAW:
+ /* FIXME: actually set an internal flag and behave accordingly */
+ break;
+
+ case WM_SETTEXT:
+ EDIT_WM_SetText(es, (LPCWSTR)lParam, unicode);
+ result = TRUE;
+ break;
+
+ case WM_SIZE:
+ EDIT_WM_Size(es, (UINT)wParam, LOWORD(lParam), HIWORD(lParam));
+ break;
+
+ case WM_STYLECHANGED:
+ result = EDIT_WM_StyleChanged(es, wParam, (const STYLESTRUCT *)lParam);
+ break;
+
+ case WM_STYLECHANGING:
+ result = 0; /* See EDIT_WM_StyleChanged */
+ break;
+
+ case WM_SYSKEYDOWN:
+ result = EDIT_WM_SysKeyDown(es, (INT)wParam, (DWORD)lParam);
+ break;
+
+ case WM_TIMER:
+ EDIT_WM_Timer(es);
+ break;
+
+ case WM_VSCROLL:
+ result = EDIT_WM_VScroll(es, LOWORD(wParam), (short)HIWORD(wParam));
+ break;
+
+ case WM_MOUSEWHEEL:
+ {
+ int gcWheelDelta = 0;
+ UINT pulScrollLines = 3;
+ SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
+
+ if (wParam & (MK_SHIFT | MK_CONTROL)) {
+ result = DefWindowProcW(hwnd, msg, wParam, lParam);
+ break;
+ }
+ gcWheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
+ if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
+ {
+ int cLineScroll= (int) min((UINT) es->line_count, pulScrollLines);
+ cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
+ result = EDIT_EM_LineScroll(es, 0, cLineScroll);
+ }
+ }
+ break;
+
+
+ /* IME messages to make the edit control IME aware */
+ case WM_IME_SETCONTEXT:
+ break;
+
+ case WM_IME_STARTCOMPOSITION:
+ es->composition_start = es->selection_end;
+ es->composition_len = 0;
+ break;
+
+ case WM_IME_COMPOSITION:
+ EDIT_ImeComposition(hwnd, lParam, es);
+ break;
+
+ case WM_IME_ENDCOMPOSITION:
+ 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:
+ break;
+
+ case WM_IME_SELECT:
+ break;
+
+ 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);
+
+ return result;
+}
+
+/*********************************************************************
+ *
+ * EditWndProc (USER32.@)
+ */
+LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return EditWndProc_common(hWnd, uMsg, wParam, lParam, FALSE);
+}
+
+/*********************************************************************
+ *
+ * EditWndProcW (USER32.@)
+ */
+LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return EditWndProc_common(hWnd, uMsg, wParam, lParam, TRUE);
+}
+
+/*********************************************************************
+ * edit class descriptor
+ */
+static const WCHAR editW[] = {'E','d','i','t',0};
+const struct builtin_class_descr EDIT_builtin_class =
+{
+ editW, /* name */
+ CS_DBLCLKS | CS_PARENTDC, /* style */
+ EditWndProcA, /* procA */
+ EditWndProcW, /* procW */
+ sizeof(EDITSTATE *), /* extra */
+ IDC_IBEAM, /* cursor */
+ 0 /* brush */
+};
--
1.5.6.5
More information about the wine-patches
mailing list