2 * Unit test suite for rich edit control
4 * Copyright 2006 Google (Thomas Kho)
5 * Copyright 2007 Matt Finnicum
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <wine/test.h>
28 static HMODULE hmoduleRichEdit;
30 static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
32 hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
33 |WS_VISIBLE, 0, 0, 200, 60, parent, NULL,
34 hmoduleRichEdit, NULL);
35 ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
39 static HWND new_richedit(HWND parent) {
40 return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent);
43 static const char haystack[] = "WINEWine wineWine wine WineWine";
56 struct find_s find_tests[] = {
57 /* Find in empty text */
58 {0, -1, "foo", FR_DOWN, -1, 0},
59 {0, -1, "foo", 0, -1, 0},
60 {0, -1, "", FR_DOWN, -1, 0},
61 {20, 5, "foo", FR_DOWN, -1, 0},
62 {5, 20, "foo", FR_DOWN, -1, 0}
65 struct find_s find_tests2[] = {
67 {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1, 0},
68 {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1, 0},
70 /* Subsequent finds */
71 {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4, 0},
72 {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13, 0},
73 {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
74 {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
77 {19, 20, "Wine", FR_MATCHCASE, 13, 0},
78 {10, 20, "Wine", FR_MATCHCASE, 4, 0},
79 {20, 10, "Wine", FR_MATCHCASE, 13, 0},
81 /* Case-insensitive */
82 {1, 31, "wInE", FR_DOWN, 4, 0},
83 {1, 31, "Wine", FR_DOWN, 4, 0},
85 /* High-to-low ranges */
86 {20, 5, "Wine", FR_DOWN, -1, 0},
87 {2, 1, "Wine", FR_DOWN, -1, 0},
88 {30, 29, "Wine", FR_DOWN, -1, 0},
89 {20, 5, "Wine", 0, 13, 0},
92 {5, 10, "", FR_DOWN, -1, 0},
93 {10, 5, "", FR_DOWN, -1, 0},
94 {0, -1, "", FR_DOWN, -1, 0},
95 {10, 5, "", 0, -1, 0},
97 /* Whole-word search */
98 {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 0},
99 {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1, 0},
100 {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 0},
101 {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0, 0},
102 {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23, 0},
103 {11, -1, "winewine", FR_WHOLEWORD, 0, 0},
104 {31, -1, "winewine", FR_WHOLEWORD, 23, 0},
107 {5, 200, "XXX", FR_DOWN, -1, 0},
108 {-20, 20, "Wine", FR_DOWN, -1, 0},
109 {-20, 20, "Wine", FR_DOWN, -1, 0},
110 {-15, -20, "Wine", FR_DOWN, -1, 0},
111 {1<<12, 1<<13, "Wine", FR_DOWN, -1, 0},
113 /* Check the case noted in bug 4479 where matches at end aren't recognized */
114 {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
115 {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
116 {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
117 {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
118 {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
120 /* The backwards case of bug 4479; bounds look right
121 * Fails because backward find is wrong */
122 {19, 20, "WINE", FR_MATCHCASE, 0, 0},
123 {0, 20, "WINE", FR_MATCHCASE, -1, 0}
126 static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
129 memset(&ft, 0, sizeof(ft));
130 ft.chrg.cpMin = f->start;
131 ft.chrg.cpMax = f->end;
132 ft.lpstrText = f->needle;
133 findloc = SendMessage(hwnd, EM_FINDTEXT, f->flags, (LPARAM) &ft);
134 ok(findloc == f->expected_loc,
135 "EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d\n",
136 name, id, f->needle, f->start, f->end, f->flags, findloc);
139 static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f,
143 memset(&ft, 0, sizeof(ft));
144 ft.chrg.cpMin = f->start;
145 ft.chrg.cpMax = f->end;
146 ft.lpstrText = f->needle;
147 findloc = SendMessage(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM) &ft);
148 ok(findloc == f->expected_loc,
149 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
150 name, id, f->needle, f->start, f->end, f->flags, findloc);
151 ok(ft.chrgText.cpMin == f->expected_loc,
152 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
153 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin);
154 ok(ft.chrgText.cpMax == ((f->expected_loc == -1) ? -1
155 : f->expected_loc + strlen(f->needle)),
156 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d\n",
157 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax);
160 static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find,
165 for (i = 0; i < num_tests; i++) {
166 if (find[i]._todo_wine) {
168 check_EM_FINDTEXT(hwnd, name, &find[i], i);
169 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
172 check_EM_FINDTEXT(hwnd, name, &find[i], i);
173 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
178 static void test_EM_FINDTEXT(void)
180 HWND hwndRichEdit = new_richedit(NULL);
182 /* Empty rich edit control */
183 run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests,
184 sizeof(find_tests)/sizeof(struct find_s));
186 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
189 run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2,
190 sizeof(find_tests2)/sizeof(struct find_s));
192 DestroyWindow(hwndRichEdit);
195 static const struct getline_s {
200 {0, 10, "foo bar\r"},
205 /* Buffer smaller than line length */
211 static void test_EM_GETLINE(void)
214 HWND hwndRichEdit = new_richedit(NULL);
215 static const int nBuf = 1024;
216 char dest[1024], origdest[1024];
217 const char text[] = "foo bar\n"
221 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
223 memset(origdest, 0xBB, nBuf);
224 for (i = 0; i < sizeof(gl)/sizeof(struct getline_s); i++)
227 int expected_nCopied = min(gl[i].buffer_len, strlen(gl[i].text));
228 int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text) + 1);
229 memset(dest, 0xBB, nBuf);
230 *(WORD *) dest = gl[i].buffer_len;
232 /* EM_GETLINE appends a "\r\0" to the end of the line
233 * nCopied counts up to and including the '\r' */
234 nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest);
235 ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
237 /* two special cases since a parameter is passed via dest */
238 if (gl[i].buffer_len == 0)
239 ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
241 else if (gl[i].buffer_len == 1)
242 ok(dest[0] == gl[i].text[0] && !dest[1] &&
243 !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
246 ok(!strncmp(dest, gl[i].text, expected_bytes_written),
247 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
248 ok(!strncmp(dest + expected_bytes_written, origdest
249 + expected_bytes_written, nBuf - expected_bytes_written),
250 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
254 DestroyWindow(hwndRichEdit);
257 static int get_scroll_pos_y(HWND hwnd)
260 SendMessage(hwnd, EM_GETSCROLLPOS, 0, (LPARAM) &p);
261 ok(p.x != -1 && p.y != -1, "p.x:%d p.y:%d\n", p.x, p.y);
265 static void move_cursor(HWND hwnd, long charindex)
268 cr.cpMax = charindex;
269 cr.cpMin = charindex;
270 SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) &cr);
273 static void line_scroll(HWND hwnd, int amount)
275 SendMessage(hwnd, EM_LINESCROLL, 0, amount);
278 static void test_EM_SCROLLCARET(void)
281 HWND hwndRichEdit = new_richedit(NULL);
282 const char text[] = "aa\n"
283 "this is a long line of text that should be longer than the "
292 /* Can't verify this */
293 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
295 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
297 /* Caret above visible window */
298 line_scroll(hwndRichEdit, 3);
299 prevY = get_scroll_pos_y(hwndRichEdit);
300 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
301 curY = get_scroll_pos_y(hwndRichEdit);
302 ok(prevY != curY, "%d == %d\n", prevY, curY);
304 /* Caret below visible window */
305 move_cursor(hwndRichEdit, sizeof(text) - 1);
306 line_scroll(hwndRichEdit, -3);
307 prevY = get_scroll_pos_y(hwndRichEdit);
308 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
309 curY = get_scroll_pos_y(hwndRichEdit);
310 ok(prevY != curY, "%d == %d\n", prevY, curY);
312 /* Caret in visible window */
313 move_cursor(hwndRichEdit, sizeof(text) - 2);
314 prevY = get_scroll_pos_y(hwndRichEdit);
315 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
316 curY = get_scroll_pos_y(hwndRichEdit);
317 ok(prevY == curY, "%d != %d\n", prevY, curY);
319 /* Caret still in visible window */
320 line_scroll(hwndRichEdit, -1);
321 prevY = get_scroll_pos_y(hwndRichEdit);
322 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
323 curY = get_scroll_pos_y(hwndRichEdit);
324 ok(prevY == curY, "%d != %d\n", prevY, curY);
326 DestroyWindow(hwndRichEdit);
329 static void test_EM_SETTEXTMODE(void)
331 HWND hwndRichEdit = new_richedit(NULL);
332 CHARFORMAT2 cf2, cf2test;
336 /*Test that EM_SETTEXTMODE fails if text exists within the control*/
337 /*Insert text into the control*/
339 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
341 /*Attempt to change the control to plain text mode*/
342 rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_PLAINTEXT, 0);
343 ok(rc != 0, "EM_SETTEXTMODE: changed text mode in control containing text - returned: %d\n", rc);
345 /*Test that EM_SETTEXTMODE does not allow rich edit text to be pasted.
346 If rich text is pasted, it should have the same formatting as the rest
347 of the text in the control*/
350 *NOTE: If the default text was already italicized, the test will simply
351 reverse; in other words, it will copy a regular "wine" into a plain
352 text window that uses an italicized format*/
353 cf2.cbSize = sizeof(CHARFORMAT2);
354 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT,
357 cf2.dwMask = CFM_ITALIC | cf2.dwMask;
358 cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
360 /*EM_SETCHARFORMAT is not yet fully implemented for all WPARAMs in wine;
361 however, SCF_ALL has been implemented*/
362 SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
363 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
365 /*Select the string "wine"*/
368 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
370 /*Copy the italicized "wine" to the clipboard*/
371 SendMessage(hwndRichEdit, WM_COPY, 0, 0);
373 /*Reset the formatting to default*/
374 cf2.dwEffects = CFE_ITALIC^cf2.dwEffects;
375 SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
377 /*Clear the text in the control*/
378 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "");
380 /*Switch to Plain Text Mode*/
381 rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_PLAINTEXT, 0);
382 ok(rc == 0, "EM_SETTEXTMODE: unable to switch to plain text mode with empty control: returned: %d\n", rc);
384 /*Input "wine" again in normal format*/
385 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
387 /*Paste the italicized "wine" into the control*/
388 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
390 /*Select a character from the first "wine" string*/
393 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
395 /*Retrieve its formatting*/
396 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION,
399 /*Select a character from the second "wine" string*/
402 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
404 /*Retrieve its formatting*/
405 cf2test.cbSize = sizeof(CHARFORMAT2);
406 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION,
409 /*Compare the two formattings*/
410 ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects),
411 "two formats found in plain text mode - cf2.dwEffects: %x cf2test.dwEffects: %x\n",
412 cf2.dwEffects, cf2test.dwEffects);
413 /*Test TM_RICHTEXT by: switching back to Rich Text mode
414 printing "wine" in the current format(normal)
415 pasting "wine" from the clipboard(italicized)
416 comparing the two formats(should differ)*/
418 /*Attempt to switch with text in control*/
419 rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_RICHTEXT, 0);
420 ok(rc != 0, "EM_SETTEXTMODE: changed from plain text to rich text with text in control - returned: %d\n", rc);
423 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "");
425 /*Switch into Rich Text mode*/
426 rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_RICHTEXT, 0);
427 ok(rc == 0, "EM_SETTEXTMODE: unable to change to rich text with empty control - returned: %d\n", rc);
429 /*Print "wine" in normal formatting into the control*/
430 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
432 /*Paste italicized "wine" into the control*/
433 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
435 /*Select text from the first "wine" string*/
438 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
440 /*Retrieve its formatting*/
441 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION,
444 /*Select text from the second "wine" string*/
447 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
449 /*Retrieve its formatting*/
450 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION,
453 /*Test that the two formattings are not the same*/
454 todo_wine ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects != cf2test.dwEffects),
455 "expected different formats - cf2.dwMask: %x, cf2test.dwMask: %x, cf2.dwEffects: %x, cf2test.dwEffects: %x\n",
456 cf2.dwMask, cf2test.dwMask, cf2.dwEffects, cf2test.dwEffects);
458 DestroyWindow(hwndRichEdit);
461 static void test_TM_PLAINTEXT(void)
463 /*Tests plain text properties*/
465 HWND hwndRichEdit = new_richedit(NULL);
466 CHARFORMAT2 cf2, cf2test;
469 /*Switch to plain text mode*/
471 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "");
472 SendMessage(hwndRichEdit, EM_SETTEXTMODE, TM_PLAINTEXT, 0);
474 /*Fill control with text*/
476 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "Is Wine an emulator? No it's not");
478 /*Select some text and bold it*/
482 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
483 cf2.cbSize = sizeof(CHARFORMAT2);
484 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT,
487 cf2.dwMask = CFM_BOLD | cf2.dwMask;
488 cf2.dwEffects = CFE_BOLD ^ cf2.dwEffects;
490 SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2);
492 /*Get the formatting of those characters*/
494 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2);
496 /*Get the formatting of some other characters*/
497 cf2test.cbSize = sizeof(CHARFORMAT2);
500 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
501 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2test);
503 /*Test that they are the same as plain text allows only one formatting*/
505 ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects),
506 "two selections' formats differ - cf2.dwMask: %x, cf2test.dwMask %x, cf2.dwEffects: %x, cf2test.dwEffects: %x\n",
507 cf2.dwMask, cf2test.dwMask, cf2.dwEffects, cf2test.dwEffects);
509 /*Fill the control with a "wine" string, which when inserted will be bold*/
511 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
513 /*Copy the bolded "wine" string*/
517 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
518 SendMessage(hwndRichEdit, WM_COPY, 0, 0);
520 /*Swap back to rich text*/
522 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "");
523 SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_RICHTEXT, 0);
525 /*Set the default formatting to bold italics*/
527 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT, (LPARAM) &cf2);
528 cf2.dwMask |= CFM_ITALIC;
529 cf2.dwEffects ^= CFE_ITALIC;
530 SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
532 /*Set the text in the control to "wine", which will be bold and italicized*/
534 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
536 /*Paste the plain text "wine" string, which should take the insert
537 formatting, which at the moment is bold italics*/
539 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
541 /*Select the first "wine" string and retrieve its formatting*/
545 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
546 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2);
548 /*Select the second "wine" string and retrieve its formatting*/
552 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
553 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2test);
555 /*Compare the two formattings. They should be the same.*/
557 ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects),
558 "Copied text retained formatting - cf2.dwMask: %x, cf2test.dwMask: %x, cf2.dwEffects: %x, cf2test.dwEffects: %x\n",
559 cf2.dwMask, cf2test.dwMask, cf2.dwEffects, cf2test.dwEffects);
560 DestroyWindow(hwndRichEdit);
563 static void test_WM_GETTEXT(void)
565 HWND hwndRichEdit = new_richedit(NULL);
566 static const char text[] = "Hello. My name is RichEdit!";
567 char buffer[1024] = {0};
570 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
571 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
572 result = strcmp(buffer,text);
574 "WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
575 DestroyWindow(hwndRichEdit);
578 /* FIXME: need to test unimplemented options and robustly test wparam */
579 static void test_EM_SETOPTIONS(void)
581 HWND hwndRichEdit = new_richedit(NULL);
582 static const char text[] = "Hello. My name is RichEdit!";
583 char buffer[1024] = {0};
585 /* NEGATIVE TESTING - NO OPTIONS SET */
586 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
587 SendMessage(hwndRichEdit, EM_SETOPTIONS, ECOOP_SET, 0);
589 /* testing no readonly by sending 'a' to the control*/
590 SetFocus(hwndRichEdit);
591 SendMessage(hwndRichEdit, WM_CHAR, 'a', 0x1E0001);
592 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
594 "EM_SETOPTIONS: Text not changed! s1:%s s2:%s\n", text, buffer);
595 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
597 /* READONLY - sending 'a' to the control */
598 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
599 SendMessage(hwndRichEdit, EM_SETOPTIONS, ECOOP_SET, ECO_READONLY);
600 SetFocus(hwndRichEdit);
601 SendMessage(hwndRichEdit, WM_CHAR, 'a', 0x1E0001);
602 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
603 ok(buffer[0]==text[0],
604 "EM_SETOPTIONS: Text changed! s1:%s s2:%s\n", text, buffer);
606 DestroyWindow(hwndRichEdit);
609 static void check_CFE_LINK_rcvd(HWND hwnd, int is_url)
611 CHARFORMAT2W text_format;
612 int link_present = 0;
613 text_format.cbSize = sizeof(text_format);
614 SendMessage(hwnd, EM_SETSEL, 0, 0);
615 SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM) &text_format);
616 link_present = text_format.dwEffects & CFE_LINK;
618 { /* control text is url; should get CFE_LINK */
619 ok(0 != link_present, "URL Case: CFE_LINK not set.\n");
623 ok(0 == link_present, "Non-URL Case: CFE_LINK set.\n");
627 static HWND new_static_wnd(HWND parent) {
628 return new_window("Static", 0, parent);
631 static void test_EM_AUTOURLDETECT(void)
638 {"http://www.winehq.org", 1},
639 {"http//winehq.org", 0},
640 {"ww.winehq.org", 0},
641 {"www.winehq.org", 1},
642 {"ftp://192.168.1.1", 1},
643 {"ftp//192.168.1.1", 0},
644 {"mailto:your@email.com", 1},
645 {"prospero:prosperoserver", 1},
647 {"news:newserver", 1},
648 {"wais:waisserver", 1}
653 HWND hwndRichEdit, parent;
655 parent = new_static_wnd(NULL);
656 hwndRichEdit = new_richedit(parent);
657 /* Try and pass EM_AUTOURLDETECT some test wParam values */
658 urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, FALSE, 0);
659 ok(urlRet==0, "Good wParam: urlRet is: %d\n", urlRet);
660 urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, 1, 0);
661 ok(urlRet==0, "Good wParam2: urlRet is: %d\n", urlRet);
662 /* Windows returns -2147024809 (0x80070057) on bad wParam values */
663 urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, 8, 0);
664 ok(urlRet==E_INVALIDARG, "Bad wParam: urlRet is: %d\n", urlRet);
665 urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, (WPARAM)"h", (LPARAM)"h");
666 ok(urlRet==E_INVALIDARG, "Bad wParam2: urlRet is: %d\n", urlRet);
667 /* for each url, check the text to see if CFE_LINK effect is present */
668 for (i = 0; i < sizeof(urls)/sizeof(struct urls_s); i++) {
669 SendMessage(hwndRichEdit, EM_AUTOURLDETECT, FALSE, 0);
670 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) urls[i].text);
671 SendMessage(hwndRichEdit, WM_CHAR, 0, 0);
672 check_CFE_LINK_rcvd(hwndRichEdit, 0);
673 SendMessage(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
674 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) urls[i].text);
675 SendMessage(hwndRichEdit, WM_CHAR, 0, 0);
676 check_CFE_LINK_rcvd(hwndRichEdit, urls[i].is_url);
678 DestroyWindow(hwndRichEdit);
679 DestroyWindow(parent);
682 static void test_EM_SCROLL(void)
685 int r; /* return value */
686 int expr; /* expected return value */
687 HWND hwndRichEdit = new_richedit(NULL);
688 int y_before, y_after; /* units of lines of text */
690 /* test a richedit box containing a single line of text */
691 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "a");/* one line of text */
693 for (i = 0; i < 4; i++) {
694 static const int cmd[4] = { SB_PAGEDOWN, SB_PAGEUP, SB_LINEDOWN, SB_LINEUP };
696 r = SendMessage(hwndRichEdit, EM_SCROLL, cmd[i], 0);
697 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
698 ok(expr == r, "EM_SCROLL improper return value returned (i == %d). "
699 "Got 0x%08x, expected 0x%08x\n", i, r, expr);
700 ok(y_after == 0, "EM_SCROLL improper scroll. scrolled to line %d, not 1 "
701 "(i == %d)\n", y_after, i);
705 * test a richedit box that will scroll. There are two general
706 * cases: the case without any long lines and the case with a long
709 for (i = 0; i < 2; i++) { /* iterate through different bodies of text */
711 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "a\nb\nc\nd\ne");
713 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)
714 "a LONG LINE LONG LINE LONG LINE LONG LINE LONG LINE "
715 "LONG LINE LONG LINE LONG LINE LONG LINE LONG LINE "
716 "LONG LINE \nb\nc\nd\ne");
717 for (j = 0; j < 12; j++) /* reset scrol position to top */
718 SendMessage(hwndRichEdit, EM_SCROLL, SB_PAGEUP, 0);
720 /* get first visible line */
721 y_before = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
722 r = SendMessage(hwndRichEdit, EM_SCROLL, SB_PAGEDOWN, 0); /* page down */
724 /* get new current first visible line */
725 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
727 ok(((r & 0xffffff00) == 0x00010000) &&
728 ((r & 0x000000ff) != 0x00000000),
729 "EM_SCROLL page down didn't scroll by a small positive number of "
730 "lines (r == 0x%08x)\n", r);
731 ok(y_after > y_before, "EM_SCROLL page down not functioning "
732 "(line %d scrolled to line %d\n", y_before, y_after);
736 r = SendMessage(hwndRichEdit, EM_SCROLL, SB_PAGEUP, 0); /* page up */
737 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
738 ok(((r & 0xffffff00) == 0x0001ff00),
739 "EM_SCROLL page up didn't scroll by a small negative number of lines "
740 "(r == 0x%08x)\n", r);
741 ok(y_after < y_before, "EM_SCROLL page up not functioning (line "
742 "%d scrolled to line %d\n", y_before, y_after);
746 r = SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */
748 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
750 ok(r == 0x00010001, "EM_SCROLL line down didn't scroll by one line "
751 "(r == 0x%08x)\n", r);
752 ok(y_after -1 == y_before, "EM_SCROLL line down didn't go down by "
753 "1 line (%d scrolled to %d)\n", y_before, y_after);
757 r = SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */
759 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
761 ok(r == 0x0001ffff, "EM_SCROLL line up didn't scroll by one line "
762 "(r == 0x%08x)\n", r);
763 ok(y_after +1 == y_before, "EM_SCROLL line up didn't go up by 1 "
764 "line (%d scrolled to %d)\n", y_before, y_after);
768 r = SendMessage(hwndRichEdit, EM_SCROLL,
769 SB_LINEUP, 0); /* lineup beyond top */
771 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
774 "EM_SCROLL line up returned indicating movement (0x%08x)\n", r);
775 ok(y_before == y_after,
776 "EM_SCROLL line up beyond top worked (%d)\n", y_after);
780 r = SendMessage(hwndRichEdit, EM_SCROLL,
781 SB_PAGEUP, 0);/*page up beyond top */
783 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
786 "EM_SCROLL page up returned indicating movement (0x%08x)\n", r);
787 ok(y_before == y_after,
788 "EM_SCROLL page up beyond top worked (%d)\n", y_after);
790 for (j = 0; j < 12; j++) /* page down all the way to the bottom */
791 SendMessage(hwndRichEdit, EM_SCROLL, SB_PAGEDOWN, 0);
792 y_before = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
793 r = SendMessage(hwndRichEdit, EM_SCROLL,
794 SB_PAGEDOWN, 0); /* page down beyond bot */
795 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
798 "EM_SCROLL page down returned indicating movement (0x%08x)\n", r);
799 ok(y_before == y_after,
800 "EM_SCROLL page down beyond bottom worked (%d -> %d)\n",
803 y_before = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
804 SendMessage(hwndRichEdit, EM_SCROLL,
805 SB_LINEDOWN, 0); /* line down beyond bot */
806 y_after = SendMessage(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
809 "EM_SCROLL line down returned indicating movement (0x%08x)\n", r);
810 ok(y_before == y_after,
811 "EM_SCROLL line down beyond bottom worked (%d -> %d)\n",
814 DestroyWindow(hwndRichEdit);
817 static void test_EM_SETUNDOLIMIT(void)
819 /* cases we test for:
820 * default behaviour - limiting at 100 undo's
821 * undo disabled - setting a limit of 0
822 * undo limited - undo limit set to some to some number, like 2
823 * bad input - sending a negative number should default to 100 undo's */
825 HWND hwndRichEdit = new_richedit(NULL);
830 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "x");
833 SendMessage(hwndRichEdit, WM_COPY, 0, 0);
834 /*Load "x" into the clipboard. Paste is an easy, undo'able operation.
835 also, multiple pastes don't combine like WM_CHAR would */
836 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
838 /* first case - check the default */
839 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
840 for (i=0; i<101; i++) /* Put 101 undo's on the stack */
841 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
842 for (i=0; i<100; i++) /* Undo 100 of them */
843 SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
844 ok(!SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
845 "EM_SETUNDOLIMIT allowed more than a hundred undo's by default.\n");
847 /* second case - cannot undo */
848 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0, 0);
849 SendMessage(hwndRichEdit, EM_SETUNDOLIMIT, 0, 0);
850 SendMessage(hwndRichEdit,
851 WM_PASTE, 0, 0); /* Try to put something in the undo stack */
852 ok(!SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
853 "EM_SETUNDOLIMIT allowed undo with UNDOLIMIT set to 0\n");
855 /* third case - set it to an arbitrary number */
856 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0, 0);
857 SendMessage(hwndRichEdit, EM_SETUNDOLIMIT, 2, 0);
858 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
859 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
860 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
861 /* If SETUNDOLIMIT is working, there should only be two undo's after this */
862 ok(SendMessage(hwndRichEdit, EM_CANUNDO, 0,0),
863 "EM_SETUNDOLIMIT didn't allow the first undo with UNDOLIMIT set to 2\n");
864 SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
865 ok(SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
866 "EM_SETUNDOLIMIT didn't allow a second undo with UNDOLIMIT set to 2\n");
867 SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
868 ok(!SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
869 "EM_SETUNDOLIMIT allowed a third undo with UNDOLIMIT set to 2\n");
871 /* fourth case - setting negative numbers should default to 100 undos */
872 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
873 result = SendMessage(hwndRichEdit, EM_SETUNDOLIMIT, -1, 0);
875 "EM_SETUNDOLIMIT returned %d when set to -1, instead of 100\n",result);
877 DestroyWindow(hwndRichEdit);
880 static void test_ES_PASSWORD(void)
882 /* This isn't hugely testable, so we're just going to run it through it's paces. */
884 HWND hwndRichEdit = new_richedit(NULL);
887 /* First, check the default of a regular control */
888 result = SendMessage(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
890 "EM_GETPASSWORDCHAR returned %c by default, instead of NULL\n",result);
892 /* Now, set it to something normal */
893 SendMessage(hwndRichEdit, EM_SETPASSWORDCHAR, 'x', 0);
894 result = SendMessage(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
896 "EM_GETPASSWORDCHAR returned %c (%d) when set to 'x', instead of x (120)\n",result,result);
898 /* Now, set it to something odd */
899 SendMessage(hwndRichEdit, EM_SETPASSWORDCHAR, (WCHAR)1234, 0);
900 result = SendMessage(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
902 "EM_GETPASSWORDCHAR returned %c (%d) when set to 'x', instead of x (120)\n",result,result);
903 DestroyWindow(hwndRichEdit);
906 static void test_EM_SETTEXTEX(void)
908 HWND hwndRichEdit = new_richedit(NULL);
911 WCHAR TestItem1[] = {'T', 'e', 's', 't',
913 'T', 'e', 'x', 't', 0};
914 #define MAX_BUF_LEN 1024
915 WCHAR buf[MAX_BUF_LEN];
919 setText.codepage = 1200; /* no constant for unicode */
920 getText.codepage = 1200; /* no constant for unicode */
921 getText.cb = MAX_BUF_LEN;
922 getText.flags = GT_DEFAULT;
925 SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1);
926 SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf);
927 ok(lstrcmpW(buf, TestItem1) == 0,
928 "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
930 result = SendMessage(hwndRichEdit, EM_SETTEXTEX,
931 (WPARAM)&setText, (LPARAM) NULL);
932 SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf);
935 "EM_SETTEXTEX returned %d, instead of 1\n",result);
936 ok(lstrlenW(buf) == 0,
937 "EM_SETTEXTEX with NULL lParam should clear rich edit.\n");
939 /* put some text back */
941 SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1);
942 /* select some text */
945 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
946 /* replace current selection */
947 setText.flags = ST_SELECTION;
948 result = SendMessage(hwndRichEdit, EM_SETTEXTEX,
949 (WPARAM)&setText, (LPARAM) NULL);
951 "EM_SETTEXTEX with NULL lParam to replace selection"
952 " with no text should return 0. Got %i\n",
955 /* put some text back */
957 SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1);
958 /* select some text */
961 SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
962 /* replace current selection */
963 setText.flags = ST_SELECTION;
964 result = SendMessage(hwndRichEdit, EM_SETTEXTEX,
965 (WPARAM)&setText, (LPARAM) TestItem1);
967 SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf);
968 ok(result == lstrlenW(TestItem1),
969 "EM_SETTEXTEX with NULL lParam to replace selection"
970 " with no text should return 0. Got %i\n",
972 ok(lstrlenW(buf) == 22,
973 "EM_SETTEXTEX to replace selection with more text failed: %i.\n",
976 DestroyWindow(hwndRichEdit);
979 static void test_EM_LIMITTEXT(void)
983 HWND hwndRichEdit = new_richedit(NULL);
985 /* The main purpose of this test is to demonstrate that the nonsense in MSDN
986 * about setting the length to -1 for multiline edit controls doesn't happen.
989 /* Don't check default gettextlimit case. That's done in other tests */
991 /* Set textlimit to 100 */
992 SendMessage (hwndRichEdit, EM_LIMITTEXT, 100, 0);
993 ret = SendMessage (hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
995 "EM_LIMITTEXT: set to 100, returned: %d, expected: 100\n", ret);
997 /* Set textlimit to 0 */
998 SendMessage (hwndRichEdit, EM_LIMITTEXT, 0, 0);
999 ret = SendMessage (hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1001 "EM_LIMITTEXT: set to 0, returned: %d, expected: 65536\n", ret);
1003 /* Set textlimit to -1 */
1004 SendMessage (hwndRichEdit, EM_LIMITTEXT, -1, 0);
1005 ret = SendMessage (hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1007 "EM_LIMITTEXT: set to -1, returned: %d, expected: -1\n", ret);
1009 /* Set textlimit to -2 */
1010 SendMessage (hwndRichEdit, EM_LIMITTEXT, -2, 0);
1011 ret = SendMessage (hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1013 "EM_LIMITTEXT: set to -2, returned: %d, expected: -2\n", ret);
1015 DestroyWindow (hwndRichEdit);
1019 static void test_EM_EXLIMITTEXT(void)
1021 int i, selBegin, selEnd, len1, len2;
1022 char text[1024 + 1];
1023 int textlimit = 0; /* multiple of 100 */
1024 HWND hwndRichEdit = new_richedit(NULL);
1026 i = SendMessage(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1027 ok(32767 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 32767, i); /* default */
1030 SendMessage(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
1031 i = SendMessage(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1033 ok(textlimit == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", textlimit, i);
1036 SendMessage(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
1037 i = SendMessage(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1039 ok(textlimit == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", textlimit, i);
1041 SendMessage(hwndRichEdit, EM_EXLIMITTEXT, 0, 0);
1042 i = SendMessage(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1043 /* default for WParam = 0 */
1044 ok(65536 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 65536, i);
1046 textlimit = sizeof(text)-1;
1047 memset(text, 'W', textlimit);
1048 text[sizeof(text)-1] = 0;
1049 SendMessage(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
1050 /* maxed out text */
1051 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
1053 SendMessage(hwndRichEdit, EM_SETSEL, 0, -1); /* select everything */
1054 SendMessage(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
1055 len1 = selEnd - selBegin;
1057 SendMessage(hwndRichEdit, WM_KEYDOWN, VK_BACK, 1);
1058 SendMessage(hwndRichEdit, WM_CHAR, VK_BACK, 1);
1059 SendMessage(hwndRichEdit, WM_KEYUP, VK_BACK, 1);
1060 SendMessage(hwndRichEdit, EM_SETSEL, 0, -1);
1061 SendMessage(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
1062 len2 = selEnd - selBegin;
1065 "EM_EXLIMITTEXT: Change Expected\nOld Length: %d, New Length: %d, Limit: %d\n",
1068 SendMessage(hwndRichEdit, WM_KEYDOWN, 'A', 1);
1069 SendMessage(hwndRichEdit, WM_CHAR, 'A', 1);
1070 SendMessage(hwndRichEdit, WM_KEYUP, 'A', 1);
1071 SendMessage(hwndRichEdit, EM_SETSEL, 0, -1);
1072 SendMessage(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
1073 len1 = selEnd - selBegin;
1076 "EM_EXLIMITTEXT: Change Expected\nOld Length: %d, New Length: %d, Limit: %d\n",
1079 SendMessage(hwndRichEdit, WM_KEYDOWN, 'A', 1);
1080 SendMessage(hwndRichEdit, WM_CHAR, 'A', 1);
1081 SendMessage(hwndRichEdit, WM_KEYUP, 'A', 1); /* full; should be no effect */
1082 SendMessage(hwndRichEdit, EM_SETSEL, 0, -1);
1083 SendMessage(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
1084 len2 = selEnd - selBegin;
1087 "EM_EXLIMITTEXT: No Change Expected\nOld Length: %d, New Length: %d, Limit: %d\n",
1090 DestroyWindow(hwndRichEdit);
1093 static void test_EM_GETLIMITTEXT(void)
1096 HWND hwndRichEdit = new_richedit(NULL);
1098 i = SendMessage(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1099 ok(32767 == i, "expected: %d, actual: %d\n", 32767, i); /* default value */
1101 SendMessage(hwndRichEdit, EM_EXLIMITTEXT, 0, 50000);
1102 i = SendMessage(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
1103 ok(50000 == i, "expected: %d, actual: %d\n", 50000, i);
1105 DestroyWindow(hwndRichEdit);
1108 static void test_WM_SETFONT(void)
1110 /* There is no invalid input or error conditions for this function.
1111 * NULL wParam and lParam just fall back to their default values
1112 * It should be noted that even if you use a gibberish name for your fonts
1113 * here, it will still work because the name is stored. They will display as
1114 * System, but will report their name to be whatever they were created as */
1116 HWND hwndRichEdit = new_richedit(NULL);
1117 HFONT testFont1 = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
1118 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
1119 FF_DONTCARE, "Marlett");
1120 HFONT testFont2 = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
1121 OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
1122 FF_DONTCARE, "MS Sans Serif");
1123 HFONT testFont3 = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
1124 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
1125 FF_DONTCARE, "Courier");
1126 LOGFONTA sentLogFont;
1127 CHARFORMAT2A returnedCF2A;
1129 returnedCF2A.cbSize = sizeof(returnedCF2A);
1131 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "x");
1132 SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont1,(LPARAM) MAKELONG((WORD) TRUE, 0));
1133 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
1135 GetObjectA(testFont1, sizeof(LOGFONTA), &sentLogFont);
1136 ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
1137 "EM_GETCHARFOMAT: Returned wrong font on test 1. Sent: %s, Returned: %s\n",
1138 sentLogFont.lfFaceName,returnedCF2A.szFaceName);
1140 SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont2,(LPARAM) MAKELONG((WORD) TRUE, 0));
1141 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
1142 GetObjectA(testFont2, sizeof(LOGFONTA), &sentLogFont);
1143 ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
1144 "EM_GETCHARFOMAT: Returned wrong font on test 2. Sent: %s, Returned: %s\n",
1145 sentLogFont.lfFaceName,returnedCF2A.szFaceName);
1147 SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont3,(LPARAM) MAKELONG((WORD) TRUE, 0));
1148 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
1149 GetObjectA(testFont3, sizeof(LOGFONTA), &sentLogFont);
1150 ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
1151 "EM_GETCHARFOMAT: Returned wrong font on test 3. Sent: %s, Returned: %s\n",
1152 sentLogFont.lfFaceName,returnedCF2A.szFaceName);
1154 /* This last test is special since we send in NULL. We clear the variables
1155 * and just compare to "System" instead of the sent in font name. */
1156 ZeroMemory(&returnedCF2A,sizeof(returnedCF2A));
1157 ZeroMemory(&sentLogFont,sizeof(sentLogFont));
1158 returnedCF2A.cbSize = sizeof(returnedCF2A);
1160 SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)NULL,(LPARAM) MAKELONG((WORD) TRUE, 0));
1161 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
1162 GetObjectA(NULL, sizeof(LOGFONTA), &sentLogFont);
1163 ok (!strcmp("System",returnedCF2A.szFaceName),
1164 "EM_GETCHARFOMAT: Returned wrong font on test 4. Sent: NULL, Returned: %s. Expected \"System\".\n",returnedCF2A.szFaceName);
1166 DestroyWindow(hwndRichEdit);
1170 static DWORD CALLBACK test_EM_GETMODIFY_esCallback(DWORD_PTR dwCookie,
1175 const char** str = (const char**)dwCookie;
1176 int size = strlen(*str);
1177 if(size > 3) /* let's make it peice-meal for fun */
1184 memcpy(pbBuff, *str, *pcb);
1190 static void test_EM_GETMODIFY(void)
1192 HWND hwndRichEdit = new_richedit(NULL);
1195 WCHAR TestItem1[] = {'T', 'e', 's', 't',
1197 'T', 'e', 'x', 't', 0};
1198 WCHAR TestItem2[] = {'T', 'e', 's', 't',
1200 'O', 't', 'h', 'e', 'r',
1201 'T', 'e', 'x', 't', 0};
1202 const char* streamText = "hello world";
1207 HFONT testFont = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
1208 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
1209 FF_DONTCARE, "Courier");
1211 setText.codepage = 1200; /* no constant for unicode */
1212 setText.flags = ST_KEEPUNDO;
1215 /* modify flag shouldn't be set when richedit is first created */
1216 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1218 "EM_GETMODIFY returned non-zero, instead of zero on create\n");
1220 /* setting modify flag should actually set it */
1221 SendMessage(hwndRichEdit, EM_SETMODIFY, TRUE, 0);
1222 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1224 "EM_GETMODIFY returned zero, instead of non-zero on EM_SETMODIFY\n");
1226 /* clearing modify flag should actually clear it */
1227 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1228 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1230 "EM_GETMODIFY returned non-zero, instead of zero on EM_SETMODIFY\n");
1232 /* setting font doesn't change modify flag */
1233 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1234 SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont,(LPARAM) MAKELONG((WORD) TRUE, 0));
1235 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1237 "EM_GETMODIFY returned non-zero, instead of zero on setting font\n");
1239 /* setting text should set modify flag */
1240 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1241 SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
1242 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1244 "EM_GETMODIFY returned zero, instead of non-zero on setting text\n");
1246 /* undo previous text doesn't reset modify flag */
1247 SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
1248 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1250 "EM_GETMODIFY returned zero, instead of non-zero on undo after setting text\n");
1252 /* set text with no flag to keep undo stack should not set modify flag */
1253 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1255 SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
1256 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1258 "EM_GETMODIFY returned non-zero, instead of zero when setting text while not keeping undo stack\n");
1260 /* WM_SETTEXT doesn't modify */
1261 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1262 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem2);
1263 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1266 "EM_GETMODIFY returned non-zero for WM_SETTEXT\n");
1269 /* clear the text */
1270 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1271 SendMessage(hwndRichEdit, WM_CLEAR, 0, 0);
1272 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1274 "EM_GETMODIFY returned non-zero, instead of zero for WM_CLEAR\n");
1277 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1278 SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
1279 SendMessage(hwndRichEdit, EM_SETSEL, 0, 2);
1280 SendMessage(hwndRichEdit, EM_REPLACESEL, TRUE, (LPARAM)TestItem2);
1281 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1283 "EM_GETMODIFY returned zero, instead of non-zero when replacing text\n");
1285 /* copy/paste text 1 */
1286 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1287 SendMessage(hwndRichEdit, EM_SETSEL, 0, 2);
1288 SendMessage(hwndRichEdit, WM_COPY, 0, 0);
1289 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
1290 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1292 "EM_GETMODIFY returned zero, instead of non-zero when pasting identical text\n");
1294 /* copy/paste text 2 */
1295 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1296 SendMessage(hwndRichEdit, EM_SETSEL, 0, 2);
1297 SendMessage(hwndRichEdit, WM_COPY, 0, 0);
1298 SendMessage(hwndRichEdit, EM_SETSEL, 0, 3);
1299 SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
1300 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1302 "EM_GETMODIFY returned zero, instead of non-zero when pasting different text\n");
1305 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1306 SendMessage(hwndRichEdit, EM_SETSEL, 0, 1);
1307 SendMessage(hwndRichEdit, WM_CHAR, 'A', 0);
1308 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1310 "EM_GETMODIFY returned zero, instead of non-zero for WM_CHAR\n");
1312 /* set char format */
1313 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1314 cf2.cbSize = sizeof(CHARFORMAT2);
1315 SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT,
1317 cf2.dwMask = CFM_ITALIC | cf2.dwMask;
1318 cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
1319 SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
1320 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1322 "EM_GETMODIFY returned zero, instead of non-zero for EM_SETCHARFORMAT\n");
1324 /* set para format */
1325 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1326 pf2.cbSize = sizeof(PARAFORMAT2);
1327 SendMessage(hwndRichEdit, EM_GETPARAFORMAT, 0,
1329 pf2.dwMask = PFM_ALIGNMENT | pf2.dwMask;
1330 pf2.wAlignment = PFA_RIGHT;
1331 SendMessage(hwndRichEdit, EM_SETPARAFORMAT, 0, (LPARAM) &pf2);
1332 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1334 "EM_GETMODIFY returned zero, instead of non-zero for EM_SETPARAFORMAT\n");
1337 SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
1338 es.dwCookie = (DWORD_PTR)&streamText;
1340 es.pfnCallback = test_EM_GETMODIFY_esCallback;
1341 SendMessage(hwndRichEdit, EM_STREAMIN,
1342 (WPARAM)(SF_TEXT), (LPARAM)&es);
1343 result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
1345 "EM_GETMODIFY returned zero, instead of non-zero for EM_STREAM\n");
1347 DestroyWindow(hwndRichEdit);
1353 long expected_retval;
1354 int expected_getsel_start;
1355 int expected_getsel_end;
1356 int _exsetsel_todo_wine;
1357 int _getsel_todo_wine;
1360 const struct exsetsel_s exsetsel_tests[] = {
1362 {5, 10, 10, 5, 10, 0, 0},
1363 {15, 17, 17, 15, 17, 0, 0},
1364 /* test cpMax > strlen() */
1365 {0, 100, 18, 0, 18, 0, 1},
1366 /* test cpMin == cpMax */
1367 {5, 5, 5, 5, 5, 0, 0},
1368 /* test cpMin < 0 && cpMax >= 0 (bug 4462) */
1369 {-1, 0, 5, 5, 5, 0, 0},
1370 {-1, 17, 5, 5, 5, 0, 0},
1371 {-1, 18, 5, 5, 5, 0, 0},
1372 /* test cpMin < 0 && cpMax < 0 */
1373 {-1, -1, 17, 17, 17, 0, 0},
1374 {-4, -5, 17, 17, 17, 0, 0},
1375 /* test cMin >=0 && cpMax < 0 (bug 6814) */
1376 {0, -1, 18, 0, 18, 0, 1},
1377 {17, -5, 18, 17, 18, 0, 1},
1378 {18, -3, 17, 17, 17, 0, 0},
1379 /* test if cpMin > cpMax */
1380 {15, 19, 18, 15, 18, 0, 1},
1381 {19, 15, 18, 15, 18, 0, 1}
1384 static void check_EM_EXSETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id) {
1389 cr.cpMin = setsel->min;
1390 cr.cpMax = setsel->max;
1391 result = SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) &cr);
1393 if (setsel->_exsetsel_todo_wine) {
1395 ok(result == setsel->expected_retval, "EM_EXSETSEL(%d): expected: %ld actual: %ld\n", id, setsel->expected_retval, result);
1398 ok(result == setsel->expected_retval, "EM_EXSETSEL(%d): expected: %ld actual: %ld\n", id, setsel->expected_retval, result);
1401 SendMessage(hwnd, EM_GETSEL, (WPARAM) &start, (LPARAM) &end);
1403 if (setsel->_getsel_todo_wine) {
1405 ok(start == setsel->expected_getsel_start && end == setsel->expected_getsel_end, "EM_EXSETSEL(%d): expected (%d,%d) actual:(%d,%d)\n", id, setsel->expected_getsel_start, setsel->expected_getsel_end, start, end);
1408 ok(start == setsel->expected_getsel_start && end == setsel->expected_getsel_end, "EM_EXSETSEL(%d): expected (%d,%d) actual:(%d,%d)\n", id, setsel->expected_getsel_start, setsel->expected_getsel_end, start, end);
1412 static void test_EM_EXSETSEL(void)
1414 HWND hwndRichEdit = new_richedit(NULL);
1416 const int num_tests = sizeof(exsetsel_tests)/sizeof(struct exsetsel_s);
1418 /* sending some text to the window */
1419 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "testing selection");
1420 /* 01234567890123456*/
1423 for (i = 0; i < num_tests; i++) {
1424 check_EM_EXSETSEL(hwndRichEdit, &exsetsel_tests[i], i);
1427 DestroyWindow(hwndRichEdit);
1430 static void test_WM_PASTE(void)
1433 char buffer[1024] = {0};
1434 const char* text1 = "testing paste\r";
1435 const char* text2 = "testing paste\r\rtesting paste";
1436 const char* text3 = "testing paste\rpaste\rtesting paste";
1437 HWND hwndRichEdit = new_richedit(NULL);
1439 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1);
1440 SendMessage(hwndRichEdit, EM_SETSEL, 0, 14);
1441 SendMessage(hwndRichEdit, WM_CHAR, 3, 0); /* ctrl-c */
1442 SendMessage(hwndRichEdit, EM_SETSEL, 14, 14);
1443 SendMessage(hwndRichEdit, WM_CHAR, 22, 0); /* ctrl-v */
1444 SendMessage(hwndRichEdit, WM_CHAR, 26, 0); /* ctrl-z */
1445 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1446 result = strcmp(text1, buffer);
1448 "test paste: strcmp = %i\n", result);
1450 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text2);
1451 SendMessage(hwndRichEdit, EM_SETSEL, 8, 13);
1452 SendMessage(hwndRichEdit, WM_CHAR, 3, 0); /* ctrl-c */
1453 SendMessage(hwndRichEdit, EM_SETSEL, 14, 14);
1454 SendMessage(hwndRichEdit, WM_CHAR, 22, 0); /* ctrl-v */
1455 SendMessage(hwndRichEdit, WM_CHAR, 26, 0); /* ctrl-z */
1456 SendMessage(hwndRichEdit, WM_CHAR, 25, 0); /* ctrl-y */
1457 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1458 result = strcmp(buffer,text3);
1460 "test paste: strcmp = %i\n", result);
1462 DestroyWindow(hwndRichEdit);
1465 static int nCallbackCount = 0;
1467 static DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff,
1470 const char text[] = {'t','e','s','t'};
1472 if (sizeof(text) <= cb)
1474 if ((int)dwCookie != nCallbackCount)
1480 memcpy (pbBuff, text, sizeof(text));
1481 *pcb = sizeof(text);
1488 return 1; /* indicates callback failed */
1491 static void test_EM_StreamIn_Undo(void)
1493 /* The purpose of this test is to determine when a EM_StreamIn should be
1494 * undoable. This is important because WM_PASTE currently uses StreamIn and
1495 * pasting should always be undoable but streaming isn't always.
1498 * StreamIn plain text without SFF_SELECTION.
1499 * StreamIn plain text with SFF_SELECTION set but a zero-length selection
1500 * StreamIn plain text with SFF_SELECTION and a valid, normal selection
1501 * StreamIn plain text with SFF_SELECTION and a backwards-selection (from>to)
1502 * Feel free to add tests for other text modes or StreamIn things.
1506 HWND hwndRichEdit = new_richedit(NULL);
1509 char buffer[1024] = {0};
1510 const char randomtext[] = "Some text";
1512 es.pfnCallback = (EDITSTREAMCALLBACK) EditStreamCallback;
1514 /* StreamIn, no SFF_SELECTION */
1515 es.dwCookie = nCallbackCount;
1516 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
1517 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) randomtext);
1518 SendMessage(hwndRichEdit, EM_SETSEL,0,0);
1519 SendMessage(hwndRichEdit, EM_STREAMIN, (WPARAM)SF_TEXT, (LPARAM)&es);
1520 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1521 result = strcmp (buffer,"test");
1523 "EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
1525 result = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0);
1526 ok (result == FALSE,
1527 "EM_STREAMIN without SFF_SELECTION wrongly allows undo\n");
1529 /* StreamIn, SFF_SELECTION, but nothing selected */
1530 es.dwCookie = nCallbackCount;
1531 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
1532 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) randomtext);
1533 SendMessage(hwndRichEdit, EM_SETSEL,0,0);
1534 SendMessage(hwndRichEdit, EM_STREAMIN,
1535 (WPARAM)(SF_TEXT|SFF_SELECTION), (LPARAM)&es);
1536 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1537 result = strcmp (buffer,"testSome text");
1539 "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
1541 result = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0);
1543 "EM_STREAMIN with SFF_SELECTION but no selection set "
1544 "should create an undo\n");
1546 /* StreamIn, SFF_SELECTION, with a selection */
1547 es.dwCookie = nCallbackCount;
1548 SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
1549 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) randomtext);
1550 SendMessage(hwndRichEdit, EM_SETSEL,4,5);
1551 SendMessage(hwndRichEdit, EM_STREAMIN,
1552 (WPARAM)(SF_TEXT|SFF_SELECTION), (LPARAM)&es);
1553 SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1554 result = strcmp (buffer,"Sometesttext");
1556 "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
1558 result = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0);
1560 "EM_STREAMIN with SFF_SELECTION and selection set "
1561 "should create an undo\n");
1565 START_TEST( editor )
1570 /* Must explicitly LoadLibrary(). The test has no references to functions in
1571 * RICHED20.DLL, so the linker doesn't actually link to it. */
1572 hmoduleRichEdit = LoadLibrary("RICHED20.DLL");
1573 ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
1576 test_EM_SCROLLCARET();
1578 test_EM_SETTEXTMODE();
1579 test_TM_PLAINTEXT();
1580 test_EM_SETOPTIONS();
1582 test_EM_AUTOURLDETECT();
1583 test_EM_SETUNDOLIMIT();
1585 test_EM_SETTEXTEX();
1586 test_EM_LIMITTEXT();
1587 test_EM_EXLIMITTEXT();
1588 test_EM_GETLIMITTEXT();
1590 test_EM_GETMODIFY();
1593 test_EM_StreamIn_Undo();
1595 /* Set the environment variable WINETEST_RICHED20 to keep windows
1596 * responsive and open for 30 seconds. This is useful for debugging.
1598 * The message pump uses PeekMessage() to empty the queue and then sleeps for
1599 * 50ms before retrying the queue. */
1600 end = time(NULL) + 30;
1601 if (getenv( "WINETEST_RICHED20" )) {
1602 while (time(NULL) < end) {
1603 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1604 TranslateMessage(&msg);
1605 DispatchMessage(&msg);
1612 OleFlushClipboard();
1613 ok(FreeLibrary(hmoduleRichEdit) != 0, "error: %d\n", (int) GetLastError());