2 * Tests for IRichEditOle and friends.
4 * Copyright 2008 Google (Dan Hipschman)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include <wine/test.h>
36 static HMODULE hmoduleRichEdit
;
38 static HWND
new_window(LPCSTR lpClassName
, DWORD dwStyle
, HWND parent
)
40 HWND hwnd
= CreateWindowA(lpClassName
, NULL
,
41 dwStyle
| WS_POPUP
| WS_HSCROLL
| WS_VSCROLL
| WS_VISIBLE
,
42 0, 0, 200, 60, parent
, NULL
, hmoduleRichEdit
, NULL
);
46 static HWND
new_richedit(HWND parent
)
48 return new_window(RICHEDIT_CLASS20A
, ES_MULTILINE
, parent
);
51 static BOOL
touch_file(LPCWSTR filename
)
55 file
= CreateFileW(filename
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
56 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
58 if(file
== INVALID_HANDLE_VALUE
)
64 static BOOL
is_existing_file(LPCWSTR filename
)
68 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
,
69 OPEN_EXISTING
, 0, NULL
);
70 if(file
== INVALID_HANDLE_VALUE
)
76 static void create_interfaces(HWND
*w
, IRichEditOle
**reOle
, ITextDocument
**txtDoc
,
77 ITextSelection
**txtSel
)
79 *w
= new_richedit(NULL
);
80 SendMessageA(*w
, EM_GETOLEINTERFACE
, 0, (LPARAM
)reOle
);
81 IRichEditOle_QueryInterface(*reOle
, &IID_ITextDocument
,
83 ITextDocument_GetSelection(*txtDoc
, txtSel
);
86 static void release_interfaces(HWND
*w
, IRichEditOle
**reOle
, ITextDocument
**txtDoc
,
87 ITextSelection
**txtSel
)
90 ITextSelection_Release(*txtSel
);
91 ITextDocument_Release(*txtDoc
);
92 IRichEditOle_Release(*reOle
);
96 static ULONG
get_refcount(IUnknown
*iface
)
98 IUnknown_AddRef(iface
);
99 return IUnknown_Release(iface
);
102 static void test_Interfaces(void)
104 IRichEditOle
*reOle
= NULL
, *reOle1
= NULL
;
105 ITextDocument
*txtDoc
= NULL
;
106 ITextSelection
*txtSel
= NULL
;
113 w
= new_richedit(NULL
);
115 skip("Couldn't create window\n");
119 res
= SendMessageA(w
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&reOle
);
120 ok(res
, "SendMessage\n");
121 ok(reOle
!= NULL
, "EM_GETOLEINTERFACE\n");
122 refcount
= get_refcount((IUnknown
*)reOle
);
123 ok(refcount
== 2, "got wrong ref count: %d\n", refcount
);
125 res
= SendMessageA(w
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&reOle1
);
126 ok(res
== 1, "SendMessage\n");
127 ok(reOle1
== reOle
, "Should not return a new IRichEditOle interface\n");
128 refcount
= get_refcount((IUnknown
*)reOle
);
129 ok(refcount
== 3, "got wrong ref count: %d\n", refcount
);
131 hres
= IRichEditOle_QueryInterface(reOle
, &IID_ITextDocument
,
133 ok(hres
== S_OK
, "IRichEditOle_QueryInterface\n");
134 ok(txtDoc
!= NULL
, "IRichEditOle_QueryInterface\n");
136 hres
= ITextDocument_GetSelection(txtDoc
, NULL
);
137 ok(hres
== E_INVALIDARG
, "ITextDocument_GetSelection: 0x%x\n", hres
);
139 ITextDocument_GetSelection(txtDoc
, &txtSel
);
142 hres
= ITextSelection_QueryInterface(txtSel
, &IID_ITextSelection
, (void **) &punk
);
143 ok(hres
== S_OK
, "ITextSelection_QueryInterface\n");
144 ok(punk
!= NULL
, "ITextSelection_QueryInterface\n");
145 IUnknown_Release(punk
);
148 hres
= ITextSelection_QueryInterface(txtSel
, &IID_ITextRange
, (void **) &punk
);
149 ok(hres
== S_OK
, "ITextSelection_QueryInterface\n");
150 ok(punk
!= NULL
, "ITextSelection_QueryInterface\n");
151 IUnknown_Release(punk
);
154 hres
= ITextSelection_QueryInterface(txtSel
, &IID_IDispatch
, (void **) &punk
);
155 ok(hres
== S_OK
, "ITextSelection_QueryInterface\n");
156 ok(punk
!= NULL
, "ITextSelection_QueryInterface\n");
157 IUnknown_Release(punk
);
159 ITextDocument_Release(txtDoc
);
160 IRichEditOle_Release(reOle
);
161 refcount
= IRichEditOle_Release(reOle
);
162 ok(refcount
== 1, "got wrong ref count: %d\n", refcount
);
165 /* Methods should return CO_E_RELEASED if the backing document has
166 been released. One test should suffice. */
167 hres
= ITextSelection_CanEdit(txtSel
, NULL
);
168 ok(hres
== CO_E_RELEASED
, "ITextSelection after ITextDocument destroyed\n");
170 ITextSelection_Release(txtSel
);
173 static void test_ITextDocument_Open(void)
175 IRichEditOle
*reOle
= NULL
;
176 ITextDocument
*txtDoc
= NULL
;
177 ITextSelection
*txtSel
= NULL
;
182 WCHAR filename
[] = {'t', 'e', 's', 't','.','t','x','t', 0};
185 static const CHAR chACP
[] = "TestSomeText";
186 static const CHAR chUTF8
[] = "\xef\xbb\xbfTextWithUTF8BOM";
187 static const WCHAR chUTF16
[] = {0xfeff, 'T', 'e', 's', 't', 'S', 'o', 'm',
188 'e', 'T', 'e', 'x', 't', 0};
190 #define MAX_BUF_LEN 1024
191 CHAR bufACP
[MAX_BUF_LEN
];
192 WCHAR bufUnicode
[MAX_BUF_LEN
];
194 static const int tomConstantsSingle
[] =
196 tomReadOnly
, tomShareDenyRead
, tomShareDenyWrite
,
197 tomCreateAlways
, tomOpenExisting
, tomOpenAlways
,
198 tomTruncateExisting
, tomRTF
, tomText
201 static const int tomConstantsMulti
[] =
203 tomReadOnly
|tomShareDenyRead
|tomPasteFile
, tomReadOnly
|tomPasteFile
,
204 tomReadOnly
|tomShareDenyWrite
|tomPasteFile
,
205 tomReadOnly
|tomShareDenyRead
|tomShareDenyWrite
|tomPasteFile
, tomShareDenyWrite
|tomPasteFile
,
206 tomShareDenyRead
|tomShareDenyWrite
|tomPasteFile
, tomShareDenyRead
|tomPasteFile
,
207 tomShareDenyRead
|tomShareDenyWrite
, tomReadOnly
|tomShareDenyRead
|tomShareDenyWrite
,
208 tomReadOnly
|tomShareDenyWrite
, tomReadOnly
|tomShareDenyRead
211 int tomNumSingle
= sizeof(tomConstantsSingle
)/sizeof(tomConstantsSingle
[0]);
212 int tomNumMulti
= sizeof(tomConstantsMulti
)/sizeof(tomConstantsMulti
[0]);
215 V_VT(&testfile
) = VT_BSTR
;
216 V_BSTR(&testfile
) = SysAllocString(filename
);
218 for(i
=0; i
< tomNumSingle
; i
++)
220 touch_file(filename
);
221 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
222 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsSingle
[i
], CP_ACP
);
223 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
224 tomConstantsSingle
[i
], hres
);
225 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
226 DeleteFileW(filename
);
228 touch_file(filename
);
229 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
230 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsSingle
[i
], CP_UTF8
);
231 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
232 tomConstantsSingle
[i
], hres
);
233 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
234 DeleteFileW(filename
);
237 for(i
=0; i
< tomNumMulti
; i
++)
239 touch_file(filename
);
240 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
241 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsMulti
[i
], CP_ACP
);
242 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
243 tomConstantsMulti
[i
], hres
);
244 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
245 DeleteFileW(filename
);
247 touch_file(filename
);
248 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
249 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsMulti
[i
], CP_UTF8
);
250 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
251 tomConstantsMulti
[i
], hres
);
252 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
253 DeleteFileW(filename
);
256 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
257 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateAlways
, CP_ACP
);
258 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_ACP\n");
259 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
260 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
261 DeleteFileW(filename
);
263 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
264 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateAlways
, CP_UTF8
);
265 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_UTF8\n");
266 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
267 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
268 DeleteFileW(filename
);
270 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
271 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenAlways
, CP_ACP
);
272 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_ACP\n");
273 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
274 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
275 DeleteFileW(filename
);
277 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
278 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenAlways
, CP_UTF8
);
279 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_UTF8\n");
280 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
281 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
282 DeleteFileW(filename
);
284 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
285 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_ACP
);
286 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_ACP\n");
287 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
288 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
289 DeleteFileW(filename
);
291 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
292 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_UTF8
);
293 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_UTF8\n");
294 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
295 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
296 DeleteFileW(filename
);
298 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
299 touch_file(filename
);
300 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_ACP
);
301 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "ITextDocument_Open should fail Codepage:CP_ACP\n");
302 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
303 DeleteFileW(filename
);
305 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
306 touch_file(filename
);
307 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_UTF8
);
308 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
309 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
310 DeleteFileW(filename
);
312 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
313 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenExisting
, CP_ACP
);
314 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "ITextDocument_Open should fail Codepage:CP_ACP\n");
315 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
317 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
318 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenExisting
, CP_UTF8
);
319 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
320 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
322 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
323 DeleteFileW(filename
);
324 ITextDocument_Open(txtDoc
, &testfile
, tomText
, CP_ACP
);
325 todo_wine
ok(is_existing_file(filename
) == TRUE
, "a file should be created default\n");
326 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
327 DeleteFileW(filename
);
329 /* test of share mode */
330 touch_file(filename
);
331 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
332 ITextDocument_Open(txtDoc
, &testfile
, tomShareDenyRead
, CP_ACP
);
333 SetLastError(0xdeadbeef);
334 hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
,
335 FILE_ATTRIBUTE_NORMAL
, NULL
);
336 todo_wine
ok(GetLastError() == ERROR_SHARING_VIOLATION
, "ITextDocument_Open should fail\n");
338 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
339 DeleteFileW(filename
);
341 touch_file(filename
);
342 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
343 ITextDocument_Open(txtDoc
, &testfile
, tomShareDenyWrite
, CP_ACP
);
344 SetLastError(0xdeadbeef);
345 hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
,
346 FILE_ATTRIBUTE_NORMAL
, NULL
);
347 todo_wine
ok(GetLastError() == ERROR_SHARING_VIOLATION
, "ITextDocument_Open should fail\n");
349 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
350 DeleteFileW(filename
);
352 touch_file(filename
);
353 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
354 SetLastError(0xdeadbeef);
355 ITextDocument_Open(txtDoc
, &testfile
, tomShareDenyWrite
|tomShareDenyRead
, CP_ACP
);
356 hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
,
357 FILE_ATTRIBUTE_NORMAL
, NULL
);
358 todo_wine
ok(GetLastError() == ERROR_SHARING_VIOLATION
, "ITextDocument_Open should fail\n");
360 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
361 DeleteFileW(filename
);
363 /* tests to check the content */
364 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
365 FILE_ATTRIBUTE_NORMAL
, NULL
);
366 WriteFile(hFile
, chACP
, sizeof(chACP
)-sizeof(CHAR
), &dw
, NULL
);
368 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
369 ITextDocument_Open(txtDoc
, &testfile
, tomReadOnly
, CP_ACP
);
370 result
= SendMessageA(w
, WM_GETTEXT
, 1024, (LPARAM
)bufACP
);
371 todo_wine
ok(result
== 12, "ITextDocument_Open: Test ASCII returned %d, expected 12\n", result
);
372 result
= strcmp(bufACP
, chACP
);
373 todo_wine
ok(result
== 0, "ITextDocument_Open: Test ASCII set wrong text: Result: %s\n", bufACP
);
374 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
375 DeleteFileW(filename
);
377 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
378 FILE_ATTRIBUTE_NORMAL
, NULL
);
379 WriteFile(hFile
, chUTF8
, sizeof(chUTF8
)-sizeof(CHAR
), &dw
, NULL
);
381 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
382 ITextDocument_Open(txtDoc
, &testfile
, tomReadOnly
, CP_UTF8
);
383 result
= SendMessageA(w
, WM_GETTEXT
, 1024, (LPARAM
)bufACP
);
384 todo_wine
ok(result
== 15, "ITextDocument_Open: Test UTF-8 returned %d, expected 15\n", result
);
385 result
= strcmp(bufACP
, &chUTF8
[3]);
386 todo_wine
ok(result
== 0, "ITextDocument_Open: Test UTF-8 set wrong text: Result: %s\n", bufACP
);
387 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
388 DeleteFileW(filename
);
390 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
391 FILE_ATTRIBUTE_NORMAL
, NULL
);
392 WriteFile(hFile
, chUTF16
, sizeof(chUTF16
)-sizeof(WCHAR
), &dw
, NULL
);
394 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
395 ITextDocument_Open(txtDoc
, &testfile
, tomReadOnly
, 1200);
396 result
= SendMessageW(w
, WM_GETTEXT
, 1024, (LPARAM
)bufUnicode
);
397 todo_wine
ok(result
== 12, "ITextDocument_Open: Test UTF-16 returned %d, expected 12\n", result
);
398 result
= lstrcmpW(bufUnicode
, &chUTF16
[1]);
399 todo_wine
ok(result
== 0, "ITextDocument_Open: Test UTF-16 set wrong text: Result: %s\n", wine_dbgstr_w(bufUnicode
));
400 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
401 DeleteFileW(filename
);
403 VariantClear(&testfile
);
406 static void test_ITextSelection_GetText(void)
409 IRichEditOle
*reOle
= NULL
;
410 ITextDocument
*txtDoc
= NULL
;
411 ITextSelection
*txtSel
= NULL
;
415 static const CHAR test_text1
[] = "TestSomeText";
416 static const WCHAR bufW1
[] = {'T', 'e', 's', 't', 0};
417 static const WCHAR bufW2
[] = {'T', 'e', 'x', 't', '\r', 0};
418 static const WCHAR bufW3
[] = {'T', 'e', 'x', 't', 0};
419 static const WCHAR bufW4
[] = {'T', 'e', 's', 't', 'S', 'o', 'm',
420 'e', 'T', 'e', 'x', 't', '\r', 0};
421 static const WCHAR bufW5
[] = {'\r', 0};
422 BOOL is64bit
= sizeof(void *) > sizeof(int);
424 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
425 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
428 SendMessageA(w
, EM_SETSEL
, first
, lim
);
429 hres
= ITextSelection_GetText(txtSel
, &bstr
);
430 ok(hres
== S_OK
, "ITextSelection_GetText\n");
431 ok(!lstrcmpW(bstr
, bufW1
), "got wrong text: %s\n", wine_dbgstr_w(bstr
));
435 SendMessageA(w
, EM_SETSEL
, first
, lim
);
436 hres
= ITextSelection_GetText(txtSel
, &bstr
);
437 ok(hres
== S_OK
, "ITextSelection_GetText\n");
438 ok(!lstrcmpW(bstr
, bufW1
), "got wrong text: %s\n", wine_dbgstr_w(bstr
));
442 SendMessageA(w
, EM_SETSEL
, first
, lim
);
443 hres
= ITextSelection_GetText(txtSel
, &bstr
);
444 ok(hres
== S_OK
, "ITextSelection_GetText\n");
445 ok(!bstr
, "got wrong text: %s\n", wine_dbgstr_w(bstr
));
449 hres
= ITextSelection_GetText(txtSel
, NULL
);
450 ok(hres
== E_INVALIDARG
, "ITextSelection_GetText\n");
454 SendMessageA(w
, EM_SETSEL
, first
, lim
);
455 hres
= ITextSelection_GetText(txtSel
, &bstr
);
456 ok(hres
== S_OK
, "ITextSelection_GetText\n");
457 ok(!lstrcmpW(bstr
, bufW3
), "got wrong text: %s\n", wine_dbgstr_w(bstr
));
461 SendMessageA(w
, EM_SETSEL
, first
, lim
);
462 hres
= ITextSelection_GetText(txtSel
, &bstr
);
463 ok(hres
== S_OK
, "ITextSelection_GetText\n");
464 ok(!lstrcmpW(bstr
, bufW2
), "got wrong text: %s\n", wine_dbgstr_w(bstr
));
467 first
= 12, lim
= 13;
468 SendMessageA(w
, EM_SETSEL
, first
, lim
);
469 hres
= ITextSelection_GetText(txtSel
, &bstr
);
470 ok(hres
== S_OK
, "ITextSelection_GetText\n");
471 ok(!lstrcmpW(bstr
, bufW5
), "got wrong text: %s\n", wine_dbgstr_w(bstr
));
475 SendMessageA(w
, EM_SETSEL
, first
, lim
);
476 hres
= ITextSelection_GetText(txtSel
, &bstr
);
477 ok(hres
== S_OK
, "ITextSelection_GetText\n");
478 ok(!lstrcmpW(bstr
, bufW4
), "got wrong text: %s\n", wine_dbgstr_w(bstr
));
482 SendMessageA(w
, EM_SETSEL
, first
, lim
);
483 hres
= ITextSelection_GetText(txtSel
, &bstr
);
484 ok(hres
== S_OK
, "ITextSelection_GetText\n");
485 ok(!bstr
, "got wrong text: %s\n", wine_dbgstr_w(bstr
));
487 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
490 static void test_ITextDocument_Range(void)
493 IRichEditOle
*reOle
= NULL
;
494 ITextDocument
*txtDoc
= NULL
;
495 ITextRange
*txtRge
= NULL
;
496 ITextRange
*pointer
= NULL
;
500 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
501 hres
= ITextDocument_Range(txtDoc
, 0, 0, &txtRge
);
502 ok(hres
== S_OK
, "ITextDocument_Range fails 0x%x.\n", hres
);
503 refcount
= get_refcount((IUnknown
*)txtRge
);
504 ok(refcount
== 1, "get wrong refcount: returned %d expected 1\n", refcount
);
507 hres
= ITextDocument_Range(txtDoc
, 0, 0, &txtRge
);
508 ok(hres
== S_OK
, "ITextDocument_Range fails 0x%x.\n", hres
);
509 ok(pointer
!= txtRge
, "A new pointer should be returned\n");
510 ITextRange_Release(pointer
);
512 hres
= ITextDocument_Range(txtDoc
, 0, 0, NULL
);
513 ok(hres
== E_INVALIDARG
, "ITextDocument_Range should fail 0x%x.\n", hres
);
515 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
516 hres
= ITextRange_CanEdit(txtRge
, NULL
);
517 ok(hres
== CO_E_RELEASED
, "ITextRange after ITextDocument destroyed\n");
518 ITextRange_Release(txtRge
);
521 static void test_ITextRange_GetChar(void)
524 IRichEditOle
*reOle
= NULL
;
525 ITextDocument
*txtDoc
= NULL
;
526 ITextRange
*txtRge
= NULL
;
528 LONG pch
= 0xdeadbeef;
530 static const CHAR test_text1
[] = "TestSomeText";
533 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
534 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
535 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
537 hres
= ITextRange_GetChar(txtRge
, &pch
);
538 ok(hres
== S_OK
, "ITextRange_GetChar\n");
539 ok(pch
== 'T', "got wrong char: %c\n", pch
);
540 ITextRange_Release(txtRge
);
541 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
544 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
545 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
546 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
548 hres
= ITextRange_GetChar(txtRge
, &pch
);
549 ok(hres
== S_OK
, "ITextRange_GetChar\n");
550 ok(pch
== 'T', "got wrong char: %c\n", pch
);
551 ITextRange_Release(txtRge
);
552 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
554 first
= 12, lim
= 12;
555 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
556 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
557 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
559 hres
= ITextRange_GetChar(txtRge
, &pch
);
560 ok(hres
== S_OK
, "ITextRange_GetChar\n");
561 ok(pch
== '\r', "got wrong char: %c\n", pch
);
562 ITextRange_Release(txtRge
);
563 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
565 first
= 13, lim
= 13;
566 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
567 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
568 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
570 hres
= ITextRange_GetChar(txtRge
, &pch
);
571 ok(hres
== S_OK
, "ITextRange_GetChar\n");
572 ok(pch
== '\r', "got wrong char: %c\n", pch
);
573 ITextRange_Release(txtRge
);
574 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
576 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
577 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
578 first
= 12, lim
= 12;
579 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
580 hres
= ITextRange_GetChar(txtRge
, NULL
);
581 ok(hres
== E_INVALIDARG
, "ITextRange_GetChar\n");
582 ITextRange_Release(txtRge
);
583 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
586 static void test_ITextSelection_GetChar(void)
589 IRichEditOle
*reOle
= NULL
;
590 ITextDocument
*txtDoc
= NULL
;
591 ITextSelection
*txtSel
= NULL
;
593 LONG pch
= 0xdeadbeef;
595 static const CHAR test_text1
[] = "TestSomeText";
597 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
598 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
601 SendMessageA(w
, EM_SETSEL
, first
, lim
);
603 hres
= ITextSelection_GetChar(txtSel
, &pch
);
604 ok(hres
== S_OK
, "ITextSelection_GetChar\n");
605 ok(pch
== 'T', "got wrong char: %c\n", pch
);
608 SendMessageA(w
, EM_SETSEL
, first
, lim
);
610 hres
= ITextSelection_GetChar(txtSel
, &pch
);
611 ok(hres
== S_OK
, "ITextSelection_GetChar\n");
612 ok(pch
== 'T', "got wrong char: %c\n", pch
);
614 first
= 12, lim
= 12;
615 SendMessageA(w
, EM_SETSEL
, first
, lim
);
617 hres
= ITextSelection_GetChar(txtSel
, &pch
);
618 ok(hres
== S_OK
, "ITextSelection_GetChar\n");
619 ok(pch
== '\r', "got wrong char: %c\n", pch
);
621 first
= 13, lim
= 13;
622 SendMessageA(w
, EM_SETSEL
, first
, lim
);
624 hres
= ITextSelection_GetChar(txtSel
, &pch
);
625 ok(hres
== S_OK
, "ITextSelection_GetChar\n");
626 ok(pch
== '\r', "got wrong char: %c\n", pch
);
628 hres
= ITextSelection_GetChar(txtSel
, NULL
);
629 ok(hres
== E_INVALIDARG
, "ITextSelection_GetChar\n");
631 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
634 static void test_ITextRange_GetStart_GetEnd(void)
637 IRichEditOle
*reOle
= NULL
;
638 ITextDocument
*txtDoc
= NULL
;
639 ITextRange
*txtRge
= NULL
;
641 int first
, lim
, start
, end
;
642 static const CHAR test_text1
[] = "TestSomeText";
644 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
645 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
648 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
650 hres
= ITextRange_GetStart(txtRge
, &start
);
651 ok(hres
== S_OK
, "ITextRange_GetStart\n");
652 ok(start
== 1, "got wrong start value: %d\n", start
);
654 hres
= ITextRange_GetEnd(txtRge
, &end
);
655 ok(hres
== S_OK
, "ITextRange_GetEnd\n");
656 ok(end
== 6, "got wrong end value: %d\n", end
);
657 ITextRange_Release(txtRge
);
660 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
662 hres
= ITextRange_GetStart(txtRge
, &start
);
663 ok(hres
== S_OK
, "ITextRange_GetStart\n");
664 ok(start
== 1, "got wrong start value: %d\n", start
);
666 hres
= ITextRange_GetEnd(txtRge
, &end
);
667 ok(hres
== S_OK
, "ITextRange_GetEnd\n");
668 ok(end
== 6, "got wrong end value: %d\n", end
);
669 ITextRange_Release(txtRge
);
671 first
= -1, lim
= 13;
672 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
674 hres
= ITextRange_GetStart(txtRge
, &start
);
675 ok(hres
== S_OK
, "ITextRange_GetStart\n");
676 ok(start
== 0, "got wrong start value: %d\n", start
);
678 hres
= ITextRange_GetEnd(txtRge
, &end
);
679 ok(hres
== S_OK
, "ITextRange_GetEnd\n");
680 ok(end
== 13, "got wrong end value: %d\n", end
);
681 ITextRange_Release(txtRge
);
683 first
= 13, lim
= 13;
684 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
686 hres
= ITextRange_GetStart(txtRge
, &start
);
687 ok(hres
== S_OK
, "ITextRange_GetStart\n");
688 ok(start
== 12, "got wrong start value: %d\n", start
);
690 hres
= ITextRange_GetEnd(txtRge
, &end
);
691 ok(hres
== S_OK
, "ITextRange_GetEnd\n");
692 ok(end
== 12, "got wrong end value: %d\n", end
);
693 ITextRange_Release(txtRge
);
695 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
698 static void test_ITextSelection_GetStart_GetEnd(void)
701 IRichEditOle
*reOle
= NULL
;
702 ITextDocument
*txtDoc
= NULL
;
703 ITextSelection
*txtSel
= NULL
;
705 int first
, lim
, start
, end
;
706 static const CHAR test_text1
[] = "TestSomeText";
708 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
709 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
712 SendMessageA(w
, EM_SETSEL
, first
, lim
);
714 hres
= ITextSelection_GetStart(txtSel
, &start
);
715 ok(hres
== S_OK
, "ITextSelection_GetStart\n");
716 ok(start
== 2, "got wrong start value: %d\n", start
);
718 hres
= ITextSelection_GetEnd(txtSel
, &end
);
719 ok(hres
== S_OK
, "ITextSelection_GetEnd\n");
720 ok(end
== 5, "got wrong end value: %d\n", end
);
723 SendMessageA(w
, EM_SETSEL
, first
, lim
);
725 hres
= ITextSelection_GetStart(txtSel
, &start
);
726 ok(hres
== S_OK
, "ITextSelection_GetStart\n");
727 ok(start
== 2, "got wrong start value: %d\n", start
);
729 hres
= ITextSelection_GetEnd(txtSel
, &end
);
730 ok(hres
== S_OK
, "ITextSelection_GetEnd\n");
731 ok(end
== 5, "got wrong end value: %d\n", end
);
734 SendMessageA(w
, EM_SETSEL
, first
, lim
);
736 hres
= ITextSelection_GetStart(txtSel
, &start
);
737 ok(hres
== S_OK
, "ITextSelection_GetStart\n");
738 ok(start
== 0, "got wrong start value: %d\n", start
);
740 hres
= ITextSelection_GetEnd(txtSel
, &end
);
741 ok(hres
== S_OK
, "ITextSelection_GetEnd\n");
742 ok(end
== 13, "got wrong end value: %d\n", end
);
744 first
= 13, lim
= 13;
745 SendMessageA(w
, EM_SETSEL
, first
, lim
);
747 hres
= ITextSelection_GetStart(txtSel
, &start
);
748 ok(hres
== S_OK
, "ITextSelection_GetStart\n");
749 ok(start
== 12, "got wrong start value: %d\n", start
);
751 hres
= ITextSelection_GetEnd(txtSel
, &end
);
752 ok(hres
== S_OK
, "ITextSelection_GetEnd\n");
753 ok(end
== 12, "got wrong end value: %d\n", end
);
755 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
758 static void test_ITextRange_GetDuplicate(void)
761 IRichEditOle
*reOle
= NULL
;
762 ITextDocument
*txtDoc
= NULL
;
763 ITextRange
*txtRge
= NULL
;
764 ITextRange
*txtRgeDup
= NULL
;
766 LONG first
, lim
, start
, end
;
767 static const CHAR test_text1
[] = "TestSomeText";
769 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
770 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
772 hres
= ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
773 ok(hres
== S_OK
, "ITextDocument_Range fails 0x%x.\n", hres
);
775 hres
= ITextRange_GetDuplicate(txtRge
, &txtRgeDup
);
776 ok(hres
== S_OK
, "ITextRange_GetDuplicate\n");
777 ok(txtRgeDup
!= txtRge
, "A new pointer should be returned\n");
778 ITextRange_GetStart(txtRgeDup
, &start
);
779 ok(start
== first
, "got wrong value: %d\n", start
);
780 ITextRange_GetEnd(txtRgeDup
, &end
);
781 ok(end
== lim
, "got wrong value: %d\n", end
);
783 ITextRange_Release(txtRgeDup
);
785 hres
= ITextRange_GetDuplicate(txtRge
, NULL
);
786 ok(hres
== E_INVALIDARG
, "ITextRange_GetDuplicate\n");
788 ITextRange_Release(txtRge
);
789 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
792 static void test_ITextRange_Collapse(void)
795 IRichEditOle
*reOle
= NULL
;
796 ITextDocument
*txtDoc
= NULL
;
797 ITextRange
*txtRge
= NULL
;
799 LONG first
, lim
, start
, end
;
800 static const CHAR test_text1
[] = "TestSomeText";
802 create_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
803 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
806 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
807 hres
= ITextRange_Collapse(txtRge
, tomTrue
);
808 ok(hres
== S_OK
, "ITextRange_Collapse\n");
809 ITextRange_GetStart(txtRge
, &start
);
810 ok(start
== 4, "got wrong start value: %d\n", start
);
811 ITextRange_GetEnd(txtRge
, &end
);
812 ok(end
== 4, "got wrong end value: %d\n", end
);
813 ITextRange_Release(txtRge
);
815 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
816 hres
= ITextRange_Collapse(txtRge
, tomStart
);
817 ok(hres
== S_OK
, "ITextRange_Collapse\n");
818 ITextRange_GetStart(txtRge
, &start
);
819 ok(start
== 4, "got wrong start value: %d\n", start
);
820 ITextRange_GetEnd(txtRge
, &end
);
821 ok(end
== 4, "got wrong end value: %d\n", end
);
822 ITextRange_Release(txtRge
);
824 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
825 hres
= ITextRange_Collapse(txtRge
, tomFalse
);
826 ok(hres
== S_OK
, "ITextRange_Collapse\n");
827 ITextRange_GetStart(txtRge
, &start
);
828 ok(start
== 8, "got wrong start value: %d\n", start
);
829 ITextRange_GetEnd(txtRge
, &end
);
830 ok(end
== 8, "got wrong end value: %d\n", end
);
831 ITextRange_Release(txtRge
);
833 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
834 hres
= ITextRange_Collapse(txtRge
, tomEnd
);
835 ok(hres
== S_OK
, "ITextRange_Collapse\n");
836 ITextRange_GetStart(txtRge
, &start
);
837 ok(start
== 8, "got wrong start value: %d\n", start
);
838 ITextRange_GetEnd(txtRge
, &end
);
839 ok(end
== 8, "got wrong end value: %d\n", end
);
840 ITextRange_Release(txtRge
);
842 /* tomStart is the default */
843 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
844 hres
= ITextRange_Collapse(txtRge
, 256);
845 ok(hres
== S_OK
, "ITextRange_Collapse\n");
846 ITextRange_GetStart(txtRge
, &start
);
847 ok(start
== 4, "got wrong start value: %d\n", start
);
848 ITextRange_GetEnd(txtRge
, &end
);
849 ok(end
== 4, "got wrong end value: %d\n", end
);
850 ITextRange_Release(txtRge
);
853 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
854 hres
= ITextRange_Collapse(txtRge
, tomEnd
);
855 ok(hres
== S_FALSE
, "ITextRange_Collapse\n");
856 ITextRange_GetStart(txtRge
, &start
);
857 ok(start
== 6, "got wrong start value: %d\n", start
);
858 ITextRange_GetEnd(txtRge
, &end
);
859 ok(end
== 6, "got wrong end value: %d\n", end
);
860 ITextRange_Release(txtRge
);
863 ITextDocument_Range(txtDoc
, first
, lim
, &txtRge
);
864 hres
= ITextRange_Collapse(txtRge
, tomStart
);
865 ok(hres
== S_FALSE
, "ITextRange_Collapse\n");
866 ITextRange_GetStart(txtRge
, &start
);
867 ok(start
== 8, "got wrong start value: %d\n", start
);
868 ITextRange_GetEnd(txtRge
, &end
);
869 ok(end
== 8, "got wrong end value: %d\n", end
);
870 ITextRange_Release(txtRge
);
872 release_interfaces(&w
, &reOle
, &txtDoc
, NULL
);
875 static void test_ITextSelection_Collapse(void)
878 IRichEditOle
*reOle
= NULL
;
879 ITextDocument
*txtDoc
= NULL
;
880 ITextSelection
*txtSel
= NULL
;
882 LONG first
, lim
, start
, end
;
883 static const CHAR test_text1
[] = "TestSomeText";
885 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
886 SendMessageA(w
, WM_SETTEXT
, 0, (LPARAM
)test_text1
);
889 SendMessageA(w
, EM_SETSEL
, first
, lim
);
890 hres
= ITextSelection_Collapse(txtSel
, tomTrue
);
891 ok(hres
== S_OK
, "ITextSelection_Collapse\n");
892 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
893 ok(start
== 4, "got wrong start value: %d\n", start
);
894 ok(end
== 4, "got wrong end value: %d\n", end
);
896 SendMessageA(w
, EM_SETSEL
, first
, lim
);
897 hres
= ITextSelection_Collapse(txtSel
, tomStart
);
898 ok(hres
== S_OK
, "ITextSelection_Collapse\n");
899 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
900 ok(start
== 4, "got wrong start value: %d\n", start
);
901 ok(end
== 4, "got wrong end value: %d\n", end
);
903 SendMessageA(w
, EM_SETSEL
, first
, lim
);
904 hres
= ITextSelection_Collapse(txtSel
, tomFalse
);
905 ok(hres
== S_OK
, "ITextSelection_Collapse\n");
906 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
907 ok(start
== 8, "got wrong start value: %d\n", start
);
908 ok(end
== 8, "got wrong end value: %d\n", end
);
910 SendMessageA(w
, EM_SETSEL
, first
, lim
);
911 hres
= ITextSelection_Collapse(txtSel
, tomEnd
);
912 ok(hres
== S_OK
, "ITextSelection_Collapse\n");
913 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
914 ok(start
== 8, "got wrong start value: %d\n", start
);
915 ok(end
== 8, "got wrong end value: %d\n", end
);
917 /* tomStart is the default */
918 SendMessageA(w
, EM_SETSEL
, first
, lim
);
919 hres
= ITextSelection_Collapse(txtSel
, 256);
920 ok(hres
== S_OK
, "ITextSelection_Collapse\n");
921 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
922 ok(start
== 4, "got wrong start value: %d\n", start
);
923 ok(end
== 4, "got wrong end value: %d\n", end
);
926 SendMessageA(w
, EM_SETSEL
, first
, lim
);
927 hres
= ITextSelection_Collapse(txtSel
, tomEnd
);
928 ok(hres
== S_FALSE
, "ITextSelection_Collapse\n");
929 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
930 ok(start
== 6, "got wrong start value: %d\n", start
);
931 ok(end
== 6, "got wrong end value: %d\n", end
);
934 SendMessageA(w
, EM_SETSEL
, first
, lim
);
935 hres
= ITextSelection_Collapse(txtSel
, tomStart
);
936 ok(hres
== S_FALSE
, "ITextSelection_Collapse\n");
937 SendMessageA(w
, EM_GETSEL
, (LPARAM
)&start
, (WPARAM
)&end
);
938 ok(start
== 8, "got wrong start value: %d\n", start
);
939 ok(end
== 8, "got wrong end value: %d\n", end
);
941 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
946 /* Must explicitly LoadLibrary(). The test has no references to functions in
947 * RICHED20.DLL, so the linker doesn't actually link to it. */
948 hmoduleRichEdit
= LoadLibraryA("riched20.dll");
949 ok(hmoduleRichEdit
!= NULL
, "error: %d\n", (int) GetLastError());
952 test_ITextDocument_Open();
953 test_ITextSelection_GetText();
954 test_ITextSelection_GetChar();
955 test_ITextSelection_GetStart_GetEnd();
956 test_ITextSelection_Collapse();
957 test_ITextDocument_Range();
958 test_ITextRange_GetChar();
959 test_ITextRange_GetStart_GetEnd();
960 test_ITextRange_GetDuplicate();
961 test_ITextRange_Collapse();