ReactOS  0.4.15-dev-2774-gc8ce0cc
richole.c
Go to the documentation of this file.
1 /*
2  * Tests for IRichEditOle and friends.
3  *
4  * Copyright 2008 Google (Dan Hipschman)
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #define COBJMACROS
22 
23 #include <stdarg.h>
24 
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>
35 
37 
38 DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
39 
40 static const WCHAR sysW[] = {'S','y','s','t','e','m',0};
41 
42 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
43 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
44 {
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);
49 }
50 
51 static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent)
52 {
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;
58 }
59 
61 {
63 }
64 
66 {
67  HANDLE file;
68 
71 
73  return FALSE;
75  return TRUE;
76 }
77 
79 {
80  HANDLE file;
81 
83  OPEN_EXISTING, 0, NULL);
85  return FALSE;
87  return TRUE;
88 }
89 
90 static void create_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc,
91  ITextSelection **txtSel)
92 {
93  *w = new_richedit(NULL);
95  IRichEditOle_QueryInterface(*reOle, &IID_ITextDocument,
96  (void **) txtDoc);
97  ITextDocument_GetSelection(*txtDoc, txtSel);
98 }
99 
100 static void release_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc,
101  ITextSelection **txtSel)
102 {
103  if(txtSel)
104  ITextSelection_Release(*txtSel);
105  ITextDocument_Release(*txtDoc);
106  IRichEditOle_Release(*reOle);
107  DestroyWindow(*w);
108 }
109 
111 {
112  IUnknown_AddRef(iface);
113  return IUnknown_Release(iface);
114 }
115 
116 #if 0 /*avoid CORE-16799*/
117 #define CHECK_TYPEINFO(disp,expected_riid) _check_typeinfo((IDispatch *)disp, expected_riid, __LINE__)
118 static void _check_typeinfo(IDispatch* disp, REFIID expected_riid, int line)
119 {
121  TYPEATTR *typeattr;
122  UINT count;
123  HRESULT hr;
124 
125  count = 10;
126  hr = IDispatch_GetTypeInfoCount(disp, &count);
127  ok_(__FILE__,line)(hr == S_OK, "IDispatch_GetTypeInfoCount failed: 0x%08x.\n", hr);
128  ok_(__FILE__,line)(count == 1, "got wrong count: %u.\n", count);
129 
130  hr = IDispatch_GetTypeInfo(disp, 0, LOCALE_SYSTEM_DEFAULT, &typeinfo);
131  ok_(__FILE__,line)(hr == S_OK, "IDispatch_GetTypeInfo failed: 0x%08x.\n", hr);
132 
133  hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
134  ok_(__FILE__,line)(hr == S_OK, "ITypeInfo_GetTypeAttr failed: 0x%08x.\n", hr);
135  ok_(__FILE__,line)(IsEqualGUID(&typeattr->guid, expected_riid),
136  "Unexpected type guid: %s.\n", wine_dbgstr_guid(&typeattr->guid));
137 
138  ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
139  ITypeInfo_Release(typeinfo);
140 }
141 #endif
142 
143 static void test_Interfaces(void)
144 {
145  IRichEditOle *reOle = NULL, *reOle1 = NULL;
146  ITextDocument *txtDoc = NULL;
147 #if 0 /*avoid CORE-16799*/
148  ITextDocument2Old *txtDoc2Old = NULL;
149 #endif
150  ITextSelection *txtSel = NULL, *txtSel2;
151  IUnknown *punk;
152  HRESULT hres;
153  LRESULT res;
154  HWND w;
155  ULONG refcount;
156 
157  w = new_richedit(NULL);
158  if (!w) {
159  skip("Couldn't create window\n");
160  return;
161  }
162 
163  res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle);
164  ok(res, "SendMessage\n");
165  ok(reOle != NULL, "EM_GETOLEINTERFACE\n");
166  EXPECT_REF(reOle, 2);
167 
168  res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle1);
169  ok(res == 1, "SendMessage\n");
170  ok(reOle1 == reOle, "Should not return a new IRichEditOle interface\n");
171  EXPECT_REF(reOle, 3);
172 
173  hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument,
174  (void **) &txtDoc);
175  ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
176  ok(txtDoc != NULL, "IRichEditOle_QueryInterface\n");
177 #if 0 /*avoid CORE-16799*/
178  CHECK_TYPEINFO(txtDoc, &IID_ITextDocument);
179 #endif
180 
181  hres = ITextDocument_GetSelection(txtDoc, NULL);
182  ok(hres == E_INVALIDARG, "ITextDocument_GetSelection: 0x%x\n", hres);
183 
184  EXPECT_REF(txtDoc, 4);
185 
186  hres = ITextDocument_GetSelection(txtDoc, &txtSel);
187  ok(hres == S_OK, "got 0x%08x\n", hres);
188 
189  EXPECT_REF(txtDoc, 4);
190  EXPECT_REF(txtSel, 2);
191 
192  hres = ITextDocument_GetSelection(txtDoc, &txtSel2);
193  ok(hres == S_OK, "got 0x%08x\n", hres);
194  ok(txtSel2 == txtSel, "got %p, %p\n", txtSel, txtSel2);
195 
196  EXPECT_REF(txtDoc, 4);
197  EXPECT_REF(txtSel, 3);
198 
199  ITextSelection_Release(txtSel2);
200 
201  punk = NULL;
202  hres = ITextSelection_QueryInterface(txtSel, &IID_ITextSelection, (void **) &punk);
203  ok(hres == S_OK, "ITextSelection_QueryInterface\n");
204  ok(punk != NULL, "ITextSelection_QueryInterface\n");
205  IUnknown_Release(punk);
206 
207  punk = NULL;
208  hres = ITextSelection_QueryInterface(txtSel, &IID_ITextRange, (void **) &punk);
209  ok(hres == S_OK, "ITextSelection_QueryInterface\n");
210  ok(punk != NULL, "ITextSelection_QueryInterface\n");
211  IUnknown_Release(punk);
212 
213  punk = NULL;
214  hres = ITextSelection_QueryInterface(txtSel, &IID_IDispatch, (void **) &punk);
215  ok(hres == S_OK, "ITextSelection_QueryInterface\n");
216  ok(punk != NULL, "ITextSelection_QueryInterface\n");
217  IUnknown_Release(punk);
218 
219  punk = NULL;
220  hres = IRichEditOle_QueryInterface(reOle, &IID_IOleClientSite, (void **) &punk);
221  ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
222 
223  punk = NULL;
224  hres = IRichEditOle_QueryInterface(reOle, &IID_IOleWindow, (void **) &punk);
225  ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
226 
227  punk = NULL;
228  hres = IRichEditOle_QueryInterface(reOle, &IID_IOleInPlaceSite, (void **) &punk);
229  ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
230 
231 #if 0 /*avoid CORE-16799*/
232  hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument2Old, (void **)&txtDoc2Old);
233  ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
234  ok(txtDoc2Old != NULL, "IRichEditOle_QueryInterface\n");
235  ok((ITextDocument *)txtDoc2Old == txtDoc, "interface pointer isn't equal.\n");
236  EXPECT_REF(txtDoc2Old, 5);
237  EXPECT_REF(reOle, 5);
238  CHECK_TYPEINFO(txtDoc2Old, &IID_ITextDocument);
239 
240  ITextDocument2Old_Release(txtDoc2Old);
241 #endif
242 
243  ITextDocument_Release(txtDoc);
244  IRichEditOle_Release(reOle);
245  refcount = IRichEditOle_Release(reOle);
246  ok(refcount == 1, "got wrong ref count: %d\n", refcount);
247  DestroyWindow(w);
248 
249  /* Methods should return CO_E_RELEASED if the backing document has
250  been released. One test should suffice. */
251  hres = ITextSelection_CanEdit(txtSel, NULL);
252  ok(hres == CO_E_RELEASED, "ITextSelection after ITextDocument destroyed\n");
253 
254  ITextSelection_Release(txtSel);
255 
256 #if 0 /*avoid CORE-16799*/
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");
261 
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);
269 #endif
270 }
271 
272 static void test_ITextDocument_Open(void)
273 {
274  IRichEditOle *reOle = NULL;
275  ITextDocument *txtDoc = NULL;
276  ITextSelection *txtSel = NULL;
277  HRESULT hres;
278  HWND w;
279  HANDLE hFile;
280  VARIANT testfile;
281  WCHAR filename[] = {'t', 'e', 's', 't','.','t','x','t', 0};
282  int result;
283  DWORD dw;
284  static const CHAR chACP[] = "TestSomeText";
285  static const CHAR chUTF8[] = "\xef\xbb\xbfTextWithUTF8BOM";
286  static const WCHAR chUTF16[] = {0xfeff, 'T', 'e', 's', 't', 'S', 'o', 'm',
287  'e', 'T', 'e', 'x', 't', 0};
288 
289 #define MAX_BUF_LEN 1024
290  CHAR bufACP[MAX_BUF_LEN];
291  WCHAR bufUnicode[MAX_BUF_LEN];
292 
293  static const int tomConstantsSingle[] =
294  {
298  };
299 
300  static const int tomConstantsMulti[] =
301  {
308  };
309 
310  int tomNumSingle = ARRAY_SIZE(tomConstantsSingle);
311  int tomNumMulti = ARRAY_SIZE(tomConstantsMulti);
312  int i;
313 
314  V_VT(&testfile) = VT_BSTR;
315  V_BSTR(&testfile) = SysAllocString(filename);
316 
317  for(i=0; i < tomNumSingle; i++)
318  {
320  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
321  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_ACP);
322  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
323  tomConstantsSingle[i], hres);
324  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
326 
328  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
329  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_UTF8);
330  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
331  tomConstantsSingle[i], hres);
332  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
334  }
335 
336  for(i=0; i < tomNumMulti; i++)
337  {
339  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
340  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_ACP);
341  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
342  tomConstantsMulti[i], hres);
343  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
345 
347  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
348  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_UTF8);
349  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
350  tomConstantsMulti[i], hres);
351  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
353  }
354 
355  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
356  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_ACP);
357  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
358  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
359  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
361 
362  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
363  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_UTF8);
364  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
365  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
366  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
368 
369  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
370  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_ACP);
371  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
372  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
373  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
375 
376  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
377  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_UTF8);
378  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
379  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
380  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
382 
383  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
384  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
385  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
386  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
387  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
389 
390  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
391  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
392  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
393  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
394  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
396 
397  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
399  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
400  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_ACP\n");
401  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
403 
404  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
406  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
407  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
408  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
410 
411  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
412  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_ACP);
413  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_ACP\n");
414  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
415 
416  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
417  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_UTF8);
418  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
419  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
420 
421  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
423  hres = ITextDocument_Open(txtDoc, &testfile, tomText, CP_ACP);
424 todo_wine {
425  ok(hres == S_OK, "got 0x%08x\n", hres);
426  ok(is_existing_file(filename) == TRUE, "a file should be created default\n");
427 }
428  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
430 
431  /* test of share mode */
433  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
434  hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyRead, CP_ACP);
435 todo_wine
436  ok(hres == S_OK, "got 0x%08x\n", hres);
437  SetLastError(0xdeadbeef);
440  todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
442  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
444 
446  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
447  hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite, CP_ACP);
448 todo_wine
449  ok(hres == S_OK, "got 0x%08x\n", hres);
450  SetLastError(0xdeadbeef);
453  todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
455  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
457 
459  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
460  SetLastError(0xdeadbeef);
461  hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite|tomShareDenyRead, CP_ACP);
462 todo_wine
463  ok(hres == S_OK, "got 0x%08x\n", hres);
466  todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
468  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
470 
471  /* tests to check the content */
474  WriteFile(hFile, chACP, sizeof(chACP)-sizeof(CHAR), &dw, NULL);
476  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
477  hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_ACP);
478 todo_wine
479  ok(hres == S_OK, "got 0x%08x\n", hres);
480  result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
481  todo_wine ok(result == 12, "ITextDocument_Open: Test ASCII returned %d, expected 12\n", result);
482  result = strcmp(bufACP, chACP);
483  todo_wine ok(result == 0, "ITextDocument_Open: Test ASCII set wrong text: Result: %s\n", bufACP);
484  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
486 
489  WriteFile(hFile, chUTF8, sizeof(chUTF8)-sizeof(CHAR), &dw, NULL);
491  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
492  hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_UTF8);
493 todo_wine
494  ok(hres == S_OK, "got 0x%08x\n", hres);
495  result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
496  todo_wine ok(result == 15, "ITextDocument_Open: Test UTF-8 returned %d, expected 15\n", result);
497  result = strcmp(bufACP, &chUTF8[3]);
498  todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-8 set wrong text: Result: %s\n", bufACP);
499  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
501 
504  WriteFile(hFile, chUTF16, sizeof(chUTF16)-sizeof(WCHAR), &dw, NULL);
506  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
507  hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, 1200);
508 todo_wine
509  ok(hres == S_OK, "got 0x%08x\n", hres);
510  result = SendMessageW(w, WM_GETTEXT, 1024, (LPARAM)bufUnicode);
511  todo_wine ok(result == 12, "ITextDocument_Open: Test UTF-16 returned %d, expected 12\n", result);
512  result = lstrcmpW(bufUnicode, &chUTF16[1]);
513  todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-16 set wrong text: Result: %s\n", wine_dbgstr_w(bufUnicode));
514  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
516 
517  VariantClear(&testfile);
518 }
519 
520 static void test_GetText(void)
521 {
522  HWND w;
523  IRichEditOle *reOle = NULL;
524  ITextDocument *txtDoc = NULL;
525  ITextSelection *txtSel = NULL;
526  HRESULT hres;
527  BSTR bstr = NULL;
528  int first, lim;
529  static const CHAR test_text1[] = "TestSomeText";
530  static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0};
531  static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0};
532  static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0};
533  static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm',
534  'e', 'T', 'e', 'x', 't', '\r', 0};
535  static const WCHAR bufW5[] = {'\r', 0};
536  static const WCHAR bufW6[] = {'T','e','s','t','S','o','m','e','T',0};
537  BOOL is64bit = sizeof(void *) > sizeof(int);
538  ITextRange *range;
539 
540  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
541  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
542 
543  /* ITextSelection */
544  first = 0; lim = 4;
545  SendMessageA(w, EM_SETSEL, first, lim);
546  hres = ITextSelection_GetText(txtSel, &bstr);
547  ok(hres == S_OK, "ITextSelection_GetText\n");
548  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
549  SysFreeString(bstr);
550 
551  first = 4; lim = 0;
552  SendMessageA(w, EM_SETSEL, first, lim);
553  hres = ITextSelection_GetText(txtSel, &bstr);
554  ok(hres == S_OK, "ITextSelection_GetText\n");
555  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
556  SysFreeString(bstr);
557 
558  first = 1; lim = 1;
559  SendMessageA(w, EM_SETSEL, first, lim);
560  hres = ITextSelection_GetText(txtSel, &bstr);
561  ok(hres == S_OK, "ITextSelection_GetText\n");
562  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
563 
564  if (!is64bit)
565  {
566  hres = ITextSelection_GetText(txtSel, NULL);
567  ok(hres == E_INVALIDARG, "ITextSelection_GetText\n");
568  }
569 
570  first = 8; lim = 12;
571  SendMessageA(w, EM_SETSEL, first, lim);
572  hres = ITextSelection_GetText(txtSel, &bstr);
573  ok(hres == S_OK, "ITextSelection_GetText\n");
574  ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
575  SysFreeString(bstr);
576 
577  first = 8; lim = 13;
578  SendMessageA(w, EM_SETSEL, first, lim);
579  hres = ITextSelection_GetText(txtSel, &bstr);
580  ok(hres == S_OK, "ITextSelection_GetText\n");
581  ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
582  SysFreeString(bstr);
583 
584  first = 12; lim = 13;
585  SendMessageA(w, EM_SETSEL, first, lim);
586  hres = ITextSelection_GetText(txtSel, &bstr);
587  ok(hres == S_OK, "ITextSelection_GetText\n");
588  ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
589  SysFreeString(bstr);
590 
591  first = 0; lim = -1;
592  SendMessageA(w, EM_SETSEL, first, lim);
593  hres = ITextSelection_GetText(txtSel, &bstr);
594  ok(hres == S_OK, "ITextSelection_GetText\n");
595  ok(!lstrcmpW(bstr, bufW4), "got wrong text: %s\n", wine_dbgstr_w(bstr));
596  SysFreeString(bstr);
597 
598  first = -1; lim = 9;
599  SendMessageA(w, EM_SETSEL, first, lim);
600  hres = ITextSelection_GetText(txtSel, &bstr);
601  ok(hres == S_OK, "ITextSelection_GetText\n");
602  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
603 
604  /* ITextRange */
605  hres = ITextDocument_Range(txtDoc, 0, 4, &range);
606  ok(hres == S_OK, "got 0x%08x\n", hres);
607  hres = ITextRange_GetText(range, &bstr);
608  ok(hres == S_OK, "got 0x%08x\n", hres);
609  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
610 
611  SysFreeString(bstr);
612  ITextRange_Release(range);
613 
614  hres = ITextDocument_Range(txtDoc, 4, 0, &range);
615  ok(hres == S_OK, "got 0x%08x\n", hres);
616  hres = ITextRange_GetText(range, &bstr);
617  ok(hres == S_OK, "got 0x%08x\n", hres);
618  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
619 
620  SysFreeString(bstr);
621  ITextRange_Release(range);
622 
623  hres = ITextDocument_Range(txtDoc, 1, 1, &range);
624  ok(hres == S_OK, "got 0x%08x\n", hres);
625  hres = ITextRange_GetText(range, &bstr);
626  ok(hres == S_OK, "got 0x%08x\n", hres);
627  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
628  if (!is64bit)
629  {
630  hres = ITextRange_GetText(range, NULL);
631  ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
632  }
633  ITextRange_Release(range);
634 
635  hres = ITextDocument_Range(txtDoc, 8, 12, &range);
636  ok(hres == S_OK, "got 0x%08x\n", hres);
637  hres = ITextRange_GetText(range, &bstr);
638  ok(hres == S_OK, "got 0x%08x\n", hres);
639  ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
640 
641  SysFreeString(bstr);
642  ITextRange_Release(range);
643 
644  hres = ITextDocument_Range(txtDoc, 8, 13, &range);
645  ok(hres == S_OK, "got 0x%08x\n", hres);
646  hres = ITextRange_GetText(range, &bstr);
647  ok(hres == S_OK, "got 0x%08x\n", hres);
648  ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
649 
650  SysFreeString(bstr);
651  ITextRange_Release(range);
652 
653  hres = ITextDocument_Range(txtDoc, 12, 13, &range);
654  ok(hres == S_OK, "got 0x%08x\n", hres);
655  hres = ITextRange_GetText(range, &bstr);
656  ok(hres == S_OK, "got 0x%08x\n", hres);
657  ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
658 
659  SysFreeString(bstr);
660  ITextRange_Release(range);
661 
662  hres = ITextDocument_Range(txtDoc, 0, -1, &range);
663  ok(hres == S_OK, "got 0x%08x\n", hres);
664  hres = ITextRange_GetText(range, &bstr);
665  ok(hres == S_OK, "got 0x%08x\n", hres);
666  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
667  ITextRange_Release(range);
668 
669  hres = ITextDocument_Range(txtDoc, -1, 9, &range);
670  ok(hres == S_OK, "got 0x%08x\n", hres);
671  hres = ITextRange_GetText(range, &bstr);
672  ok(hres == S_OK, "got 0x%08x\n", hres);
673  ok(!lstrcmpW(bstr, bufW6), "got wrong text: %s\n", wine_dbgstr_w(bstr));
674 
675  SysFreeString(bstr);
676 
677  release_interfaces(&w, &reOle, &txtDoc, NULL);
678 
679  /* detached selection/range */
680  if (is64bit) {
681  bstr = (void*)0xdeadbeef;
682  hres = ITextSelection_GetText(txtSel, &bstr);
683  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
684 todo_wine
685  ok(bstr == NULL, "got %p\n", bstr);
686 
687  bstr = (void*)0xdeadbeef;
688  hres = ITextRange_GetText(range, &bstr);
689  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
690 todo_wine
691  ok(bstr == NULL, "got %p\n", bstr);
692  }
693  else {
694  hres = ITextSelection_GetText(txtSel, NULL);
695  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
696 
697  hres = ITextRange_GetText(range, NULL);
698  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
699  }
700 
701  ITextRange_Release(range);
702  ITextSelection_Release(txtSel);
703 }
704 
705 static void test_ITextDocument_Range(void)
706 {
707  static const CHAR test_text1[] = "TestSomeText";
708  HWND w;
709  IRichEditOle *reOle = NULL;
710  ITextDocument *txtDoc = NULL;
711  ITextRange *txtRge, *range2;
712  HRESULT hres;
713  LONG value;
714 
715  create_interfaces(&w, &reOle, &txtDoc, NULL);
716  hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
717  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
718  EXPECT_REF(txtRge, 1);
719 
720  hres = ITextDocument_Range(txtDoc, 0, 0, &range2);
721  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
722  ok(range2 != txtRge, "A new pointer should be returned\n");
723  ITextRange_Release(range2);
724 
725  hres = ITextDocument_Range(txtDoc, 0, 0, NULL);
726  ok(hres == E_INVALIDARG, "ITextDocument_Range should fail 0x%x.\n", hres);
727 
728  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
729 
730  hres = ITextDocument_Range(txtDoc, 8, 30, &range2);
731  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
732  hres = ITextRange_GetStart(range2, &value);
733  ok(hres == S_OK, "got 0x%08x\n", hres);
734  ok(value == 8, "got %d\n", value);
735 
736  hres = ITextRange_GetEnd(range2, &value);
737  ok(hres == S_OK, "got 0x%08x\n", hres);
738  ok(value == 13, "got %d\n", value);
739  ITextRange_Release(range2);
740 
741  release_interfaces(&w, &reOle, &txtDoc, NULL);
742  hres = ITextRange_CanEdit(txtRge, NULL);
743  ok(hres == CO_E_RELEASED, "ITextRange after ITextDocument destroyed\n");
744  ITextRange_Release(txtRge);
745 }
746 
747 static void test_ITextRange_GetChar(void)
748 {
749  HWND w;
750  IRichEditOle *reOle = NULL;
751  ITextDocument *txtDoc = NULL;
752  ITextRange *txtRge = NULL;
753  HRESULT hres;
754  LONG pch;
755  int first, lim;
756  static const CHAR test_text1[] = "TestSomeText";
757 
758  first = 0, lim = 4;
759  create_interfaces(&w, &reOle, &txtDoc, NULL);
760  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
761  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
762  ok(hres == S_OK, "got 0x%08x\n", hres);
763  pch = 0xdeadbeef;
764  hres = ITextRange_GetChar(txtRge, &pch);
765  ok(hres == S_OK, "ITextRange_GetChar\n");
766  ok(pch == 'T', "got wrong char: %c\n", pch);
767  ITextRange_Release(txtRge);
768  release_interfaces(&w, &reOle, &txtDoc, NULL);
769 
770  first = 0; lim = 0;
771  create_interfaces(&w, &reOle, &txtDoc, NULL);
772  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
773  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
774  ok(hres == S_OK, "got 0x%08x\n", hres);
775  pch = 0xdeadbeef;
776  hres = ITextRange_GetChar(txtRge, &pch);
777  ok(hres == S_OK, "ITextRange_GetChar\n");
778  ok(pch == 'T', "got wrong char: %c\n", pch);
779  ITextRange_Release(txtRge);
780  release_interfaces(&w, &reOle, &txtDoc, NULL);
781 
782  first = 12; lim = 12;
783  create_interfaces(&w, &reOle, &txtDoc, NULL);
784  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
785  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
786  ok(hres == S_OK, "got 0x%08x\n", hres);
787  pch = 0xdeadbeef;
788  hres = ITextRange_GetChar(txtRge, &pch);
789  ok(hres == S_OK, "ITextRange_GetChar\n");
790  ok(pch == '\r', "got wrong char: %c\n", pch);
791  ITextRange_Release(txtRge);
792  release_interfaces(&w, &reOle, &txtDoc, NULL);
793 
794  first = 13; lim = 13;
795  create_interfaces(&w, &reOle, &txtDoc, NULL);
796  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
797  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
798  ok(hres == S_OK, "got 0x%08x\n", hres);
799  pch = 0xdeadbeef;
800  hres = ITextRange_GetChar(txtRge, &pch);
801  ok(hres == S_OK, "ITextRange_GetChar\n");
802  ok(pch == '\r', "got wrong char: %c\n", pch);
803  ITextRange_Release(txtRge);
804  release_interfaces(&w, &reOle, &txtDoc, NULL);
805 
806  create_interfaces(&w, &reOle, &txtDoc, NULL);
807  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
808  first = 12; lim = 12;
809  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
810  ok(hres == S_OK, "got 0x%08x\n", hres);
811  hres = ITextRange_GetChar(txtRge, NULL);
812  ok(hres == E_INVALIDARG, "ITextRange_GetChar\n");
813 
814  release_interfaces(&w, &reOle, &txtDoc, NULL);
815 
816  hres = ITextRange_GetChar(txtRge, NULL);
817  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
818 
819  hres = ITextRange_GetChar(txtRge, &pch);
820  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
821 
822  ITextRange_Release(txtRge);
823 }
824 
825 /* Helper function for testing ITextRange_ScrollIntoView */
826 static void check_range(HWND w, ITextDocument* doc, int first, int lim,
827  LONG bStart, int expected_nonzero)
828 {
829  SCROLLINFO si;
830  ITextRange *txtRge = NULL;
831  HRESULT hres;
832 
833  si.cbSize = sizeof(SCROLLINFO);
834  si.fMask = SIF_POS | SIF_RANGE;
835 
836  hres = ITextDocument_Range(doc, first, lim, &txtRge);
837  ok(hres == S_OK, "got 0x%08x\n", hres);
838  hres = ITextRange_ScrollIntoView(txtRge, bStart);
839  ok(hres == S_OK, "got 0x%08x\n", hres);
840  GetScrollInfo(w, SB_VERT, &si);
841  if (expected_nonzero) {
842  ok(si.nPos != 0,
843  "Scrollbar at 0, should be >0. (TextRange %d-%d, scroll range %d-%d.)\n",
844  first, lim, si.nMin, si.nMax);
845  } else {
846  ok(si.nPos == 0,
847  "Scrollbar at %d, should be 0. (TextRange %d-%d, scroll range %d-%d.)\n",
848  si.nPos, first, lim, si.nMin, si.nMax);
849  }
850 }
851 
853 {
854  HWND w;
855  IRichEditOle *reOle = NULL;
856  ITextDocument *txtDoc = NULL;
857  ITextRange *txtRge = NULL;
858  HRESULT hres;
859  static const CHAR test_text1[] = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10";
860 
861  create_interfaces(&w, &reOle, &txtDoc, NULL);
862  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
863 
864  /* Scroll to the top. */
865  check_range(w, txtDoc, 0, 1, tomStart, 0);
866  check_range(w, txtDoc, 0, 1, tomEnd, 0);
867 
868  /* Scroll to the bottom. */
869  check_range(w, txtDoc, 19, 20, tomStart, 1);
870  check_range(w, txtDoc, 19, 20, tomEnd, 1);
871 
872  /* Back up to the top. */
873  check_range(w, txtDoc, 0, 1, tomStart, 0);
874  check_range(w, txtDoc, 0, 1, tomEnd, 0);
875 
876  /* Large range */
877  check_range(w, txtDoc, 0, 20, tomStart, 0);
878  check_range(w, txtDoc, 0, 20, tomEnd, 1);
879 
880  hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
881  ok(hres == S_OK, "got 0x%08x\n", hres);
882  release_interfaces(&w, &reOle, &txtDoc, NULL);
883  hres = ITextRange_ScrollIntoView(txtRge, tomStart);
884  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
885  ITextRange_Release(txtRge);
886 }
887 
889 {
890  HWND w;
891  IRichEditOle *reOle = NULL;
892  ITextDocument *txtDoc = NULL;
893  ITextSelection *txtSel = NULL;
894  HRESULT hres;
895  LONG pch;
896  int first, lim;
897  static const CHAR test_text1[] = "TestSomeText";
898 
899  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
900  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
901 
902  first = 0; lim = 4;
903  SendMessageA(w, EM_SETSEL, first, lim);
904  pch = 0xdeadbeef;
905  hres = ITextSelection_GetChar(txtSel, &pch);
906  ok(hres == S_OK, "ITextSelection_GetChar\n");
907  ok(pch == 'T', "got wrong char: %c\n", pch);
908 
909  first = 0; lim = 0;
910  SendMessageA(w, EM_SETSEL, first, lim);
911  pch = 0xdeadbeef;
912  hres = ITextSelection_GetChar(txtSel, &pch);
913  ok(hres == S_OK, "ITextSelection_GetChar\n");
914  ok(pch == 'T', "got wrong char: %c\n", pch);
915 
916  first = 12; lim = 12;
917  SendMessageA(w, EM_SETSEL, first, lim);
918  pch = 0xdeadbeef;
919  hres = ITextSelection_GetChar(txtSel, &pch);
920  ok(hres == S_OK, "ITextSelection_GetChar\n");
921  ok(pch == '\r', "got wrong char: %c\n", pch);
922 
923  first = 13; lim = 13;
924  SendMessageA(w, EM_SETSEL, first, lim);
925  pch = 0xdeadbeef;
926  hres = ITextSelection_GetChar(txtSel, &pch);
927  ok(hres == S_OK, "ITextSelection_GetChar\n");
928  ok(pch == '\r', "got wrong char: %c\n", pch);
929 
930  hres = ITextSelection_GetChar(txtSel, NULL);
931  ok(hres == E_INVALIDARG, "ITextSelection_GetChar\n");
932 
933  release_interfaces(&w, &reOle, &txtDoc, NULL);
934 
935  hres = ITextSelection_GetChar(txtSel, NULL);
936  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
937 
938  hres = ITextSelection_GetChar(txtSel, &pch);
939  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
940 
941  ITextSelection_Release(txtSel);
942 }
943 
945 {
946  HWND w;
947  IRichEditOle *reOle = NULL;
948  ITextDocument *txtDoc = NULL;
949  ITextRange *txtRge = NULL;
950  HRESULT hres;
951  int first, lim, start, end;
952  static const CHAR test_text1[] = "TestSomeText";
953 
954  create_interfaces(&w, &reOle, &txtDoc, NULL);
955  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
956 
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);
969 
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);
982 
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);
995 
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);
1007 
1008  /* SetStart */
1009  hres = ITextRange_SetStart(txtRge, 0);
1010  ok(hres == S_OK, "got 0x%08x\n", hres);
1011 
1012  /* same value */
1013  hres = ITextRange_SetStart(txtRge, 0);
1014  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1015 
1016  hres = ITextRange_SetStart(txtRge, 1);
1017  ok(hres == S_OK, "got 0x%08x\n", hres);
1018 
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);
1023 
1024  hres = ITextRange_SetStart(txtRge, -1);
1025  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1026 
1027  hres = ITextRange_SetStart(txtRge, 0);
1028  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1029 
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);
1034 
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);
1038 
1039  hres = ITextRange_SetEnd(txtRge, 3);
1040  ok(hres == S_OK, "got 0x%08x\n", hres);
1041 
1042  hres = ITextRange_SetStart(txtRge, 10);
1043  ok(hres == S_OK, "got 0x%08x\n", hres);
1044 
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);
1049 
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);
1054 
1055  /* more that total text length */
1056  hres = ITextRange_SetStart(txtRge, 50);
1057  ok(hres == S_OK, "got 0x%08x\n", hres);
1058 
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);
1063 
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);
1068 
1069  /* SetEnd */
1070  hres = ITextRange_SetStart(txtRge, 0);
1071  ok(hres == S_OK, "got 0x%08x\n", hres);
1072 
1073  /* same value */
1074  hres = ITextRange_SetEnd(txtRge, 5);
1075  ok(hres == S_OK, "got 0x%08x\n", hres);
1076 
1077  hres = ITextRange_SetEnd(txtRge, 5);
1078  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1079 
1080  /* negative resets to 0 */
1081  hres = ITextRange_SetEnd(txtRge, -1);
1082  ok(hres == S_OK, "got 0x%08x\n", hres);
1083 
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);
1088 
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);
1093 
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);
1097 
1098  hres = ITextRange_SetEnd(txtRge, 1);
1099  ok(hres == S_OK, "got 0x%08x\n", hres);
1100 
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);
1105 
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);
1110 
1111  /* more than total count */
1112  hres = ITextRange_SetEnd(txtRge, 50);
1113  ok(hres == S_OK, "got 0x%08x\n", hres);
1114 
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);
1119 
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);
1124 
1125  /* zero */
1126  hres = ITextRange_SetEnd(txtRge, 0);
1127  ok(hres == S_OK, "got 0x%08x\n", hres);
1128 
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);
1133 
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);
1138 
1139  release_interfaces(&w, &reOle, &txtDoc, NULL);
1140 
1141  /* detached range */
1142  hres = ITextRange_SetStart(txtRge, 0);
1143  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1144 
1145  hres = ITextRange_SetEnd(txtRge, 3);
1146  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1147 
1148  hres = ITextRange_GetStart(txtRge, &start);
1149  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1150 
1151  hres = ITextRange_GetStart(txtRge, NULL);
1152  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1153 
1154  hres = ITextRange_GetEnd(txtRge, &end);
1155  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1156 
1157  hres = ITextRange_GetEnd(txtRge, NULL);
1158  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1159 
1160  ITextRange_Release(txtRge);
1161 }
1162 
1164 {
1165  HWND w;
1166  IRichEditOle *reOle = NULL;
1167  ITextDocument *txtDoc = NULL;
1168  ITextSelection *txtSel = NULL;
1169  HRESULT hres;
1170  int first, lim, start, end;
1171  static const CHAR test_text1[] = "TestSomeText";
1172 
1173  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1174  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1175 
1176  first = 2; lim = 5;
1177  SendMessageA(w, EM_SETSEL, first, lim);
1178  start = 0xdeadbeef;
1179  hres = ITextSelection_GetStart(txtSel, &start);
1180  ok(hres == S_OK, "ITextSelection_GetStart\n");
1181  ok(start == 2, "got wrong start value: %d\n", start);
1182  end = 0xdeadbeef;
1183  hres = ITextSelection_GetEnd(txtSel, &end);
1184  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1185  ok(end == 5, "got wrong end value: %d\n", end);
1186 
1187  first = 5; lim = 2;
1188  SendMessageA(w, EM_SETSEL, first, lim);
1189  start = 0xdeadbeef;
1190  hres = ITextSelection_GetStart(txtSel, &start);
1191  ok(hres == S_OK, "ITextSelection_GetStart\n");
1192  ok(start == 2, "got wrong start value: %d\n", start);
1193  end = 0xdeadbeef;
1194  hres = ITextSelection_GetEnd(txtSel, &end);
1195  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1196  ok(end == 5, "got wrong end value: %d\n", end);
1197 
1198  first = 0; lim = -1;
1199  SendMessageA(w, EM_SETSEL, first, lim);
1200  start = 0xdeadbeef;
1201  hres = ITextSelection_GetStart(txtSel, &start);
1202  ok(hres == S_OK, "ITextSelection_GetStart\n");
1203  ok(start == 0, "got wrong start value: %d\n", start);
1204  end = 0xdeadbeef;
1205  hres = ITextSelection_GetEnd(txtSel, &end);
1206  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1207  ok(end == 13, "got wrong end value: %d\n", end);
1208 
1209  first = 13; lim = 13;
1210  SendMessageA(w, EM_SETSEL, first, lim);
1211  start = 0xdeadbeef;
1212  hres = ITextSelection_GetStart(txtSel, &start);
1213  ok(hres == S_OK, "ITextSelection_GetStart\n");
1214  ok(start == 12, "got wrong start value: %d\n", start);
1215  end = 0xdeadbeef;
1216  hres = ITextSelection_GetEnd(txtSel, &end);
1217  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1218  ok(end == 12, "got wrong end value: %d\n", end);
1219 
1220  /* SetStart/SetEnd */
1221  hres = ITextSelection_SetStart(txtSel, 0);
1222  ok(hres == S_OK, "got 0x%08x\n", hres);
1223 
1224  /* same value */
1225  hres = ITextSelection_SetStart(txtSel, 0);
1226  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1227 
1228  hres = ITextSelection_SetStart(txtSel, 1);
1229  ok(hres == S_OK, "got 0x%08x\n", hres);
1230 
1231  /* negative resets to 0, return value is S_FALSE when
1232  position wasn't changed */
1233  hres = ITextSelection_SetStart(txtSel, -1);
1234  ok(hres == S_OK, "got 0x%08x\n", hres);
1235 
1236  hres = ITextSelection_SetStart(txtSel, -1);
1237  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1238 
1239  hres = ITextSelection_SetStart(txtSel, 0);
1240  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1241 
1242  start = -1;
1243  hres = ITextSelection_GetStart(txtSel, &start);
1244  ok(hres == S_OK, "got 0x%08x\n", hres);
1245  ok(start == 0, "got %d\n", start);
1246 
1247  /* greater than initial end, but less than total char count */
1248  hres = ITextSelection_SetStart(txtSel, 1);
1249  ok(hres == S_OK, "got 0x%08x\n", hres);
1250 
1251  hres = ITextSelection_SetEnd(txtSel, 3);
1252  ok(hres == S_OK, "got 0x%08x\n", hres);
1253 
1254  hres = ITextSelection_SetStart(txtSel, 10);
1255  ok(hres == S_OK, "got 0x%08x\n", hres);
1256 
1257  start = 0;
1258  hres = ITextSelection_GetStart(txtSel, &start);
1259  ok(hres == S_OK, "got 0x%08x\n", hres);
1260  ok(start == 10, "got %d\n", start);
1261 
1262  end = 0;
1263  hres = ITextSelection_GetEnd(txtSel, &end);
1264  ok(hres == S_OK, "got 0x%08x\n", hres);
1265  ok(end == 10, "got %d\n", end);
1266 
1267  /* more that total text length */
1268  hres = ITextSelection_SetStart(txtSel, 50);
1269  ok(hres == S_OK, "got 0x%08x\n", hres);
1270 
1271  start = 0;
1272  hres = ITextSelection_GetStart(txtSel, &start);
1273  ok(hres == S_OK, "got 0x%08x\n", hres);
1274  ok(start == 12, "got %d\n", start);
1275 
1276  end = 0;
1277  hres = ITextSelection_GetEnd(txtSel, &end);
1278  ok(hres == S_OK, "got 0x%08x\n", hres);
1279  ok(end == 12, "got %d\n", end);
1280 
1281  /* SetEnd */
1282  hres = ITextSelection_SetStart(txtSel, 0);
1283  ok(hres == S_OK, "got 0x%08x\n", hres);
1284 
1285  /* same value */
1286  hres = ITextSelection_SetEnd(txtSel, 5);
1287  ok(hres == S_OK, "got 0x%08x\n", hres);
1288 
1289  hres = ITextSelection_SetEnd(txtSel, 5);
1290  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1291 
1292  /* negative resets to 0 */
1293  hres = ITextSelection_SetEnd(txtSel, -1);
1294  ok(hres == S_OK, "got 0x%08x\n", hres);
1295 
1296  end = -1;
1297  hres = ITextSelection_GetEnd(txtSel, &end);
1298  ok(hres == S_OK, "got 0x%08x\n", hres);
1299  ok(end == 0, "got %d\n", end);
1300 
1301  start = -1;
1302  hres = ITextSelection_GetStart(txtSel, &start);
1303  ok(hres == S_OK, "got 0x%08x\n", hres);
1304  ok(start == 0, "got %d\n", start);
1305 
1306  /* greater than initial end, but less than total char count */
1307  hres = ITextSelection_SetStart(txtSel, 3);
1308  ok(hres == S_OK, "got 0x%08x\n", hres);
1309 
1310  hres = ITextSelection_SetEnd(txtSel, 1);
1311  ok(hres == S_OK, "got 0x%08x\n", hres);
1312 
1313  start = 0;
1314  hres = ITextSelection_GetStart(txtSel, &start);
1315  ok(hres == S_OK, "got 0x%08x\n", hres);
1316  ok(start == 1, "got %d\n", start);
1317 
1318  end = 0;
1319  hres = ITextSelection_GetEnd(txtSel, &end);
1320  ok(hres == S_OK, "got 0x%08x\n", hres);
1321  ok(end == 1, "got %d\n", end);
1322 
1323  /* more than total count */
1324  hres = ITextSelection_SetEnd(txtSel, 50);
1325  ok(hres == S_OK, "got 0x%08x\n", hres);
1326 
1327  start = 0;
1328  hres = ITextSelection_GetStart(txtSel, &start);
1329  ok(hres == S_OK, "got 0x%08x\n", hres);
1330  ok(start == 1, "got %d\n", start);
1331 
1332  end = 0;
1333  hres = ITextSelection_GetEnd(txtSel, &end);
1334  ok(hres == S_OK, "got 0x%08x\n", hres);
1335  ok(end == 13, "got %d\n", end);
1336 
1337  /* zero */
1338  hres = ITextSelection_SetEnd(txtSel, 0);
1339  ok(hres == S_OK, "got 0x%08x\n", hres);
1340 
1341  start = 0;
1342  hres = ITextSelection_GetStart(txtSel, &start);
1343  ok(hres == S_OK, "got 0x%08x\n", hres);
1344  ok(start == 0, "got %d\n", start);
1345 
1346  end = 0;
1347  hres = ITextSelection_GetEnd(txtSel, &end);
1348  ok(hres == S_OK, "got 0x%08x\n", hres);
1349  ok(end == 0, "got %d\n", end);
1350 
1351  release_interfaces(&w, &reOle, &txtDoc, NULL);
1352 
1353  /* detached selection */
1354  hres = ITextSelection_GetStart(txtSel, NULL);
1355  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1356 
1357  hres = ITextSelection_GetStart(txtSel, &start);
1358  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1359 
1360  hres = ITextSelection_GetEnd(txtSel, NULL);
1361  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1362 
1363  hres = ITextSelection_GetEnd(txtSel, &end);
1364  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1365 
1366  ITextSelection_Release(txtSel);
1367 }
1368 
1370 {
1371  HWND w;
1372  IRichEditOle *reOle = NULL;
1373  ITextDocument *txtDoc = NULL;
1374  ITextRange *txtRge = NULL;
1375  ITextRange *txtRgeDup = NULL;
1376  HRESULT hres;
1377  LONG first, lim, start, end;
1378  static const CHAR test_text1[] = "TestSomeText";
1379 
1380  create_interfaces(&w, &reOle, &txtDoc, NULL);
1381  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1382  first = 0; lim = 4;
1383  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1384  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
1385 
1386  hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1387  ok(hres == S_OK, "ITextRange_GetDuplicate\n");
1388  ok(txtRgeDup != txtRge, "A new pointer should be returned\n");
1389  hres = ITextRange_GetStart(txtRgeDup, &start);
1390  ok(hres == S_OK, "got 0x%08x\n", hres);
1391  ok(start == first, "got wrong value: %d\n", start);
1392  hres = ITextRange_GetEnd(txtRgeDup, &end);
1393  ok(hres == S_OK, "got 0x%08x\n", hres);
1394  ok(end == lim, "got wrong value: %d\n", end);
1395 
1396  ITextRange_Release(txtRgeDup);
1397 
1398  hres = ITextRange_GetDuplicate(txtRge, NULL);
1399  ok(hres == E_INVALIDARG, "ITextRange_GetDuplicate\n");
1400 
1401  release_interfaces(&w, &reOle, &txtDoc, NULL);
1402 
1403  hres = ITextRange_GetDuplicate(txtRge, NULL);
1404  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1405 
1406  hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1407  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1408 
1409  ITextRange_Release(txtRge);
1410 }
1411 
1412 static void test_ITextRange_Collapse(void)
1413 {
1414  HWND w;
1415  IRichEditOle *reOle = NULL;
1416  ITextDocument *txtDoc = NULL;
1417  ITextRange *txtRge = NULL;
1418  HRESULT hres;
1419  LONG first, lim, start, end;
1420  static const CHAR test_text1[] = "TestSomeText";
1421 
1422  create_interfaces(&w, &reOle, &txtDoc, NULL);
1423  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1424 
1425  first = 4; lim = 8;
1426  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1427  ok(hres == S_OK, "got 0x%08x\n", hres);
1428  hres = ITextRange_Collapse(txtRge, tomTrue);
1429  ok(hres == S_OK, "ITextRange_Collapse\n");
1430  hres = ITextRange_GetStart(txtRge, &start);
1431  ok(hres == S_OK, "got 0x%08x\n", hres);
1432  ok(start == 4, "got wrong start value: %d\n", start);
1433  hres = ITextRange_GetEnd(txtRge, &end);
1434  ok(hres == S_OK, "got 0x%08x\n", hres);
1435  ok(end == 4, "got wrong end value: %d\n", end);
1436  ITextRange_Release(txtRge);
1437 
1438  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1439  ok(hres == S_OK, "got 0x%08x\n", hres);
1440  hres = ITextRange_Collapse(txtRge, tomStart);
1441  ok(hres == S_OK, "ITextRange_Collapse\n");
1442  hres = ITextRange_GetStart(txtRge, &start);
1443  ok(hres == S_OK, "got 0x%08x\n", hres);
1444  ok(start == 4, "got wrong start value: %d\n", start);
1445  hres = ITextRange_GetEnd(txtRge, &end);
1446  ok(hres == S_OK, "got 0x%08x\n", hres);
1447  ok(end == 4, "got wrong end value: %d\n", end);
1448  ITextRange_Release(txtRge);
1449 
1450  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1451  ok(hres == S_OK, "got 0x%08x\n", hres);
1452  hres = ITextRange_Collapse(txtRge, tomFalse);
1453  ok(hres == S_OK, "ITextRange_Collapse\n");
1454  hres = ITextRange_GetStart(txtRge, &start);
1455  ok(hres == S_OK, "got 0x%08x\n", hres);
1456  ok(start == 8, "got wrong start value: %d\n", start);
1457  hres = ITextRange_GetEnd(txtRge, &end);
1458  ok(hres == S_OK, "got 0x%08x\n", hres);
1459  ok(end == 8, "got wrong end value: %d\n", end);
1460  ITextRange_Release(txtRge);
1461 
1462  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1463  ok(hres == S_OK, "got 0x%08x\n", hres);
1464  hres = ITextRange_Collapse(txtRge, tomEnd);
1465  ok(hres == S_OK, "ITextRange_Collapse\n");
1466  hres = ITextRange_GetStart(txtRge, &start);
1467  ok(hres == S_OK, "got 0x%08x\n", hres);
1468  ok(start == 8, "got wrong start value: %d\n", start);
1469  hres = ITextRange_GetEnd(txtRge, &end);
1470  ok(hres == S_OK, "got 0x%08x\n", hres);
1471  ok(end == 8, "got wrong end value: %d\n", end);
1472  ITextRange_Release(txtRge);
1473 
1474  /* tomStart is the default */
1475  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1476  ok(hres == S_OK, "got 0x%08x\n", hres);
1477  hres = ITextRange_Collapse(txtRge, 256);
1478  ok(hres == S_OK, "ITextRange_Collapse\n");
1479  hres = ITextRange_GetStart(txtRge, &start);
1480  ok(hres == S_OK, "got 0x%08x\n", hres);
1481  ok(start == 4, "got wrong start value: %d\n", start);
1482  hres = ITextRange_GetEnd(txtRge, &end);
1483  ok(hres == S_OK, "got 0x%08x\n", hres);
1484  ok(end == 4, "got wrong end value: %d\n", end);
1485  ITextRange_Release(txtRge);
1486 
1487  first = 6; lim = 6;
1488  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1489  ok(hres == S_OK, "got 0x%08x\n", hres);
1490  hres = ITextRange_Collapse(txtRge, tomEnd);
1491  ok(hres == S_FALSE, "ITextRange_Collapse\n");
1492  hres = ITextRange_GetStart(txtRge, &start);
1493  ok(hres == S_OK, "got 0x%08x\n", hres);
1494  ok(start == 6, "got wrong start value: %d\n", start);
1495  hres = ITextRange_GetEnd(txtRge, &end);
1496  ok(hres == S_OK, "got 0x%08x\n", hres);
1497  ok(end == 6, "got wrong end value: %d\n", end);
1498  ITextRange_Release(txtRge);
1499 
1500  first = 8; lim = 8;
1501  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1502  ok(hres == S_OK, "got 0x%08x\n", hres);
1503  hres = ITextRange_Collapse(txtRge, tomStart);
1504  ok(hres == S_FALSE, "ITextRange_Collapse\n");
1505  hres = ITextRange_GetStart(txtRge, &start);
1506  ok(hres == S_OK, "got 0x%08x\n", hres);
1507  ok(start == 8, "got wrong start value: %d\n", start);
1508  hres = ITextRange_GetEnd(txtRge, &end);
1509  ok(hres == S_OK, "got 0x%08x\n", hres);
1510  ok(end == 8, "got wrong end value: %d\n", end);
1511 
1512  release_interfaces(&w, &reOle, &txtDoc, NULL);
1513 
1514  hres = ITextRange_Collapse(txtRge, tomStart);
1515  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1516 
1517  hres = ITextRange_Collapse(txtRge, tomUndefined);
1518  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1519 
1520  ITextRange_Release(txtRge);
1521 }
1522 
1524 {
1525  HWND w;
1526  IRichEditOle *reOle = NULL;
1527  ITextDocument *txtDoc = NULL;
1528  ITextSelection *txtSel = NULL;
1529  HRESULT hres;
1530  LONG first, lim, start, end;
1531  static const CHAR test_text1[] = "TestSomeText";
1532 
1533  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1534  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1535 
1536  first = 4; lim = 8;
1537  SendMessageA(w, EM_SETSEL, first, lim);
1538  hres = ITextSelection_Collapse(txtSel, tomTrue);
1539  ok(hres == S_OK, "ITextSelection_Collapse\n");
1541  ok(start == 4, "got wrong start value: %d\n", start);
1542  ok(end == 4, "got wrong end value: %d\n", end);
1543 
1544  SendMessageA(w, EM_SETSEL, first, lim);
1545  hres = ITextSelection_Collapse(txtSel, tomStart);
1546  ok(hres == S_OK, "ITextSelection_Collapse\n");
1548  ok(start == 4, "got wrong start value: %d\n", start);
1549  ok(end == 4, "got wrong end value: %d\n", end);
1550 
1551  SendMessageA(w, EM_SETSEL, first, lim);
1552  hres = ITextSelection_Collapse(txtSel, tomFalse);
1553  ok(hres == S_OK, "ITextSelection_Collapse\n");
1555  ok(start == 8, "got wrong start value: %d\n", start);
1556  ok(end == 8, "got wrong end value: %d\n", end);
1557 
1558  SendMessageA(w, EM_SETSEL, first, lim);
1559  hres = ITextSelection_Collapse(txtSel, tomEnd);
1560  ok(hres == S_OK, "ITextSelection_Collapse\n");
1562  ok(start == 8, "got wrong start value: %d\n", start);
1563  ok(end == 8, "got wrong end value: %d\n", end);
1564 
1565  /* tomStart is the default */
1566  SendMessageA(w, EM_SETSEL, first, lim);
1567  hres = ITextSelection_Collapse(txtSel, 256);
1568  ok(hres == S_OK, "ITextSelection_Collapse\n");
1570  ok(start == 4, "got wrong start value: %d\n", start);
1571  ok(end == 4, "got wrong end value: %d\n", end);
1572 
1573  first = 6; lim = 6;
1574  SendMessageA(w, EM_SETSEL, first, lim);
1575  hres = ITextSelection_Collapse(txtSel, tomEnd);
1576  ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1578  ok(start == 6, "got wrong start value: %d\n", start);
1579  ok(end == 6, "got wrong end value: %d\n", end);
1580 
1581  first = 8; lim = 8;
1582  SendMessageA(w, EM_SETSEL, first, lim);
1583  hres = ITextSelection_Collapse(txtSel, tomStart);
1584  ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1586  ok(start == 8, "got wrong start value: %d\n", start);
1587  ok(end == 8, "got wrong end value: %d\n", end);
1588 
1589  release_interfaces(&w, &reOle, &txtDoc, NULL);
1590 
1591  hres = ITextSelection_Collapse(txtSel, tomStart);
1592  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1593 
1594  hres = ITextSelection_Collapse(txtSel, tomUndefined);
1595  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1596 
1597  ITextSelection_Release(txtSel);
1598 }
1599 
1600 static void test_GetClientSite(void)
1601 {
1602  HWND w;
1603  IRichEditOle *reOle = NULL, *reOle1 = NULL;
1604  ITextDocument *txtDoc = NULL;
1605  IOleClientSite *clientSite = NULL, *clientSite1 = NULL, *clientSite2 = NULL;
1606  IOleWindow *oleWin = NULL, *oleWin1 = NULL;
1607  IOleInPlaceSite *olePlace = NULL, *olePlace1 = NULL;
1608  HRESULT hres;
1609  LONG refcount1, refcount2;
1610 
1611  create_interfaces(&w, &reOle, &txtDoc, NULL);
1612  hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1613  ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1614  EXPECT_REF(clientSite, 1);
1615 
1616  hres = IOleClientSite_QueryInterface(clientSite, &IID_IRichEditOle, (void **)&reOle1);
1617  ok(hres == E_NOINTERFACE, "IOleClientSite_QueryInterface: %x\n", hres);
1618 
1619  hres = IRichEditOle_GetClientSite(reOle, &clientSite1);
1620  ok(hres == S_OK, "got 0x%08x\n", hres);
1621  ok(clientSite != clientSite1, "got %p, %p\n", clientSite, clientSite1);
1622  IOleClientSite_Release(clientSite1);
1623 
1624  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleClientSite, (void **)&clientSite1);
1625  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1626  ok(clientSite == clientSite1, "Should not return a new pointer.\n");
1627  EXPECT_REF(clientSite, 2);
1628 
1629  /* IOleWindow interface */
1630  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1631  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1632  refcount1 = get_refcount((IUnknown *)clientSite);
1633  refcount2 = get_refcount((IUnknown *)oleWin);
1634  ok(refcount1 == refcount2, "got wrong ref count.\n");
1635 
1636  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin1);
1637  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1638  ok(oleWin == oleWin1, "Should not return a new pointer.\n");
1639  refcount1 = get_refcount((IUnknown *)clientSite);
1640  refcount2 = get_refcount((IUnknown *)oleWin);
1641  ok(refcount1 == refcount2, "got wrong ref count.\n");
1642 
1643  hres = IOleWindow_QueryInterface(oleWin, &IID_IOleClientSite, (void **)&clientSite2);
1644  ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1645  ok(clientSite2 == clientSite1, "got wrong pointer\n");
1646 
1647  /* IOleInPlaceSite interface */
1648  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1649  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1650  refcount1 = get_refcount((IUnknown *)olePlace);
1651  refcount2 = get_refcount((IUnknown *)clientSite);
1652  ok(refcount1 == refcount2, "got wrong ref count.\n");
1653 
1654  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace1);
1655  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1656  ok(olePlace == olePlace1, "Should not return a new pointer.\n");
1657  IOleInPlaceSite_Release(olePlace1);
1658 
1659  hres = IOleWindow_QueryInterface(oleWin, &IID_IOleInPlaceSite, (void **)&olePlace1);
1660  ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1661  refcount1 = get_refcount((IUnknown *)olePlace1);
1662  refcount2 = get_refcount((IUnknown *)oleWin);
1663  ok(refcount1 == refcount2, "got wrong ref count.\n");
1664 
1665  IOleInPlaceSite_Release(olePlace1);
1666  IOleInPlaceSite_Release(olePlace);
1667  IOleWindow_Release(oleWin1);
1668  IOleWindow_Release(oleWin);
1669  IOleClientSite_Release(clientSite2);
1670  IOleClientSite_Release(clientSite1);
1671  IOleClientSite_Release(clientSite);
1672  release_interfaces(&w, &reOle, &txtDoc, NULL);
1673 }
1674 
1675 static void test_IOleWindow_GetWindow(void)
1676 {
1677  HWND w;
1678  IRichEditOle *reOle = NULL;
1679  ITextDocument *txtDoc = NULL;
1680  IOleClientSite *clientSite = NULL;
1681  IOleWindow *oleWin = NULL;
1682  HRESULT hres;
1683  HWND hwnd;
1684 
1685  create_interfaces(&w, &reOle, &txtDoc, NULL);
1686  hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1687  ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1688 
1689  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1690  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1691  hres = IOleWindow_GetWindow(oleWin, &hwnd);
1692  ok(hres == S_OK, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1693  ok(w == hwnd, "got wrong pointer\n");
1694 
1695  hres = IOleWindow_GetWindow(oleWin, NULL);
1696  ok(hres == E_INVALIDARG, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1697 
1698  IOleWindow_Release(oleWin);
1699  IOleClientSite_Release(clientSite);
1700  release_interfaces(&w, &reOle, &txtDoc, NULL);
1701 }
1702 
1704 {
1705  HWND w;
1706  IRichEditOle *reOle = NULL;
1707  ITextDocument *txtDoc = NULL;
1708  IOleClientSite *clientSite = NULL;
1709  IOleInPlaceSite *olePlace = NULL;
1710  HRESULT hres;
1711  HWND hwnd;
1712 
1713  create_interfaces(&w, &reOle, &txtDoc, NULL);
1714  hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1715  ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1716 
1717  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1718  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1719  hres = IOleInPlaceSite_GetWindow(olePlace, &hwnd);
1720  ok(hres == S_OK, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1721  ok(w == hwnd, "got wrong pointer.\n");
1722 
1723  hres = IOleInPlaceSite_GetWindow(olePlace, NULL);
1724  ok(hres == E_INVALIDARG, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1725 
1726  IOleInPlaceSite_Release(olePlace);
1727  IOleClientSite_Release(clientSite);
1728  release_interfaces(&w, &reOle, &txtDoc, NULL);
1729 }
1730 
1731 static void test_GetFont(void)
1732 {
1733  static const CHAR test_text1[] = "TestSomeText";
1734  IRichEditOle *reOle = NULL;
1735  ITextDocument *doc = NULL;
1736  ITextRange *range = NULL;
1738  ITextFont *font, *font2;
1739  CHARFORMAT2A cf;
1740  LONG value;
1741  float size;
1742  HRESULT hr;
1743  HWND hwnd;
1744  BOOL ret;
1745 
1746  create_interfaces(&hwnd, &reOle, &doc, NULL);
1747  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1748 
1749  hr = ITextDocument_GetSelection(doc, &selection);
1750  ok(hr == S_OK, "got 0x%08x\n", hr);
1751  hr = ITextSelection_GetFont(selection, &font);
1752  ok(hr == S_OK, "got 0x%08x\n", hr);
1753  hr = ITextSelection_GetFont(selection, &font2);
1754  ok(hr == S_OK, "got 0x%08x\n", hr);
1755  ok(font != font2, "got %p, %p\n", font, font2);
1756  ITextFont_Release(font2);
1757  ITextFont_Release(font);
1758  ITextSelection_Release(selection);
1759 
1760  EXPECT_REF(reOle, 3);
1761  EXPECT_REF(doc, 3);
1762 
1763  hr = ITextDocument_Range(doc, 0, 4, &range);
1764  ok(hr == S_OK, "got 0x%08x\n", hr);
1765 
1766  EXPECT_REF(reOle, 3);
1767  EXPECT_REF(doc, 3);
1768  EXPECT_REF(range, 1);
1769 
1770  hr = ITextRange_GetFont(range, NULL);
1771  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1772 
1773  hr = ITextRange_GetFont(range, &font);
1774  ok(hr == S_OK, "got 0x%08x\n", hr);
1775 
1776  EXPECT_REF(reOle, 3);
1777  EXPECT_REF(doc, 3);
1778  EXPECT_REF(range, 2);
1779  EXPECT_REF(font, 1);
1780 
1781  hr = ITextRange_GetFont(range, &font2);
1782  ok(hr == S_OK, "got 0x%08x\n", hr);
1783  ok(font != font2, "got %p, %p\n", font, font2);
1784 
1785  EXPECT_REF(reOle, 3);
1786  EXPECT_REF(doc, 3);
1787  EXPECT_REF(range, 3);
1788  EXPECT_REF(font, 1);
1789  EXPECT_REF(font2, 1);
1790 
1791  ITextFont_Release(font2);
1792 
1793  /* set different font style within a range */
1794  hr = ITextFont_GetItalic(font, NULL);
1795  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1796 
1797  hr = ITextFont_GetSize(font, NULL);
1798  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1799 
1800  size = 0.0;
1801  hr = ITextFont_GetSize(font, &size);
1802  ok(hr == S_OK, "got 0x%08x\n", hr);
1803  ok(size > 0.0, "size %.2f\n", size);
1804 
1805  value = 0;
1806  hr = ITextFont_GetLanguageID(font, &value);
1807  ok(hr == S_OK, "got 0x%08x\n", hr);
1808  ok(value == GetSystemDefaultLCID(), "got lcid %x, user lcid %x\n", value,
1810 
1811  /* range is non-italic */
1812  value = tomTrue;
1813  hr = ITextFont_GetItalic(font, &value);
1814  ok(hr == S_OK, "got 0x%08x\n", hr);
1815  ok(value == tomFalse, "got %d\n", value);
1816 
1817  cf.cbSize = sizeof(CHARFORMAT2A);
1818  cf.dwMask = CFM_ITALIC|CFM_SIZE;
1819  cf.dwEffects = CFE_ITALIC;
1820  cf.yHeight = 24.0;
1821 
1822  SendMessageA(hwnd, EM_SETSEL, 2, 3);
1824  ok(ret, "got %d\n", ret);
1825 
1826  /* now range is partially italicized */
1827  value = tomFalse;
1828  hr = ITextFont_GetItalic(font, &value);
1829  ok(hr == S_OK, "got 0x%08x\n", hr);
1830  ok(value == tomUndefined, "got %d\n", value);
1831 
1832  size = 0.0;
1833  hr = ITextFont_GetSize(font, &size);
1834  ok(hr == S_OK, "got 0x%08x\n", hr);
1835  ok(size == tomUndefined, "size %.2f\n", size);
1836 
1837  ITextFont_Release(font);
1838  release_interfaces(&hwnd, &reOle, &doc, NULL);
1839 
1840  hr = ITextRange_GetFont(range, NULL);
1841  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1842 
1843  hr = ITextRange_GetFont(range, &font2);
1844  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1845 
1846  ITextRange_Release(range);
1847 }
1848 
1849 static void test_GetPara(void)
1850 {
1851  static const CHAR test_text1[] = "TestSomeText";
1852  IRichEditOle *reOle = NULL;
1853  ITextDocument *doc = NULL;
1855  ITextRange *range = NULL;
1856  ITextPara *para, *para2;
1857  HRESULT hr;
1858  HWND hwnd;
1859 
1860  create_interfaces(&hwnd, &reOle, &doc, &selection);
1861  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1862 
1863  EXPECT_REF(reOle, 3);
1864  EXPECT_REF(doc, 3);
1865 
1866  hr = ITextDocument_Range(doc, 0, 4, &range);
1867  ok(hr == S_OK, "got 0x%08x\n", hr);
1868 
1869  EXPECT_REF(reOle, 3);
1870  EXPECT_REF(doc, 3);
1871  EXPECT_REF(range, 1);
1872 
1873  hr = ITextRange_GetPara(range, NULL);
1874  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1875 
1876  hr = ITextRange_GetPara(range, &para);
1877  ok(hr == S_OK, "got 0x%08x\n", hr);
1878 
1879  EXPECT_REF(reOle, 3);
1880  EXPECT_REF(doc, 3);
1881  EXPECT_REF(range, 2);
1882  EXPECT_REF(para, 1);
1883 
1884  hr = ITextRange_GetPara(range, &para2);
1885  ok(hr == S_OK, "got 0x%08x\n", hr);
1886  ok(para != para2, "got %p, %p\n", para, para2);
1887 
1888  EXPECT_REF(reOle, 3);
1889  EXPECT_REF(doc, 3);
1890  EXPECT_REF(range, 3);
1891  EXPECT_REF(para, 1);
1892  EXPECT_REF(para2, 1);
1893 
1894  ITextPara_Release(para);
1895  ITextPara_Release(para2);
1896 
1897  EXPECT_REF(reOle, 3);
1898  EXPECT_REF(doc, 3);
1899  EXPECT_REF(selection, 2);
1900 
1901  hr = ITextSelection_GetPara(selection, &para);
1902  ok(hr == S_OK, "got 0x%08x\n", hr);
1903 
1904  EXPECT_REF(reOle, 3);
1905  EXPECT_REF(doc, 3);
1906  EXPECT_REF(selection, 3);
1907  EXPECT_REF(para, 1);
1908 
1909  hr = ITextSelection_GetPara(selection, &para2);
1910  ok(hr == S_OK, "got 0x%08x\n", hr);
1911  ok(para != para2, "got %p, %p\n", para, para2);
1912 
1913  ITextPara_Release(para);
1914  ITextPara_Release(para2);
1915  release_interfaces(&hwnd, &reOle, &doc, NULL);
1916 
1917  hr = ITextRange_GetPara(range, NULL);
1918  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1919 
1920  hr = ITextRange_GetPara(range, &para);
1921  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1922 
1923  hr = ITextSelection_GetPara(selection, NULL);
1924  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1925 
1926  hr = ITextSelection_GetPara(selection, &para);
1927  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1928 
1929  ITextSelection_Release(selection);
1930  ITextRange_Release(range);
1931 }
1932 
1933 static void test_dispatch(void)
1934 {
1935  static const WCHAR testnameW[] = {'G','e','t','T','e','x','t',0};
1936  static const WCHAR testname2W[] = {'T','e','x','t',0};
1937  IRichEditOle *reOle = NULL;
1938  ITextDocument *doc = NULL;
1939  ITextRange *range = NULL;
1940  WCHAR *nameW;
1941  DISPID dispid;
1942  HRESULT hr;
1943  UINT count;
1944  HWND hwnd;
1945 
1946  create_interfaces(&hwnd, &reOle, &doc, NULL);
1947 
1948  range = NULL;
1949  hr = ITextDocument_Range(doc, 0, 0, &range);
1950  ok(hr == S_OK, "got 0x%08x\n", hr);
1951  ok(range != NULL, "got %p\n", range);
1952 
1953  dispid = 123;
1954  nameW = (WCHAR*)testnameW;
1955  hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1956  ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
1957  ok(dispid == DISPID_UNKNOWN, "got %d\n", dispid);
1958 
1959  dispid = 123;
1960  nameW = (WCHAR*)testname2W;
1961  hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1962  ok(hr == S_OK, "got 0x%08x\n", hr);
1963  ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1964 
1965  release_interfaces(&hwnd, &reOle, &doc, NULL);
1966 
1967  /* try dispatch methods on detached range */
1968  hr = ITextRange_GetTypeInfoCount(range, &count);
1969  ok(hr == S_OK, "got 0x%08x\n", hr);
1970 
1971  dispid = 123;
1972  nameW = (WCHAR*)testname2W;
1973  hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1974  ok(hr == S_OK, "got 0x%08x\n", hr);
1975  ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1976 
1977  ITextRange_Release(range);
1978 }
1979 
1981 {
1982  HRESULT hr, hrexp = duplicate ? S_OK : CO_E_RELEASED;
1983  LONG value;
1984  float size;
1985  BSTR str;
1986 
1987  hr = ITextFont_GetBold(font, NULL);
1988  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1989 
1990  hr = ITextFont_GetBold(font, &value);
1991  ok(hr == hrexp, "got 0x%08x\n", hr);
1992 
1993  hr = ITextFont_GetForeColor(font, NULL);
1994  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1995 
1996  hr = ITextFont_GetForeColor(font, &value);
1997  ok(hr == hrexp, "got 0x%08x\n", hr);
1998 
1999  hr = ITextFont_GetItalic(font, NULL);
2000  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2001 
2002  hr = ITextFont_GetItalic(font, &value);
2003  ok(hr == hrexp, "got 0x%08x\n", hr);
2004 
2005  hr = ITextFont_GetLanguageID(font, NULL);
2006  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2007 
2008  hr = ITextFont_GetLanguageID(font, &value);
2009  ok(hr == hrexp, "got 0x%08x\n", hr);
2010 
2011  hr = ITextFont_GetName(font, NULL);
2012  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2013 
2014  hr = ITextFont_GetName(font, &str);
2015  ok(hr == hrexp, "got 0x%08x\n", hr);
2016 
2017  hr = ITextFont_GetSize(font, NULL);
2018  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2019 
2020  hr = ITextFont_GetSize(font, &size);
2021  ok(hr == hrexp, "got 0x%08x\n", hr);
2022 
2023  hr = ITextFont_GetStrikeThrough(font, NULL);
2024  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2025 
2026  hr = ITextFont_GetStrikeThrough(font, &value);
2027  ok(hr == hrexp, "got 0x%08x\n", hr);
2028 
2029  hr = ITextFont_GetSubscript(font, NULL);
2030  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2031 
2032  hr = ITextFont_GetSubscript(font, &value);
2033  ok(hr == hrexp, "got 0x%08x\n", hr);
2034 
2035  hr = ITextFont_GetSuperscript(font, NULL);
2036  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2037 
2038  hr = ITextFont_GetSuperscript(font, &value);
2039  ok(hr == hrexp, "got 0x%08x\n", hr);
2040 
2041  hr = ITextFont_GetUnderline(font, NULL);
2042  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2043 
2044  hr = ITextFont_GetUnderline(font, &value);
2045  ok(hr == hrexp, "got 0x%08x\n", hr);
2046 }
2047 
2049 {
2050  float valuef;
2051  LONG value;
2052  HRESULT hr;
2053  BSTR str;
2054 
2055  value = tomUndefined;
2056  hr = ITextFont_GetAllCaps(font, &value);
2057  ok(hr == S_OK, "got 0x%08x\n", hr);
2058  ok(value == tomFalse, "got %d\n", value);
2059 
2060  value = tomUndefined;
2061  hr = ITextFont_GetAnimation(font, &value);
2062  ok(hr == S_OK, "got 0x%08x\n", hr);
2063  ok(value == tomFalse, "got %d\n", value);
2064 
2065  value = tomUndefined;
2066  hr = ITextFont_GetBackColor(font, &value);
2067  ok(hr == S_OK, "got 0x%08x\n", hr);
2068  ok(value == tomAutoColor, "got %d\n", value);
2069 
2070  value = tomUndefined;
2071  hr = ITextFont_GetBold(font, &value);
2072  ok(hr == S_OK, "got 0x%08x\n", hr);
2073  ok(value == tomFalse || value == tomTrue, "got %d\n", value);
2074 
2075  value = tomUndefined;
2076  hr = ITextFont_GetEmboss(font, &value);
2077  ok(hr == S_OK, "got 0x%08x\n", hr);
2078  ok(value == tomFalse, "got %d\n", value);
2079 
2080  value = tomUndefined;
2081  hr = ITextFont_GetForeColor(font, &value);
2082  ok(hr == S_OK, "got 0x%08x\n", hr);
2083  ok(value == tomAutoColor, "got %d\n", value);
2084 
2085  value = tomUndefined;
2086  hr = ITextFont_GetHidden(font, &value);
2087  ok(hr == S_OK, "got 0x%08x\n", hr);
2088  ok(value == tomFalse, "got %d\n", value);
2089 
2090  value = tomUndefined;
2091  hr = ITextFont_GetEngrave(font, &value);
2092  ok(hr == S_OK, "got 0x%08x\n", hr);
2093  ok(value == tomFalse, "got %d\n", value);
2094 
2095  value = tomUndefined;
2096  hr = ITextFont_GetItalic(font, &value);
2097  ok(hr == S_OK, "got 0x%08x\n", hr);
2098  ok(value == tomFalse, "got %d\n", value);
2099 
2100  valuef = 1.0;
2101  hr = ITextFont_GetKerning(font, &valuef);
2102  ok(hr == S_OK, "got 0x%08x\n", hr);
2103  ok(valuef == 0.0, "got %.2f\n", valuef);
2104 
2105  value = tomUndefined;
2106  hr = ITextFont_GetLanguageID(font, &value);
2107  ok(hr == S_OK, "got 0x%08x\n", hr);
2108  ok(value == GetSystemDefaultLCID(), "got %d\n", value);
2109 
2110  str = NULL;
2111  hr = ITextFont_GetName(font, &str);
2112  ok(hr == S_OK, "got 0x%08x\n", hr);
2113  ok(!lstrcmpW(sysW, str), "%s\n", wine_dbgstr_w(str));
2114  SysFreeString(str);
2115 
2116  value = tomUndefined;
2117  hr = ITextFont_GetOutline(font, &value);
2118  ok(hr == S_OK, "got 0x%08x\n", hr);
2119  ok(value == tomFalse, "got %d\n", value);
2120 
2121  valuef = 1.0;
2122  hr = ITextFont_GetPosition(font, &valuef);
2123  ok(hr == S_OK, "got 0x%08x\n", hr);
2124  ok(valuef == 0.0, "got %.2f\n", valuef);
2125 
2126  value = tomUndefined;
2127  hr = ITextFont_GetProtected(font, &value);
2128  ok(hr == S_OK, "got 0x%08x\n", hr);
2129  ok(value == tomFalse, "got %d\n", value);
2130 
2131  value = tomUndefined;
2132  hr = ITextFont_GetShadow(font, &value);
2133  ok(hr == S_OK, "got 0x%08x\n", hr);
2134  ok(value == tomFalse, "got %d\n", value);
2135 
2136  valuef = 0.0;
2137  hr = ITextFont_GetSize(font, &valuef);
2138  ok(hr == S_OK, "got 0x%08x\n", hr);
2139  ok(valuef >= 0.0, "got %.2f\n", valuef);
2140 
2141  value = tomUndefined;
2142  hr = ITextFont_GetSmallCaps(font, &value);
2143  ok(hr == S_OK, "got 0x%08x\n", hr);
2144  ok(value == tomFalse, "got %d\n", value);
2145 
2146  valuef = 1.0;
2147  hr = ITextFont_GetSpacing(font, &valuef);
2148  ok(hr == S_OK, "got 0x%08x\n", hr);
2149  ok(valuef == 0.0, "got %.2f\n", valuef);
2150 
2151  value = tomUndefined;
2152  hr = ITextFont_GetStrikeThrough(font, &value);
2153  ok(hr == S_OK, "got 0x%08x\n", hr);
2154  ok(value == tomFalse, "got %d\n", value);
2155 
2156  value = tomUndefined;
2157  hr = ITextFont_GetSubscript(font, &value);
2158  ok(hr == S_OK, "got 0x%08x\n", hr);
2159  ok(value == tomFalse, "got %d\n", value);
2160 
2161  value = tomUndefined;
2162  hr = ITextFont_GetSuperscript(font, &value);
2163  ok(hr == S_OK, "got 0x%08x\n", hr);
2164  ok(value == tomFalse, "got %d\n", value);
2165 
2166  value = tomUndefined;
2167  hr = ITextFont_GetUnderline(font, &value);
2168  ok(hr == S_OK, "got 0x%08x\n", hr);
2169  ok(value == tomFalse, "got %d\n", value);
2170 
2171  value = tomUndefined;
2172  hr = ITextFont_GetWeight(font, &value);
2173  ok(hr == S_OK, "got 0x%08x\n", hr);
2174  ok(value == FW_NORMAL || value == FW_BOLD, "got %d\n", value);
2175 }
2176 
2178 {
2179  float valuef;
2180  LONG value;
2181  HRESULT hr;
2182 
2183  value = tomFalse;
2184  hr = ITextFont_GetAllCaps(font, &value);
2185  ok(hr == S_OK, "got 0x%08x\n", hr);
2186  ok(value == tomUndefined, "got %d\n", value);
2187 
2188  value = tomFalse;
2189  hr = ITextFont_GetAnimation(font, &value);
2190  ok(hr == S_OK, "got 0x%08x\n", hr);
2191  ok(value == tomUndefined, "got %d\n", value);
2192 
2193  value = tomFalse;
2194  hr = ITextFont_GetBackColor(font, &value);
2195  ok(hr == S_OK, "got 0x%08x\n", hr);
2196  ok(value == tomUndefined, "got %d\n", value);
2197 
2198  value = tomFalse;
2199  hr = ITextFont_GetBold(font, &value);
2200  ok(hr == S_OK, "got 0x%08x\n", hr);
2201  ok(value == tomUndefined, "got %d\n", value);
2202 
2203  value = tomFalse;
2204  hr = ITextFont_GetEmboss(font, &value);
2205  ok(hr == S_OK, "got 0x%08x\n", hr);
2206  ok(value == tomUndefined, "got %d\n", value);
2207 
2208  value = tomFalse;
2209  hr = ITextFont_GetForeColor(font, &value);
2210  ok(hr == S_OK, "got 0x%08x\n", hr);
2211  ok(value == tomUndefined, "got %d\n", value);
2212 
2213  value = tomFalse;
2214  hr = ITextFont_GetHidden(font, &value);
2215  ok(hr == S_OK, "got 0x%08x\n", hr);
2216  ok(value == tomUndefined, "got %d\n", value);
2217 
2218  value = tomFalse;
2219  hr = ITextFont_GetEngrave(font, &value);
2220  ok(hr == S_OK, "got 0x%08x\n", hr);
2221  ok(value == tomUndefined, "got %d\n", value);
2222 
2223  value = tomFalse;
2224  hr = ITextFont_GetItalic(font, &value);
2225  ok(hr == S_OK, "got 0x%08x\n", hr);
2226  ok(value == tomUndefined, "got %d\n", value);
2227 
2228  valuef = 0.0;
2229  hr = ITextFont_GetKerning(font, &valuef);
2230  ok(hr == S_OK, "got 0x%08x\n", hr);
2231  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2232 
2233  value = tomFalse;
2234  hr = ITextFont_GetLanguageID(font, &value);
2235  ok(hr == S_OK, "got 0x%08x\n", hr);
2236  ok(value == tomUndefined, "got %d\n", value);
2237 
2238  value = tomFalse;
2239  hr = ITextFont_GetOutline(font, &value);
2240  ok(hr == S_OK, "got 0x%08x\n", hr);
2241  ok(value == tomUndefined, "got %d\n", value);
2242 
2243  valuef = 0.0;
2244  hr = ITextFont_GetPosition(font, &valuef);
2245  ok(hr == S_OK, "got 0x%08x\n", hr);
2246  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2247 
2248  value = tomFalse;
2249  hr = ITextFont_GetProtected(font, &value);
2250  ok(hr == S_OK, "got 0x%08x\n", hr);
2251  ok(value == tomUndefined, "got %d\n", value);
2252 
2253  value = tomFalse;
2254  hr = ITextFont_GetShadow(font, &value);
2255  ok(hr == S_OK, "got 0x%08x\n", hr);
2256  ok(value == tomUndefined, "got %d\n", value);
2257 
2258  valuef = 0.0;
2259  hr = ITextFont_GetSize(font, &valuef);
2260  ok(hr == S_OK, "got 0x%08x\n", hr);
2261  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2262 
2263  value = tomFalse;
2264  hr = ITextFont_GetSmallCaps(font, &value);
2265  ok(hr == S_OK, "got 0x%08x\n", hr);
2266  ok(value == tomUndefined, "got %d\n", value);
2267 
2268  valuef = 0.0;
2269  hr = ITextFont_GetSpacing(font, &valuef);
2270  ok(hr == S_OK, "got 0x%08x\n", hr);
2271  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2272 
2273  value = tomFalse;
2274  hr = ITextFont_GetStrikeThrough(font, &value);
2275  ok(hr == S_OK, "got 0x%08x\n", hr);
2276  ok(value == tomUndefined, "got %d\n", value);
2277 
2278  value = tomFalse;
2279  hr = ITextFont_GetSubscript(font, &value);
2280  ok(hr == S_OK, "got 0x%08x\n", hr);
2281  ok(value == tomUndefined, "got %d\n", value);
2282 
2283  value = tomFalse;
2284  hr = ITextFont_GetSuperscript(font, &value);
2285  ok(hr == S_OK, "got 0x%08x\n", hr);
2286  ok(value == tomUndefined, "got %d\n", value);
2287 
2288  value = tomFalse;
2289  hr = ITextFont_GetUnderline(font, &value);
2290  ok(hr == S_OK, "got 0x%08x\n", hr);
2291  ok(value == tomUndefined, "got %d\n", value);
2292 
2293  value = tomFalse;
2294  hr = ITextFont_GetWeight(font, &value);
2295  ok(hr == S_OK, "got 0x%08x\n", hr);
2296  ok(value == tomUndefined, "got %d\n", value);
2297 }
2298 
2300 {
2301  return value * 72.0 / 1440;
2302 }
2303 
2304 static void test_ITextFont(void)
2305 {
2306  static const WCHAR arialW[] = {'A','r','i','a','l',0};
2307  static const CHAR test_text1[] = "TestSomeText";
2308  ITextFont *font, *font2, *font3;
2309  FLOAT size, position, kerning;
2310  IRichEditOle *reOle = NULL;
2311  ITextDocument *doc = NULL;
2312  ITextRange *range = NULL;
2313  CHARFORMAT2A cf;
2314  LONG value;
2315  HRESULT hr;
2316  HWND hwnd;
2317  BOOL ret;
2318  BSTR str;
2319 
2320  create_interfaces(&hwnd, &reOle, &doc, NULL);
2321  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2322 
2323  hr = ITextDocument_Range(doc, 0, 10, &range);
2324  ok(hr == S_OK, "got 0x%08x\n", hr);
2325 
2326  hr = ITextRange_GetFont(range, &font);
2327  ok(hr == S_OK, "got 0x%08x\n", hr);
2328 
2329  hr = ITextFont_Reset(font, tomUseTwips);
2330  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2331 
2332  hr = ITextFont_Reset(font, tomUsePoints);
2333  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2334 
2335  hr = ITextFont_GetName(font, NULL);
2336  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2337 
2338  /* default font size unit is point */
2339  size = 0.0;
2340  hr = ITextFont_GetSize(font, &size);
2341  ok(hr == S_OK, "got 0x%08x\n", hr);
2342 
2343  /* set to some non-zero values */
2344  hr = ITextFont_SetPosition(font, 20.0);
2345  ok(hr == S_OK, "got 0x%08x\n", hr);
2346 
2347  hr = ITextFont_SetKerning(font, 10.0);
2348  ok(hr == S_OK, "got 0x%08x\n", hr);
2349 
2350  position = 0.0;
2351  hr = ITextFont_GetPosition(font, &position);
2352  ok(hr == S_OK, "got 0x%08x\n", hr);
2353 
2354  kerning = 0.0;
2355  hr = ITextFont_GetKerning(font, &kerning);
2356  ok(hr == S_OK, "got 0x%08x\n", hr);
2357 
2358  memset(&cf, 0, sizeof(cf));
2359  cf.cbSize = sizeof(cf);
2360  cf.dwMask = CFM_SIZE|CFM_OFFSET|CFM_KERNING;
2361 
2362  /* CHARFORMAT members are in twips */
2363  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2365  ok(ret, "got %d\n", ret);
2366  ok(size == twips_to_points(cf.yHeight), "got yHeight %d, size %.2f\n", cf.yHeight, size);
2367  ok(position == twips_to_points(cf.yOffset), "got yOffset %d, position %.2f\n", cf.yOffset, position);
2368  ok(kerning == twips_to_points(cf.wKerning), "got wKerning %d, kerning %.2f\n", cf.wKerning, kerning);
2369 
2370  hr = ITextFont_Reset(font, tomUseTwips);
2371  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2372 
2373  hr = ITextFont_Reset(font, tomUsePoints);
2374  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2375 
2376  hr = ITextFont_GetDuplicate(font, &font2);
2377  ok(hr == S_OK, "got 0x%08x\n", hr);
2378 
2379  hr = ITextFont_Reset(font2, tomUseTwips);
2380  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2381 
2382  hr = ITextFont_Reset(font2, tomUsePoints);
2383  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2384 
2385  ITextFont_Release(font2);
2386 
2387  /* default font name */
2388  str = NULL;
2389  hr = ITextFont_GetName(font, &str);
2390  ok(hr == S_OK, "got 0x%08x\n", hr);
2391  ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2392  SysFreeString(str);
2393 
2394  /* change font name for an inner subrange */
2395  memset(&cf, 0, sizeof(cf));
2396  cf.cbSize = sizeof(cf);
2397  cf.dwMask = CFM_FACE;
2398  strcpy(cf.szFaceName, "Arial");
2399 
2400  SendMessageA(hwnd, EM_SETSEL, 3, 4);
2402  ok(ret, "got %d\n", ret);
2403 
2404  /* still original name */
2405  str = NULL;
2406  hr = ITextFont_GetName(font, &str);
2407  ok(hr == S_OK, "got 0x%08x\n", hr);
2408  ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2409  SysFreeString(str);
2410 
2411  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2413  ok(ret, "got %d\n", ret);
2414 
2415  str = NULL;
2416  hr = ITextFont_GetName(font, &str);
2417  ok(hr == S_OK, "got 0x%08x\n", hr);
2418  ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2419  SysFreeString(str);
2420 
2421  /* name is returned for first position within a range */
2422  SendMessageA(hwnd, EM_SETSEL, 0, 1);
2424  ok(ret, "got %d\n", ret);
2425 
2426  str = NULL;
2427  hr = ITextFont_GetName(font, &str);
2428  ok(hr == S_OK, "got 0x%08x\n", hr);
2429  ok(!lstrcmpW(str, arialW), "got %s\n", wine_dbgstr_w(str));
2430  SysFreeString(str);
2431 
2432  /* GetDuplicate() */
2433  hr = ITextFont_GetDuplicate(font, NULL);
2434  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2435 
2436  EXPECT_REF(range, 2);
2437  font2 = NULL;
2438  hr = ITextFont_GetDuplicate(font, &font2);
2439  ok(hr == S_OK, "got 0x%08x\n", hr);
2440  EXPECT_REF(range, 2);
2441 
2442  /* set whole range to italic */
2443  cf.cbSize = sizeof(CHARFORMAT2A);
2444  cf.dwMask = CFM_ITALIC;
2445  cf.dwEffects = CFE_ITALIC;
2446 
2447  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2449  ok(ret, "got %d\n", ret);
2450 
2451  value = tomFalse;
2452  hr = ITextFont_GetItalic(font, &value);
2453  ok(hr == S_OK, "got 0x%08x\n", hr);
2454  ok(value == tomTrue, "got %d\n", value);
2455 
2456  /* duplicate retains original value */
2457  value = tomTrue;
2458  hr = ITextFont_GetItalic(font2, &value);
2459  ok(hr == S_OK, "got 0x%08x\n", hr);
2460  ok(value == tomFalse, "got %d\n", value);
2461 
2462  /* get a duplicate from a cloned font */
2463  hr = ITextFont_GetDuplicate(font2, &font3);
2464  ok(hr == S_OK, "got 0x%08x\n", hr);
2465  ITextFont_Release(font3);
2466 
2467  ITextRange_Release(range);
2468  release_interfaces(&hwnd, &reOle, &doc, NULL);
2469 
2470  hr = ITextFont_GetDuplicate(font, NULL);
2471  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2472 
2475 
2476  /* get a duplicate of detached font */
2477  hr = ITextFont_GetDuplicate(font2, &font3);
2478  ok(hr == S_OK, "got 0x%08x\n", hr);
2479  ITextFont_Release(font3);
2480 
2481  /* reset detached font to undefined */
2482  value = tomUndefined;
2483  hr = ITextFont_GetBold(font2, &value);
2484  ok(hr == S_OK, "got 0x%08x\n", hr);
2485  ok(value != tomUndefined, "got %d\n", value);
2486 
2487  /* reset to undefined for detached font */
2488  hr = ITextFont_Reset(font2, tomUndefined);
2489  ok(hr == S_OK, "got 0x%08x\n", hr);
2490  test_textfont_undefined(font2);
2491 
2492  /* font is detached, default means global TOM defaults */
2493  hr = ITextFont_Reset(font2, tomDefault);
2494  ok(hr == S_OK, "got 0x%08x\n", hr);
2496 
2497  hr = ITextFont_GetDuplicate(font2, &font3);
2498  ok(hr == S_OK, "got 0x%08x\n", hr);
2500 
2501  hr = ITextFont_Reset(font2, tomApplyNow);
2502  ok(hr == S_OK, "got 0x%08x\n", hr);
2504 
2505  hr = ITextFont_Reset(font2, tomApplyLater);
2506  ok(hr == S_OK, "got 0x%08x\n", hr);
2508 
2509  hr = ITextFont_Reset(font2, tomTrackParms);
2510  ok(hr == S_OK, "got 0x%08x\n", hr);
2512 
2513  hr = ITextFont_SetItalic(font2, tomUndefined);
2514  ok(hr == S_OK, "got 0x%08x\n", hr);
2515 
2516  hr = ITextFont_GetItalic(font2, &value);
2517  ok(hr == S_OK, "got 0x%08x\n", hr);
2518  ok(value == tomFalse, "got %d\n", value);
2519 
2520  hr = ITextFont_Reset(font2, tomCacheParms);
2521  ok(hr == S_OK, "got 0x%08x\n", hr);
2523 
2524  ITextFont_Release(font3);
2525  ITextFont_Release(font2);
2526 
2527  font2 = (void*)0xdeadbeef;
2528  hr = ITextFont_GetDuplicate(font, &font2);
2529  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2530  ok(font2 == NULL, "got %p\n", font2);
2531 
2532  hr = ITextFont_Reset(font, tomDefault);
2533  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2534 
2535  ITextFont_Release(font);
2536 
2537  /* Reset() */
2538  create_interfaces(&hwnd, &reOle, &doc, NULL);
2539  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2540 
2541  hr = ITextDocument_Range(doc, 0, 10, &range);
2542  ok(hr == S_OK, "got 0x%08x\n", hr);
2543 
2544  hr = ITextRange_GetFont(range, &font);
2545  ok(hr == S_OK, "got 0x%08x\n", hr);
2546 
2547  value = tomUndefined;
2548  hr = ITextFont_GetBold(font, &value);
2549  ok(hr == S_OK, "got 0x%08x\n", hr);
2550  ok(value != tomUndefined, "got %d\n", value);
2551 
2552  /* reset to undefined for attached font */
2553  hr = ITextFont_Reset(font, tomUndefined);
2554  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2555 
2556  value = tomUndefined;
2557  hr = ITextFont_GetBold(font, &value);
2558  ok(hr == S_OK, "got 0x%08x\n", hr);
2559  ok(value != tomUndefined, "got %d\n", value);
2560 
2561  /* tomCacheParms/tomTrackParms */
2562  hr = ITextFont_Reset(font, tomCacheParms);
2563  ok(hr == S_OK, "got 0x%08x\n", hr);
2564 
2565  hr = ITextFont_GetItalic(font, &value);
2566  ok(hr == S_OK, "got 0x%08x\n", hr);
2567  ok(value == tomFalse, "got %d\n", value);
2568 
2569  memset(&cf, 0, sizeof(cf));
2570  cf.cbSize = sizeof(CHARFORMAT2A);
2571  cf.dwMask = CFM_ITALIC;
2572 
2573  cf.dwEffects = CFE_ITALIC;
2574  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2576  ok(ret, "got %d\n", ret);
2577 
2578  /* still cached value */
2579  hr = ITextFont_GetItalic(font, &value);
2580  ok(hr == S_OK, "got 0x%08x\n", hr);
2581  ok(value == tomFalse, "got %d\n", value);
2582 
2583  hr = ITextFont_Reset(font, tomTrackParms);
2584  ok(hr == S_OK, "got 0x%08x\n", hr);
2585 
2586  hr = ITextFont_GetItalic(font, &value);
2587  ok(hr == S_OK, "got 0x%08x\n", hr);
2588  ok(value == tomTrue, "got %d\n", value);
2589 
2590  /* switch back to cache - value retained */
2591  hr = ITextFont_Reset(font, tomCacheParms);
2592  ok(hr == S_OK, "got 0x%08x\n", hr);
2593 
2594  hr = ITextFont_GetItalic(font, &value);
2595  ok(hr == S_OK, "got 0x%08x\n", hr);
2596  ok(value == tomTrue, "got %d\n", value);
2597 
2598  /* tomApplyLater */
2599  hr = ITextFont_Reset(font, tomApplyLater);
2600  ok(hr == S_OK, "got 0x%08x\n", hr);
2601 
2602  hr = ITextFont_SetItalic(font, tomFalse);
2603  ok(hr == S_OK, "got 0x%08x\n", hr);
2604 
2605  hr = ITextFont_GetItalic(font, &value);
2606  ok(hr == S_OK, "got 0x%08x\n", hr);
2607  ok(value == tomFalse, "got %d\n", value);
2608 
2609  cf.dwEffects = 0;
2610  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2612  ok(ret, "got %d\n", ret);
2613  ok((cf.dwEffects & CFE_ITALIC) == CFE_ITALIC, "got 0x%08x\n", cf.dwEffects);
2614 
2615  hr = ITextFont_Reset(font, tomApplyNow);
2616  ok(hr == S_OK, "got 0x%08x\n", hr);
2617 
2618  cf.dwEffects = 0;
2619  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2621  ok(ret, "got %d\n", ret);
2622  ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2623 
2624  hr = ITextFont_SetItalic(font, tomUndefined);
2625  ok(hr == S_OK, "got 0x%08x\n", hr);
2626 
2627  hr = ITextFont_GetItalic(font, &value);
2628  ok(hr == S_OK, "got 0x%08x\n", hr);
2629  ok(value == tomFalse, "got %d\n", value);
2630 
2631  hr = ITextFont_SetItalic(font, tomAutoColor);
2632  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2633 
2634  cf.dwEffects = 0;
2635  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2637  ok(ret, "got %d\n", ret);
2638  ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2639 
2640  ITextRange_Release(range);
2641  ITextFont_Release(font);
2642  release_interfaces(&hwnd, &reOle, &doc, NULL);
2643 }
2644 
2645 static void test_Delete(void)
2646 {
2647  static const CHAR test_text1[] = "TestSomeText";
2648  IRichEditOle *reOle = NULL;
2649  ITextDocument *doc = NULL;
2650  ITextRange *range, *range2;
2651  LONG value;
2652  HRESULT hr;
2653  HWND hwnd;
2654 
2655  create_interfaces(&hwnd, &reOle, &doc, NULL);
2656  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2657 
2658  hr = ITextDocument_Range(doc, 0, 4, &range);
2659  ok(hr == S_OK, "got 0x%08x\n", hr);
2660 
2661  hr = ITextDocument_Range(doc, 1, 2, &range2);
2662  ok(hr == S_OK, "got 0x%08x\n", hr);
2663 
2664  hr = ITextRange_GetEnd(range, &value);
2665  ok(hr == S_OK, "got 0x%08x\n", hr);
2666  ok(value == 4, "got %d\n", value);
2667 
2668  /* unit type doesn't matter is count is 0 */
2669  value = 0;
2670  hr = ITextRange_Delete(range2, tomSentence, 0, &value);
2671 todo_wine {
2672  ok(hr == S_OK, "got 0x%08x\n", hr);
2673  ok(value == 1, "got %d\n", value);
2674 }
2675  value = 1;
2676  hr = ITextRange_Delete(range2, tomCharacter, 0, &value);
2677 todo_wine {
2678  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2679  ok(value == 0, "got %d\n", value);
2680 }
2681  hr = ITextRange_GetEnd(range, &value);
2682  ok(hr == S_OK, "got 0x%08x\n", hr);
2683 todo_wine
2684  ok(value == 3, "got %d\n", value);
2685 
2686  hr = ITextRange_GetStart(range2, &value);
2687  ok(hr == S_OK, "got 0x%08x\n", hr);
2688  ok(value == 1, "got %d\n", value);
2689 
2690  hr = ITextRange_GetEnd(range2, &value);
2691  ok(hr == S_OK, "got 0x%08x\n", hr);
2692 todo_wine
2693  ok(value == 1, "got %d\n", value);
2694 
2695  ITextRange_Release(range);
2696  ITextRange_Release(range2);
2697  release_interfaces(&hwnd, &reOle, &doc, NULL);
2698 }
2699 
2700 static void test_SetText(void)
2701 {
2702  static const CHAR test_text1[] = "TestSomeText";
2703  static const WCHAR textW[] = {'a','b','c','d','e','f','g','h','i',0};
2704  IRichEditOle *reOle = NULL;
2705  ITextDocument *doc = NULL;
2706  ITextRange *range, *range2;
2707  LONG value;
2708  HRESULT hr;
2709  HWND hwnd;
2710  BSTR str;
2711 
2712  create_interfaces(&hwnd, &reOle, &doc, NULL);
2713  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2714 
2715  hr = ITextDocument_Range(doc, 0, 4, &range);
2716  ok(hr == S_OK, "got 0x%08x\n", hr);
2717 
2718  hr = ITextDocument_Range(doc, 0, 4, &range2);
2719  ok(hr == S_OK, "got 0x%08x\n", hr);
2720 
2721  value = 1;
2722  hr = ITextRange_GetStart(range2, &value);
2723  ok(hr == S_OK, "got 0x%08x\n", hr);
2724  ok(value == 0, "got %d\n", value);
2725 
2726  value = 0;
2727  hr = ITextRange_GetEnd(range2, &value);
2728  ok(hr == S_OK, "got 0x%08x\n", hr);
2729  ok(value == 4, "got %d\n", value);
2730 
2731  hr = ITextRange_SetText(range, NULL);
2732  ok(hr == S_OK, "got 0x%08x\n", hr);
2733 
2734  value = 1;
2735  hr = ITextRange_GetEnd(range2, &value);
2736  ok(hr == S_OK, "got 0x%08x\n", hr);
2737  ok(value == 0, "got %d\n", value);
2738 
2740  hr = ITextRange_SetText(range, str);
2741  ok(hr == S_OK, "got 0x%08x\n", hr);
2742  SysFreeString(str);
2743 
2744  value = 1;
2745  hr = ITextRange_GetStart(range, &value);
2746  ok(hr == S_OK, "got 0x%08x\n", hr);
2747  ok(value == 0, "got %d\n", value);
2748 
2749  value = 0;
2750  hr = ITextRange_GetEnd(range, &value);
2751  ok(hr == S_OK, "got 0x%08x\n", hr);
2752  ok(value == 9, "got %d\n", value);
2753 
2754  value = 1;
2755  hr = ITextRange_GetStart(range2, &value);
2756  ok(hr == S_OK, "got 0x%08x\n", hr);
2757  ok(value == 0, "got %d\n", value);
2758 
2759  value = 0;
2760  hr = ITextRange_GetEnd(range2, &value);
2761  ok(hr == S_OK, "got 0x%08x\n", hr);
2762  ok(value == 0, "got %d\n", value);
2763 
2764  str = SysAllocStringLen(NULL, 0);
2765  hr = ITextRange_SetText(range, str);
2766  ok(hr == S_OK, "got 0x%08x\n", hr);
2767  value = 1;
2768  hr = ITextRange_GetEnd(range, &value);
2769  ok(hr == S_OK, "got 0x%08x\n", hr);
2770  ok(value == 0, "got %d\n", value);
2771  SysFreeString(str);
2772 
2773  ITextRange_Release(range2);
2774  release_interfaces(&hwnd, &reOle, &doc, NULL);
2775 
2776  hr = ITextRange_SetText(range, NULL);
2777  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2778 
2779  str = SysAllocStringLen(NULL, 0);
2780  hr = ITextRange_SetText(range, str);
2781  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2782  SysFreeString(str);
2783 
2784  ITextRange_Release(range);
2785 }
2786 
2787 static void test_InRange(void)
2788 {
2789  static const CHAR test_text1[] = "TestSomeText";
2790  ITextRange *range, *range2, *range3;
2791  IRichEditOle *reOle = NULL;
2792  ITextDocument *doc = NULL;
2794  LONG value;
2795  HRESULT hr;
2796  HWND hwnd;
2797 
2798  create_interfaces(&hwnd, &reOle, &doc, &selection);
2799  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2800  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2801 
2802  hr = ITextDocument_Range(doc, 0, 4, &range);
2803  ok(hr == S_OK, "got 0x%08x\n", hr);
2804 
2805  hr = ITextDocument_Range(doc, 0, 4, &range2);
2806  ok(hr == S_OK, "got 0x%08x\n", hr);
2807 
2808  /* matches selection */
2809  hr = ITextDocument_Range(doc, 1, 2, &range3);
2810  ok(hr == S_OK, "got 0x%08x\n", hr);
2811 
2812  hr = ITextRange_InRange(range, NULL, NULL);
2813  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2814 
2815  value = tomTrue;
2816  hr = ITextRange_InRange(range, NULL, &value);
2817  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2818  ok(value == tomFalse, "got %d\n", value);
2819 
2820  hr = ITextRange_InRange(range, range2, NULL);
2821  ok(hr == S_OK, "got 0x%08x\n", hr);
2822 
2823  value = tomFalse;
2824  hr = ITextRange_InRange(range, range2, &value);
2825  ok(hr == S_OK, "got 0x%08x\n", hr);
2826  ok(value == tomTrue, "got %d\n", value);
2827 
2828  /* selection */
2829  hr = ITextSelection_InRange(selection, NULL, NULL);
2830  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2831 
2832  value = tomTrue;
2833  hr = ITextSelection_InRange(selection, NULL, &value);
2834  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2835  ok(value == tomFalse, "got %d\n", value);
2836 
2837  hr = ITextSelection_InRange(selection, range2, NULL);
2838  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2839 
2840  value = tomTrue;
2841  hr = ITextSelection_InRange(selection, range2, &value);
2842  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2843  ok(value == tomFalse, "got %d\n", value);
2844 
2845  value = tomTrue;
2846  hr = ITextSelection_InRange(selection, range3, &value);
2847  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2848  ok(value == tomFalse, "got %d\n", value);
2849 
2850  /* seems to work on ITextSelection ranges only */
2851  value = tomFalse;
2852  hr = ITextSelection_InRange(selection, (ITextRange*)selection, &value);
2853  ok(hr == S_OK, "got 0x%08x\n", hr);
2854  ok(value == tomTrue, "got %d\n", value);
2855 
2856  release_interfaces(&hwnd, &reOle, &doc, NULL);
2857 
2858  hr = ITextRange_InRange(range, NULL, NULL);
2859  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2860 
2861  value = tomTrue;
2862  hr = ITextRange_InRange(range, NULL, &value);
2863  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2864  ok(value == tomFalse, "got %d\n", value);
2865 
2866  hr = ITextRange_InRange(range, range2, NULL);
2867  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2868 
2869  value = tomTrue;
2870  hr = ITextRange_InRange(range, range2, &value);
2871  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2872  ok(value == tomFalse, "got %d\n", value);
2873 
2874  /* selection */
2875  hr = ITextSelection_InRange(selection, NULL, NULL);
2876  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2877 
2878  value = tomTrue;
2879  hr = ITextSelection_InRange(selection, NULL, &value);
2880  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2881  ok(value == tomFalse, "got %d\n", value);
2882 
2883  hr = ITextSelection_InRange(selection, range2, NULL);
2884  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2885 
2886  value = tomTrue;
2887  hr = ITextSelection_InRange(selection, range2, &value);
2888  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2889  ok(value == tomFalse, "got %d\n", value);
2890 
2891  ITextRange_Release(range);
2892  ITextRange_Release(range2);
2893  ITextRange_Release(range3);
2894  ITextSelection_Release(selection);
2895 }
2896 
2897 static void test_ITextRange_IsEqual(void)
2898 {
2899  static const CHAR test_text1[] = "TestSomeText";
2900  ITextRange *range, *range2, *range3;
2901  IRichEditOle *reOle = NULL;
2902  ITextDocument *doc = NULL;
2904  LONG value;
2905  HRESULT hr;
2906  HWND hwnd;
2907 
2908  create_interfaces(&hwnd, &reOle, &doc, &selection);
2909  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2910  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2911 
2912  hr = ITextDocument_Range(doc, 0, 4, &range);
2913  ok(hr == S_OK, "got 0x%08x\n", hr);
2914 
2915  hr = ITextDocument_Range(doc, 0, 4, &range2);
2916  ok(hr == S_OK, "got 0x%08x\n", hr);
2917 
2918  /* matches selection */
2919  hr = ITextDocument_Range(doc, 1, 2, &range3);
2920  ok(hr == S_OK, "got 0x%08x\n", hr);
2921 
2922  hr = ITextRange_IsEqual(range, NULL, NULL);
2923  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2924 
2925  value = tomTrue;
2926  hr = ITextRange_IsEqual(range, NULL, &value);
2927  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2928  ok(value == tomFalse, "got %d\n", value);
2929 
2930  hr = ITextRange_IsEqual(range, range2, NULL);
2931  ok(hr == S_OK, "got 0x%08x\n", hr);
2932 
2933  value = tomFalse;
2934  hr = ITextRange_IsEqual(range, range2, &value);
2935  ok(hr == S_OK, "got 0x%08x\n", hr);
2936  ok(value == tomTrue, "got %d\n", value);
2937 
2938  value = tomTrue;
2939  hr = ITextRange_IsEqual(range, range3, &value);
2940  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2941  ok(value == tomFalse, "got %d\n", value);
2942 
2943  /* selection */
2944  hr = ITextSelection_IsEqual(selection, NULL, NULL);
2945  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2946 
2947  value = tomTrue;
2948  hr = ITextSelection_IsEqual(selection, NULL, &value);
2949  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2950  ok(value == tomFalse, "got %d\n", value);
2951 
2952  hr = ITextSelection_IsEqual(selection, range2, NULL);
2953  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2954 
2955  value = tomTrue;
2956  hr = ITextSelection_IsEqual(selection, range2, &value);
2957  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2958  ok(value == tomFalse, "got %d\n", value);
2959 
2960  value = tomTrue;
2961  hr = ITextSelection_IsEqual(selection, range3, &value);
2962  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2963  ok(value == tomFalse, "got %d\n", value);
2964 
2965  /* seems to work on ITextSelection ranges only */
2966  value = tomFalse;
2967  hr = ITextSelection_IsEqual(selection, (ITextRange*)selection, &value);
2968  ok(hr == S_OK, "got 0x%08x\n", hr);
2969  ok(value == tomTrue, "got %d\n", value);
2970 
2971  release_interfaces(&hwnd, &reOle, &doc, NULL);
2972 
2973  hr = ITextRange_IsEqual(range, NULL, NULL);
2974  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2975 
2976  value = tomTrue;
2977  hr = ITextRange_IsEqual(range, NULL, &value);
2978  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2979  ok(value == tomFalse, "got %d\n", value);
2980 
2981  hr = ITextRange_IsEqual(range, range2, NULL);
2982  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2983 
2984  value = tomTrue;
2985  hr = ITextRange_IsEqual(range, range2, &value);
2986  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2987  ok(value == tomFalse, "got %d\n", value);
2988 
2989  /* selection */
2990  hr = ITextSelection_IsEqual(selection, NULL, NULL);
2991  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2992 
2993  value = tomTrue;
2994  hr = ITextSelection_IsEqual(selection, NULL, &value);
2995  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2996  ok(value == tomFalse, "got %d\n", value);
2997 
2998  hr = ITextSelection_IsEqual(selection, range2, NULL);
2999  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3000 
3001  value = tomTrue;
3002  hr = ITextSelection_IsEqual(selection, range2, &value);
3003  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3004  ok(value == tomFalse, "got %d\n", value);
3005 
3006  ITextRange_Release(range);
3007  ITextRange_Release(range2);
3008  ITextRange_Release(range3);
3009  ITextSelection_Release(selection);
3010 }
3011 
3012 static void test_Select(void)
3013 {
3014  static const CHAR test_text1[] = "TestSomeText";
3015  IRichEditOle *reOle = NULL;
3016  ITextDocument *doc = NULL;
3018  ITextRange *range;
3019  LONG value;
3020  HRESULT hr;
3021  HWND hwnd;
3022 
3023  create_interfaces(&hwnd, &reOle, &doc, &selection);
3024  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3025  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3026 
3027  hr = ITextDocument_Range(doc, 0, 4, &range);
3028  ok(hr == S_OK, "got 0x%08x\n", hr);
3029 
3030  hr = ITextRange_Select(range);
3031  ok(hr == S_OK, "got 0x%08x\n", hr);
3032 
3033  value = 1;
3034  hr = ITextSelection_GetStart(selection, &value);
3035  ok(hr == S_OK, "got 0x%08x\n", hr);
3036  ok(value == 0, "got %d\n", value);
3037 
3038  hr = ITextRange_Select(range);
3039  ok(hr == S_OK, "got 0x%08x\n", hr);
3040 
3041  hr = ITextSelection_Select(selection);
3042  ok(hr == S_OK, "got 0x%08x\n", hr);
3043 
3044  release_interfaces(&hwnd, &reOle, &doc, NULL);
3045 
3046  hr = ITextRange_Select(range);
3047  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3048 
3049  hr = ITextSelection_Select(selection);
3050  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3051 
3052  ITextRange_Release(range);
3053  ITextSelection_Release(selection);
3054 }
3055 
3056 static void test_GetStoryType(void)
3057 {
3058  static const CHAR test_text1[] = "TestSomeText";
3059  IRichEditOle *reOle = NULL;
3060  ITextDocument *doc = NULL;
3062  ITextRange *range;
3063  LONG value;
3064  HRESULT hr;
3065  HWND hwnd;
3066 
3067  create_interfaces(&hwnd, &reOle, &doc, &selection);
3068  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3069  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3070 
3071  hr = ITextDocument_Range(doc, 0, 4, &range);
3072  ok(hr == S_OK, "got 0x%08x\n", hr);
3073 
3074  hr = ITextRange_GetStoryType(range, NULL);
3075  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3076 
3078  hr = ITextRange_GetStoryType(range, &value);
3079  ok(hr == S_OK, "got 0x%08x\n", hr);
3080  ok(value == tomUnknownStory, "got %d\n", value);
3081 
3082  hr = ITextSelection_GetStoryType(selection, NULL);
3083  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3084 
3086  hr = ITextSelection_GetStoryType(selection, &value);
3087  ok(hr == S_OK, "got 0x%08x\n", hr);
3088  ok(value == tomUnknownStory, "got %d\n", value);
3089 
3090  release_interfaces(&hwnd, &reOle, &doc, NULL);
3091 
3092  hr = ITextRange_GetStoryType(range, NULL);
3093  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3094 
3095  value = 123;
3096  hr = ITextRange_GetStoryType(range, &value);
3097  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3098  ok(value == 123, "got %d\n", value);
3099 
3100  hr = ITextSelection_GetStoryType(selection, NULL);
3101  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3102 
3103  value = 123;
3104  hr = ITextSelection_GetStoryType(selection, &value);
3105  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3106  ok(value == 123, "got %d\n", value);
3107 
3108  ITextRange_Release(range);
3109  ITextSelection_Release(selection);
3110 }
3111 
3112 static void test_SetFont(void)
3113 {
3114  static const CHAR test_text1[] = "TestSomeText";
3115  IRichEditOle *reOle = NULL;
3116  ITextDocument *doc = NULL;
3118  ITextRange *range, *range2;
3119  ITextFont *font, *font2;
3120  LONG value;
3121  HRESULT hr;
3122  HWND hwnd;
3123 
3124  create_interfaces(&hwnd, &reOle, &doc, &selection);
3125  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3126  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3127 
3128  hr = ITextDocument_Range(doc, 0, 4, &range);
3129  ok(hr == S_OK, "got 0x%08x\n", hr);
3130 
3131  hr = ITextDocument_Range(doc, 5, 2, &range2);
3132  ok(hr == S_OK, "got 0x%08x\n", hr);
3133 
3134  EXPECT_REF(range, 1);
3135  hr = ITextRange_GetFont(range, &font);
3136  ok(hr == S_OK, "got 0x%08x\n", hr);
3137  EXPECT_REF(range, 2);
3138 
3139  EXPECT_REF(range2, 1);
3140  hr = ITextRange_GetFont(range2, &font2);
3141  ok(hr == S_OK, "got 0x%08x\n", hr);
3142  EXPECT_REF(range2, 2);
3143 
3144  hr = ITextRange_SetFont(range, NULL);
3145  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3146 
3147  /* setting same font, no-op */
3148  EXPECT_REF(range, 2);
3149  hr = ITextRange_SetFont(range, font);
3150  ok(hr == S_OK, "got 0x%08x\n", hr);
3151  EXPECT_REF(range, 2);
3152 
3153  EXPECT_REF(range2, 2);
3154  EXPECT_REF(range, 2);
3155  hr = ITextRange_SetFont(range, font2);
3156  ok(hr == S_OK, "got 0x%08x\n", hr);
3157  EXPECT_REF(range2, 2);
3158  EXPECT_REF(range, 2);
3159 
3160  /* originally range 0-4 is non-italic */
3161  value = tomTrue;
3162  hr = ITextFont_GetItalic(font, &value);
3163  ok(hr == S_OK, "got 0x%08x\n", hr);
3164  ok(value == tomFalse, "got %d\n", value);
3165 
3166  /* set range 5-2 to italic, then set this font to range 0-4 */
3167  hr = ITextFont_SetItalic(font2, tomTrue);
3168  ok(hr == S_OK, "got 0x%08x\n", hr);
3169 
3170  hr = ITextRange_SetFont(range, font2);
3171  ok(hr == S_OK, "got 0x%08x\n", hr);
3172 
3173  value = tomFalse;
3174  hr = ITextFont_GetItalic(font, &value);
3175  ok(hr == S_OK, "got 0x%08x\n", hr);
3176  ok(value == tomTrue, "got %d\n", value);
3177 
3178  release_interfaces(&hwnd, &reOle, &doc, NULL);
3179 
3180  hr = ITextRange_SetFont(range, NULL);
3181  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3182 
3183  hr = ITextRange_SetFont(range, font);
3184  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3185 
3186  hr = ITextSelection_SetFont(selection, NULL);
3187  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3188 
3189  hr = ITextSelection_SetFont(selection, font);
3190  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3191 
3192  ITextFont_Release(font);
3193  ITextFont_Release(font2);
3194  ITextRange_Release(range);
3195  ITextRange_Release(range2);
3196  ITextSelection_Release(selection);
3197 }
3198 
3199 static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
3200  LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
3201  LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
3202 {
3203  reobj->cbStruct = sizeof(*reobj);
3204  reobj->clsid = CLSID_NULL;
3205  reobj->cp = cp;
3206  reobj->poleobj = poleobj;
3207  reobj->pstg = pstg;
3208  reobj->polesite = polesite;
3209  reobj->sizel.cx = sizel_cx;
3210  reobj->sizel.cy = sizel_cy;
3211  reobj->dvaspect = aspect;
3212  reobj->dwFlags = flags;
3213  reobj->dwUser = user;
3214 }
3215 
3216 #define CHECK_REOBJECT_STRUCT(reobj,poleobj,pstg,polesite,user) \
3217  _check_reobject_struct(reobj, poleobj, pstg, polesite, user, __LINE__)
3218 static void _check_reobject_struct(REOBJECT reobj, LPOLEOBJECT poleobj, LPSTORAGE pstg,
3219  LPOLECLIENTSITE polesite, DWORD user, int line)
3220 {
3221  ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n");
3222  ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n");
3223  ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n");
3224  ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
3225 }
3226 
3227 static void test_InsertObject(void)
3228 {
3229  static CHAR test_text1[] = "abcdefg";
3230  IRichEditOle *reole = NULL;
3231  ITextDocument *doc = NULL;
3232  IOleClientSite *clientsite;
3233  REOBJECT reo1, reo2, reo3, received_reo1, received_reo2, received_reo3, received_reo4;
3234  HRESULT hr;
3235  HWND hwnd;
3236  LONG count;
3237 
3238  create_interfaces(&hwnd, &reole, &doc, NULL);
3239  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3240 
3241  hr = IRichEditOle_InsertObject(reole, NULL);
3242  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3243 
3244  /* insert object1 in (0, 1)*/
3245  SendMessageA(hwnd, EM_SETSEL, 0, 1);
3246  hr = IRichEditOle_GetClientSite(reole, &clientsite);
3247  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3248  fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1);
3249  hr = IRichEditOle_InsertObject(reole, &reo1);
3250  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3251  count = IRichEditOle_GetObjectCount(reole);
3252  ok(count == 1, "got wrong object count: %d\n", count);
3253  IOleClientSite_Release(clientsite);
3254 
3255  /* insert object2 in (2, 3)*/
3256  SendMessageA(hwnd, EM_SETSEL, 2, 3);
3257  hr = IRichEditOle_GetClientSite(reole, &clientsite);
3258  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3259  fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 2);
3260  hr = IRichEditOle_InsertObject(reole, &reo2);
3261  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3262  count = IRichEditOle_GetObjectCount(reole);
3263  ok(count == 2, "got wrong object count: %d\n", count);
3264  IOleClientSite_Release(clientsite);
3265 
3266  /* insert object3 in (1, 2)*/
3267  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3268  hr = IRichEditOle_GetClientSite(reole, &clientsite);
3269  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3270  fill_reobject_struct(&reo3, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 3);
3271  hr = IRichEditOle_InsertObject(reole, &reo3);
3272  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3273  count = IRichEditOle_GetObjectCount(reole);
3274  ok(count == 3, "got wrong object count: %d\n", count);
3275  IOleClientSite_Release(clientsite);
3276 
3277  /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
3278  received_reo1.cbStruct = sizeof(received_reo1);
3279  hr = IRichEditOle_GetObject(reole, 0, &received_reo1, REO_GETOBJ_ALL_INTERFACES);
3280  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3281  CHECK_REOBJECT_STRUCT(received_reo1, NULL, NULL, reo1.polesite, 1);
3282 
3283  received_reo2.cbStruct = sizeof(received_reo2);
3284  hr = IRichEditOle_GetObject(reole, 1, &received_reo2, REO_GETOBJ_ALL_INTERFACES);
3285  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3286  CHECK_REOBJECT_STRUCT(received_reo2, NULL, NULL, reo3.polesite, 3);
3287 
3288  received_reo3.cbStruct = sizeof(received_reo3);
3289  hr = IRichEditOle_GetObject(reole, 2, &received_reo3, REO_GETOBJ_ALL_INTERFACES);
3290  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3291  CHECK_REOBJECT_STRUCT(received_reo3, NULL, NULL, reo2.polesite, 2);
3292 
3293  hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES);
3294  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3295 
3296  received_reo4.cbStruct = 0;
3297  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3298  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3299 
3300  received_reo4.cbStruct = sizeof(received_reo4);
3301  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_PSTG);
3302  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3303  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
3304 
3305  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_POLESITE);
3306  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3307  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3308 
3309  hr = IRichEditOle_GetObject(reole, 4, &received_reo4, REO_GETOBJ_POLESITE);
3310  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3311 
3312  hr = IRichEditOle_GetObject(reole, 1024, &received_reo4, REO_GETOBJ_POLESITE);
3313  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3314 
3315  /* received_reo4 will be zeroed before be used */
3316  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_NO_INTERFACES);
3317  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3318