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:
parent
b9eb76dea0
commit
592b53d0a4
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue