From: Thomas Faber Date: Fri, 4 Nov 2011 23:07:16 +0000 (+0000) Subject: [RICHED20_WINETEST] X-Git-Tag: backups/iut-netsh@54410~98 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=c0f989c66a7bc24aa0bae1329cc7e52107ac3204 [RICHED20_WINETEST] - Sync to Wine 1.3.32 svn path=/trunk/; revision=54290 --- diff --git a/rostests/winetests/riched20/editor.c b/rostests/winetests/riched20/editor.c index 685eeade3fe..827f35dffe4 100644 --- a/rostests/winetests/riched20/editor.c +++ b/rostests/winetests/riched20/editor.c @@ -46,21 +46,32 @@ static CHAR string1[MAX_PATH], string2[MAX_PATH], string3[MAX_PATH]; static HMODULE hmoduleRichEdit; -static int is_win9x = 0; - -static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) { +static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) { HWND hwnd; - hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL + hwnd = CreateWindowA(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL |WS_VISIBLE, 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL); ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError()); return hwnd; } +static HWND new_windowW(LPCWSTR lpClassName, DWORD dwStyle, HWND parent) { + HWND hwnd; + hwnd = CreateWindowW(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL + |WS_VISIBLE, 0, 0, 200, 60, parent, NULL, + hmoduleRichEdit, NULL); + ok(hwnd != NULL, "class: %s, error: %d\n", wine_dbgstr_w(lpClassName), (int) GetLastError()); + return hwnd; +} + static HWND new_richedit(HWND parent) { return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent); } +static HWND new_richeditW(HWND parent) { + return new_windowW(RICHEDIT_CLASS20W, ES_MULTILINE, parent); +} + /* Keeps the window reponsive for the deley_time in seconds. * This is useful for debugging a test to see what is happening. */ static void keep_responsive(time_t delay_time) @@ -81,27 +92,6 @@ static void keep_responsive(time_t delay_time) } } -static void processPendingMessages(void) -{ - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -static void pressKeyWithModifier(HWND hwnd, BYTE mod_vk, BYTE vk) -{ - BYTE mod_scan_code = MapVirtualKey(mod_vk, MAPVK_VK_TO_VSC); - BYTE scan_code = MapVirtualKey(vk, MAPVK_VK_TO_VSC); - SetFocus(hwnd); - keybd_event(mod_vk, mod_scan_code, 0, 0); - keybd_event(vk, scan_code, 0, 0); - keybd_event(vk, scan_code, KEYEVENTF_KEYUP, 0); - keybd_event(mod_vk, mod_scan_code, KEYEVENTF_KEYUP, 0); - processPendingMessages(); -} - static void simulate_typing_characters(HWND hwnd, const char* szChars) { int ret; @@ -155,7 +145,7 @@ struct find_s { }; -struct find_s find_tests[] = { +static struct find_s find_tests[] = { /* Find in empty text */ {0, -1, "foo", FR_DOWN, -1}, {0, -1, "foo", 0, -1}, @@ -164,7 +154,7 @@ struct find_s find_tests[] = { {5, 20, "foo", FR_DOWN, -1} }; -struct find_s find_tests2[] = { +static struct find_s find_tests2[] = { /* No-result find */ {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1}, {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1}, @@ -386,7 +376,7 @@ static void test_EM_GETLINE(void) * to the MSDN documentation fo EM_GETLINE, which does not state that * a NULL terminating character will be added unless no text is copied. * - * Windows 95, 98 & NT do not append a NULL terminating character, but + * Windows NT does not append a NULL terminating character, but * Windows 2000 and up do append a NULL terminating character if there * is space in the buffer. The test will ignore this difference. */ ok(!strncmp(dest, gl[i].text, expected_bytes_written), @@ -520,11 +510,13 @@ static void test_EM_SCROLLCARET(void) static void test_EM_POSFROMCHAR(void) { HWND hwndRichEdit = new_richedit(NULL); - int i; + int i, expected; LRESULT result; unsigned int height = 0; int xpos = 0; POINTL pt; + LOCALESIGNATURE sig; + BOOL rtl; static const char text[] = "aa\n" "this is a long line of text that should be longer than the " "control's width\n" @@ -535,6 +527,10 @@ static void test_EM_POSFROMCHAR(void) "gg\n" "hh\n"; + rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE, + (LPSTR) &sig, sizeof(LOCALESIGNATURE)) && + (sig.lsUsb[3] & 0x08000000) != 0); + /* Fill the control to lines to ensure that most of them are offscreen */ for (i = 0; i < 50; i++) { @@ -586,7 +582,8 @@ static void test_EM_POSFROMCHAR(void) /* Testing position way past end of text */ result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 55 * 16, 0); ok(HIWORD(result) == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), 50 * height); - ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + expected = (rtl ? 8 : 1); + ok(LOWORD(result) == expected, "EM_POSFROMCHAR reports x=%d, expected %d\n", LOWORD(result), expected); /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */ SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */ @@ -608,7 +605,8 @@ static void test_EM_POSFROMCHAR(void) /* Testing position way past end of text */ result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 55 * 16, 0); ok(HIWORD(result) == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), (50 - 1) * height); - ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + expected = (rtl ? 8 : 1); + ok(LOWORD(result) == expected, "EM_POSFROMCHAR reports x=%d, expected %d\n", LOWORD(result), expected); /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text); @@ -636,7 +634,7 @@ static void test_EM_POSFROMCHAR(void) SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0)); ok(pt.x > xpos, "pt.x = %d\n", pt.x); - xpos = pt.x; + xpos = (rtl ? pt.x + 7 : pt.x); SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0)+1); ok(pt.x == xpos, "pt.x = %d\n", pt.x); @@ -666,6 +664,12 @@ static void test_EM_SETCHARFORMAT(void) }; int i; CHARRANGE cr; + LOCALESIGNATURE sig; + BOOL rtl; + + rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE, + (LPSTR) &sig, sizeof(LOCALESIGNATURE)) && + (sig.lsUsb[3] & 0x08000000) != 0); /* Invalid flags, CHARFORMAT2 structure blanked out */ memset(&cf2, 0, sizeof(cf2)); @@ -764,8 +768,13 @@ static void test_EM_SETCHARFORMAT(void) ok(rc == 0, "Text marked as modified, expected not modified!\n"); rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, 0, (LPARAM) &cf2); ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); - rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0); - ok(rc == 0, "Text marked as modified, expected not modified!\n"); + if (! rtl) + { + rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0); + ok(rc == 0, "Text marked as modified, expected not modified!\n"); + } + else + skip("RTL language found\n"); /* wParam==SCF_SELECTION sets modify if nonempty selection */ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -1053,6 +1062,11 @@ static void test_EM_SETTEXTMODE(void) CHARRANGE cr; int rc = 0; + /*Attempt to use mutually exclusive modes*/ + rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_PLAINTEXT|TM_RICHTEXT, 0); + ok(rc == E_INVALIDARG, + "EM_SETTEXTMODE: using mutually exclusive mode flags - returned: %x\n", rc); + /*Test that EM_SETTEXTMODE fails if text exists within the control*/ /*Insert text into the control*/ @@ -1060,7 +1074,8 @@ static void test_EM_SETTEXTMODE(void) /*Attempt to change the control to plain text mode*/ rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_PLAINTEXT, 0); - ok(rc != 0, "EM_SETTEXTMODE: changed text mode in control containing text - returned: %d\n", rc); + ok(rc == E_UNEXPECTED, + "EM_SETTEXTMODE: changed text mode in control containing text - returned: %x\n", rc); /*Test that EM_SETTEXTMODE does not allow rich edit text to be pasted. If rich text is pasted, it should have the same formatting as the rest @@ -1526,7 +1541,6 @@ static void test_EM_SETOPTIONS(void) SendMessage(hwndRichEdit, EM_SETOPTIONS, ECOOP_SET, 0); /* testing no readonly by sending 'a' to the control*/ - SetFocus(hwndRichEdit); SendMessage(hwndRichEdit, WM_CHAR, 'a', 0x1E0001); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok(buffer[0]=='a', @@ -1536,7 +1550,6 @@ static void test_EM_SETOPTIONS(void) /* READONLY - sending 'a' to the control */ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text); SendMessage(hwndRichEdit, EM_SETOPTIONS, ECOOP_SET, ECO_READONLY); - SetFocus(hwndRichEdit); SendMessage(hwndRichEdit, WM_CHAR, 'a', 0x1E0001); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok(buffer[0]==text[0], @@ -2440,10 +2453,10 @@ static void test_EM_SCROLL(void) DestroyWindow(hwndRichEdit); } -unsigned int recursionLevel = 0; -unsigned int WM_SIZE_recursionLevel = 0; -BOOL bailedOutOfRecursion = FALSE; -LRESULT (WINAPI *richeditProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +static unsigned int recursionLevel = 0; +static unsigned int WM_SIZE_recursionLevel = 0; +static BOOL bailedOutOfRecursion = FALSE; +static LRESULT (WINAPI *richeditProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static LRESULT WINAPI RicheditStupidOverrideProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -3336,13 +3349,8 @@ static void test_WM_SETTEXT(void) result = lstrcmpW(b, bufW); \ ok(result == 0, "WM_SETTEXT round trip: strcmp = %ld\n", result); - if (is_win9x) - { - skip("Cannot perform unicode tests\n"); - return; - } -hwndRichEdit = CreateWindowW(RICHEDIT_CLASS20W, NULL, - ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE, + hwndRichEdit = CreateWindowW(RICHEDIT_CLASS20W, NULL, + ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE, 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL); ok(hwndRichEdit != NULL, "class: RichEdit20W, error: %d\n", (int) GetLastError()); TEST_SETTEXTW(rtftextA, sometextW) /* interpreted as ascii rtf */ @@ -4423,17 +4431,9 @@ static void test_EM_REPLACESEL(int redraw) r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0); ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r); - /* Win98's riched20 and WinXP's riched20 disagree on what to return from - EM_REPLACESEL. The general rule seems to be that Win98's riched20 - returns the number of characters *inserted* into the control (after - required conversions), but WinXP's riched20 returns the number of - characters interpreted from the original lParam. Wine's builtin riched20 - implements the WinXP behavior. - */ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "RichEdit1\r\n"); - ok(11 == r /* WinXP */ || 10 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 11 or 10\n", r); + ok(r == 11, "EM_REPLACESEL returned %d, expected 11\n", r); /* Test number of lines reported after EM_REPLACESEL */ r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0); @@ -4491,8 +4491,7 @@ static void test_EM_REPLACESEL(int redraw) SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n"); - ok(3 == r /* WinXP */ || 1 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 3 or 1\n", r); + ok(r == 3, "EM_REPLACESEL returned %d, expected 3\n", r); r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr); ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r); ok(cr.cpMin == 1, "EM_EXGETSEL returned cpMin=%d, expected 1\n", cr.cpMin); @@ -4514,8 +4513,7 @@ static void test_EM_REPLACESEL(int redraw) SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\r\r\r\n\r\r\r"); - ok(9 == r /* WinXP */ || 7 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 9 or 7\n", r); + ok(r == 9, "EM_REPLACESEL returned %d, expected 9\n", r); r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr); ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r); ok(cr.cpMin == 7, "EM_EXGETSEL returned cpMin=%d, expected 7\n", cr.cpMin); @@ -4537,8 +4535,7 @@ static void test_EM_REPLACESEL(int redraw) SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n\r\n"); - ok(5 == r /* WinXP */ || 2 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 5 or 2\n", r); + ok(r == 5, "EM_REPLACESEL returned %d, expected 5\n", r); r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr); ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r); ok(cr.cpMin == 2, "EM_EXGETSEL returned cpMin=%d, expected 2\n", cr.cpMin); @@ -4560,8 +4557,7 @@ static void test_EM_REPLACESEL(int redraw) SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n\r\r"); - ok(5 == r /* WinXP */ || 3 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 5 or 3\n", r); + ok(r == 5, "EM_REPLACESEL returned %d, expected 5\n", r); r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr); ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r); ok(cr.cpMin == 3, "EM_EXGETSEL returned cpMin=%d, expected 3\n", cr.cpMin); @@ -4583,8 +4579,7 @@ static void test_EM_REPLACESEL(int redraw) SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\rX\r\n\r\r"); - ok(6 == r /* WinXP */ || 5 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 6 or 5\n", r); + ok(r == 6, "EM_REPLACESEL returned %d, expected 6\n", r); r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr); ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r); ok(cr.cpMin == 5, "EM_EXGETSEL returned cpMin=%d, expected 5\n", cr.cpMin); @@ -4628,8 +4623,7 @@ static void test_EM_REPLACESEL(int redraw) SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\n\n\n\n\r\r\r\r\n"); - ok(9 == r /* WinXP */ || 7 == r /* Win98 */, - "EM_REPLACESEL returned %d, expected 9 or 7\n", r); + ok(r == 9, "EM_REPLACESEL returned %d, expected 9\n", r); r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr); ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r); ok(cr.cpMin == 7, "EM_EXGETSEL returned cpMin=%d, expected 7\n", cr.cpMin); @@ -4657,6 +4651,22 @@ static void test_EM_REPLACESEL(int redraw) DestroyWindow(hwndRichEdit); } +/* Native riched20 inspects the keyboard state (e.g. GetKeyState) + * to test the state of the modifiers (Ctrl/Alt/Shift). + * + * Therefore Ctrl- keystrokes need to be simulated with + * keybd_event or by using SetKeyboardState to set the modifiers + * and SendMessage to simulate the keystrokes. + */ +static LRESULT send_ctrl_key(HWND hwnd, UINT key) +{ + LRESULT result; + hold_key(VK_CONTROL); + result = SendMessage(hwnd, WM_KEYDOWN, key, 1); + release_key(VK_CONTROL); + return result; +} + static void test_WM_PASTE(void) { int result; @@ -4669,34 +4679,19 @@ static void test_WM_PASTE(void) const char* text3 = "testing paste\r\npaste\r\ntesting paste"; HWND hwndRichEdit = new_richedit(NULL); - /* Native riched20 inspects the keyboard state (e.g. GetKeyState) - * to test the state of the modifiers (Ctrl/Alt/Shift). - * - * Therefore Ctrl- keystrokes need to be simulated with - * keybd_event or by using SetKeyboardState to set the modifiers - * and SendMessage to simulate the keystrokes. - */ - - /* Sent keystrokes with keybd_event */ -#define SEND_CTRL_C(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'C') -#define SEND_CTRL_X(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'X') -#define SEND_CTRL_V(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'V') -#define SEND_CTRL_Z(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'Z') -#define SEND_CTRL_Y(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'Y') - SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1); SendMessage(hwndRichEdit, EM_SETSEL, 0, 14); - SEND_CTRL_C(hwndRichEdit); /* Copy */ + send_ctrl_key(hwndRichEdit, 'C'); /* Copy */ SendMessage(hwndRichEdit, EM_SETSEL, 14, 14); - SEND_CTRL_V(hwndRichEdit); /* Paste */ + send_ctrl_key(hwndRichEdit, 'V'); /* Paste */ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); /* Pasted text should be visible at this step */ result = strcmp(text1_step1, buffer); ok(result == 0, "test paste: strcmp = %i, text='%s'\n", result, buffer); - SEND_CTRL_Z(hwndRichEdit); /* Undo */ + send_ctrl_key(hwndRichEdit, 'Z'); /* Undo */ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); /* Text should be the same as before (except for \r -> \r\n conversion) */ result = strcmp(text1_after, buffer); @@ -4705,37 +4700,31 @@ static void test_WM_PASTE(void) SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text2); SendMessage(hwndRichEdit, EM_SETSEL, 8, 13); - SEND_CTRL_C(hwndRichEdit); /* Copy */ + send_ctrl_key(hwndRichEdit, 'C'); /* Copy */ SendMessage(hwndRichEdit, EM_SETSEL, 14, 14); - SEND_CTRL_V(hwndRichEdit); /* Paste */ + send_ctrl_key(hwndRichEdit, 'V'); /* Paste */ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); /* Pasted text should be visible at this step */ result = strcmp(text3, buffer); ok(result == 0, "test paste: strcmp = %i\n", result); - SEND_CTRL_Z(hwndRichEdit); /* Undo */ + send_ctrl_key(hwndRichEdit, 'Z'); /* Undo */ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); /* Text should be the same as before (except for \r -> \r\n conversion) */ result = strcmp(text2_after, buffer); ok(result == 0, "test paste: strcmp = %i\n", result); - SEND_CTRL_Y(hwndRichEdit); /* Redo */ + send_ctrl_key(hwndRichEdit, 'Y'); /* Redo */ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); /* Text should revert to post-paste state */ result = strcmp(buffer,text3); ok(result == 0, "test paste: strcmp = %i\n", result); -#undef SEND_CTRL_C -#undef SEND_CTRL_X -#undef SEND_CTRL_V -#undef SEND_CTRL_Z -#undef SEND_CTRL_Y - SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); /* Send WM_CHAR to simulates Ctrl-V */ SendMessage(hwndRichEdit, WM_CHAR, 22, - (MapVirtualKey('V', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('V', MAPVK_VK_TO_VSC) << 16) | 1); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); /* Shouldn't paste because pasting is handled by WM_KEYDOWN */ result = strcmp(buffer,""); @@ -4749,7 +4738,7 @@ static void test_WM_PASTE(void) /* Simulates paste (Ctrl-V) */ hold_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_KEYDOWN, 'V', - (MapVirtualKey('V', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('V', MAPVK_VK_TO_VSC) << 16) | 1); release_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); result = strcmp(buffer,"paste"); @@ -4761,7 +4750,7 @@ static void test_WM_PASTE(void) /* Simulates copy (Ctrl-C) */ hold_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_KEYDOWN, 'C', - (MapVirtualKey('C', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('C', MAPVK_VK_TO_VSC) << 16) | 1); release_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0); SendMessage(hwndRichEdit, WM_PASTE, 0, 0); @@ -4775,10 +4764,10 @@ static void test_WM_PASTE(void) /* Simulates select all (Ctrl-A) */ hold_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_KEYDOWN, 'A', - (MapVirtualKey('A', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('A', MAPVK_VK_TO_VSC) << 16) | 1); /* Simulates select cut (Ctrl-X) */ SendMessage(hwndRichEdit, WM_KEYDOWN, 'X', - (MapVirtualKey('X', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('X', MAPVK_VK_TO_VSC) << 16) | 1); release_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); result = strcmp(buffer,""); @@ -4793,14 +4782,14 @@ static void test_WM_PASTE(void) /* Simulates undo (Ctrl-Z) */ hold_key(VK_CONTROL); SendMessage(hwndRichEdit, WM_KEYDOWN, 'Z', - (MapVirtualKey('Z', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('Z', MAPVK_VK_TO_VSC) << 16) | 1); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); result = strcmp(buffer,""); ok(result == 0, "test paste: strcmp = %i, actual = '%s'\n", result, buffer); /* Simulates redo (Ctrl-Y) */ SendMessage(hwndRichEdit, WM_KEYDOWN, 'Y', - (MapVirtualKey('Y', MAPVK_VK_TO_VSC) << 16) & 1); + (MapVirtualKey('Y', MAPVK_VK_TO_VSC) << 16) | 1); SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); result = strcmp(buffer,"cut\r\n"); todo_wine ok(result == 0, @@ -4816,6 +4805,7 @@ static void test_EM_FORMATRANGE(void) HDC hdc; HWND hwndRichEdit = new_richedit(NULL); FORMATRANGE fr; + BOOL skip_non_english; static const struct { const char *string; /* The string */ int first; /* First 'pagebreak', 0 for don't care */ @@ -4828,6 +4818,10 @@ static void test_EM_FORMATRANGE(void) {"WINE\r\n\r\nwine\r\nwine", 5, 6} }; + skip_non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH); + if (skip_non_english) + skip("Skipping some tests on non-English platform\n"); + hdc = GetDC(hwndRichEdit); ok(hdc != NULL, "Could not get HDC\n"); @@ -4889,7 +4883,8 @@ static void test_EM_FORMATRANGE(void) fr.chrg.cpMax = -1; r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) &fr); todo_wine { - ok(fr.rc.bottom == (stringsize.cy * tpp_y), "Expected bottom to be %d, got %d\n", (stringsize.cy * tpp_y), fr.rc.bottom); + if (! skip_non_english) + ok(fr.rc.bottom == (stringsize.cy * tpp_y), "Expected bottom to be %d, got %d\n", (stringsize.cy * tpp_y), fr.rc.bottom); } if (fmtstrings[i].first) todo_wine { @@ -4905,7 +4900,7 @@ static void test_EM_FORMATRANGE(void) todo_wine { ok(r == fmtstrings[i].second, "Expected %d, got %d\n", fmtstrings[i].second, r); } - else + else if (! skip_non_english) ok (r < len, "Expected < %d, got %d\n", len, r); /* There is at least on more page, but we don't care */ @@ -5017,20 +5012,29 @@ static void test_EM_STREAMIN(void) const char * streamText3 = "RichEdit1"; - struct StringWithLength cookieForStream4; const char * streamText4 = "This text just needs to be long enough to cause run to be split onto " "two separate lines and make sure the null terminating character is " "handled properly.\0"; int length4 = strlen(streamText4) + 1; - cookieForStream4.buffer = (char *)streamText4; - cookieForStream4.length = length4; + struct StringWithLength cookieForStream4 = { + length4, + (char *)streamText4, + }; + + const WCHAR streamText5[] = { 'T', 'e', 's', 't', 'S', 'o', 'm', 'e', 'T', 'e', 'x', 't' }; + int length5 = sizeof(streamText5) / sizeof(WCHAR); + struct StringWithLength cookieForStream5 = { + sizeof(streamText5), + (char *)streamText5, + }; /* Minimal test without \par at the end */ es.dwCookie = (DWORD_PTR)&streamText0; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 12, "got %ld, expected %d\n", result, 12); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == 12, @@ -5044,7 +5048,8 @@ static void test_EM_STREAMIN(void) es.dwCookie = (DWORD_PTR)&streamText0a; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 12, "got %ld, expected %d\n", result, 12); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == 12, @@ -5058,7 +5063,8 @@ static void test_EM_STREAMIN(void) es.dwCookie = (DWORD_PTR)&streamText0b; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 13, "got %ld, expected %d\n", result, 13); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == 14, @@ -5071,7 +5077,8 @@ static void test_EM_STREAMIN(void) es.dwCookie = (DWORD_PTR)&streamText1; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 12, "got %ld, expected %d\n", result, 12); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == 12, @@ -5083,7 +5090,8 @@ static void test_EM_STREAMIN(void) es.dwCookie = (DWORD_PTR)&streamText2; es.dwError = 0; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 0, "got %ld, expected %d\n", result, 0); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == 0, @@ -5094,7 +5102,8 @@ static void test_EM_STREAMIN(void) es.dwCookie = (DWORD_PTR)&streamText3; es.dwError = 0; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 0, "got %ld, expected %d\n", result, 0); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == 0, @@ -5106,13 +5115,25 @@ static void test_EM_STREAMIN(void) es.dwCookie = (DWORD_PTR)&cookieForStream4; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback2; - SendMessage(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es); + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es); + ok(result == length4, "got %ld, expected %d\n", result, length4); result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); ok (result == length4, "EM_STREAMIN: Test 4 returned %ld, expected %d\n", result, length4); ok(es.dwError == 0, "EM_STREAMIN: Test 4 set error %d, expected %d\n", es.dwError, 0); + es.dwCookie = (DWORD_PTR)&cookieForStream5; + es.dwError = 0; + es.pfnCallback = test_EM_STREAMIN_esCallback2; + result = SendMessage(hwndRichEdit, EM_STREAMIN, SF_TEXT | SF_UNICODE, (LPARAM)&es); + ok(result == sizeof(streamText5), "got %ld, expected %u\n", result, (UINT)sizeof(streamText5)); + + result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); + ok (result == length5, + "EM_STREAMIN: Test 4 returned %ld, expected %d\n", result, length5); + ok(es.dwError == 0, "EM_STREAMIN: Test 5 set error %d, expected %d\n", es.dwError, 0); + DestroyWindow(hwndRichEdit); } @@ -5240,17 +5261,8 @@ static void test_unicode_conversions(void) WPARAM wparam = (wm_get_text == WM_GETTEXT) ? 64 : (WPARAM)>ex; \ assert(wm_get_text == WM_GETTEXT || wm_get_text == EM_GETTEXTEX); \ memset(bufW, 0xAA, sizeof(bufW)); \ - if (is_win9x) \ - { \ - assert(wm_get_text == EM_GETTEXTEX); \ - ret = SendMessageA(hwnd, wm_get_text, wparam, (LPARAM)bufW); \ - ok(ret, "SendMessageA(%02x) error %u\n", wm_get_text, GetLastError()); \ - } \ - else \ - { \ - ret = SendMessageW(hwnd, wm_get_text, wparam, (LPARAM)bufW); \ - ok(ret, "SendMessageW(%02x) error %u\n", wm_get_text, GetLastError()); \ - } \ + ret = SendMessageW(hwnd, wm_get_text, wparam, (LPARAM)bufW); \ + ok(ret, "SendMessageW(%02x) error %u\n", wm_get_text, GetLastError()); \ ret = lstrcmpW(bufW, txt); \ ok(!ret, "%02x: strings do not match: expected[0] %x got[0] %x\n", wm_get_text, txt[0], bufW[0]); \ } while(0) @@ -5270,10 +5282,7 @@ static void test_unicode_conversions(void) ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); ret = IsWindowUnicode(hwnd); - if (is_win9x) - ok(!ret, "RichEdit20W should NOT be unicode under Win9x\n"); - else - ok(ret, "RichEdit20W should be unicode under NT\n"); + ok(ret, "RichEdit20W should be unicode under NT\n"); /* EM_SETTEXTEX is supported starting from version 3.0 */ em_settextex_supported = is_em_settextex_supported(hwnd); @@ -5299,10 +5308,7 @@ static void test_unicode_conversions(void) expect_empty(hwnd, WM_GETTEXT); expect_empty(hwnd, EM_GETTEXTEX); - if (is_win9x) - set_textA(hwnd, WM_SETTEXT, textW); - else - set_textA(hwnd, WM_SETTEXT, textA); + set_textA(hwnd, WM_SETTEXT, textA); expect_textA(hwnd, WM_GETTEXT, textA); expect_textA(hwnd, EM_GETTEXTEX, textA); expect_textW(hwnd, EM_GETTEXTEX, textW); @@ -5315,22 +5321,19 @@ static void test_unicode_conversions(void) expect_textW(hwnd, EM_GETTEXTEX, textW); } - if (!is_win9x) + set_textW(hwnd, WM_SETTEXT, textW); + expect_textW(hwnd, WM_GETTEXT, textW); + expect_textA(hwnd, WM_GETTEXT, textA); + expect_textW(hwnd, EM_GETTEXTEX, textW); + expect_textA(hwnd, EM_GETTEXTEX, textA); + + if (em_settextex_supported) { - set_textW(hwnd, WM_SETTEXT, textW); + set_textW(hwnd, EM_SETTEXTEX, textW); expect_textW(hwnd, WM_GETTEXT, textW); expect_textA(hwnd, WM_GETTEXT, textA); expect_textW(hwnd, EM_GETTEXTEX, textW); expect_textA(hwnd, EM_GETTEXTEX, textA); - - if (em_settextex_supported) - { - set_textW(hwnd, EM_SETTEXTEX, textW); - expect_textW(hwnd, WM_GETTEXT, textW); - expect_textA(hwnd, WM_GETTEXT, textA); - expect_textW(hwnd, EM_GETTEXTEX, textW); - expect_textA(hwnd, EM_GETTEXTEX, textA); - } } DestroyWindow(hwnd); @@ -5354,22 +5357,19 @@ static void test_unicode_conversions(void) expect_textW(hwnd, EM_GETTEXTEX, textW); } - if (!is_win9x) - { set_textW(hwnd, WM_SETTEXT, textW); expect_textW(hwnd, WM_GETTEXT, textW); expect_textA(hwnd, WM_GETTEXT, textA); expect_textW(hwnd, EM_GETTEXTEX, textW); expect_textA(hwnd, EM_GETTEXTEX, textA); - if (em_settextex_supported) - { - set_textW(hwnd, EM_SETTEXTEX, textW); - expect_textW(hwnd, WM_GETTEXT, textW); - expect_textA(hwnd, WM_GETTEXT, textA); - expect_textW(hwnd, EM_GETTEXTEX, textW); - expect_textA(hwnd, EM_GETTEXTEX, textA); - } + if (em_settextex_supported) + { + set_textW(hwnd, EM_SETTEXTEX, textW); + expect_textW(hwnd, WM_GETTEXT, textW); + expect_textA(hwnd, WM_GETTEXT, textA); + expect_textW(hwnd, EM_GETTEXTEX, textW); + expect_textA(hwnd, EM_GETTEXTEX, textA); } DestroyWindow(hwnd); } @@ -5437,12 +5437,8 @@ static void test_EM_GETTEXTLENGTHEX(void) char buffer[64] = {0}; /* single line */ - if (!is_win9x) - hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP, - 0, 0, 200, 60, 0, 0, 0, 0); - else - hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP, - 0, 0, 200, 60, 0, 0, 0, 0); + hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP, + 0, 0, 200, 60, 0, 0, 0, 0); ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF; @@ -5486,12 +5482,8 @@ static void test_EM_GETTEXTLENGTHEX(void) DestroyWindow(hwnd); /* multi line */ - if (!is_win9x) - hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP | ES_MULTILINE, - 0, 0, 200, 60, 0, 0, 0, 0); - else - hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP | ES_MULTILINE, - 0, 0, 200, 60, 0, 0, 0, 0); + hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP | ES_MULTILINE, + 0, 0, 200, 60, 0, 0, 0, 0); ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF; @@ -5794,12 +5786,8 @@ static void test_undo_coalescing(void) char buffer[64] = {0}; /* multi-line control inserts CR normally */ - if (!is_win9x) - hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE, - 0, 0, 200, 60, 0, 0, 0, 0); - else - hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP|ES_MULTILINE, - 0, 0, 200, 60, 0, 0, 0, 0); + hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE, + 0, 0, 200, 60, 0, 0, 0, 0); ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); result = SendMessage(hwnd, EM_CANUNDO, 0, 0); @@ -5946,9 +5934,6 @@ static LONG CALLBACK customWordBreakProc(WCHAR *text, int pos, int bytes, int co return 0; } -#define SEND_CTRL_LEFT(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, VK_LEFT) -#define SEND_CTRL_RIGHT(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, VK_RIGHT) - static void test_word_movement(void) { HWND hwnd; @@ -5964,25 +5949,25 @@ static void test_word_movement(void) SendMessage(hwnd, EM_SETSEL, 0, 0); /* |one two three */ - SEND_CTRL_RIGHT(hwnd); + send_ctrl_key(hwnd, VK_RIGHT); /* one |two three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); ok(sel_start == 4, "Cursor is at %d instead of %d\n", sel_start, 4); - SEND_CTRL_RIGHT(hwnd); + send_ctrl_key(hwnd, VK_RIGHT); /* one two |three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); ok(sel_start == 9, "Cursor is at %d instead of %d\n", sel_start, 9); - SEND_CTRL_LEFT(hwnd); + send_ctrl_key(hwnd, VK_LEFT); /* one |two three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); ok(sel_start == 4, "Cursor is at %d instead of %d\n", sel_start, 4); - SEND_CTRL_LEFT(hwnd); + send_ctrl_key(hwnd, VK_LEFT); /* |one two three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); @@ -5990,7 +5975,7 @@ static void test_word_movement(void) SendMessage(hwnd, EM_SETSEL, 8, 8); /* one two | three */ - SEND_CTRL_RIGHT(hwnd); + send_ctrl_key(hwnd, VK_RIGHT); /* one two |three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); @@ -5998,7 +5983,7 @@ static void test_word_movement(void) SendMessage(hwnd, EM_SETSEL, 11, 11); /* one two th|ree */ - SEND_CTRL_LEFT(hwnd); + send_ctrl_key(hwnd, VK_LEFT); /* one two |three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); @@ -6009,7 +5994,7 @@ static void test_word_movement(void) ok (result == TRUE, "Failed to clear the text.\n"); SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)customWordBreakProc); /* |one twoXthree */ - SEND_CTRL_RIGHT(hwnd); + send_ctrl_key(hwnd, VK_RIGHT); /* one twoX|three */ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); @@ -6019,11 +6004,6 @@ static void test_word_movement(void) /* Make sure the behaviour is the same with a unicode richedit window, * and using unicode functions. */ - if (is_win9x) - { - skip("Cannot test with unicode richedit window\n"); - return; - } hwnd = CreateWindowW(RICHEDIT_CLASS20W, NULL, ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE, @@ -6034,7 +6014,7 @@ static void test_word_movement(void) ok (result == TRUE, "Failed to clear the text.\n"); SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)customWordBreakProc); /* |one twoXthree */ - SEND_CTRL_RIGHT(hwnd); + send_ctrl_key(hwnd, VK_RIGHT); /* one twoX|three */ SendMessageW(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); ok(sel_start == sel_end, "Selection should be empty\n"); @@ -6056,7 +6036,7 @@ static void test_EM_CHARFROMPOS(void) hwnd = new_richedit(NULL); result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"one two three four five six seven\reight"); - + ok(result == 1, "Expected 1, got %d\n", result); GetClientRect(hwnd, &rcClient); result = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point); @@ -6074,7 +6054,7 @@ static void test_EM_CHARFROMPOS(void) todo_wine ok(result == 33, "expected character index of 33 but got %d\n", result); point.x = 1000; - point.y = 40; + point.y = 36; result = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point); todo_wine ok(result == 39, "expected character index of 39 but got %d\n", result); @@ -6384,6 +6364,49 @@ static void test_format_rect(void) rc.top, rc.left, rc.bottom, rc.right, expected.top, expected.left, expected.bottom, expected.right); + /* Reset to default rect and check how the format rect adjusts to window + * resize and how it copes with very small windows */ + SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)NULL); + + MoveWindow(hwnd, 0, 0, 100, 30, FALSE); + GetClientRect(hwnd, &clientRect); + + expected = clientRect; + expected.left += 1; + expected.right -= 1; + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(rc.top == expected.top && rc.left == expected.left && + rc.bottom == expected.bottom && rc.right == expected.right, + "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n", + rc.top, rc.left, rc.bottom, rc.right, + expected.top, expected.left, expected.bottom, expected.right); + + MoveWindow(hwnd, 0, 0, 0, 30, FALSE); + GetClientRect(hwnd, &clientRect); + + expected = clientRect; + expected.left += 1; + expected.right -= 1; + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(rc.top == expected.top && rc.left == expected.left && + rc.bottom == expected.bottom && rc.right == expected.right, + "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n", + rc.top, rc.left, rc.bottom, rc.right, + expected.top, expected.left, expected.bottom, expected.right); + + MoveWindow(hwnd, 0, 0, 100, 0, FALSE); + GetClientRect(hwnd, &clientRect); + + expected = clientRect; + expected.left += 1; + expected.right -= 1; + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(rc.top == expected.top && rc.left == expected.left && + rc.bottom == expected.bottom && rc.right == expected.right, + "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n", + rc.top, rc.left, rc.bottom, rc.right, + expected.top, expected.left, expected.bottom, expected.right); + DestroyWindow(hwnd); /* The extended window style affects the formatting rectangle. */ @@ -6446,7 +6469,7 @@ static void test_WM_GETDLGCODE(void) msg.message = WM_KEYDOWN; msg.wParam = VK_RETURN; - msg.lParam = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC) | 0x0001; + msg.lParam = (MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC) << 16) | 0x0001; msg.pt.x = 0; msg.pt.y = 0; msg.time = GetTickCount(); @@ -6496,7 +6519,7 @@ static void test_WM_GETDLGCODE(void) DestroyWindow(hwnd); msg.wParam = VK_TAB; - msg.lParam = MapVirtualKey(VK_TAB, MAPVK_VK_TO_VSC) | 0x0001; + msg.lParam = (MapVirtualKey(VK_TAB, MAPVK_VK_TO_VSC) << 16) | 0x0001; hwnd = CreateWindowEx(0, RICHEDIT_CLASS, NULL, ES_MULTILINE|WS_POPUP, @@ -6547,7 +6570,7 @@ static void test_WM_GETDLGCODE(void) release_key(VK_CONTROL); msg.wParam = 'a'; - msg.lParam = MapVirtualKey('a', MAPVK_VK_TO_VSC) | 0x0001; + msg.lParam = (MapVirtualKey('a', MAPVK_VK_TO_VSC) << 16) | 0x0001; hwnd = CreateWindowEx(0, RICHEDIT_CLASS, NULL, ES_MULTILINE|WS_POPUP, @@ -7062,15 +7085,101 @@ static void test_dialogmode(void) DestroyWindow(hwParent); } +static void test_EM_FINDWORDBREAK_W(void) +{ + static const struct { + WCHAR c; + BOOL isdelimiter; /* expected result of WB_ISDELIMITER */ + } delimiter_tests[] = { + {0x0a, FALSE}, /* newline */ + {0x0b, FALSE}, /* vertical tab */ + {0x0c, FALSE}, /* form feed */ + {0x0d, FALSE}, /* carriage return */ + {0x20, TRUE}, /* space */ + {0x61, FALSE}, /* capital letter a */ + {0xa0, FALSE}, /* no-break space */ + {0x2000, FALSE}, /* en quad */ + {0x3000, FALSE}, /* Ideographic space */ + {0x1100, FALSE}, /* Hangul Choseong Kiyeok (G sound) Ordinary Letter*/ + {0x11ff, FALSE}, /* Hangul Jongseoung Kiyeok-Hieuh (Hard N sound) Ordinary Letter*/ + {0x115f, FALSE}, /* Hangul Choseong Filler (no sound, used with two letter Hangul words) Ordinary Letter */ + {0xac00, FALSE}, /* Hangul character GA*/ + {0xd7af, FALSE}, /* End of Hangul character chart */ + {0xf020, TRUE}, /* MS private for CP_SYMBOL round trip?, see kb897872 */ + {0xff20, FALSE}, /* fullwidth commercial @ */ + {WCH_EMBEDDING, FALSE}, /* object replacement character*/ + }; + int i; + HWND hwndRichEdit = new_richeditW(NULL); + ok(IsWindowUnicode(hwndRichEdit), "window should be unicode\n"); + for (i = 0; i < sizeof(delimiter_tests)/sizeof(delimiter_tests[0]); i++) + { + WCHAR wbuf[2]; + int result; + + wbuf[0] = delimiter_tests[i].c; + wbuf[1] = 0; + SendMessageW(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)wbuf); + result = SendMessageW(hwndRichEdit, EM_FINDWORDBREAK, WB_ISDELIMITER,0); + if (wbuf[0] == 0x20 || wbuf[0] == 0xf020) + todo_wine + ok(result == delimiter_tests[i].isdelimiter, + "wanted ISDELIMITER_W(0x%x) %d, got %d\n", + delimiter_tests[i].c, delimiter_tests[i].isdelimiter,result); + else + ok(result == delimiter_tests[i].isdelimiter, + "wanted ISDELIMITER_W(0x%x) %d, got %d\n", + delimiter_tests[i].c, delimiter_tests[i].isdelimiter, result); + } + DestroyWindow(hwndRichEdit); +} + +static void test_EM_FINDWORDBREAK_A(void) +{ + static const struct { + WCHAR c; + BOOL isdelimiter; /* expected result of WB_ISDELIMITER */ + } delimiter_tests[] = { + {0x0a, FALSE}, /* newline */ + {0x0b, FALSE}, /* vertical tab */ + {0x0c, FALSE}, /* form feed */ + {0x0d, FALSE}, /* carriage return */ + {0x20, TRUE}, /* space */ + {0x61, FALSE}, /* capital letter a */ + }; + int i; + HWND hwndRichEdit = new_richedit(NULL); + + ok(!IsWindowUnicode(hwndRichEdit), "window should not be unicode\n"); + for (i = 0; i < sizeof(delimiter_tests)/sizeof(delimiter_tests[0]); i++) + { + int result; + char buf[2]; + buf[0] = delimiter_tests[i].c; + buf[1] = 0; + SendMessageW(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buf); + result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_ISDELIMITER, 0); + if (buf[0] == 0x20) + todo_wine + ok(result == delimiter_tests[i].isdelimiter, + "wanted ISDELIMITER_A(0x%x) %d, got %d\n", + delimiter_tests[i].c, delimiter_tests[i].isdelimiter,result); + else + ok(result == delimiter_tests[i].isdelimiter, + "wanted ISDELIMITER_A(0x%x) %d, got %d\n", + delimiter_tests[i].c, delimiter_tests[i].isdelimiter, result); + } + DestroyWindow(hwndRichEdit); +} + START_TEST( editor ) { + BOOL ret; /* Must explicitly LoadLibrary(). The test has no references to functions in * RICHED20.DLL, so the linker doesn't actually link to it. */ hmoduleRichEdit = LoadLibrary("RICHED20.DLL"); ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); - is_win9x = GetVersion() & 0x80000000; - test_WM_CHAR(); test_EM_FINDTEXT(); test_EM_GETLINE(); @@ -7119,6 +7228,8 @@ START_TEST( editor ) test_WM_GETDLGCODE(); test_zoom(); test_dialogmode(); + test_EM_FINDWORDBREAK_W(); + test_EM_FINDWORDBREAK_A(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging. @@ -7128,5 +7239,6 @@ START_TEST( editor ) } OleFlushClipboard(); - ok(FreeLibrary(hmoduleRichEdit) != 0, "error: %d\n", (int) GetLastError()); + ret = FreeLibrary(hmoduleRichEdit); + ok(ret, "error: %d\n", (int) GetLastError()); } diff --git a/rostests/winetests/riched20/richole.c b/rostests/winetests/riched20/richole.c index 6eefdd0ffb5..ee89086416f 100644 --- a/rostests/winetests/riched20/richole.c +++ b/rostests/winetests/riched20/richole.c @@ -21,7 +21,7 @@ #define COBJMACROS #include -#include + #include #include #include diff --git a/rostests/winetests/riched20/testlist.c b/rostests/winetests/riched20/testlist.c index f74770ece73..0688dbfc303 100644 --- a/rostests/winetests/riched20/testlist.c +++ b/rostests/winetests/riched20/testlist.c @@ -7,11 +7,13 @@ #include "wine/test.h" extern void func_editor(void); +extern void func_richole(void); extern void func_txtsrv(void); const struct test winetest_testlist[] = { - { "editor", func_editor }, - { "txtsrv", func_txtsrv }, + { "editor", func_editor }, + { "richole", func_richole }, + { "txtsrv", func_txtsrv }, { 0, 0 } }; diff --git a/rostests/winetests/riched20/txtsrv.c b/rostests/winetests/riched20/txtsrv.c index 8da111de2c7..8d126ea4a95 100644 --- a/rostests/winetests/riched20/txtsrv.c +++ b/rostests/winetests/riched20/txtsrv.c @@ -35,6 +35,24 @@ #include static HMODULE hmoduleRichEdit; +static IID *pIID_ITextServices; +static IID *pIID_ITextHost; +static IID *pIID_ITextHost2; + +static const char *debugstr_guid(REFIID riid) +{ + static char buf[50]; + + if(!riid) + return "(null)"; + + sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + riid->Data1, riid->Data2, riid->Data3, riid->Data4[0], + riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4], + riid->Data4[5], riid->Data4[6], riid->Data4[7]); + + return buf; +} /* Define C Macros for ITextServices calls. */ @@ -75,17 +93,22 @@ static ITextServicesVtbl itextServicesStdcallVtbl; typedef struct ITextHostTestImpl { - ITextHostVtbl *lpVtbl; + ITextHost ITextHost_iface; LONG refCount; } ITextHostTestImpl; +static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface) +{ + return CONTAINING_RECORD(iface, ITextHostTestImpl, ITextHost_iface); +} + static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid, LPVOID *ppvObject) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ITextHost)) { + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, pIID_ITextHost)) { *ppvObject = This; ITextHost_AddRef((ITextHost *)*ppvObject); return S_OK; @@ -96,14 +119,14 @@ static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, static ULONG WINAPI ITextHostImpl_AddRef(ITextHost *iface) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); ULONG refCount = InterlockedIncrement(&This->refCount); return refCount; } static ULONG WINAPI ITextHostImpl_Release(ITextHost *iface) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); ULONG refCount = InterlockedDecrement(&This->refCount); if (!refCount) @@ -117,7 +140,7 @@ static ULONG WINAPI ITextHostImpl_Release(ITextHost *iface) static HDC WINAPI ITextHostImpl_TxGetDC(ITextHost *iface) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetDC(%p)\n", This); return NULL; } @@ -125,7 +148,7 @@ static HDC WINAPI ITextHostImpl_TxGetDC(ITextHost *iface) static INT WINAPI ITextHostImpl_TxReleaseDC(ITextHost *iface, HDC hdc) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxReleaseDC(%p)\n", This); return 0; } @@ -134,7 +157,7 @@ static BOOL WINAPI ITextHostImpl_TxShowScrollBar(ITextHost *iface, INT fnBar, BOOL fShow) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxShowScrollBar(%p, fnBar=%d, fShow=%d)\n", This, fnBar, fShow); return FALSE; @@ -144,7 +167,7 @@ static BOOL WINAPI ITextHostImpl_TxEnableScrollBar(ITextHost *iface, INT fuSBFlags, INT fuArrowflags) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxEnableScrollBar(%p, fuSBFlags=%d, fuArrowflags=%d)\n", This, fuSBFlags, fuArrowflags); return FALSE; @@ -156,7 +179,7 @@ static BOOL WINAPI ITextHostImpl_TxSetScrollRange(ITextHost *iface, INT nMaxPos, BOOL fRedraw) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetScrollRange(%p, fnBar=%d, nMinPos=%d, nMaxPos=%d, fRedraw=%d)\n", This, fnBar, nMinPos, nMaxPos, fRedraw); return FALSE; @@ -167,7 +190,7 @@ static BOOL WINAPI ITextHostImpl_TxSetScrollPos(ITextHost *iface, INT nPos, BOOL fRedraw) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetScrollPos(%p, fnBar=%d, nPos=%d, fRedraw=%d)\n", This, fnBar, nPos, fRedraw); return FALSE; @@ -177,14 +200,14 @@ static void WINAPI ITextHostImpl_TxInvalidateRect(ITextHost *iface, LPCRECT prc, BOOL fMode) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxInvalidateRect(%p, prc=%p, fMode=%d)\n", This, prc, fMode); } static void WINAPI ITextHostImpl_TxViewChange(ITextHost *iface, BOOL fUpdate) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxViewChange(%p, fUpdate=%d)\n", This, fUpdate); } @@ -193,7 +216,7 @@ static BOOL WINAPI ITextHostImpl_TxCreateCaret(ITextHost *iface, HBITMAP hbmp, INT xWidth, INT yHeight) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxCreateCaret(%p, nbmp=%p, xWidth=%d, yHeight=%d)\n", This, hbmp, xWidth, yHeight); return FALSE; @@ -201,7 +224,7 @@ static BOOL WINAPI ITextHostImpl_TxCreateCaret(ITextHost *iface, static BOOL WINAPI ITextHostImpl_TxShowCaret(ITextHost *iface, BOOL fShow) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxShowCaret(%p, fShow=%d)\n", This, fShow); return FALSE; @@ -210,7 +233,7 @@ static BOOL WINAPI ITextHostImpl_TxShowCaret(ITextHost *iface, BOOL fShow) static BOOL WINAPI ITextHostImpl_TxSetCaretPos(ITextHost *iface, INT x, INT y) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetCaretPos(%p, x=%d, y=%d)\n", This, x, y); return FALSE; } @@ -218,7 +241,7 @@ static BOOL WINAPI ITextHostImpl_TxSetCaretPos(ITextHost *iface, static BOOL WINAPI ITextHostImpl_TxSetTimer(ITextHost *iface, UINT idTimer, UINT uTimeout) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetTimer(%p, idTimer=%u, uTimeout=%u)\n", This, idTimer, uTimeout); return FALSE; @@ -226,7 +249,7 @@ static BOOL WINAPI ITextHostImpl_TxSetTimer(ITextHost *iface, static void WINAPI ITextHostImpl_TxKillTimer(ITextHost *iface, UINT idTimer) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxKillTimer(%p, idTimer=%u)\n", This, idTimer); } @@ -238,20 +261,20 @@ static void WINAPI ITextHostImpl_TxScrollWindowEx(ITextHost *iface, LPRECT lprcUpdate, UINT fuScroll) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxScrollWindowEx(%p, %d, %d, %p, %p, %p, %p, %d)\n", This, dx, dy, lprcScroll, lprcClip, hRgnUpdate, lprcUpdate, fuScroll); } static void WINAPI ITextHostImpl_TxSetCapture(ITextHost *iface, BOOL fCapture) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetCapture(%p, fCapture=%d)\n", This, fCapture); } static void WINAPI ITextHostImpl_TxSetFocus(ITextHost *iface) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetFocus(%p)\n", This); } @@ -259,7 +282,7 @@ static void WINAPI ITextHostImpl_TxSetCursor(ITextHost *iface, HCURSOR hcur, BOOL fText) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxSetCursor(%p, hcur=%p, fText=%d)\n", This, hcur, fText); } @@ -267,7 +290,7 @@ static void WINAPI ITextHostImpl_TxSetCursor(ITextHost *iface, static BOOL WINAPI ITextHostImpl_TxScreenToClient(ITextHost *iface, LPPOINT lppt) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxScreenToClient(%p, lppt=%p)\n", This, lppt); return FALSE; } @@ -275,7 +298,7 @@ static BOOL WINAPI ITextHostImpl_TxScreenToClient(ITextHost *iface, static BOOL WINAPI ITextHostImpl_TxClientToScreen(ITextHost *iface, LPPOINT lppt) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxClientToScreen(%p, lppt=%p)\n", This, lppt); return FALSE; } @@ -283,7 +306,7 @@ static BOOL WINAPI ITextHostImpl_TxClientToScreen(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxActivate(ITextHost *iface, LONG *plOldState) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxActivate(%p, plOldState=%p)\n", This, plOldState); return E_NOTIMPL; } @@ -291,7 +314,7 @@ static HRESULT WINAPI ITextHostImpl_TxActivate(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxDeactivate(ITextHost *iface, LONG lNewState) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxDeactivate(%p, lNewState=%d)\n", This, lNewState); return E_NOTIMPL; } @@ -299,7 +322,7 @@ static HRESULT WINAPI ITextHostImpl_TxDeactivate(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetClientRect(ITextHost *iface, LPRECT prc) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetClientRect(%p, prc=%p)\n", This, prc); return E_NOTIMPL; } @@ -307,7 +330,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetClientRect(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetViewInset(ITextHost *iface, LPRECT prc) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetViewInset(%p, prc=%p)\n", This, prc); return E_NOTIMPL; } @@ -315,7 +338,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetViewInset(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetCharFormat(ITextHost *iface, const CHARFORMATW **ppCF) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetCharFormat(%p, ppCF=%p)\n", This, ppCF); return E_NOTIMPL; } @@ -323,7 +346,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetCharFormat(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetParaFormat(ITextHost *iface, const PARAFORMAT **ppPF) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetParaFormat(%p, ppPF=%p)\n", This, ppPF); return E_NOTIMPL; } @@ -331,7 +354,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetParaFormat(ITextHost *iface, static COLORREF WINAPI ITextHostImpl_TxGetSysColor(ITextHost *iface, int nIndex) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetSysColor(%p, nIndex=%d)\n", This, nIndex); return E_NOTIMPL; } @@ -339,7 +362,7 @@ static COLORREF WINAPI ITextHostImpl_TxGetSysColor(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetBackStyle(ITextHost *iface, TXTBACKSTYLE *pStyle) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetBackStyle(%p, pStyle=%p)\n", This, pStyle); return E_NOTIMPL; } @@ -347,7 +370,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetBackStyle(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetMaxLength(ITextHost *iface, DWORD *pLength) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetMaxLength(%p, pLength=%p)\n", This, pLength); return E_NOTIMPL; } @@ -355,7 +378,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetMaxLength(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *pdwScrollBar) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetScrollBars(%p, pdwScrollBar=%p)\n", This, pdwScrollBar); return E_NOTIMPL; @@ -364,7 +387,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetScrollBars(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetPasswordChar(ITextHost *iface, WCHAR *pch) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetPasswordChar(%p, pch=%p)\n", This, pch); return E_NOTIMPL; } @@ -372,7 +395,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetPasswordChar(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetAcceleratorPos(ITextHost *iface, LONG *pch) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetAcceleratorPos(%p, pch=%p)\n", This, pch); return E_NOTIMPL; } @@ -380,7 +403,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetAcceleratorPos(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxGetExtent(ITextHost *iface, LPSIZEL lpExtent) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetExtent(%p, lpExtent=%p)\n", This, lpExtent); return E_NOTIMPL; } @@ -388,7 +411,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetExtent(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_OnTxCharFormatChange(ITextHost *iface, const CHARFORMATW *pcf) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to OnTxCharFormatChange(%p, pcf=%p)\n", This, pcf); return E_NOTIMPL; } @@ -396,7 +419,7 @@ static HRESULT WINAPI ITextHostImpl_OnTxCharFormatChange(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_OnTxParaFormatChange(ITextHost *iface, const PARAFORMAT *ppf) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to OnTxParaFormatChange(%p, ppf=%p)\n", This, ppf); return E_NOTIMPL; } @@ -407,7 +430,7 @@ static HRESULT WINAPI ITextHostImpl_TxGetPropertyBits(ITextHost *iface, DWORD dwMask, DWORD *pdwBits) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetPropertyBits(%p, dwMask=0x%08x, pdwBits=%p)\n", This, dwMask, pdwBits); *pdwBits = 0; @@ -417,31 +440,31 @@ static HRESULT WINAPI ITextHostImpl_TxGetPropertyBits(ITextHost *iface, static HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, DWORD iNotify, void *pv) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This, iNotify, pv); return E_NOTIMPL; } static HIMC WINAPI ITextHostImpl_TxImmGetContext(ITextHost *iface) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxImmGetContext(%p)\n", This); return 0; } static void WINAPI ITextHostImpl_TxImmReleaseContext(ITextHost *iface, HIMC himc) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxImmReleaseContext(%p, himc=%p)\n", This, himc); } /* This function must set the variable pointed to by *lSelBarWidth. - Otherwise an uninitalized value will be used to calculate + Otherwise an uninitialized value will be used to calculate positions and sizes even if E_NOTIMPL is returned. */ static HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface, LONG *lSelBarWidth) { - ITextHostTestImpl *This = (ITextHostTestImpl *)iface; + ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetSelectionBarWidth(%p, lSelBarWidth=%p)\n", This, lSelBarWidth); *lSelBarWidth = 0; @@ -604,24 +627,24 @@ static BOOL init_texthost(void) skip("Insufficient memory to create ITextHost interface\n"); return FALSE; } - dummyTextHost->lpVtbl = &itextHostVtbl; + dummyTextHost->ITextHost_iface.lpVtbl = &itextHostVtbl; dummyTextHost->refCount = 1; /* MSDN states that an IUnknown object is returned by CreateTextServices which is then queried to obtain a ITextServices object. */ pCreateTextServices = (void*)GetProcAddress(hmoduleRichEdit, "CreateTextServices"); - result = (*pCreateTextServices)(NULL,(ITextHost*)dummyTextHost, &init); - ok(result == S_OK, "Did not return OK when created. Returned %x\n", result); + result = (*pCreateTextServices)(NULL, &dummyTextHost->ITextHost_iface, &init); + ok(result == S_OK, "Did not return S_OK when created (result = %x)\n", result); if (result != S_OK) { CoTaskMemFree(dummyTextHost); skip("CreateTextServices failed.\n"); return FALSE; } - result = IUnknown_QueryInterface(init, &IID_ITextServices, + result = IUnknown_QueryInterface(init, pIID_ITextServices, (void **)&txtserv); - ok((result == S_OK) && (txtserv != NULL), "Querying interface failed\n"); + ok((result == S_OK) && (txtserv != NULL), "Querying interface failed (result = %x, txtserv = %p)\n", result, txtserv); IUnknown_Release(init); if (!((result == S_OK) && (txtserv != NULL))) { CoTaskMemFree(dummyTextHost); @@ -632,6 +655,12 @@ static BOOL init_texthost(void) return TRUE; } +static void free_texthost(void) +{ + IUnknown_Release(txtserv); + CoTaskMemFree(dummyTextHost); +} + static void test_TxGetText(void) { HRESULT hres; @@ -641,10 +670,9 @@ static void test_TxGetText(void) return; hres = ITextServices_TxGetText(txtserv, &rettext); - ok(hres == S_OK, "ITextServices_TxGetText failed\n"); + ok(hres == S_OK, "ITextServices_TxGetText failed (result = %x)\n", hres); - IUnknown_Release(txtserv); - CoTaskMemFree(dummyTextHost); + free_texthost(); } static void test_TxSetText(void) @@ -657,19 +685,18 @@ static void test_TxSetText(void) return; hres = ITextServices_TxSetText(txtserv, settext); - ok(hres == S_OK, "ITextServices_TxSetText failed\n"); + ok(hres == S_OK, "ITextServices_TxSetText failed (result = %x)\n", hres); hres = ITextServices_TxGetText(txtserv, &rettext); - ok(hres == S_OK, "ITextServices_TxGetText failed\n"); + ok(hres == S_OK, "ITextServices_TxGetText failed (result = %x)\n", hres); ok(SysStringLen(rettext) == 4, - "String returned of wrong length\n"); + "String returned of wrong length (expected 4, got %d)\n", SysStringLen(rettext)); ok(memcmp(rettext,settext,SysStringByteLen(rettext)) == 0, "String returned differs\n"); SysFreeString(rettext); - IUnknown_Release(txtserv); - CoTaskMemFree(dummyTextHost); + free_texthost(); } static void test_TxGetNaturalSize(void) { @@ -708,9 +735,7 @@ static void test_TxGetNaturalSize(void) { ret = GetCharWidth32(hdcDraw,'A','Z',charwidth_caps_text); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("GetCharWidth32 is not available\n"); - RestoreDC(hdcDraw,1); - ReleaseDC(NULL,hdcDraw); - return; + goto cleanup; } /* Make measurements in MM_TEXT */ @@ -718,13 +743,20 @@ static void test_TxGetNaturalSize(void) { xdim = 0; ydim = 0; result = ITextServices_TxSetText(txtserv, oneA); - ok(result == S_OK, "ITextServices_TxSetText failed\n"); + ok(result == S_OK, "ITextServices_TxSetText failed (result = %x)\n", result); + if (result != S_OK) { + skip("Could not set text\n"); + goto cleanup; + } + SetLastError(0xdeadbeef); result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT, hdcDraw, NULL, NULL, TXTNS_FITTOCONTENT, &psizelExtent, &xdim, &ydim); - todo_wine ok(result == S_OK, "TxGetNaturalSize failed\n"); + todo_wine ok(result == S_OK || broken(result == E_FAIL), /* WINXP Arabic Language */ + "TxGetNaturalSize gave unexpected return value (result = %x)\n", result); + if (result == S_OK) { todo_wine ok(ydim == tmInfo_text.tmHeight, "Height calculated incorrectly (expected %d, got %d)\n", tmInfo_text.tmHeight, ydim); @@ -732,12 +764,14 @@ static void test_TxGetNaturalSize(void) { todo_wine ok(xdim >= charwidth_caps_text[0] && xdim <= charwidth_caps_text[0] + 1, "Width calculated incorrectly (expected %d {+1}, got %d)\n", charwidth_caps_text[0], xdim); + } else + skip("TxGetNaturalSize measurements not performed (xdim = %d, ydim = %d, result = %x, error = %x)\n", + xdim, ydim, result, GetLastError()); +cleanup: RestoreDC(hdcDraw,1); ReleaseDC(NULL,hdcDraw); - - IUnknown_Release(txtserv); - CoTaskMemFree(dummyTextHost); + free_texthost(); } static void test_TxDraw(void) @@ -757,14 +791,28 @@ static void test_TxDraw(void) result = ITextServices_TxDraw(txtserv, dwAspect, 0, pvAspect, ptd, tmphdc, hicTargetDev, &client, NULL, NULL, NULL, 0, 0); - ok(result == S_OK, "TxDraw failed\n"); + ok(result == S_OK, "TxDraw failed (result = %x)\n", result); } - IUnknown_Release(txtserv); - CoTaskMemFree(dummyTextHost); + free_texthost(); + +} + +DEFINE_GUID(expected_iid_itextservices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5); +DEFINE_GUID(expected_iid_itexthost, 0x13e670f4,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1); +DEFINE_GUID(expected_iid_itexthost2, 0x13e670f5,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1); +static void test_IIDs(void) +{ + ok(IsEqualIID(pIID_ITextServices, &expected_iid_itextservices), + "unexpected value for IID_ITextServices: %s\n", debugstr_guid(pIID_ITextServices)); + ok(IsEqualIID(pIID_ITextHost, &expected_iid_itexthost), + "unexpected value for IID_ITextHost: %s\n", debugstr_guid(pIID_ITextHost)); + ok(IsEqualIID(pIID_ITextHost2, &expected_iid_itexthost2), + "unexpected value for IID_ITextHost2: %s\n", debugstr_guid(pIID_ITextHost2)); } + START_TEST( txtsrv ) { setup_thiscall_wrappers(); @@ -774,10 +822,14 @@ START_TEST( txtsrv ) hmoduleRichEdit = LoadLibrary("RICHED20.DLL"); ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); + pIID_ITextServices = (IID*)GetProcAddress(hmoduleRichEdit, "IID_ITextServices"); + pIID_ITextHost = (IID*)GetProcAddress(hmoduleRichEdit, "IID_ITextHost"); + pIID_ITextHost2 = (IID*)GetProcAddress(hmoduleRichEdit, "IID_ITextHost2"); + test_IIDs(); + if (init_texthost()) { - IUnknown_Release(txtserv); - CoTaskMemFree(dummyTextHost); + free_texthost(); test_TxGetText(); test_TxSetText();