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