Author: fireball
Date: Mon Jun 26 13:20:47 2006
New Revision: 22631
URL:
http://svn.reactos.org/svn/reactos?rev=22631&view=rev
Log:
- 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.
Modified:
trunk/reactos/dll/win32/user32/controls/edit.c
trunk/reactos/dll/win32/user32/user32.rbuild
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/user32/controls/edit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/…
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/edit.c (original)
+++ trunk/reactos/dll/win32/user32/controls/edit.c Mon Jun 26 13:20:47 2006
@@ -141,6 +141,11 @@
#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_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 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,12 +1055,60 @@
}
}
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;
}
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 @@
es->line_count--;
}
}
- else
+ else if (delta != 0)
{
while (current_line)
{
@@ -1401,17 +1456,9 @@
*/
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 @@
else
ret = EDIT_WordBreakProc(es->text + start, index, count, action);
-#ifndef __REACTOS__
- WIN_RestoreWndsLock(iWndsLocks);
-#endif
return ret;
}
@@ -1680,7 +1724,7 @@
*
* 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 @@
*
* 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 @@
{
COLORREF BkColor;
COLORREF TextColor;
+ LOGFONTW underline_font;
+ HFONT hUnderline = 0;
+ HFONT old_font = 0;
INT ret;
INT li;
INT BkMode;
@@ -2265,9 +2312,20 @@
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 @@
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_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 @@
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 @@
*
* 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 @@
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_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 @@
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
@@ -4241,7 +4303,6 @@
return strlen(textA);
}
}
-
/*********************************************************************
*
@@ -4706,7 +4767,7 @@
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 @@
}
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);
+}
Modified: trunk/reactos/dll/win32/user32/user32.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/user32.rb…
==============================================================================
--- trunk/reactos/dll/win32/user32/user32.rbuild (original)
+++ trunk/reactos/dll/win32/user32/user32.rbuild Mon Jun 26 13:20:47 2006
@@ -14,6 +14,7 @@
<library>gdi32</library>
<library>kernel32</library>
<library>advapi32</library>
+ <library>imm32</library>
<directory name="include">
<pch>user32.h</pch>
</directory>
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE (original)
+++ trunk/reactos/media/doc/README.WINE Mon Jun 26 13:20:47 2006
@@ -116,7 +116,7 @@
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