riched20: Split unicode and ansi window procs, handle messages depending on the unicode flag.

Add a hack for WM_GETTEXT in RichEdit20W class when running in win9x emulation mode.
This commit is contained in:
Dmitry Timoshkov 2007-03-22 19:09:43 +08:00 committed by Alexandre Julliard
parent b9eb76dea0
commit 592b53d0a4
4 changed files with 90 additions and 66 deletions

View File

@ -1413,17 +1413,16 @@ get_msg_name(UINT msg)
return "";
}
/******************************************************************
* RichEditANSIWndProc (RICHED20.10)
*/
LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam, BOOL unicode)
{
ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0);
TRACE("hWnd %p msg %04x (%s) %08x %08lx\n",
hWnd, msg, get_msg_name(msg), wParam, lParam);
TRACE("hwnd %p msg %04x (%s) %x %lx, unicode %d\n",
hWnd, msg, get_msg_name(msg), wParam, lParam, unicode);
if (!editor && msg != WM_NCCREATE && msg != WM_NCDESTROY) {
ERR("RichEditANSIWndProc called with invalid hWnd %p - application bug?\n", hWnd);
ERR("called with invalid hWnd %p - application bug?\n", hWnd);
return 0;
}
@ -1490,7 +1489,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
TRACE("WM_NCCREATE: style 0x%08x\n", pcs->style);
editor = ME_MakeEditor(hWnd);
SetWindowLongPtrW(hWnd, 0, (LONG_PTR)editor);
pcs = 0; /* ignore */
return TRUE;
}
case EM_EMPTYUNDOBUFFER:
@ -1817,7 +1815,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
{
int from, to;
ME_Style *style;
LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
size_t len = lstrlenW(wszText);
TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
@ -1833,7 +1831,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
*/
if (len>0 && wszText[len-1] == '\n')
ME_ClearTempStyle(editor);
ME_EndToUnicode(hWnd, wszText);
ME_EndToUnicode(unicode, wszText);
ME_CommitUndo(editor);
if (!wParam)
ME_EmptyUndoStack(editor);
@ -1885,21 +1883,21 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
if (lParam)
{
TRACE("WM_SETTEXT lParam==%lx\n",lParam);
if (!IsWindowUnicode(hWnd) && !strncmp((char *)lParam, "{\\rtf", 5))
if (!unicode && !strncmp((char *)lParam, "{\\rtf", 5))
{
/* Undocumented: WM_SETTEXT supports RTF text */
ME_StreamInRTFString(editor, 0, (char *)lParam);
}
else
{
LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */
if (lstrlenW(wszText) > 0)
{
/* uses default style! */
ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
}
ME_EndToUnicode(hWnd, wszText);
ME_EndToUnicode(unicode, wszText);
}
}
else
@ -1980,9 +1978,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
{
TEXTRANGEW tr; /* W and A differ only by rng->lpstrText */
tr.chrg.cpMin = 0;
tr.chrg.cpMax = wParam-1;
tr.chrg.cpMax = wParam ? (wParam - 1) : 0;
tr.lpstrText = (WCHAR *)lParam;
return RichEditANSIWndProc(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode);
}
case EM_GETTEXTEX:
{
@ -2003,7 +2001,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
nStart = 0;
nCount = ex->cb - 1;
}
if (ex->codepage == 1200 || IsWindowUnicode(hWnd))
if (ex->codepage == 1200 || unicode)
{
nCount = min(nCount, ex->cb / sizeof(WCHAR) - 1);
return ME_GetTextW(editor, (LPWSTR)lParam, nStart, nCount, ex->flags & GT_USECRLF);
@ -2033,7 +2031,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
tr.chrg.cpMin = from;
tr.chrg.cpMax = to;
tr.lpstrText = (WCHAR *)lParam;
return RichEditANSIWndProc(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode);
}
case EM_GETSCROLLPOS:
{
@ -2046,9 +2044,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
{
TEXTRANGEW *rng = (TEXTRANGEW *)lParam;
TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d emul1.0=%d length=%d\n",
rng->chrg.cpMin, rng->chrg.cpMax, IsWindowUnicode(hWnd),
rng->chrg.cpMin, rng->chrg.cpMax, unicode,
editor->bEmulateVersion10, ME_GetTextLength(editor));
if (IsWindowUnicode(hWnd))
if (unicode)
return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, editor->bEmulateVersion10);
else
{
@ -2066,7 +2064,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case EM_GETLINE:
{
ME_DisplayItem *run;
const BOOL bUnicode = IsWindowUnicode(hWnd);
const unsigned int nMaxChars = *(WORD *) lParam;
unsigned int nEndChars, nCharsLeft = nMaxChars;
char *dest = (char *) lParam;
@ -2075,7 +2072,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
int nLF = editor->bEmulateVersion10;
TRACE("EM_GETLINE: row=%d, nMaxChars=%d (%s)\n", (int) wParam, nMaxChars,
bUnicode ? "Unicode" : "Ansi");
unicode ? "Unicode" : "Ansi");
run = ME_FindRowWithNumber(editor, wParam);
if (run == NULL)
@ -2091,19 +2088,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
strText = run->member.run.strText;
nCopy = min(nCharsLeft, strText->nLen);
if (bUnicode)
if (unicode)
lstrcpynW((LPWSTR) dest, strText->szData, nCopy);
else
nCopy = WideCharToMultiByte(CP_ACP, 0, strText->szData, nCopy, dest,
nCharsLeft, NULL, NULL);
dest += nCopy * (bUnicode ? sizeof(WCHAR) : 1);
dest += nCopy * (unicode ? sizeof(WCHAR) : 1);
nCharsLeft -= nCopy;
}
/* append \r\0 (or \r\n\0 in 1.0), space allowing */
nEndChars = min(nCharsLeft, 2 + nLF);
nCharsLeft -= nEndChars;
if (bUnicode)
if (unicode)
{
const WCHAR src[] = {'\r', '\0'};
const WCHAR src10[] = {'\r', '\n', '\0'};
@ -2362,7 +2359,15 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
goto do_default;
case WM_CHAR:
{
WCHAR wstr = LOWORD(wParam);
WCHAR wstr;
if (unicode)
wstr = (WCHAR)wParam;
else
{
CHAR charA = wParam;
MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1);
}
if (editor->AutoURLDetect_bEnable)
ME_AutoURLDetect(editor, wstr);
@ -2532,7 +2537,8 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
LRESULT ret;
int mask = 0;
int changes = 0;
if ((ret = RichEditANSIWndProc(hWnd, WM_GETTEXTLENGTH, 0, 0)) == 0)
ret = RichEditWndProc_common(hWnd, WM_GETTEXTLENGTH, 0, 0, unicode);
if (!ret)
{
/*Check for valid wParam*/
if ((((wParam & TM_RICHTEXT) && ((wParam & TM_PLAINTEXT) << 1))) ||
@ -2566,6 +2572,29 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
return 0L;
}
static LRESULT WINAPI RichEditWndProcW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
BOOL unicode = TRUE;
/* Under Win9x RichEdit20W returns ANSI strings, see the tests. */
if (msg == WM_GETTEXT && (GetVersion() & 0x80000000))
unicode = FALSE;
return RichEditWndProc_common(hWnd, msg, wParam, lParam, unicode);
}
static LRESULT WINAPI RichEditWndProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return RichEditWndProc_common(hWnd, msg, wParam, lParam, FALSE);
}
/******************************************************************
* RichEditANSIWndProc (RICHED20.10)
*/
LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return RichEditWndProcA(hWnd, msg, wParam, lParam);
}
/******************************************************************
* RichEdit10ANSIWndProc (RICHED20.9)
@ -2648,7 +2677,7 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
WCHAR *pStart = buffer;
if (!item) {
*buffer = L'\0';
*buffer = 0;
return 0;
}
@ -2700,12 +2729,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
if (!nChars)
{
TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart);
*buffer = L'\0';
*buffer = 0;
return nWritten;
}
item = ME_FindItemFwd(item, diRun);
}
*buffer = L'\0';
*buffer = 0;
TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart);
return nWritten;
}
@ -2716,7 +2745,7 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance)
WNDCLASSA wcA;
wcW.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
wcW.lpfnWndProc = RichEditANSIWndProc;
wcW.lpfnWndProc = RichEditWndProcW;
wcW.cbClsExtra = 0;
wcW.cbWndExtra = sizeof(ME_TextEditor *);
wcW.hInstance = NULL; /* hInstance would register DLL-local class */
@ -2742,7 +2771,7 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance)
}
wcA.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
wcA.lpfnWndProc = RichEditANSIWndProc;
wcA.lpfnWndProc = RichEditWndProcA;
wcA.cbClsExtra = 0;
wcA.cbWndExtra = sizeof(ME_TextEditor *);
wcA.hInstance = NULL; /* hInstance would register DLL-local class */

View File

@ -115,10 +115,8 @@ int ME_VPosToPos(ME_String *s, int nVPos);
int ME_PosToVPos(ME_String *s, int nPos);
void ME_StrDeleteV(ME_String *s, int nVChar, int nChars);
/* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */
LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz);
void ME_EndToUnicode(HWND hWnd, LPVOID psz);
LPSTR ME_ToAnsi(HWND hWnd, LPVOID psz);
void ME_EndToAnsi(HWND hWnd, LPVOID psz);
LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz);
void ME_EndToUnicode(BOOL unicode, LPVOID psz);
static inline int ME_IsWSpace(WCHAR ch)
{

View File

@ -345,9 +345,9 @@ ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code)
return editor->pfnWordBreak(str->szData, start, str->nLen, code);
}
LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
{
if (IsWindowUnicode(hWnd))
if (unicode)
return (LPWSTR)psz;
else {
WCHAR *tmp;
@ -358,27 +358,8 @@ LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
}
}
void ME_EndToUnicode(HWND hWnd, LPVOID psz)
void ME_EndToUnicode(BOOL unicode, LPVOID psz)
{
if (!IsWindowUnicode(hWnd))
FREE_OBJ(psz);
}
LPSTR ME_ToAnsi(HWND hWnd, LPVOID psz)
{
if (!IsWindowUnicode(hWnd))
return (LPSTR)psz;
else {
char *tmp;
int nChars = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)psz, -1, NULL, 0, NULL, NULL);
if((tmp = ALLOC_N_OBJ(char, nChars)) != NULL)
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)psz, -1, tmp, nChars, NULL, NULL);
return tmp;
}
}
void ME_EndToAnsi(HWND hWnd, LPVOID psz)
{
if (!IsWindowUnicode(hWnd))
if (!unicode)
FREE_OBJ(psz);
}

View File

@ -1578,16 +1578,13 @@ static void test_unicode_conversions(void)
ret = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)txt); \
ok(ret, "SendMessageA(WM_SETTEXT) error %u\n", GetLastError()); \
} while(0)
#define expect_textA(hwnd, txt, todo) \
#define expect_textA(hwnd, txt) \
do { \
memset(bufA, 0xAA, sizeof(bufA)); \
ret = SendMessageA(hwnd, WM_GETTEXT, 64, (LPARAM)bufA); \
ok(ret, "SendMessageA(WM_GETTEXT) error %u\n", GetLastError()); \
ret = lstrcmpA(bufA, txt); \
if (todo) \
todo_wine ok(!ret, "strings not match: expected %s got %s\n", txt, bufA); \
else \
ok(!ret, "strings not match: expected %s got %s\n", txt, bufA); \
ok(!ret, "strings not match: expected %s got %s\n", txt, bufA); \
} while(0)
#define set_textW(hwnd, txt) \
@ -1601,7 +1598,7 @@ static void test_unicode_conversions(void)
ret = SendMessageW(hwnd, WM_GETTEXT, 64, (LPARAM)bufW); \
ok(ret, "SendMessageW(WM_GETTEXT) error %u\n", GetLastError()); \
ret = lstrcmpW(bufW, txt); \
ok(!ret, "strings not match\n"); \
ok(!ret, "strings not match expected[0] %x got[0] %x\n", txt[0], bufW[0]); \
} while(0)
hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
@ -1614,11 +1611,30 @@ static void test_unicode_conversions(void)
else
ok(ret, "RichEdit20W should be unicode under NT\n");
memset(bufA, 0xAA, sizeof(bufA));
ret = SendMessageA(hwnd, WM_GETTEXT, 64, (LPARAM)bufA);
ok(!ret, "empty richedit should return 0, got %d\n", ret);
ok(!*bufA, "empty richedit should return empty string, got %s\n", bufA);
ret = SendMessageA(hwnd, WM_CHAR, (WPARAM)textW[0], 0);
ok(!ret, "SendMessageA(WM_CHAR) should return 0, got %d\n", ret);
expect_textA(hwnd, "t");
ret = SendMessageA(hwnd, WM_CHAR, (WPARAM)textA[1], 0);
ok(!ret, "SendMessageA(WM_CHAR) should return 0, got %d\n", ret);
expect_textA(hwnd, "te");
set_textA(hwnd, NULL);
memset(bufA, 0xAA, sizeof(bufA));
ret = SendMessageA(hwnd, WM_GETTEXT, 64, (LPARAM)bufA);
ok(!ret, "empty richedit should return 0, got %d\n", ret);
ok(!*bufA, "empty richedit should return empty string, got %s\n", bufA);
if (is_win9x)
set_textA(hwnd, textW);
else
set_textA(hwnd, textA);
expect_textA(hwnd, textA, is_win9x);
expect_textA(hwnd, textA);
if (!is_win9x)
{
@ -1635,7 +1651,7 @@ static void test_unicode_conversions(void)
ok(!ret, "RichEdit20A should NOT be unicode\n");
set_textA(hwnd, textA);
expect_textA(hwnd, textA, FALSE);
expect_textA(hwnd, textA);
if (!is_win9x)
{