diff --git a/rostests/winetests/riched20/editor.c b/rostests/winetests/riched20/editor.c index 1e588576815..847b25c082a 100644 --- a/rostests/winetests/riched20/editor.c +++ b/rostests/winetests/riched20/editor.c @@ -4362,7 +4362,9 @@ const struct exsetsel_s exsetsel_tests[] = { {5, 10, 10, 5, 10, 0}, {15, 17, 17, 15, 17, 0}, /* test cpMax > strlen() */ - {0, 100, 18, 0, 18, 1}, + {0, 100, 18, 0, 18, 0}, + /* test cpMin < 0 && cpMax >= 0 after cpMax > strlen() */ + {-1, 1, 17, 17, 17, 0}, /* test cpMin == cpMax */ {5, 5, 5, 5, 5, 0}, /* test cpMin < 0 && cpMax >= 0 (bug 4462) */ @@ -4372,13 +4374,13 @@ const struct exsetsel_s exsetsel_tests[] = { /* test cpMin < 0 && cpMax < 0 */ {-1, -1, 17, 17, 17, 0}, {-4, -5, 17, 17, 17, 0}, - /* test cMin >=0 && cpMax < 0 (bug 6814) */ - {0, -1, 18, 0, 18, 1}, - {17, -5, 18, 17, 18, 1}, + /* test cpMin >=0 && cpMax < 0 (bug 6814) */ + {0, -1, 18, 0, 18, 0}, + {17, -5, 18, 17, 18, 0}, {18, -3, 17, 17, 17, 0}, /* test if cpMin > cpMax */ - {15, 19, 18, 15, 18, 1}, - {19, 15, 18, 15, 18, 1} + {15, 19, 18, 15, 18, 0}, + {19, 15, 18, 15, 18, 0}, }; static void check_EM_EXSETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id) { @@ -5070,11 +5072,13 @@ static void test_EM_STREAMIN(void) DWORD phase; LRESULT result; EDITSTREAM es; - char buffer[1024] = {0}; + char buffer[1024] = {0}, tmp[16]; + CHARRANGE range; const char * streamText0 = "{\\rtf1 TestSomeText}"; const char * streamText0a = "{\\rtf1 TestSomeText\\par}"; const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}"; + const char * ptr; const char * streamText1 = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n" @@ -5099,6 +5103,9 @@ static void test_EM_STREAMIN(void) "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"; + + const WCHAR UTF8Split_exp[4] = {0xd6, 0xcf, 0xcb, 0}; + int length4 = strlen(streamText4) + 1; struct StringWithLength cookieForStream4 = { length4, @@ -5128,7 +5135,8 @@ static void test_EM_STREAMIN(void) ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0); /* Native richedit 2.0 ignores last \par */ - es.dwCookie = (DWORD_PTR)&streamText0a; + ptr = streamText0a; + es.dwCookie = (DWORD_PTR)&ptr; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback; result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); @@ -5157,6 +5165,43 @@ static void test_EM_STREAMIN(void) "EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer); ok(es.dwError == 0, "EM_STREAMIN: Test 0-b set error %d, expected %d\n", es.dwError, 0); + /* Show that when using SFF_SELECTION the last \par is not ignored. */ + ptr = streamText0a; + es.dwCookie = (DWORD_PTR)&ptr; + es.dwError = 0; + es.pfnCallback = test_EM_STREAMIN_esCallback; + result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es); + ok(result == 12, "got %ld, expected %d\n", result, 12); + + result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer); + ok (result == 12, + "EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result); + result = strcmp (buffer,"TestSomeText"); + 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); + + range.cpMin = 0; + range.cpMax = -1; + result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range); + ok (result == 13, "got %ld\n", result); + + ptr = streamText0a; + es.dwCookie = (DWORD_PTR)&ptr; + es.dwError = 0; + es.pfnCallback = test_EM_STREAMIN_esCallback; + + result = SendMessageA(hwndRichEdit, EM_STREAMIN, SFF_SELECTION | SF_RTF, (LPARAM)&es); + ok(result == 13, "got %ld, expected 13\n", result); + + result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer); + ok (result == 14, + "EM_STREAMIN: Test SFF_SELECTION 0-a returned %ld, expected 14\n", result); + result = strcmp (buffer,"TestSomeText\r\n"); + ok (result == 0, + "EM_STREAMIN: Test SFF_SELECTION 0-a set wrong text: Result: %s\n",buffer); + ok(es.dwError == 0, "EM_STREAMIN: Test SFF_SELECTION 0-a set error %d, expected %d\n", es.dwError, 0); + es.dwCookie = (DWORD_PTR)&streamText1; es.dwError = 0; es.pfnCallback = test_EM_STREAMIN_esCallback; @@ -5216,10 +5261,12 @@ static void test_EM_STREAMIN(void) result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es); ok(result == 8, "got %ld\n", result); + WideCharToMultiByte(CP_ACP, 0, UTF8Split_exp, -1, tmp, sizeof(tmp), NULL, NULL); + result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer); ok(result == 3, "EM_STREAMIN: Test UTF8Split returned %ld\n", result); - result = memcmp (buffer,"\xd6\xcf\xcb", 3); + result = memcmp (buffer, tmp, 3); ok(result == 0, "EM_STREAMIN: Test UTF8Split set wrong text: Result: %s\n",buffer); ok(es.dwError == 0, "EM_STREAMIN: Test UTF8Split set error %d, expected %d\n", es.dwError, 0); @@ -5891,6 +5938,62 @@ static void test_WM_NOTIFY(void) DestroyWindow(parent); } +static int cpMin_EN_LINK = -1; +static int cpMax_EN_LINK = -1; + +static LRESULT WINAPI EN_LINK_ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + ENLINK* enlink = (ENLINK*)lParam; + if(message == WM_NOTIFY && enlink->nmhdr.code == EN_LINK) + { + cpMin_EN_LINK = enlink->chrg.cpMin; + cpMax_EN_LINK = enlink->chrg.cpMax; + } + return DefWindowProcA(hwnd, message, wParam, lParam); +} + +static void test_EN_LINK(void) +{ + HWND parent; + WNDCLASSA cls; + HWND hwndRichedit_EN_LINK; + CHARFORMAT2A cf2; + + /* register class to capture WM_NOTIFY */ + cls.style = 0; + cls.lpfnWndProc = EN_LINK_ParentMsgCheckProcA; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "EN_LINK_ParentClass"; + if(!RegisterClassA(&cls)) assert(0); + + parent = CreateWindowA(cls.lpszClassName, NULL, WS_POPUP|WS_VISIBLE, + 0, 0, 200, 60, NULL, NULL, NULL, NULL); + ok(parent != 0, "Failed to create parent window\n"); + + hwndRichedit_EN_LINK = new_richedit(parent); + ok(hwndRichedit_EN_LINK != 0, "Failed to create edit window\n"); + + SendMessageA(hwndRichedit_EN_LINK, EM_SETEVENTMASK, 0, ENM_LINK); + + cf2.cbSize = sizeof(CHARFORMAT2A); + cf2.dwMask = CFM_LINK; + cf2.dwEffects = CFE_LINK; + SendMessageA(hwndRichedit_EN_LINK, EM_SETCHARFORMAT, 0, (LPARAM)&cf2); + /* mixing letters and numbers causes runs to be split */ + SendMessageA(hwndRichedit_EN_LINK, WM_SETTEXT, 0, (LPARAM)"link text with at least 2 runs"); + SendMessageA(hwndRichedit_EN_LINK, WM_LBUTTONDOWN, 0, MAKELPARAM(5, 5)); + ok(cpMin_EN_LINK == 0 && cpMax_EN_LINK == 31, "Expected link range [0,31) got [%i,%i)\n", cpMin_EN_LINK, cpMax_EN_LINK); + + DestroyWindow(hwndRichedit_EN_LINK); + DestroyWindow(parent); +} + static void test_undo_coalescing(void) { HWND hwnd; @@ -7474,6 +7577,25 @@ static void test_reset_default_para_fmt( void ) DestroyWindow( richedit ); } +static void test_EM_SETREADONLY(void) +{ + HWND richedit = new_richeditW(NULL); + DWORD dwStyle; + LRESULT res; + + res = SendMessageA(richedit, EM_SETREADONLY, TRUE, 0); + ok(res == 1, "EM_SETREADONLY\n"); + dwStyle = GetWindowLongA(richedit, GWL_STYLE); + ok(dwStyle & ES_READONLY, "got wrong value: 0x%x\n", dwStyle & ES_READONLY); + + res = SendMessageA(richedit, EM_SETREADONLY, FALSE, 0); + ok(res == 1, "EM_SETREADONLY\n"); + dwStyle = GetWindowLongA(richedit, GWL_STYLE); + ok(!(dwStyle & ES_READONLY), "got wrong value: 0x%x\n", dwStyle & ES_READONLY); + + DestroyWindow(richedit); +} + START_TEST( editor ) { BOOL ret; @@ -7519,6 +7641,7 @@ START_TEST( editor ) test_EM_REPLACESEL(1); test_EM_REPLACESEL(0); test_WM_NOTIFY(); + test_EN_LINK(); test_EM_AUTOURLDETECT(); test_eventMask(); test_undo_coalescing(); @@ -7536,6 +7659,7 @@ START_TEST( editor ) test_enter(); test_WM_CREATE(); test_reset_default_para_fmt(); + test_EM_SETREADONLY(); /* 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 5a3ffbe8e6a..eed335c2560 100644 --- a/rostests/winetests/riched20/richole.c +++ b/rostests/winetests/riched20/richole.c @@ -86,21 +86,29 @@ static void create_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txt static void release_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc, ITextSelection **txtSel) { + if(txtSel) + ITextSelection_Release(*txtSel); ITextDocument_Release(*txtDoc); IRichEditOle_Release(*reOle); DestroyWindow(*w); - ITextSelection_Release(*txtSel); +} + +static ULONG get_refcount(IUnknown *iface) +{ + IUnknown_AddRef(iface); + return IUnknown_Release(iface); } static void test_Interfaces(void) { - IRichEditOle *reOle = NULL; + IRichEditOle *reOle = NULL, *reOle1 = NULL; ITextDocument *txtDoc = NULL; ITextSelection *txtSel = NULL; IUnknown *punk; HRESULT hres; LRESULT res; HWND w; + ULONG refcount; w = new_richedit(NULL); if (!w) { @@ -111,6 +119,14 @@ static void test_Interfaces(void) res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle); ok(res, "SendMessage\n"); ok(reOle != NULL, "EM_GETOLEINTERFACE\n"); + refcount = get_refcount((IUnknown *)reOle); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + + res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle1); + ok(res == 1, "SendMessage\n"); + ok(reOle1 == reOle, "Should not return a new IRichEditOle interface\n"); + refcount = get_refcount((IUnknown *)reOle); + ok(refcount == 3, "got wrong ref count: %d\n", refcount); hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument, (void **) &txtDoc); @@ -142,6 +158,8 @@ static void test_Interfaces(void) ITextDocument_Release(txtDoc); IRichEditOle_Release(reOle); + refcount = IRichEditOle_Release(reOle); + ok(refcount == 1, "got wrong ref count: %d\n", refcount); DestroyWindow(w); /* Methods should return CO_E_RELEASED if the backing document has @@ -385,6 +403,544 @@ static void test_ITextDocument_Open(void) VariantClear(&testfile); } +static void test_ITextSelection_GetText(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextSelection *txtSel = NULL; + HRESULT hres; + BSTR bstr = NULL; + int first, lim; + static const CHAR test_text1[] = "TestSomeText"; + static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0}; + static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0}; + static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0}; + static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm', + 'e', 'T', 'e', 'x', 't', '\r', 0}; + static const WCHAR bufW5[] = {'\r', 0}; + BOOL is64bit = sizeof(void *) > sizeof(int); + + create_interfaces(&w, &reOle, &txtDoc, &txtSel); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 0, lim = 4; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 4, lim = 0; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 1, lim = 1; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr)); + + if (!is64bit) + { + hres = ITextSelection_GetText(txtSel, NULL); + ok(hres == E_INVALIDARG, "ITextSelection_GetText\n"); + } + + first = 8, lim = 12; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 8, lim = 13; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 12, lim = 13; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = 0, lim = -1; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!lstrcmpW(bstr, bufW4), "got wrong text: %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + first = -1, lim = 9; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_GetText(txtSel, &bstr); + ok(hres == S_OK, "ITextSelection_GetText\n"); + ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr)); + + release_interfaces(&w, &reOle, &txtDoc, &txtSel); +} + +static void test_ITextDocument_Range(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + ITextRange *pointer = NULL; + HRESULT hres; + ULONG refcount; + + create_interfaces(&w, &reOle, &txtDoc, NULL); + hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge); + ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres); + refcount = get_refcount((IUnknown *)txtRge); + ok(refcount == 1, "get wrong refcount: returned %d expected 1\n", refcount); + + pointer = txtRge; + hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge); + ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres); + ok(pointer != txtRge, "A new pointer should be returned\n"); + ITextRange_Release(pointer); + + hres = ITextDocument_Range(txtDoc, 0, 0, NULL); + ok(hres == E_INVALIDARG, "ITextDocument_Range should fail 0x%x.\n", hres); + + release_interfaces(&w, &reOle, &txtDoc, NULL); + hres = ITextRange_CanEdit(txtRge, NULL); + ok(hres == CO_E_RELEASED, "ITextRange after ITextDocument destroyed\n"); + ITextRange_Release(txtRge); +} + +static void test_ITextRange_GetChar(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + HRESULT hres; + LONG pch = 0xdeadbeef; + int first, lim; + static const CHAR test_text1[] = "TestSomeText"; + + first = 0, lim = 4; + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + ITextDocument_Range(txtDoc, first, lim, &txtRge); + pch = 0xdeadbeef; + hres = ITextRange_GetChar(txtRge, &pch); + ok(hres == S_OK, "ITextRange_GetChar\n"); + ok(pch == 'T', "got wrong char: %c\n", pch); + ITextRange_Release(txtRge); + release_interfaces(&w, &reOle, &txtDoc, NULL); + + first = 0, lim = 0; + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + ITextDocument_Range(txtDoc, first, lim, &txtRge); + pch = 0xdeadbeef; + hres = ITextRange_GetChar(txtRge, &pch); + ok(hres == S_OK, "ITextRange_GetChar\n"); + ok(pch == 'T', "got wrong char: %c\n", pch); + ITextRange_Release(txtRge); + release_interfaces(&w, &reOle, &txtDoc, NULL); + + first = 12, lim = 12; + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + ITextDocument_Range(txtDoc, first, lim, &txtRge); + pch = 0xdeadbeef; + hres = ITextRange_GetChar(txtRge, &pch); + ok(hres == S_OK, "ITextRange_GetChar\n"); + ok(pch == '\r', "got wrong char: %c\n", pch); + ITextRange_Release(txtRge); + release_interfaces(&w, &reOle, &txtDoc, NULL); + + first = 13, lim = 13; + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + ITextDocument_Range(txtDoc, first, lim, &txtRge); + pch = 0xdeadbeef; + hres = ITextRange_GetChar(txtRge, &pch); + ok(hres == S_OK, "ITextRange_GetChar\n"); + ok(pch == '\r', "got wrong char: %c\n", pch); + ITextRange_Release(txtRge); + release_interfaces(&w, &reOle, &txtDoc, NULL); + + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + first = 12, lim = 12; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_GetChar(txtRge, NULL); + ok(hres == E_INVALIDARG, "ITextRange_GetChar\n"); + ITextRange_Release(txtRge); + release_interfaces(&w, &reOle, &txtDoc, NULL); +} + +static void test_ITextSelection_GetChar(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextSelection *txtSel = NULL; + HRESULT hres; + LONG pch = 0xdeadbeef; + int first, lim; + static const CHAR test_text1[] = "TestSomeText"; + + create_interfaces(&w, &reOle, &txtDoc, &txtSel); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 0, lim = 4; + SendMessageA(w, EM_SETSEL, first, lim); + pch = 0xdeadbeef; + hres = ITextSelection_GetChar(txtSel, &pch); + ok(hres == S_OK, "ITextSelection_GetChar\n"); + ok(pch == 'T', "got wrong char: %c\n", pch); + + first = 0, lim = 0; + SendMessageA(w, EM_SETSEL, first, lim); + pch = 0xdeadbeef; + hres = ITextSelection_GetChar(txtSel, &pch); + ok(hres == S_OK, "ITextSelection_GetChar\n"); + ok(pch == 'T', "got wrong char: %c\n", pch); + + first = 12, lim = 12; + SendMessageA(w, EM_SETSEL, first, lim); + pch = 0xdeadbeef; + hres = ITextSelection_GetChar(txtSel, &pch); + ok(hres == S_OK, "ITextSelection_GetChar\n"); + ok(pch == '\r', "got wrong char: %c\n", pch); + + first = 13, lim = 13; + SendMessageA(w, EM_SETSEL, first, lim); + pch = 0xdeadbeef; + hres = ITextSelection_GetChar(txtSel, &pch); + ok(hres == S_OK, "ITextSelection_GetChar\n"); + ok(pch == '\r', "got wrong char: %c\n", pch); + + hres = ITextSelection_GetChar(txtSel, NULL); + ok(hres == E_INVALIDARG, "ITextSelection_GetChar\n"); + + release_interfaces(&w, &reOle, &txtDoc, &txtSel); +} + +static void test_ITextRange_GetStart_GetEnd(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + HRESULT hres; + int first, lim, start, end; + static const CHAR test_text1[] = "TestSomeText"; + + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 1, lim = 6; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + start = 0xdeadbeef; + hres = ITextRange_GetStart(txtRge, &start); + ok(hres == S_OK, "ITextRange_GetStart\n"); + ok(start == 1, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextRange_GetEnd(txtRge, &end); + ok(hres == S_OK, "ITextRange_GetEnd\n"); + ok(end == 6, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + first = 6, lim = 1; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + start = 0xdeadbeef; + hres = ITextRange_GetStart(txtRge, &start); + ok(hres == S_OK, "ITextRange_GetStart\n"); + ok(start == 1, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextRange_GetEnd(txtRge, &end); + ok(hres == S_OK, "ITextRange_GetEnd\n"); + ok(end == 6, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + first = -1, lim = 13; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + start = 0xdeadbeef; + hres = ITextRange_GetStart(txtRge, &start); + ok(hres == S_OK, "ITextRange_GetStart\n"); + ok(start == 0, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextRange_GetEnd(txtRge, &end); + ok(hres == S_OK, "ITextRange_GetEnd\n"); + ok(end == 13, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + first = 13, lim = 13; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + start = 0xdeadbeef; + hres = ITextRange_GetStart(txtRge, &start); + ok(hres == S_OK, "ITextRange_GetStart\n"); + ok(start == 12, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextRange_GetEnd(txtRge, &end); + ok(hres == S_OK, "ITextRange_GetEnd\n"); + ok(end == 12, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + release_interfaces(&w, &reOle, &txtDoc, NULL); +} + +static void test_ITextSelection_GetStart_GetEnd(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextSelection *txtSel = NULL; + HRESULT hres; + int first, lim, start, end; + static const CHAR test_text1[] = "TestSomeText"; + + create_interfaces(&w, &reOle, &txtDoc, &txtSel); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 2, lim = 5; + SendMessageA(w, EM_SETSEL, first, lim); + start = 0xdeadbeef; + hres = ITextSelection_GetStart(txtSel, &start); + ok(hres == S_OK, "ITextSelection_GetStart\n"); + ok(start == 2, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextSelection_GetEnd(txtSel, &end); + ok(hres == S_OK, "ITextSelection_GetEnd\n"); + ok(end == 5, "got wrong end value: %d\n", end); + + first = 5, lim = 2; + SendMessageA(w, EM_SETSEL, first, lim); + start = 0xdeadbeef; + hres = ITextSelection_GetStart(txtSel, &start); + ok(hres == S_OK, "ITextSelection_GetStart\n"); + ok(start == 2, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextSelection_GetEnd(txtSel, &end); + ok(hres == S_OK, "ITextSelection_GetEnd\n"); + ok(end == 5, "got wrong end value: %d\n", end); + + first = 0, lim = -1; + SendMessageA(w, EM_SETSEL, first, lim); + start = 0xdeadbeef; + hres = ITextSelection_GetStart(txtSel, &start); + ok(hres == S_OK, "ITextSelection_GetStart\n"); + ok(start == 0, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextSelection_GetEnd(txtSel, &end); + ok(hres == S_OK, "ITextSelection_GetEnd\n"); + ok(end == 13, "got wrong end value: %d\n", end); + + first = 13, lim = 13; + SendMessageA(w, EM_SETSEL, first, lim); + start = 0xdeadbeef; + hres = ITextSelection_GetStart(txtSel, &start); + ok(hres == S_OK, "ITextSelection_GetStart\n"); + ok(start == 12, "got wrong start value: %d\n", start); + end = 0xdeadbeef; + hres = ITextSelection_GetEnd(txtSel, &end); + ok(hres == S_OK, "ITextSelection_GetEnd\n"); + ok(end == 12, "got wrong end value: %d\n", end); + + release_interfaces(&w, &reOle, &txtDoc, &txtSel); +} + +static void test_ITextRange_GetDuplicate(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + ITextRange *txtRgeDup = NULL; + HRESULT hres; + LONG first, lim, start, end; + static const CHAR test_text1[] = "TestSomeText"; + + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + first = 0, lim = 4; + hres = ITextDocument_Range(txtDoc, first, lim, &txtRge); + ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres); + + hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup); + ok(hres == S_OK, "ITextRange_GetDuplicate\n"); + ok(txtRgeDup != txtRge, "A new pointer should be returned\n"); + ITextRange_GetStart(txtRgeDup, &start); + ok(start == first, "got wrong value: %d\n", start); + ITextRange_GetEnd(txtRgeDup, &end); + ok(end == lim, "got wrong value: %d\n", end); + + ITextRange_Release(txtRgeDup); + + hres = ITextRange_GetDuplicate(txtRge, NULL); + ok(hres == E_INVALIDARG, "ITextRange_GetDuplicate\n"); + + ITextRange_Release(txtRge); + release_interfaces(&w, &reOle, &txtDoc, NULL); +} + +static void test_ITextRange_Collapse(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextRange *txtRge = NULL; + HRESULT hres; + LONG first, lim, start, end; + static const CHAR test_text1[] = "TestSomeText"; + + create_interfaces(&w, &reOle, &txtDoc, NULL); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 4, lim = 8; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, tomTrue); + ok(hres == S_OK, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 4, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 4, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, tomStart); + ok(hres == S_OK, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 4, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 4, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, tomFalse); + ok(hres == S_OK, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 8, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 8, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, tomEnd); + ok(hres == S_OK, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 8, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 8, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + /* tomStart is the default */ + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, 256); + ok(hres == S_OK, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 4, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 4, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + first = 6, lim = 6; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, tomEnd); + ok(hres == S_FALSE, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 6, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 6, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + first = 8, lim = 8; + ITextDocument_Range(txtDoc, first, lim, &txtRge); + hres = ITextRange_Collapse(txtRge, tomStart); + ok(hres == S_FALSE, "ITextRange_Collapse\n"); + ITextRange_GetStart(txtRge, &start); + ok(start == 8, "got wrong start value: %d\n", start); + ITextRange_GetEnd(txtRge, &end); + ok(end == 8, "got wrong end value: %d\n", end); + ITextRange_Release(txtRge); + + release_interfaces(&w, &reOle, &txtDoc, NULL); +} + +static void test_ITextSelection_Collapse(void) +{ + HWND w; + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextSelection *txtSel = NULL; + HRESULT hres; + LONG first, lim, start, end; + static const CHAR test_text1[] = "TestSomeText"; + + create_interfaces(&w, &reOle, &txtDoc, &txtSel); + SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); + + first = 4, lim = 8; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, tomTrue); + ok(hres == S_OK, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 4, "got wrong start value: %d\n", start); + ok(end == 4, "got wrong end value: %d\n", end); + + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, tomStart); + ok(hres == S_OK, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 4, "got wrong start value: %d\n", start); + ok(end == 4, "got wrong end value: %d\n", end); + + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, tomFalse); + ok(hres == S_OK, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 8, "got wrong start value: %d\n", start); + ok(end == 8, "got wrong end value: %d\n", end); + + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, tomEnd); + ok(hres == S_OK, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 8, "got wrong start value: %d\n", start); + ok(end == 8, "got wrong end value: %d\n", end); + + /* tomStart is the default */ + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, 256); + ok(hres == S_OK, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 4, "got wrong start value: %d\n", start); + ok(end == 4, "got wrong end value: %d\n", end); + + first = 6, lim = 6; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, tomEnd); + ok(hres == S_FALSE, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 6, "got wrong start value: %d\n", start); + ok(end == 6, "got wrong end value: %d\n", end); + + first = 8, lim = 8; + SendMessageA(w, EM_SETSEL, first, lim); + hres = ITextSelection_Collapse(txtSel, tomStart); + ok(hres == S_FALSE, "ITextSelection_Collapse\n"); + SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); + ok(start == 8, "got wrong start value: %d\n", start); + ok(end == 8, "got wrong end value: %d\n", end); + + release_interfaces(&w, &reOle, &txtDoc, &txtSel); +} + START_TEST(richole) { /* Must explicitly LoadLibrary(). The test has no references to functions in @@ -394,4 +950,13 @@ START_TEST(richole) test_Interfaces(); test_ITextDocument_Open(); + test_ITextSelection_GetText(); + test_ITextSelection_GetChar(); + test_ITextSelection_GetStart_GetEnd(); + test_ITextSelection_Collapse(); + test_ITextDocument_Range(); + test_ITextRange_GetChar(); + test_ITextRange_GetStart_GetEnd(); + test_ITextRange_GetDuplicate(); + test_ITextRange_Collapse(); }