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
34 #include <wine/test.h>
36 static HMODULE hmoduleRichEdit;
38 static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
40 hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
41 |WS_VISIBLE, 0, 0, 500, 60, parent, NULL,
42 hmoduleRichEdit, NULL);
43 ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
47 static HWND new_richedit(HWND parent) {
48 return new_window(RICHEDIT_CLASS10A, ES_MULTILINE, parent);
51 static BOOL is_rtl(void) {
54 return (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE,
55 (LPSTR) &sig, sizeof(LOCALESIGNATURE)) &&
56 (sig.lsUsb[3] & 0x08000000) != 0);
59 static void test_WM_SETTEXT(void)
67 { "TestSomeText", 1, 1},
68 { "TestSomeText\r", 1, 1},
69 { "TestSomeText\rSomeMoreText\r", 2, 1, 1}, /* NT4 and below */
70 { "TestSomeText\n\nTestSomeText", 3, 3},
71 { "TestSomeText\r\r\nTestSomeText", 2, 2},
72 { "TestSomeText\r\r\n\rTestSomeText", 3, 2, 2}, /* NT4 and below */
73 { "TestSomeText\r\n\r\r\n\rTestSomeText", 4, 3, 3}, /* NT4 and below */
74 { "TestSomeText\r\n", 2, 2},
75 { "TestSomeText\r\nSomeMoreText\r\n", 3, 3},
76 { "TestSomeText\r\n\r\nTestSomeText", 3, 3},
77 { "TestSomeText TestSomeText", 1, 1},
78 { "TestSomeText \r\nTestSomeText", 2, 2},
79 { "TestSomeText\r\n \r\nTestSomeText", 3, 3},
80 { "TestSomeText\n", 2, 2},
81 { "TestSomeText\r\r\r", 3, 1, 1}, /* NT4 and below */
82 { "TestSomeText\r\r\rSomeMoreText", 4, 1, 1} /* NT4 and below */
84 HWND hwndRichEdit = new_richedit(NULL);
88 /* This test attempts to show that WM_SETTEXT on a riched32 control does not
89 * attempt to modify the text that is pasted into the control, and should
90 * return it as is. In particular, \r\r\n is NOT converted, unlike riched20.
92 * For riched32, the rules for breaking lines seem to be the following:
93 * - \r\n is one line break. This is the normal case.
94 * - \r{0,2}\n is one line break. In particular, \n by itself is a line break.
95 * - \r{0,N-1}\r\r\n is N line breaks.
96 * - \n{1,N} are that many line breaks.
97 * - \r with text or other characters (except \n) past it, is a line break. That
98 * is, a run of \r{N} without a terminating \n is considered N line breaks
99 * - \r at the end of the text is NOT a line break. This differs from riched20,
100 * where \r at the end of the text is a proper line break.
101 * However, on RTL language versions, \r is simply skipped and never used
102 * for line breaking (only \n adds a line break)
105 for (i = 0; i < sizeof(testitems)/sizeof(testitems[0]); i++) {
107 char buf[1024] = {0};
110 result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) testitems[i].itemtext);
111 ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
112 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf);
113 ok (result == lstrlen(buf),
114 "[%d] WM_GETTEXT returned %ld instead of expected %u\n",
115 i, result, lstrlen(buf));
116 result = strcmp(testitems[i].itemtext, buf);
118 "[%d] WM_SETTEXT round trip: strcmp = %ld\n", i, result);
119 result = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
120 ok (result == (rtl ? testitems[i].lines_rtl : testitems[i].lines) ||
121 broken(testitems[i].lines_broken && result == testitems[i].lines_broken),
122 "[%d] EM_GETLINECOUNT returned %ld, expected %d\n", i, result, testitems[i].lines);
125 DestroyWindow(hwndRichEdit);
128 static void test_WM_GETTEXTLENGTH(void)
130 HWND hwndRichEdit = new_richedit(NULL);
131 static const char text3[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee";
132 static const char text4[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee\r\n";
135 /* Test for WM_GETTEXTLENGTH */
136 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text3);
137 result = SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
138 ok(result == lstrlen(text3),
139 "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
140 result, lstrlen(text3));
142 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text4);
143 result = SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
144 ok(result == lstrlen(text4),
145 "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
146 result, lstrlen(text4));
148 DestroyWindow(hwndRichEdit);
151 static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie,
156 const char** str = (const char**)dwCookie;
157 int size = strlen(*str);
163 memcpy(pbBuff, *str, *pcb);
170 static void test_EM_STREAMIN(void)
172 HWND hwndRichEdit = new_richedit(NULL);
175 char buffer[1024] = {0};
177 const char * streamText0 = "{\\rtf1 TestSomeText}";
178 const char * streamText0a = "{\\rtf1 TestSomeText\\par}";
179 const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
181 const char * streamText1 =
182 "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n"
183 "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n"
186 /* This should be accepted in richedit 1.0 emulation. See bug #8326 */
187 const char * streamText2 =
188 "{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;"
189 "\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255"
190 "\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 "
191 "\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 "
192 "\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 "
193 "\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 "
194 "\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line }";
196 const char * streamText3 = "RichEdit1";
198 /* Minimal test without \par at the end */
199 es.dwCookie = (DWORD_PTR)&streamText0;
201 es.pfnCallback = test_EM_STREAMIN_esCallback;
202 SendMessage(hwndRichEdit, EM_STREAMIN,
203 (WPARAM)(SF_RTF), (LPARAM)&es);
205 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
207 "EM_STREAMIN: Test 0 returned %ld, expected 12\n", result);
208 result = strcmp (buffer,"TestSomeText");
210 "EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
211 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
213 /* Native richedit 2.0 ignores last \par */
214 es.dwCookie = (DWORD_PTR)&streamText0a;
216 es.pfnCallback = test_EM_STREAMIN_esCallback;
217 SendMessage(hwndRichEdit, EM_STREAMIN,
218 (WPARAM)(SF_RTF), (LPARAM)&es);
220 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
222 "EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
223 result = strcmp (buffer,"TestSomeText");
225 "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
226 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
228 /* Native richedit 2.0 ignores last \par, next-to-last \par appears */
229 es.dwCookie = (DWORD_PTR)&streamText0b;
231 es.pfnCallback = test_EM_STREAMIN_esCallback;
232 SendMessage(hwndRichEdit, EM_STREAMIN,
233 (WPARAM)(SF_RTF), (LPARAM)&es);
235 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
237 "EM_STREAMIN: Test 0-b returned %ld, expected 14\n", result);
238 result = strcmp (buffer,"TestSomeText\r\n");
240 "EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer);
241 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
243 es.dwCookie = (DWORD_PTR)&streamText1;
245 es.pfnCallback = test_EM_STREAMIN_esCallback;
246 SendMessage(hwndRichEdit, EM_STREAMIN,
247 (WPARAM)(SF_RTF), (LPARAM)&es);
249 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
251 "EM_STREAMIN: Test 1 returned %ld, expected 12\n", result);
252 result = strcmp (buffer,"TestSomeText");
254 "EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
255 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
258 es.dwCookie = (DWORD_PTR)&streamText2;
260 SendMessage(hwndRichEdit, EM_STREAMIN,
261 (WPARAM)(SF_RTF), (LPARAM)&es);
263 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
266 "EM_STREAMIN: Test 2 returned %ld, expected 9\n", result);
268 result = strcmp (buffer,"RichEdit1");
271 "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
273 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
275 es.dwCookie = (DWORD_PTR)&streamText3;
277 SendMessage(hwndRichEdit, EM_STREAMIN,
278 (WPARAM)(SF_RTF), (LPARAM)&es);
280 result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
282 "EM_STREAMIN: Test 3 returned %ld, expected 0\n", result);
283 ok (strlen(buffer) == 0,
284 "EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer);
285 ok(es.dwError == -16, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, -16);
287 DestroyWindow(hwndRichEdit);
290 static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
295 char** str = (char**)dwCookie;
298 memcpy(*str, pbBuff, *pcb);
304 static void test_EM_STREAMOUT(void)
306 HWND hwndRichEdit = new_richedit(NULL);
309 char buf[1024] = {0};
312 const char * TestItem1 = "TestSomeText";
313 const char * TestItem2 = "TestSomeText\r";
314 const char * TestItem3 = "TestSomeText\r\n";
316 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
318 es.dwCookie = (DWORD_PTR)&p;
320 es.pfnCallback = test_WM_SETTEXT_esCallback;
321 memset(buf, 0, sizeof(buf));
322 SendMessage(hwndRichEdit, EM_STREAMOUT,
323 (WPARAM)(SF_TEXT), (LPARAM)&es);
325 ok(r == 12, "streamed text length is %d, expecting 12\n", r);
326 ok(strcmp(buf, TestItem1) == 0,
327 "streamed text different, got %s\n", buf);
329 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
331 es.dwCookie = (DWORD_PTR)&p;
333 es.pfnCallback = test_WM_SETTEXT_esCallback;
334 memset(buf, 0, sizeof(buf));
335 SendMessage(hwndRichEdit, EM_STREAMOUT,
336 (WPARAM)(SF_TEXT), (LPARAM)&es);
339 ok(r == 13, "streamed text length is %d, expecting 13\n", r);
340 ok(strcmp(buf, TestItem2) == 0,
341 "streamed text different, got %s\n", buf);
343 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
345 es.dwCookie = (DWORD_PTR)&p;
347 es.pfnCallback = test_WM_SETTEXT_esCallback;
348 memset(buf, 0, sizeof(buf));
349 SendMessage(hwndRichEdit, EM_STREAMOUT,
350 (WPARAM)(SF_TEXT), (LPARAM)&es);
352 ok(r == 14, "streamed text length is %d, expecting 14\n", r);
353 ok(strcmp(buf, TestItem3) == 0,
354 "streamed text different, got %s\n", buf);
356 DestroyWindow(hwndRichEdit);
359 static const struct getline_s {
363 const char *broken_text;
365 {0, 10, "foo bar\r\n", "foo bar\r\n"},
366 {1, 10, "\r", "\r\r\r\n"},
367 {2, 10, "\r\r\n", "bar\n"},
368 {3, 10, "bar\n", "\r\n"},
371 /* Buffer smaller than line length */
377 static void test_EM_GETLINE(void)
380 HWND hwndRichEdit = new_richedit(NULL);
381 static const int nBuf = 1024;
382 char dest[1024], origdest[1024];
384 const char text[] = "foo bar\r\n"
388 BOOL broken_os = FALSE;
391 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
392 linecount = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
396 win_skip("Win9x, WinME and NT4 handle '\\r only' differently\n");
399 memset(origdest, 0xBB, nBuf);
400 for (i = 0; i < sizeof(gl)/sizeof(struct getline_s); i++)
402 int nCopied, expected_nCopied, expected_bytes_written;
405 if (gl[i].line >= linecount)
406 continue; /* Win9x, WinME and NT4 */
408 if (broken_os && gl[i].broken_text)
409 /* Win9x, WinME and NT4 */
410 strcpy(gl_text, gl[i].broken_text);
412 strcpy(gl_text, gl[i].text);
414 expected_nCopied = min(gl[i].buffer_len, strlen(gl_text));
415 /* Cater for the fact that Win9x, WinME and NT4 don't append the '\0' */
416 expected_bytes_written = min(gl[i].buffer_len, strlen(gl_text) + (broken_os ? 0 : 1));
418 memset(dest, 0xBB, nBuf);
419 *(WORD *) dest = gl[i].buffer_len;
421 /* EM_GETLINE appends a "\r\0" to the end of the line
422 * nCopied counts up to and including the '\r' */
423 nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest);
424 ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
426 /* two special cases since a parameter is passed via dest */
427 if (gl[i].buffer_len == 0)
428 ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
430 else if (gl[i].buffer_len == 1)
431 ok(dest[0] == gl_text[0] && !dest[1] &&
432 !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
435 ok(!strncmp(dest, gl_text, expected_bytes_written),
436 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
437 if (! rtl || expected_bytes_written == gl[i].buffer_len)
438 ok(!strncmp(dest + expected_bytes_written, origdest
439 + expected_bytes_written, nBuf - expected_bytes_written),
440 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
442 ok(dest[expected_bytes_written] == 0 &&
443 !strncmp(dest + expected_bytes_written + 1, origdest
444 + expected_bytes_written + 1, nBuf - (expected_bytes_written + 1)),
445 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
449 DestroyWindow(hwndRichEdit);
452 static void test_EM_LINELENGTH(void)
454 HWND hwndRichEdit = new_richedit(NULL);
464 int offset_test[16][2] = {
465 {0, 9}, /* Line 1: |richedit1\r */
466 {5, 9}, /* Line 1: riche|dit1\r */
467 {10, 9}, /* Line 2: |richedit1\n */
468 {15, 9}, /* Line 2: riche|dit1\n */
469 {20, 9}, /* Line 3: |richedit1\r\n */
470 {25, 9}, /* Line 3: riche|dit1\r\n */
471 {30, 9}, /* Line 3: richedit1\r|\n */
472 {31, 5}, /* Line 4: |short\r */
473 {42, 9}, /* Line 5: riche|dit1\r */
474 {46, 9}, /* Line 5: richedit1|\r */
475 {47, 0}, /* Line 6: |\r */
476 {48, 0}, /* Line 7: |\r */
477 {49, 0}, /* Line 8: |\r\r\n */
478 {50, 0}, /* Line 8: \r|\r\n */
479 {51, 0}, /* Line 8: \r\r|\n */
480 {52, 0}, /* Line 9: \r\r\n| */
485 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
487 result = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
489 win_skip("Win9x, WinME and NT4 don't handle '\\r only' correctly\n");
492 ok(result == 9, "Incorrect line count of %ld\n", result);
494 for (i = 0; i < sizeof(offset_test)/sizeof(offset_test[0]); i++) {
495 result = SendMessage(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
496 ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
497 offset_test[i][0], result, offset_test[i][1]);
500 DestroyWindow(hwndRichEdit);
503 static void test_EM_GETTEXTRANGE(void)
505 HWND hwndRichEdit = new_richedit(NULL);
506 const char * text1 = "foo bar\r\nfoo bar";
507 const char * text3 = "foo bar\rfoo bar";
508 const char * expect1 = "bar\r\nfoo";
509 const char * expect2 = "\nfoo";
510 const char * expect3 = "bar\rfoo";
511 char buffer[1024] = {0};
513 TEXTRANGEA textRange;
515 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
517 textRange.lpstrText = buffer;
518 textRange.chrg.cpMin = 4;
519 textRange.chrg.cpMax = 12;
520 result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
521 ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
522 ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
524 textRange.lpstrText = buffer;
525 textRange.chrg.cpMin = 8;
526 textRange.chrg.cpMax = 12;
527 result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
528 ok(result == 4, "EM_GETTEXTRANGE returned %ld\n", result);
529 ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
531 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text3);
533 textRange.lpstrText = buffer;
534 textRange.chrg.cpMin = 4;
535 textRange.chrg.cpMax = 11;
536 result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
537 ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
539 ok(!strcmp(expect3, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
542 DestroyWindow(hwndRichEdit);
545 static void test_EM_GETSELTEXT(void)
547 HWND hwndRichEdit = new_richedit(NULL);
548 const char * text1 = "foo bar\r\nfoo bar";
549 const char * text2 = "foo bar\rfoo bar";
550 const char * expect1 = "bar\r\nfoo";
551 const char * expect2 = "bar\rfoo";
552 char buffer[1024] = {0};
555 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
557 SendMessage(hwndRichEdit, EM_SETSEL, 4, 12);
558 result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
559 ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
560 ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
562 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
564 SendMessage(hwndRichEdit, EM_SETSEL, 4, 11);
565 result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
566 ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
568 ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
571 DestroyWindow(hwndRichEdit);
574 static const char haystack[] = "WINEWine wineWine wine WineWine";
577 static const char haystack2[] = "first\r\r\nsecond";
588 static struct find_s find_tests[] = {
589 /* Find in empty text */
590 {0, -1, "foo", FR_DOWN, -1},
591 {0, -1, "foo", 0, -1},
592 {0, -1, "", FR_DOWN, -1},
593 {20, 5, "foo", FR_DOWN, -1},
594 {5, 20, "foo", FR_DOWN, -1}
597 static struct find_s find_tests2[] = {
599 {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1},
600 {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1},
602 /* Subsequent finds */
603 {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4},
604 {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13},
605 {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
606 {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
609 {19, 20, "Wine", FR_MATCHCASE, -1},
610 {10, 20, "Wine", FR_MATCHCASE, 13},
611 {20, 10, "Wine", FR_MATCHCASE, -1},
613 /* Case-insensitive */
614 {1, 31, "wInE", FR_DOWN, 4},
615 {1, 31, "Wine", FR_DOWN, 4},
617 /* High-to-low ranges */
618 {20, 5, "Wine", FR_DOWN, -1},
619 {2, 1, "Wine", FR_DOWN, -1},
620 {30, 29, "Wine", FR_DOWN, -1},
621 {20, 5, "Wine", 0, /*13*/ -1},
624 {5, 10, "", FR_DOWN, -1},
625 {10, 5, "", FR_DOWN, -1},
626 {0, -1, "", FR_DOWN, -1},
629 /* Whole-word search */
630 {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
631 {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1},
632 {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
633 {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0},
634 {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23},
635 {11, -1, "winewine", FR_WHOLEWORD, 23},
636 {31, -1, "winewine", FR_WHOLEWORD, -1},
639 {5, 200, "XXX", FR_DOWN, -1},
640 {-20, 20, "Wine", FR_DOWN, -1},
641 {-20, 20, "Wine", FR_DOWN, -1},
642 {-15, -20, "Wine", FR_DOWN, -1},
643 {1<<12, 1<<13, "Wine", FR_DOWN, -1},
645 /* Check the case noted in bug 4479 where matches at end aren't recognized */
646 {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
647 {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
648 {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27},
649 {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
650 {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
652 /* The backwards case of bug 4479; bounds look right
653 * Fails because backward find is wrong */
654 {19, 20, "WINE", FR_MATCHCASE, -1},
655 {0, 20, "WINE", FR_MATCHCASE, 0},
657 {0, -1, "wineWine wine", FR_DOWN, 0},
658 {0, -1, "wineWine wine", 0, 0},
659 {0, -1, "INEW", 0, 1},
660 {0, 31, "INEW", 0, 1},
661 {4, -1, "INEW", 0, 10},
664 static struct find_s find_tests3[] = {
665 /* Searching for end of line characters */
666 {0, -1, "t\r\r\ns", FR_DOWN | FR_MATCHCASE, 4},
667 {6, -1, "\r\n", FR_DOWN | FR_MATCHCASE, 6},
668 {7, -1, "\n", FR_DOWN | FR_MATCHCASE, 7},
671 static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
674 memset(&ft, 0, sizeof(ft));
675 ft.chrg.cpMin = f->start;
676 ft.chrg.cpMax = f->end;
677 ft.lpstrText = f->needle;
678 findloc = SendMessage(hwnd, EM_FINDTEXT, f->flags, (LPARAM) &ft);
679 ok(findloc == f->expected_loc,
680 "EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
681 name, id, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
684 static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f,
688 int expected_end_loc;
690 memset(&ft, 0, sizeof(ft));
691 ft.chrg.cpMin = f->start;
692 ft.chrg.cpMax = f->end;
693 ft.lpstrText = f->needle;
694 ft.chrgText.cpMax = 0xdeadbeef;
695 findloc = SendMessage(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM) &ft);
696 ok(findloc == f->expected_loc,
697 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
698 name, id, f->needle, f->start, f->end, f->flags, findloc);
699 ok(ft.chrgText.cpMin == f->expected_loc,
700 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d, expected %d\n",
701 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin, f->expected_loc);
702 expected_end_loc = ((f->expected_loc == -1) ? -1
703 : f->expected_loc + strlen(f->needle));
704 ok(ft.chrgText.cpMax == expected_end_loc ||
705 broken(ft.chrgText.cpMin == -1 && ft.chrgText.cpMax == 0xdeadbeef), /* Win9x, WinME and NT4 */
706 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d, expected %d\n",
707 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax, expected_end_loc);
710 static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find,
715 for (i = 0; i < num_tests; i++) {
716 check_EM_FINDTEXT(hwnd, name, &find[i], i);
717 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
721 static void test_EM_FINDTEXT(void)
723 HWND hwndRichEdit = new_richedit(NULL);
725 /* Empty rich edit control */
726 run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests,
727 sizeof(find_tests)/sizeof(struct find_s));
729 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
732 run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2,
733 sizeof(find_tests2)/sizeof(struct find_s));
735 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack2);
737 /* Haystack text 2 (with EOL characters) */
738 run_tests_EM_FINDTEXT(hwndRichEdit, "3", find_tests3,
739 sizeof(find_tests3)/sizeof(struct find_s));
741 DestroyWindow(hwndRichEdit);
744 static void test_EM_POSFROMCHAR(void)
746 HWND hwndRichEdit = new_richedit(NULL);
750 unsigned int height = 0;
752 int xpos_rtl_adjusted = 0;
753 static const char text[] = "aa\n"
754 "this is a long line of text that should be longer than the "
763 /* Fill the control to lines to ensure that most of them are offscreen */
764 for (i = 0; i < 50; i++)
766 /* Do not modify the string; it is exactly 16 characters long. */
767 SendMessage(hwndRichEdit, EM_SETSEL, 0, 0);
768 SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"0123456789ABCD\r\n");
772 Richedit 1.0 receives a POINTL* on wParam and character offset on lParam, returns void.
773 Richedit 2.0 receives character offset on wParam, ignores lParam, returns MAKELONG(x,y)
774 Richedit 3.0 accepts either of the above API conventions.
777 /* Testing Richedit 1.0 API format */
779 /* Testing start of lines. X-offset should be constant on all cases (native is 1).
780 Since all lines are identical and drawn with the same font,
781 they should have the same height... right?
783 for (i = 0; i < 50; i++)
785 /* All the lines are 16 characters long */
786 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16);
787 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
790 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
792 broken(pl.x == 0), /* Win9x, WinME and NT4 */
793 "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
795 xpos_rtl_adjusted = xpos + (is_rtl() ? 7 : 0);
799 ok(pl.y > 0, "EM_POSFROMCHAR reports y=%d, expected > 0\n", pl.y);
800 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
805 ok(pl.y == i * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, i * height);
806 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
810 /* Testing position at end of text */
811 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16);
812 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
813 ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height);
814 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
816 /* Testing position way past end of text */
817 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16);
818 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
819 ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height);
821 ok(pl.x == xpos_rtl_adjusted, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos_rtl_adjusted);
824 /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */
825 SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */
826 for (i = 0; i < 50; i++)
828 /* All the lines are 16 characters long */
829 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16);
830 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
831 ok(pl.y == (i - 1) * height,
832 "EM_POSFROMCHAR reports y=%d, expected %d\n",
833 pl.y, (i - 1) * height);
834 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
837 /* Testing position at end of text */
838 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16);
839 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
840 ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height);
841 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
843 /* Testing position way past end of text */
844 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16);
845 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
846 ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height);
847 ok(pl.x == xpos_rtl_adjusted, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos_rtl_adjusted);
849 /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */
850 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
851 SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */
853 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0);
854 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
855 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
857 broken(pl.x == 0), /* Win9x, WinME and NT4 */
858 "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
861 SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0);
862 result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0);
863 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
864 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
866 /* Fails on builtin because horizontal scrollbar is not being shown */
868 broken(pl.x == xpos), /* Win9x, WinME and NT4 */
869 "EM_POSFROMCHAR reports x=%d, expected value less than %d\n", pl.x, xpos);
871 DestroyWindow(hwndRichEdit);
874 static void test_word_wrap(void)
877 POINTL point = {0, 60}; /* This point must be below the first line */
878 const char *text = "Must be long enough to test line wrapping";
879 DWORD dwCommonStyle = WS_VISIBLE|WS_POPUP|WS_VSCROLL|ES_MULTILINE;
880 int res, pos, lines, prevlines, reflines[3];
882 /* Test the effect of WS_HSCROLL and ES_AUTOHSCROLL styles on wrapping
883 * when specified on window creation and set later. */
884 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
885 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
886 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
887 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
888 ok(res, "WM_SETTEXT failed.\n");
889 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
890 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
891 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
892 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
894 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL);
895 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
896 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
899 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle|WS_HSCROLL,
900 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
901 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
903 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
904 ok(res, "WM_SETTEXT failed.\n");
905 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
906 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
907 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
908 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
910 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL);
911 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
912 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
915 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle|ES_AUTOHSCROLL,
916 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
917 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
918 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
919 ok(res, "WM_SETTEXT failed.\n");
920 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
922 broken(pos == lstrlen(text)), /* Win9x, WinME and NT4 */
923 "pos=%d indicating word wrap when none is expected.\n", pos);
924 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
925 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
927 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle);
928 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
930 broken(pos == lstrlen(text)), /* Win9x, WinME and NT4 */
931 "pos=%d indicating word wrap when none is expected.\n", pos);
932 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
933 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
936 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL,
937 dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL,
938 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
939 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
940 res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
941 ok(res, "WM_SETTEXT failed.\n");
942 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
944 broken(pos == lstrlen(text)), /* Win9x, WinME and NT4 */
945 "pos=%d indicating word wrap when none is expected.\n", pos);
946 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
947 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
949 SetWindowLong(hwnd, GWL_STYLE, dwCommonStyle);
950 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
952 broken(pos == lstrlen(text)), /* Win9x, WinME and NT4 */
953 "pos=%d indicating word wrap when none is expected.\n", pos);
954 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
955 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
957 /* Test the effect of EM_SETTARGETDEVICE on word wrap. */
958 res = SendMessage(hwnd, EM_SETTARGETDEVICE, 0, 1);
959 ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
960 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
962 broken(pos == lstrlen(text)), /* Win9x, WinME and NT4 */
963 "pos=%d indicating word wrap when none is expected.\n", pos);
964 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
965 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
967 res = SendMessage(hwnd, EM_SETTARGETDEVICE, 0, 0);
968 ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
969 pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
970 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
973 /* First lets see if the text would wrap normally (needed for reference) */
974 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
975 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
976 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
977 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
978 res = SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) text);
979 ok(res, "EM_REPLACESEL failed.\n");
980 /* Should have wrapped */
981 reflines[0] = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
982 ok(reflines[0] > 1, "Line was expected to wrap (%d lines).\n", reflines[0]);
983 /* Resize the window to fit the line */
984 MoveWindow(hwnd, 0, 0, 600, 80, TRUE);
985 /* Text should not be wrapped */
986 reflines[1] = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
987 ok(reflines[1] == 1, "Line wasn't expected to wrap (%d lines).\n", reflines[1]);
988 /* Resize the window again to make sure the line wraps again */
989 MoveWindow(hwnd, 0, 0, 10, 80, TRUE);
990 reflines[2] = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
991 ok(reflines[2] > 1, "Line was expected to wrap (%d lines).\n", reflines[2]);
994 /* Same test with redraw disabled */
995 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
996 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
997 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
998 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
999 /* Redraw is disabled by making the window invisible. */
1000 SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
1001 ok(!IsWindowVisible(hwnd), "Window shouldn't be visible.\n");
1002 res = SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) text);
1003 ok(res, "EM_REPLACESEL failed.\n");
1004 /* Should have wrapped */
1005 prevlines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
1006 ok(prevlines == reflines[0],
1007 "Line was expected to wrap (%d lines).\n", prevlines);
1008 /* Resize the window to fit the line, no change to the number of lines */
1009 MoveWindow(hwnd, 0, 0, 600, 80, TRUE);
1010 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
1012 ok(lines == prevlines ||
1013 broken(lines == reflines[1]), /* Win98, WinME and NT4 */
1014 "Expected no change in the number of lines\n");
1015 /* Resize the window again to make sure the line wraps again */
1016 MoveWindow(hwnd, 0, 0, 10, 80, TRUE);
1017 lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
1019 ok(lines == prevlines ||
1020 broken(lines == reflines[2]), /* Win98, WinME and NT4 */
1021 "Expected no change in the number of lines\n");
1022 DestroyWindow(hwnd);
1025 static void test_EM_GETOPTIONS(void)
1030 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL,
1032 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1033 options = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
1034 ok(options == 0, "Incorrect options %x\n", options);
1035 DestroyWindow(hwnd);
1037 hwnd = CreateWindow(RICHEDIT_CLASS10A, NULL,
1038 WS_POPUP|WS_VSCROLL|WS_HSCROLL,
1039 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1040 options = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
1041 ok(options == ECO_AUTOVSCROLL ||
1042 broken(options == 0), /* Win9x, WinME and NT4 */
1043 "Incorrect initial options %x\n", options);
1044 DestroyWindow(hwnd);
1047 static void test_autoscroll(void)
1052 /* The WS_VSCROLL and WS_HSCROLL styles implicitly set
1053 * auto vertical/horizontal scrolling options. */
1054 hwnd = CreateWindowEx(0, RICHEDIT_CLASS10A, NULL,
1055 WS_POPUP|ES_MULTILINE|WS_VSCROLL|WS_HSCROLL,
1056 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1057 ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS10A, (int) GetLastError());
1058 ret = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
1059 ok(ret & ECO_AUTOVSCROLL ||
1060 broken(!(ret & ECO_AUTOVSCROLL)), /* Win9x, WinME and NT4 */
1061 "ECO_AUTOVSCROLL isn't set.\n");
1062 ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
1063 ret = GetWindowLong(hwnd, GWL_STYLE);
1065 ok(ret & ES_AUTOVSCROLL ||
1066 broken(!(ret & ES_AUTOVSCROLL)), /* Win9x, WinMe and NT4 */
1067 "ES_AUTOVSCROLL isn't set.\n");
1068 ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
1069 DestroyWindow(hwnd);
1071 hwnd = CreateWindowEx(0, RICHEDIT_CLASS10A, NULL,
1072 WS_POPUP|ES_MULTILINE,
1073 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1074 ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS10A, (int) GetLastError());
1075 ret = SendMessage(hwnd, EM_GETOPTIONS, 0, 0);
1076 ok(!(ret & ECO_AUTOVSCROLL), "ECO_AUTOVSCROLL is set.\n");
1077 ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
1078 ret = GetWindowLong(hwnd, GWL_STYLE);
1079 ok(!(ret & ES_AUTOVSCROLL), "ES_AUTOVSCROLL is set.\n");
1080 ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
1081 DestroyWindow(hwnd);
1084 START_TEST( editor )
1090 /* Must explicitly LoadLibrary(). The test has no references to functions in
1091 * RICHED32.DLL, so the linker doesn't actually link to it. */
1092 hmoduleRichEdit = LoadLibrary("RICHED32.DLL");
1093 ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
1096 test_EM_GETTEXTRANGE();
1097 test_EM_GETSELTEXT();
1098 test_WM_GETTEXTLENGTH();
1100 test_EM_STREAMOUT();
1102 test_EM_LINELENGTH();
1104 test_EM_POSFROMCHAR();
1106 test_EM_GETOPTIONS();
1109 /* Set the environment variable WINETEST_RICHED32 to keep windows
1110 * responsive and open for 30 seconds. This is useful for debugging.
1112 * The message pump uses PeekMessage() to empty the queue and then sleeps for
1113 * 50ms before retrying the queue. */
1114 end = time(NULL) + 30;
1115 if (getenv( "WINETEST_RICHED32" )) {
1116 while (time(NULL) < end) {
1117 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1118 TranslateMessage(&msg);
1119 DispatchMessage(&msg);
1126 OleFlushClipboard();
1127 ret = FreeLibrary(hmoduleRichEdit);
1128 ok(ret, "error: %u\n", GetLastError());