riched20/tests: Use correct integral type.
[wine.git] / dlls / riched20 / tests / richole.c
blob8d8ba5b1e9d2c6cadbe6597a68f319a23e6cf075
1 /*
2 * Tests for IRichEditOle and friends.
4 * Copyright 2008 Google (Dan Hipschman)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include <windef.h>
26 #include <winbase.h>
27 #include <wingdi.h>
28 #include <winuser.h>
29 #include <initguid.h>
30 #include <ole2.h>
31 #include <richedit.h>
32 #include <richole.h>
33 #include <tom.h>
34 #include <wine/test.h>
36 static HMODULE hmoduleRichEdit;
38 DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
40 static const WCHAR sysW[] = {'S','y','s','t','e','m',0};
42 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
43 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
45 ULONG rc;
46 IUnknown_AddRef(obj);
47 rc = IUnknown_Release(obj);
48 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
51 static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent)
53 HWND hwnd = CreateWindowA(lpClassName, NULL,
54 dwStyle | WS_POPUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
55 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL);
56 ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
57 return hwnd;
60 static HWND new_richedit(HWND parent)
62 return new_window(RICHEDIT_CLASS20A, ES_MULTILINE, parent);
65 static BOOL touch_file(LPCWSTR filename)
67 HANDLE file;
69 file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
70 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
72 if(file == INVALID_HANDLE_VALUE)
73 return FALSE;
74 CloseHandle(file);
75 return TRUE;
78 static BOOL is_existing_file(LPCWSTR filename)
80 HANDLE file;
82 file = CreateFileW(filename, GENERIC_READ, 0, NULL,
83 OPEN_EXISTING, 0, NULL);
84 if(file == INVALID_HANDLE_VALUE)
85 return FALSE;
86 CloseHandle(file);
87 return TRUE;
90 static void create_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc,
91 ITextSelection **txtSel)
93 *w = new_richedit(NULL);
94 SendMessageA(*w, EM_GETOLEINTERFACE, 0, (LPARAM)reOle);
95 IRichEditOle_QueryInterface(*reOle, &IID_ITextDocument,
96 (void **) txtDoc);
97 ITextDocument_GetSelection(*txtDoc, txtSel);
100 static void release_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc,
101 ITextSelection **txtSel)
103 if(txtSel)
104 ITextSelection_Release(*txtSel);
105 ITextDocument_Release(*txtDoc);
106 IRichEditOle_Release(*reOle);
107 DestroyWindow(*w);
110 static ULONG get_refcount(IUnknown *iface)
112 IUnknown_AddRef(iface);
113 return IUnknown_Release(iface);
116 #define CHECK_TYPEINFO(disp,expected_riid) _check_typeinfo((IDispatch *)disp, expected_riid, __LINE__)
117 static void _check_typeinfo(IDispatch* disp, REFIID expected_riid, int line)
119 ITypeInfo *typeinfo;
120 TYPEATTR *typeattr;
121 UINT count;
122 HRESULT hr;
124 count = 10;
125 hr = IDispatch_GetTypeInfoCount(disp, &count);
126 ok_(__FILE__,line)(hr == S_OK, "IDispatch_GetTypeInfoCount failed: 0x%08x.\n", hr);
127 ok_(__FILE__,line)(count == 1, "got wrong count: %u.\n", count);
129 hr = IDispatch_GetTypeInfo(disp, 0, LOCALE_SYSTEM_DEFAULT, &typeinfo);
130 ok_(__FILE__,line)(hr == S_OK, "IDispatch_GetTypeInfo failed: 0x%08x.\n", hr);
132 hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
133 ok_(__FILE__,line)(hr == S_OK, "ITypeInfo_GetTypeAttr failed: 0x%08x.\n", hr);
134 ok_(__FILE__,line)(IsEqualGUID(&typeattr->guid, expected_riid),
135 "Unexpected type guid: %s.\n", wine_dbgstr_guid(&typeattr->guid));
137 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
138 ITypeInfo_Release(typeinfo);
141 static void test_Interfaces(void)
143 IRichEditOle *reOle = NULL, *reOle1 = NULL;
144 ITextDocument *txtDoc = NULL;
145 ITextDocument2Old *txtDoc2Old = NULL;
146 ITextSelection *txtSel = NULL, *txtSel2;
147 IUnknown *punk;
148 HRESULT hres;
149 LRESULT res;
150 HWND w;
151 ULONG refcount;
152 IUnknown *unk, *unk2;
154 w = new_richedit(NULL);
155 if (!w) {
156 skip("Couldn't create window\n");
157 return;
160 res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle);
161 ok(res, "SendMessage\n");
162 ok(reOle != NULL, "EM_GETOLEINTERFACE\n");
163 EXPECT_REF(reOle, 2);
165 res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle1);
166 ok(res == 1, "SendMessage\n");
167 ok(reOle1 == reOle, "Should not return a new IRichEditOle interface\n");
168 EXPECT_REF(reOle, 3);
170 hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument,
171 (void **) &txtDoc);
172 ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
173 ok(txtDoc != NULL, "IRichEditOle_QueryInterface\n");
174 CHECK_TYPEINFO(txtDoc, &IID_ITextDocument);
176 hres = ITextDocument_GetSelection(txtDoc, NULL);
177 ok(hres == E_INVALIDARG, "ITextDocument_GetSelection: 0x%x\n", hres);
179 EXPECT_REF(txtDoc, 4);
181 hres = ITextDocument_GetSelection(txtDoc, &txtSel);
182 ok(hres == S_OK, "got 0x%08x\n", hres);
184 hres = ITextDocument_QueryInterface(txtDoc, &IID_IUnknown, (void **)&unk);
185 ok(hres == S_OK, "got 0x%08x\n", hres);
186 hres = ITextSelection_QueryInterface(txtSel, &IID_IUnknown, (void **)&unk2);
187 ok(hres == S_OK, "got 0x%08x\n", hres);
188 ok(unk != unk2, "unknowns are the same\n");
189 IUnknown_Release(unk2);
190 IUnknown_Release(unk);
192 EXPECT_REF(txtDoc, 4);
193 EXPECT_REF(txtSel, 2);
195 hres = ITextDocument_GetSelection(txtDoc, &txtSel2);
196 ok(hres == S_OK, "got 0x%08x\n", hres);
197 ok(txtSel2 == txtSel, "got %p, %p\n", txtSel, txtSel2);
199 EXPECT_REF(txtDoc, 4);
200 EXPECT_REF(txtSel, 3);
202 ITextSelection_Release(txtSel2);
204 punk = NULL;
205 hres = ITextSelection_QueryInterface(txtSel, &IID_ITextSelection, (void **) &punk);
206 ok(hres == S_OK, "ITextSelection_QueryInterface\n");
207 ok(punk != NULL, "ITextSelection_QueryInterface\n");
208 IUnknown_Release(punk);
210 punk = NULL;
211 hres = ITextSelection_QueryInterface(txtSel, &IID_ITextRange, (void **) &punk);
212 ok(hres == S_OK, "ITextSelection_QueryInterface\n");
213 ok(punk != NULL, "ITextSelection_QueryInterface\n");
214 IUnknown_Release(punk);
216 punk = NULL;
217 hres = ITextSelection_QueryInterface(txtSel, &IID_IDispatch, (void **) &punk);
218 ok(hres == S_OK, "ITextSelection_QueryInterface\n");
219 ok(punk != NULL, "ITextSelection_QueryInterface\n");
220 IUnknown_Release(punk);
222 punk = NULL;
223 hres = IRichEditOle_QueryInterface(reOle, &IID_IOleClientSite, (void **) &punk);
224 ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
226 punk = NULL;
227 hres = IRichEditOle_QueryInterface(reOle, &IID_IOleWindow, (void **) &punk);
228 ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
230 punk = NULL;
231 hres = IRichEditOle_QueryInterface(reOle, &IID_IOleInPlaceSite, (void **) &punk);
232 ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
234 hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument2Old, (void **)&txtDoc2Old);
235 ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
236 ok(txtDoc2Old != NULL, "IRichEditOle_QueryInterface\n");
237 ok((ITextDocument *)txtDoc2Old == txtDoc, "interface pointer isn't equal.\n");
238 EXPECT_REF(txtDoc2Old, 5);
239 EXPECT_REF(reOle, 5);
240 CHECK_TYPEINFO(txtDoc2Old, &IID_ITextDocument);
242 ITextDocument2Old_Release(txtDoc2Old);
244 ITextDocument_Release(txtDoc);
245 IRichEditOle_Release(reOle);
246 refcount = IRichEditOle_Release(reOle);
247 ok(refcount == 1, "got wrong ref count: %d\n", refcount);
248 DestroyWindow(w);
250 /* Methods should return CO_E_RELEASED if the backing document has
251 been released. One test should suffice. */
252 hres = ITextSelection_CanEdit(txtSel, NULL);
253 ok(hres == CO_E_RELEASED, "ITextSelection after ITextDocument destroyed\n");
255 ITextSelection_Release(txtSel);
257 w = new_richedit(NULL);
258 res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle);
259 ok(res, "SendMessage\n");
260 ok(reOle != NULL, "EM_GETOLEINTERFACE\n");
262 hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument2Old, (void **)&txtDoc2Old);
263 ok(hres == S_OK, "IRichEditOle_QueryInterface failed: 0x%08x.\n", hres);
264 ok(txtDoc2Old != NULL, "IRichEditOle_QueryInterface\n");
265 CHECK_TYPEINFO(txtDoc2Old, &IID_ITextDocument);
266 ITextDocument2Old_Release(txtDoc2Old);
267 IRichEditOle_Release(reOle);
268 DestroyWindow(w);
271 static void test_ITextDocument_Open(void)
273 IRichEditOle *reOle = NULL;
274 ITextDocument *txtDoc = NULL;
275 ITextSelection *txtSel = NULL;
276 HRESULT hres;
277 HWND w;
278 HANDLE hFile;
279 VARIANT testfile;
280 WCHAR filename[] = {'t', 'e', 's', 't','.','t','x','t', 0};
281 int result;
282 DWORD dw;
283 static const CHAR chACP[] = "TestSomeText";
284 static const CHAR chUTF8[] = "\xef\xbb\xbfTextWithUTF8BOM";
285 static const WCHAR chUTF16[] = {0xfeff, 'T', 'e', 's', 't', 'S', 'o', 'm',
286 'e', 'T', 'e', 'x', 't', 0};
288 #define MAX_BUF_LEN 1024
289 CHAR bufACP[MAX_BUF_LEN];
290 WCHAR bufUnicode[MAX_BUF_LEN];
292 static const int tomConstantsSingle[] =
294 tomReadOnly, tomShareDenyRead, tomShareDenyWrite,
295 tomCreateAlways, tomOpenExisting, tomOpenAlways,
296 tomTruncateExisting, tomRTF, tomText
299 static const int tomConstantsMulti[] =
301 tomReadOnly|tomShareDenyRead|tomPasteFile, tomReadOnly|tomPasteFile,
302 tomReadOnly|tomShareDenyWrite|tomPasteFile,
303 tomReadOnly|tomShareDenyRead|tomShareDenyWrite|tomPasteFile, tomShareDenyWrite|tomPasteFile,
304 tomShareDenyRead|tomShareDenyWrite|tomPasteFile, tomShareDenyRead|tomPasteFile,
305 tomShareDenyRead|tomShareDenyWrite, tomReadOnly|tomShareDenyRead|tomShareDenyWrite,
306 tomReadOnly|tomShareDenyWrite, tomReadOnly|tomShareDenyRead
309 int tomNumSingle = ARRAY_SIZE(tomConstantsSingle);
310 int tomNumMulti = ARRAY_SIZE(tomConstantsMulti);
311 int i;
313 V_VT(&testfile) = VT_BSTR;
314 V_BSTR(&testfile) = SysAllocString(filename);
316 for(i=0; i < tomNumSingle; i++)
318 touch_file(filename);
319 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
320 hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_ACP);
321 todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
322 tomConstantsSingle[i], hres);
323 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
324 DeleteFileW(filename);
326 touch_file(filename);
327 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
328 hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_UTF8);
329 todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
330 tomConstantsSingle[i], hres);
331 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
332 DeleteFileW(filename);
335 for(i=0; i < tomNumMulti; i++)
337 touch_file(filename);
338 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
339 hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_ACP);
340 todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
341 tomConstantsMulti[i], hres);
342 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
343 DeleteFileW(filename);
345 touch_file(filename);
346 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
347 hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_UTF8);
348 todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
349 tomConstantsMulti[i], hres);
350 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
351 DeleteFileW(filename);
354 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
355 hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_ACP);
356 todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
357 todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
358 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
359 DeleteFileW(filename);
361 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
362 hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_UTF8);
363 todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
364 todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
365 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
366 DeleteFileW(filename);
368 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
369 hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_ACP);
370 todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
371 todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
372 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
373 DeleteFileW(filename);
375 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
376 hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_UTF8);
377 todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
378 todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
379 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
380 DeleteFileW(filename);
382 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
383 hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
384 todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
385 todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
386 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
387 DeleteFileW(filename);
389 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
390 hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
391 todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
392 todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
393 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
394 DeleteFileW(filename);
396 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
397 touch_file(filename);
398 hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
399 todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_ACP\n");
400 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
401 DeleteFileW(filename);
403 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
404 touch_file(filename);
405 hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
406 todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
407 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
408 DeleteFileW(filename);
410 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
411 hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_ACP);
412 todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_ACP\n");
413 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
415 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
416 hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_UTF8);
417 todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
418 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
420 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
421 DeleteFileW(filename);
422 hres = ITextDocument_Open(txtDoc, &testfile, tomText, CP_ACP);
423 todo_wine {
424 ok(hres == S_OK, "got 0x%08x\n", hres);
425 ok(is_existing_file(filename) == TRUE, "a file should be created default\n");
427 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
428 DeleteFileW(filename);
430 /* test of share mode */
431 touch_file(filename);
432 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
433 hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyRead, CP_ACP);
434 todo_wine
435 ok(hres == S_OK, "got 0x%08x\n", hres);
436 SetLastError(0xdeadbeef);
437 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
438 FILE_ATTRIBUTE_NORMAL, NULL);
439 todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
440 CloseHandle(hFile);
441 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
442 DeleteFileW(filename);
444 touch_file(filename);
445 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
446 hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite, CP_ACP);
447 todo_wine
448 ok(hres == S_OK, "got 0x%08x\n", hres);
449 SetLastError(0xdeadbeef);
450 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
451 FILE_ATTRIBUTE_NORMAL, NULL);
452 todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
453 CloseHandle(hFile);
454 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
455 DeleteFileW(filename);
457 touch_file(filename);
458 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
459 SetLastError(0xdeadbeef);
460 hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite|tomShareDenyRead, CP_ACP);
461 todo_wine
462 ok(hres == S_OK, "got 0x%08x\n", hres);
463 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
464 FILE_ATTRIBUTE_NORMAL, NULL);
465 todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
466 CloseHandle(hFile);
467 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
468 DeleteFileW(filename);
470 /* tests to check the content */
471 hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
472 FILE_ATTRIBUTE_NORMAL, NULL);
473 WriteFile(hFile, chACP, sizeof(chACP)-sizeof(CHAR), &dw, NULL);
474 CloseHandle(hFile);
475 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
476 hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_ACP);
477 todo_wine
478 ok(hres == S_OK, "got 0x%08x\n", hres);
479 result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
480 todo_wine ok(result == 12, "ITextDocument_Open: Test ASCII returned %d, expected 12\n", result);
481 result = strcmp(bufACP, chACP);
482 todo_wine ok(result == 0, "ITextDocument_Open: Test ASCII set wrong text: Result: %s\n", bufACP);
483 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
484 DeleteFileW(filename);
486 hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
487 FILE_ATTRIBUTE_NORMAL, NULL);
488 WriteFile(hFile, chUTF8, sizeof(chUTF8)-sizeof(CHAR), &dw, NULL);
489 CloseHandle(hFile);
490 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
491 hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_UTF8);
492 todo_wine
493 ok(hres == S_OK, "got 0x%08x\n", hres);
494 result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
495 todo_wine ok(result == 15, "ITextDocument_Open: Test UTF-8 returned %d, expected 15\n", result);
496 result = strcmp(bufACP, &chUTF8[3]);
497 todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-8 set wrong text: Result: %s\n", bufACP);
498 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
499 DeleteFileW(filename);
501 hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
502 FILE_ATTRIBUTE_NORMAL, NULL);
503 WriteFile(hFile, chUTF16, sizeof(chUTF16)-sizeof(WCHAR), &dw, NULL);
504 CloseHandle(hFile);
505 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
506 hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, 1200);
507 todo_wine
508 ok(hres == S_OK, "got 0x%08x\n", hres);
509 result = SendMessageW(w, WM_GETTEXT, 1024, (LPARAM)bufUnicode);
510 todo_wine ok(result == 12, "ITextDocument_Open: Test UTF-16 returned %d, expected 12\n", result);
511 result = lstrcmpW(bufUnicode, &chUTF16[1]);
512 todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-16 set wrong text: Result: %s\n", wine_dbgstr_w(bufUnicode));
513 release_interfaces(&w, &reOle, &txtDoc, &txtSel);
514 DeleteFileW(filename);
516 VariantClear(&testfile);
519 static void test_GetText(void)
521 HWND w;
522 IRichEditOle *reOle = NULL;
523 ITextDocument *txtDoc = NULL;
524 ITextSelection *txtSel = NULL;
525 HRESULT hres;
526 BSTR bstr = NULL;
527 int first, lim;
528 static const CHAR test_text1[] = "TestSomeText";
529 static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0};
530 static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0};
531 static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0};
532 static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm',
533 'e', 'T', 'e', 'x', 't', '\r', 0};
534 static const WCHAR bufW5[] = {'\r', 0};
535 static const WCHAR bufW6[] = {'T','e','s','t','S','o','m','e','T',0};
536 BOOL is64bit = sizeof(void *) > sizeof(int);
537 ITextRange *range;
539 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
540 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
542 /* ITextSelection */
543 first = 0; lim = 4;
544 SendMessageA(w, EM_SETSEL, first, lim);
545 hres = ITextSelection_GetText(txtSel, &bstr);
546 ok(hres == S_OK, "ITextSelection_GetText\n");
547 ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
548 SysFreeString(bstr);
550 first = 4; lim = 0;
551 SendMessageA(w, EM_SETSEL, first, lim);
552 hres = ITextSelection_GetText(txtSel, &bstr);
553 ok(hres == S_OK, "ITextSelection_GetText\n");
554 ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
555 SysFreeString(bstr);
557 first = 1; lim = 1;
558 SendMessageA(w, EM_SETSEL, first, lim);
559 hres = ITextSelection_GetText(txtSel, &bstr);
560 ok(hres == S_OK, "ITextSelection_GetText\n");
561 ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
563 if (!is64bit)
565 hres = ITextSelection_GetText(txtSel, NULL);
566 ok(hres == E_INVALIDARG, "ITextSelection_GetText\n");
569 first = 8; lim = 12;
570 SendMessageA(w, EM_SETSEL, first, lim);
571 hres = ITextSelection_GetText(txtSel, &bstr);
572 ok(hres == S_OK, "ITextSelection_GetText\n");
573 ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
574 SysFreeString(bstr);
576 first = 8; lim = 13;
577 SendMessageA(w, EM_SETSEL, first, lim);
578 hres = ITextSelection_GetText(txtSel, &bstr);
579 ok(hres == S_OK, "ITextSelection_GetText\n");
580 ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
581 SysFreeString(bstr);
583 first = 12; lim = 13;
584 SendMessageA(w, EM_SETSEL, first, lim);
585 hres = ITextSelection_GetText(txtSel, &bstr);
586 ok(hres == S_OK, "ITextSelection_GetText\n");
587 ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
588 SysFreeString(bstr);
590 first = 0; lim = -1;
591 SendMessageA(w, EM_SETSEL, first, lim);
592 hres = ITextSelection_GetText(txtSel, &bstr);
593 ok(hres == S_OK, "ITextSelection_GetText\n");
594 ok(!lstrcmpW(bstr, bufW4), "got wrong text: %s\n", wine_dbgstr_w(bstr));
595 SysFreeString(bstr);
597 first = -1; lim = 9;
598 SendMessageA(w, EM_SETSEL, first, lim);
599 hres = ITextSelection_GetText(txtSel, &bstr);
600 ok(hres == S_OK, "ITextSelection_GetText\n");
601 ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
603 /* ITextRange */
604 hres = ITextDocument_Range(txtDoc, 0, 4, &range);
605 ok(hres == S_OK, "got 0x%08x\n", hres);
606 hres = ITextRange_GetText(range, &bstr);
607 ok(hres == S_OK, "got 0x%08x\n", hres);
608 ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
610 SysFreeString(bstr);
611 ITextRange_Release(range);
613 hres = ITextDocument_Range(txtDoc, 4, 0, &range);
614 ok(hres == S_OK, "got 0x%08x\n", hres);
615 hres = ITextRange_GetText(range, &bstr);
616 ok(hres == S_OK, "got 0x%08x\n", hres);
617 ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
619 SysFreeString(bstr);
620 ITextRange_Release(range);
622 hres = ITextDocument_Range(txtDoc, 1, 1, &range);
623 ok(hres == S_OK, "got 0x%08x\n", hres);
624 hres = ITextRange_GetText(range, &bstr);
625 ok(hres == S_OK, "got 0x%08x\n", hres);
626 ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
627 if (!is64bit)
629 hres = ITextRange_GetText(range, NULL);
630 ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
632 ITextRange_Release(range);
634 hres = ITextDocument_Range(txtDoc, 8, 12, &range);
635 ok(hres == S_OK, "got 0x%08x\n", hres);
636 hres = ITextRange_GetText(range, &bstr);
637 ok(hres == S_OK, "got 0x%08x\n", hres);
638 ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
640 SysFreeString(bstr);
641 ITextRange_Release(range);
643 hres = ITextDocument_Range(txtDoc, 8, 13, &range);
644 ok(hres == S_OK, "got 0x%08x\n", hres);
645 hres = ITextRange_GetText(range, &bstr);
646 ok(hres == S_OK, "got 0x%08x\n", hres);
647 ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
649 SysFreeString(bstr);
650 ITextRange_Release(range);
652 hres = ITextDocument_Range(txtDoc, 12, 13, &range);
653 ok(hres == S_OK, "got 0x%08x\n", hres);
654 hres = ITextRange_GetText(range, &bstr);
655 ok(hres == S_OK, "got 0x%08x\n", hres);
656 ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
658 SysFreeString(bstr);
659 ITextRange_Release(range);
661 hres = ITextDocument_Range(txtDoc, 0, -1, &range);
662 ok(hres == S_OK, "got 0x%08x\n", hres);
663 hres = ITextRange_GetText(range, &bstr);
664 ok(hres == S_OK, "got 0x%08x\n", hres);
665 ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
666 ITextRange_Release(range);
668 hres = ITextDocument_Range(txtDoc, -1, 9, &range);
669 ok(hres == S_OK, "got 0x%08x\n", hres);
670 hres = ITextRange_GetText(range, &bstr);
671 ok(hres == S_OK, "got 0x%08x\n", hres);
672 ok(!lstrcmpW(bstr, bufW6), "got wrong text: %s\n", wine_dbgstr_w(bstr));
674 SysFreeString(bstr);
676 release_interfaces(&w, &reOle, &txtDoc, NULL);
678 /* detached selection/range */
679 if (is64bit) {
680 bstr = (void*)0xdeadbeef;
681 hres = ITextSelection_GetText(txtSel, &bstr);
682 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
683 todo_wine
684 ok(bstr == NULL, "got %p\n", bstr);
686 bstr = (void*)0xdeadbeef;
687 hres = ITextRange_GetText(range, &bstr);
688 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
689 todo_wine
690 ok(bstr == NULL, "got %p\n", bstr);
692 else {
693 hres = ITextSelection_GetText(txtSel, NULL);
694 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
696 hres = ITextRange_GetText(range, NULL);
697 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
700 ITextRange_Release(range);
701 ITextSelection_Release(txtSel);
704 static void test_ITextDocument_Range(void)
706 static const CHAR test_text1[] = "TestSomeText";
707 HWND w;
708 IRichEditOle *reOle = NULL;
709 ITextDocument *txtDoc = NULL;
710 ITextRange *txtRge, *range2;
711 HRESULT hres;
712 LONG value;
714 create_interfaces(&w, &reOle, &txtDoc, NULL);
715 hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
716 ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
717 EXPECT_REF(txtRge, 1);
719 hres = ITextDocument_Range(txtDoc, 0, 0, &range2);
720 ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
721 ok(range2 != txtRge, "A new pointer should be returned\n");
722 ITextRange_Release(range2);
724 hres = ITextDocument_Range(txtDoc, 0, 0, NULL);
725 ok(hres == E_INVALIDARG, "ITextDocument_Range should fail 0x%x.\n", hres);
727 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
729 hres = ITextDocument_Range(txtDoc, 8, 30, &range2);
730 ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
731 hres = ITextRange_GetStart(range2, &value);
732 ok(hres == S_OK, "got 0x%08x\n", hres);
733 ok(value == 8, "got %d\n", value);
735 hres = ITextRange_GetEnd(range2, &value);
736 ok(hres == S_OK, "got 0x%08x\n", hres);
737 ok(value == 13, "got %d\n", value);
738 ITextRange_Release(range2);
740 release_interfaces(&w, &reOle, &txtDoc, NULL);
741 hres = ITextRange_CanEdit(txtRge, NULL);
742 ok(hres == CO_E_RELEASED, "ITextRange after ITextDocument destroyed\n");
743 ITextRange_Release(txtRge);
746 static void test_ITextRange_GetChar(void)
748 HWND w;
749 IRichEditOle *reOle = NULL;
750 ITextDocument *txtDoc = NULL;
751 ITextRange *txtRge = NULL;
752 HRESULT hres;
753 LONG pch;
754 int first, lim;
755 static const CHAR test_text1[] = "TestSomeText";
757 first = 0, lim = 4;
758 create_interfaces(&w, &reOle, &txtDoc, NULL);
759 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
760 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
761 ok(hres == S_OK, "got 0x%08x\n", hres);
762 pch = 0xdeadbeef;
763 hres = ITextRange_GetChar(txtRge, &pch);
764 ok(hres == S_OK, "ITextRange_GetChar\n");
765 ok(pch == 'T', "got wrong char: %c\n", pch);
766 ITextRange_Release(txtRge);
767 release_interfaces(&w, &reOle, &txtDoc, NULL);
769 first = 0; lim = 0;
770 create_interfaces(&w, &reOle, &txtDoc, NULL);
771 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
772 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
773 ok(hres == S_OK, "got 0x%08x\n", hres);
774 pch = 0xdeadbeef;
775 hres = ITextRange_GetChar(txtRge, &pch);
776 ok(hres == S_OK, "ITextRange_GetChar\n");
777 ok(pch == 'T', "got wrong char: %c\n", pch);
778 ITextRange_Release(txtRge);
779 release_interfaces(&w, &reOle, &txtDoc, NULL);
781 first = 12; lim = 12;
782 create_interfaces(&w, &reOle, &txtDoc, NULL);
783 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
784 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
785 ok(hres == S_OK, "got 0x%08x\n", hres);
786 pch = 0xdeadbeef;
787 hres = ITextRange_GetChar(txtRge, &pch);
788 ok(hres == S_OK, "ITextRange_GetChar\n");
789 ok(pch == '\r', "got wrong char: %c\n", pch);
790 ITextRange_Release(txtRge);
791 release_interfaces(&w, &reOle, &txtDoc, NULL);
793 first = 13; lim = 13;
794 create_interfaces(&w, &reOle, &txtDoc, NULL);
795 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
796 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
797 ok(hres == S_OK, "got 0x%08x\n", hres);
798 pch = 0xdeadbeef;
799 hres = ITextRange_GetChar(txtRge, &pch);
800 ok(hres == S_OK, "ITextRange_GetChar\n");
801 ok(pch == '\r', "got wrong char: %c\n", pch);
802 ITextRange_Release(txtRge);
803 release_interfaces(&w, &reOle, &txtDoc, NULL);
805 create_interfaces(&w, &reOle, &txtDoc, NULL);
806 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
807 first = 12; lim = 12;
808 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
809 ok(hres == S_OK, "got 0x%08x\n", hres);
810 hres = ITextRange_GetChar(txtRge, NULL);
811 ok(hres == E_INVALIDARG, "ITextRange_GetChar\n");
813 release_interfaces(&w, &reOle, &txtDoc, NULL);
815 hres = ITextRange_GetChar(txtRge, NULL);
816 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
818 hres = ITextRange_GetChar(txtRge, &pch);
819 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
821 ITextRange_Release(txtRge);
824 /* Helper function for testing ITextRange_ScrollIntoView */
825 static void check_range(HWND w, ITextDocument* doc, int first, int lim,
826 LONG bStart, int expected_nonzero)
828 SCROLLINFO si;
829 ITextRange *txtRge = NULL;
830 HRESULT hres;
832 si.cbSize = sizeof(SCROLLINFO);
833 si.fMask = SIF_POS | SIF_RANGE;
835 hres = ITextDocument_Range(doc, first, lim, &txtRge);
836 ok(hres == S_OK, "got 0x%08x\n", hres);
837 hres = ITextRange_ScrollIntoView(txtRge, bStart);
838 ok(hres == S_OK, "got 0x%08x\n", hres);
839 GetScrollInfo(w, SB_VERT, &si);
840 if (expected_nonzero) {
841 ok(si.nPos != 0,
842 "Scrollbar at 0, should be >0. (TextRange %d-%d, scroll range %d-%d.)\n",
843 first, lim, si.nMin, si.nMax);
844 } else {
845 ok(si.nPos == 0,
846 "Scrollbar at %d, should be 0. (TextRange %d-%d, scroll range %d-%d.)\n",
847 si.nPos, first, lim, si.nMin, si.nMax);
851 static void test_ITextRange_ScrollIntoView(void)
853 HWND w;
854 IRichEditOle *reOle = NULL;
855 ITextDocument *txtDoc = NULL;
856 ITextRange *txtRge = NULL;
857 HRESULT hres;
858 static const CHAR test_text1[] = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10";
860 create_interfaces(&w, &reOle, &txtDoc, NULL);
861 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
863 /* Scroll to the top. */
864 check_range(w, txtDoc, 0, 1, tomStart, 0);
865 check_range(w, txtDoc, 0, 1, tomEnd, 0);
867 /* Scroll to the bottom. */
868 check_range(w, txtDoc, 19, 20, tomStart, 1);
869 check_range(w, txtDoc, 19, 20, tomEnd, 1);
871 /* Back up to the top. */
872 check_range(w, txtDoc, 0, 1, tomStart, 0);
873 check_range(w, txtDoc, 0, 1, tomEnd, 0);
875 /* Large range */
876 check_range(w, txtDoc, 0, 20, tomStart, 0);
877 check_range(w, txtDoc, 0, 20, tomEnd, 1);
879 hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
880 ok(hres == S_OK, "got 0x%08x\n", hres);
881 release_interfaces(&w, &reOle, &txtDoc, NULL);
882 hres = ITextRange_ScrollIntoView(txtRge, tomStart);
883 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
884 ITextRange_Release(txtRge);
887 static void test_ITextSelection_GetChar(void)
889 HWND w;
890 IRichEditOle *reOle = NULL;
891 ITextDocument *txtDoc = NULL;
892 ITextSelection *txtSel = NULL;
893 HRESULT hres;
894 LONG pch;
895 int first, lim;
896 static const CHAR test_text1[] = "TestSomeText";
898 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
899 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
901 first = 0; lim = 4;
902 SendMessageA(w, EM_SETSEL, first, lim);
903 pch = 0xdeadbeef;
904 hres = ITextSelection_GetChar(txtSel, &pch);
905 ok(hres == S_OK, "ITextSelection_GetChar\n");
906 ok(pch == 'T', "got wrong char: %c\n", pch);
908 first = 0; lim = 0;
909 SendMessageA(w, EM_SETSEL, first, lim);
910 pch = 0xdeadbeef;
911 hres = ITextSelection_GetChar(txtSel, &pch);
912 ok(hres == S_OK, "ITextSelection_GetChar\n");
913 ok(pch == 'T', "got wrong char: %c\n", pch);
915 first = 12; lim = 12;
916 SendMessageA(w, EM_SETSEL, first, lim);
917 pch = 0xdeadbeef;
918 hres = ITextSelection_GetChar(txtSel, &pch);
919 ok(hres == S_OK, "ITextSelection_GetChar\n");
920 ok(pch == '\r', "got wrong char: %c\n", pch);
922 first = 13; lim = 13;
923 SendMessageA(w, EM_SETSEL, first, lim);
924 pch = 0xdeadbeef;
925 hres = ITextSelection_GetChar(txtSel, &pch);
926 ok(hres == S_OK, "ITextSelection_GetChar\n");
927 ok(pch == '\r', "got wrong char: %c\n", pch);
929 hres = ITextSelection_GetChar(txtSel, NULL);
930 ok(hres == E_INVALIDARG, "ITextSelection_GetChar\n");
932 release_interfaces(&w, &reOle, &txtDoc, NULL);
934 hres = ITextSelection_GetChar(txtSel, NULL);
935 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
937 hres = ITextSelection_GetChar(txtSel, &pch);
938 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
940 ITextSelection_Release(txtSel);
943 static void test_ITextRange_GetStart_GetEnd(void)
945 HWND w;
946 IRichEditOle *reOle = NULL;
947 ITextDocument *txtDoc = NULL;
948 ITextRange *txtRge = NULL;
949 HRESULT hres;
950 int first, lim;
951 LONG start, end;
952 static const CHAR test_text1[] = "TestSomeText";
954 create_interfaces(&w, &reOle, &txtDoc, NULL);
955 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
957 first = 1; lim = 6;
958 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
959 ok(hres == S_OK, "got 0x%08x\n", hres);
960 start = 0xdeadbeef;
961 hres = ITextRange_GetStart(txtRge, &start);
962 ok(hres == S_OK, "ITextRange_GetStart\n");
963 ok(start == 1, "got wrong start value: %d\n", start);
964 end = 0xdeadbeef;
965 hres = ITextRange_GetEnd(txtRge, &end);
966 ok(hres == S_OK, "ITextRange_GetEnd\n");
967 ok(end == 6, "got wrong end value: %d\n", end);
968 ITextRange_Release(txtRge);
970 first = 6; lim = 1;
971 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
972 ok(hres == S_OK, "got 0x%08x\n", hres);
973 start = 0xdeadbeef;
974 hres = ITextRange_GetStart(txtRge, &start);
975 ok(hres == S_OK, "ITextRange_GetStart\n");
976 ok(start == 1, "got wrong start value: %d\n", start);
977 end = 0xdeadbeef;
978 hres = ITextRange_GetEnd(txtRge, &end);
979 ok(hres == S_OK, "ITextRange_GetEnd\n");
980 ok(end == 6, "got wrong end value: %d\n", end);
981 ITextRange_Release(txtRge);
983 first = -1; lim = 13;
984 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
985 ok(hres == S_OK, "got 0x%08x\n", hres);
986 start = 0xdeadbeef;
987 hres = ITextRange_GetStart(txtRge, &start);
988 ok(hres == S_OK, "ITextRange_GetStart\n");
989 ok(start == 0, "got wrong start value: %d\n", start);
990 end = 0xdeadbeef;
991 hres = ITextRange_GetEnd(txtRge, &end);
992 ok(hres == S_OK, "ITextRange_GetEnd\n");
993 ok(end == 13, "got wrong end value: %d\n", end);
994 ITextRange_Release(txtRge);
996 first = 13; lim = 13;
997 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
998 ok(hres == S_OK, "got 0x%08x\n", hres);
999 start = 0xdeadbeef;
1000 hres = ITextRange_GetStart(txtRge, &start);
1001 ok(hres == S_OK, "ITextRange_GetStart\n");
1002 ok(start == 12, "got wrong start value: %d\n", start);
1003 end = 0xdeadbeef;
1004 hres = ITextRange_GetEnd(txtRge, &end);
1005 ok(hres == S_OK, "ITextRange_GetEnd\n");
1006 ok(end == 12, "got wrong end value: %d\n", end);
1008 /* SetStart */
1009 hres = ITextRange_SetStart(txtRge, 0);
1010 ok(hres == S_OK, "got 0x%08x\n", hres);
1012 /* same value */
1013 hres = ITextRange_SetStart(txtRge, 0);
1014 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1016 hres = ITextRange_SetStart(txtRge, 1);
1017 ok(hres == S_OK, "got 0x%08x\n", hres);
1019 /* negative resets to 0, return value is S_FALSE when
1020 position wasn't changed */
1021 hres = ITextRange_SetStart(txtRge, -1);
1022 ok(hres == S_OK, "got 0x%08x\n", hres);
1024 hres = ITextRange_SetStart(txtRge, -1);
1025 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1027 hres = ITextRange_SetStart(txtRge, 0);
1028 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1030 start = -1;
1031 hres = ITextRange_GetStart(txtRge, &start);
1032 ok(hres == S_OK, "got 0x%08x\n", hres);
1033 ok(start == 0, "got %d\n", start);
1035 /* greater than initial end, but less than total char count */
1036 hres = ITextRange_SetStart(txtRge, 1);
1037 ok(hres == S_OK, "got 0x%08x\n", hres);
1039 hres = ITextRange_SetEnd(txtRge, 3);
1040 ok(hres == S_OK, "got 0x%08x\n", hres);
1042 hres = ITextRange_SetStart(txtRge, 10);
1043 ok(hres == S_OK, "got 0x%08x\n", hres);
1045 start = 0;
1046 hres = ITextRange_GetStart(txtRge, &start);
1047 ok(hres == S_OK, "got 0x%08x\n", hres);
1048 ok(start == 10, "got %d\n", start);
1050 end = 0;
1051 hres = ITextRange_GetEnd(txtRge, &end);
1052 ok(hres == S_OK, "got 0x%08x\n", hres);
1053 ok(end == 10, "got %d\n", end);
1055 /* more that total text length */
1056 hres = ITextRange_SetStart(txtRge, 50);
1057 ok(hres == S_OK, "got 0x%08x\n", hres);
1059 start = 0;
1060 hres = ITextRange_GetStart(txtRge, &start);
1061 ok(hres == S_OK, "got 0x%08x\n", hres);
1062 ok(start == 12, "got %d\n", start);
1064 end = 0;
1065 hres = ITextRange_GetEnd(txtRge, &end);
1066 ok(hres == S_OK, "got 0x%08x\n", hres);
1067 ok(end == 12, "got %d\n", end);
1069 /* SetEnd */
1070 hres = ITextRange_SetStart(txtRge, 0);
1071 ok(hres == S_OK, "got 0x%08x\n", hres);
1073 /* same value */
1074 hres = ITextRange_SetEnd(txtRge, 5);
1075 ok(hres == S_OK, "got 0x%08x\n", hres);
1077 hres = ITextRange_SetEnd(txtRge, 5);
1078 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1080 /* negative resets to 0 */
1081 hres = ITextRange_SetEnd(txtRge, -1);
1082 ok(hres == S_OK, "got 0x%08x\n", hres);
1084 end = -1;
1085 hres = ITextRange_GetEnd(txtRge, &end);
1086 ok(hres == S_OK, "got 0x%08x\n", hres);
1087 ok(end == 0, "got %d\n", end);
1089 start = -1;
1090 hres = ITextRange_GetStart(txtRge, &start);
1091 ok(hres == S_OK, "got 0x%08x\n", hres);
1092 ok(start == 0, "got %d\n", start);
1094 /* greater than initial end, but less than total char count */
1095 hres = ITextRange_SetStart(txtRge, 3);
1096 ok(hres == S_OK, "got 0x%08x\n", hres);
1098 hres = ITextRange_SetEnd(txtRge, 1);
1099 ok(hres == S_OK, "got 0x%08x\n", hres);
1101 start = 0;
1102 hres = ITextRange_GetStart(txtRge, &start);
1103 ok(hres == S_OK, "got 0x%08x\n", hres);
1104 ok(start == 1, "got %d\n", start);
1106 end = 0;
1107 hres = ITextRange_GetEnd(txtRge, &end);
1108 ok(hres == S_OK, "got 0x%08x\n", hres);
1109 ok(end == 1, "got %d\n", end);
1111 /* more than total count */
1112 hres = ITextRange_SetEnd(txtRge, 50);
1113 ok(hres == S_OK, "got 0x%08x\n", hres);
1115 start = 0;
1116 hres = ITextRange_GetStart(txtRge, &start);
1117 ok(hres == S_OK, "got 0x%08x\n", hres);
1118 ok(start == 1, "got %d\n", start);
1120 end = 0;
1121 hres = ITextRange_GetEnd(txtRge, &end);
1122 ok(hres == S_OK, "got 0x%08x\n", hres);
1123 ok(end == 13, "got %d\n", end);
1125 /* zero */
1126 hres = ITextRange_SetEnd(txtRge, 0);
1127 ok(hres == S_OK, "got 0x%08x\n", hres);
1129 start = 0;
1130 hres = ITextRange_GetStart(txtRge, &start);
1131 ok(hres == S_OK, "got 0x%08x\n", hres);
1132 ok(start == 0, "got %d\n", start);
1134 end = 0;
1135 hres = ITextRange_GetEnd(txtRge, &end);
1136 ok(hres == S_OK, "got 0x%08x\n", hres);
1137 ok(end == 0, "got %d\n", end);
1139 release_interfaces(&w, &reOle, &txtDoc, NULL);
1141 /* detached range */
1142 hres = ITextRange_SetStart(txtRge, 0);
1143 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1145 hres = ITextRange_SetEnd(txtRge, 3);
1146 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1148 hres = ITextRange_GetStart(txtRge, &start);
1149 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1151 hres = ITextRange_GetStart(txtRge, NULL);
1152 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1154 hres = ITextRange_GetEnd(txtRge, &end);
1155 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1157 hres = ITextRange_GetEnd(txtRge, NULL);
1158 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1160 ITextRange_Release(txtRge);
1163 static void test_ITextSelection_GetStart_GetEnd(void)
1165 HWND w;
1166 IRichEditOle *reOle = NULL;
1167 ITextDocument *txtDoc = NULL;
1168 ITextSelection *txtSel = NULL;
1169 HRESULT hres;
1170 int first, lim;
1171 LONG start, end;
1172 static const CHAR test_text1[] = "TestSomeText";
1174 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1175 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1177 first = 2; lim = 5;
1178 SendMessageA(w, EM_SETSEL, first, lim);
1179 start = 0xdeadbeef;
1180 hres = ITextSelection_GetStart(txtSel, &start);
1181 ok(hres == S_OK, "ITextSelection_GetStart\n");
1182 ok(start == 2, "got wrong start value: %d\n", start);
1183 end = 0xdeadbeef;
1184 hres = ITextSelection_GetEnd(txtSel, &end);
1185 ok(hres == S_OK, "ITextSelection_GetEnd\n");
1186 ok(end == 5, "got wrong end value: %d\n", end);
1188 first = 5; lim = 2;
1189 SendMessageA(w, EM_SETSEL, first, lim);
1190 start = 0xdeadbeef;
1191 hres = ITextSelection_GetStart(txtSel, &start);
1192 ok(hres == S_OK, "ITextSelection_GetStart\n");
1193 ok(start == 2, "got wrong start value: %d\n", start);
1194 end = 0xdeadbeef;
1195 hres = ITextSelection_GetEnd(txtSel, &end);
1196 ok(hres == S_OK, "ITextSelection_GetEnd\n");
1197 ok(end == 5, "got wrong end value: %d\n", end);
1199 first = 0; lim = -1;
1200 SendMessageA(w, EM_SETSEL, first, lim);
1201 start = 0xdeadbeef;
1202 hres = ITextSelection_GetStart(txtSel, &start);
1203 ok(hres == S_OK, "ITextSelection_GetStart\n");
1204 ok(start == 0, "got wrong start value: %d\n", start);
1205 end = 0xdeadbeef;
1206 hres = ITextSelection_GetEnd(txtSel, &end);
1207 ok(hres == S_OK, "ITextSelection_GetEnd\n");
1208 ok(end == 13, "got wrong end value: %d\n", end);
1210 first = 13; lim = 13;
1211 SendMessageA(w, EM_SETSEL, first, lim);
1212 start = 0xdeadbeef;
1213 hres = ITextSelection_GetStart(txtSel, &start);
1214 ok(hres == S_OK, "ITextSelection_GetStart\n");
1215 ok(start == 12, "got wrong start value: %d\n", start);
1216 end = 0xdeadbeef;
1217 hres = ITextSelection_GetEnd(txtSel, &end);
1218 ok(hres == S_OK, "ITextSelection_GetEnd\n");
1219 ok(end == 12, "got wrong end value: %d\n", end);
1221 /* SetStart/SetEnd */
1222 hres = ITextSelection_SetStart(txtSel, 0);
1223 ok(hres == S_OK, "got 0x%08x\n", hres);
1225 /* same value */
1226 hres = ITextSelection_SetStart(txtSel, 0);
1227 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1229 hres = ITextSelection_SetStart(txtSel, 1);
1230 ok(hres == S_OK, "got 0x%08x\n", hres);
1232 /* negative resets to 0, return value is S_FALSE when
1233 position wasn't changed */
1234 hres = ITextSelection_SetStart(txtSel, -1);
1235 ok(hres == S_OK, "got 0x%08x\n", hres);
1237 hres = ITextSelection_SetStart(txtSel, -1);
1238 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1240 hres = ITextSelection_SetStart(txtSel, 0);
1241 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1243 start = -1;
1244 hres = ITextSelection_GetStart(txtSel, &start);
1245 ok(hres == S_OK, "got 0x%08x\n", hres);
1246 ok(start == 0, "got %d\n", start);
1248 /* greater than initial end, but less than total char count */
1249 hres = ITextSelection_SetStart(txtSel, 1);
1250 ok(hres == S_OK, "got 0x%08x\n", hres);
1252 hres = ITextSelection_SetEnd(txtSel, 3);
1253 ok(hres == S_OK, "got 0x%08x\n", hres);
1255 hres = ITextSelection_SetStart(txtSel, 10);
1256 ok(hres == S_OK, "got 0x%08x\n", hres);
1258 start = 0;
1259 hres = ITextSelection_GetStart(txtSel, &start);
1260 ok(hres == S_OK, "got 0x%08x\n", hres);
1261 ok(start == 10, "got %d\n", start);
1263 end = 0;
1264 hres = ITextSelection_GetEnd(txtSel, &end);
1265 ok(hres == S_OK, "got 0x%08x\n", hres);
1266 ok(end == 10, "got %d\n", end);
1268 /* more that total text length */
1269 hres = ITextSelection_SetStart(txtSel, 50);
1270 ok(hres == S_OK, "got 0x%08x\n", hres);
1272 start = 0;
1273 hres = ITextSelection_GetStart(txtSel, &start);
1274 ok(hres == S_OK, "got 0x%08x\n", hres);
1275 ok(start == 12, "got %d\n", start);
1277 end = 0;
1278 hres = ITextSelection_GetEnd(txtSel, &end);
1279 ok(hres == S_OK, "got 0x%08x\n", hres);
1280 ok(end == 12, "got %d\n", end);
1282 /* SetEnd */
1283 hres = ITextSelection_SetStart(txtSel, 0);
1284 ok(hres == S_OK, "got 0x%08x\n", hres);
1286 /* same value */
1287 hres = ITextSelection_SetEnd(txtSel, 5);
1288 ok(hres == S_OK, "got 0x%08x\n", hres);
1290 hres = ITextSelection_SetEnd(txtSel, 5);
1291 ok(hres == S_FALSE, "got 0x%08x\n", hres);
1293 /* negative resets to 0 */
1294 hres = ITextSelection_SetEnd(txtSel, -1);
1295 ok(hres == S_OK, "got 0x%08x\n", hres);
1297 end = -1;
1298 hres = ITextSelection_GetEnd(txtSel, &end);
1299 ok(hres == S_OK, "got 0x%08x\n", hres);
1300 ok(end == 0, "got %d\n", end);
1302 start = -1;
1303 hres = ITextSelection_GetStart(txtSel, &start);
1304 ok(hres == S_OK, "got 0x%08x\n", hres);
1305 ok(start == 0, "got %d\n", start);
1307 /* greater than initial end, but less than total char count */
1308 hres = ITextSelection_SetStart(txtSel, 3);
1309 ok(hres == S_OK, "got 0x%08x\n", hres);
1311 hres = ITextSelection_SetEnd(txtSel, 1);
1312 ok(hres == S_OK, "got 0x%08x\n", hres);
1314 start = 0;
1315 hres = ITextSelection_GetStart(txtSel, &start);
1316 ok(hres == S_OK, "got 0x%08x\n", hres);
1317 ok(start == 1, "got %d\n", start);
1319 end = 0;
1320 hres = ITextSelection_GetEnd(txtSel, &end);
1321 ok(hres == S_OK, "got 0x%08x\n", hres);
1322 ok(end == 1, "got %d\n", end);
1324 /* more than total count */
1325 hres = ITextSelection_SetEnd(txtSel, 50);
1326 ok(hres == S_OK, "got 0x%08x\n", hres);
1328 start = 0;
1329 hres = ITextSelection_GetStart(txtSel, &start);
1330 ok(hres == S_OK, "got 0x%08x\n", hres);
1331 ok(start == 1, "got %d\n", start);
1333 end = 0;
1334 hres = ITextSelection_GetEnd(txtSel, &end);
1335 ok(hres == S_OK, "got 0x%08x\n", hres);
1336 ok(end == 13, "got %d\n", end);
1338 /* zero */
1339 hres = ITextSelection_SetEnd(txtSel, 0);
1340 ok(hres == S_OK, "got 0x%08x\n", hres);
1342 start = 0;
1343 hres = ITextSelection_GetStart(txtSel, &start);
1344 ok(hres == S_OK, "got 0x%08x\n", hres);
1345 ok(start == 0, "got %d\n", start);
1347 end = 0;
1348 hres = ITextSelection_GetEnd(txtSel, &end);
1349 ok(hres == S_OK, "got 0x%08x\n", hres);
1350 ok(end == 0, "got %d\n", end);
1352 release_interfaces(&w, &reOle, &txtDoc, NULL);
1354 /* detached selection */
1355 hres = ITextSelection_GetStart(txtSel, NULL);
1356 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1358 hres = ITextSelection_GetStart(txtSel, &start);
1359 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1361 hres = ITextSelection_GetEnd(txtSel, NULL);
1362 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1364 hres = ITextSelection_GetEnd(txtSel, &end);
1365 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1367 ITextSelection_Release(txtSel);
1370 static void test_ITextRange_GetDuplicate(void)
1372 HWND w;
1373 IRichEditOle *reOle = NULL;
1374 ITextDocument *txtDoc = NULL;
1375 ITextRange *txtRge = NULL;
1376 ITextRange *txtRgeDup = NULL;
1377 HRESULT hres;
1378 LONG first, lim, start, end;
1379 static const CHAR test_text1[] = "TestSomeText";
1381 create_interfaces(&w, &reOle, &txtDoc, NULL);
1382 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1383 first = 0; lim = 4;
1384 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1385 ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
1387 hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1388 ok(hres == S_OK, "ITextRange_GetDuplicate\n");
1389 ok(txtRgeDup != txtRge, "A new pointer should be returned\n");
1390 hres = ITextRange_GetStart(txtRgeDup, &start);
1391 ok(hres == S_OK, "got 0x%08x\n", hres);
1392 ok(start == first, "got wrong value: %d\n", start);
1393 hres = ITextRange_GetEnd(txtRgeDup, &end);
1394 ok(hres == S_OK, "got 0x%08x\n", hres);
1395 ok(end == lim, "got wrong value: %d\n", end);
1397 ITextRange_Release(txtRgeDup);
1399 hres = ITextRange_GetDuplicate(txtRge, NULL);
1400 ok(hres == E_INVALIDARG, "ITextRange_GetDuplicate\n");
1402 release_interfaces(&w, &reOle, &txtDoc, NULL);
1404 hres = ITextRange_GetDuplicate(txtRge, NULL);
1405 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1407 hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1408 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1410 ITextRange_Release(txtRge);
1413 static void test_ITextRange_Collapse(void)
1415 HWND w;
1416 IRichEditOle *reOle = NULL;
1417 ITextDocument *txtDoc = NULL;
1418 ITextRange *txtRge = NULL;
1419 HRESULT hres;
1420 LONG first, lim, start, end;
1421 static const CHAR test_text1[] = "TestSomeText";
1423 create_interfaces(&w, &reOle, &txtDoc, NULL);
1424 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1426 first = 4; lim = 8;
1427 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1428 ok(hres == S_OK, "got 0x%08x\n", hres);
1429 hres = ITextRange_Collapse(txtRge, tomTrue);
1430 ok(hres == S_OK, "ITextRange_Collapse\n");
1431 hres = ITextRange_GetStart(txtRge, &start);
1432 ok(hres == S_OK, "got 0x%08x\n", hres);
1433 ok(start == 4, "got wrong start value: %d\n", start);
1434 hres = ITextRange_GetEnd(txtRge, &end);
1435 ok(hres == S_OK, "got 0x%08x\n", hres);
1436 ok(end == 4, "got wrong end value: %d\n", end);
1437 ITextRange_Release(txtRge);
1439 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1440 ok(hres == S_OK, "got 0x%08x\n", hres);
1441 hres = ITextRange_Collapse(txtRge, tomStart);
1442 ok(hres == S_OK, "ITextRange_Collapse\n");
1443 hres = ITextRange_GetStart(txtRge, &start);
1444 ok(hres == S_OK, "got 0x%08x\n", hres);
1445 ok(start == 4, "got wrong start value: %d\n", start);
1446 hres = ITextRange_GetEnd(txtRge, &end);
1447 ok(hres == S_OK, "got 0x%08x\n", hres);
1448 ok(end == 4, "got wrong end value: %d\n", end);
1449 ITextRange_Release(txtRge);
1451 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1452 ok(hres == S_OK, "got 0x%08x\n", hres);
1453 hres = ITextRange_Collapse(txtRge, tomFalse);
1454 ok(hres == S_OK, "ITextRange_Collapse\n");
1455 hres = ITextRange_GetStart(txtRge, &start);
1456 ok(hres == S_OK, "got 0x%08x\n", hres);
1457 ok(start == 8, "got wrong start value: %d\n", start);
1458 hres = ITextRange_GetEnd(txtRge, &end);
1459 ok(hres == S_OK, "got 0x%08x\n", hres);
1460 ok(end == 8, "got wrong end value: %d\n", end);
1461 ITextRange_Release(txtRge);
1463 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1464 ok(hres == S_OK, "got 0x%08x\n", hres);
1465 hres = ITextRange_Collapse(txtRge, tomEnd);
1466 ok(hres == S_OK, "ITextRange_Collapse\n");
1467 hres = ITextRange_GetStart(txtRge, &start);
1468 ok(hres == S_OK, "got 0x%08x\n", hres);
1469 ok(start == 8, "got wrong start value: %d\n", start);
1470 hres = ITextRange_GetEnd(txtRge, &end);
1471 ok(hres == S_OK, "got 0x%08x\n", hres);
1472 ok(end == 8, "got wrong end value: %d\n", end);
1473 ITextRange_Release(txtRge);
1475 /* tomStart is the default */
1476 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1477 ok(hres == S_OK, "got 0x%08x\n", hres);
1478 hres = ITextRange_Collapse(txtRge, 256);
1479 ok(hres == S_OK, "ITextRange_Collapse\n");
1480 hres = ITextRange_GetStart(txtRge, &start);
1481 ok(hres == S_OK, "got 0x%08x\n", hres);
1482 ok(start == 4, "got wrong start value: %d\n", start);
1483 hres = ITextRange_GetEnd(txtRge, &end);
1484 ok(hres == S_OK, "got 0x%08x\n", hres);
1485 ok(end == 4, "got wrong end value: %d\n", end);
1486 ITextRange_Release(txtRge);
1488 first = 6; lim = 6;
1489 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1490 ok(hres == S_OK, "got 0x%08x\n", hres);
1491 hres = ITextRange_Collapse(txtRge, tomEnd);
1492 ok(hres == S_FALSE, "ITextRange_Collapse\n");
1493 hres = ITextRange_GetStart(txtRge, &start);
1494 ok(hres == S_OK, "got 0x%08x\n", hres);
1495 ok(start == 6, "got wrong start value: %d\n", start);
1496 hres = ITextRange_GetEnd(txtRge, &end);
1497 ok(hres == S_OK, "got 0x%08x\n", hres);
1498 ok(end == 6, "got wrong end value: %d\n", end);
1499 ITextRange_Release(txtRge);
1501 first = 8; lim = 8;
1502 hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1503 ok(hres == S_OK, "got 0x%08x\n", hres);
1504 hres = ITextRange_Collapse(txtRge, tomStart);
1505 ok(hres == S_FALSE, "ITextRange_Collapse\n");
1506 hres = ITextRange_GetStart(txtRge, &start);
1507 ok(hres == S_OK, "got 0x%08x\n", hres);
1508 ok(start == 8, "got wrong start value: %d\n", start);
1509 hres = ITextRange_GetEnd(txtRge, &end);
1510 ok(hres == S_OK, "got 0x%08x\n", hres);
1511 ok(end == 8, "got wrong end value: %d\n", end);
1513 release_interfaces(&w, &reOle, &txtDoc, NULL);
1515 hres = ITextRange_Collapse(txtRge, tomStart);
1516 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1518 hres = ITextRange_Collapse(txtRge, tomUndefined);
1519 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1521 ITextRange_Release(txtRge);
1524 static void test_ITextSelection_Collapse(void)
1526 HWND w;
1527 IRichEditOle *reOle = NULL;
1528 ITextDocument *txtDoc = NULL;
1529 ITextSelection *txtSel = NULL;
1530 HRESULT hres;
1531 LONG first, lim, start, end;
1532 static const CHAR test_text1[] = "TestSomeText";
1534 create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1535 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1537 first = 4; lim = 8;
1538 SendMessageA(w, EM_SETSEL, first, lim);
1539 hres = ITextSelection_Collapse(txtSel, tomTrue);
1540 ok(hres == S_OK, "ITextSelection_Collapse\n");
1541 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1542 ok(start == 4, "got wrong start value: %d\n", start);
1543 ok(end == 4, "got wrong end value: %d\n", end);
1545 SendMessageA(w, EM_SETSEL, first, lim);
1546 hres = ITextSelection_Collapse(txtSel, tomStart);
1547 ok(hres == S_OK, "ITextSelection_Collapse\n");
1548 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1549 ok(start == 4, "got wrong start value: %d\n", start);
1550 ok(end == 4, "got wrong end value: %d\n", end);
1552 SendMessageA(w, EM_SETSEL, first, lim);
1553 hres = ITextSelection_Collapse(txtSel, tomFalse);
1554 ok(hres == S_OK, "ITextSelection_Collapse\n");
1555 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1556 ok(start == 8, "got wrong start value: %d\n", start);
1557 ok(end == 8, "got wrong end value: %d\n", end);
1559 SendMessageA(w, EM_SETSEL, first, lim);
1560 hres = ITextSelection_Collapse(txtSel, tomEnd);
1561 ok(hres == S_OK, "ITextSelection_Collapse\n");
1562 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1563 ok(start == 8, "got wrong start value: %d\n", start);
1564 ok(end == 8, "got wrong end value: %d\n", end);
1566 /* tomStart is the default */
1567 SendMessageA(w, EM_SETSEL, first, lim);
1568 hres = ITextSelection_Collapse(txtSel, 256);
1569 ok(hres == S_OK, "ITextSelection_Collapse\n");
1570 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1571 ok(start == 4, "got wrong start value: %d\n", start);
1572 ok(end == 4, "got wrong end value: %d\n", end);
1574 first = 6; lim = 6;
1575 SendMessageA(w, EM_SETSEL, first, lim);
1576 hres = ITextSelection_Collapse(txtSel, tomEnd);
1577 ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1578 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1579 ok(start == 6, "got wrong start value: %d\n", start);
1580 ok(end == 6, "got wrong end value: %d\n", end);
1582 first = 8; lim = 8;
1583 SendMessageA(w, EM_SETSEL, first, lim);
1584 hres = ITextSelection_Collapse(txtSel, tomStart);
1585 ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1586 SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1587 ok(start == 8, "got wrong start value: %d\n", start);
1588 ok(end == 8, "got wrong end value: %d\n", end);
1590 release_interfaces(&w, &reOle, &txtDoc, NULL);
1592 hres = ITextSelection_Collapse(txtSel, tomStart);
1593 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1595 hres = ITextSelection_Collapse(txtSel, tomUndefined);
1596 ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1598 ITextSelection_Release(txtSel);
1601 static void test_GetClientSite(void)
1603 HWND w;
1604 IRichEditOle *reOle = NULL, *reOle1 = NULL;
1605 ITextDocument *txtDoc = NULL;
1606 IOleClientSite *clientSite = NULL, *clientSite1 = NULL, *clientSite2 = NULL;
1607 IOleWindow *oleWin = NULL, *oleWin1 = NULL;
1608 IOleInPlaceSite *olePlace = NULL, *olePlace1 = NULL;
1609 HRESULT hres;
1610 LONG refcount1, refcount2;
1612 create_interfaces(&w, &reOle, &txtDoc, NULL);
1613 hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1614 ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1615 EXPECT_REF(clientSite, 1);
1617 hres = IOleClientSite_QueryInterface(clientSite, &IID_IRichEditOle, (void **)&reOle1);
1618 ok(hres == E_NOINTERFACE, "IOleClientSite_QueryInterface: %x\n", hres);
1620 hres = IRichEditOle_GetClientSite(reOle, &clientSite1);
1621 ok(hres == S_OK, "got 0x%08x\n", hres);
1622 ok(clientSite != clientSite1, "got %p, %p\n", clientSite, clientSite1);
1623 IOleClientSite_Release(clientSite1);
1625 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleClientSite, (void **)&clientSite1);
1626 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1627 ok(clientSite == clientSite1, "Should not return a new pointer.\n");
1628 EXPECT_REF(clientSite, 2);
1630 /* IOleWindow interface */
1631 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1632 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1633 refcount1 = get_refcount((IUnknown *)clientSite);
1634 refcount2 = get_refcount((IUnknown *)oleWin);
1635 ok(refcount1 == refcount2, "got wrong ref count.\n");
1637 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin1);
1638 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1639 ok(oleWin == oleWin1, "Should not return a new pointer.\n");
1640 refcount1 = get_refcount((IUnknown *)clientSite);
1641 refcount2 = get_refcount((IUnknown *)oleWin);
1642 ok(refcount1 == refcount2, "got wrong ref count.\n");
1644 hres = IOleWindow_QueryInterface(oleWin, &IID_IOleClientSite, (void **)&clientSite2);
1645 ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1646 ok(clientSite2 == clientSite1, "got wrong pointer\n");
1648 /* IOleInPlaceSite interface */
1649 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1650 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1651 refcount1 = get_refcount((IUnknown *)olePlace);
1652 refcount2 = get_refcount((IUnknown *)clientSite);
1653 ok(refcount1 == refcount2, "got wrong ref count.\n");
1655 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace1);
1656 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1657 ok(olePlace == olePlace1, "Should not return a new pointer.\n");
1658 IOleInPlaceSite_Release(olePlace1);
1660 hres = IOleWindow_QueryInterface(oleWin, &IID_IOleInPlaceSite, (void **)&olePlace1);
1661 ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1662 refcount1 = get_refcount((IUnknown *)olePlace1);
1663 refcount2 = get_refcount((IUnknown *)oleWin);
1664 ok(refcount1 == refcount2, "got wrong ref count.\n");
1666 IOleInPlaceSite_Release(olePlace1);
1667 IOleInPlaceSite_Release(olePlace);
1668 IOleWindow_Release(oleWin1);
1669 IOleWindow_Release(oleWin);
1670 IOleClientSite_Release(clientSite2);
1671 IOleClientSite_Release(clientSite1);
1672 IOleClientSite_Release(clientSite);
1673 release_interfaces(&w, &reOle, &txtDoc, NULL);
1676 static void test_IOleWindow_GetWindow(void)
1678 HWND w;
1679 IRichEditOle *reOle = NULL;
1680 ITextDocument *txtDoc = NULL;
1681 IOleClientSite *clientSite = NULL;
1682 IOleWindow *oleWin = NULL;
1683 HRESULT hres;
1684 HWND hwnd;
1686 create_interfaces(&w, &reOle, &txtDoc, NULL);
1687 hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1688 ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1690 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1691 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1692 hres = IOleWindow_GetWindow(oleWin, &hwnd);
1693 ok(hres == S_OK, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1694 ok(w == hwnd, "got wrong pointer\n");
1696 hres = IOleWindow_GetWindow(oleWin, NULL);
1697 ok(hres == E_INVALIDARG, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1699 IOleWindow_Release(oleWin);
1700 IOleClientSite_Release(clientSite);
1701 release_interfaces(&w, &reOle, &txtDoc, NULL);
1704 static void test_IOleInPlaceSite_GetWindow(void)
1706 HWND w;
1707 IRichEditOle *reOle = NULL;
1708 ITextDocument *txtDoc = NULL;
1709 IOleClientSite *clientSite = NULL;
1710 IOleInPlaceSite *olePlace = NULL;
1711 HRESULT hres;
1712 HWND hwnd;
1714 create_interfaces(&w, &reOle, &txtDoc, NULL);
1715 hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1716 ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1718 hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1719 ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1720 hres = IOleInPlaceSite_GetWindow(olePlace, &hwnd);
1721 ok(hres == S_OK, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1722 ok(w == hwnd, "got wrong pointer.\n");
1724 hres = IOleInPlaceSite_GetWindow(olePlace, NULL);
1725 ok(hres == E_INVALIDARG, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1727 IOleInPlaceSite_Release(olePlace);
1728 IOleClientSite_Release(clientSite);
1729 release_interfaces(&w, &reOle, &txtDoc, NULL);
1732 static void test_GetFont(void)
1734 static const CHAR test_text1[] = "TestSomeText";
1735 IRichEditOle *reOle = NULL;
1736 ITextDocument *doc = NULL;
1737 ITextRange *range = NULL;
1738 ITextSelection *selection;
1739 ITextFont *font, *font2;
1740 CHARFORMAT2A cf;
1741 LONG value;
1742 float size;
1743 HRESULT hr;
1744 HWND hwnd;
1745 BOOL ret;
1747 create_interfaces(&hwnd, &reOle, &doc, NULL);
1748 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1750 hr = ITextDocument_GetSelection(doc, &selection);
1751 ok(hr == S_OK, "got 0x%08x\n", hr);
1752 hr = ITextSelection_GetFont(selection, &font);
1753 ok(hr == S_OK, "got 0x%08x\n", hr);
1754 hr = ITextSelection_GetFont(selection, &font2);
1755 ok(hr == S_OK, "got 0x%08x\n", hr);
1756 ok(font != font2, "got %p, %p\n", font, font2);
1757 ITextFont_Release(font2);
1758 ITextFont_Release(font);
1759 ITextSelection_Release(selection);
1761 EXPECT_REF(reOle, 3);
1762 EXPECT_REF(doc, 3);
1764 hr = ITextDocument_Range(doc, 0, 4, &range);
1765 ok(hr == S_OK, "got 0x%08x\n", hr);
1767 EXPECT_REF(reOle, 3);
1768 EXPECT_REF(doc, 3);
1769 EXPECT_REF(range, 1);
1771 hr = ITextRange_GetFont(range, NULL);
1772 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1774 hr = ITextRange_GetFont(range, &font);
1775 ok(hr == S_OK, "got 0x%08x\n", hr);
1777 EXPECT_REF(reOle, 3);
1778 EXPECT_REF(doc, 3);
1779 EXPECT_REF(range, 2);
1780 EXPECT_REF(font, 1);
1782 hr = ITextRange_GetFont(range, &font2);
1783 ok(hr == S_OK, "got 0x%08x\n", hr);
1784 ok(font != font2, "got %p, %p\n", font, font2);
1786 EXPECT_REF(reOle, 3);
1787 EXPECT_REF(doc, 3);
1788 EXPECT_REF(range, 3);
1789 EXPECT_REF(font, 1);
1790 EXPECT_REF(font2, 1);
1792 ITextFont_Release(font2);
1794 /* set different font style within a range */
1795 hr = ITextFont_GetItalic(font, NULL);
1796 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1798 hr = ITextFont_GetSize(font, NULL);
1799 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1801 size = 0.0;
1802 hr = ITextFont_GetSize(font, &size);
1803 ok(hr == S_OK, "got 0x%08x\n", hr);
1804 ok(size > 0.0, "size %.2f\n", size);
1806 value = 0;
1807 hr = ITextFont_GetLanguageID(font, &value);
1808 ok(hr == S_OK, "got 0x%08x\n", hr);
1809 ok(value == GetSystemDefaultLCID(), "got lcid %x, user lcid %x\n", value,
1810 GetSystemDefaultLCID());
1812 /* range is non-italic */
1813 value = tomTrue;
1814 hr = ITextFont_GetItalic(font, &value);
1815 ok(hr == S_OK, "got 0x%08x\n", hr);
1816 ok(value == tomFalse, "got %d\n", value);
1818 cf.cbSize = sizeof(CHARFORMAT2A);
1819 cf.dwMask = CFM_ITALIC|CFM_SIZE;
1820 cf.dwEffects = CFE_ITALIC;
1821 cf.yHeight = 24.0;
1823 SendMessageA(hwnd, EM_SETSEL, 2, 3);
1824 ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
1825 ok(ret, "got %d\n", ret);
1827 /* now range is partially italicized */
1828 value = tomFalse;
1829 hr = ITextFont_GetItalic(font, &value);
1830 ok(hr == S_OK, "got 0x%08x\n", hr);
1831 ok(value == tomUndefined, "got %d\n", value);
1833 size = 0.0;
1834 hr = ITextFont_GetSize(font, &size);
1835 ok(hr == S_OK, "got 0x%08x\n", hr);
1836 ok(size == tomUndefined, "size %.2f\n", size);
1838 ITextFont_Release(font);
1839 release_interfaces(&hwnd, &reOle, &doc, NULL);
1841 hr = ITextRange_GetFont(range, NULL);
1842 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1844 hr = ITextRange_GetFont(range, &font2);
1845 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1847 ITextRange_Release(range);
1850 static void test_GetPara(void)
1852 static const CHAR test_text1[] = "TestSomeText";
1853 IRichEditOle *reOle = NULL;
1854 ITextDocument *doc = NULL;
1855 ITextSelection *selection;
1856 ITextRange *range = NULL;
1857 ITextPara *para, *para2;
1858 HRESULT hr;
1859 HWND hwnd;
1861 create_interfaces(&hwnd, &reOle, &doc, &selection);
1862 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1864 EXPECT_REF(reOle, 3);
1865 EXPECT_REF(doc, 3);
1867 hr = ITextDocument_Range(doc, 0, 4, &range);
1868 ok(hr == S_OK, "got 0x%08x\n", hr);
1870 EXPECT_REF(reOle, 3);
1871 EXPECT_REF(doc, 3);
1872 EXPECT_REF(range, 1);
1874 hr = ITextRange_GetPara(range, NULL);
1875 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1877 hr = ITextRange_GetPara(range, &para);
1878 ok(hr == S_OK, "got 0x%08x\n", hr);
1880 EXPECT_REF(reOle, 3);
1881 EXPECT_REF(doc, 3);
1882 EXPECT_REF(range, 2);
1883 EXPECT_REF(para, 1);
1885 hr = ITextRange_GetPara(range, &para2);
1886 ok(hr == S_OK, "got 0x%08x\n", hr);
1887 ok(para != para2, "got %p, %p\n", para, para2);
1889 EXPECT_REF(reOle, 3);
1890 EXPECT_REF(doc, 3);
1891 EXPECT_REF(range, 3);
1892 EXPECT_REF(para, 1);
1893 EXPECT_REF(para2, 1);
1895 ITextPara_Release(para);
1896 ITextPara_Release(para2);
1898 EXPECT_REF(reOle, 3);
1899 EXPECT_REF(doc, 3);
1900 EXPECT_REF(selection, 2);
1902 hr = ITextSelection_GetPara(selection, &para);
1903 ok(hr == S_OK, "got 0x%08x\n", hr);
1905 EXPECT_REF(reOle, 3);
1906 EXPECT_REF(doc, 3);
1907 EXPECT_REF(selection, 3);
1908 EXPECT_REF(para, 1);
1910 hr = ITextSelection_GetPara(selection, &para2);
1911 ok(hr == S_OK, "got 0x%08x\n", hr);
1912 ok(para != para2, "got %p, %p\n", para, para2);
1914 ITextPara_Release(para);
1915 ITextPara_Release(para2);
1916 release_interfaces(&hwnd, &reOle, &doc, NULL);
1918 hr = ITextRange_GetPara(range, NULL);
1919 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1921 hr = ITextRange_GetPara(range, &para);
1922 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1924 hr = ITextSelection_GetPara(selection, NULL);
1925 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1927 hr = ITextSelection_GetPara(selection, &para);
1928 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1930 ITextSelection_Release(selection);
1931 ITextRange_Release(range);
1934 static void test_dispatch(void)
1936 static const WCHAR testnameW[] = {'G','e','t','T','e','x','t',0};
1937 static const WCHAR testname2W[] = {'T','e','x','t',0};
1938 IRichEditOle *reOle = NULL;
1939 ITextDocument *doc = NULL;
1940 ITextRange *range = NULL;
1941 WCHAR *nameW;
1942 DISPID dispid;
1943 HRESULT hr;
1944 UINT count;
1945 HWND hwnd;
1947 create_interfaces(&hwnd, &reOle, &doc, NULL);
1949 range = NULL;
1950 hr = ITextDocument_Range(doc, 0, 0, &range);
1951 ok(hr == S_OK, "got 0x%08x\n", hr);
1952 ok(range != NULL, "got %p\n", range);
1954 dispid = 123;
1955 nameW = (WCHAR*)testnameW;
1956 hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1957 ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
1958 ok(dispid == DISPID_UNKNOWN, "got %d\n", dispid);
1960 dispid = 123;
1961 nameW = (WCHAR*)testname2W;
1962 hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1963 ok(hr == S_OK, "got 0x%08x\n", hr);
1964 ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1966 release_interfaces(&hwnd, &reOle, &doc, NULL);
1968 /* try dispatch methods on detached range */
1969 hr = ITextRange_GetTypeInfoCount(range, &count);
1970 ok(hr == S_OK, "got 0x%08x\n", hr);
1972 dispid = 123;
1973 nameW = (WCHAR*)testname2W;
1974 hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1975 ok(hr == S_OK, "got 0x%08x\n", hr);
1976 ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1978 ITextRange_Release(range);
1981 static void test_detached_font_getters(ITextFont *font, BOOL duplicate)
1983 HRESULT hr, hrexp = duplicate ? S_OK : CO_E_RELEASED;
1984 LONG value;
1985 float size;
1986 BSTR str;
1988 hr = ITextFont_GetBold(font, NULL);
1989 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1991 hr = ITextFont_GetBold(font, &value);
1992 ok(hr == hrexp, "got 0x%08x\n", hr);
1994 hr = ITextFont_GetForeColor(font, NULL);
1995 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1997 hr = ITextFont_GetForeColor(font, &value);
1998 ok(hr == hrexp, "got 0x%08x\n", hr);
2000 hr = ITextFont_GetItalic(font, NULL);
2001 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2003 hr = ITextFont_GetItalic(font, &value);
2004 ok(hr == hrexp, "got 0x%08x\n", hr);
2006 hr = ITextFont_GetLanguageID(font, NULL);
2007 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2009 hr = ITextFont_GetLanguageID(font, &value);
2010 ok(hr == hrexp, "got 0x%08x\n", hr);
2012 hr = ITextFont_GetName(font, NULL);
2013 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2015 hr = ITextFont_GetName(font, &str);
2016 ok(hr == hrexp, "got 0x%08x\n", hr);
2018 hr = ITextFont_GetSize(font, NULL);
2019 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2021 hr = ITextFont_GetSize(font, &size);
2022 ok(hr == hrexp, "got 0x%08x\n", hr);
2024 hr = ITextFont_GetStrikeThrough(font, NULL);
2025 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2027 hr = ITextFont_GetStrikeThrough(font, &value);
2028 ok(hr == hrexp, "got 0x%08x\n", hr);
2030 hr = ITextFont_GetSubscript(font, NULL);
2031 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2033 hr = ITextFont_GetSubscript(font, &value);
2034 ok(hr == hrexp, "got 0x%08x\n", hr);
2036 hr = ITextFont_GetSuperscript(font, NULL);
2037 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2039 hr = ITextFont_GetSuperscript(font, &value);
2040 ok(hr == hrexp, "got 0x%08x\n", hr);
2042 hr = ITextFont_GetUnderline(font, NULL);
2043 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2045 hr = ITextFont_GetUnderline(font, &value);
2046 ok(hr == hrexp, "got 0x%08x\n", hr);
2049 static void test_textfont_global_defaults(ITextFont *font)
2051 float valuef;
2052 LONG value;
2053 HRESULT hr;
2054 BSTR str;
2056 value = tomUndefined;
2057 hr = ITextFont_GetAllCaps(font, &value);
2058 ok(hr == S_OK, "got 0x%08x\n", hr);
2059 ok(value == tomFalse, "got %d\n", value);
2061 value = tomUndefined;
2062 hr = ITextFont_GetAnimation(font, &value);
2063 ok(hr == S_OK, "got 0x%08x\n", hr);
2064 ok(value == tomFalse, "got %d\n", value);
2066 value = tomUndefined;
2067 hr = ITextFont_GetBackColor(font, &value);
2068 ok(hr == S_OK, "got 0x%08x\n", hr);
2069 ok(value == tomAutoColor, "got %d\n", value);
2071 value = tomUndefined;
2072 hr = ITextFont_GetBold(font, &value);
2073 ok(hr == S_OK, "got 0x%08x\n", hr);
2074 ok(value == tomFalse || value == tomTrue, "got %d\n", value);
2076 value = tomUndefined;
2077 hr = ITextFont_GetEmboss(font, &value);
2078 ok(hr == S_OK, "got 0x%08x\n", hr);
2079 ok(value == tomFalse, "got %d\n", value);
2081 value = tomUndefined;
2082 hr = ITextFont_GetForeColor(font, &value);
2083 ok(hr == S_OK, "got 0x%08x\n", hr);
2084 ok(value == tomAutoColor, "got %d\n", value);
2086 value = tomUndefined;
2087 hr = ITextFont_GetHidden(font, &value);
2088 ok(hr == S_OK, "got 0x%08x\n", hr);
2089 ok(value == tomFalse, "got %d\n", value);
2091 value = tomUndefined;
2092 hr = ITextFont_GetEngrave(font, &value);
2093 ok(hr == S_OK, "got 0x%08x\n", hr);
2094 ok(value == tomFalse, "got %d\n", value);
2096 value = tomUndefined;
2097 hr = ITextFont_GetItalic(font, &value);
2098 ok(hr == S_OK, "got 0x%08x\n", hr);
2099 ok(value == tomFalse, "got %d\n", value);
2101 valuef = 1.0;
2102 hr = ITextFont_GetKerning(font, &valuef);
2103 ok(hr == S_OK, "got 0x%08x\n", hr);
2104 ok(valuef == 0.0, "got %.2f\n", valuef);
2106 value = tomUndefined;
2107 hr = ITextFont_GetLanguageID(font, &value);
2108 ok(hr == S_OK, "got 0x%08x\n", hr);
2109 ok(value == GetSystemDefaultLCID(), "got %d\n", value);
2111 str = NULL;
2112 hr = ITextFont_GetName(font, &str);
2113 ok(hr == S_OK, "got 0x%08x\n", hr);
2114 ok(!lstrcmpW(sysW, str), "%s\n", wine_dbgstr_w(str));
2115 SysFreeString(str);
2117 value = tomUndefined;
2118 hr = ITextFont_GetOutline(font, &value);
2119 ok(hr == S_OK, "got 0x%08x\n", hr);
2120 ok(value == tomFalse, "got %d\n", value);
2122 valuef = 1.0;
2123 hr = ITextFont_GetPosition(font, &valuef);
2124 ok(hr == S_OK, "got 0x%08x\n", hr);
2125 ok(valuef == 0.0, "got %.2f\n", valuef);
2127 value = tomUndefined;
2128 hr = ITextFont_GetProtected(font, &value);
2129 ok(hr == S_OK, "got 0x%08x\n", hr);
2130 ok(value == tomFalse, "got %d\n", value);
2132 value = tomUndefined;
2133 hr = ITextFont_GetShadow(font, &value);
2134 ok(hr == S_OK, "got 0x%08x\n", hr);
2135 ok(value == tomFalse, "got %d\n", value);
2137 valuef = 0.0;
2138 hr = ITextFont_GetSize(font, &valuef);
2139 ok(hr == S_OK, "got 0x%08x\n", hr);
2140 ok(valuef >= 0.0, "got %.2f\n", valuef);
2142 value = tomUndefined;
2143 hr = ITextFont_GetSmallCaps(font, &value);
2144 ok(hr == S_OK, "got 0x%08x\n", hr);
2145 ok(value == tomFalse, "got %d\n", value);
2147 valuef = 1.0;
2148 hr = ITextFont_GetSpacing(font, &valuef);
2149 ok(hr == S_OK, "got 0x%08x\n", hr);
2150 ok(valuef == 0.0, "got %.2f\n", valuef);
2152 value = tomUndefined;
2153 hr = ITextFont_GetStrikeThrough(font, &value);
2154 ok(hr == S_OK, "got 0x%08x\n", hr);
2155 ok(value == tomFalse, "got %d\n", value);
2157 value = tomUndefined;
2158 hr = ITextFont_GetSubscript(font, &value);
2159 ok(hr == S_OK, "got 0x%08x\n", hr);
2160 ok(value == tomFalse, "got %d\n", value);
2162 value = tomUndefined;
2163 hr = ITextFont_GetSuperscript(font, &value);
2164 ok(hr == S_OK, "got 0x%08x\n", hr);
2165 ok(value == tomFalse, "got %d\n", value);
2167 value = tomUndefined;
2168 hr = ITextFont_GetUnderline(font, &value);
2169 ok(hr == S_OK, "got 0x%08x\n", hr);
2170 ok(value == tomFalse, "got %d\n", value);
2172 value = tomUndefined;
2173 hr = ITextFont_GetWeight(font, &value);
2174 ok(hr == S_OK, "got 0x%08x\n", hr);
2175 ok(value == FW_NORMAL || value == FW_BOLD, "got %d\n", value);
2178 static void test_textfont_undefined(ITextFont *font)
2180 float valuef;
2181 LONG value;
2182 HRESULT hr;
2184 value = tomFalse;
2185 hr = ITextFont_GetAllCaps(font, &value);
2186 ok(hr == S_OK, "got 0x%08x\n", hr);
2187 ok(value == tomUndefined, "got %d\n", value);
2189 value = tomFalse;
2190 hr = ITextFont_GetAnimation(font, &value);
2191 ok(hr == S_OK, "got 0x%08x\n", hr);
2192 ok(value == tomUndefined, "got %d\n", value);
2194 value = tomFalse;
2195 hr = ITextFont_GetBackColor(font, &value);
2196 ok(hr == S_OK, "got 0x%08x\n", hr);
2197 ok(value == tomUndefined, "got %d\n", value);
2199 value = tomFalse;
2200 hr = ITextFont_GetBold(font, &value);
2201 ok(hr == S_OK, "got 0x%08x\n", hr);
2202 ok(value == tomUndefined, "got %d\n", value);
2204 value = tomFalse;
2205 hr = ITextFont_GetEmboss(font, &value);
2206 ok(hr == S_OK, "got 0x%08x\n", hr);
2207 ok(value == tomUndefined, "got %d\n", value);
2209 value = tomFalse;
2210 hr = ITextFont_GetForeColor(font, &value);
2211 ok(hr == S_OK, "got 0x%08x\n", hr);
2212 ok(value == tomUndefined, "got %d\n", value);
2214 value = tomFalse;
2215 hr = ITextFont_GetHidden(font, &value);
2216 ok(hr == S_OK, "got 0x%08x\n", hr);
2217 ok(value == tomUndefined, "got %d\n", value);
2219 value = tomFalse;
2220 hr = ITextFont_GetEngrave(font, &value);
2221 ok(hr == S_OK, "got 0x%08x\n", hr);
2222 ok(value == tomUndefined, "got %d\n", value);
2224 value = tomFalse;
2225 hr = ITextFont_GetItalic(font, &value);
2226 ok(hr == S_OK, "got 0x%08x\n", hr);
2227 ok(value == tomUndefined, "got %d\n", value);
2229 valuef = 0.0;
2230 hr = ITextFont_GetKerning(font, &valuef);
2231 ok(hr == S_OK, "got 0x%08x\n", hr);
2232 ok(valuef == tomUndefined, "got %.2f\n", valuef);
2234 value = tomFalse;
2235 hr = ITextFont_GetLanguageID(font, &value);
2236 ok(hr == S_OK, "got 0x%08x\n", hr);
2237 ok(value == tomUndefined, "got %d\n", value);
2239 value = tomFalse;
2240 hr = ITextFont_GetOutline(font, &value);
2241 ok(hr == S_OK, "got 0x%08x\n", hr);
2242 ok(value == tomUndefined, "got %d\n", value);
2244 valuef = 0.0;
2245 hr = ITextFont_GetPosition(font, &valuef);
2246 ok(hr == S_OK, "got 0x%08x\n", hr);
2247 ok(valuef == tomUndefined, "got %.2f\n", valuef);
2249 value = tomFalse;
2250 hr = ITextFont_GetProtected(font, &value);
2251 ok(hr == S_OK, "got 0x%08x\n", hr);
2252 ok(value == tomUndefined, "got %d\n", value);
2254 value = tomFalse;
2255 hr = ITextFont_GetShadow(font, &value);
2256 ok(hr == S_OK, "got 0x%08x\n", hr);
2257 ok(value == tomUndefined, "got %d\n", value);
2259 valuef = 0.0;
2260 hr = ITextFont_GetSize(font, &valuef);
2261 ok(hr == S_OK, "got 0x%08x\n", hr);
2262 ok(valuef == tomUndefined, "got %.2f\n", valuef);
2264 value = tomFalse;
2265 hr = ITextFont_GetSmallCaps(font, &value);
2266 ok(hr == S_OK, "got 0x%08x\n", hr);
2267 ok(value == tomUndefined, "got %d\n", value);
2269 valuef = 0.0;
2270 hr = ITextFont_GetSpacing(font, &valuef);
2271 ok(hr == S_OK, "got 0x%08x\n", hr);
2272 ok(valuef == tomUndefined, "got %.2f\n", valuef);
2274 value = tomFalse;
2275 hr = ITextFont_GetStrikeThrough(font, &value);
2276 ok(hr == S_OK, "got 0x%08x\n", hr);
2277 ok(value == tomUndefined, "got %d\n", value);
2279 value = tomFalse;
2280 hr = ITextFont_GetSubscript(font, &value);
2281 ok(hr == S_OK, "got 0x%08x\n", hr);
2282 ok(value == tomUndefined, "got %d\n", value);
2284 value = tomFalse;
2285 hr = ITextFont_GetSuperscript(font, &value);
2286 ok(hr == S_OK, "got 0x%08x\n", hr);
2287 ok(value == tomUndefined, "got %d\n", value);
2289 value = tomFalse;
2290 hr = ITextFont_GetUnderline(font, &value);
2291 ok(hr == S_OK, "got 0x%08x\n", hr);
2292 ok(value == tomUndefined, "got %d\n", value);
2294 value = tomFalse;
2295 hr = ITextFont_GetWeight(font, &value);
2296 ok(hr == S_OK, "got 0x%08x\n", hr);
2297 ok(value == tomUndefined, "got %d\n", value);
2300 static inline FLOAT twips_to_points(LONG value)
2302 return value * 72.0 / 1440;
2305 static void test_ITextFont(void)
2307 static const WCHAR arialW[] = {'A','r','i','a','l',0};
2308 static const CHAR test_text1[] = "TestSomeText";
2309 ITextFont *font, *font2, *font3;
2310 FLOAT size, position, kerning;
2311 IRichEditOle *reOle = NULL;
2312 ITextDocument *doc = NULL;
2313 ITextRange *range = NULL;
2314 CHARFORMAT2A cf;
2315 LONG value;
2316 HRESULT hr;
2317 HWND hwnd;
2318 BOOL ret;
2319 BSTR str;
2321 create_interfaces(&hwnd, &reOle, &doc, NULL);
2322 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2324 hr = ITextDocument_Range(doc, 0, 10, &range);
2325 ok(hr == S_OK, "got 0x%08x\n", hr);
2327 hr = ITextRange_GetFont(range, &font);
2328 ok(hr == S_OK, "got 0x%08x\n", hr);
2330 hr = ITextFont_Reset(font, tomUseTwips);
2331 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2333 hr = ITextFont_Reset(font, tomUsePoints);
2334 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2336 hr = ITextFont_GetName(font, NULL);
2337 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2339 /* default font size unit is point */
2340 size = 0.0;
2341 hr = ITextFont_GetSize(font, &size);
2342 ok(hr == S_OK, "got 0x%08x\n", hr);
2344 /* set to some non-zero values */
2345 hr = ITextFont_SetPosition(font, 20.0);
2346 ok(hr == S_OK, "got 0x%08x\n", hr);
2348 hr = ITextFont_SetKerning(font, 10.0);
2349 ok(hr == S_OK, "got 0x%08x\n", hr);
2351 position = 0.0;
2352 hr = ITextFont_GetPosition(font, &position);
2353 ok(hr == S_OK, "got 0x%08x\n", hr);
2355 kerning = 0.0;
2356 hr = ITextFont_GetKerning(font, &kerning);
2357 ok(hr == S_OK, "got 0x%08x\n", hr);
2359 memset(&cf, 0, sizeof(cf));
2360 cf.cbSize = sizeof(cf);
2361 cf.dwMask = CFM_SIZE|CFM_OFFSET|CFM_KERNING;
2363 /* CHARFORMAT members are in twips */
2364 SendMessageA(hwnd, EM_SETSEL, 0, 10);
2365 ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2366 ok(ret, "got %d\n", ret);
2367 ok(size == twips_to_points(cf.yHeight), "got yHeight %d, size %.2f\n", cf.yHeight, size);
2368 ok(position == twips_to_points(cf.yOffset), "got yOffset %d, position %.2f\n", cf.yOffset, position);
2369 ok(kerning == twips_to_points(cf.wKerning), "got wKerning %d, kerning %.2f\n", cf.wKerning, kerning);
2371 hr = ITextFont_Reset(font, tomUseTwips);
2372 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2374 hr = ITextFont_Reset(font, tomUsePoints);
2375 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2377 hr = ITextFont_GetDuplicate(font, &font2);
2378 ok(hr == S_OK, "got 0x%08x\n", hr);
2380 hr = ITextFont_Reset(font2, tomUseTwips);
2381 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2383 hr = ITextFont_Reset(font2, tomUsePoints);
2384 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2386 ITextFont_Release(font2);
2388 /* default font name */
2389 str = NULL;
2390 hr = ITextFont_GetName(font, &str);
2391 ok(hr == S_OK, "got 0x%08x\n", hr);
2392 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2393 SysFreeString(str);
2395 /* change font name for an inner subrange */
2396 memset(&cf, 0, sizeof(cf));
2397 cf.cbSize = sizeof(cf);
2398 cf.dwMask = CFM_FACE;
2399 strcpy(cf.szFaceName, "Arial");
2401 SendMessageA(hwnd, EM_SETSEL, 3, 4);
2402 ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2403 ok(ret, "got %d\n", ret);
2405 /* still original name */
2406 str = NULL;
2407 hr = ITextFont_GetName(font, &str);
2408 ok(hr == S_OK, "got 0x%08x\n", hr);
2409 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2410 SysFreeString(str);
2412 SendMessageA(hwnd, EM_SETSEL, 1, 2);
2413 ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2414 ok(ret, "got %d\n", ret);
2416 str = NULL;
2417 hr = ITextFont_GetName(font, &str);
2418 ok(hr == S_OK, "got 0x%08x\n", hr);
2419 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2420 SysFreeString(str);
2422 /* name is returned for first position within a range */
2423 SendMessageA(hwnd, EM_SETSEL, 0, 1);
2424 ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2425 ok(ret, "got %d\n", ret);
2427 str = NULL;
2428 hr = ITextFont_GetName(font, &str);
2429 ok(hr == S_OK, "got 0x%08x\n", hr);
2430 ok(!lstrcmpW(str, arialW), "got %s\n", wine_dbgstr_w(str));
2431 SysFreeString(str);
2433 /* GetDuplicate() */
2434 hr = ITextFont_GetDuplicate(font, NULL);
2435 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2437 EXPECT_REF(range, 2);
2438 font2 = NULL;
2439 hr = ITextFont_GetDuplicate(font, &font2);
2440 ok(hr == S_OK, "got 0x%08x\n", hr);
2441 EXPECT_REF(range, 2);
2443 /* set whole range to italic */
2444 cf.cbSize = sizeof(CHARFORMAT2A);
2445 cf.dwMask = CFM_ITALIC;
2446 cf.dwEffects = CFE_ITALIC;
2448 SendMessageA(hwnd, EM_SETSEL, 0, 10);
2449 ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2450 ok(ret, "got %d\n", ret);
2452 value = tomFalse;
2453 hr = ITextFont_GetItalic(font, &value);
2454 ok(hr == S_OK, "got 0x%08x\n", hr);
2455 ok(value == tomTrue, "got %d\n", value);
2457 /* duplicate retains original value */
2458 value = tomTrue;
2459 hr = ITextFont_GetItalic(font2, &value);
2460 ok(hr == S_OK, "got 0x%08x\n", hr);
2461 ok(value == tomFalse, "got %d\n", value);
2463 /* get a duplicate from a cloned font */
2464 hr = ITextFont_GetDuplicate(font2, &font3);
2465 ok(hr == S_OK, "got 0x%08x\n", hr);
2466 ITextFont_Release(font3);
2468 ITextRange_Release(range);
2469 release_interfaces(&hwnd, &reOle, &doc, NULL);
2471 hr = ITextFont_GetDuplicate(font, NULL);
2472 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2474 test_detached_font_getters(font, FALSE);
2475 test_detached_font_getters(font2, TRUE);
2477 /* get a duplicate of detached font */
2478 hr = ITextFont_GetDuplicate(font2, &font3);
2479 ok(hr == S_OK, "got 0x%08x\n", hr);
2480 ITextFont_Release(font3);
2482 /* reset detached font to undefined */
2483 value = tomUndefined;
2484 hr = ITextFont_GetBold(font2, &value);
2485 ok(hr == S_OK, "got 0x%08x\n", hr);
2486 ok(value != tomUndefined, "got %d\n", value);
2488 /* reset to undefined for detached font */
2489 hr = ITextFont_Reset(font2, tomUndefined);
2490 ok(hr == S_OK, "got 0x%08x\n", hr);
2491 test_textfont_undefined(font2);
2493 /* font is detached, default means global TOM defaults */
2494 hr = ITextFont_Reset(font2, tomDefault);
2495 ok(hr == S_OK, "got 0x%08x\n", hr);
2496 test_textfont_global_defaults(font2);
2498 hr = ITextFont_GetDuplicate(font2, &font3);
2499 ok(hr == S_OK, "got 0x%08x\n", hr);
2500 test_textfont_global_defaults(font2);
2502 hr = ITextFont_Reset(font2, tomApplyNow);
2503 ok(hr == S_OK, "got 0x%08x\n", hr);
2504 test_textfont_global_defaults(font2);
2506 hr = ITextFont_Reset(font2, tomApplyLater);
2507 ok(hr == S_OK, "got 0x%08x\n", hr);
2508 test_textfont_global_defaults(font2);
2510 hr = ITextFont_Reset(font2, tomTrackParms);
2511 ok(hr == S_OK, "got 0x%08x\n", hr);
2512 test_textfont_global_defaults(font2);
2514 hr = ITextFont_SetItalic(font2, tomUndefined);
2515 ok(hr == S_OK, "got 0x%08x\n", hr);
2517 hr = ITextFont_GetItalic(font2, &value);
2518 ok(hr == S_OK, "got 0x%08x\n", hr);
2519 ok(value == tomFalse, "got %d\n", value);
2521 hr = ITextFont_Reset(font2, tomCacheParms);
2522 ok(hr == S_OK, "got 0x%08x\n", hr);
2523 test_textfont_global_defaults(font2);
2525 ITextFont_Release(font3);
2526 ITextFont_Release(font2);
2528 font2 = (void*)0xdeadbeef;
2529 hr = ITextFont_GetDuplicate(font, &font2);
2530 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2531 ok(font2 == NULL, "got %p\n", font2);
2533 hr = ITextFont_Reset(font, tomDefault);
2534 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2536 ITextFont_Release(font);
2538 /* Reset() */
2539 create_interfaces(&hwnd, &reOle, &doc, NULL);
2540 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2542 hr = ITextDocument_Range(doc, 0, 10, &range);
2543 ok(hr == S_OK, "got 0x%08x\n", hr);
2545 hr = ITextRange_GetFont(range, &font);
2546 ok(hr == S_OK, "got 0x%08x\n", hr);
2548 value = tomUndefined;
2549 hr = ITextFont_GetBold(font, &value);
2550 ok(hr == S_OK, "got 0x%08x\n", hr);
2551 ok(value != tomUndefined, "got %d\n", value);
2553 /* reset to undefined for attached font */
2554 hr = ITextFont_Reset(font, tomUndefined);
2555 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2557 value = tomUndefined;
2558 hr = ITextFont_GetBold(font, &value);
2559 ok(hr == S_OK, "got 0x%08x\n", hr);
2560 ok(value != tomUndefined, "got %d\n", value);
2562 /* tomCacheParms/tomTrackParms */
2563 hr = ITextFont_Reset(font, tomCacheParms);
2564 ok(hr == S_OK, "got 0x%08x\n", hr);
2566 hr = ITextFont_GetItalic(font, &value);
2567 ok(hr == S_OK, "got 0x%08x\n", hr);
2568 ok(value == tomFalse, "got %d\n", value);
2570 memset(&cf, 0, sizeof(cf));
2571 cf.cbSize = sizeof(CHARFORMAT2A);
2572 cf.dwMask = CFM_ITALIC;
2574 cf.dwEffects = CFE_ITALIC;
2575 SendMessageA(hwnd, EM_SETSEL, 0, 10);
2576 ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2577 ok(ret, "got %d\n", ret);
2579 /* still cached value */
2580 hr = ITextFont_GetItalic(font, &value);
2581 ok(hr == S_OK, "got 0x%08x\n", hr);
2582 ok(value == tomFalse, "got %d\n", value);
2584 hr = ITextFont_Reset(font, tomTrackParms);
2585 ok(hr == S_OK, "got 0x%08x\n", hr);
2587 hr = ITextFont_GetItalic(font, &value);
2588 ok(hr == S_OK, "got 0x%08x\n", hr);
2589 ok(value == tomTrue, "got %d\n", value);
2591 /* switch back to cache - value retained */
2592 hr = ITextFont_Reset(font, tomCacheParms);
2593 ok(hr == S_OK, "got 0x%08x\n", hr);
2595 hr = ITextFont_GetItalic(font, &value);
2596 ok(hr == S_OK, "got 0x%08x\n", hr);
2597 ok(value == tomTrue, "got %d\n", value);
2599 /* tomApplyLater */
2600 hr = ITextFont_Reset(font, tomApplyLater);
2601 ok(hr == S_OK, "got 0x%08x\n", hr);
2603 hr = ITextFont_SetItalic(font, tomFalse);
2604 ok(hr == S_OK, "got 0x%08x\n", hr);
2606 hr = ITextFont_GetItalic(font, &value);
2607 ok(hr == S_OK, "got 0x%08x\n", hr);
2608 ok(value == tomFalse, "got %d\n", value);
2610 cf.dwEffects = 0;
2611 SendMessageA(hwnd, EM_SETSEL, 0, 10);
2612 ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2613 ok(ret, "got %d\n", ret);
2614 ok((cf.dwEffects & CFE_ITALIC) == CFE_ITALIC, "got 0x%08x\n", cf.dwEffects);
2616 hr = ITextFont_Reset(font, tomApplyNow);
2617 ok(hr == S_OK, "got 0x%08x\n", hr);
2619 cf.dwEffects = 0;
2620 SendMessageA(hwnd, EM_SETSEL, 0, 10);
2621 ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2622 ok(ret, "got %d\n", ret);
2623 ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2625 hr = ITextFont_SetItalic(font, tomUndefined);
2626 ok(hr == S_OK, "got 0x%08x\n", hr);
2628 hr = ITextFont_GetItalic(font, &value);
2629 ok(hr == S_OK, "got 0x%08x\n", hr);
2630 ok(value == tomFalse, "got %d\n", value);
2632 hr = ITextFont_SetItalic(font, tomAutoColor);
2633 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2635 cf.dwEffects = 0;
2636 SendMessageA(hwnd, EM_SETSEL, 0, 10);
2637 ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2638 ok(ret, "got %d\n", ret);
2639 ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2641 ITextRange_Release(range);
2642 ITextFont_Release(font);
2643 release_interfaces(&hwnd, &reOle, &doc, NULL);
2646 static void test_Delete(void)
2648 static const CHAR test_text1[] = "TestSomeText";
2649 IRichEditOle *reOle = NULL;
2650 ITextDocument *doc = NULL;
2651 ITextRange *range, *range2;
2652 LONG value;
2653 HRESULT hr;
2654 HWND hwnd;
2656 create_interfaces(&hwnd, &reOle, &doc, NULL);
2657 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2659 hr = ITextDocument_Range(doc, 0, 4, &range);
2660 ok(hr == S_OK, "got 0x%08x\n", hr);
2662 hr = ITextDocument_Range(doc, 1, 2, &range2);
2663 ok(hr == S_OK, "got 0x%08x\n", hr);
2665 hr = ITextRange_GetEnd(range, &value);
2666 ok(hr == S_OK, "got 0x%08x\n", hr);
2667 ok(value == 4, "got %d\n", value);
2669 /* unit type doesn't matter is count is 0 */
2670 value = 0;
2671 hr = ITextRange_Delete(range2, tomSentence, 0, &value);
2672 todo_wine {
2673 ok(hr == S_OK, "got 0x%08x\n", hr);
2674 ok(value == 1, "got %d\n", value);
2676 value = 1;
2677 hr = ITextRange_Delete(range2, tomCharacter, 0, &value);
2678 todo_wine {
2679 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2680 ok(value == 0, "got %d\n", value);
2682 hr = ITextRange_GetEnd(range, &value);
2683 ok(hr == S_OK, "got 0x%08x\n", hr);
2684 todo_wine
2685 ok(value == 3, "got %d\n", value);
2687 hr = ITextRange_GetStart(range2, &value);
2688 ok(hr == S_OK, "got 0x%08x\n", hr);
2689 ok(value == 1, "got %d\n", value);
2691 hr = ITextRange_GetEnd(range2, &value);
2692 ok(hr == S_OK, "got 0x%08x\n", hr);
2693 todo_wine
2694 ok(value == 1, "got %d\n", value);
2696 ITextRange_Release(range);
2697 ITextRange_Release(range2);
2698 release_interfaces(&hwnd, &reOle, &doc, NULL);
2701 static void test_SetText(void)
2703 static const CHAR test_text1[] = "TestSomeText";
2704 static const WCHAR textW[] = {'a','b','c','d','e','f','g','h','i',0};
2705 IRichEditOle *reOle = NULL;
2706 ITextDocument *doc = NULL;
2707 ITextRange *range, *range2;
2708 LONG value;
2709 HRESULT hr;
2710 HWND hwnd;
2711 BSTR str;
2713 create_interfaces(&hwnd, &reOle, &doc, NULL);
2714 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2716 hr = ITextDocument_Range(doc, 0, 4, &range);
2717 ok(hr == S_OK, "got 0x%08x\n", hr);
2719 hr = ITextDocument_Range(doc, 0, 4, &range2);
2720 ok(hr == S_OK, "got 0x%08x\n", hr);
2722 value = 1;
2723 hr = ITextRange_GetStart(range2, &value);
2724 ok(hr == S_OK, "got 0x%08x\n", hr);
2725 ok(value == 0, "got %d\n", value);
2727 value = 0;
2728 hr = ITextRange_GetEnd(range2, &value);
2729 ok(hr == S_OK, "got 0x%08x\n", hr);
2730 ok(value == 4, "got %d\n", value);
2732 hr = ITextRange_SetText(range, NULL);
2733 ok(hr == S_OK, "got 0x%08x\n", hr);
2735 value = 1;
2736 hr = ITextRange_GetEnd(range2, &value);
2737 ok(hr == S_OK, "got 0x%08x\n", hr);
2738 ok(value == 0, "got %d\n", value);
2740 str = SysAllocString(textW);
2741 hr = ITextRange_SetText(range, str);
2742 ok(hr == S_OK, "got 0x%08x\n", hr);
2743 SysFreeString(str);
2745 value = 1;
2746 hr = ITextRange_GetStart(range, &value);
2747 ok(hr == S_OK, "got 0x%08x\n", hr);
2748 ok(value == 0, "got %d\n", value);
2750 value = 0;
2751 hr = ITextRange_GetEnd(range, &value);
2752 ok(hr == S_OK, "got 0x%08x\n", hr);
2753 ok(value == 9, "got %d\n", value);
2755 value = 1;
2756 hr = ITextRange_GetStart(range2, &value);
2757 ok(hr == S_OK, "got 0x%08x\n", hr);
2758 ok(value == 0, "got %d\n", value);
2760 value = 0;
2761 hr = ITextRange_GetEnd(range2, &value);
2762 ok(hr == S_OK, "got 0x%08x\n", hr);
2763 ok(value == 0, "got %d\n", value);
2765 str = SysAllocStringLen(NULL, 0);
2766 hr = ITextRange_SetText(range, str);
2767 ok(hr == S_OK, "got 0x%08x\n", hr);
2768 value = 1;
2769 hr = ITextRange_GetEnd(range, &value);
2770 ok(hr == S_OK, "got 0x%08x\n", hr);
2771 ok(value == 0, "got %d\n", value);
2772 SysFreeString(str);
2774 ITextRange_Release(range2);
2775 release_interfaces(&hwnd, &reOle, &doc, NULL);
2777 hr = ITextRange_SetText(range, NULL);
2778 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2780 str = SysAllocStringLen(NULL, 0);
2781 hr = ITextRange_SetText(range, str);
2782 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2783 SysFreeString(str);
2785 ITextRange_Release(range);
2788 static void test_InRange(void)
2790 static const CHAR test_text1[] = "TestSomeText";
2791 ITextRange *range, *range2, *range3;
2792 IRichEditOle *reOle = NULL;
2793 ITextDocument *doc = NULL;
2794 ITextSelection *selection;
2795 LONG value;
2796 HRESULT hr;
2797 HWND hwnd;
2799 create_interfaces(&hwnd, &reOle, &doc, &selection);
2800 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2801 SendMessageA(hwnd, EM_SETSEL, 1, 2);
2803 hr = ITextDocument_Range(doc, 0, 4, &range);
2804 ok(hr == S_OK, "got 0x%08x\n", hr);
2806 hr = ITextDocument_Range(doc, 0, 4, &range2);
2807 ok(hr == S_OK, "got 0x%08x\n", hr);
2809 /* matches selection */
2810 hr = ITextDocument_Range(doc, 1, 2, &range3);
2811 ok(hr == S_OK, "got 0x%08x\n", hr);
2813 hr = ITextRange_InRange(range, NULL, NULL);
2814 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2816 value = tomTrue;
2817 hr = ITextRange_InRange(range, NULL, &value);
2818 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2819 ok(value == tomFalse, "got %d\n", value);
2821 hr = ITextRange_InRange(range, range2, NULL);
2822 ok(hr == S_OK, "got 0x%08x\n", hr);
2824 value = tomFalse;
2825 hr = ITextRange_InRange(range, range2, &value);
2826 ok(hr == S_OK, "got 0x%08x\n", hr);
2827 ok(value == tomTrue, "got %d\n", value);
2829 /* selection */
2830 hr = ITextSelection_InRange(selection, NULL, NULL);
2831 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2833 value = tomTrue;
2834 hr = ITextSelection_InRange(selection, NULL, &value);
2835 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2836 ok(value == tomFalse, "got %d\n", value);
2838 hr = ITextSelection_InRange(selection, range2, NULL);
2839 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2841 value = tomTrue;
2842 hr = ITextSelection_InRange(selection, range2, &value);
2843 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2844 ok(value == tomFalse, "got %d\n", value);
2846 value = tomTrue;
2847 hr = ITextSelection_InRange(selection, range3, &value);
2848 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2849 ok(value == tomFalse, "got %d\n", value);
2851 /* seems to work on ITextSelection ranges only */
2852 value = tomFalse;
2853 hr = ITextSelection_InRange(selection, (ITextRange*)selection, &value);
2854 ok(hr == S_OK, "got 0x%08x\n", hr);
2855 ok(value == tomTrue, "got %d\n", value);
2857 release_interfaces(&hwnd, &reOle, &doc, NULL);
2859 hr = ITextRange_InRange(range, NULL, NULL);
2860 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2862 value = tomTrue;
2863 hr = ITextRange_InRange(range, NULL, &value);
2864 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2865 ok(value == tomFalse, "got %d\n", value);
2867 hr = ITextRange_InRange(range, range2, NULL);
2868 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2870 value = tomTrue;
2871 hr = ITextRange_InRange(range, range2, &value);
2872 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2873 ok(value == tomFalse, "got %d\n", value);
2875 /* selection */
2876 hr = ITextSelection_InRange(selection, NULL, NULL);
2877 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2879 value = tomTrue;
2880 hr = ITextSelection_InRange(selection, NULL, &value);
2881 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2882 ok(value == tomFalse, "got %d\n", value);
2884 hr = ITextSelection_InRange(selection, range2, NULL);
2885 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2887 value = tomTrue;
2888 hr = ITextSelection_InRange(selection, range2, &value);
2889 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2890 ok(value == tomFalse, "got %d\n", value);
2892 ITextRange_Release(range);
2893 ITextRange_Release(range2);
2894 ITextRange_Release(range3);
2895 ITextSelection_Release(selection);
2898 static void test_ITextRange_IsEqual(void)
2900 static const CHAR test_text1[] = "TestSomeText";
2901 ITextRange *range, *range2, *range3;
2902 IRichEditOle *reOle = NULL;
2903 ITextDocument *doc = NULL;
2904 ITextSelection *selection;
2905 LONG value;
2906 HRESULT hr;
2907 HWND hwnd;
2909 create_interfaces(&hwnd, &reOle, &doc, &selection);
2910 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2911 SendMessageA(hwnd, EM_SETSEL, 1, 2);
2913 hr = ITextDocument_Range(doc, 0, 4, &range);
2914 ok(hr == S_OK, "got 0x%08x\n", hr);
2916 hr = ITextDocument_Range(doc, 0, 4, &range2);
2917 ok(hr == S_OK, "got 0x%08x\n", hr);
2919 /* matches selection */
2920 hr = ITextDocument_Range(doc, 1, 2, &range3);
2921 ok(hr == S_OK, "got 0x%08x\n", hr);
2923 hr = ITextRange_IsEqual(range, NULL, NULL);
2924 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2926 value = tomTrue;
2927 hr = ITextRange_IsEqual(range, NULL, &value);
2928 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2929 ok(value == tomFalse, "got %d\n", value);
2931 hr = ITextRange_IsEqual(range, range2, NULL);
2932 ok(hr == S_OK, "got 0x%08x\n", hr);
2934 value = tomFalse;
2935 hr = ITextRange_IsEqual(range, range2, &value);
2936 ok(hr == S_OK, "got 0x%08x\n", hr);
2937 ok(value == tomTrue, "got %d\n", value);
2939 value = tomTrue;
2940 hr = ITextRange_IsEqual(range, range3, &value);
2941 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2942 ok(value == tomFalse, "got %d\n", value);
2944 /* selection */
2945 hr = ITextSelection_IsEqual(selection, NULL, NULL);
2946 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2948 value = tomTrue;
2949 hr = ITextSelection_IsEqual(selection, NULL, &value);
2950 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2951 ok(value == tomFalse, "got %d\n", value);
2953 hr = ITextSelection_IsEqual(selection, range2, NULL);
2954 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2956 value = tomTrue;
2957 hr = ITextSelection_IsEqual(selection, range2, &value);
2958 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2959 ok(value == tomFalse, "got %d\n", value);
2961 value = tomTrue;
2962 hr = ITextSelection_IsEqual(selection, range3, &value);
2963 ok(hr == S_FALSE, "got 0x%08x\n", hr);
2964 ok(value == tomFalse, "got %d\n", value);
2966 /* seems to work on ITextSelection ranges only */
2967 value = tomFalse;
2968 hr = ITextSelection_IsEqual(selection, (ITextRange*)selection, &value);
2969 ok(hr == S_OK, "got 0x%08x\n", hr);
2970 ok(value == tomTrue, "got %d\n", value);
2972 release_interfaces(&hwnd, &reOle, &doc, NULL);
2974 hr = ITextRange_IsEqual(range, NULL, NULL);
2975 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2977 value = tomTrue;
2978 hr = ITextRange_IsEqual(range, NULL, &value);
2979 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2980 ok(value == tomFalse, "got %d\n", value);
2982 hr = ITextRange_IsEqual(range, range2, NULL);
2983 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2985 value = tomTrue;
2986 hr = ITextRange_IsEqual(range, range2, &value);
2987 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2988 ok(value == tomFalse, "got %d\n", value);
2990 /* selection */
2991 hr = ITextSelection_IsEqual(selection, NULL, NULL);
2992 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2994 value = tomTrue;
2995 hr = ITextSelection_IsEqual(selection, NULL, &value);
2996 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2997 ok(value == tomFalse, "got %d\n", value);
2999 hr = ITextSelection_IsEqual(selection, range2, NULL);
3000 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3002 value = tomTrue;
3003 hr = ITextSelection_IsEqual(selection, range2, &value);
3004 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3005 ok(value == tomFalse, "got %d\n", value);
3007 ITextRange_Release(range);
3008 ITextRange_Release(range2);
3009 ITextRange_Release(range3);
3010 ITextSelection_Release(selection);
3013 static void test_Select(void)
3015 static const CHAR test_text1[] = "TestSomeText";
3016 IRichEditOle *reOle = NULL;
3017 ITextDocument *doc = NULL;
3018 ITextSelection *selection;
3019 ITextRange *range;
3020 LONG value;
3021 HRESULT hr;
3022 HWND hwnd;
3024 create_interfaces(&hwnd, &reOle, &doc, &selection);
3025 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3026 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3028 hr = ITextDocument_Range(doc, 0, 4, &range);
3029 ok(hr == S_OK, "got 0x%08x\n", hr);
3031 hr = ITextRange_Select(range);
3032 ok(hr == S_OK, "got 0x%08x\n", hr);
3034 value = 1;
3035 hr = ITextSelection_GetStart(selection, &value);
3036 ok(hr == S_OK, "got 0x%08x\n", hr);
3037 ok(value == 0, "got %d\n", value);
3039 hr = ITextRange_Select(range);
3040 ok(hr == S_OK, "got 0x%08x\n", hr);
3042 hr = ITextSelection_Select(selection);
3043 ok(hr == S_OK, "got 0x%08x\n", hr);
3045 release_interfaces(&hwnd, &reOle, &doc, NULL);
3047 hr = ITextRange_Select(range);
3048 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3050 hr = ITextSelection_Select(selection);
3051 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3053 ITextRange_Release(range);
3054 ITextSelection_Release(selection);
3057 static void test_GetStoryType(void)
3059 static const CHAR test_text1[] = "TestSomeText";
3060 IRichEditOle *reOle = NULL;
3061 ITextDocument *doc = NULL;
3062 ITextSelection *selection;
3063 ITextRange *range;
3064 LONG value;
3065 HRESULT hr;
3066 HWND hwnd;
3068 create_interfaces(&hwnd, &reOle, &doc, &selection);
3069 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3070 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3072 hr = ITextDocument_Range(doc, 0, 4, &range);
3073 ok(hr == S_OK, "got 0x%08x\n", hr);
3075 hr = ITextRange_GetStoryType(range, NULL);
3076 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3078 value = tomTextFrameStory;
3079 hr = ITextRange_GetStoryType(range, &value);
3080 ok(hr == S_OK, "got 0x%08x\n", hr);
3081 ok(value == tomUnknownStory, "got %d\n", value);
3083 hr = ITextSelection_GetStoryType(selection, NULL);
3084 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3086 value = tomTextFrameStory;
3087 hr = ITextSelection_GetStoryType(selection, &value);
3088 ok(hr == S_OK, "got 0x%08x\n", hr);
3089 ok(value == tomUnknownStory, "got %d\n", value);
3091 release_interfaces(&hwnd, &reOle, &doc, NULL);
3093 hr = ITextRange_GetStoryType(range, NULL);
3094 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3096 value = 123;
3097 hr = ITextRange_GetStoryType(range, &value);
3098 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3099 ok(value == 123, "got %d\n", value);
3101 hr = ITextSelection_GetStoryType(selection, NULL);
3102 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3104 value = 123;
3105 hr = ITextSelection_GetStoryType(selection, &value);
3106 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3107 ok(value == 123, "got %d\n", value);
3109 ITextRange_Release(range);
3110 ITextSelection_Release(selection);
3113 static void test_SetFont(void)
3115 static const CHAR test_text1[] = "TestSomeText";
3116 IRichEditOle *reOle = NULL;
3117 ITextDocument *doc = NULL;
3118 ITextSelection *selection;
3119 ITextRange *range, *range2;
3120 ITextFont *font, *font2;
3121 LONG value;
3122 HRESULT hr;
3123 HWND hwnd;
3125 create_interfaces(&hwnd, &reOle, &doc, &selection);
3126 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3127 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3129 hr = ITextDocument_Range(doc, 0, 4, &range);
3130 ok(hr == S_OK, "got 0x%08x\n", hr);
3132 hr = ITextDocument_Range(doc, 5, 2, &range2);
3133 ok(hr == S_OK, "got 0x%08x\n", hr);
3135 EXPECT_REF(range, 1);
3136 hr = ITextRange_GetFont(range, &font);
3137 ok(hr == S_OK, "got 0x%08x\n", hr);
3138 EXPECT_REF(range, 2);
3140 EXPECT_REF(range2, 1);
3141 hr = ITextRange_GetFont(range2, &font2);
3142 ok(hr == S_OK, "got 0x%08x\n", hr);
3143 EXPECT_REF(range2, 2);
3145 hr = ITextRange_SetFont(range, NULL);
3146 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3148 /* setting same font, no-op */
3149 EXPECT_REF(range, 2);
3150 hr = ITextRange_SetFont(range, font);
3151 ok(hr == S_OK, "got 0x%08x\n", hr);
3152 EXPECT_REF(range, 2);
3154 EXPECT_REF(range2, 2);
3155 EXPECT_REF(range, 2);
3156 hr = ITextRange_SetFont(range, font2);
3157 ok(hr == S_OK, "got 0x%08x\n", hr);
3158 EXPECT_REF(range2, 2);
3159 EXPECT_REF(range, 2);
3161 /* originally range 0-4 is non-italic */
3162 value = tomTrue;
3163 hr = ITextFont_GetItalic(font, &value);
3164 ok(hr == S_OK, "got 0x%08x\n", hr);
3165 ok(value == tomFalse, "got %d\n", value);
3167 /* set range 5-2 to italic, then set this font to range 0-4 */
3168 hr = ITextFont_SetItalic(font2, tomTrue);
3169 ok(hr == S_OK, "got 0x%08x\n", hr);
3171 hr = ITextRange_SetFont(range, font2);
3172 ok(hr == S_OK, "got 0x%08x\n", hr);
3174 value = tomFalse;
3175 hr = ITextFont_GetItalic(font, &value);
3176 ok(hr == S_OK, "got 0x%08x\n", hr);
3177 ok(value == tomTrue, "got %d\n", value);
3179 release_interfaces(&hwnd, &reOle, &doc, NULL);
3181 hr = ITextRange_SetFont(range, NULL);
3182 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3184 hr = ITextRange_SetFont(range, font);
3185 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3187 hr = ITextSelection_SetFont(selection, NULL);
3188 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3190 hr = ITextSelection_SetFont(selection, font);
3191 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3193 ITextFont_Release(font);
3194 ITextFont_Release(font2);
3195 ITextRange_Release(range);
3196 ITextRange_Release(range2);
3197 ITextSelection_Release(selection);
3200 static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
3201 LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
3202 LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
3204 reobj->cbStruct = sizeof(*reobj);
3205 reobj->clsid = CLSID_NULL;
3206 reobj->cp = cp;
3207 reobj->poleobj = poleobj;
3208 reobj->pstg = pstg;
3209 reobj->polesite = polesite;
3210 reobj->sizel.cx = sizel_cx;
3211 reobj->sizel.cy = sizel_cy;
3212 reobj->dvaspect = aspect;
3213 reobj->dwFlags = flags;
3214 reobj->dwUser = user;
3217 #define CHECK_REOBJECT_STRUCT(reole,index,flags,cp,poleobj,pstg,polesite,user) \
3218 _check_reobject_struct(reole, index, flags, cp, poleobj, pstg, polesite, user, __LINE__)
3219 static void _check_reobject_struct(IRichEditOle *reole, LONG index, DWORD flags, LONG cp,
3220 LPOLEOBJECT poleobj, LPSTORAGE pstg, LPOLECLIENTSITE polesite, DWORD user, int line)
3222 REOBJECT reobj;
3223 HRESULT hr;
3225 reobj.cbStruct = sizeof(reobj);
3226 reobj.cp = cp;
3227 hr = IRichEditOle_GetObject(reole, index, &reobj, flags);
3228 ok(hr == S_OK, "IRichEditOle_GetObject failed: %#x.\n", hr);
3229 ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n");
3230 ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n");
3231 ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n");
3232 ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
3235 #define INSERT_REOBJECT(reole,reobj,cp,user) \
3236 _insert_reobject(reole, reobj, cp, user, __LINE__)
3237 static void _insert_reobject(IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line)
3239 IOleClientSite *clientsite;
3240 HRESULT hr;
3241 hr = IRichEditOle_GetClientSite(reole, &clientsite);
3242 ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_GetClientSite got hr %#x.\n", hr);
3243 fill_reobject_struct(reobj, cp, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, user);
3244 hr = IRichEditOle_InsertObject(reole, reobj);
3245 ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_InsertObject got hr %#x.\n", hr);
3246 IOleClientSite_Release(clientsite);
3249 static void test_InsertObject(void)
3251 static CHAR test_text1[] = "abcdefg";
3252 IRichEditOle *reole = NULL;
3253 ITextDocument *doc = NULL;
3254 REOBJECT reo1, reo2, reo3, received_reo;
3255 HRESULT hr;
3256 HWND hwnd;
3257 const WCHAR *expected_string, *string;
3258 const CHAR *expected_stringA;
3259 ITextSelection *selection;
3260 IDataObject *dataobject;
3261 TEXTRANGEA textrange;
3262 FORMATETC formatetc;
3263 CHARRANGE charrange;
3264 GETTEXTEX gettextex;
3265 STGMEDIUM stgmedium;
3266 WCHAR buffer[1024];
3267 CHAR bufferA[1024];
3268 LONG count, result;
3269 ITextRange *range;
3270 BSTR bstr;
3272 create_interfaces(&hwnd, &reole, &doc, &selection);
3273 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3275 hr = IRichEditOle_InsertObject(reole, NULL);
3276 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3278 /* insert object1 in (0, 1)*/
3279 SendMessageA(hwnd, EM_SETSEL, 0, 1);
3280 INSERT_REOBJECT(reole, &reo1, REO_CP_SELECTION, 1);
3281 count = IRichEditOle_GetObjectCount(reole);
3282 ok(count == 1, "got wrong object count: %d\n", count);
3284 /* insert object2 in (2, 3)*/
3285 SendMessageA(hwnd, EM_SETSEL, 2, 3);
3286 INSERT_REOBJECT(reole, &reo2, REO_CP_SELECTION, 2);
3287 count = IRichEditOle_GetObjectCount(reole);
3288 ok(count == 2, "got wrong object count: %d\n", count);
3290 /* insert object3 in (1, 2)*/
3291 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3292 INSERT_REOBJECT(reole, &reo3, REO_CP_SELECTION, 3);
3293 count = IRichEditOle_GetObjectCount(reole);
3294 ok(count == 3, "got wrong object count: %d\n", count);
3296 /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
3297 CHECK_REOBJECT_STRUCT(reole, 0, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1);
3298 CHECK_REOBJECT_STRUCT(reole, 1, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3);
3299 CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo2.polesite, 2);
3301 hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES);
3302 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3304 received_reo.cbStruct = 0;
3305 hr = IRichEditOle_GetObject(reole, 2, &received_reo, REO_GETOBJ_ALL_INTERFACES);
3306 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3308 CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_PSTG, 0, NULL, NULL, NULL, 2);
3309 CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_POLESITE, 0, NULL, NULL, reo2.polesite, 2);
3311 hr = IRichEditOle_GetObject(reole, 3, &received_reo, REO_GETOBJ_POLESITE);
3312 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3314 hr = IRichEditOle_GetObject(reole, 4, &received_reo, REO_GETOBJ_POLESITE);
3315 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3317 hr = IRichEditOle_GetObject(reole, 1024, &received_reo, REO_GETOBJ_POLESITE);
3318 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3320 hr = IRichEditOle_GetObject(reole, -10, &received_reo, REO_GETOBJ_POLESITE);
3321 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3323 /* received_reo will be zeroed before be used */
3324 received_reo.cbStruct = sizeof(received_reo);
3325 received_reo.polesite = (IOleClientSite *)0xdeadbeef;
3326 hr = IRichEditOle_GetObject(reole, 2, &received_reo, REO_GETOBJ_NO_INTERFACES);
3327 ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3328 ok(received_reo.polesite == NULL, "Got wrong site interface.\n");
3330 CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1);
3331 CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo3.polesite, 3);
3332 CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 2, NULL, NULL, reo2.polesite, 2);
3334 received_reo.cbStruct = sizeof(received_reo);
3335 received_reo.polesite = (IOleClientSite *)0xdeadbeef;
3336 received_reo.dwUser = 4;
3337 received_reo.cp = 4;
3338 hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo, REO_GETOBJ_ALL_INTERFACES);
3339 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3340 ok(received_reo.polesite == (IOleClientSite *)0xdeadbeef, "Got wrong site interface.\n");
3341 ok(received_reo.dwUser == 4, "Got wrong user-defined value: %d.\n", received_reo.dwUser);
3343 SendMessageA(hwnd, EM_SETSEL, 0, 1);
3344 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1);
3346 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3347 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3);
3349 SendMessageA(hwnd, EM_SETSEL, 2, 3);
3350 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo2.polesite, 2);
3352 SendMessageA(hwnd, EM_SETSEL, 0, 2);
3353 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1);
3355 SendMessageA(hwnd, EM_SETSEL, 1, 3);
3356 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3);
3358 SendMessageA(hwnd, EM_SETSEL, 2, 0);
3359 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1);
3361 SendMessageA(hwnd, EM_SETSEL, 0, 6);
3362 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1);
3364 SendMessageA(hwnd, EM_SETSEL, 4, 5);
3365 received_reo.cbStruct = sizeof(received_reo);
3366 received_reo.cp = 0;
3367 hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo, REO_GETOBJ_ALL_INTERFACES);
3368 ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3370 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3372 /* "abc|d|efg" */
3373 INSERT_REOBJECT(reole, &reo1, 3, 1);
3374 INSERT_REOBJECT(reole, &reo2, 5, 2);
3376 SendMessageW(hwnd, EM_SETSEL, 2, 3);
3377 result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
3378 ok(result == SEL_TEXT, "Got selection type: %x.\n", result);
3380 SendMessageW(hwnd, EM_SETSEL, 3, 4);
3381 result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
3382 ok(result == SEL_OBJECT, "Got selection type: %x.\n", result);
3383 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo1.polesite, 1);
3385 SendMessageW(hwnd, EM_SETSEL, 2, 4);
3386 result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
3387 ok(result == (SEL_TEXT | SEL_OBJECT), "Got selection type: %x.\n", result);
3389 SendMessageW(hwnd, EM_SETSEL, 5, 6);
3390 CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo2.polesite, 2);
3392 expected_string = L"abc\xfffc""d\xfffc""efg";
3393 gettextex.cb = sizeof(buffer);
3394 gettextex.flags = GT_DEFAULT;
3395 gettextex.codepage = 1200;
3396 gettextex.lpDefaultChar = NULL;
3397 gettextex.lpUsedDefChar = NULL;
3398 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3399 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3400 todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3402 gettextex.flags = GT_RAWTEXT;
3403 memset(buffer, 0, sizeof(buffer));
3404 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3405 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3406 todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3408 gettextex.flags = GT_NOHIDDENTEXT;
3409 memset(buffer, 0, sizeof(buffer));
3410 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3411 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3412 todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3414 gettextex.flags = GT_SELECTION;
3415 memset(buffer, 0, sizeof(buffer));
3416 SendMessageW(hwnd, EM_SETSEL, 0, -1);
3417 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3418 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3419 todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3421 expected_string = L"abc d efg";
3422 gettextex.flags = GT_USECRLF;
3423 memset(buffer, 0, sizeof(buffer));
3424 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3425 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3426 ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3428 expected_stringA = "abc d efg";
3429 memset(bufferA, 0, sizeof(bufferA));
3430 SendMessageA(hwnd, EM_SETSEL, 0, -1);
3431 result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA);
3432 ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
3433 ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
3435 memset(bufferA, 0, sizeof(bufferA));
3436 textrange.lpstrText = bufferA;
3437 textrange.chrg.cpMin = 0;
3438 textrange.chrg.cpMax = 11;
3439 result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange);
3440 ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
3441 ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
3443 expected_string = L"abc\xfffc""d\xfffc""efg\r";
3444 hr = ITextDocument_Range(doc, 0, 11, &range);
3445 ok(hr == S_OK, "Got hr %#x.\n", hr);
3446 hr = ITextRange_GetText(range, &bstr);
3447 ok(hr == S_OK, "Got hr %#x.\n", hr);
3448 ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr));
3449 todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr));
3450 SysFreeString(bstr);
3451 hr = ITextRange_SetRange(range, 3, 4);
3452 ok(hr == S_OK, "Got hr %#x.\n", hr);
3453 hr = ITextRange_GetChar(range, &result);
3454 ok(hr == S_OK, "Got hr %#x.\n", hr);
3455 todo_wine ok(result == 0xfffc, "Got char: %c\n", result);
3456 ITextRange_Release(range);
3458 SendMessageW(hwnd, EM_SETSEL, 0, -1);
3459 hr = ITextSelection_GetText(selection, &bstr);
3460 ok(hr == S_OK, "Got hr %#x.\n", hr);
3461 ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr));
3462 todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr));
3463 SysFreeString(bstr);
3464 SendMessageW(hwnd, EM_SETSEL, 3, 4);
3465 result = 0;
3466 hr = ITextSelection_GetChar(selection, &result);
3467 ok(hr == S_OK, "Got hr %#x.\n", hr);
3468 todo_wine ok(result == 0xfffc, "Got char: %c\n", result);
3470 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
3471 result = SendMessageW(hwnd, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT, 0);
3472 ok(!result, "Got result %x.\n", result);
3473 /* "abc|d|efg" */
3474 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3475 INSERT_REOBJECT(reole, &reo1, 3, 1);
3476 INSERT_REOBJECT(reole, &reo2, 5, 2);
3478 expected_string = L"abc d efg";
3479 charrange.cpMin = 0;
3480 charrange.cpMax = 11;
3481 hr = IRichEditOle_GetClipboardData(reole, &charrange, 1, &dataobject);
3482 ok(hr == S_OK, "Got hr %#x.\n", hr);
3483 formatetc.cfFormat = CF_UNICODETEXT;
3484 formatetc.dwAspect = DVASPECT_CONTENT;
3485 formatetc.ptd = NULL;
3486 formatetc.tymed = TYMED_HGLOBAL;
3487 formatetc.lindex = -1;
3488 hr = IDataObject_GetData(dataobject, &formatetc, &stgmedium);
3489 ok(hr == S_OK, "Got hr %#x.\n", hr);
3490 string = GlobalLock(stgmedium.hGlobal);
3491 ok(lstrlenW(string) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(string));
3492 ok(!lstrcmpW(string, expected_string), "Got wrong content: %s.\n", debugstr_w(string));
3493 GlobalUnlock(stgmedium.hGlobal);
3495 expected_string = L"abc\xfffc""d\xfffc""efg";
3496 gettextex.cb = sizeof(buffer);
3497 gettextex.flags = GT_DEFAULT;
3498 gettextex.codepage = 1200;
3499 gettextex.lpDefaultChar = NULL;
3500 gettextex.lpUsedDefChar = NULL;
3501 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3502 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3503 todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3505 gettextex.flags = GT_RAWTEXT;
3506 memset(buffer, 0, sizeof(buffer));
3507 result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer);
3508 ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result);
3509 todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer));
3511 expected_stringA = "abc d efg";
3512 memset(bufferA, 0, sizeof(bufferA));
3513 SendMessageA(hwnd, EM_SETSEL, 0, -1);
3514 result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA);
3515 ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
3516 ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
3518 memset(bufferA, 0, sizeof(bufferA));
3519 textrange.lpstrText = bufferA;
3520 textrange.chrg.cpMin = 0;
3521 textrange.chrg.cpMax = 11;
3522 result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange);
3523 ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
3524 ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
3526 expected_string = L"abc\xfffc""d\xfffc""efg";
3527 hr = ITextDocument_Range(doc, 0, 11, &range);
3528 ok(hr == S_OK, "Got hr %#x.\n", hr);
3529 hr = ITextRange_GetText(range, &bstr);
3530 ok(hr == S_OK, "Got hr %#x.\n", hr);
3531 todo_wine ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr));
3532 todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr));
3533 SysFreeString(bstr);
3534 hr = ITextRange_SetRange(range, 3, 4);
3535 ok(hr == S_OK, "Got hr %#x.\n", hr);
3536 hr = ITextRange_GetChar(range, &result);
3537 ok(hr == S_OK, "Got hr %#x.\n", hr);
3538 todo_wine ok(result == 0xfffc, "Got char: %c\n", result);
3539 ITextRange_Release(range);
3541 SendMessageW(hwnd, EM_SETSEL, 0, -1);
3542 hr = ITextSelection_GetText(selection, &bstr);
3543 ok(hr == S_OK, "Got hr %#x.\n", hr);
3544 todo_wine ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr));
3545 todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr));
3546 SysFreeString(bstr);
3547 SendMessageW(hwnd, EM_SETSEL, 3, 4);
3548 result = 0;
3549 hr = ITextSelection_GetChar(selection, &result);
3550 ok(hr == S_OK, "Got hr %#x.\n", hr);
3551 todo_wine ok(result == 0xfffc, "Got char: %c\n", result);
3553 release_interfaces(&hwnd, &reole, &doc, &selection);
3556 static void test_GetStoryLength(void)
3558 static const CHAR test_text1[] = "TestSomeText";
3559 IRichEditOle *reOle = NULL;
3560 ITextDocument *doc = NULL;
3561 ITextSelection *selection;
3562 ITextRange *range;
3563 LONG value;
3564 HRESULT hr;
3565 HWND hwnd;
3567 create_interfaces(&hwnd, &reOle, &doc, &selection);
3568 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3569 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3571 hr = ITextDocument_Range(doc, 0, 4, &range);
3572 ok(hr == S_OK, "got 0x%08x\n", hr);
3574 hr = ITextRange_GetStoryLength(range, NULL);
3575 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3577 value = 0;
3578 hr = ITextRange_GetStoryLength(range, &value);
3579 ok(hr == S_OK, "got 0x%08x\n", hr);
3580 ok(value == 13, "got %d\n", value);
3582 hr = ITextSelection_GetStoryLength(selection, NULL);
3583 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3585 value = 0;
3586 hr = ITextSelection_GetStoryLength(selection, &value);
3587 ok(hr == S_OK, "got 0x%08x\n", hr);
3588 ok(value == 13, "got %d\n", value);
3590 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
3592 value = 0;
3593 hr = ITextRange_GetStoryLength(range, &value);
3594 ok(hr == S_OK, "got 0x%08x\n", hr);
3595 ok(value == 1, "got %d\n", value);
3597 value = 0;
3598 hr = ITextSelection_GetStoryLength(selection, &value);
3599 ok(hr == S_OK, "got 0x%08x\n", hr);
3600 ok(value == 1, "got %d\n", value);
3602 release_interfaces(&hwnd, &reOle, &doc, NULL);
3604 hr = ITextRange_GetStoryLength(range, NULL);
3605 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3607 value = 100;
3608 hr = ITextRange_GetStoryLength(range, &value);
3609 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3610 ok(value == 100, "got %d\n", value);
3612 hr = ITextSelection_GetStoryLength(selection, NULL);
3613 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3615 value = 100;
3616 hr = ITextSelection_GetStoryLength(selection, &value);
3617 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3618 ok(value == 100, "got %d\n", value);
3620 ITextSelection_Release(selection);
3621 ITextRange_Release(range);
3624 static void test_ITextSelection_GetDuplicate(void)
3626 static const CHAR test_text1[] = "TestSomeText";
3627 IRichEditOle *reOle = NULL;
3628 ITextDocument *doc = NULL;
3629 ITextSelection *selection, *sel2;
3630 ITextRange *range, *range2;
3631 ITextFont *font;
3632 LONG value;
3633 HRESULT hr;
3634 HWND hwnd;
3636 create_interfaces(&hwnd, &reOle, &doc, &selection);
3637 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3638 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3640 hr = ITextSelection_GetDuplicate(selection, NULL);
3641 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3643 EXPECT_REF(selection, 2);
3645 hr = ITextSelection_GetDuplicate(selection, &range);
3646 ok(hr == S_OK, "got 0x%08x\n", hr);
3648 hr = ITextSelection_GetDuplicate(selection, &range2);
3649 ok(hr == S_OK, "got 0x%08x\n", hr);
3650 ok(range != range2, "got %p, %p\n", range, range2);
3652 EXPECT_REF(selection, 2);
3653 EXPECT_REF(range, 1);
3654 EXPECT_REF(range2, 1);
3656 ITextRange_Release(range2);
3658 value = 0;
3659 hr = ITextRange_GetStart(range, &value);
3660 ok(hr == S_OK, "got 0x%08x\n", hr);
3661 ok(value == 1, "got %d\n", value);
3663 value = 0;
3664 hr = ITextRange_GetEnd(range, &value);
3665 ok(hr == S_OK, "got 0x%08x\n", hr);
3666 ok(value == 2, "got %d\n", value);
3668 SendMessageA(hwnd, EM_SETSEL, 2, 3);
3670 value = 0;
3671 hr = ITextRange_GetStart(range, &value);
3672 ok(hr == S_OK, "got 0x%08x\n", hr);
3673 ok(value == 1, "got %d\n", value);
3675 value = 0;
3676 hr = ITextRange_GetEnd(range, &value);
3677 ok(hr == S_OK, "got 0x%08x\n", hr);
3678 ok(value == 2, "got %d\n", value);
3680 hr = ITextRange_QueryInterface(range, &IID_ITextSelection, (void**)&sel2);
3681 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
3683 release_interfaces(&hwnd, &reOle, &doc, NULL);
3685 hr = ITextSelection_GetDuplicate(selection, NULL);
3686 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3688 hr = ITextSelection_GetDuplicate(selection, &range);
3689 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3691 hr = ITextRange_GetFont(range, &font);
3692 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3694 ITextSelection_Release(selection);
3695 ITextRange_Release(range);
3698 #define RESET_RANGE(range,start,end) \
3699 _reset_range(range, start, end, __LINE__)
3700 static void _reset_range(ITextRange *range, LONG start, LONG end, int line)
3702 HRESULT hr;
3704 hr = ITextRange_SetStart(range, start);
3705 ok_(__FILE__,line)(hr == S_OK, "SetStart failed: 0x%08x\n", hr);
3706 hr = ITextRange_SetEnd(range, end);
3707 ok_(__FILE__,line)(hr == S_OK, "SetEnd failed: 0x%08x\n", hr);
3710 #define CHECK_RANGE(range,expected_start,expected_end) \
3711 _check_range(range, expected_start, expected_end, __LINE__)
3712 static void _check_range(ITextRange* range, LONG expected_start, LONG expected_end, int line)
3714 HRESULT hr;
3715 LONG value;
3717 hr = ITextRange_GetStart(range, &value);
3718 ok_(__FILE__,line)(hr == S_OK, "GetStart failed: 0x%08x\n", hr);
3719 ok_(__FILE__,line)(value == expected_start, "Expected start %d got %d\n",
3720 expected_start, value);
3721 hr = ITextRange_GetEnd(range, &value);
3722 ok_(__FILE__,line)(hr == S_OK, "GetEnd failed: 0x%08x\n", hr);
3723 ok_(__FILE__,line)(value == expected_end, "Expected end %d got %d\n",
3724 expected_end, value);
3727 #define RESET_SELECTION(selection,start,end) \
3728 _reset_selection(selection, start, end, __LINE__)
3729 static void _reset_selection(ITextSelection *selection, LONG start, LONG end, int line)
3731 HRESULT hr;
3733 hr = ITextSelection_SetStart(selection, start);
3734 ok_(__FILE__,line)(hr == S_OK, "SetStart failed: 0x%08x\n", hr);
3735 hr = ITextSelection_SetEnd(selection, end);
3736 ok_(__FILE__,line)(hr == S_OK, "SetEnd failed: 0x%08x\n", hr);
3739 #define CHECK_SELECTION(selection,expected_start,expected_end) \
3740 _check_selection(selection, expected_start, expected_end, __LINE__)
3741 static void _check_selection(ITextSelection *selection, LONG expected_start, LONG expected_end, int line)
3743 HRESULT hr;
3744 LONG value;
3746 hr = ITextSelection_GetStart(selection, &value);
3747 ok_(__FILE__,line)(hr == S_OK, "GetStart failed: 0x%08x\n", hr);
3748 ok_(__FILE__,line)(value == expected_start, "Expected start %d got %d\n",
3749 expected_start, value);
3750 hr = ITextSelection_GetEnd(selection, &value);
3751 ok_(__FILE__,line)(hr == S_OK, "GetEnd failed: 0x%08x\n", hr);
3752 ok_(__FILE__,line)(value == expected_end, "Expected end %d got %d\n",
3753 expected_end, value);
3756 static void test_ITextRange_SetRange(void)
3758 static const CHAR test_text1[] = "TestSomeText";
3759 ITextDocument *txtDoc = NULL;
3760 IRichEditOle *reOle = NULL;
3761 ITextRange *txtRge = NULL;
3762 HRESULT hr;
3763 HWND w;
3765 create_interfaces(&w, &reOle, &txtDoc, NULL);
3766 SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3767 ITextDocument_Range(txtDoc, 0, 0, &txtRge);
3769 hr = ITextRange_SetRange(txtRge, 2, 4);
3770 ok(hr == S_OK, "got 0x%08x.\n", hr);
3771 CHECK_RANGE(txtRge, 2, 4);
3773 hr = ITextRange_SetRange(txtRge, 2, 4);
3774 ok(hr == S_FALSE, "got 0x%08x.\n", hr);
3775 CHECK_RANGE(txtRge, 2, 4);
3777 hr = ITextRange_SetRange(txtRge, 4, 2);
3778 ok(hr == S_FALSE, "got 0x%08x.\n", hr);
3779 CHECK_RANGE(txtRge, 2, 4);
3781 hr = ITextRange_SetRange(txtRge, 14, 14);
3782 ok(hr == S_OK, "got 0x%08x.\n", hr);
3783 CHECK_RANGE(txtRge, 12, 12);
3785 hr = ITextRange_SetRange(txtRge, 15, 15);
3786 ok(hr == S_FALSE, "got 0x%08x.\n", hr);
3787 CHECK_RANGE(txtRge, 12, 12);
3789 hr = ITextRange_SetRange(txtRge, 14, 1);
3790 ok(hr == S_OK, "got 0x%08x.\n", hr);
3791 CHECK_RANGE(txtRge, 1, 13);
3793 hr = ITextRange_SetRange(txtRge, -1, 4);
3794 ok(hr == S_OK, "got 0x%08x.\n", hr);
3795 CHECK_RANGE(txtRge, 0, 4);
3797 ITextRange_Release(txtRge);
3798 release_interfaces(&w, &reOle, &txtDoc, NULL);
3801 static void test_Expand(void)
3803 static const char test_text1[] = "TestSomeText";
3804 IRichEditOle *reole = NULL;
3805 ITextDocument *doc = NULL;
3806 ITextSelection *selection;
3807 ITextRange *range;
3808 LONG value;
3809 HRESULT hr;
3810 HWND hwnd;
3812 create_interfaces(&hwnd, &reole, &doc, &selection);
3813 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3814 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3816 hr = ITextDocument_Range(doc, 0, 4, &range);
3817 ok(hr == S_OK, "got 0x%08x\n", hr);
3819 hr = ITextRange_Expand(range, tomStory, NULL);
3820 ok(hr == S_OK, "got 0x%08x\n", hr);
3821 CHECK_RANGE(range, 0, 13);
3823 hr = ITextSelection_Expand(selection, tomStory, NULL);
3824 ok(hr == S_OK, "got 0x%08x\n", hr);
3825 CHECK_SELECTION(selection, 0, 13);
3827 RESET_RANGE(range, 1, 2);
3828 RESET_SELECTION(selection, 1, 2);
3830 value = 0;
3831 hr = ITextRange_Expand(range, tomStory, &value);
3832 ok(hr == S_OK, "got 0x%08x\n", hr);
3833 ok(value == 12, "got %d\n", value);
3834 CHECK_RANGE(range, 0, 13);
3836 value = 0;
3837 hr = ITextSelection_Expand(selection, tomStory, &value);
3838 ok(hr == S_OK, "got 0x%08x\n", hr);
3839 ok(value == 12, "got %d\n", value);
3840 CHECK_SELECTION(selection, 0, 13);
3842 release_interfaces(&hwnd, &reole, &doc, NULL);
3844 hr = ITextRange_Expand(range, tomStory, NULL);
3845 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3847 hr = ITextRange_Expand(range, tomStory, &value);
3848 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3850 hr = ITextSelection_Expand(selection, tomStory, NULL);
3851 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3853 hr = ITextSelection_Expand(selection, tomStory, &value);
3854 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3856 ITextSelection_Release(selection);
3857 ITextRange_Release(range);
3860 static void test_MoveEnd_story(void)
3862 static const char test_text1[] = "Word1 Word2";
3863 IRichEditOle *reole = NULL;
3864 ITextDocument *doc = NULL;
3865 ITextSelection *selection;
3866 ITextRange *range;
3867 LONG delta;
3868 HRESULT hr;
3869 HWND hwnd;
3871 create_interfaces(&hwnd, &reole, &doc, &selection);
3872 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3873 SendMessageA(hwnd, EM_SETSEL, 1, 2);
3875 hr = ITextDocument_Range(doc, 1, 2, &range);
3876 ok(hr == S_OK, "got 0x%08x\n", hr);
3878 hr = ITextRange_MoveEnd(range, tomStory, 0, &delta);
3879 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3880 ok(delta == 0, "got %d\n", delta);
3881 CHECK_RANGE(range, 1, 2);
3883 hr = ITextRange_MoveEnd(range, tomStory, -1, &delta);
3884 ok(hr == S_OK, "got 0x%08x\n", hr);
3885 ok(delta == -1, "got %d\n", delta);
3886 CHECK_RANGE(range, 0, 0);
3888 hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
3889 ok(hr == S_OK, "got 0x%08x\n", hr);
3890 ok(delta == 1, "got %d\n", delta);
3891 CHECK_RANGE(range, 0, 12);
3893 hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
3894 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3895 ok(delta == 0, "got %d\n", delta);
3896 CHECK_RANGE(range, 0, 12);
3898 RESET_RANGE(range, 1, 2);
3900 hr = ITextRange_MoveEnd(range, tomStory, 3, &delta);
3901 ok(hr == S_OK, "got 0x%08x\n", hr);
3902 ok(delta == 1, "got %d\n", delta);
3903 CHECK_RANGE(range, 1, 12);
3905 RESET_RANGE(range, 2, 3);
3907 hr = ITextRange_MoveEnd(range, tomStory, -3, &delta);
3908 ok(hr == S_OK, "got 0x%08x\n", hr);
3909 ok(delta == -1, "got %d\n", delta);
3910 CHECK_RANGE(range, 0, 0);
3912 hr = ITextRange_MoveEnd(range, tomStory, -1, &delta);
3913 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3914 ok(delta == 0, "got %d\n", delta);
3915 CHECK_RANGE(range, 0, 0);
3917 hr = ITextSelection_MoveEnd(selection, tomStory, 0, &delta);
3918 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3919 ok(delta == 0, "got %d\n", delta);
3920 CHECK_SELECTION(selection, 1, 2);
3922 hr = ITextSelection_MoveEnd(selection, tomStory, -1, &delta);
3923 ok(hr == S_OK, "got 0x%08x\n", hr);
3924 ok(delta == -1, "got %d\n", delta);
3925 CHECK_SELECTION(selection, 0, 0);
3927 hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
3928 ok(hr == S_OK, "got 0x%08x\n", hr);
3929 ok(delta == 1, "got %d\n", delta);
3930 CHECK_SELECTION(selection, 0, 12);
3932 hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
3933 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3934 ok(delta == 0, "got %d\n", delta);
3935 CHECK_SELECTION(selection, 0, 12);
3937 RESET_SELECTION(selection, 1, 2);
3939 hr = ITextSelection_MoveEnd(selection, tomStory, 3, &delta);
3940 ok(hr == S_OK, "got 0x%08x\n", hr);
3941 ok(delta == 1, "got %d\n", delta);
3942 CHECK_SELECTION(selection, 1, 12);
3944 RESET_SELECTION(selection, 2, 3);
3946 hr = ITextSelection_MoveEnd(selection, tomStory, -3, &delta);
3947 ok(hr == S_OK, "got 0x%08x\n", hr);
3948 ok(delta == -1, "got %d\n", delta);
3949 CHECK_SELECTION(selection, 0, 0);
3951 hr = ITextSelection_MoveEnd(selection, tomStory, -1, &delta);
3952 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3953 ok(delta == 0, "got %d\n", delta);
3954 CHECK_SELECTION(selection, 0, 0);
3956 release_interfaces(&hwnd, &reole, &doc, NULL);
3958 hr = ITextRange_MoveEnd(range, tomStory, 1, NULL);
3959 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3961 hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
3962 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3964 hr = ITextSelection_MoveEnd(selection, tomStory, 1, NULL);
3965 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3967 hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
3968 ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3970 ITextSelection_Release(selection);
3971 ITextRange_Release(range);
3974 static void test_character_movestart(ITextRange *range, int textlen, int i, int j, LONG target)
3976 HRESULT hr;
3977 LONG delta = 0;
3978 LONG expected_delta;
3979 LONG expected_start = target;
3981 if (expected_start < 0)
3982 expected_start = 0;
3983 else if (expected_start > textlen)
3984 expected_start = textlen;
3985 expected_delta = expected_start - i;
3986 hr = ITextRange_SetRange(range, i, j);
3987 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
3988 hr = ITextRange_MoveStart(range, tomCharacter, target - i, &delta);
3989 if (expected_start == i) {
3990 ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - i, hr);
3991 ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, target - i, delta);
3992 CHECK_RANGE(range, i, j);
3993 } else {
3994 ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - i, hr);
3995 ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, target - i, delta);
3996 if (expected_start <= j)
3997 CHECK_RANGE(range, expected_start, j);
3998 else
3999 CHECK_RANGE(range, expected_start, expected_start);
4003 static void test_character_moveend(ITextRange *range, int textlen, int i, int j, LONG target)
4005 HRESULT hr;
4006 LONG delta;
4007 LONG expected_delta;
4008 LONG expected_end = target;
4010 if (expected_end < 0)
4011 expected_end = 0;
4012 else if (expected_end > textlen + 1)
4013 expected_end = textlen + 1;
4014 expected_delta = expected_end - j;
4015 hr = ITextRange_SetRange(range, i, j);
4016 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
4017 hr = ITextRange_MoveEnd(range, tomCharacter, target - j, &delta);
4018 if (expected_end == j) {
4019 ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - j, hr);
4020 ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, target - j, delta);
4021 CHECK_RANGE(range, i, j);
4022 } else {
4023 ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - j, hr);
4024 ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, target - j, delta);
4025 if (i <= expected_end)
4026 CHECK_RANGE(range, i, expected_end);
4027 else
4028 CHECK_RANGE(range, expected_end, expected_end);
4032 static void test_character_move(ITextRange *range, int textlen, int i, int j, LONG target)
4034 HRESULT hr;
4035 LONG move_by;
4036 LONG delta = 0;
4037 LONG expected_delta;
4038 LONG expected_location = target;
4040 if (expected_location < 0)
4041 expected_location = 0;
4042 else if (expected_location > textlen)
4043 expected_location = textlen;
4045 if (target <= i) {
4046 move_by = target - i;
4047 expected_delta = expected_location - i;
4048 if (i != j) {
4049 --move_by;
4050 --expected_delta;
4052 } else if (j <= target) {
4053 move_by = target - j;
4054 expected_delta = expected_location - j;
4055 if (i != j) {
4056 ++move_by;
4057 ++expected_delta;
4059 } else {
4060 /* There's no way to move to a point between start and end: */
4061 return;
4064 hr = ITextRange_SetRange(range, i, j);
4065 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
4066 hr = ITextRange_Move(range, tomCharacter, move_by, &delta);
4067 if (expected_delta == 0) {
4068 ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, move_by, hr);
4069 ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, move_by, delta);
4070 CHECK_RANGE(range, expected_location, expected_location);
4071 } else {
4072 ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, move_by, hr);
4073 ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, move_by, delta);
4074 CHECK_RANGE(range, expected_location, expected_location);
4078 static void test_character_startof(ITextRange *range, int textlen, int i, int j)
4080 HRESULT hr;
4081 LONG delta;
4083 hr = ITextRange_SetRange(range, i, j);
4084 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
4085 hr = ITextRange_StartOf(range, tomCharacter, tomMove, &delta);
4086 if (i == j) {
4087 ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
4088 ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta);
4089 } else {
4090 ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
4091 ok(delta == -1, "(%d,%d) tomMove got delta %d\n", i, j, delta);
4093 CHECK_RANGE(range, i, i);
4095 hr = ITextRange_SetRange(range, i, j);
4096 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
4097 hr = ITextRange_StartOf(range, tomCharacter, tomExtend, &delta);
4098 ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr);
4099 ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta);
4100 CHECK_RANGE(range, i, j);
4103 static void test_character_endof(ITextRange *range, int textlen, int i, int j)
4105 HRESULT hr;
4106 LONG end;
4107 LONG delta;
4109 hr = ITextRange_SetRange(range, i, j);
4110 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
4111 hr = ITextRange_EndOf(range, tomCharacter, tomMove, &delta);
4113 /* A character "end", apparently cannot be before the very first character */
4114 end = j;
4115 if (j == 0)
4116 ++end;
4118 if (i == end) {
4119 ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
4120 ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta);
4121 } else {
4122 ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
4123 ok(delta == 1, "(%d,%d) tomMove got delta %d\n", i, j, delta);
4125 CHECK_RANGE(range, end, end);
4127 hr = ITextRange_SetRange(range, i, j);
4128 ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
4129 hr = ITextRange_EndOf(range, tomCharacter, tomExtend, &delta);
4130 if (0 < j) {
4131 ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr);
4132 ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta);
4133 } else {
4134 ok(hr == S_OK, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr);
4135 ok(delta == 1, "(%d,%d) tomExtend got delta %d\n", i, j, delta);
4137 CHECK_RANGE(range, i, end);
4140 static void test_character_movement(void)
4142 static const char test_text1[] = "ab\n c";
4143 IRichEditOle *reole = NULL;
4144 ITextDocument *doc = NULL;
4145 ITextRange *range;
4146 ITextSelection *selection;
4147 HRESULT hr;
4148 HWND hwnd;
4149 int i, j;
4150 const int textlen = strlen(test_text1);
4152 create_interfaces(&hwnd, &reole, &doc, &selection);
4153 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
4155 hr = ITextDocument_Range(doc, 0, 0, &range);
4156 ok(hr == S_OK, "got 0x%08x\n", hr);
4158 /* Exhaustive test of every possible combination of (start,end) locations,
4159 * against every possible target location to move to. */
4160 for (i = 0; i <= textlen; i++) {
4161 for (j = i; j <= textlen; j++) {
4162 LONG target;
4163 for (target = -2; target <= textlen + 3; target++) {
4164 test_character_moveend(range, textlen, i, j, target);
4165 test_character_movestart(range, textlen, i, j, target);
4166 test_character_move(range, textlen, i, j, target);
4168 test_character_startof(range, textlen, i, j);
4169 test_character_endof(range, textlen, i, j);
4173 release_interfaces(&hwnd, &reole, &doc, NULL);
4174 ITextSelection_Release(selection);
4175 ITextRange_Release(range);
4178 #define CLIPBOARD_RANGE_CONTAINS(range, start, end, expected) _clipboard_range_contains(range, start, end, expected, __LINE__, 0);
4179 #define TODO_CLIPBOARD_RANGE_CONTAINS(range, start, end, expected) _clipboard_range_contains(range, start, end, expected, __LINE__, 1);
4180 static void _clipboard_range_contains(ITextRange *range, LONG start, LONG end, const char *expected, int line, int todo)
4182 HRESULT hr;
4183 BOOL clipboard_open;
4184 HGLOBAL global;
4185 const char *clipboard_text;
4187 hr = ITextRange_SetRange(range, start, end);
4188 ok_(__FILE__,line)(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr);
4189 hr = ITextRange_Copy(range, NULL);
4190 ok_(__FILE__,line)(hr == S_OK, "Copy failed: 0x%08x\n", hr);
4192 clipboard_open = OpenClipboard(NULL);
4193 ok_(__FILE__,line)(clipboard_open, "OpenClipboard failed: %d\n", GetLastError());
4194 global = GetClipboardData(CF_TEXT);
4195 ok_(__FILE__,line)(global != NULL, "GetClipboardData failed: %p\n", global);
4196 clipboard_text = GlobalLock(global);
4197 ok_(__FILE__,line)(clipboard_text != NULL, "GlobalLock failed: %p\n", clipboard_text);
4198 todo_wine_if(todo) ok_(__FILE__,line)(!strcmp(expected, clipboard_text), "unexpected contents: %s\n", wine_dbgstr_a(clipboard_text));
4199 GlobalUnlock(global);
4200 CloseClipboard();
4203 static void test_clipboard(void)
4205 static const char text_in[] = "ab\n c";
4206 IRichEditOle *reole = NULL;
4207 ITextDocument *doc = NULL;
4208 ITextRange *range;
4209 ITextSelection *selection;
4210 HRESULT hr;
4211 HWND hwnd;
4213 create_interfaces(&hwnd, &reole, &doc, &selection);
4214 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text_in);
4216 hr = ITextDocument_Range(doc, 0, 0, &range);
4217 ok(hr == S_OK, "got 0x%08x\n", hr);
4219 CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c")
4220 CLIPBOARD_RANGE_CONTAINS(range, 0, 0, "ab\r\n c")
4221 CLIPBOARD_RANGE_CONTAINS(range, 1, 1, "ab\r\n c")
4222 CLIPBOARD_RANGE_CONTAINS(range, 0, 1, "a")
4223 CLIPBOARD_RANGE_CONTAINS(range, 5, 6, "")
4225 /* Setting password char does not stop Copy */
4226 SendMessageA(hwnd, EM_SETPASSWORDCHAR, '*', 0);
4227 CLIPBOARD_RANGE_CONTAINS(range, 0, 1, "a")
4229 /* Cut can be undone */
4230 hr = ITextRange_SetRange(range, 0, 1);
4231 ok(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr);
4232 hr = ITextRange_Cut(range, NULL);
4233 ok(hr == S_OK, "Cut failed: 0x%08x\n", hr);
4234 CLIPBOARD_RANGE_CONTAINS(range, 0, 4, "b\r\n c");
4235 hr = ITextDocument_Undo(doc, 1, NULL);
4236 todo_wine ok(hr == S_OK, "Undo failed: 0x%08x\n", hr);
4237 TODO_CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c");
4239 /* Cannot cut when read-only */
4240 SendMessageA(hwnd, EM_SETREADONLY, TRUE, 0);
4241 hr = ITextRange_SetRange(range, 0, 1);
4242 ok(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr);
4243 hr = ITextRange_Cut(range, NULL);
4244 ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr);
4246 release_interfaces(&hwnd, &reole, &doc, NULL);
4247 ITextSelection_Release(selection);
4248 ITextRange_Release(range);
4251 START_TEST(richole)
4253 /* Must explicitly LoadLibrary(). The test has no references to functions in
4254 * RICHED20.DLL, so the linker doesn't actually link to it. */
4255 hmoduleRichEdit = LoadLibraryA("riched20.dll");
4256 ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
4258 test_Interfaces();
4259 test_ITextDocument_Open();
4260 test_GetText();
4261 test_ITextSelection_GetChar();
4262 test_ITextSelection_GetStart_GetEnd();
4263 test_ITextSelection_Collapse();
4264 test_ITextDocument_Range();
4265 test_ITextRange_GetChar();
4266 test_ITextRange_ScrollIntoView();
4267 test_ITextRange_GetStart_GetEnd();
4268 test_ITextRange_SetRange();
4269 test_ITextRange_GetDuplicate();
4270 test_ITextRange_Collapse();
4271 test_GetClientSite();
4272 test_IOleWindow_GetWindow();
4273 test_IOleInPlaceSite_GetWindow();
4274 test_GetFont();
4275 test_GetPara();
4276 test_dispatch();
4277 test_ITextFont();
4278 test_Delete();
4279 test_SetText();
4280 test_InRange();
4281 test_ITextRange_IsEqual();
4282 test_Select();
4283 test_GetStoryType();
4284 test_SetFont();
4285 test_InsertObject();
4286 test_GetStoryLength();
4287 test_ITextSelection_GetDuplicate();
4288 test_Expand();
4289 test_MoveEnd_story();
4290 test_character_movement();
4291 test_clipboard();