diff --git a/rostests/winetests/riched20/editor.c b/rostests/winetests/riched20/editor.c index e32d403097b..3db9b232de0 100644 --- a/rostests/winetests/riched20/editor.c +++ b/rostests/winetests/riched20/editor.c @@ -601,6 +601,7 @@ static void test_EM_POSFROMCHAR(void) POINTL pt; LOCALESIGNATURE sig; BOOL rtl; + PARAFORMAT2 fmt; static const char text[] = "aa\n" "this is a long line of text that should be longer than the " "control's width\n" @@ -727,6 +728,18 @@ static void test_EM_POSFROMCHAR(void) SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, -1); ok(pt.x == 1, "pt.x = %d\n", pt.x); + /* test negative indentation */ + SendMessageA(hwndRichEdit, WM_SETTEXT, 0, + (LPARAM)"{\\rtf1\\pard\\fi-200\\li-200\\f1 TestSomeText\\par}"); + SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, 0); + ok(pt.x == 1, "pt.x = %d\n", pt.x); + + fmt.cbSize = sizeof(fmt); + SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt); + ok(fmt.dxStartIndent == -400, "got %d\n", fmt.dxStartIndent); + ok(fmt.dxOffset == 200, "got %d\n", fmt.dxOffset); + ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment); + DestroyWindow(hwndRichEdit); } @@ -3281,11 +3294,12 @@ static void test_EM_SETUNDOLIMIT(void) SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"x"); cr.cpMin = 0; - cr.cpMax = 1; + cr.cpMax = -1; + SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr); + SendMessageA(hwndRichEdit, WM_COPY, 0, 0); /*Load "x" into the clipboard. Paste is an easy, undo'able operation. also, multiple pastes don't combine like WM_CHAR would */ - SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr); /* first case - check the default */ SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0); @@ -3808,7 +3822,7 @@ static void test_EM_SETTEXTEX(void) getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; getText.lpUsedDefChar = NULL; - memset(buf, 0, MAX_BUF_LEN); + memset(buf, 0, sizeof(buf)); SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf); ok(lstrcmpW(buf, TestItem2) == 0, "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); @@ -3823,7 +3837,7 @@ static void test_EM_SETTEXTEX(void) getText.flags = GT_USECRLF; /* <-- asking for CR -> CRLF conversion */ getText.lpDefaultChar = NULL; getText.lpUsedDefChar = NULL; - memset(buf, 0, MAX_BUF_LEN); + memset(buf, 0, sizeof(buf)); SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf); ok(lstrcmpW(buf, TestItem1) == 0, "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); @@ -5032,7 +5046,7 @@ static void test_EM_REPLACESEL(int redraw) todo_wine ok(!strcmp(buffer, "WTestSomeTextne"), "WM_GETTEXT returned incorrect string\n"); if (!redraw) - /* This is needed to avoid interferring with keybd_event calls + /* This is needed to avoid interfering with keybd_event calls * on other tests that simulate keyboard events. */ SendMessageA(hwndRichEdit, WM_SETREDRAW, TRUE, 0); @@ -5403,9 +5417,10 @@ static void test_EM_STREAMIN(void) EDITSTREAM es; char buffer[1024] = {0}, tmp[16]; CHARRANGE range; + PARAFORMAT2 fmt; - const char * streamText0 = "{\\rtf1 TestSomeText}"; - const char * streamText0a = "{\\rtf1 TestSomeText\\par}"; + const char * streamText0 = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText}"; + const char * streamText0a = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText\\par}"; const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}"; const char * ptr; @@ -5462,6 +5477,17 @@ static void test_EM_STREAMIN(void) ok (result == 0, "EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer); ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0); + /* Show that para fmts are ignored */ + range.cpMin = 2; + range.cpMax = 2; + result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range); + memset(&fmt, 0xcc, sizeof(fmt)); + fmt.cbSize = sizeof(fmt); + result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt); + ok(fmt.dxStartIndent == 0, "got %d\n", fmt.dxStartIndent); + ok(fmt.dxOffset == 0, "got %d\n", fmt.dxOffset); + ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment); + ok((fmt.wEffects & PFE_RTLPARA) == 0, "got %x\n", fmt.wEffects); /* Native richedit 2.0 ignores last \par */ ptr = streamText0a; @@ -5478,6 +5504,17 @@ static void test_EM_STREAMIN(void) ok (result == 0, "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer); ok(es.dwError == 0, "EM_STREAMIN: Test 0-a set error %d, expected %d\n", es.dwError, 0); + /* This time para fmts are processed */ + range.cpMin = 2; + range.cpMax = 2; + result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range); + memset(&fmt, 0xcc, sizeof(fmt)); + fmt.cbSize = sizeof(fmt); + result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt); + ok(fmt.dxStartIndent == 300, "got %d\n", fmt.dxStartIndent); + ok(fmt.dxOffset == -100, "got %d\n", fmt.dxOffset); + ok(fmt.wAlignment == PFA_RIGHT, "got %d\n", fmt.wAlignment); + ok((fmt.wEffects & PFE_RTLPARA) == PFE_RTLPARA, "got %x\n", fmt.wEffects); /* Native richedit 2.0 ignores last \par, next-to-last \par appears */ es.dwCookie = (DWORD_PTR)&streamText0b; @@ -8219,7 +8256,7 @@ static void test_alignment_style(void) pf.cbSize = sizeof(PARAFORMAT2); pf.dwMask = -1; SendMessageW(richedit, EM_GETPARAFORMAT, SCF_SELECTION, (LPARAM)&pf); - ok(pf.wAlignment == ES_CENTER, "got %d expected ES_CENTER\n", pf.wAlignment); + ok(pf.wAlignment == PFA_LEFT, "got %d expected PFA_LEFT\n", pf.wAlignment); DestroyWindow(richedit); } @@ -8254,6 +8291,96 @@ static void test_WM_GETTEXTLENGTH(void) DestroyWindow(hwndRichEdit); } +static void test_rtf_specials(void) +{ + const char *specials = "{\\rtf1\\emspace\\enspace\\bullet\\lquote" + "\\rquote\\ldblquote\\rdblquote\\ltrmark\\rtlmark\\zwj\\zwnj}"; + const WCHAR expect_specials[] = {' ',' ',0x2022,0x2018,0x2019,0x201c, + 0x201d,0x200e,0x200f,0x200d,0x200c}; + const char *pard = "{\\rtf1 ABC\\rtlpar\\par DEF\\par HIJ\\pard\\par}"; + HWND edit = new_richeditW( NULL ); + EDITSTREAM es; + WCHAR buf[80]; + LRESULT result; + PARAFORMAT2 fmt; + + es.dwCookie = (DWORD_PTR)&specials; + es.dwError = 0; + es.pfnCallback = test_EM_STREAMIN_esCallback; + result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es ); + ok( result == 11, "got %ld\n", result ); + + result = SendMessageW( edit, WM_GETTEXT, sizeof(buf)/sizeof(buf[0]), (LPARAM)buf ); + ok( result == sizeof(expect_specials)/sizeof(expect_specials[0]), "got %ld\n", result ); + ok( !memcmp( buf, expect_specials, sizeof(expect_specials) ), "got %s\n", wine_dbgstr_w(buf) ); + + /* Show that \rtlpar propagates to the second paragraph and is + reset by \pard in the third. */ + es.dwCookie = (DWORD_PTR)&pard; + result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es ); + ok( result == 11, "got %ld\n", result ); + + fmt.cbSize = sizeof(fmt); + SendMessageW( edit, EM_SETSEL, 1, 1 ); + SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt ); + ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" ); + ok( fmt.wEffects & PFE_RTLPARA, "rtl para not set\n" ); + SendMessageW( edit, EM_SETSEL, 5, 5 ); + SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt ); + ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" ); + ok( fmt.wEffects & PFE_RTLPARA, "rtl para not set\n" ); + SendMessageW( edit, EM_SETSEL, 9, 9 ); + SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt ); + ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" ); + ok( !(fmt.wEffects & PFE_RTLPARA), "rtl para set\n" ); + + DestroyWindow( edit ); +} + +static void test_background(void) +{ + HWND hwndRichEdit = new_richedit(NULL); + + /* set the background color to black */ + ValidateRect(hwndRichEdit, NULL); + SendMessageA(hwndRichEdit, EM_SETBKGNDCOLOR, FALSE, RGB(0, 0, 0)); + ok(GetUpdateRect(hwndRichEdit, NULL, FALSE), "Update rectangle is empty!\n"); + + DestroyWindow(hwndRichEdit); +} + +static void test_window_classes(void) +{ + static const struct + { + const char *class; + BOOL success; + } test[] = + { + { "RichEdit", FALSE }, + { "RichEdit20A", TRUE }, + { "RichEdit20W", TRUE }, + { "RichEdit50A", FALSE }, + { "RichEdit50W", FALSE } + }; + int i; + HWND hwnd; + + for (i = 0; i < sizeof(test)/sizeof(test[0]); i++) + { + SetLastError(0xdeadbeef); + hwnd = CreateWindowExA(0, test[i].class, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL); +todo_wine_if(!strcmp(test[i].class, "RichEdit50A") || !strcmp(test[i].class, "RichEdit50W")) + ok(!hwnd == !test[i].success, "CreateWindow(%s) should %s\n", + test[i].class, test[i].success ? "succeed" : "fail"); + if (!hwnd) +todo_wine + ok(GetLastError() == ERROR_CANNOT_FIND_WND_CLASS, "got %d\n", GetLastError()); + else + DestroyWindow(hwnd); + } +} + START_TEST( editor ) { BOOL ret; @@ -8263,6 +8390,7 @@ START_TEST( editor ) ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); is_lang_japanese = (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE); + test_window_classes(); test_WM_CHAR(); test_EM_FINDTEXT(FALSE); test_EM_FINDTEXT(TRUE); @@ -8323,6 +8451,8 @@ START_TEST( editor ) test_EM_SETREADONLY(); test_EM_SETFONTSIZE(); test_alignment_style(); + test_rtf_specials(); + test_background(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging. diff --git a/rostests/winetests/riched20/richole.c b/rostests/winetests/riched20/richole.c index bbc04ee41bd..38a8f8039e9 100644 --- a/rostests/winetests/riched20/richole.c +++ b/rostests/winetests/riched20/richole.c @@ -53,6 +53,7 @@ static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) HWND 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; } @@ -761,6 +762,65 @@ static void test_ITextRange_GetChar(void) ITextRange_Release(txtRge); } +/* Helper function for testing ITextRange_ScrollIntoView */ +static void check_range(HWND w, ITextDocument* doc, int first, int lim, + LONG bStart, int expected_nonzero) +{ + SCROLLINFO si; + ITextRange *txtRge = NULL; + HRESULT hres; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE; + + hres = ITextDocument_Range(doc, first, lim, &txtRge); + ok(hres == S_OK, "got 0x%08x\n", hres); + hres = ITextRange_ScrollIntoView(txtRge, bStart); + ok(hres == S_OK, "got 0x%08x\n", hres); + GetScrollInfo(w, SB_VERT, &si); + if (expected_nonzero) { + ok(si.nPos != 0, + "Scrollbar at 0, should be >0. (TextRange %d-%d, scroll range %d-%d.)\n", + first, lim, si.nMin, si.nMax); + } else { + ok(si.nPos == 0, + "Scrollbar at %d, should be 0. (TextRange %d-%d, scroll range %d-%d.)\n", + si.nPos, first, lim, si.nMin, si.nMax); + } +} + +static void test_ITextRange_ScrollIntoView(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + HRESULT hres; + static const CHAR test_text1[] = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10"; + + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + /* Scroll to the top. */ + check_range(w, txtDoc, 0, 1, tomStart, 0); + + /* Scroll to the bottom. */ + check_range(w, txtDoc, 19, 20, tomStart, 1); + + /* Back up to the top. */ + check_range(w, txtDoc, 0, 1, tomStart, 0); + + /* Large range */ + check_range(w, txtDoc, 0, 20, tomStart, 0); + + hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge); + ok(hres == S_OK, "got 0x%08x\n", hres); + release_interfaces(&w, &reOle, &txtDoc, NULL); + hres = ITextRange_ScrollIntoView(txtRge, tomStart); + ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres); + ITextRange_Release(txtRge); +} + static void test_ITextSelection_GetChar(void) { HWND w; @@ -3801,6 +3861,7 @@ START_TEST(richole) test_ITextSelection_GetStoryLength(); test_ITextDocument_Range(); test_ITextRange_GetChar(); + test_ITextRange_ScrollIntoView(); test_ITextRange_GetStart_GetEnd(); test_ITextRange_GetDuplicate(); test_ITextRange_SetStart();