diff --git a/modules/rostests/winetests/riched20/editor.c b/modules/rostests/winetests/riched20/editor.c index 791f471dee2..40477666a1e 100644 --- a/modules/rostests/winetests/riched20/editor.c +++ b/modules/rostests/winetests/riched20/editor.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include @@ -51,12 +53,38 @@ static CHAR string1[MAX_PATH], string2[MAX_PATH], string3[MAX_PATH]; static HMODULE hmoduleRichEdit; static BOOL is_lang_japanese; +#if defined(__i386__) && !defined(__MINGW32__) && (!defined(_MSC_VER) || !defined(__clang__)) +static void disable_beep( HWND hwnd ) +{ + /* don't attempt to disable beep if we don't have thiscall compiler support */ +} +#else +#define ITextServices_OnTxPropertyBitsChange(This,a,b) (This)->lpVtbl->OnTxPropertyBitsChange(This,a,b) +static void disable_beep( HWND hwnd ) +{ + IRichEditOle *richole; + ITextServices *services; + IID *pIID_ITextServices = (IID *)GetProcAddress( hmoduleRichEdit, "IID_ITextServices" ); + + if (SendMessageW( hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&richole )) + { + if (SUCCEEDED( IRichEditOle_QueryInterface( richole, pIID_ITextServices, (void **)&services ) )) + { + ITextServices_OnTxPropertyBitsChange( services, TXTBIT_ALLOWBEEP, 0 ); + ITextServices_Release( services ); + } + IRichEditOle_Release( richole ); + } +} +#endif + static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) { HWND 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()); + disable_beep( hwnd ); return hwnd; } @@ -66,6 +94,7 @@ static HWND new_windowW(LPCWSTR lpClassName, DWORD dwStyle, HWND parent) { |WS_VISIBLE, 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL); ok(hwnd != NULL, "class: %s, error: %d\n", wine_dbgstr_w(lpClassName), (int) GetLastError()); + disable_beep( hwnd ); return hwnd; } @@ -615,7 +644,7 @@ static void test_EM_POSFROMCHAR(void) "gg\n" "hh\n"; - rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE, + rtl = (GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_FONTSIGNATURE, (LPSTR) &sig, sizeof(LOCALESIGNATURE)) && (sig.lsUsb[3] & 0x08000000) != 0); @@ -772,7 +801,7 @@ static void test_EM_SETCHARFORMAT(void) BOOL rtl; DWORD expect_effects; - rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE, + rtl = (GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_FONTSIGNATURE, (LPSTR) &sig, sizeof(LOCALESIGNATURE)) && (sig.lsUsb[3] & 0x08000000) != 0); @@ -1791,8 +1820,8 @@ static void test_EM_GETTEXTRANGE(void) textRange.chrg.cpMin = 4; textRange.chrg.cpMax = 8; result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange); - todo_wine ok(result == 5, "EM_GETTEXTRANGE returned %ld\n", result); - todo_wine ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETTEXTRANGE filled %s\n", buffer); + ok(result == 5, "EM_GETTEXTRANGE returned %ld\n", result); + ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETTEXTRANGE filled %s\n", buffer); } DestroyWindow(hwndRichEdit); @@ -1829,8 +1858,8 @@ static void test_EM_GETSELTEXT(void) SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk"); SendMessageA(hwndRichEdit, EM_SETSEL, 4, 8); result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer); - todo_wine ok(result == 5, "EM_GETSELTEXT returned %ld\n", result); - todo_wine ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETSELTEXT filled %s\n", buffer); + ok(result == 5, "EM_GETSELTEXT returned %ld\n", result); + ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETSELTEXT filled %s\n", buffer); } DestroyWindow(hwndRichEdit); @@ -1863,6 +1892,7 @@ static void test_EM_SETOPTIONS(void) hmoduleRichEdit, NULL); ok(hwndRichEdit != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError()); + disable_beep( hwndRichEdit ); options = SendMessageA(hwndRichEdit, EM_GETOPTIONS, 0, 0); /* WS_[VH]SCROLL cause the ECO_AUTO[VH]SCROLL options to be set */ ok(options == (ECO_AUTOVSCROLL|ECO_AUTOHSCROLL), @@ -3110,11 +3140,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -3124,11 +3152,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a"); @@ -3138,11 +3164,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a\na"); @@ -3152,11 +3176,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -3166,11 +3188,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text); SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -5610,7 +5630,7 @@ static void test_EM_FORMATRANGE(void) {"WINE\r\n\r\nwine\r\nwine", 5, 6} }; - skip_non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH); + skip_non_english = (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH); if (skip_non_english) skip("Skipping some tests on non-English platform\n"); @@ -6348,6 +6368,7 @@ static void test_WM_CHAR(void) hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP, 0, 0, 200, 60, 0, 0, 0, 0); ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); + disable_beep( hwnd ); p = char_list; while (*p != '\0') { @@ -6951,6 +6972,7 @@ static void test_undo_coalescing(void) 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()); + disable_beep( hwnd ); result = SendMessageA(hwnd, EM_CANUNDO, 0, 0); ok (result == FALSE, "Can undo after window creation.\n"); @@ -7461,12 +7483,25 @@ static void test_format_rect(void) ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(&expected)); + /* reset back to client rect and now try adding selection bar */ + SendMessageA(hwnd, EM_SETRECT, 0, 0); + expected = clientRect; + InflateRect(&expected, -1, 0); + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), + wine_dbgstr_rect(&expected)); + SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR); + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), + wine_dbgstr_rect(&expected)); + SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_AND, ~ECO_SELECTIONBAR); + /* Set the absolute value of the formatting rectangle. */ rc = clientRect; SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc); expected = clientRect; SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); - ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc), + ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(&expected)); /* MSDN documents the EM_SETRECT message as using the rectangle provided in @@ -8987,38 +9022,6 @@ static void test_EM_SELECTIONTYPE(void) DestroyWindow(hwnd); } -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; @@ -9026,9 +9029,8 @@ START_TEST( editor ) * RICHED20.DLL, so the linker doesn't actually link to it. */ hmoduleRichEdit = LoadLibraryA("riched20.dll"); ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); - is_lang_japanese = (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE); + is_lang_japanese = (PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_JAPANESE); - test_window_classes(); test_WM_CHAR(); test_EM_FINDTEXT(FALSE); test_EM_FINDTEXT(TRUE); diff --git a/modules/rostests/winetests/riched20/richole.c b/modules/rostests/winetests/riched20/richole.c index 492bdc3fa9a..3885eb527fc 100644 --- a/modules/rostests/winetests/riched20/richole.c +++ b/modules/rostests/winetests/riched20/richole.c @@ -149,6 +149,7 @@ static void test_Interfaces(void) LRESULT res; HWND w; ULONG refcount; + IUnknown *unk, *unk2; w = new_richedit(NULL); if (!w) { @@ -180,6 +181,14 @@ static void test_Interfaces(void) hres = ITextDocument_GetSelection(txtDoc, &txtSel); ok(hres == S_OK, "got 0x%08x\n", hres); + hres = ITextDocument_QueryInterface(txtDoc, &IID_IUnknown, (void **)&unk); + ok(hres == S_OK, "got 0x%08x\n", hres); + hres = ITextSelection_QueryInterface(txtSel, &IID_IUnknown, (void **)&unk2); + ok(hres == S_OK, "got 0x%08x\n", hres); + ok(unk != unk2, "unknowns are the same\n"); + IUnknown_Release(unk2); + IUnknown_Release(unk); + EXPECT_REF(txtDoc, 4); EXPECT_REF(txtSel, 2); @@ -3203,29 +3212,62 @@ static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj, reobj->dwUser = user; } -#define CHECK_REOBJECT_STRUCT(reobj,poleobj,pstg,polesite,user) \ - _check_reobject_struct(reobj, poleobj, pstg, polesite, user, __LINE__) -static void _check_reobject_struct(REOBJECT reobj, LPOLEOBJECT poleobj, LPSTORAGE pstg, - LPOLECLIENTSITE polesite, DWORD user, int line) +#define CHECK_REOBJECT_STRUCT(reole,index,flags,cp,poleobj,pstg,polesite,user) \ + _check_reobject_struct(reole, index, flags, cp, poleobj, pstg, polesite, user, __LINE__) +static void _check_reobject_struct(IRichEditOle *reole, LONG index, DWORD flags, LONG cp, + LPOLEOBJECT poleobj, LPSTORAGE pstg, LPOLECLIENTSITE polesite, DWORD user, int line) { + REOBJECT reobj; + HRESULT hr; + + reobj.cbStruct = sizeof(reobj); + reobj.cp = cp; + hr = IRichEditOle_GetObject(reole, index, &reobj, flags); + ok(hr == S_OK, "IRichEditOle_GetObject failed: %#x.\n", hr); ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n"); ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n"); ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n"); ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n"); } +#define INSERT_REOBJECT(reole,reobj,cp,user) \ + _insert_reobject(reole, reobj, cp, user, __LINE__) +static void _insert_reobject(IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line) +{ + IOleClientSite *clientsite; + HRESULT hr; + hr = IRichEditOle_GetClientSite(reole, &clientsite); + ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_GetClientSite got hr %#x.\n", hr); + fill_reobject_struct(reobj, cp, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, user); + hr = IRichEditOle_InsertObject(reole, reobj); + ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_InsertObject got hr %#x.\n", hr); + IOleClientSite_Release(clientsite); +} + static void test_InsertObject(void) { static CHAR test_text1[] = "abcdefg"; IRichEditOle *reole = NULL; ITextDocument *doc = NULL; - IOleClientSite *clientsite; - REOBJECT reo1, reo2, reo3, received_reo1, received_reo2, received_reo3, received_reo4; + REOBJECT reo1, reo2, reo3, received_reo; HRESULT hr; HWND hwnd; - LONG count; + const WCHAR *expected_string; + const CHAR *expected_stringA; + ITextSelection *selection; + IDataObject *dataobject; + TEXTRANGEA textrange; + FORMATETC formatetc; + CHARRANGE charrange; + GETTEXTEX gettextex; + STGMEDIUM stgmedium; + WCHAR buffer[1024]; + CHAR bufferA[1024]; + LONG count, result; + ITextRange *range; + BSTR bstr; - create_interfaces(&hwnd, &reole, &doc, NULL); + create_interfaces(&hwnd, &reole, &doc, &selection); SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); hr = IRichEditOle_InsertObject(reole, NULL); @@ -3233,161 +3275,278 @@ static void test_InsertObject(void) /* insert object1 in (0, 1)*/ SendMessageA(hwnd, EM_SETSEL, 0, 1); - hr = IRichEditOle_GetClientSite(reole, &clientsite); - ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr); - fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1); - hr = IRichEditOle_InsertObject(reole, &reo1); - ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr); + INSERT_REOBJECT(reole, &reo1, REO_CP_SELECTION, 1); count = IRichEditOle_GetObjectCount(reole); ok(count == 1, "got wrong object count: %d\n", count); - IOleClientSite_Release(clientsite); /* insert object2 in (2, 3)*/ SendMessageA(hwnd, EM_SETSEL, 2, 3); - hr = IRichEditOle_GetClientSite(reole, &clientsite); - ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr); - fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 2); - hr = IRichEditOle_InsertObject(reole, &reo2); - ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr); + INSERT_REOBJECT(reole, &reo2, REO_CP_SELECTION, 2); count = IRichEditOle_GetObjectCount(reole); ok(count == 2, "got wrong object count: %d\n", count); - IOleClientSite_Release(clientsite); /* insert object3 in (1, 2)*/ SendMessageA(hwnd, EM_SETSEL, 1, 2); - hr = IRichEditOle_GetClientSite(reole, &clientsite); - ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr); - fill_reobject_struct(&reo3, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 3); - hr = IRichEditOle_InsertObject(reole, &reo3); - ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr); + INSERT_REOBJECT(reole, &reo3, REO_CP_SELECTION, 3); count = IRichEditOle_GetObjectCount(reole); ok(count == 3, "got wrong object count: %d\n", count); - IOleClientSite_Release(clientsite); /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */ - received_reo1.cbStruct = sizeof(received_reo1); - hr = IRichEditOle_GetObject(reole, 0, &received_reo1, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo1, NULL, NULL, reo1.polesite, 1); - - received_reo2.cbStruct = sizeof(received_reo2); - hr = IRichEditOle_GetObject(reole, 1, &received_reo2, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo2, NULL, NULL, reo3.polesite, 3); - - received_reo3.cbStruct = sizeof(received_reo3); - hr = IRichEditOle_GetObject(reole, 2, &received_reo3, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo3, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, 0, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, 1, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo2.polesite, 2); hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = 0; - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + received_reo.cbStruct = 0; + hr = IRichEditOle_GetObject(reole, 2, &received_reo, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = sizeof(received_reo4); - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_PSTG); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2); - - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_POLESITE); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_PSTG, 0, NULL, NULL, NULL, 2); + CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_POLESITE, 0, NULL, NULL, reo2.polesite, 2); - hr = IRichEditOle_GetObject(reole, 4, &received_reo4, REO_GETOBJ_POLESITE); + hr = IRichEditOle_GetObject(reole, 3, &received_reo, REO_GETOBJ_POLESITE); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - hr = IRichEditOle_GetObject(reole, 1024, &received_reo4, REO_GETOBJ_POLESITE); + hr = IRichEditOle_GetObject(reole, 4, &received_reo, REO_GETOBJ_POLESITE); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - /* received_reo4 will be zeroed before be used */ - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_NO_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2); + hr = IRichEditOle_GetObject(reole, 1024, &received_reo, REO_GETOBJ_POLESITE); + ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + hr = IRichEditOle_GetObject(reole, -10, &received_reo, REO_GETOBJ_POLESITE); + ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 1; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + /* received_reo will be zeroed before be used */ + received_reo.cbStruct = sizeof(received_reo); + received_reo.polesite = (IOleClientSite *)0xdeadbeef; + hr = IRichEditOle_GetObject(reole, 2, &received_reo, REO_GETOBJ_NO_INTERFACES); ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3); + ok(received_reo.polesite == (IOleClientSite *)NULL, "Got wrong site interface.\n"); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 2; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 2, NULL, NULL, reo2.polesite, 2); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 4; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + received_reo.cbStruct = sizeof(received_reo); + received_reo.polesite = (IOleClientSite *)0xdeadbeef; + received_reo.dwUser = 4; + received_reo.cp = 4; + hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - /* received_reo4 didn't be zeroed in E_INVALIDARG case */ - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + ok(received_reo.polesite == (IOleClientSite *)0xdeadbeef, "Got wrong site interface.\n"); + ok(received_reo.dwUser == 4, "Got wrong user-defined value: %d.\n", received_reo.dwUser); SendMessageA(hwnd, EM_SETSEL, 0, 1); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 1; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 1, 2); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3); SendMessageA(hwnd, EM_SETSEL, 2, 3); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo2.polesite, 2); SendMessageA(hwnd, EM_SETSEL, 0, 2); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 1, 3); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3); SendMessageA(hwnd, EM_SETSEL, 2, 0); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 0, 6); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 4, 5); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + received_reo.cbStruct = sizeof(received_reo); + received_reo.cp = 0; + hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - release_interfaces(&hwnd, &reole, &doc, NULL); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); + + /* "abc|d|efg" */ + INSERT_REOBJECT(reole, &reo1, 3, 1); + INSERT_REOBJECT(reole, &reo2, 5, 2); + + SendMessageW(hwnd, EM_SETSEL, 2, 3); + result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0); + ok(result == SEL_TEXT, "Got selection type: %x.\n", result); + + SendMessageW(hwnd, EM_SETSEL, 3, 4); + result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0); + todo_wine ok(result == SEL_OBJECT, "Got selection type: %x.\n", result); + todo_wine CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo1.polesite, 1); + + SendMessageW(hwnd, EM_SETSEL, 2, 4); + result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0); + todo_wine ok(result == (SEL_TEXT | SEL_OBJECT), "Got selection type: %x.\n", result); + + SendMessageW(hwnd, EM_SETSEL, 5, 6); + todo_wine CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo2.polesite, 2); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg"; +#endif + + gettextex.cb = sizeof(buffer); + gettextex.flags = GT_DEFAULT; + gettextex.codepage = 1200; + gettextex.lpDefaultChar = NULL; + gettextex.lpUsedDefChar = NULL; + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + gettextex.flags = GT_RAWTEXT; + memset(buffer, 0, sizeof(buffer)); + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + expected_stringA = "abc d efg"; + memset(bufferA, 0, sizeof(bufferA)); + SendMessageA(hwnd, EM_SETSEL, 0, -1); + result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + + memset(bufferA, 0, sizeof(bufferA)); + textrange.lpstrText = bufferA; + textrange.chrg.cpMin = 0; + textrange.chrg.cpMax = 11; + result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg\r"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg\r"; +#endif + + hr = ITextDocument_Range(doc, 0, 11, &range); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetText(range, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hr = ITextRange_SetRange(range, 3, 4); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetChar(range, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + ITextRange_Release(range); + + SendMessageW(hwnd, EM_SETSEL, 0, -1); + hr = ITextSelection_GetText(selection, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + SendMessageW(hwnd, EM_SETSEL, 3, 4); + result = 0; + hr = ITextSelection_GetChar(selection, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)""); + result = SendMessageW(hwnd, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT, 0); + ok(!result, "Got result %x.\n", result); + /* "abc|d|efg" */ + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); + INSERT_REOBJECT(reole, &reo1, 3, 1); + INSERT_REOBJECT(reole, &reo2, 5, 2); + + expected_string = L"abc d efg"; + charrange.cpMin = 0; + charrange.cpMax = 11; + hr = IRichEditOle_GetClipboardData(reole, &charrange, 1, &dataobject); + ok(hr == S_OK, "Got hr %#x.\n", hr); + formatetc.cfFormat = CF_UNICODETEXT; + formatetc.dwAspect = DVASPECT_CONTENT; + formatetc.ptd = NULL; + formatetc.tymed = TYMED_HGLOBAL; + formatetc.lindex = -1; + hr = IDataObject_GetData(dataobject, &formatetc, &stgmedium); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(lstrlenW(stgmedium.hGlobal) == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(stgmedium.hGlobal, expected_string), "Got wrong content: %s.\n", debugstr_w(stgmedium.hGlobal)); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg"; +#endif + + gettextex.cb = sizeof(buffer); + gettextex.flags = GT_DEFAULT; + gettextex.codepage = 1200; + gettextex.lpDefaultChar = NULL; + gettextex.lpUsedDefChar = NULL; + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + gettextex.flags = GT_RAWTEXT; + memset(buffer, 0, sizeof(buffer)); + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + expected_stringA = "abc d efg"; + memset(bufferA, 0, sizeof(bufferA)); + SendMessageA(hwnd, EM_SETSEL, 0, -1); + result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + + memset(bufferA, 0, sizeof(bufferA)); + textrange.lpstrText = bufferA; + textrange.chrg.cpMin = 0; + textrange.chrg.cpMax = 11; + result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg"; +#endif + + hr = ITextDocument_Range(doc, 0, 11, &range); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetText(range, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hr = ITextRange_SetRange(range, 3, 4); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetChar(range, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + ITextRange_Release(range); + + SendMessageW(hwnd, EM_SETSEL, 0, -1); + hr = ITextSelection_GetText(selection, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + SendMessageW(hwnd, EM_SETSEL, 3, 4); + result = 0; + hr = ITextSelection_GetChar(selection, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + + release_interfaces(&hwnd, &reole, &doc, &selection); } static void test_GetStoryLength(void) @@ -3694,7 +3853,7 @@ static void test_Expand(void) ITextRange_Release(range); } -static void test_MoveEnd(void) +static void test_MoveEnd_story(void) { static const char test_text1[] = "Word1 Word2"; IRichEditOle *reole = NULL; @@ -3808,272 +3967,288 @@ static void test_MoveEnd(void) ITextRange_Release(range); } -static void test_ITextRange_SetStart(void) +static void test_character_movestart(ITextRange *range, int textlen, int i, int j, LONG target) { - 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_SetStart(txtRge, first); - ok(hres == S_FALSE, "ITextRange_SetStart\n"); - -#define TEST_TXTRGE_SETSTART(cp, expected_start, expected_end) \ - hres = ITextRange_SetStart(txtRge, cp); \ - ok(hres == S_OK, "ITextRange_SetStart\n"); \ - ITextRange_GetStart(txtRge, &start); \ - ITextRange_GetEnd(txtRge, &end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTRGE_SETSTART(2, 2, 8) - TEST_TXTRGE_SETSTART(-1, 0, 8) - TEST_TXTRGE_SETSTART(13, 12, 12) - - release_interfaces(&w, &reOle, &txtDoc, NULL); + HRESULT hr; + LONG delta = 0; + LONG expected_delta; + LONG expected_start = target; + + if (expected_start < 0) + expected_start = 0; + else if (expected_start > textlen) + expected_start = textlen; + expected_delta = expected_start - i; + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_MoveStart(range, tomCharacter, target - i, &delta); + if (expected_start == i) { + ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - i, hr); + ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, target - i, delta); + CHECK_RANGE(range, i, j); + } else { + ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - i, hr); + ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, target - i, delta); + if (expected_start <= j) + CHECK_RANGE(range, expected_start, j); + else + CHECK_RANGE(range, expected_start, expected_start); + } } -static void test_ITextRange_SetEnd(void) +static void test_character_moveend(ITextRange *range, int textlen, int i, int j, LONG target) { - 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_SetEnd(txtRge, lim); - ok(hres == S_FALSE, "ITextRange_SetEnd\n"); - -#define TEST_TXTRGE_SETEND(cp, expected_start, expected_end) \ - hres = ITextRange_SetEnd(txtRge, cp); \ - ok(hres == S_OK, "ITextRange_SetEnd\n"); \ - ITextRange_GetStart(txtRge, &start); \ - ITextRange_GetEnd(txtRge, &end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTRGE_SETEND(6, 4, 6) - TEST_TXTRGE_SETEND(14, 4, 13) - TEST_TXTRGE_SETEND(-1, 0, 0) - - ITextRange_Release(txtRge); - release_interfaces(&w, &reOle, &txtDoc, NULL); + HRESULT hr; + LONG delta; + LONG expected_delta; + LONG expected_end = target; + + if (expected_end < 0) + expected_end = 0; + else if (expected_end > textlen + 1) + expected_end = textlen + 1; + expected_delta = expected_end - j; + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_MoveEnd(range, tomCharacter, target - j, &delta); + if (expected_end == j) { + ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - j, hr); + ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, target - j, delta); + CHECK_RANGE(range, i, j); + } else { + ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - j, hr); + ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, target - j, delta); + if (i <= expected_end) + CHECK_RANGE(range, i, expected_end); + else + CHECK_RANGE(range, expected_end, expected_end); + } } -static void test_ITextSelection_SetStart(void) +static void test_character_move(ITextRange *range, int textlen, int i, int j, LONG target) { - 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_SetStart(txtSel, first); - ok(hres == S_FALSE, "ITextSelection_SetStart\n"); - -#define TEST_TXTSEL_SETSTART(cp, expected_start, expected_end) \ - hres = ITextSelection_SetStart(txtSel, cp); \ - ok(hres == S_OK, "ITextSelection_SetStart\n"); \ - SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTSEL_SETSTART(2, 2, 8) - TEST_TXTSEL_SETSTART(-1, 0, 8) - TEST_TXTSEL_SETSTART(13, 12, 12) + HRESULT hr; + LONG move_by; + LONG delta = 0; + LONG expected_delta; + LONG expected_location = target; + + if (expected_location < 0) + expected_location = 0; + else if (expected_location > textlen) + expected_location = textlen; + + if (target <= i) { + move_by = target - i; + expected_delta = expected_location - i; + if (i != j) { + --move_by; + --expected_delta; + } + } else if (j <= target) { + move_by = target - j; + expected_delta = expected_location - j; + if (i != j) { + ++move_by; + ++expected_delta; + } + } else { + /* There's no way to move to a point between start and end: */ + return; + } - release_interfaces(&w, &reOle, &txtDoc, &txtSel); + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_Move(range, tomCharacter, move_by, &delta); + if (expected_delta == 0) { + ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, move_by, hr); + ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, move_by, delta); + CHECK_RANGE(range, expected_location, expected_location); + } else { + ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, move_by, hr); + ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, move_by, delta); + CHECK_RANGE(range, expected_location, expected_location); + } } -static void test_ITextSelection_SetEnd(void) +static void test_character_startof(ITextRange *range, int textlen, int i, int j) { - 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_SetEnd(txtSel, lim); - ok(hres == S_FALSE, "ITextSelection_SetEnd\n"); - -#define TEST_TXTSEL_SETEND(cp, expected_start, expected_end) \ - hres = ITextSelection_SetEnd(txtSel, cp); \ - ok(hres == S_OK, "ITextSelection_SetEnd\n"); \ - SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTSEL_SETEND(6, 4, 6) - TEST_TXTSEL_SETEND(14, 4, 13) - TEST_TXTSEL_SETEND(-1, 0, 0) - - release_interfaces(&w, &reOle, &txtDoc, &txtSel); + HRESULT hr; + LONG delta; + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_StartOf(range, tomCharacter, tomMove, &delta); + if (i == j) { + ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } else { + ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == -1, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } + CHECK_RANGE(range, i, i); + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_StartOf(range, tomCharacter, tomExtend, &delta); + ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta); + CHECK_RANGE(range, i, j); } -static void test_ITextRange_GetFont(void) +static void test_character_endof(ITextRange *range, int textlen, int i, int j) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextRange *txtRge = NULL; - ITextFont *txtFont = NULL, *txtFont1 = NULL; - HRESULT hres; - int first, lim; - int refcount; - static const CHAR test_text1[] = "TestSomeText"; - LONG value; - - create_interfaces(&w, &reOle, &txtDoc, NULL); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 4; - ITextDocument_Range(txtDoc, first, lim, &txtRge); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - - hres = ITextRange_GetFont(txtRge, &txtFont); - ok(hres == S_OK, "ITextRange_GetFont\n"); - refcount = get_refcount((IUnknown *)txtFont); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); - - hres = ITextRange_GetFont(txtRge, &txtFont1); - ok(hres == S_OK, "ITextRange_GetFont\n"); - ok(txtFont1 != txtFont, "A new pointer should be return\n"); - refcount = get_refcount((IUnknown *)txtFont1); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - ITextFont_Release(txtFont1); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); - - ITextRange_Release(txtRge); - release_interfaces(&w, &reOle, &txtDoc, NULL); - - hres = ITextFont_GetOutline(txtFont, &value); - ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n"); - - ITextFont_Release(txtFont); + HRESULT hr; + LONG end; + LONG delta; + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_EndOf(range, tomCharacter, tomMove, &delta); + + /* A character "end", apparently cannot be before the very first character */ + end = j; + if (j == 0) + ++end; + + if (i == end) { + ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } else { + ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == 1, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } + CHECK_RANGE(range, end, end); + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_EndOf(range, tomCharacter, tomExtend, &delta); + if (0 < j) { + ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta); + } else { + ok(hr == S_OK, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr); + ok(delta == 1, "(%d,%d) tomExtend got delta %d\n", i, j, delta); + } + CHECK_RANGE(range, i, end); } -static void test_ITextSelection_GetFont(void) +static void test_character_movement(void) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextSelection *txtSel = NULL; - ITextFont *txtFont = NULL, *txtFont1 = NULL; - HRESULT hres; - int first, lim; - int refcount; - static const CHAR test_text1[] = "TestSomeText"; - LONG value; - - create_interfaces(&w, &reOle, &txtDoc, &txtSel); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 4; - SendMessageA(w, EM_SETSEL, first, lim); - refcount = get_refcount((IUnknown *)txtSel); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); - - hres = ITextSelection_GetFont(txtSel, &txtFont); - ok(hres == S_OK, "ITextSelection_GetFont\n"); - refcount = get_refcount((IUnknown *)txtFont); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - refcount = get_refcount((IUnknown *)txtSel); - ok(refcount == 3, "got wrong ref count: %d\n", refcount); + static const char test_text1[] = "ab\n c"; + IRichEditOle *reole = NULL; + ITextDocument *doc = NULL; + ITextRange *range; + ITextSelection *selection; + HRESULT hr; + HWND hwnd; + int i, j; + const int textlen = strlen(test_text1); - hres = ITextSelection_GetFont(txtSel, &txtFont1); - ok(hres == S_OK, "ITextSelection_GetFont\n"); - ok(txtFont1 != txtFont, "A new pointer should be return\n"); - refcount = get_refcount((IUnknown *)txtFont1); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - ITextFont_Release(txtFont1); - refcount = get_refcount((IUnknown *)txtSel); - ok(refcount == 3, "got wrong ref count: %d\n", refcount); + create_interfaces(&hwnd, &reole, &doc, &selection); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); - release_interfaces(&w, &reOle, &txtDoc, &txtSel); + hr = ITextDocument_Range(doc, 0, 0, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); - hres = ITextFont_GetOutline(txtFont, &value); - ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n"); + /* Exhaustive test of every possible combination of (start,end) locations, + * against every possible target location to move to. */ + for (i = 0; i <= textlen; i++) { + for (j = i; j <= textlen; j++) { + LONG target; + for (target = -2; target <= textlen + 3; target++) { + test_character_moveend(range, textlen, i, j, target); + test_character_movestart(range, textlen, i, j, target); + test_character_move(range, textlen, i, j, target); + } + test_character_startof(range, textlen, i, j); + test_character_endof(range, textlen, i, j); + } + } - ITextFont_Release(txtFont); + release_interfaces(&hwnd, &reole, &doc, NULL); + ITextSelection_Release(selection); + ITextRange_Release(range); } -static void test_ITextRange_GetPara(void) +#define CLIPBOARD_RANGE_CONTAINS(range, start, end, expected) _clipboard_range_contains(range, start, end, expected, __LINE__, 0); +#define TODO_CLIPBOARD_RANGE_CONTAINS(range, start, end, expected) _clipboard_range_contains(range, start, end, expected, __LINE__, 1); +static void _clipboard_range_contains(ITextRange *range, LONG start, LONG end, const char *expected, int line, int todo) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextRange *txtRge = NULL; - ITextPara *txtPara = NULL, *txtPara1 = NULL; - HRESULT hres; - int first, lim; - int refcount; - static const CHAR test_text1[] = "TestSomeText"; - LONG value; - - create_interfaces(&w, &reOle, &txtDoc, NULL); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 4; - ITextDocument_Range(txtDoc, first, lim, &txtRge); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); + HRESULT hr; + BOOL clipboard_open; + HGLOBAL global; + const char *clipboard_text; + + hr = ITextRange_SetRange(range, start, end); + ok_(__FILE__,line)(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr); + hr = ITextRange_Copy(range, NULL); + ok_(__FILE__,line)(hr == S_OK, "Copy failed: 0x%08x\n", hr); + + clipboard_open = OpenClipboard(NULL); + ok_(__FILE__,line)(clipboard_open, "OpenClipboard failed: %d\n", GetLastError()); + global = GetClipboardData(CF_TEXT); + ok_(__FILE__,line)(global != NULL, "GetClipboardData failed: %p\n", global); + clipboard_text = GlobalLock(global); + ok_(__FILE__,line)(clipboard_text != NULL, "GlobalLock failed: %p\n", clipboard_text); +#ifdef __REACTOS__ + if (expected != NULL && clipboard_text != NULL) + todo_wine_if(todo) ok_(__FILE__,line)(!strcmp(expected, clipboard_text), "unexpected contents: %s\n", wine_dbgstr_a(clipboard_text)); + else + todo_wine_if(todo) ok_(__FILE__,line)(FALSE, "Either 'expected' or 'clipboard_text' was NULL\n"); +#else + todo_wine_if(todo) ok_(__FILE__,line)(!strcmp(expected, clipboard_text), "unexpected contents: %s\n", wine_dbgstr_a(clipboard_text)); +#endif + GlobalUnlock(global); + CloseClipboard(); +} - hres = ITextRange_GetPara(txtRge, &txtPara); - ok(hres == S_OK, "ITextRange_GetPara\n"); - refcount = get_refcount((IUnknown *)txtPara); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); +static void test_clipboard(void) +{ + static const char text_in[] = "ab\n c"; + IRichEditOle *reole = NULL; + ITextDocument *doc = NULL; + ITextRange *range; + ITextSelection *selection; + HRESULT hr; + HWND hwnd; - hres = ITextRange_GetPara(txtRge, &txtPara1); - ok(hres == S_OK, "ITextRange_GetPara\n"); - ok(txtPara1 != txtPara, "A new pointer should be return\n"); - refcount = get_refcount((IUnknown *)txtPara1); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - ITextPara_Release(txtPara1); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); + create_interfaces(&hwnd, &reole, &doc, &selection); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text_in); - ITextRange_Release(txtRge); - release_interfaces(&w, &reOle, &txtDoc, NULL); + hr = ITextDocument_Range(doc, 0, 0, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); - hres = ITextPara_GetStyle(txtPara, &value); - ok(hres == CO_E_RELEASED, "ITextPara after ITextDocument destroyed\n"); + CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c") + CLIPBOARD_RANGE_CONTAINS(range, 0, 0, "ab\r\n c") + CLIPBOARD_RANGE_CONTAINS(range, 1, 1, "ab\r\n c") + CLIPBOARD_RANGE_CONTAINS(range, 0, 1, "a") + CLIPBOARD_RANGE_CONTAINS(range, 5, 6, "") + + /* Setting password char does not stop Copy */ + SendMessageA(hwnd, EM_SETPASSWORDCHAR, '*', 0); + CLIPBOARD_RANGE_CONTAINS(range, 0, 1, "a") + + /* Cut can be undone */ + hr = ITextRange_SetRange(range, 0, 1); + ok(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr); + hr = ITextRange_Cut(range, NULL); + ok(hr == S_OK, "Cut failed: 0x%08x\n", hr); + CLIPBOARD_RANGE_CONTAINS(range, 0, 4, "b\r\n c"); + hr = ITextDocument_Undo(doc, 1, NULL); + todo_wine ok(hr == S_OK, "Undo failed: 0x%08x\n", hr); + TODO_CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c"); + + /* Cannot cut when read-only */ + SendMessageA(hwnd, EM_SETREADONLY, TRUE, 0); + hr = ITextRange_SetRange(range, 0, 1); + ok(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr); + hr = ITextRange_Cut(range, NULL); + ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr); - ITextPara_Release(txtPara); + release_interfaces(&hwnd, &reole, &doc, NULL); + ITextSelection_Release(selection); + ITextRange_Release(range); } START_TEST(richole) @@ -4088,21 +4263,14 @@ START_TEST(richole) test_GetText(); test_ITextSelection_GetChar(); test_ITextSelection_GetStart_GetEnd(); - test_ITextSelection_SetStart(); - test_ITextSelection_SetEnd(); test_ITextSelection_Collapse(); - test_ITextSelection_GetFont(); test_ITextDocument_Range(); test_ITextRange_GetChar(); test_ITextRange_ScrollIntoView(); test_ITextRange_GetStart_GetEnd(); test_ITextRange_SetRange(); test_ITextRange_GetDuplicate(); - test_ITextRange_SetStart(); - test_ITextRange_SetEnd(); test_ITextRange_Collapse(); - test_ITextRange_GetFont(); - test_ITextRange_GetPara(); test_GetClientSite(); test_IOleWindow_GetWindow(); test_IOleInPlaceSite_GetWindow(); @@ -4121,5 +4289,7 @@ START_TEST(richole) test_GetStoryLength(); test_ITextSelection_GetDuplicate(); test_Expand(); - test_MoveEnd(); + test_MoveEnd_story(); + test_character_movement(); + test_clipboard(); } diff --git a/modules/rostests/winetests/riched20/txtsrv.c b/modules/rostests/winetests/riched20/txtsrv.c index dd290e3fb2f..1f789da8a37 100644 --- a/modules/rostests/winetests/riched20/txtsrv.c +++ b/modules/rostests/winetests/riched20/txtsrv.c @@ -48,7 +48,7 @@ static PCreateTextServices pCreateTextServices; /* Use a special table for x86 machines to convert the thiscall * calling convention. This isn't needed on other platforms. */ -#if defined(__i386__) && !defined(__MINGW32__) +#if defined(__i386__) && !defined(__MINGW32__) && (!defined(_MSC_VER) || !defined(__clang__)) static ITextServicesVtbl itextServicesStdcallVtbl; #define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl) #else /* __i386__ */ @@ -61,8 +61,8 @@ static ITextServicesVtbl itextServicesStdcallVtbl; #define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e) #define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) TXTSERV_VTABLE(This)->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) #define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) TXTSERV_VTABLE(This)->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) -#define ITextServices_OnTxInplaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInplaceActivate(This,a) -#define ITextServices_OnTxInplaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInplaceDeactivate(This) +#define ITextServices_OnTxInPlaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInPlaceActivate(This,a) +#define ITextServices_OnTxInPlaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInPlaceDeactivate(This) #define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This) #define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This) #define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a) @@ -85,7 +85,10 @@ typedef struct ITextHostTestImpl { ITextHost ITextHost_iface; LONG refCount; + HWND window; + RECT client_rect; CHARFORMAT2W char_format; + DWORD scrollbars, props; } ITextHostTestImpl; static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface) @@ -93,6 +96,11 @@ static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface) return CONTAINING_RECORD(iface, ITextHostTestImpl, ITextHost_iface); } +static const WCHAR lorem[] = L"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. " + "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. " + "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid, LPVOID *ppvObject) @@ -133,6 +141,7 @@ static HDC __thiscall ITextHostImpl_TxGetDC(ITextHost *iface) { ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetDC(%p)\n", This); + if (This->window) return GetDC( This->window ); return NULL; } @@ -140,6 +149,7 @@ static INT __thiscall ITextHostImpl_TxReleaseDC(ITextHost *iface, HDC hdc) { ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxReleaseDC(%p)\n", This); + if (This->window) return ReleaseDC( This->window, hdc ); return 0; } @@ -287,7 +297,8 @@ static HRESULT __thiscall ITextHostImpl_TxGetClientRect(ITextHost *iface, LPRECT { ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetClientRect(%p, prc=%p)\n", This, prc); - return E_NOTIMPL; + *prc = This->client_rect; + return S_OK; } static HRESULT __thiscall ITextHostImpl_TxGetViewInset(ITextHost *iface, LPRECT prc) @@ -333,12 +344,12 @@ static HRESULT __thiscall ITextHostImpl_TxGetMaxLength(ITextHost *iface, DWORD * return E_NOTIMPL; } -static HRESULT __thiscall ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *pdwScrollBar) +static HRESULT __thiscall ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *scrollbars) { ITextHostTestImpl *This = impl_from_ITextHost(iface); - TRACECALL("Call to TxGetScrollBars(%p, pdwScrollBar=%p)\n", - This, pdwScrollBar); - return E_NOTIMPL; + TRACECALL("Call to TxGetScrollBars(%p, scrollbars=%p)\n", This, scrollbars); + *scrollbars = This->scrollbars; + return S_OK; } static HRESULT __thiscall ITextHostImpl_TxGetPasswordChar(ITextHost *iface, WCHAR *pch) @@ -383,15 +394,28 @@ static HRESULT __thiscall ITextHostImpl_TxGetPropertyBits(ITextHost *iface, DWOR ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetPropertyBits(%p, dwMask=0x%08x, pdwBits=%p)\n", This, dwMask, pdwBits); - *pdwBits = 0; + *pdwBits = This->props & dwMask; return S_OK; } -static HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWORD iNotify, void *pv) +static int en_vscroll_sent; +static int en_update_sent; +static HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost *iface, DWORD code, void *data ) { ITextHostTestImpl *This = impl_from_ITextHost(iface); - TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This, iNotify, pv); - return E_NOTIMPL; + TRACECALL( "Call to TxNotify(%p, code = %#x, data = %p)\n", This, code, data ); + switch (code) + { + case EN_VSCROLL: + en_vscroll_sent++; + ok( !data, "got %p\n", data ); + break; + case EN_UPDATE: + en_update_sent++; + ok( !data, "got %p\n", data ); + break; + } + return S_OK; } static HIMC __thiscall ITextHostImpl_TxImmGetContext(ITextHost *iface) @@ -492,7 +516,7 @@ typedef struct static void setup_thiscall_wrappers(void) { -#if defined(__i386__) && !defined(__MINGW32__) +#if defined(__i386__) && !defined(__MINGW32__) && (!defined(_MSC_VER) || !defined(__clang__)) void** pVtable; void** pVtableEnd; THISCALL_TO_STDCALL_THUNK *thunk; @@ -591,9 +615,13 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret) } dummyTextHost->ITextHost_iface.lpVtbl = &itextHostVtbl; dummyTextHost->refCount = 1; + dummyTextHost->window = NULL; + SetRectEmpty( &dummyTextHost->client_rect ); memset(&dummyTextHost->char_format, 0, sizeof(dummyTextHost->char_format)); dummyTextHost->char_format.cbSize = sizeof(dummyTextHost->char_format); dummyTextHost->char_format.dwMask = CFM_ALL2; + dummyTextHost->scrollbars = 0; + dummyTextHost->props = 0; hf = GetStockObject(DEFAULT_GUI_FONT); hf_to_cf(hf, &dummyTextHost->char_format); @@ -602,6 +630,7 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret) ITextServices object. */ result = pCreateTextServices(NULL, &dummyTextHost->ITextHost_iface, &init); ok(result == S_OK, "Did not return S_OK when created (result = %x)\n", result); + ok(dummyTextHost->refCount == 1, "host ref %d\n", dummyTextHost->refCount); if (result != S_OK) { CoTaskMemFree(dummyTextHost); win_skip("CreateTextServices failed.\n"); @@ -621,9 +650,30 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret) return TRUE; } +static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj, + LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx, + LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user) +{ + reobj->cbStruct = sizeof(*reobj); + reobj->clsid = CLSID_NULL; + reobj->cp = cp; + reobj->poleobj = poleobj; + reobj->pstg = pstg; + reobj->polesite = polesite; + reobj->sizel.cx = sizel_cx; + reobj->sizel.cy = sizel_cy; + reobj->dvaspect = aspect; + reobj->dwFlags = flags; + reobj->dwUser = user; +} + static void test_TxGetText(void) { + const WCHAR *expected_string; + IOleClientSite *clientsite; ITextServices *txtserv; + IRichEditOle *reole; + REOBJECT reobject; ITextHost *host; HRESULT hres; BSTR rettext; @@ -635,6 +685,24 @@ static void test_TxGetText(void) ok(hres == S_OK, "ITextServices_TxGetText failed (result = %x)\n", hres); SysFreeString(rettext); + hres = ITextServices_TxSetText(txtserv, L"abcdefg"); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + hres = ITextServices_QueryInterface(txtserv, &IID_IRichEditOle, (void **)&reole); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + hres = IRichEditOle_GetClientSite(reole, &clientsite); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + expected_string = L"abc\xfffc""defg"; + fill_reobject_struct(&reobject, 3, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1); + hres = IRichEditOle_InsertObject(reole, &reobject); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + hres = ITextServices_TxGetText(txtserv, &rettext); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + ok(lstrlenW(rettext) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(rettext)); + todo_wine ok(!lstrcmpW(rettext, expected_string), "Got wrong content: %s.\n", debugstr_w(rettext)); + SysFreeString(rettext); + IOleClientSite_Release(clientsite); + IRichEditOle_Release(reole); + ITextServices_Release(txtserv); ITextHost_Release(host); } @@ -689,7 +757,7 @@ static void _check_txgetnaturalsize(HRESULT res, LONG width, LONG height, HDC hd expected_width = expected_rect.right - expected_rect.left; expected_height = expected_rect.bottom - expected_rect.top; ok_(__FILE__,line)(res == S_OK, "ITextServices_TxGetNaturalSize failed: 0x%08x.\n", res); - ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1, + todo_wine ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1, "got wrong width: %d, expected: %d {+1}.\n", width, expected_width); ok_(__FILE__,line)(height == expected_height, "got wrong height: %d, expected: %d.\n", height, expected_height); @@ -701,7 +769,7 @@ static void test_TxGetNaturalSize(void) ITextHost *host; HRESULT result; SIZEL extent; - static const WCHAR test_text[] = {'T','e','s','t','S','o','m','e','T','e','x','t',0}; + static const WCHAR test_text[] = L"TestSomeText"; LONG width, height; HDC hdcDraw; HWND hwnd; @@ -736,7 +804,7 @@ static void test_TxGetNaturalSize(void) height = 0; result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT, hdcDraw, NULL, NULL, TXTNS_FITTOCONTENT, &extent, &width, &height); - todo_wine CHECK_TXGETNATURALSIZE(result, width, height, hdcDraw, rect, test_text); + CHECK_TXGETNATURALSIZE(result, width, height, hdcDraw, rect, test_text); ReleaseDC(hwnd, hdcDraw); DestroyWindow(hwnd); @@ -748,26 +816,51 @@ static void test_TxDraw(void) { ITextServices *txtserv; ITextHost *host; - HDC tmphdc = GetDC(NULL); - DWORD dwAspect = DVASPECT_CONTENT; - HDC hicTargetDev = NULL; /* Means "default" device */ - DVTARGETDEVICE *ptd = NULL; - void *pvAspect = NULL; - HRESULT result; - RECTL client = {0,0,100,100}; - + HRESULT hr; + RECT client = {0, 0, 100, 100}; + ITextHostTestImpl *host_impl; + HDC hdc; if (!init_texthost(&txtserv, &host)) return; - todo_wine { - result = ITextServices_TxDraw(txtserv, dwAspect, 0, pvAspect, ptd, - tmphdc, hicTargetDev, &client, NULL, - NULL, NULL, 0, 0); - ok(result == S_OK, "TxDraw failed (result = %x)\n", result); - } - + host_impl = impl_from_ITextHost( host ); + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_CLIENTRECTCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, + host_impl->props ); + hdc = GetDC( host_impl->window ); + + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, (RECTL *)&client, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == E_FAIL, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, (RECTL *)&client, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, (RECTL *)&client, NULL, + NULL, NULL, 0, TXTVIEW_ACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ITextServices_OnTxInPlaceDeactivate( txtserv ); + + ReleaseDC( host_impl->window, hdc ); ITextServices_Release(txtserv); + DestroyWindow( host_impl->window ); ITextHost_Release(host); } @@ -863,6 +956,7 @@ static void test_QueryInterface(void) IRichEditOle *reole, *txtsrv_reole; ITextDocument *txtdoc, *txtsrv_txtdoc; ITextDocument2Old *txtdoc2old, *txtsrv_txtdoc2old; + IUnknown *unk, *unk2; ULONG refcount; if(!init_texthost(&txtserv, &host)) @@ -879,6 +973,14 @@ static void test_QueryInterface(void) refcount = get_refcount((IUnknown *)txtsrv_reole); ok(refcount == 2, "got wrong ref count: %d\n", refcount); + hres = ITextServices_QueryInterface( txtserv, &IID_IUnknown, (void **)&unk ); + ok( hres == S_OK, "got 0x%08x\n", hres ); + hres = IRichEditOle_QueryInterface( txtsrv_reole, &IID_IUnknown, (void **)&unk2 ); + ok( hres == S_OK, "got 0x%08x\n", hres ); + ok( unk == unk2, "unknowns differ\n" ); + IUnknown_Release( unk2 ); + IUnknown_Release( unk ); + hres = IRichEditOle_QueryInterface(txtsrv_reole, &IID_ITextDocument, (void **)&txtdoc); ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres); refcount = get_refcount((IUnknown *)txtserv); @@ -987,20 +1089,134 @@ static void test_TxGetScroll(void) ITextServices *txtserv; ITextHost *host; HRESULT ret; + LONG min_pos, max_pos, pos, page; + BOOL enabled; + ITextHostTestImpl *host_impl; + RECT client = {0, 0, 100, 100}; if (!init_texthost(&txtserv, &host)) return; + host_impl = impl_from_ITextHost( host ); + ret = ITextServices_TxGetHScroll(txtserv, NULL, NULL, NULL, NULL, NULL); - ok(ret == S_OK, "ITextSerHices_GetVScroll failed: 0x%08x.\n", ret); + ok(ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret); ret = ITextServices_TxGetVScroll(txtserv, NULL, NULL, NULL, NULL, NULL); - ok(ret == S_OK, "ITextServices_GetVScroll failed: 0x%08x.\n", ret); - + ok(ret == S_OK, "ITextServices_TxGetVScroll failed: 0x%08x.\n", ret); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); + ok( max_pos == 0, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == 0, "got %d\n", page ); + ok( !enabled, "got %d\n", enabled ); + + host_impl->scrollbars = WS_VSCROLL; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, host_impl->props ); + + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + ret = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( ret == S_OK, "got 0x%08x.\n", ret ); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); +todo_wine + ok( max_pos == 0, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == client.bottom, "got %d\n", page ); + ok( !enabled, "got %d\n", enabled ); + + ret = ITextServices_TxSetText( txtserv, lorem ); + ok( ret == S_OK, "got 0x%08x.\n", ret ); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); + ok( max_pos > client.bottom, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == client.bottom, "got %d\n", page ); + ok( enabled, "got %d\n", enabled ); + + host_impl->scrollbars = WS_VSCROLL | ES_DISABLENOSCROLL; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE, host_impl->props ); + ITextServices_TxSetText( txtserv, L"short" ); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); +todo_wine + ok( max_pos == 0, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == client.bottom, "got %d\n", page ); + ok( !enabled, "got %d\n", enabled ); + + DestroyWindow( host_impl->window ); ITextServices_Release(txtserv); ITextHost_Release(host); } +static void test_notifications( void ) +{ + ITextServices *txtserv; + ITextHost *host; + LRESULT res; + HRESULT hr; + RECT client = { 0, 0, 100, 100 }; + ITextHostTestImpl *host_impl; + + init_texthost( &txtserv, &host ); + host_impl = impl_from_ITextHost( host ); + + host_impl->scrollbars = WS_VSCROLL; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, host_impl->props ); + + ITextServices_TxSetText( txtserv, lorem ); + + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + hr = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( hr == S_OK, "got 0x%08x.\n", hr ); + + hr = ITextServices_TxSendMessage( txtserv, EM_SETEVENTMASK, 0, ENM_SCROLL, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* check EN_VSCROLL notification is sent */ + en_vscroll_sent = 0; + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, SB_LINEDOWN, 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 1, "got %d\n", en_vscroll_sent ); + + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, SB_BOTTOM, 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 2, "got %d\n", en_vscroll_sent ); + + /* but not when the thumb is moved */ + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, MAKEWPARAM( SB_THUMBTRACK, 0 ), 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, MAKEWPARAM( SB_THUMBPOSITION, 0 ), 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 2, "got %d\n", en_vscroll_sent ); + + /* EN_UPDATE is sent by TxDraw() */ + en_update_sent = 0; + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_ACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_update_sent == 1, "got %d\n", en_update_sent ); + + DestroyWindow( host_impl->window ); + ITextServices_Release( txtserv ); + ITextHost_Release( host ); +} + START_TEST( txtsrv ) { ITextServices *txtserv; @@ -1033,6 +1249,7 @@ START_TEST( txtsrv ) test_QueryInterface(); test_default_format(); test_TxGetScroll(); + test_notifications(); } if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE); } diff --git a/sdk/include/psdk/textserv.h b/sdk/include/psdk/textserv.h index 455e88c5581..16a9a534a91 100644 --- a/sdk/include/psdk/textserv.h +++ b/sdk/include/psdk/textserv.h @@ -33,9 +33,9 @@ extern "C" { #define THISCALLMETHOD_(type,method) type (__thiscall *method) #endif -DEFINE_GUID(IID_ITextServices,0x8d33f740,0xcf58,0x11ce,0xa8,0x9d,0x00,0xaa,0x00,0x6c,0xad,0xc5); -DEFINE_GUID(IID_ITextHost, 0xc5bdd8d0,0xd26e,0x11ce,0xa8,0x9e,0x00,0xaa,0x00,0x6c,0xad,0xc5); -DEFINE_GUID(IID_ITextHost2, 0xc5bdd8d0,0xd26e,0x11ce,0xa8,0x9e,0x00,0xaa,0x00,0x6c,0xad,0xc5); +EXTERN_C const IID IID_ITextServices; +EXTERN_C const IID IID_ITextHost; +EXTERN_C const IID IID_ITextHost2; /***************************************************************************** * ITextServices interface @@ -108,10 +108,10 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) INT y, DWORD* pHitResult) PURE; - THISCALLMETHOD_(HRESULT,OnTxInplaceActivate)( THIS_ + THISCALLMETHOD_(HRESULT,OnTxInPlaceActivate)( THIS_ LPCRECT prcClient) PURE; - THISCALLMETHOD_(HRESULT,OnTxInplaceDeactivate)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,OnTxInPlaceDeactivate)( THIS ) PURE; THISCALLMETHOD_(HRESULT,OnTxUIActivate)( THIS ) PURE; @@ -151,6 +151,7 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) DWORD* pdwHeight) PURE; }; +#undef INTERFACE #ifdef COBJMACROS /*** IUnknown methods ***/ @@ -159,8 +160,6 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) #define ITextServices_Release(p) (p)->lpVtbl->Release(p) #endif -#undef INTERFACE - typedef enum _TXTBACKSTYLE { TXTBACK_TRANSPARENT = 0, TXTBACK_OPAQUE @@ -180,7 +179,7 @@ enum TXTNATURALSIZE { enum TXTVIEW { TXTVIEW_ACTIVE = 0, - TXTVIEW_INACTIVE = 1 + TXTVIEW_INACTIVE = -1 }; #define TXTBIT_RICHTEXT 0x000001 @@ -361,6 +360,7 @@ DECLARE_INTERFACE_(ITextHost,IUnknown) LONG* lSelBarWidth) PURE; }; +#undef INTERFACE #ifdef COBJMACROS /*** IUnknown methods ***/ @@ -369,8 +369,80 @@ DECLARE_INTERFACE_(ITextHost,IUnknown) #define ITextHost_Release(p) (p)->lpVtbl->Release(p) #endif +/***************************************************************************** + * ITextHost2 interface + */ +#define INTERFACE ITextHost2 +DECLARE_INTERFACE_(ITextHost2,ITextHost) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)( THIS_ REFIID riid, void** ppvObject ) PURE; + STDMETHOD_(ULONG,AddRef)( THIS ) PURE; + STDMETHOD_(ULONG,Release)( THIS ) PURE; + /*** ITextHost methods ***/ + THISCALLMETHOD_(HDC,TxGetDC)( THIS ) PURE; + THISCALLMETHOD_(INT,TxReleaseDC)( THIS_ HDC hdc ) PURE; + THISCALLMETHOD_(BOOL,TxShowScrollBar)( THIS_ INT fnBar, BOOL fShow ) PURE; + THISCALLMETHOD_(BOOL,TxEnableScrollBar)( THIS_ INT fuSBFlags, INT fuArrowflags ) PURE; + THISCALLMETHOD_(BOOL,TxSetScrollRange)( THIS_ INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw ) PURE; + THISCALLMETHOD_(BOOL,TxSetScrollPos)( THIS_ INT fnBar, INT nPos, BOOL fRedraw ) PURE; + THISCALLMETHOD_(void,TxInvalidateRect)( THIS_ LPCRECT prc, BOOL fMode ) PURE; + THISCALLMETHOD_(void,TxViewChange)( THIS_ BOOL fUpdate ) PURE; + THISCALLMETHOD_(BOOL,TxCreateCaret)( THIS_ HBITMAP hbmp, INT xWidth, INT yHeight ) PURE; + THISCALLMETHOD_(BOOL,TxShowCaret)( THIS_ BOOL fShow ) PURE; + THISCALLMETHOD_(BOOL,TxSetCaretPos)( THIS_ INT x, INT y ) PURE; + THISCALLMETHOD_(BOOL,TxSetTimer)( THIS_ UINT idTimer, UINT uTimeout ) PURE; + THISCALLMETHOD_(void,TxKillTimer)( THIS_ UINT idTimer ) PURE; + THISCALLMETHOD_(void,TxScrollWindowEx)( THIS_ INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, + HRGN hRgnUpdate, LPRECT lprcUpdate, UINT fuScroll ) PURE; + THISCALLMETHOD_(void,TxSetCapture)( THIS_ BOOL fCapture ) PURE; + THISCALLMETHOD_(void,TxSetFocus)( THIS ) PURE; + THISCALLMETHOD_(void,TxSetCursor)( THIS_ HCURSOR hcur, BOOL fText ) PURE; + THISCALLMETHOD_(BOOL,TxScreenToClient)( THIS_ LPPOINT lppt ) PURE; + THISCALLMETHOD_(BOOL,TxClientToScreen)( THIS_ LPPOINT lppt ) PURE; + THISCALLMETHOD_(HRESULT,TxActivate)( THIS_ LONG* plOldState ) PURE; + THISCALLMETHOD_(HRESULT,TxDeactivate)( THIS_ LONG lNewState ) PURE; + THISCALLMETHOD_(HRESULT,TxGetClientRect)( THIS_ LPRECT prc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetViewInset)( THIS_ LPRECT prc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetCharFormat)( THIS_ const CHARFORMATW** ppCF ) PURE; + THISCALLMETHOD_(HRESULT,TxGetParaFormat)( THIS_ const PARAFORMAT** ppPF ) PURE; + THISCALLMETHOD_(COLORREF,TxGetSysColor)( THIS_ int nIndex ) PURE; + THISCALLMETHOD_(HRESULT,TxGetBackStyle)( THIS_ TXTBACKSTYLE* pStyle ) PURE; + THISCALLMETHOD_(HRESULT,TxGetMaxLength)( THIS_ DWORD* plength ) PURE; + THISCALLMETHOD_(HRESULT,TxGetScrollBars)( THIS_ DWORD* pdwScrollBar ) PURE; + THISCALLMETHOD_(HRESULT,TxGetPasswordChar)( THIS_ WCHAR* pch ) PURE; + THISCALLMETHOD_(HRESULT,TxGetAcceleratorPos)( THIS_ LONG* pch ) PURE; + THISCALLMETHOD_(HRESULT,TxGetExtent)( THIS_ LPSIZEL lpExtent ) PURE; + THISCALLMETHOD_(HRESULT,OnTxCharFormatChange)( THIS_ const CHARFORMATW* pcf ) PURE; + THISCALLMETHOD_(HRESULT,OnTxParaFormatChange)( THIS_ const PARAFORMAT* ppf ) PURE; + THISCALLMETHOD_(HRESULT,TxGetPropertyBits)( THIS_ DWORD dwMask, DWORD* pdwBits ) PURE; + THISCALLMETHOD_(HRESULT,TxNotify)( THIS_ DWORD iNotify, void* pv ) PURE; + THISCALLMETHOD_(HIMC,TxImmGetContext)( THIS ) PURE; + THISCALLMETHOD_(void,TxImmReleaseContext)( THIS_ HIMC himc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetSelectionBarWidth)( THIS_ LONG* lSelBarWidth ) PURE; + /* ITextHost2 methods */ + THISCALLMETHOD_(BOOL,TxIsDoubleClickPending)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetWindow)( THIS_ HWND *hwnd ) PURE; + THISCALLMETHOD_(HRESULT,TxSetForegroundWindow)( THIS ) PURE; + THISCALLMETHOD_(HPALETTE,TxGetPalette)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetEastAsianFlags)( THIS_ LONG *flags ) PURE; + THISCALLMETHOD_(HCURSOR,TxSetCursor2)( THIS_ HCURSOR cursor, BOOL text ) PURE; + THISCALLMETHOD_(void,TxFreeTextServicesNotification)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetEditStyle)( THIS_ DWORD item, DWORD *data ) PURE; + THISCALLMETHOD_(HRESULT,TxGetWindowStyles)( THIS_ DWORD *style, DWORD *ex_style ) PURE; + THISCALLMETHOD_(HRESULT,TxShowDropCaret)( THIS_ BOOL show, HDC hdc, const RECT *rect ) PURE; + THISCALLMETHOD_(HRESULT,TxDestroyCaret)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetHorzExtent)( THIS_ LONG *horz_extent ) PURE; +}; #undef INTERFACE +#ifdef COBJMACROS +/*** IUnknown methods ***/ +#define ITextHost2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define ITextHost2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define ITextHost2_Release(p) (p)->lpVtbl->Release(p) +#endif + HRESULT WINAPI CreateTextServices(IUnknown*,ITextHost*,IUnknown**); typedef HRESULT (WINAPI *PCreateTextServices)(IUnknown*,ITextHost*,IUnknown**); @@ -380,3 +452,4 @@ typedef HRESULT (WINAPI *PCreateTextServices)(IUnknown*,ITextHost*,IUnknown**); #endif #endif /* _TEXTSERV_H */ +