msvcrt/tests: Remove a space before a '\n'.
[wine/gsoc-2012-control.git] / dlls / riched32 / tests / editor.c
blobac98d16518e573f6981450878beb714ce0f0203f
1 /*
2 * Unit test suite for rich edit control 1.0
4 * Copyright 2006 Google (Thomas Kho)
5 * Copyright 2007 Matt Finnicum
6 * Copyright 2007 Dmitry Timoshkov
7 * Copyright 2007 Alex VillacĂ­s Lasso
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <stdarg.h>
25 #include <assert.h>
26 #include <windef.h>
27 #include <winbase.h>
28 #include <wingdi.h>
29 #include <winuser.h>
30 #include <winnls.h>
31 #include <ole2.h>
32 #include <richedit.h>
33 #include <time.h>
34 #include <wine/test.h>
36 static HMODULE hmoduleRichEdit;
38 static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
39 HWND hwnd;
40 hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
41 |WS_VISIBLE, 0, 0, 200, 60, parent, NULL,
42 hmoduleRichEdit, NULL);
43 ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
44 return hwnd;
47 static HWND new_richedit(HWND parent) {
48 return new_window(RICHEDIT_CLASS10A, ES_MULTILINE, parent);
51 static void test_WM_SETTEXT(void)
53 HWND hwndRichEdit = new_richedit(NULL);
54 const char * TestItem1 = "TestSomeText";
55 const char * TestItem2 = "TestSomeText\r";
56 const char * TestItem3 = "TestSomeText\rSomeMoreText\r";
57 const char * TestItem4 = "TestSomeText\n\nTestSomeText";
58 const char * TestItem5 = "TestSomeText\r\r\nTestSomeText";
59 const char * TestItem6 = "TestSomeText\r\r\n\rTestSomeText";
60 const char * TestItem7 = "TestSomeText\r\n\r\r\n\rTestSomeText";
61 const char * TestItem8 = "TestSomeText\r\n";
62 const char * TestItem9 = "TestSomeText\r\nSomeMoreText\r\n";
63 const char * TestItem10 = "TestSomeText\r\n\r\nTestSomeText";
64 const char * TestItem11 = "TestSomeText TestSomeText";
65 const char * TestItem12 = "TestSomeText \r\nTestSomeText";
66 const char * TestItem13 = "TestSomeText\r\n \r\nTestSomeText";
67 const char * TestItem14 = "TestSomeText\n";
68 const char * TestItem15 = "TestSomeText\r\r\r";
69 const char * TestItem16 = "TestSomeText\r\r\rSomeMoreText";
70 char buf[1024] = {0};
71 LRESULT result;
73 /* This test attempts to show that WM_SETTEXT on a riched32 control does not
74 * attempt to modify the text that is pasted into the control, and should
75 * return it as is. In particular, \r\r\n is NOT converted, unlike riched20.
77 * For riched32, the rules for breaking lines seem to be the following:
78 * - \r\n is one line break. This is the normal case.
79 * - \r{0,2}\n is one line break. In particular, \n by itself is a line break.
80 * - \r{0,N-1}\r\r\n is N line breaks.
81 * - \n{1,N} are that many line breaks.
82 * - \r with text or other characters (except \n) past it, is a line break. That
83 * is, a run of \r{N} without a terminating \n is considered N line breaks
84 * - \r at the end of the text is NOT a line break. This differs from riched20,
85 * where \r at the end of the text is a proper line break.
88 #define TEST_SETTEXT(a, b, nlines) \
89 result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) a); \
90 ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); \
91 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf); \
92 ok (result == lstrlen(buf), \
93 "WM_GETTEXT returned %ld instead of expected %u\n", \
94 result, lstrlen(buf)); \
95 result = strcmp(b, buf); \
96 ok(result == 0, \
97 "WM_SETTEXT round trip: strcmp = %ld\n", result); \
98 result = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0); \
99 ok(result == nlines, "EM_GETLINECOUNT returned %ld, expected %d\n", result, nlines);
101 TEST_SETTEXT(TestItem1, TestItem1, 1)
102 TEST_SETTEXT(TestItem2, TestItem2, 1)
103 TEST_SETTEXT(TestItem3, TestItem3, 2)
104 TEST_SETTEXT(TestItem4, TestItem4, 3)
105 TEST_SETTEXT(TestItem5, TestItem5, 2)
106 TEST_SETTEXT(TestItem6, TestItem6, 3)
107 TEST_SETTEXT(TestItem7, TestItem7, 4)
108 TEST_SETTEXT(TestItem8, TestItem8, 2)
109 TEST_SETTEXT(TestItem9, TestItem9, 3)
110 TEST_SETTEXT(TestItem10, TestItem10, 3)
111 TEST_SETTEXT(TestItem11, TestItem11, 1)
112 TEST_SETTEXT(TestItem12, TestItem12, 2)
113 TEST_SETTEXT(TestItem13, TestItem13, 3)
114 TEST_SETTEXT(TestItem14, TestItem14, 2)
115 TEST_SETTEXT(TestItem15, TestItem15, 3)
116 TEST_SETTEXT(TestItem16, TestItem16, 4)
118 #undef TEST_SETTEXT
119 DestroyWindow(hwndRichEdit);
122 static void test_WM_GETTEXTLENGTH(void)
124 HWND hwndRichEdit = new_richedit(NULL);
125 static const char text3[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee";
126 static const char text4[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee\r\n";
127 int result;
129 /* Test for WM_GETTEXTLENGTH */
130 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text3);
131 result = SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
132 ok(result == lstrlen(text3),
133 "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
134 result, lstrlen(text3));
136 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text4);
137 result = SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
138 ok(result == lstrlen(text4),
139 "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
140 result, lstrlen(text4));
142 DestroyWindow(hwndRichEdit);
145 static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie,
146 LPBYTE pbBuff,
147 LONG cb,
148 LONG *pcb)
150 const char** str = (const char**)dwCookie;
151 int size = strlen(*str);
152 *pcb = cb;
153 if (*pcb > size) {
154 *pcb = size;
156 if (*pcb > 0) {
157 memcpy(pbBuff, *str, *pcb);
158 *str += *pcb;
160 return 0;
164 static void test_EM_STREAMIN(void)
166 HWND hwndRichEdit = new_richedit(NULL);
167 LRESULT result;
168 EDITSTREAM es;
169 char buffer[1024] = {0};
171 const char * streamText0 = "{\\rtf1 TestSomeText}";
172 const char * streamText0a = "{\\rtf1 TestSomeText\\par}";
173 const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
175 const char * streamText1 =
176 "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n"
177 "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n"
178 "}\r\n";
180 /* This should be accepted in richedit 1.0 emulation. See bug #8326 */
181 const char * streamText2 =
182 "{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;"
183 "\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255"
184 "\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 "
185 "\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 "
186 "\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 "
187 "\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 "
188 "\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line }";
190 const char * streamText3 = "RichEdit1";
192 /* Minimal test without \par at the end */
193 es.dwCookie = (DWORD_PTR)&streamText0;
194 es.dwError = 0;
195 es.pfnCallback = test_EM_STREAMIN_esCallback;
196 SendMessage(hwndRichEdit, EM_STREAMIN,
197 (WPARAM)(SF_RTF), (LPARAM)&es);
199 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
200 ok (result == 12,
201 "EM_STREAMIN: Test 0 returned %ld, expected 12\n", result);
202 result = strcmp (buffer,"TestSomeText");
203 ok (result == 0,
204 "EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
205 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
207 /* Native richedit 2.0 ignores last \par */
208 es.dwCookie = (DWORD_PTR)&streamText0a;
209 es.dwError = 0;
210 es.pfnCallback = test_EM_STREAMIN_esCallback;
211 SendMessage(hwndRichEdit, EM_STREAMIN,
212 (WPARAM)(SF_RTF), (LPARAM)&es);
214 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
215 ok (result == 12,
216 "EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
217 result = strcmp (buffer,"TestSomeText");
218 ok (result == 0,
219 "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
220 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
222 /* Native richedit 2.0 ignores last \par, next-to-last \par appears */
223 es.dwCookie = (DWORD_PTR)&streamText0b;
224 es.dwError = 0;
225 es.pfnCallback = test_EM_STREAMIN_esCallback;
226 SendMessage(hwndRichEdit, EM_STREAMIN,
227 (WPARAM)(SF_RTF), (LPARAM)&es);
229 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
230 ok (result == 14,
231 "EM_STREAMIN: Test 0-b returned %ld, expected 14\n", result);
232 result = strcmp (buffer,"TestSomeText\r\n");
233 ok (result == 0,
234 "EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer);
235 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
237 es.dwCookie = (DWORD_PTR)&streamText1;
238 es.dwError = 0;
239 es.pfnCallback = test_EM_STREAMIN_esCallback;
240 SendMessage(hwndRichEdit, EM_STREAMIN,
241 (WPARAM)(SF_RTF), (LPARAM)&es);
243 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
244 ok (result == 12,
245 "EM_STREAMIN: Test 1 returned %ld, expected 12\n", result);
246 result = strcmp (buffer,"TestSomeText");
247 ok (result == 0,
248 "EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
249 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
252 es.dwCookie = (DWORD_PTR)&streamText2;
253 es.dwError = 0;
254 SendMessage(hwndRichEdit, EM_STREAMIN,
255 (WPARAM)(SF_RTF), (LPARAM)&es);
257 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
258 todo_wine {
259 ok (result == 9,
260 "EM_STREAMIN: Test 2 returned %ld, expected 9\n", result);
262 result = strcmp (buffer,"RichEdit1");
263 todo_wine {
264 ok (result == 0,
265 "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
267 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
269 es.dwCookie = (DWORD_PTR)&streamText3;
270 es.dwError = 0;
271 SendMessage(hwndRichEdit, EM_STREAMIN,
272 (WPARAM)(SF_RTF), (LPARAM)&es);
274 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
275 ok (result == 0,
276 "EM_STREAMIN: Test 3 returned %ld, expected 0\n", result);
277 ok (strlen(buffer) == 0,
278 "EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer);
279 ok(es.dwError == -16, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, -16);
281 DestroyWindow(hwndRichEdit);
284 static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
285 LPBYTE pbBuff,
286 LONG cb,
287 LONG *pcb)
289 char** str = (char**)dwCookie;
290 *pcb = cb;
291 if (*pcb > 0) {
292 memcpy(*str, pbBuff, *pcb);
293 *str += *pcb;
295 return 0;
298 static void test_EM_STREAMOUT(void)
300 HWND hwndRichEdit = new_richedit(NULL);
301 int r;
302 EDITSTREAM es;
303 char buf[1024] = {0};
304 char * p;
306 const char * TestItem1 = "TestSomeText";
307 const char * TestItem2 = "TestSomeText\r";
308 const char * TestItem3 = "TestSomeText\r\n";
310 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
311 p = buf;
312 es.dwCookie = (DWORD_PTR)&p;
313 es.dwError = 0;
314 es.pfnCallback = test_WM_SETTEXT_esCallback;
315 memset(buf, 0, sizeof(buf));
316 SendMessage(hwndRichEdit, EM_STREAMOUT,
317 (WPARAM)(SF_TEXT), (LPARAM)&es);
318 r = strlen(buf);
319 ok(r == 12, "streamed text length is %d, expecting 12\n", r);
320 ok(strcmp(buf, TestItem1) == 0,
321 "streamed text different, got %s\n", buf);
323 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
324 p = buf;
325 es.dwCookie = (DWORD_PTR)&p;
326 es.dwError = 0;
327 es.pfnCallback = test_WM_SETTEXT_esCallback;
328 memset(buf, 0, sizeof(buf));
329 SendMessage(hwndRichEdit, EM_STREAMOUT,
330 (WPARAM)(SF_TEXT), (LPARAM)&es);
331 r = strlen(buf);
333 ok(r == 13, "streamed text length is %d, expecting 13\n", r);
334 ok(strcmp(buf, TestItem2) == 0,
335 "streamed text different, got %s\n", buf);
337 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
338 p = buf;
339 es.dwCookie = (DWORD_PTR)&p;
340 es.dwError = 0;
341 es.pfnCallback = test_WM_SETTEXT_esCallback;
342 memset(buf, 0, sizeof(buf));
343 SendMessage(hwndRichEdit, EM_STREAMOUT,
344 (WPARAM)(SF_TEXT), (LPARAM)&es);
345 r = strlen(buf);
346 ok(r == 14, "streamed text length is %d, expecting 14\n", r);
347 ok(strcmp(buf, TestItem3) == 0,
348 "streamed text different, got %s\n", buf);
350 DestroyWindow(hwndRichEdit);
353 static const struct getline_s {
354 int line;
355 size_t buffer_len;
356 const char *text;
357 } gl[] = {
358 {0, 10, "foo bar\r\n"},
359 {1, 10, "\r"},
360 {2, 10, "\r\r\n"},
361 {3, 10, "bar\n"},
362 {4, 10, "\r\n"},
364 /* Buffer smaller than line length */
365 {0, 2, "foo bar\r"},
366 {0, 1, "foo bar\r"},
367 {0, 0, "foo bar\r"}
370 static void test_EM_GETLINE(void)
372 int i;
373 HWND hwndRichEdit = new_richedit(NULL);
374 static const int nBuf = 1024;
375 char dest[1024], origdest[1024];
376 const char text[] = "foo bar\r\n"
377 "\r"
378 "\r\r\n"
379 "bar\n";
381 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
383 memset(origdest, 0xBB, nBuf);
384 for (i = 0; i < sizeof(gl)/sizeof(struct getline_s); i++)
386 int nCopied;
387 int expected_nCopied = min(gl[i].buffer_len, strlen(gl[i].text));
388 int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text) + 1);
389 memset(dest, 0xBB, nBuf);
390 *(WORD *) dest = gl[i].buffer_len;
392 /* EM_GETLINE appends a "\r\0" to the end of the line
393 * nCopied counts up to and including the '\r' */
394 nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest);
395 ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
396 expected_nCopied);
397 /* two special cases since a parameter is passed via dest */
398 if (gl[i].buffer_len == 0)
399 ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
400 "buffer_len=0\n");
401 else if (gl[i].buffer_len == 1)
402 ok(dest[0] == gl[i].text[0] && !dest[1] &&
403 !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
404 else
406 ok(!strncmp(dest, gl[i].text, expected_bytes_written),
407 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
408 ok(!strncmp(dest + expected_bytes_written, origdest
409 + expected_bytes_written, nBuf - expected_bytes_written),
410 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
414 DestroyWindow(hwndRichEdit);
417 static void test_EM_LINELENGTH(void)
419 HWND hwndRichEdit = new_richedit(NULL);
420 const char * text =
421 "richedit1\r"
422 "richedit1\n"
423 "richedit1\r\n"
424 "short\r"
425 "richedit1\r"
426 "\r"
427 "\r"
428 "\r\r\n";
429 int offset_test[16][2] = {
430 {0, 9}, /* Line 1: |richedit1\r */
431 {5, 9}, /* Line 1: riche|dit1\r */
432 {10, 9}, /* Line 2: |richedit1\n */
433 {15, 9}, /* Line 2: riche|dit1\n */
434 {20, 9}, /* Line 3: |richedit1\r\n */
435 {25, 9}, /* Line 3: riche|dit1\r\n */
436 {30, 9}, /* Line 3: richedit1\r|\n */
437 {31, 5}, /* Line 4: |short\r */
438 {42, 9}, /* Line 5: riche|dit1\r */
439 {46, 9}, /* Line 5: richedit1|\r */
440 {47, 0}, /* Line 6: |\r */
441 {48, 0}, /* Line 7: |\r */
442 {49, 0}, /* Line 8: |\r\r\n */
443 {50, 0}, /* Line 8: \r|\r\n */
444 {51, 0}, /* Line 8: \r\r|\n */
445 {52, 0}, /* Line 9: \r\r\n| */
447 int i;
448 LRESULT result;
450 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
452 result = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
453 ok(result == 9, "Incorrect line count of %ld\n", result);
455 for (i = 0; i < sizeof(offset_test)/sizeof(offset_test[0]); i++) {
456 result = SendMessage(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
457 ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
458 offset_test[i][0], result, offset_test[i][1]);
461 DestroyWindow(hwndRichEdit);
464 static void test_EM_GETTEXTRANGE(void)
466 HWND hwndRichEdit = new_richedit(NULL);
467 const char * text1 = "foo bar\r\nfoo bar";
468 const char * text3 = "foo bar\rfoo bar";
469 const char * expect1 = "bar\r\nfoo";
470 const char * expect2 = "\nfoo";
471 const char * expect3 = "bar\rfoo";
472 char buffer[1024] = {0};
473 LRESULT result;
474 TEXTRANGEA textRange;
476 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
478 textRange.lpstrText = buffer;
479 textRange.chrg.cpMin = 4;
480 textRange.chrg.cpMax = 12;
481 result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
482 ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
483 ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
485 textRange.lpstrText = buffer;
486 textRange.chrg.cpMin = 8;
487 textRange.chrg.cpMax = 12;
488 result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
489 ok(result == 4, "EM_GETTEXTRANGE returned %ld\n", result);
490 ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
492 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text3);
494 textRange.lpstrText = buffer;
495 textRange.chrg.cpMin = 4;
496 textRange.chrg.cpMax = 11;
497 result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
498 ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
500 ok(!strcmp(expect3, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
503 DestroyWindow(hwndRichEdit);
506 static void test_EM_GETSELTEXT(void)
508 HWND hwndRichEdit = new_richedit(NULL);
509 const char * text1 = "foo bar\r\nfoo bar";
510 const char * text2 = "foo bar\rfoo bar";
511 const char * expect1 = "bar\r\nfoo";
512 const char * expect2 = "bar\rfoo";
513 char buffer[1024] = {0};
514 LRESULT result;
516 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
518 SendMessage(hwndRichEdit, EM_SETSEL, 4, 12);
519 result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
520 ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
521 ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
523 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
525 SendMessage(hwndRichEdit, EM_SETSEL, 4, 11);
526 result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
527 ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
529 ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
532 DestroyWindow(hwndRichEdit);
535 static const char haystack[] = "WINEWine wineWine wine WineWine";
536 /* ^0 ^10 ^20 ^30 */
538 static const char haystack2[] = "first\r\r\nsecond";
540 struct find_s {
541 int start;
542 int end;
543 const char *needle;
544 int flags;
545 int expected_loc;
549 struct find_s find_tests[] = {
550 /* Find in empty text */
551 {0, -1, "foo", FR_DOWN, -1},
552 {0, -1, "foo", 0, -1},
553 {0, -1, "", FR_DOWN, -1},
554 {20, 5, "foo", FR_DOWN, -1},
555 {5, 20, "foo", FR_DOWN, -1}
558 struct find_s find_tests2[] = {
559 /* No-result find */
560 {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1},
561 {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1},
563 /* Subsequent finds */
564 {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4},
565 {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13},
566 {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
567 {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
569 /* Find backwards */
570 {19, 20, "Wine", FR_MATCHCASE, -1},
571 {10, 20, "Wine", FR_MATCHCASE, 13},
572 {20, 10, "Wine", FR_MATCHCASE, -1},
574 /* Case-insensitive */
575 {1, 31, "wInE", FR_DOWN, 4},
576 {1, 31, "Wine", FR_DOWN, 4},
578 /* High-to-low ranges */
579 {20, 5, "Wine", FR_DOWN, -1},
580 {2, 1, "Wine", FR_DOWN, -1},
581 {30, 29, "Wine", FR_DOWN, -1},
582 {20, 5, "Wine", 0, /*13*/ -1},
584 /* Find nothing */
585 {5, 10, "", FR_DOWN, -1},
586 {10, 5, "", FR_DOWN, -1},
587 {0, -1, "", FR_DOWN, -1},
588 {10, 5, "", 0, -1},
590 /* Whole-word search */
591 {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
592 {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1},
593 {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
594 {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0},
595 {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23},
596 {11, -1, "winewine", FR_WHOLEWORD, 23},
597 {31, -1, "winewine", FR_WHOLEWORD, -1},
599 /* Bad ranges */
600 {5, 200, "XXX", FR_DOWN, -1},
601 {-20, 20, "Wine", FR_DOWN, -1},
602 {-20, 20, "Wine", FR_DOWN, -1},
603 {-15, -20, "Wine", FR_DOWN, -1},
604 {1<<12, 1<<13, "Wine", FR_DOWN, -1},
606 /* Check the case noted in bug 4479 where matches at end aren't recognized */
607 {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
608 {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
609 {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27},
610 {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
611 {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
613 /* The backwards case of bug 4479; bounds look right
614 * Fails because backward find is wrong */
615 {19, 20, "WINE", FR_MATCHCASE, -1},
616 {0, 20, "WINE", FR_MATCHCASE, 0},
618 {0, -1, "wineWine wine", FR_DOWN, 0},
619 {0, -1, "wineWine wine", 0, 0},
620 {0, -1, "INEW", 0, 1},
621 {0, 31, "INEW", 0, 1},
622 {4, -1, "INEW", 0, 10},
625 struct find_s find_tests3[] = {
626 /* Searching for end of line characters */
627 {0, -1, "t\r\r\ns", FR_DOWN | FR_MATCHCASE, 4},
628 {6, -1, "\r\n", FR_DOWN | FR_MATCHCASE, 6},
629 {7, -1, "\n", FR_DOWN | FR_MATCHCASE, 7},
632 static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
633 int findloc;
634 FINDTEXT ft;
635 memset(&ft, 0, sizeof(ft));
636 ft.chrg.cpMin = f->start;
637 ft.chrg.cpMax = f->end;
638 ft.lpstrText = f->needle;
639 findloc = SendMessage(hwnd, EM_FINDTEXT, f->flags, (LPARAM) &ft);
640 ok(findloc == f->expected_loc,
641 "EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
642 name, id, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
645 static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f,
646 int id) {
647 int findloc;
648 FINDTEXTEX ft;
649 int expected_end_loc;
651 memset(&ft, 0, sizeof(ft));
652 ft.chrg.cpMin = f->start;
653 ft.chrg.cpMax = f->end;
654 ft.lpstrText = f->needle;
655 findloc = SendMessage(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM) &ft);
656 ok(findloc == f->expected_loc,
657 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
658 name, id, f->needle, f->start, f->end, f->flags, findloc);
659 ok(ft.chrgText.cpMin == f->expected_loc,
660 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d, expected %d\n",
661 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin, f->expected_loc);
662 expected_end_loc = ((f->expected_loc == -1) ? -1
663 : f->expected_loc + strlen(f->needle));
664 ok(ft.chrgText.cpMax == expected_end_loc,
665 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d, expected %d\n",
666 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax, expected_end_loc);
669 static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find,
670 int num_tests)
672 int i;
674 for (i = 0; i < num_tests; i++) {
675 if (*name == '3' && i == 0) {
676 todo_wine {
677 check_EM_FINDTEXT(hwnd, name, &find[i], i);
678 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
680 } else {
681 check_EM_FINDTEXT(hwnd, name, &find[i], i);
682 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
687 static void test_EM_FINDTEXT(void)
689 HWND hwndRichEdit = new_richedit(NULL);
691 /* Empty rich edit control */
692 run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests,
693 sizeof(find_tests)/sizeof(struct find_s));
695 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
697 /* Haystack text */
698 run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2,
699 sizeof(find_tests2)/sizeof(struct find_s));
701 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack2);
703 /* Haystack text 2 (with EOL characters) */
704 run_tests_EM_FINDTEXT(hwndRichEdit, "3", find_tests3,
705 sizeof(find_tests3)/sizeof(struct find_s));
707 DestroyWindow(hwndRichEdit);
710 static void test_EM_POSFROMCHAR(void)
712 HWND hwndRichEdit = new_richedit(NULL);
713 int i;
714 POINTL pl;
715 LRESULT result;
716 unsigned int height = 0;
717 int xpos = 0;
718 static const char text[] = "aa\n"
719 "this is a long line of text that should be longer than the "
720 "control's width\n"
721 "cc\n"
722 "dd\n"
723 "ee\n"
724 "ff\n"
725 "gg\n"
726 "hh\n";
728 /* Fill the control to lines to ensure that most of them are offscreen */
729 for (i = 0; i < 50; i++)
731 /* Do not modify the string; it is exactly 16 characters long. */
732 SendMessage(hwndRichEdit, EM_SETSEL, 0, 0);
733 SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"0123456789ABCD\r\n");
737 Richedit 1.0 receives a POINTL* on wParam and character offset on lParam, returns void.
738 Richedit 2.0 receives character offset on wParam, ignores lParam, returns MAKELONG(x,y)
739 Richedit 3.0 accepts either of the above API conventions.
742 /* Testing Richedit 1.0 API format */
744 /* Testing start of lines. X-offset should be constant on all cases (native is 1).
745 Since all lines are identical and drawn with the same font,
746 they should have the same height... right?
748 for (i = 0; i < 50; i++)
750 /* All the lines are 16 characters long */
751 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16);
752 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
753 if (i == 0)
755 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
756 ok(pl.x == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
757 xpos = pl.x;
759 else if (i == 1)
761 ok(pl.y > 0, "EM_POSFROMCHAR reports y=%d, expected > 0\n", pl.y);
762 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
763 height = pl.y;
765 else
767 ok(pl.y == i * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, i * height);
768 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
772 /* Testing position at end of text */
773 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16);
774 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
775 ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height);
776 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
778 /* Testing position way past end of text */
779 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16);
780 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
781 ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height);
782 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
785 /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */
786 SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */
787 for (i = 0; i < 50; i++)
789 /* All the lines are 16 characters long */
790 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16);
791 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
792 ok(pl.y == (i - 1) * height,
793 "EM_POSFROMCHAR reports y=%d, expected %d\n",
794 pl.y, (i - 1) * height);
795 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
798 /* Testing position at end of text */
799 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16);
800 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
801 ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height);
802 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
804 /* Testing position way past end of text */
805 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16);
806 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
807 ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height);
808 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
810 /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */
811 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
812 SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */
814 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0);
815 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
816 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
817 ok(pl.x == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
818 xpos = pl.x;
820 SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0);
821 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0);
822 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
823 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
824 todo_wine {
825 /* Fails on builtin because horizontal scrollbar is not being shown */
826 ok(pl.x < xpos, "EM_POSFROMCHAR reports x=%hd, expected value less than %d\n", pl.x, xpos);
828 DestroyWindow(hwndRichEdit);
831 static void test_word_wrap(void)
833 HWND hwnd;
834 POINTL point = {0, 60}; /* This point must be below the first line */
835 const char *text = "Must be long enough to test line wrapping";
836 DWORD dwCommonStyle = WS_VISIBLE|WS_POPUP|WS_VSCROLL|ES_MULTILINE;
837 int res, pos, lines;
839 /* Test the effect of WS_HSCROLL and ES_AUTOHSCROLL styles on wrapping
840 * when specified on window creation and set later. */
841 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
842 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
843 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
844 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
845 ok(res, "WM_SETTEXT failed.\n");
846 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
847 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
848 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
849 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
851 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL);
852 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
853 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
854 DestroyWindow(hwnd);
856 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle|WS_HSCROLL,
857 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
858 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
860 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
861 ok(res, "WM_SETTEXT failed.\n");
862 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
863 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
864 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
865 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
867 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL);
868 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
869 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
870 DestroyWindow(hwnd);
872 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle|ES_AUTOHSCROLL,
873 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
874 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
875 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
876 ok(res, "WM_SETTEXT failed.\n");
877 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
878 ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
880 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle);
881 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
882 ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
883 DestroyWindow(hwnd);
885 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL,
886 dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL,
887 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
888 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
889 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
890 ok(res, "WM_SETTEXT failed.\n");
891 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
892 ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
894 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle);
895 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
896 ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
898 /* Test the effect of EM_SETTARGETDEVICE on word wrap. */
899 res = SendMessage(hwnd, EM_SETTARGETDEVICE, 0, 1);
900 todo_wine ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
901 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
902 ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
904 res = SendMessage(hwnd, EM_SETTARGETDEVICE, 0, 0);
905 todo_wine ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
906 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
907 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
908 DestroyWindow(hwnd);
910 /* Test to see if wrapping happens with redraw disabled. */
911 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
912 0, 0, 400, 80, NULL, NULL, hmoduleRichEdit, NULL);
913 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
914 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
915 SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
916 /* redraw is disabled by making the window invisible. */
917 ok(!IsWindowVisible(hwnd), "Window shouldn't be visible.\n");
918 res = SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) text);
919 ok(res, "EM_REPLACESEL failed.\n");
920 MoveWindow(hwnd, 0, 0, 100, 80, TRUE);
921 SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
922 /* Wrapping didn't happen while redraw was disabled. */
923 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
924 todo_wine ok(lines == 1, "Line wasn't expected to wrap (lines=%d).\n", lines);
925 /* There isn't even a rewrap from resizing the window. */
926 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
927 todo_wine ok(lines == 1, "Line wasn't expected to wrap (lines=%d).\n", lines);
928 res = SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) text);
929 ok(res, "EM_REPLACESEL failed.\n");
930 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
931 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
933 DestroyWindow(hwnd);
936 static void test_EM_GETOPTIONS(void)
938 HWND hwnd;
939 DWORD options;
941 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL,
942 WS_POPUP,
943 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
944 options = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
945 ok(options == 0, "Incorrect options %x\n", options);
946 DestroyWindow(hwnd);
948 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL,
949 WS_POPUP|WS_VSCROLL|WS_HSCROLL,
950 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
951 options = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
952 ok(options == ECO_AUTOVSCROLL,
953 "Incorrect initial options %x\n", options);
954 DestroyWindow(hwnd);
957 static void test_autoscroll(void)
959 HWND hwnd;
960 UINT ret;
962 /* The WS_VSCROLL and WS_HSCROLL styles implicitly set
963 * auto vertical/horizontal scrolling options. */
964 hwnd = CreateWindowEx(0, RICHEDIT_CLASS10A, NULL,
965 WS_POPUP|ES_MULTILINE|WS_VSCROLL|WS_HSCROLL,
966 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
967 ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int) GetLastError());
968 ret = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
969 ok(ret & ECO_AUTOVSCROLL, "ECO_AUTOVSCROLL isn't set.\n");
970 ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
971 ret = GetWindowLong(hwnd, GWL_STYLE);
972 todo_wine ok(ret & ES_AUTOVSCROLL, "ES_AUTOVSCROLL isn't set.\n");
973 ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
974 DestroyWindow(hwnd);
976 hwnd = CreateWindowEx(0, RICHEDIT_CLASS, NULL,
977 WS_POPUP|ES_MULTILINE,
978 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
979 ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int) GetLastError());
980 ret = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
981 ok(!(ret & ECO_AUTOVSCROLL), "ECO_AUTOVSCROLL is set.\n");
982 ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
983 ret = GetWindowLong(hwnd, GWL_STYLE);
984 ok(!(ret & ES_AUTOVSCROLL), "ES_AUTOVSCROLL is set.\n");
985 ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
986 DestroyWindow(hwnd);
989 START_TEST( editor )
991 MSG msg;
992 time_t end;
994 /* Must explicitly LoadLibrary(). The test has no references to functions in
995 * RICHED32.DLL, so the linker doesn't actually link to it. */
996 hmoduleRichEdit = LoadLibrary("RICHED32.DLL");
997 ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
999 test_WM_SETTEXT();
1000 test_EM_GETTEXTRANGE();
1001 test_EM_GETSELTEXT();
1002 test_WM_GETTEXTLENGTH();
1003 test_EM_STREAMIN();
1004 test_EM_STREAMOUT();
1005 test_EM_GETLINE();
1006 test_EM_LINELENGTH();
1007 test_EM_FINDTEXT();
1008 test_EM_POSFROMCHAR();
1009 test_word_wrap();
1010 test_EM_GETOPTIONS();
1011 test_autoscroll();
1013 /* Set the environment variable WINETEST_RICHED32 to keep windows
1014 * responsive and open for 30 seconds. This is useful for debugging.
1016 * The message pump uses PeekMessage() to empty the queue and then sleeps for
1017 * 50ms before retrying the queue. */
1018 end = time(NULL) + 30;
1019 if (getenv( "WINETEST_RICHED32" )) {
1020 while (time(NULL) < end) {
1021 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1022 TranslateMessage(&msg);
1023 DispatchMessage(&msg);
1024 } else {
1025 Sleep(50);
1030 OleFlushClipboard();
1031 ok(FreeLibrary(hmoduleRichEdit) != 0, "error: %d\n", (int) GetLastError());