ReactOS 0.4.16-dev-303-g11d5cb8
editor.c
Go to the documentation of this file.
1/*
2* Unit test suite for rich edit control 1.0
3*
4* Copyright 2006 Google (Thomas Kho)
5* Copyright 2007 Matt Finnicum
6* Copyright 2007 Dmitry Timoshkov
7* Copyright 2007 Alex VillacĂ­s Lasso
8*
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.
13*
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.
18*
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
22*/
23
24#include <stdarg.h>
25#include <stdio.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 <commdlg.h>
33#include <richedit.h>
34#include <time.h>
35#include <wine/test.h>
36
39
40static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) {
41 HWND hwnd;
42 hwnd = CreateWindowA(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
43 |WS_VISIBLE, 0, 0, 500, 60, parent, NULL,
45 ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
46 return hwnd;
47}
48
51}
52
53static BOOL is_rtl(void) {
55
57 (LPSTR) &sig, sizeof(LOCALESIGNATURE)) &&
58 (sig.lsUsb[3] & 0x08000000) != 0);
59}
60
61static void test_WM_SETTEXT(void)
62{
63 static const struct {
64 const char *itemtext;
66 DWORD lines_rtl;
67 DWORD lines_broken;
68 } testitems[] = {
69 { "TestSomeText", 1, 1},
70 { "TestSomeText\r", 1, 1},
71 { "TestSomeText\rSomeMoreText\r", 2, 1, 1}, /* NT4 and below */
72 { "TestSomeText\n\nTestSomeText", 3, 3},
73 { "TestSomeText\r\r\nTestSomeText", 2, 2},
74 { "TestSomeText\r\r\n\rTestSomeText", 3, 2, 2}, /* NT4 and below */
75 { "TestSomeText\r\n\r\r\n\rTestSomeText", 4, 3, 3}, /* NT4 and below */
76 { "TestSomeText\r\n", 2, 2},
77 { "TestSomeText\r\nSomeMoreText\r\n", 3, 3},
78 { "TestSomeText\r\n\r\nTestSomeText", 3, 3},
79 { "TestSomeText TestSomeText", 1, 1},
80 { "TestSomeText \r\nTestSomeText", 2, 2},
81 { "TestSomeText\r\n \r\nTestSomeText", 3, 3},
82 { "TestSomeText\n", 2, 2},
83 { "TestSomeText\r\r\r", 3, 1, 1}, /* NT4 and below */
84 { "TestSomeText\r\r\rSomeMoreText", 4, 1, 1} /* NT4 and below */
85 };
86 HWND hwndRichEdit = new_richedit(NULL);
87 int i;
88 BOOL rtl = is_rtl();
89
90 /* This test attempts to show that WM_SETTEXT on a riched32 control does not
91 * attempt to modify the text that is pasted into the control, and should
92 * return it as is. In particular, \r\r\n is NOT converted, unlike riched20.
93 *
94 * For riched32, the rules for breaking lines seem to be the following:
95 * - \r\n is one line break. This is the normal case.
96 * - \r{0,2}\n is one line break. In particular, \n by itself is a line break.
97 * - \r{0,N-1}\r\r\n is N line breaks.
98 * - \n{1,N} are that many line breaks.
99 * - \r with text or other characters (except \n) past it, is a line break. That
100 * is, a run of \r{N} without a terminating \n is considered N line breaks
101 * - \r at the end of the text is NOT a line break. This differs from riched20,
102 * where \r at the end of the text is a proper line break.
103 * However, on RTL language versions, \r is simply skipped and never used
104 * for line breaking (only \n adds a line break)
105 */
106
107 for (i = 0; i < ARRAY_SIZE(testitems); i++) {
108
109 char buf[1024] = {0};
111
112 result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)testitems[i].itemtext);
113 ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
114 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buf);
115 ok (result == lstrlenA(buf),
116 "[%d] WM_GETTEXT returned %ld instead of expected %u\n",
117 i, result, lstrlenA(buf));
118 result = strcmp(testitems[i].itemtext, buf);
119 ok (result == 0,
120 "[%d] WM_SETTEXT round trip: strcmp = %ld\n", i, result);
121 result = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
122 ok (result == (rtl ? testitems[i].lines_rtl : testitems[i].lines) ||
123 broken(testitems[i].lines_broken && result == testitems[i].lines_broken),
124 "[%d] EM_GETLINECOUNT returned %ld, expected %d\n", i, result, testitems[i].lines);
125 }
126
127 DestroyWindow(hwndRichEdit);
128}
129
130static void test_WM_GETTEXTLENGTH(void)
131{
132 HWND hwndRichEdit = new_richedit(NULL);
133 static const char text1[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee";
134 static const char text2[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee\r\n";
135 static const char text3[] = "abcdef\x8e\xf0";
136 int result;
137
138 /* Test for WM_GETTEXTLENGTH */
139 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
140 result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
141 ok(result == lstrlenA(text1),
142 "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
143 result, lstrlenA(text1));
144
145 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
146 result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
147 ok(result == lstrlenA(text2),
148 "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
149 result, lstrlenA(text2));
150
151 /* Test with multibyte character */
152 if (!is_lang_japanese)
153 skip("Skip multibyte character tests on non-Japanese platform\n");
154 else
155 {
156 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text3);
157 result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
158 ok(result == 8, "WM_GETTEXTLENGTH returned %d, expected 8\n", result);
159 }
160
161 DestroyWindow(hwndRichEdit);
162}
163
165 LPBYTE pbBuff,
166 LONG cb,
167 LONG *pcb)
168{
169 const char** str = (const char**)dwCookie;
170 int size = strlen(*str);
171 *pcb = cb;
172 if (*pcb > size) {
173 *pcb = size;
174 }
175 if (*pcb > 0) {
176 memcpy(pbBuff, *str, *pcb);
177 *str += *pcb;
178 }
179 return 0;
180}
181
182
183static void test_EM_STREAMIN(void)
184{
185 HWND hwndRichEdit = new_richedit(NULL);
188 char buffer[1024] = {0};
189
190 const char * streamText0 = "{\\rtf1 TestSomeText}";
191 const char * streamText0a = "{\\rtf1 TestSomeText\\par}";
192 const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
193
194 const char * streamText1 =
195 "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n"
196 "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n"
197 "}\r\n";
198
199 /* This should be accepted in richedit 1.0 emulation. See bug #8326 */
200 const char * streamText2 =
201 "{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;"
202 "\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255"
203 "\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 "
204 "\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 "
205 "\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 "
206 "\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 "
207 "\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line }";
208
209 const char * streamText3 = "RichEdit1";
210
211 /* Minimal test without \par at the end */
212 es.dwCookie = (DWORD_PTR)&streamText0;
213 es.dwError = 0;
214 es.pfnCallback = test_EM_STREAMIN_esCallback;
215 SendMessageA(hwndRichEdit, EM_STREAMIN,
216 (WPARAM)(SF_RTF), (LPARAM)&es);
217
218 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
219 ok (result == 12,
220 "EM_STREAMIN: Test 0 returned %ld, expected 12\n", result);
221 result = strcmp (buffer,"TestSomeText");
222 ok (result == 0,
223 "EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
224 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
225
226 /* Native richedit 2.0 ignores last \par */
227 es.dwCookie = (DWORD_PTR)&streamText0a;
228 es.dwError = 0;
229 es.pfnCallback = test_EM_STREAMIN_esCallback;
230 SendMessageA(hwndRichEdit, EM_STREAMIN,
231 (WPARAM)(SF_RTF), (LPARAM)&es);
232
233 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
234 ok (result == 12,
235 "EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
236 result = strcmp (buffer,"TestSomeText");
237 ok (result == 0,
238 "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
239 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
240
241 /* Native richedit 2.0 ignores last \par, next-to-last \par appears */
242 es.dwCookie = (DWORD_PTR)&streamText0b;
243 es.dwError = 0;
244 es.pfnCallback = test_EM_STREAMIN_esCallback;
245 SendMessageA(hwndRichEdit, EM_STREAMIN,
246 (WPARAM)(SF_RTF), (LPARAM)&es);
247
248 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
249 ok (result == 14,
250 "EM_STREAMIN: Test 0-b returned %ld, expected 14\n", result);
251 result = strcmp (buffer,"TestSomeText\r\n");
252 ok (result == 0,
253 "EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer);
254 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
255
256 es.dwCookie = (DWORD_PTR)&streamText1;
257 es.dwError = 0;
258 es.pfnCallback = test_EM_STREAMIN_esCallback;
259 SendMessageA(hwndRichEdit, EM_STREAMIN,
260 (WPARAM)(SF_RTF), (LPARAM)&es);
261
262 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
263 ok (result == 12,
264 "EM_STREAMIN: Test 1 returned %ld, expected 12\n", result);
265 result = strcmp (buffer,"TestSomeText");
266 ok (result == 0,
267 "EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
268 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
269
270
271 es.dwCookie = (DWORD_PTR)&streamText2;
272 es.dwError = 0;
273 SendMessageA(hwndRichEdit, EM_STREAMIN,
274 (WPARAM)(SF_RTF), (LPARAM)&es);
275
276 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
277 todo_wine {
278 ok (result == 9,
279 "EM_STREAMIN: Test 2 returned %ld, expected 9\n", result);
280 }
281 result = strcmp (buffer,"RichEdit1");
282 todo_wine {
283 ok (result == 0,
284 "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
285 }
286 ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
287
288 es.dwCookie = (DWORD_PTR)&streamText3;
289 es.dwError = 0;
290 SendMessageA(hwndRichEdit, EM_STREAMIN,
291 (WPARAM)(SF_RTF), (LPARAM)&es);
292
293 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
294 ok (result == 0,
295 "EM_STREAMIN: Test 3 returned %ld, expected 0\n", result);
296 ok (strlen(buffer) == 0,
297 "EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer);
298 ok(es.dwError == -16, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, -16);
299
300 DestroyWindow(hwndRichEdit);
301}
302
304 LPBYTE pbBuff,
305 LONG cb,
306 LONG *pcb)
307{
308 char** str = (char**)dwCookie;
309 *pcb = cb;
310 if (*pcb > 0) {
311 memcpy(*str, pbBuff, *pcb);
312 *str += *pcb;
313 }
314 return 0;
315}
316
317static void test_EM_STREAMOUT(void)
318{
319 HWND hwndRichEdit = new_richedit(NULL);
320 int r;
322 char buf[1024] = {0};
323 char * p;
324
325 const char * TestItem1 = "TestSomeText";
326 const char * TestItem2 = "TestSomeText\r";
327 const char * TestItem3 = "TestSomeText\r\n";
328
329 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem1);
330 p = buf;
331 es.dwCookie = (DWORD_PTR)&p;
332 es.dwError = 0;
333 es.pfnCallback = test_WM_SETTEXT_esCallback;
334 memset(buf, 0, sizeof(buf));
335 SendMessageA(hwndRichEdit, EM_STREAMOUT,
336 (WPARAM)(SF_TEXT), (LPARAM)&es);
337 r = strlen(buf);
338 ok(r == 12, "streamed text length is %d, expecting 12\n", r);
339 ok(strcmp(buf, TestItem1) == 0,
340 "streamed text different, got %s\n", buf);
341
342 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem2);
343 p = buf;
344 es.dwCookie = (DWORD_PTR)&p;
345 es.dwError = 0;
346 es.pfnCallback = test_WM_SETTEXT_esCallback;
347 memset(buf, 0, sizeof(buf));
348 SendMessageA(hwndRichEdit, EM_STREAMOUT,
349 (WPARAM)(SF_TEXT), (LPARAM)&es);
350 r = strlen(buf);
351
352 ok(r == 13, "streamed text length is %d, expecting 13\n", r);
353 ok(strcmp(buf, TestItem2) == 0,
354 "streamed text different, got %s\n", buf);
355
356 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem3);
357 p = buf;
358 es.dwCookie = (DWORD_PTR)&p;
359 es.dwError = 0;
360 es.pfnCallback = test_WM_SETTEXT_esCallback;
361 memset(buf, 0, sizeof(buf));
362 SendMessageA(hwndRichEdit, EM_STREAMOUT,
363 (WPARAM)(SF_TEXT), (LPARAM)&es);
364 r = strlen(buf);
365 ok(r == 14, "streamed text length is %d, expecting 14\n", r);
366 ok(strcmp(buf, TestItem3) == 0,
367 "streamed text different, got %s\n", buf);
368
369 DestroyWindow(hwndRichEdit);
370}
371
372static const struct getline_s {
373 int line;
374 size_t buffer_len;
375 const char *text;
376 const char *broken_text;
377} gl[] = {
378 {0, 10, "foo bar\r\n", "foo bar\r\n"},
379 {1, 10, "\r", "\r\r\r\n"},
380 {2, 10, "\r\r\n", "bar\n"},
381 {3, 10, "bar\n", "\r\n"},
382 {4, 10, "\r\n"},
383
384 /* Buffer smaller than line length */
385 {0, 2, "foo bar\r"},
386 {0, 1, "foo bar\r"},
387 {0, 0, "foo bar\r"}
389
390static void test_EM_GETLINE(void)
391{
392 int i;
393 HWND hwndRichEdit = new_richedit(NULL);
394 static const int nBuf = 1024;
395 char dest[1024], origdest[1024];
396 LRESULT linecount;
397 const char text[] = "foo bar\r\n"
398 "\r"
399 "\r\r\n"
400 "bar\n";
401 BOOL broken_os = FALSE;
402 BOOL rtl = is_rtl();
403
404 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
405 linecount = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
406 if (linecount == 4)
407 {
408 broken_os = TRUE;
409 win_skip("Win9x, WinME and NT4 handle '\\r only' differently\n");
410 }
411
412 memset(origdest, 0xBB, nBuf);
413 for (i = 0; i < ARRAY_SIZE(gl); i++)
414 {
415 int nCopied, expected_nCopied, expected_bytes_written;
416 char gl_text[1024];
417
418 if (gl[i].line >= linecount)
419 continue; /* Win9x, WinME and NT4 */
420
421 if (broken_os && gl[i].broken_text)
422 /* Win9x, WinME and NT4 */
423 strcpy(gl_text, gl[i].broken_text);
424 else
426
427 expected_nCopied = min(gl[i].buffer_len, strlen(gl_text));
428 /* Cater for the fact that Win9x, WinME and NT4 don't append the '\0' */
429 expected_bytes_written = min(gl[i].buffer_len, strlen(gl_text) + (broken_os ? 0 : 1));
430
431 memset(dest, 0xBB, nBuf);
432 *(WORD *) dest = gl[i].buffer_len;
433
434 /* EM_GETLINE appends a "\r\0" to the end of the line
435 * nCopied counts up to and including the '\r' */
436 nCopied = SendMessageA(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM)dest);
437 ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
438 expected_nCopied);
439 /* two special cases since a parameter is passed via dest */
440 if (gl[i].buffer_len == 0)
441 ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
442 "buffer_len=0\n");
443 else if (gl[i].buffer_len == 1)
444 ok(dest[0] == gl_text[0] && !dest[1] &&
445 !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
446 else
447 {
448 ok(!strncmp(dest, gl_text, expected_bytes_written),
449 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
450 if (! rtl || expected_bytes_written == gl[i].buffer_len)
451 ok(!strncmp(dest + expected_bytes_written, origdest
452 + expected_bytes_written, nBuf - expected_bytes_written),
453 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
454 else
455 ok(dest[expected_bytes_written] == 0 &&
456 !strncmp(dest + expected_bytes_written + 1, origdest
457 + expected_bytes_written + 1, nBuf - (expected_bytes_written + 1)),
458 "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
459 }
460 }
461
462 DestroyWindow(hwndRichEdit);
463}
464
465static void test_EM_LINELENGTH(void)
466{
467 HWND hwndRichEdit = new_richedit(NULL);
468 const char * text =
469 "richedit1\r"
470 "richedit1\n"
471 "richedit1\r\n"
472 "short\r"
473 "richedit1\r"
474 "\r"
475 "\r"
476 "\r\r\n";
477 int offset_test[16][2] = {
478 {0, 9}, /* Line 1: |richedit1\r */
479 {5, 9}, /* Line 1: riche|dit1\r */
480 {10, 9}, /* Line 2: |richedit1\n */
481 {15, 9}, /* Line 2: riche|dit1\n */
482 {20, 9}, /* Line 3: |richedit1\r\n */
483 {25, 9}, /* Line 3: riche|dit1\r\n */
484 {30, 9}, /* Line 3: richedit1\r|\n */
485 {31, 5}, /* Line 4: |short\r */
486 {42, 9}, /* Line 5: riche|dit1\r */
487 {46, 9}, /* Line 5: richedit1|\r */
488 {47, 0}, /* Line 6: |\r */
489 {48, 0}, /* Line 7: |\r */
490 {49, 0}, /* Line 8: |\r\r\n */
491 {50, 0}, /* Line 8: \r|\r\n */
492 {51, 0}, /* Line 8: \r\r|\n */
493 {52, 0}, /* Line 9: \r\r\n| */
494 };
495 int i;
497
498 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
499
500 result = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
501 if (result == 4) {
502 win_skip("Win9x, WinME and NT4 don't handle '\\r only' correctly\n");
503 return;
504 }
505 ok(result == 9, "Incorrect line count of %ld\n", result);
506
507 for (i = 0; i < ARRAY_SIZE(offset_test); i++) {
508 result = SendMessageA(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
509 ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
510 offset_test[i][0], result, offset_test[i][1]);
511 }
512
513 /* Test with multibyte character */
514 if (!is_lang_japanese)
515 skip("Skip multibyte character tests on non-Japanese platform\n");
516 else
517 {
518 const char *text1 =
519 "wine\n"
520 "richedit\x8e\xf0\n"
521 "wine";
522 static int offset_test1[3][3] = {
523 {0, 4}, /* Line 1: |wine\n */
524 {5, 10, 1}, /* Line 2: |richedit\x8e\xf0\n */
525 {16, 4}, /* Line 3: |wine */
526 };
527 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
528 for (i = 0; i < ARRAY_SIZE(offset_test1); i++) {
529 result = SendMessageA(hwndRichEdit, EM_LINELENGTH, offset_test1[i][0], 0);
530 todo_wine_if (offset_test1[i][2])
531 ok(result == offset_test1[i][1], "Length of line at offset %d is %ld, expected %d\n",
532 offset_test1[i][0], result, offset_test1[i][1]);
533 }
534 }
535
536 DestroyWindow(hwndRichEdit);
537}
538
539static void test_EM_GETTEXTRANGE(void)
540{
541 HWND hwndRichEdit = new_richedit(NULL);
542 const char * text1 = "foo bar\r\nfoo bar";
543 const char * text3 = "foo bar\rfoo bar";
544 const char * expect1 = "bar\r\nfoo";
545 const char * expect2 = "\nfoo";
546 const char * expect3 = "bar\rfoo";
547 char buffer[1024] = {0};
549 TEXTRANGEA textRange;
550
551 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
552
553 textRange.lpstrText = buffer;
554 textRange.chrg.cpMin = 4;
555 textRange.chrg.cpMax = 12;
556 result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
557 ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
558 ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
559
560 textRange.lpstrText = buffer;
561 textRange.chrg.cpMin = 8;
562 textRange.chrg.cpMax = 12;
563 result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
564 ok(result == 4, "EM_GETTEXTRANGE returned %ld\n", result);
565 ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
566
567 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text3);
568
569 textRange.lpstrText = buffer;
570 textRange.chrg.cpMin = 4;
571 textRange.chrg.cpMax = 11;
572 result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
573 ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
574
575 ok(!strcmp(expect3, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
576
577 /* Test with multibyte character */
578 if (!is_lang_japanese)
579 skip("Skip multibyte character tests on non-Japanese platform\n");
580 else
581 {
582 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
583 textRange.chrg.cpMin = 4;
584 textRange.chrg.cpMax = 8;
585 result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
586 ok(result == 4, "EM_GETTEXTRANGE returned %ld\n", result);
587 todo_wine ok(!strcmp("ef\x8e\xf0", buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
588 }
589
590 DestroyWindow(hwndRichEdit);
591}
592
593static void test_EM_GETSELTEXT(void)
594{
595 HWND hwndRichEdit = new_richedit(NULL);
596 const char * text1 = "foo bar\r\nfoo bar";
597 const char * text2 = "foo bar\rfoo bar";
598 const char * expect1 = "bar\r\nfoo";
599 const char * expect2 = "bar\rfoo";
600 char buffer[1024] = {0};
602
603 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
604
605 SendMessageA(hwndRichEdit, EM_SETSEL, 4, 12);
606 result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
607 ok(result == 8, "EM_GETSELTEXT returned %ld\n", result);
608 ok(!strcmp(expect1, buffer), "EM_GETSELTEXT filled %s\n", buffer);
609
610 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
611
612 SendMessageA(hwndRichEdit, EM_SETSEL, 4, 11);
613 result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
614 ok(result == 7, "EM_GETSELTEXT returned %ld\n", result);
615 ok(!strcmp(expect2, buffer), "EM_GETSELTEXT filled %s\n", buffer);
616
617 /* Test with multibyte character */
618 if (!is_lang_japanese)
619 skip("Skip multibyte character tests on non-Japanese platform\n");
620 else
621 {
622 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
623 SendMessageA(hwndRichEdit, EM_SETSEL, 4, 8);
624 result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
625 ok(result == 4, "EM_GETSELTEXT returned %ld\n", result);
626 todo_wine ok(!strcmp("ef\x8e\xf0", buffer), "EM_GETSELTEXT filled %s\n", buffer);
627 }
628
629 DestroyWindow(hwndRichEdit);
630}
631
632static const char haystack[] = "WINEWine wineWine wine WineWine";
633 /* ^0 ^10 ^20 ^30 */
634
635static const char haystack2[] = "first\r\r\nsecond";
636
637struct find_s {
638 int start;
639 int end;
640 const char *needle;
641 int flags;
642 int expected_loc;
643};
644
645
646static struct find_s find_tests[] = {
647 /* Find in empty text */
648 {0, -1, "foo", FR_DOWN, -1},
649 {0, -1, "foo", 0, -1},
650 {0, -1, "", FR_DOWN, -1},
651 {20, 5, "foo", FR_DOWN, -1},
652 {5, 20, "foo", FR_DOWN, -1}
653};
654
655static struct find_s find_tests2[] = {
656 /* No-result find */
657 {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1},
658 {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1},
659
660 /* Subsequent finds */
661 {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4},
662 {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13},
663 {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
664 {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
665
666 /* Find backwards */
667 {19, 20, "Wine", FR_MATCHCASE, -1},
668 {10, 20, "Wine", FR_MATCHCASE, 13},
669 {20, 10, "Wine", FR_MATCHCASE, -1},
670
671 /* Case-insensitive */
672 {1, 31, "wInE", FR_DOWN, 4},
673 {1, 31, "Wine", FR_DOWN, 4},
674
675 /* High-to-low ranges */
676 {20, 5, "Wine", FR_DOWN, -1},
677 {2, 1, "Wine", FR_DOWN, -1},
678 {30, 29, "Wine", FR_DOWN, -1},
679 {20, 5, "Wine", 0, /*13*/ -1},
680
681 /* Find nothing */
682 {5, 10, "", FR_DOWN, -1},
683 {10, 5, "", FR_DOWN, -1},
684 {0, -1, "", FR_DOWN, -1},
685 {10, 5, "", 0, -1},
686
687 /* Whole-word search */
688 {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
689 {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1},
690 {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
691 {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0},
692 {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23},
693 {11, -1, "winewine", FR_WHOLEWORD, 23},
694 {31, -1, "winewine", FR_WHOLEWORD, -1},
695
696 /* Bad ranges */
697 {5, 200, "XXX", FR_DOWN, -1},
698 {-20, 20, "Wine", FR_DOWN, -1},
699 {-20, 20, "Wine", FR_DOWN, -1},
700 {-15, -20, "Wine", FR_DOWN, -1},
701 {1<<12, 1<<13, "Wine", FR_DOWN, -1},
702
703 /* Check the case noted in bug 4479 where matches at end aren't recognized */
704 {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
705 {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
706 {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27},
707 {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
708 {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
709
710 /* The backwards case of bug 4479; bounds look right
711 * Fails because backward find is wrong */
712 {19, 20, "WINE", FR_MATCHCASE, -1},
713 {0, 20, "WINE", FR_MATCHCASE, 0},
714
715 {0, -1, "wineWine wine", FR_DOWN, 0},
716 {0, -1, "wineWine wine", 0, 0},
717 {0, -1, "INEW", 0, 1},
718 {0, 31, "INEW", 0, 1},
719 {4, -1, "INEW", 0, 10},
720};
721
722static struct find_s find_tests3[] = {
723 /* Searching for end of line characters */
724 {0, -1, "t\r\r\ns", FR_DOWN | FR_MATCHCASE, 4},
725 {6, -1, "\r\n", FR_DOWN | FR_MATCHCASE, 6},
726 {7, -1, "\n", FR_DOWN | FR_MATCHCASE, 7},
727};
728
729static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
730 int findloc;
731 FINDTEXTA ft;
732 memset(&ft, 0, sizeof(ft));
733 ft.chrg.cpMin = f->start;
734 ft.chrg.cpMax = f->end;
735 ft.lpstrText = f->needle;
736 findloc = SendMessageA(hwnd, EM_FINDTEXT, f->flags, (LPARAM)&ft);
737 ok(findloc == f->expected_loc,
738 "EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
739 name, id, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
740}
741
742static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f,
743 int id) {
744 int findloc;
745 FINDTEXTEXA ft;
746 int expected_end_loc;
747
748 memset(&ft, 0, sizeof(ft));
749 ft.chrg.cpMin = f->start;
750 ft.chrg.cpMax = f->end;
751 ft.lpstrText = f->needle;
752 ft.chrgText.cpMax = 0xdeadbeef;
753 findloc = SendMessageA(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM)&ft);
754 ok(findloc == f->expected_loc,
755 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
756 name, id, f->needle, f->start, f->end, f->flags, findloc);
757 ok(ft.chrgText.cpMin == f->expected_loc,
758 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d, expected %d\n",
759 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin, f->expected_loc);
760 expected_end_loc = ((f->expected_loc == -1) ? -1
761 : f->expected_loc + strlen(f->needle));
762 ok(ft.chrgText.cpMax == expected_end_loc ||
763 broken(ft.chrgText.cpMin == -1 && ft.chrgText.cpMax == 0xdeadbeef), /* Win9x, WinME and NT4 */
764 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d, expected %d\n",
765 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax, expected_end_loc);
766}
767
768static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find,
769 int num_tests)
770{
771 int i;
772
773 for (i = 0; i < num_tests; i++) {
776 }
777}
778
779static void test_EM_FINDTEXT(void)
780{
781 HWND hwndRichEdit = new_richedit(NULL);
782
783 /* Empty rich edit control */
785
786 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)haystack);
787
788 /* Haystack text */
790
791 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)haystack2);
792
793 /* Haystack text 2 (with EOL characters) */
795
796 DestroyWindow(hwndRichEdit);
797}
798
799static void test_EM_POSFROMCHAR(void)
800{
801 HWND hwndRichEdit = new_richedit(NULL);
802 int i;
803 POINTL pl;
805 unsigned int height = 0;
806 int xpos = 0;
807 int xpos_rtl_adjusted = 0;
808 static const char text[] = "aa\n"
809 "this is a long line of text that should be longer than the "
810 "control's width\n"
811 "cc\n"
812 "dd\n"
813 "ee\n"
814 "ff\n"
815 "gg\n"
816 "hh\n";
817
818 /* Fill the control to lines to ensure that most of them are offscreen */
819 for (i = 0; i < 50; i++)
820 {
821 /* Do not modify the string; it is exactly 16 characters long. */
822 SendMessageA(hwndRichEdit, EM_SETSEL, 0, 0);
823 SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"0123456789ABCD\r\n");
824 }
825
826 /*
827 Richedit 1.0 receives a POINTL* on wParam and character offset on lParam, returns void.
828 Richedit 2.0 receives character offset on wParam, ignores lParam, returns MAKELONG(x,y)
829 Richedit 3.0 accepts either of the above API conventions.
830 */
831
832 /* Testing Richedit 1.0 API format */
833
834 /* Testing start of lines. X-offset should be constant on all cases (native is 1).
835 Since all lines are identical and drawn with the same font,
836 they should have the same height... right?
837 */
838 for (i = 0; i < 50; i++)
839 {
840 /* All the lines are 16 characters long */
841 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16);
842 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
843 if (i == 0)
844 {
845 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
846 ok(pl.x == 1 ||
847 broken(pl.x == 0), /* Win9x, WinME and NT4 */
848 "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
849 xpos = pl.x;
850 xpos_rtl_adjusted = xpos + (is_rtl() ? 7 : 0);
851 }
852 else if (i == 1)
853 {
854 ok(pl.y > 0, "EM_POSFROMCHAR reports y=%d, expected > 0\n", pl.y);
855 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
856 height = pl.y;
857 }
858 else
859 {
860 ok(pl.y == i * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, i * height);
861 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
862 }
863 }
864
865 /* Testing position at end of text */
866 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16);
867 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
868 ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height);
869 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
870
871 /* Testing position way past end of text */
872 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16);
873 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
874 ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height);
875
876 ok(pl.x == xpos_rtl_adjusted, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos_rtl_adjusted);
877
878
879 /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */
880 SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */
881 for (i = 0; i < 50; i++)
882 {
883 /* All the lines are 16 characters long */
884 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16);
885 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
886 ok(pl.y == (i - 1) * height,
887 "EM_POSFROMCHAR reports y=%d, expected %d\n",
888 pl.y, (i - 1) * height);
889 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
890 }
891
892 /* Testing position at end of text */
893 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16);
894 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
895 ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height);
896 ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos);
897
898 /* Testing position way past end of text */
899 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16);
900 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
901 ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height);
902 ok(pl.x == xpos_rtl_adjusted, "EM_POSFROMCHAR reports x=%d, expected %d\n", pl.x, xpos_rtl_adjusted);
903
904 /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */
905 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
906 SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */
907
908 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0);
909 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
910 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
911 ok(pl.x == 1 ||
912 broken(pl.x == 0), /* Win9x, WinME and NT4 */
913 "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x);
914 xpos = pl.x;
915
916 SendMessageA(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0);
917 result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0);
918 ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result);
919 ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y);
920 todo_wine {
921 /* Fails on builtin because horizontal scrollbar is not being shown */
922 ok(pl.x < xpos ||
923 broken(pl.x == xpos), /* Win9x, WinME and NT4 */
924 "EM_POSFROMCHAR reports x=%d, expected value less than %d\n", pl.x, xpos);
925 }
926 DestroyWindow(hwndRichEdit);
927}
928
929static void test_word_wrap(void)
930{
931 HWND hwnd;
932 POINTL point = {0, 60}; /* This point must be below the first line */
933 const char *text = "Must be long enough to test line wrapping";
935 int res, pos, lines, prevlines, reflines[3];
936
937 /* Test the effect of WS_HSCROLL and ES_AUTOHSCROLL styles on wrapping
938 * when specified on window creation and set later. */
939 hwnd = CreateWindowA(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
940 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
941 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
943 ok(res, "WM_SETTEXT failed.\n");
945 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
947 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
948
951 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
953
955 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
956 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
957
959 ok(res, "WM_SETTEXT failed.\n");
961 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
963 ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
964
967 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
969
971 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
972 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
974 ok(res, "WM_SETTEXT failed.\n");
976 ok(!pos ||
977 broken(pos == lstrlenA(text)), /* Win9x, WinME and NT4 */
978 "pos=%d indicating word wrap when none is expected.\n", pos);
980 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
981
982 SetWindowLongA(hwnd, GWL_STYLE, dwCommonStyle);
984 ok(!pos ||
985 broken(pos == lstrlenA(text)), /* Win9x, WinME and NT4 */
986 "pos=%d indicating word wrap when none is expected.\n", pos);
988 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
990
992 dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL,
993 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
994 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
996 ok(res, "WM_SETTEXT failed.\n");
998 ok(!pos ||
999 broken(pos == lstrlenA(text)), /* Win9x, WinME and NT4 */
1000 "pos=%d indicating word wrap when none is expected.\n", pos);
1002 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
1003
1004 SetWindowLongA(hwnd, GWL_STYLE, dwCommonStyle);
1006 ok(!pos ||
1007 broken(pos == lstrlenA(text)), /* Win9x, WinME and NT4 */
1008 "pos=%d indicating word wrap when none is expected.\n", pos);
1010 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
1011
1012 /* Test the effect of EM_SETTARGETDEVICE on word wrap. */
1014 ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
1016 ok(!pos ||
1017 broken(pos == lstrlenA(text)), /* Win9x, WinME and NT4 */
1018 "pos=%d indicating word wrap when none is expected.\n", pos);
1020 ok(lines == 1, "Line was not expected to wrap (lines=%d).\n", lines);
1021
1023 ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
1025 ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
1027
1028 /* First lets see if the text would wrap normally (needed for reference) */
1029 hwnd = CreateWindowA(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
1030 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
1031 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
1032 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1034 ok(res, "EM_REPLACESEL failed.\n");
1035 /* Should have wrapped */
1036 reflines[0] = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
1037 ok(reflines[0] > 1, "Line was expected to wrap (%d lines).\n", reflines[0]);
1038 /* Resize the window to fit the line */
1039 MoveWindow(hwnd, 0, 0, 600, 80, TRUE);
1040 /* Text should not be wrapped */
1041 reflines[1] = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
1042 ok(reflines[1] == 1, "Line wasn't expected to wrap (%d lines).\n", reflines[1]);
1043 /* Resize the window again to make sure the line wraps again */
1044 MoveWindow(hwnd, 0, 0, 10, 80, TRUE);
1045 reflines[2] = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
1046 ok(reflines[2] > 1, "Line was expected to wrap (%d lines).\n", reflines[2]);
1048
1049 /* Same test with redraw disabled */
1050 hwnd = CreateWindowA(RICHEDIT_CLASS10A, NULL, dwCommonStyle,
1051 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
1052 ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
1053 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1054 /* Redraw is disabled by making the window invisible. */
1056 ok(!IsWindowVisible(hwnd), "Window shouldn't be visible.\n");
1058 ok(res, "EM_REPLACESEL failed.\n");
1059 /* Should have wrapped */
1060 prevlines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
1061 ok(prevlines == reflines[0],
1062 "Line was expected to wrap (%d lines).\n", prevlines);
1063 /* Resize the window to fit the line, no change to the number of lines */
1064 MoveWindow(hwnd, 0, 0, 600, 80, TRUE);
1066 todo_wine
1067 ok(lines == prevlines ||
1068 broken(lines == reflines[1]), /* Win98, WinME and NT4 */
1069 "Expected no change in the number of lines\n");
1070 /* Resize the window again to make sure the line wraps again */
1071 MoveWindow(hwnd, 0, 0, 10, 80, TRUE);
1073 todo_wine
1074 ok(lines == prevlines ||
1075 broken(lines == reflines[2]), /* Win98, WinME and NT4 */
1076 "Expected no change in the number of lines\n");
1078}
1079
1080static void test_EM_GETOPTIONS(void)
1081{
1082 HWND hwnd;
1083 DWORD options;
1084
1086 WS_POPUP,
1087 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1089 ok(options == 0, "Incorrect options %x\n", options);
1091
1094 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1097 broken(options == 0), /* Win9x, WinME and NT4 */
1098 "Incorrect initial options %x\n", options);
1100}
1101
1102static void test_autoscroll(void)
1103{
1104 HWND hwnd;
1105 UINT ret;
1106
1107 /* The WS_VSCROLL and WS_HSCROLL styles implicitly set
1108 * auto vertical/horizontal scrolling options. */
1111 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1112 ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS10A, (int) GetLastError());
1115 broken(!(ret & ECO_AUTOVSCROLL)), /* Win9x, WinME and NT4 */
1116 "ECO_AUTOVSCROLL isn't set.\n");
1117 ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
1119 todo_wine
1120 ok(ret & ES_AUTOVSCROLL ||
1121 broken(!(ret & ES_AUTOVSCROLL)), /* Win9x, WinMe and NT4 */
1122 "ES_AUTOVSCROLL isn't set.\n");
1123 ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
1125
1128 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
1129 ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS10A, (int) GetLastError());
1131 ok(!(ret & ECO_AUTOVSCROLL), "ECO_AUTOVSCROLL is set.\n");
1132 ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
1134 ok(!(ret & ES_AUTOVSCROLL), "ES_AUTOVSCROLL is set.\n");
1135 ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
1137}
1138
1139static void simulate_typing_characters(HWND hwnd, const char* szChars)
1140{
1141 int ret;
1142
1143 while (*szChars != '\0') {
1144 SendMessageA(hwnd, WM_KEYDOWN, *szChars, 1);
1145 ret = SendMessageA(hwnd, WM_CHAR, *szChars, 1);
1146 ok(ret == 0, "WM_CHAR('%c') ret=%d\n", *szChars, ret);
1147 SendMessageA(hwnd, WM_KEYUP, *szChars, 1);
1148 szChars++;
1149 }
1150}
1151
1152static void format_test_result(char *target, const char *src)
1153{
1154 int i;
1155 for (i = 0; i < strlen(src); i++)
1156 sprintf(target + 2*i, "%02x", src[i] & 0xFF);
1157 target[2*i] = 0;
1158}
1159
1160/*
1161 * This test attempts to show the effect of enter on a richedit
1162 * control v1.0 inserts CRLF whereas for higher versions it only
1163 * inserts CR. If shows that EM_GETTEXTEX with GT_USECRLF == WM_GETTEXT
1164 * and also shows that GT_USECRLF has no effect in richedit 1.0, but
1165 * does for higher. The same test is cloned in riched32 and riched20.
1166 * Also shows the difference between WM_CHAR/WM_KEYDOWN in v1.0 and higher versions
1167 */
1168static void test_enter(void)
1169{
1170 static const struct {
1171 const char *initialtext;
1172 const int cursor;
1173 const char *expectedtext;
1174 } testenteritems[] = {
1175 { "aaabbb\r\n", 3, "aaa\r\nbbb\r\n"},
1176 { "aaabbb\r\n", 6, "aaabbb\r\n\r\n"},
1177 { "aa\rabbb\r\n", 7, "aa\rabbb\r\n\r\n"},
1178 { "aa\rabbb\r\n", 3, "aa\r\r\nabbb\r\n"},
1179 { "aa\rabbb\r\n", 2, "aa\r\n\rabbb\r\n"}
1180 };
1181
1182 char expectedbuf[1024];
1183 char resultbuf[1024];
1184 HWND hwndRichEdit = new_richedit(NULL);
1185 UINT i;
1186 char buf[1024] = {0};
1187 GETTEXTEX getText = {sizeof(buf)};
1189 const char *expected;
1190
1191 for (i = 0; i < ARRAY_SIZE(testenteritems); i++)
1192 {
1193 /* Set the text to the initial text */
1194 result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)testenteritems[i].initialtext);
1195 ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
1196
1197 /* Send Enter */
1198 SendMessageA(hwndRichEdit, EM_SETSEL, testenteritems[i].cursor, testenteritems[i].cursor);
1199 simulate_typing_characters(hwndRichEdit, "\r");
1200
1201 /* 1. Retrieve with WM_GETTEXT */
1202 buf[0] = 0x00;
1203 result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buf);
1204 expected = testenteritems[i].expectedtext;
1205
1206 format_test_result(resultbuf, buf);
1207 format_test_result(expectedbuf, expected);
1208
1210 ok (result == 0,
1211 "[%d] WM_GETTEXT unexpected '%s' expected '%s'\n",
1212 i, resultbuf, expectedbuf);
1213
1214 /* 2. Retrieve with EM_GETTEXTEX, GT_DEFAULT */
1215 getText.flags = GT_DEFAULT;
1216 getText.codepage = CP_ACP;
1217 buf[0] = 0x00;
1218 result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
1219 expected = testenteritems[i].expectedtext;
1220
1221 format_test_result(resultbuf, buf);
1222 format_test_result(expectedbuf, expected);
1223
1225 ok (result == 0 || broken(buf[0]==0x00 /* WinNT4 */),
1226 "[%d] EM_GETTEXTEX, GT_DEFAULT unexpected '%s', expected '%s'\n",
1227 i, resultbuf, expectedbuf);
1228
1229 /* 3. Retrieve with EM_GETTEXTEX, GT_USECRLF */
1230 getText.flags = GT_USECRLF;
1231 getText.codepage = CP_ACP;
1232 buf[0] = 0x00;
1233 result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
1234 expected = testenteritems[i].expectedtext;
1235
1236 format_test_result(resultbuf, buf);
1237 format_test_result(expectedbuf, expected);
1238
1240 ok (result == 0 || broken(buf[0]==0x00 /* WinNT4 */),
1241 "[%d] EM_GETTEXTEX, GT_USECRLF unexpected '%s', expected '%s'\n",
1242 i, resultbuf, expectedbuf);
1243 }
1244
1245 /* Show that WM_CHAR is handled differently from WM_KEYDOWN */
1246 getText.flags = GT_DEFAULT;
1247 getText.codepage = CP_ACP;
1248
1249 result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
1250 ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
1251 SendMessageW(hwndRichEdit, WM_CHAR, 'T', 0);
1252 SendMessageW(hwndRichEdit, WM_KEYDOWN, VK_RETURN, 0);
1253
1254 result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
1255 ok(result == 1, "Got %d\n", (int)result);
1256 format_test_result(resultbuf, buf);
1257 format_test_result(expectedbuf, "T");
1258 result = strcmp(resultbuf, expectedbuf);
1259 ok (result == 0, "[%d] EM_GETTEXTEX, GT_DEFAULT unexpected '%s', expected '%s'\n", i, resultbuf, expectedbuf);
1260
1261 result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
1262 ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
1263 SendMessageW(hwndRichEdit, WM_CHAR, 'T', 0);
1264 SendMessageW(hwndRichEdit, WM_CHAR, '\r', 0);
1265
1266 result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
1267 ok(result == 3, "Got %ld\n", result);
1268 format_test_result(resultbuf, buf);
1269 format_test_result(expectedbuf, "T\r\n");
1270 result = strcmp(resultbuf, expectedbuf);
1271 ok (result == 0, "[%d] EM_GETTEXTEX, GT_DEFAULT unexpected '%s', expected '%s'\n", i, resultbuf, expectedbuf);
1272
1273 DestroyWindow(hwndRichEdit);
1274}
1275
1276struct exsetsel_s {
1277 LONG min;
1278 LONG max;
1284};
1285
1286static const struct exsetsel_s exsetsel_tests[] = {
1287 /* sanity tests */
1288 {5, 10, 10, 5, 10, 0, 0 },
1289 {15, 17, 17, 15, 17, 0, 0 },
1290 /* test cpMax > strlen() */
1291 {0, 100, 19, 0, 19, 1, 0 },
1292 /* test cpMin < 0 && cpMax >= 0 after cpMax > strlen() */
1293 {-1, 1, 17, 17, 17, 1, 0 },
1294 /* test cpMin == cpMax */
1295 {5, 5, 5, 5, 5, 0, 0 },
1296 /* test cpMin < 0 && cpMax >= 0 (bug 4462) */
1297 {-1, 0, 5, 5, 5, 0, 0 },
1298 {-1, 17, 5, 5, 5, 0, 0 },
1299 {-1, 18, 5, 5, 5, 0, 0 },
1300 /* test cpMin < 0 && cpMax < 0 */
1301 {-1, -1, 17, 17, 17, 0, 0 },
1302 {-4, -5, 17, 17, 17, 0, 0 },
1303 /* test cpMin >=0 && cpMax < 0 (bug 6814) */
1304 {0, -1, 19, 0, 19, 1, 0 },
1305 {17, -5, 19, 17, 19, 1, 0 },
1306 {18, -3, 19, 17, 19, 1, 1 },
1307 /* test if cpMin > cpMax */
1308 {15, 19, 19, 15, 19, 1, 0 },
1309 {19, 15, 19, 15, 19, 1, 0 },
1310 /* cpMin == strlen() && cpMax > cpMin */
1311 {17, 18, 17, 17, 17, 1, 1 },
1312 {17, 50, 19, 17, 19, 1, 0 },
1313};
1314
1315static void check_EM_EXSETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id) {
1316 CHARRANGE cr;
1318 int start, end;
1319
1320 cr.cpMin = setsel->min;
1321 cr.cpMax = setsel->max;
1323
1324 todo_wine_if (setsel->result_todo)
1325 ok(result == setsel->expected_retval, "EM_EXSETSEL(%d): expected: %ld actual: %ld\n", id, setsel->expected_retval, result);
1326
1328
1329 todo_wine_if (setsel->sel_todo)
1330 ok(start == setsel->expected_getsel_start && end == setsel->expected_getsel_end,
1331 "EM_EXSETSEL(%d): expected (%d,%d) actual:(%d,%d)\n",
1332 id, setsel->expected_getsel_start, setsel->expected_getsel_end, start, end);
1333}
1334
1335static void test_EM_EXSETSEL(void)
1336{
1337 HWND hwndRichEdit = new_richedit(NULL);
1338 int i;
1339 const int num_tests = ARRAY_SIZE(exsetsel_tests);
1340
1341 /* sending some text to the window */
1342 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"testing selection");
1343 /* 01234567890123456 */
1344
1345 for (i = 0; i < num_tests; i++) {
1346 check_EM_EXSETSEL(hwndRichEdit, &exsetsel_tests[i], i);
1347 }
1348
1349 if (!is_lang_japanese)
1350 skip("Skip multibyte character tests on non-Japanese platform\n");
1351 else
1352 {
1353 CHARRANGE cr;
1355#define MAX_BUF_LEN 1024
1356 char bufA[MAX_BUF_LEN] = {0};
1357
1358 /* Test with multibyte character */
1359 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
1360 /* 012345 6 7 8901 */
1361 cr.cpMin = 4; cr.cpMax = 8;
1362 result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1363 todo_wine ok(result == 7, "EM_EXSETSEL return %ld expected 7\n", result);
1364 result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, sizeof(bufA), (LPARAM)bufA);
1365 todo_wine ok(!strcmp(bufA, "ef\x8e\xf0"), "EM_GETSELTEXT return incorrect string\n");
1366 SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
1367 ok(cr.cpMin == 4, "Selection start incorrectly: %d expected 4\n", cr.cpMin);
1368 ok(cr.cpMax == 8, "Selection end incorrectly: %d expected 8\n", cr.cpMax);
1369 }
1370
1371 DestroyWindow(hwndRichEdit);
1372}
1373
1374static void check_EM_SETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id) {
1376 int start, end;
1377
1378 result = SendMessageA(hwnd, EM_SETSEL, setsel->min, setsel->max);
1379
1380 todo_wine_if (setsel->result_todo)
1381 ok(result == setsel->expected_retval, "EM_SETSEL(%d): expected: %ld actual: %ld\n", id, setsel->expected_retval, result);
1382
1384
1385 todo_wine_if (setsel->sel_todo)
1386 ok(start == setsel->expected_getsel_start && end == setsel->expected_getsel_end,
1387 "EM_SETSEL(%d): expected (%d,%d) actual:(%d,%d)\n",
1388 id, setsel->expected_getsel_start, setsel->expected_getsel_end, start, end);
1389}
1390
1391static void test_EM_SETSEL(void)
1392{
1393 char buffA[32] = {0};
1394 HWND hwndRichEdit = new_richedit(NULL);
1395 int i;
1396 const int num_tests = ARRAY_SIZE(exsetsel_tests);
1397
1398 /* sending some text to the window */
1399 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"testing selection");
1400 /* 01234567890123456 */
1401
1402 for (i = 0; i < num_tests; i++) {
1403 check_EM_SETSEL(hwndRichEdit, &exsetsel_tests[i], i);
1404 }
1405
1406 SendMessageA(hwndRichEdit, EM_SETSEL, 17, 18);
1407 buffA[0] = 123;
1408 SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffA);
1409 ok(buffA[0] == 0, "selection text %s\n", buffA);
1410
1411 if (!is_lang_japanese)
1412 skip("Skip multibyte character tests on non-Japanese platform\n");
1413 else
1414 {
1415 int sel_start, sel_end;
1417
1418 /* Test with multibyte character */
1419 SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
1420 /* 012345 6 7 8901 */
1421 result = SendMessageA(hwndRichEdit, EM_SETSEL, 4, 8);
1422 todo_wine ok(result == 7, "EM_SETSEL return %ld expected 7\n", result);
1423 result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, sizeof(buffA), (LPARAM)buffA);
1424 todo_wine ok(!strcmp(buffA, "ef\x8e\xf0"), "EM_GETSELTEXT return incorrect string\n");
1425 result = SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
1426 ok(sel_start == 4, "Selection start incorrectly: %d expected 4\n", sel_start);
1427 ok(sel_end == 8, "Selection end incorrectly: %d expected 8\n", sel_end);
1428 }
1429
1430 DestroyWindow(hwndRichEdit);
1431}
1432
1433START_TEST( editor )
1434{
1435 MSG msg;
1436 time_t end;
1437 BOOL ret;
1438
1439 /* Must explicitly LoadLibrary(). The test has no references to functions in
1440 * RICHED32.DLL, so the linker doesn't actually link to it. */
1441 hmoduleRichEdit = LoadLibraryA("riched32.dll");
1442 ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
1444
1458 test_enter();
1461
1462 /* Set the environment variable WINETEST_RICHED32 to keep windows
1463 * responsive and open for 30 seconds. This is useful for debugging.
1464 *
1465 * The message pump uses PeekMessage() to empty the queue and then sleeps for
1466 * 50ms before retrying the queue. */
1467 end = time(NULL) + 30;
1468 if (getenv( "WINETEST_RICHED32" )) {
1469 while (time(NULL) < end) {
1470 if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
1473 } else {
1474 Sleep(50);
1475 }
1476 }
1477 }
1478
1481 ok(ret, "error: %u\n", GetLastError());
1482}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define msg(x)
Definition: auth_time.c:54
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FR_WHOLEWORD
Definition: commdlg.h:145
#define FR_MATCHCASE
Definition: commdlg.h:136
#define FR_DOWN
Definition: commdlg.h:127
static TAGID TAGID find
Definition: db.cpp:155
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CP_ACP
Definition: compat.h:109
#define FreeLibrary(x)
Definition: compat.h:748
#define CALLBACK
Definition: compat.h:35
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1600
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1177
const WCHAR * text
Definition: package.c:1794
HRESULT WINAPI OleFlushClipboard(void)
Definition: clipboard.c:2293
r parent
Definition: btrfs.c:3010
__kernel_time_t time_t
Definition: linux.h:252
POINTL point
Definition: edittest.c:50
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint start
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLfloat f
Definition: glext.h:7540
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define es
Definition: i386-dis.c:440
const char cursor[]
Definition: icontest.c:13
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define expect2(expected1, expected2, got1, got2)
Definition: listview.c:50
static BOOL rtl
Definition: propsheet.c:36
BOOL expected
Definition: store.c:2063
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
#define todo_wine_if(is_todo)
Definition: custom.c:86
#define todo_wine
Definition: custom.c:89
static char * dest
Definition: rtl.c:135
static void simulate_typing_characters(HWND hwnd, const char *szChars)
Definition: editor.c:104
static void test_EM_EXSETSEL(void)
Definition: editor.c:4948
static void test_EM_GETSELTEXT(void)
Definition: editor.c:1801
static void check_EM_SETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id)
Definition: editor.c:4987
static HMODULE hmoduleRichEdit
Definition: editor.c:51
static void format_test_result(char *target, const char *src)
Definition: editor.c:8282
static HWND new_richedit(HWND parent)
Definition: editor.c:72
static void test_EM_GETLINE(void)
Definition: editor.c:390
static void test_WM_GETTEXTLENGTH(void)
Definition: editor.c:8693
static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
Definition: editor.c:5736
static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find, int num_tests, BOOL unicode)
Definition: editor.c:321
static const struct exsetsel_s exsetsel_tests[]
Definition: editor.c:4901
static void test_EM_STREAMIN(void)
Definition: editor.c:5826
static void check_EM_EXSETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id)
Definition: editor.c:4930
static void test_EM_STREAMOUT(void)
Definition: editor.c:3821
static void test_WM_SETTEXT(void)
Definition: editor.c:3693
static BOOL is_lang_japanese
Definition: editor.c:52
static struct find_s find_tests2[]
Definition: editor.c:166
static void test_EM_LINELENGTH(void)
Definition: editor.c:462
static struct find_s find_tests[]
Definition: editor.c:157
static void test_EM_SETSEL(void)
Definition: editor.c:5002
#define MAX_BUF_LEN
static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id, BOOL unicode)
Definition: editor.c:239
static void test_autoscroll(void)
Definition: editor.c:7336
static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f, int id, BOOL unicode)
Definition: editor.c:275
static void test_word_wrap(void)
Definition: editor.c:7240
static void test_enter(void)
Definition: editor.c:8298
static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
Definition: editor.c:3678
static void test_EM_POSFROMCHAR(void)
Definition: editor.c:597
static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent)
Definition: editor.c:54
static const struct getline_s gl[]
static const char haystack[]
Definition: editor.c:145
static void test_EM_GETTEXTRANGE(void)
Definition: editor.c:1717
static void test_EM_GETOPTIONS(void)
Definition: editor.c:1080
static const char haystack2[]
Definition: editor.c:635
static struct find_s find_tests3[]
Definition: editor.c:722
static BOOL is_rtl(void)
Definition: editor.c:53
static void test_EM_FINDTEXT(void)
Definition: editor.c:779
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_USER_DEFAULT
#define ES_AUTOVSCROLL
Definition: pedump.c:671
#define WS_POPUP
Definition: pedump.c:616
#define WS_VSCROLL
Definition: pedump.c:627
#define ES_AUTOHSCROLL
Definition: pedump.c:672
#define WS_VISIBLE
Definition: pedump.c:620
long LONG
Definition: pedump.c:60
#define WS_HSCROLL
Definition: pedump.c:628
#define ES_MULTILINE
Definition: pedump.c:667
#define GT_DEFAULT
Definition: richedit.h:1036
#define EM_GETSELTEXT
Definition: richedit.h:95
#define EM_STREAMIN
Definition: richedit.h:106
#define RICHEDIT_CLASS10A
Definition: richedit.h:52
#define SF_RTF
Definition: richedit.h:721
#define EM_POSFROMCHAR
Definition: richedit.h:77
#define EM_GETOPTIONS
Definition: richedit.h:111
#define ECO_AUTOHSCROLL
Definition: richedit.h:458
#define EM_CHARFROMPOS
Definition: richedit.h:78
#define EM_GETTEXTRANGE
Definition: richedit.h:108
#define EM_EXSETSEL
Definition: richedit.h:88
#define SF_TEXT
Definition: richedit.h:720
#define EM_FINDTEXT
Definition: richedit.h:89
#define EM_SETTARGETDEVICE
Definition: richedit.h:105
#define GT_USECRLF
Definition: richedit.h:1037
#define ECO_AUTOVSCROLL
Definition: richedit.h:457
#define EM_GETTEXTEX
Definition: richedit.h:128
#define EM_EXGETSEL
Definition: richedit.h:85
#define EM_FINDTEXTEX
Definition: richedit.h:112
#define EM_STREAMOUT
Definition: richedit.h:107
const WCHAR * str
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define win_skip
Definition: test.h:163
static int gl_text(adns_state ads, getline_ctx *src_io, const char *filename, int lno, char *buf, int buflen)
Definition: setup.c:337
#define memset(x, y, z)
Definition: compat.h:39
LONG y
Definition: windef.h:330
LONG x
Definition: windef.h:329
LONG cpMax
Definition: richedit.h:501
LONG cpMin
Definition: richedit.h:500
CHARRANGE chrg
Definition: richedit.h:581
LPCSTR lpstrText
Definition: richedit.h:582
LPCSTR lpstrText
Definition: richedit.h:594
CHARRANGE chrg
Definition: richedit.h:593
CHARRANGE chrgText
Definition: richedit.h:595
DWORD flags
Definition: richedit.h:707
UINT codepage
Definition: richedit.h:708
CHARRANGE chrg
Definition: richedit.h:508
LPSTR lpstrText
Definition: richedit.h:509
LRESULT expected_retval
Definition: editor.c:4895
LONG max
Definition: editor.c:4894
BOOL sel_todo
Definition: editor.c:1283
BOOL result_todo
Definition: editor.c:1282
int expected_getsel_end
Definition: editor.c:4897
LONG min
Definition: editor.c:4893
int expected_getsel_start
Definition: editor.c:4896
Definition: editor.c:148
int flags
Definition: editor.c:152
int start
Definition: editor.c:149
int end
Definition: editor.c:150
int expected_loc
Definition: editor.c:153
const char * needle
Definition: editor.c:151
const char * broken_text
Definition: editor.c:376
size_t buffer_len
Definition: editor.c:376
int line
Definition: editor.c:375
const char * text
Definition: editor.c:377
Definition: parser.c:49
Definition: name.c:39
DWORD lsUsb[4]
Definition: wingdi.h:2611
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
#define DWORD_PTR
Definition: treelist.c:76
eMaj lines
Definition: tritemp.h:206
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint32_t DWORD_PTR
Definition: typedefs.h:65
unsigned char * LPBYTE
Definition: typedefs.h:53
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define LOCALE_FONTSIGNATURE
Definition: winnls.h:127
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define WM_GETTEXTLENGTH
Definition: winuser.h:1622
#define SB_LINEUP
Definition: winuser.h:564
#define WM_HSCROLL
Definition: winuser.h:1746
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define WM_KEYUP
Definition: winuser.h:1719
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
LONG WINAPI GetWindowLongA(_In_ HWND, _In_ int)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4318
LONG WINAPI SetWindowLongA(_In_ HWND, _In_ int, _In_ LONG)
#define EM_GETSEL
Definition: winuser.h:2000
#define EM_REPLACESEL
Definition: winuser.h:2009
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_GETTEXT
Definition: winuser.h:1621
#define SB_LINERIGHT
Definition: winuser.h:567
#define WM_SETTEXT
Definition: winuser.h:1620
#define EM_LINELENGTH
Definition: winuser.h:2006
#define VK_RETURN
Definition: winuser.h:2204
#define EM_GETLINE
Definition: winuser.h:1994
#define EM_SCROLL
Definition: winuser.h:2010
#define PM_REMOVE
Definition: winuser.h:1199
#define SB_LINEDOWN
Definition: winuser.h:565
#define EM_SETSEL
Definition: winuser.h:2021
#define WM_CHAR
Definition: winuser.h:1720
BOOL WINAPI PeekMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
#define WM_KEYDOWN
Definition: winuser.h:1718
#define EM_GETLINECOUNT
Definition: winuser.h:1995
#define GWL_STYLE
Definition: winuser.h:855
BOOL WINAPI IsWindowVisible(_In_ HWND)
BOOL WINAPI DestroyWindow(_In_ HWND)
BOOL WINAPI MoveWindow(_In_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ BOOL)
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_SETREDRAW
Definition: winuser.h:1619
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182