1 /* Unit test suite for edit control.
2 *
3 * Copyright 2004 Vitaliy Margolen
4 * Copyright 2005 C. Scott Ananian
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <assert.h>
22 #include <windows.h>
23 #include <commctrl.h>
24
25 #include "wine/test.h"
26
27 #ifndef ES_COMBO
28 #define ES_COMBO 0x200
29 #endif
30
31 #define ID_EDITTEST2 99
32 #define MAXLEN 200
33
34 struct edit_notify {
35 int en_change, en_maxtext, en_update;
36 };
37
38 static struct edit_notify notifications;
39
40 static INT_PTR CALLBACK multi_edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
41 {
42 static int num_ok_commands = 0;
43 switch (msg)
44 {
45 case WM_INITDIALOG:
46 {
47 HWND hedit = GetDlgItem(hdlg, 1000);
48 SetFocus(hedit);
49 switch (lparam)
50 {
51 /* test cases related to bug 12319 */
52 case 0:
53 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
54 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
55 break;
56 case 1:
57 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
58 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
59 break;
60 case 2:
61 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
62 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
63 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
64 break;
65
66 /* test cases for pressing enter */
67 case 3:
68 num_ok_commands = 0;
69 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
70 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
71 break;
72
73 default:
74 break;
75 }
76 break;
77 }
78
79 case WM_COMMAND:
80 if (HIWORD(wparam) != BN_CLICKED)
81 break;
82
83 switch (LOWORD(wparam))
84 {
85 case IDOK:
86 num_ok_commands++;
87 break;
88
89 default:
90 break;
91 }
92 break;
93
94 case WM_USER:
95 {
96 HWND hfocus = GetFocus();
97 HWND hedit = GetDlgItem(hdlg, 1000);
98 HWND hedit2 = GetDlgItem(hdlg, 1001);
99 HWND hedit3 = GetDlgItem(hdlg, 1002);
100
101 if (wparam != 0xdeadbeef)
102 break;
103
104 switch (lparam)
105 {
106 case 0:
107 if (hfocus == hedit)
108 EndDialog(hdlg, 1111);
109 else if (hfocus == hedit2)
110 EndDialog(hdlg, 2222);
111 else if (hfocus == hedit3)
112 EndDialog(hdlg, 3333);
113 else
114 EndDialog(hdlg, 4444);
115 break;
116 case 1:
117 if ((hfocus == hedit) && (num_ok_commands == 0))
118 EndDialog(hdlg, 11);
119 else
120 EndDialog(hdlg, 22);
121 break;
122 default:
123 EndDialog(hdlg, 5555);
124 }
125 break;
126 }
127
128 case WM_CLOSE:
129 EndDialog(hdlg, 333);
130 break;
131
132 default:
133 break;
134 }
135
136 return FALSE;
137 }
138
139 static INT_PTR CALLBACK edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
140 {
141 switch (msg)
142 {
143 case WM_INITDIALOG:
144 {
145 HWND hedit = GetDlgItem(hdlg, 1000);
146 SetFocus(hedit);
147 switch (lparam)
148 {
149 /* from bug 11841 */
150 case 0:
151 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
152 break;
153 case 1:
154 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
155 break;
156 case 2:
157 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
158 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
159 break;
160
161 /* more test cases for WM_CHAR */
162 case 3:
163 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
164 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
165 break;
166 case 4:
167 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
168 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
169 break;
170 case 5:
171 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
172 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
173 break;
174
175 /* more test cases for WM_KEYDOWN + WM_CHAR */
176 case 6:
177 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
178 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
179 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
180 break;
181 case 7:
182 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
183 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
184 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
185 break;
186 case 8:
187 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
188 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
189 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
190 break;
191
192 /* multiple tab tests */
193 case 9:
194 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
195 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
196 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
197 break;
198 case 10:
199 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
200 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
201 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
202 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
203 break;
204
205 default:
206 break;
207 }
208 break;
209 }
210
211 case WM_COMMAND:
212 if (HIWORD(wparam) != BN_CLICKED)
213 break;
214
215 switch (LOWORD(wparam))
216 {
217 case IDOK:
218 EndDialog(hdlg, 111);
219 break;
220
221 case IDCANCEL:
222 EndDialog(hdlg, 222);
223 break;
224
225 default:
226 break;
227 }
228 break;
229
230 case WM_USER:
231 {
232 int len;
233 HWND hok = GetDlgItem(hdlg, IDOK);
234 HWND hcancel = GetDlgItem(hdlg, IDCANCEL);
235 HWND hedit = GetDlgItem(hdlg, 1000);
236 HWND hfocus = GetFocus();
237
238 if (wparam != 0xdeadbeef)
239 break;
240
241 switch (lparam)
242 {
243 case 0:
244 len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
245 if (len == 0)
246 EndDialog(hdlg, 444);
247 else
248 EndDialog(hdlg, 555);
249 break;
250
251 case 1:
252 len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
253 if ((hfocus == hok) && len == 0)
254 EndDialog(hdlg, 444);
255 else
256 EndDialog(hdlg, 555);
257 break;
258
259 case 2:
260 if (hfocus == hok)
261 EndDialog(hdlg, 11);
262 else if (hfocus == hcancel)
263 EndDialog(hdlg, 22);
264 else if (hfocus == hedit)
265 EndDialog(hdlg, 33);
266 else
267 EndDialog(hdlg, 44);
268 break;
269
270 default:
271 EndDialog(hdlg, 555);
272 }
273 break;
274 }
275
276 case WM_CLOSE:
277 EndDialog(hdlg, 333);
278 break;
279
280 default:
281 break;
282 }
283
284 return FALSE;
285 }
286
287 static INT_PTR CALLBACK edit_singleline_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
288 {
289 switch (msg)
290 {
291 case WM_INITDIALOG:
292 {
293 HWND hedit = GetDlgItem(hdlg, 1000);
294 SetFocus(hedit);
295 switch (lparam)
296 {
297 /* test cases for WM_KEYDOWN */
298 case 0:
299 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
300 break;
301 case 1:
302 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
303 break;
304 case 2:
305 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
306 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
307 break;
308
309 /* test cases for WM_CHAR */
310 case 3:
311 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
312 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
313 break;
314 case 4:
315 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
316 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
317 break;
318 case 5:
319 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
320 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
321 break;
322
323 /* test cases for WM_KEYDOWN + WM_CHAR */
324 case 6:
325 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
326 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
327 break;
328 case 7:
329 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
330 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
331 break;
332 case 8:
333 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
334 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
335 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
336 break;
337
338 default:
339 break;
340 }
341 break;
342 }
343
344 case WM_COMMAND:
345 if (HIWORD(wparam) != BN_CLICKED)
346 break;
347
348 switch (LOWORD(wparam))
349 {
350 case IDOK:
351 EndDialog(hdlg, 111);
352 break;
353
354 case IDCANCEL:
355 EndDialog(hdlg, 222);
356 break;
357
358 default:
359 break;
360 }
361 break;
362
363 case WM_USER:
364 {
365 HWND hok = GetDlgItem(hdlg, IDOK);
366 HWND hedit = GetDlgItem(hdlg, 1000);
367 HWND hfocus = GetFocus();
368 int len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
369
370 if (wparam != 0xdeadbeef)
371 break;
372
373 switch (lparam)
374 {
375 case 0:
376 if ((hfocus == hedit) && len == 0)
377 EndDialog(hdlg, 444);
378 else
379 EndDialog(hdlg, 555);
380 break;
381
382 case 1:
383 if ((hfocus == hok) && len == 0)
384 EndDialog(hdlg, 444);
385 else
386 EndDialog(hdlg, 555);
387 break;
388
389 default:
390 EndDialog(hdlg, 55);
391 }
392 break;
393 }
394
395 case WM_CLOSE:
396 EndDialog(hdlg, 333);
397 break;
398
399 default:
400 break;
401 }
402
403 return FALSE;
404 }
405
406 static INT_PTR CALLBACK edit_wantreturn_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
407 {
408 switch (msg)
409 {
410 case WM_INITDIALOG:
411 {
412 HWND hedit = GetDlgItem(hdlg, 1000);
413 SetFocus(hedit);
414 switch (lparam)
415 {
416 /* test cases for WM_KEYDOWN */
417 case 0:
418 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
419 break;
420 case 1:
421 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
422 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
423 break;
424 case 2:
425 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
426 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
427 break;
428
429 /* test cases for WM_CHAR */
430 case 3:
431 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
432 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
433 break;
434 case 4:
435 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
436 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
437 break;
438 case 5:
439 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
440 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
441 break;
442
443 /* test cases for WM_KEYDOWN + WM_CHAR */
444 case 6:
445 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
446 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
447 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
448 break;
449 case 7:
450 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
451 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
452 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
453 break;
454 case 8:
455 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
456 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
457 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
458 break;
459
460 default:
461 break;
462 }
463 break;
464 }
465
466 case WM_COMMAND:
467 if (HIWORD(wparam) != BN_CLICKED)
468 break;
469
470 switch (LOWORD(wparam))
471 {
472 case IDOK:
473 EndDialog(hdlg, 111);
474 break;
475
476 case IDCANCEL:
477 EndDialog(hdlg, 222);
478 break;
479
480 default:
481 break;
482 }
483 break;
484
485 case WM_USER:
486 {
487 HWND hok = GetDlgItem(hdlg, IDOK);
488 HWND hedit = GetDlgItem(hdlg, 1000);
489 HWND hfocus = GetFocus();
490 int len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
491
492 if (wparam != 0xdeadbeef)
493 break;
494
495 switch (lparam)
496 {
497 case 0:
498 if ((hfocus == hedit) && len == 0)
499 EndDialog(hdlg, 444);
500 else
501 EndDialog(hdlg, 555);
502 break;
503
504 case 1:
505 if ((hfocus == hok) && len == 0)
506 EndDialog(hdlg, 444);
507 else
508 EndDialog(hdlg, 555);
509 break;
510
511 case 2:
512 if ((hfocus == hedit) && len == 2)
513 EndDialog(hdlg, 444);
514 else
515 EndDialog(hdlg, 555);
516 break;
517
518 default:
519 EndDialog(hdlg, 55);
520 }
521 break;
522 }
523
524 case WM_CLOSE:
525 EndDialog(hdlg, 333);
526 break;
527
528 default:
529 break;
530 }
531
532 return FALSE;
533 }
534
535 static HINSTANCE hinst;
536 static HWND hwndET2;
537 static const char szEditTest2Class[] = "EditTest2Class";
538 static const char szEditTest3Class[] = "EditTest3Class";
539 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
540
541 static HWND create_editcontrol (DWORD style, DWORD exstyle)
542 {
543 HWND handle;
544
545 handle = CreateWindowEx(exstyle,
546 "EDIT",
547 "Test Text",
548 style,
549 10, 10, 300, 300,
550 NULL, NULL, hinst, NULL);
551 assert (handle);
552 if (winetest_interactive)
553 ShowWindow (handle, SW_SHOW);
554 return handle;
555 }
556
557 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
558 {
559 HWND parentWnd;
560 HWND editWnd;
561 RECT rect;
562
563 rect.left = 0;
564 rect.top = 0;
565 rect.right = 300;
566 rect.bottom = 300;
567 assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
568
569 parentWnd = CreateWindowEx(0,
570 szEditTextPositionClass,
571 "Edit Test",
572 WS_OVERLAPPEDWINDOW,
573 CW_USEDEFAULT, CW_USEDEFAULT,
574 rect.right - rect.left, rect.bottom - rect.top,
575 NULL, NULL, hinst, NULL);
576 assert(parentWnd);
577
578 editWnd = CreateWindowEx(exstyle,
579 "EDIT",
580 "Test Text",
581 WS_CHILD | style,
582 0, 0, 300, 300,
583 parentWnd, NULL, hinst, NULL);
584 assert(editWnd);
585 if (winetest_interactive)
586 ShowWindow (parentWnd, SW_SHOW);
587 return editWnd;
588 }
589
590 static void destroy_child_editcontrol (HWND hwndEdit)
591 {
592 if (GetParent(hwndEdit))
593 DestroyWindow(GetParent(hwndEdit));
594 else {
595 trace("Edit control has no parent!\n");
596 DestroyWindow(hwndEdit);
597 }
598 }
599
600 static LONG get_edit_style (HWND hwnd)
601 {
602 return GetWindowLongA( hwnd, GWL_STYLE ) & (
603 ES_LEFT |
604 /* FIXME: not implemented
605 ES_CENTER |
606 ES_RIGHT |
607 ES_OEMCONVERT |
608 */
609 ES_MULTILINE |
610 ES_UPPERCASE |
611 ES_LOWERCASE |
612 ES_PASSWORD |
613 ES_AUTOVSCROLL |
614 ES_AUTOHSCROLL |
615 ES_NOHIDESEL |
616 ES_COMBO |
617 ES_READONLY |
618 ES_WANTRETURN |
619 ES_NUMBER
620 );
621 }
622
623 static void set_client_height(HWND Wnd, unsigned Height)
624 {
625 RECT ClientRect, WindowRect;
626
627 GetWindowRect(Wnd, &WindowRect);
628 GetClientRect(Wnd, &ClientRect);
629 SetWindowPos(Wnd, NULL, 0, 0,
630 WindowRect.right - WindowRect.left,
631 Height + (WindowRect.bottom - WindowRect.top) -
632 (ClientRect.bottom - ClientRect.top),
633 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
634
635 /* Workaround for a bug in Windows' edit control
636 (multi-line mode) */
637 GetWindowRect(Wnd, &WindowRect);
638 SetWindowPos(Wnd, NULL, 0, 0,
639 WindowRect.right - WindowRect.left + 1,
640 WindowRect.bottom - WindowRect.top + 1,
641 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
642 SetWindowPos(Wnd, NULL, 0, 0,
643 WindowRect.right - WindowRect.left,
644 WindowRect.bottom - WindowRect.top,
645 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
646
647 GetClientRect(Wnd, &ClientRect);
648 ok(ClientRect.bottom - ClientRect.top == Height,
649 "The client height should be %ld, but is %ld\n",
650 (long)Height, (long)(ClientRect.bottom - ClientRect.top));
651 }
652
653 static void test_edit_control_1(void)
654 {
655 HWND hwEdit;
656 MSG msMessage;
657 int i;
658 LONG r;
659
660 msMessage.message = WM_KEYDOWN;
661
662 trace("EDIT: Single line\n");
663 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
664 r = get_edit_style(hwEdit);
665 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
666 for (i=0;i<65535;i++)
667 {
668 msMessage.wParam = i;
669 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
670 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
671 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
672 }
673 DestroyWindow (hwEdit);
674
675 trace("EDIT: Single line want returns\n");
676 hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
677 r = get_edit_style(hwEdit);
678 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
679 for (i=0;i<65535;i++)
680 {
681 msMessage.wParam = i;
682 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
683 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
684 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
685 }
686 DestroyWindow (hwEdit);
687
688 trace("EDIT: Multiline line\n");
689 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
690 r = get_edit_style(hwEdit);
691 ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
692 for (i=0;i<65535;i++)
693 {
694 msMessage.wParam = i;
695 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
696 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
697 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
698 }
699 DestroyWindow (hwEdit);
700
701 trace("EDIT: Multi line want returns\n");
702 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
703 r = get_edit_style(hwEdit);
704 ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
705 for (i=0;i<65535;i++)
706 {
707 msMessage.wParam = i;
708 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
709 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
710 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
711 }
712 DestroyWindow (hwEdit);
713 }
714
715 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
716 * selection. This test checks that the first 'select all' doesn't generate
717 * an UPDATE message which can escape and (via a handler) change the
718 * selection, which would cause WM_SETTEXT to break. This old bug
719 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
720 */
721 static void test_edit_control_2(void)
722 {
723 HWND hwndMain;
724 char szLocalString[MAXLEN];
725 LONG r;
726
727 /* Create main and edit windows. */
728 hwndMain = CreateWindow(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
729 0, 0, 200, 200, NULL, NULL, hinst, NULL);
730 assert(hwndMain);
731 if (winetest_interactive)
732 ShowWindow (hwndMain, SW_SHOW);
733
734 hwndET2 = CreateWindow("EDIT", NULL,
735 WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
736 0, 0, 150, 50, /* important this not be 0 size. */
737 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
738 assert(hwndET2);
739 if (winetest_interactive)
740 ShowWindow (hwndET2, SW_SHOW);
741
742 trace("EDIT: SETTEXT atomicity\n");
743 /* Send messages to "type" in the word 'foo'. */
744 r = SendMessage(hwndET2, WM_CHAR, 'f', 1);
745 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
746 r = SendMessage(hwndET2, WM_CHAR, 'o', 1);
747 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
748 r = SendMessage(hwndET2, WM_CHAR, 'o', 1);
749 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
750 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
751 GetWindowText(hwndET2, szLocalString, MAXLEN);
752 ok(lstrcmp(szLocalString, "bar")==0,
753 "Wrong contents of edit: %s\n", szLocalString);
754
755 /* OK, done! */
756 DestroyWindow (hwndET2);
757 DestroyWindow (hwndMain);
758 }
759
760 static void ET2_check_change(void) {
761 char szLocalString[MAXLEN];
762 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
763 GetWindowText(hwndET2, szLocalString, MAXLEN);
764 if (lstrcmp(szLocalString, "foo")==0) {
765 lstrcpy(szLocalString, "bar");
766 SendMessage(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
767 }
768 /* always leave the cursor at the end. */
769 SendMessage(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
770 }
771 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
772 {
773 if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
774 ET2_check_change();
775 }
776 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
777 {
778 switch (iMsg) {
779 case WM_COMMAND:
780 ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
781 break;
782 }
783 return DefWindowProc(hwnd, iMsg, wParam, lParam);
784 }
785
786 static void zero_notify(void)
787 {
788 notifications.en_change = 0;
789 notifications.en_maxtext = 0;
790 notifications.en_update = 0;
791 }
792
793 #define test_notify(enchange, enmaxtext, enupdate) \
794 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
795 "got %d\n", enchange, notifications.en_change); \
796 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
797 "got %d\n", enmaxtext, notifications.en_maxtext); \
798 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
799 "got %d\n", enupdate, notifications.en_update)
800
801
802 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
803 {
804 switch (msg) {
805 case WM_COMMAND:
806 switch (HIWORD(wParam)) {
807 case EN_MAXTEXT:
808 notifications.en_maxtext++;
809 break;
810 case EN_UPDATE:
811 notifications.en_update++;
812 break;
813 case EN_CHANGE:
814 notifications.en_change++;
815 break;
816 }
817 break;
818 }
819 return DefWindowProcA(hWnd, msg, wParam, lParam);
820 }
821
822 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
823 * to these messages.
824 */
825 static void test_edit_control_3(void)
826 {
827 HWND hWnd;
828 HWND hParent;
829 int len;
830 static const char *str = "this is a long string.";
831 static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string.";
832
833 trace("EDIT: Test notifications\n");
834
835 hParent = CreateWindowExA(0,
836 szEditTest3Class,
837 NULL,
838 0,
839 CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
840 NULL, NULL, NULL, NULL);
841 assert(hParent);
842
843 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
844 hWnd = CreateWindowExA(0,
845 "EDIT",
846 NULL,
847 0,
848 10, 10, 50, 50,
849 hParent, NULL, NULL, NULL);
850 assert(hWnd);
851
852 zero_notify();
853 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
854 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
855 ok(lstrlenA(str) > len, "text should have been truncated\n");
856 test_notify(1, 1, 1);
857
858 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
859 zero_notify();
860 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
861 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
862 ok(1 == len, "wrong text length, expected 1, got %d\n", len);
863 test_notify(1, 0, 1);
864
865 zero_notify();
866 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
867 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
868 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
869 test_notify(1, 0, 1);
870
871 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
872
873 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
874 zero_notify();
875 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
876 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
877 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
878 test_notify(1, 1, 1);
879
880 zero_notify();
881 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
882 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
883 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
884 test_notify(1, 0, 1);
885
886 DestroyWindow(hWnd);
887
888 trace("EDIT: Single line, ES_AUTOHSCROLL\n");
889 hWnd = CreateWindowExA(0,
890 "EDIT",
891 NULL,
892 ES_AUTOHSCROLL,
893 10, 10, 50, 50,
894 hParent, NULL, NULL, NULL);
895 assert(hWnd);
896
897 zero_notify();
898 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
899 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
900 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
901 test_notify(1, 0, 1);
902
903 zero_notify();
904 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
905 len = SendMessageA(hWnd,