mirror of
https://github.com/reactos/reactos.git
synced 2025-07-28 17:11:57 +00:00
- Sync edit control with Wine code
- Add imm32 dependency to user32, which is needed for edit control. This may not be a good solution, since Windows XP's user32.dll doesn't import imm32.dll. So maybe in future this should change to dynamic binding instead. But for now it works - Update Wine-sync doc This update reduces number of failing "user32_winetest.exe edit" tests from 44 to 43. svn path=/trunk/; revision=22631
This commit is contained in:
parent
16240136f4
commit
7f0a19c743
3 changed files with 225 additions and 30 deletions
|
@ -141,6 +141,11 @@ typedef struct
|
|||
#endif
|
||||
HLOCAL hloc32A; /* alias for ANSI control receiving EM_GETHANDLE
|
||||
or EM_SETHANDLE */
|
||||
/*
|
||||
* IME Data
|
||||
*/
|
||||
UINT composition_len; /* length of composition, 0 == no composition */
|
||||
int composition_start; /* the character position for the composition */
|
||||
} EDITSTATE;
|
||||
|
||||
|
||||
|
@ -203,6 +208,7 @@ static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend);
|
|||
static void EDIT_PaintLine(EDITSTATE *es, HDC hdc, INT line, BOOL rev);
|
||||
static INT EDIT_PaintText(EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
|
||||
static void EDIT_SetCaretPos(EDITSTATE *es, INT pos, BOOL after_wrap);
|
||||
static void EDIT_AdjustFormatRect(EDITSTATE *es);
|
||||
static void EDIT_SetRectNP(EDITSTATE *es, LPRECT lprc);
|
||||
static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force);
|
||||
static void EDIT_UpdateScrollInfo(EDITSTATE *es);
|
||||
|
@ -277,6 +283,7 @@ static void EDIT_WM_Timer(EDITSTATE *es);
|
|||
static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos);
|
||||
static void EDIT_UpdateText(EDITSTATE *es, LPRECT rc, BOOL bErase);
|
||||
static void EDIT_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);
|
||||
|
@ -1048,6 +1055,52 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg,
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* IME messages to make the edit control IME aware */
|
||||
case WM_IME_SETCONTEXT:
|
||||
break;
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
/*
|
||||
* FIXME in IME: This message is not always sent like it should be
|
||||
*/
|
||||
if (es->selection_start != es->selection_end)
|
||||
{
|
||||
static const WCHAR empty_stringW[] = {0};
|
||||
EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE);
|
||||
}
|
||||
es->composition_start = es->selection_end;
|
||||
es->composition_len = 0;
|
||||
break;
|
||||
|
||||
case WM_IME_COMPOSITION:
|
||||
if (es->composition_len == 0)
|
||||
{
|
||||
if (es->selection_start != es->selection_end)
|
||||
{
|
||||
static const WCHAR empty_stringW[] = {0};
|
||||
EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE);
|
||||
}
|
||||
|
||||
es->composition_start = es->selection_end;
|
||||
}
|
||||
EDIT_ImeComposition(hwnd,lParam,es);
|
||||
break;
|
||||
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
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;
|
||||
|
@ -1055,6 +1108,8 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg,
|
|||
|
||||
if (es) EDIT_UnlockBuffer(es, FALSE);
|
||||
|
||||
//TRACE("hwnd=%p msg=%x (%s) -- 0x%08lx\n", hwnd, msg, SPY_GetMsgName(msg, hwnd), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1300,7 +1355,7 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
|
|||
es->line_count--;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (delta != 0)
|
||||
{
|
||||
while (current_line)
|
||||
{
|
||||
|
@ -1401,17 +1456,9 @@ static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
|
|||
*/
|
||||
static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
INT ret;
|
||||
#else
|
||||
INT ret, iWndsLocks;
|
||||
#endif
|
||||
|
||||
/* To avoid any deadlocks, all the locks on the window structures
|
||||
must be suspended before the control is passed to the application */
|
||||
#ifndef __REACTOS__
|
||||
iWndsLocks = WIN_SuspendWndsLock();
|
||||
|
||||
if (es->word_break_proc16) {
|
||||
HGLOBAL16 hglob16;
|
||||
SEGPTR segptr;
|
||||
|
@ -1464,9 +1511,6 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
|
|||
else
|
||||
ret = EDIT_WordBreakProc(es->text + start, index, count, action);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
WIN_RestoreWndsLock(iWndsLocks);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1680,7 +1724,7 @@ static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
|
|||
*
|
||||
* Initially the edit control allocates a HLOCAL32 buffer
|
||||
* (32 bit linear memory handler). However, 16 bit application
|
||||
* might send a EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF
|
||||
* might send an EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF
|
||||
* handler). From that moment on we have to keep using this 16 bit memory
|
||||
* handler, because it is supposed to be valid at all times after EM_GETHANDLE.
|
||||
* What we do is create a HLOCAL16 buffer, copy the text, and do pointer
|
||||
|
@ -1846,7 +1890,7 @@ static void EDIT_ML_InvalidateText(EDITSTATE *es, INT start, INT end)
|
|||
*
|
||||
* EDIT_InvalidateText
|
||||
*
|
||||
* Invalidate the text from offset start upto, but not including,
|
||||
* Invalidate the text from offset start up to, but not including,
|
||||
* offset end. Useful for (re)painting the selection.
|
||||
* Regions outside the linewidth are not invalidated.
|
||||
* end == -1 means end == TextLength.
|
||||
|
@ -2254,6 +2298,9 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
|
|||
{
|
||||
COLORREF BkColor;
|
||||
COLORREF TextColor;
|
||||
LOGFONTW underline_font;
|
||||
HFONT hUnderline = 0;
|
||||
HFONT old_font = 0;
|
||||
INT ret;
|
||||
INT li;
|
||||
INT BkMode;
|
||||
|
@ -2265,9 +2312,20 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
|
|||
BkColor = GetBkColor(dc);
|
||||
TextColor = GetTextColor(dc);
|
||||
if (rev) {
|
||||
if (es->composition_len == 0)
|
||||
{
|
||||
SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
|
||||
SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
||||
SetBkMode( dc, OPAQUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
HFONT current = GetCurrentObject(dc,OBJ_FONT);
|
||||
GetObjectW(current,sizeof(LOGFONTW),&underline_font);
|
||||
underline_font.lfUnderline = TRUE;
|
||||
hUnderline = CreateFontIndirectW(&underline_font);
|
||||
old_font = SelectObject(dc,hUnderline);
|
||||
}
|
||||
}
|
||||
li = EDIT_EM_LineIndex(es, line);
|
||||
if (es->style & ES_MULTILINE) {
|
||||
|
@ -2282,9 +2340,19 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
|
|||
HeapFree(GetProcessHeap(), 0, text);
|
||||
}
|
||||
if (rev) {
|
||||
if (es->composition_len == 0)
|
||||
{
|
||||
SetBkColor(dc, BkColor);
|
||||
SetTextColor(dc, TextColor);
|
||||
SetBkMode( dc, BkMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (old_font)
|
||||
SelectObject(dc,old_font);
|
||||
if (hUnderline)
|
||||
DeleteObject(hUnderline);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -2408,9 +2476,6 @@ static void EDIT_SetRectNP(EDITSTATE *es, LPRECT rc)
|
|||
*/
|
||||
static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force)
|
||||
{
|
||||
#ifndef __REACTOS__
|
||||
HINSTANCE16 hInstance = GetWindowLongW( es->hwndSelf, GWL_HINSTANCE );
|
||||
#endif
|
||||
|
||||
/* Edit window might be already destroyed */
|
||||
if(!IsWindow(es->hwndSelf))
|
||||
|
@ -2431,11 +2496,12 @@ static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force)
|
|||
if (force || (es->lock_count == 1)) {
|
||||
if (es->hloc32W) {
|
||||
CHAR *textA = NULL;
|
||||
#ifndef __REACTOS__
|
||||
BOOL _16bit = FALSE;
|
||||
#endif
|
||||
UINT countA = 0;
|
||||
UINT countW = strlenW(es->text) + 1;
|
||||
#ifndef __REACTOS__
|
||||
STACK16FRAME* stack16 = NULL;
|
||||
HANDLE16 oldDS = 0;
|
||||
#endif
|
||||
|
||||
if(es->hloc32A)
|
||||
{
|
||||
|
@ -2552,7 +2618,7 @@ static void EDIT_UpdateScrollInfo(EDITSTATE *es)
|
|||
*
|
||||
* Find the beginning of words.
|
||||
* Note: unlike the specs for a WordBreakProc, this function only
|
||||
* allows to be called without linebreaks between s[0] upto
|
||||
* 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.
|
||||
*
|
||||
|
@ -3006,7 +3072,7 @@ static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy)
|
|||
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);
|
||||
nyoff = max(0, es->line_count - lines_per_page);
|
||||
dy = (es->y_offset - nyoff) * es->line_height;
|
||||
if (dx || dy) {
|
||||
RECT rc1;
|
||||
|
@ -3469,10 +3535,6 @@ static void EDIT_EM_ScrollCaret(EDITSTATE *es)
|
|||
*/
|
||||
static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc)
|
||||
{
|
||||
#ifndef __REACTOS__
|
||||
HINSTANCE16 hInstance = GetWindowLongW( es->hwndSelf, GWL_HINSTANCE );
|
||||
#endif
|
||||
|
||||
if (!(es->style & ES_MULTILINE))
|
||||
return;
|
||||
|
||||
|
@ -4142,7 +4204,7 @@ static LRESULT EDIT_WM_Create(EDITSTATE *es, LPCWSTR name)
|
|||
EDIT_SetRectNP(es, &clientRect);
|
||||
|
||||
if (name && *name) {
|
||||
EDIT_EM_ReplaceSel(es, FALSE, name, FALSE, TRUE);
|
||||
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
|
||||
|
@ -4242,7 +4304,6 @@ static INT EDIT_WM_GetText(EDITSTATE *es, INT count, LPWSTR dst, BOOL unicode)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* WM_HSCROLL
|
||||
|
@ -4706,7 +4767,7 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode)
|
|||
|
||||
if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
|
||||
return FALSE;
|
||||
SetWindowLongPtrW( hwnd, 0, (LONG)es );
|
||||
SetWindowLongPtrW( hwnd, 0, (LONG_PTR)es );
|
||||
|
||||
/*
|
||||
* Note: since the EDITSTATE has not been fully initialized yet,
|
||||
|
@ -5304,3 +5365,136 @@ static void EDIT_UpdateText(EDITSTATE *es, LPRECT rc, BOOL bErase)
|
|||
}
|
||||
InvalidateRect(es->hwndSelf, rc, bErase);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* The Following code is to handle inline editing from IMEs
|
||||
*/
|
||||
|
||||
static void EDIT_GetCompositionStr(HWND hwnd, LPARAM CompFlag, EDITSTATE *es)
|
||||
{
|
||||
DWORD dwBufLen;
|
||||
LPWSTR lpCompStr = NULL;
|
||||
HIMC hIMC;
|
||||
LPSTR lpCompStrAttr = NULL;
|
||||
DWORD dwBufLenAttr;
|
||||
|
||||
if (!(hIMC = ImmGetContext(hwnd)))
|
||||
return;
|
||||
|
||||
dwBufLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
|
||||
|
||||
if (dwBufLen <= 0)
|
||||
{
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
return;
|
||||
}
|
||||
|
||||
lpCompStr = HeapAlloc(GetProcessHeap(),0,dwBufLen);
|
||||
if (!lpCompStr)
|
||||
{
|
||||
ERR("Unable to allocate IME CompositionString\n");
|
||||
ImmReleaseContext(hwnd,hIMC);
|
||||
return;
|
||||
}
|
||||
|
||||
ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, dwBufLen);
|
||||
lpCompStr[dwBufLen/sizeof(WCHAR)] = 0;
|
||||
|
||||
if (CompFlag & GCS_COMPATTR)
|
||||
{
|
||||
/*
|
||||
* We do not use the attributes yet. it would tell us what characters
|
||||
* are in transition and which are converted or decided upon
|
||||
*/
|
||||
dwBufLenAttr = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
|
||||
if (dwBufLenAttr)
|
||||
{
|
||||
dwBufLenAttr ++;
|
||||
lpCompStrAttr = HeapAlloc(GetProcessHeap(),0,dwBufLenAttr);
|
||||
if (!lpCompStrAttr)
|
||||
{
|
||||
ERR("Unable to allocate IME Attribute String\n");
|
||||
HeapFree(GetProcessHeap(),0,lpCompStr);
|
||||
ImmReleaseContext(hwnd,hIMC);
|
||||
return;
|
||||
}
|
||||
ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr,
|
||||
dwBufLenAttr);
|
||||
lpCompStrAttr[dwBufLenAttr] = 0;
|
||||
}
|
||||
else
|
||||
lpCompStrAttr = NULL;
|
||||
}
|
||||
|
||||
/* check for change in composition start */
|
||||
if (es->selection_end < es->composition_start)
|
||||
es->composition_start = es->selection_end;
|
||||
|
||||
/* replace existing selection string */
|
||||
es->selection_start = es->composition_start;
|
||||
|
||||
if (es->composition_len > 0)
|
||||
es->selection_end = es->composition_start + es->composition_len;
|
||||
else
|
||||
es->selection_end = es->selection_start;
|
||||
|
||||
EDIT_EM_ReplaceSel(es, FALSE, lpCompStr, TRUE, TRUE);
|
||||
es->composition_len = abs(es->composition_start - es->selection_end);
|
||||
|
||||
es->selection_start = es->composition_start;
|
||||
es->selection_end = es->selection_start + es->composition_len;
|
||||
|
||||
HeapFree(GetProcessHeap(),0,lpCompStrAttr);
|
||||
HeapFree(GetProcessHeap(),0,lpCompStr);
|
||||
ImmReleaseContext(hwnd,hIMC);
|
||||
}
|
||||
|
||||
static void EDIT_GetResultStr(HWND hwnd, EDITSTATE *es)
|
||||
{
|
||||
DWORD dwBufLen;
|
||||
LPWSTR lpResultStr;
|
||||
HIMC hIMC;
|
||||
|
||||
if ( !(hIMC = ImmGetContext(hwnd)))
|
||||
return;
|
||||
|
||||
dwBufLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
|
||||
if (dwBufLen <= 0)
|
||||
{
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
return;
|
||||
}
|
||||
|
||||
lpResultStr = HeapAlloc(GetProcessHeap(),0, dwBufLen);
|
||||
if (!lpResultStr)
|
||||
{
|
||||
ERR("Unable to alloc buffer for IME string\n");
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
return;
|
||||
}
|
||||
|
||||
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, dwBufLen);
|
||||
lpResultStr[dwBufLen/sizeof(WCHAR)] = 0;
|
||||
|
||||
/* check for change in composition start */
|
||||
if (es->selection_end < es->composition_start)
|
||||
es->composition_start = es->selection_end;
|
||||
|
||||
es->selection_start = es->composition_start;
|
||||
es->selection_end = es->composition_start + es->composition_len;
|
||||
EDIT_EM_ReplaceSel(es, TRUE, lpResultStr, TRUE, TRUE);
|
||||
es->composition_start = es->selection_end;
|
||||
es->composition_len = 0;
|
||||
|
||||
HeapFree(GetProcessHeap(),0,lpResultStr);
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
}
|
||||
|
||||
static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es)
|
||||
{
|
||||
if (CompFlag & GCS_RESULTSTR)
|
||||
EDIT_GetResultStr(hwnd,es);
|
||||
if (CompFlag & GCS_COMPSTR)
|
||||
EDIT_GetCompositionStr(hwnd, CompFlag, es);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<library>gdi32</library>
|
||||
<library>kernel32</library>
|
||||
<library>advapi32</library>
|
||||
<library>imm32</library>
|
||||
<directory name="include">
|
||||
<pch>user32.h</pch>
|
||||
</directory>
|
||||
|
|
|
@ -116,7 +116,7 @@ msvcrt -
|
|||
User32 -
|
||||
reactos/dll/win32/user32/controls/button.c # Synced at 20060621
|
||||
reactos/dll/win32/user32/controls/combo.c # Synced at 20060617
|
||||
reactos/dll/win32/user32/controls/edit.c # Synced at 20051210
|
||||
reactos/dll/win32/user32/controls/edit.c # Synced at 20060623
|
||||
reactos/dll/win32/user32/controls/icontitle.c # Synced at 20060617
|
||||
reactos/dll/win32/user32/controls/listbox.c # Synced at 20060616
|
||||
reactos/dll/win32/user32/controls/scrollbar.c # Forked
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue