user32: Fix case where EM_SCROLL with page down results in trying to scroll up past...
[wine] / dlls / user32 / tests / edit.c
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_EDITTESTDBUTTON 0x123
32 #define ID_EDITTEST2 99
33 #define MAXLEN 200
34
35 struct edit_notify {
36     int en_change, en_maxtext, en_update;
37 };
38
39 static struct edit_notify notifications;
40
41 static INT_PTR CALLBACK multi_edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
42 {
43     static int num_ok_commands = 0;
44     switch (msg)
45     {
46         case WM_INITDIALOG:
47         {
48             HWND hedit = GetDlgItem(hdlg, 1000);
49             SetFocus(hedit);
50             switch (lparam)
51             {
52                 /* test cases related to bug 12319 */
53                 case 0:
54                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
55                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
56                     break;
57                 case 1:
58                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
59                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
60                     break;
61                 case 2:
62                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
63                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
64                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
65                     break;
66
67                 /* test cases for pressing enter */
68                 case 3:
69                     num_ok_commands = 0;
70                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
71                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
72                     break;
73
74                 default:
75                     break;
76             }
77             break;
78         }
79
80         case WM_COMMAND:
81             if (HIWORD(wparam) != BN_CLICKED)
82                 break;
83
84             switch (LOWORD(wparam))
85             {
86                 case IDOK:
87                     num_ok_commands++;
88                     break;
89
90                 default:
91                     break;
92             }
93             break;
94
95         case WM_USER:
96         {
97             HWND hfocus = GetFocus();
98             HWND hedit = GetDlgItem(hdlg, 1000);
99             HWND hedit2 = GetDlgItem(hdlg, 1001);
100             HWND hedit3 = GetDlgItem(hdlg, 1002);
101
102             if (wparam != 0xdeadbeef)
103                 break;
104
105             switch (lparam)
106             {
107                 case 0:
108                     if (hfocus == hedit)
109                         EndDialog(hdlg, 1111);
110                     else if (hfocus == hedit2)
111                         EndDialog(hdlg, 2222);
112                     else if (hfocus == hedit3)
113                         EndDialog(hdlg, 3333);
114                     else
115                         EndDialog(hdlg, 4444);
116                     break;
117                 case 1:
118                     if ((hfocus == hedit) && (num_ok_commands == 0))
119                         EndDialog(hdlg, 11);
120                     else
121                         EndDialog(hdlg, 22);
122                     break;
123                 default:
124                     EndDialog(hdlg, 5555);
125             }
126             break;
127         }
128
129         case WM_CLOSE:
130             EndDialog(hdlg, 333);
131             break;
132
133         default:
134             break;
135     }
136
137     return FALSE;
138 }
139
140 static INT_PTR CALLBACK edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
141 {
142     switch (msg)
143     {
144         case WM_INITDIALOG:
145         {
146             HWND hedit = GetDlgItem(hdlg, 1000);
147             SetFocus(hedit);
148             switch (lparam)
149             {
150                 /* from bug 11841 */
151                 case 0:
152                     PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
153                     break;
154                 case 1:
155                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
156                     break;
157                 case 2:
158                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
159                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
160                     break;
161
162                 /* more test cases for WM_CHAR */
163                 case 3:
164                     PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
165                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
166                     break;
167                 case 4:
168                     PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
169                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
170                     break;
171                 case 5:
172                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
173                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
174                     break;
175
176                 /* more test cases for WM_KEYDOWN + WM_CHAR */
177                 case 6:
178                     PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
179                     PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
180                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
181                     break;
182                 case 7:
183                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
184                     PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
185                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
186                     break;
187                 case 8:
188                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
189                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
190                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
191                     break;
192
193                 /* multiple tab tests */
194                 case 9:
195                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
196                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
197                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
198                     break;
199                 case 10:
200                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
201                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
202                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
203                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
204                     break;
205
206                 default:
207                     break;
208             }
209             break;
210         }
211
212         case WM_COMMAND:
213             if (HIWORD(wparam) != BN_CLICKED)
214                 break;
215
216             switch (LOWORD(wparam))
217             {
218                 case IDOK:
219                     EndDialog(hdlg, 111);
220                     break;
221
222                 case IDCANCEL:
223                     EndDialog(hdlg, 222);
224                     break;
225
226                 default:
227                     break;
228             }
229             break;
230
231         case WM_USER:
232         {
233             int len;
234             HWND hok = GetDlgItem(hdlg, IDOK);
235             HWND hcancel = GetDlgItem(hdlg, IDCANCEL);
236             HWND hedit = GetDlgItem(hdlg, 1000);
237             HWND hfocus = GetFocus();
238
239             if (wparam != 0xdeadbeef)
240                 break;
241
242             switch (lparam)
243             {
244                 case 0:
245                     len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
246                     if (len == 0)
247                         EndDialog(hdlg, 444);
248                     else
249                         EndDialog(hdlg, 555);
250                     break;
251
252                 case 1:
253                     len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
254                     if ((hfocus == hok) && len == 0)
255                         EndDialog(hdlg, 444);
256                     else
257                         EndDialog(hdlg, 555);
258                     break;
259
260                 case 2:
261                     if (hfocus == hok)
262                         EndDialog(hdlg, 11);
263                     else if (hfocus == hcancel)
264                         EndDialog(hdlg, 22);
265                     else if (hfocus == hedit)
266                         EndDialog(hdlg, 33);
267                     else
268                         EndDialog(hdlg, 44);
269                     break;
270
271                 default:
272                     EndDialog(hdlg, 555);
273             }
274             break;
275         }
276
277         case WM_CLOSE:
278             EndDialog(hdlg, 333);
279             break;
280
281         default:
282             break;
283     }
284
285     return FALSE;
286 }
287
288 static INT_PTR CALLBACK edit_singleline_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
289 {
290     switch (msg)
291     {
292         case WM_INITDIALOG:
293         {
294             HWND hedit = GetDlgItem(hdlg, 1000);
295             SetFocus(hedit);
296             switch (lparam)
297             {
298                 /* test cases for WM_KEYDOWN */
299                 case 0:
300                     PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
301                     break;
302                 case 1:
303                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
304                     break;
305                 case 2:
306                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
307                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
308                     break;
309
310                 /* test cases for WM_CHAR */
311                 case 3:
312                     PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
313                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
314                     break;
315                 case 4:
316                     PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
317                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
318                     break;
319                 case 5:
320                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
321                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
322                     break;
323
324                 /* test cases for WM_KEYDOWN + WM_CHAR */
325                 case 6:
326                     PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
327                     PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
328                     break;
329                 case 7:
330                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
331                     PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
332                     break;
333                 case 8:
334                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
335                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
336                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
337                     break;
338
339                 default:
340                     break;
341             }
342             break;
343         }
344
345         case WM_COMMAND:
346             if (HIWORD(wparam) != BN_CLICKED)
347                 break;
348
349             switch (LOWORD(wparam))
350             {
351                 case IDOK:
352                     EndDialog(hdlg, 111);
353                     break;
354
355                 case IDCANCEL:
356                     EndDialog(hdlg, 222);
357                     break;
358
359                 default:
360                     break;
361             }
362             break;
363
364         case WM_USER:
365         {
366             HWND hok = GetDlgItem(hdlg, IDOK);
367             HWND hedit = GetDlgItem(hdlg, 1000);
368             HWND hfocus = GetFocus();
369             int len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
370
371             if (wparam != 0xdeadbeef)
372                 break;
373
374             switch (lparam)
375             {
376                 case 0:
377                     if ((hfocus == hedit) && len == 0)
378                         EndDialog(hdlg, 444);
379                     else
380                         EndDialog(hdlg, 555);
381                     break;
382
383                 case 1:
384                     if ((hfocus == hok) && len == 0)
385                         EndDialog(hdlg, 444);
386                     else
387                         EndDialog(hdlg, 555);
388                     break;
389
390                 default:
391                     EndDialog(hdlg, 55);
392             }
393             break;
394         }
395
396         case WM_CLOSE:
397             EndDialog(hdlg, 333);
398             break;
399
400         default:
401             break;
402     }
403
404     return FALSE;
405 }
406
407 static INT_PTR CALLBACK edit_wantreturn_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
408 {
409     switch (msg)
410     {
411         case WM_INITDIALOG:
412         {
413             HWND hedit = GetDlgItem(hdlg, 1000);
414             SetFocus(hedit);
415             switch (lparam)
416             {
417                 /* test cases for WM_KEYDOWN */
418                 case 0:
419                     PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
420                     break;
421                 case 1:
422                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
423                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
424                     break;
425                 case 2:
426                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
427                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
428                     break;
429
430                 /* test cases for WM_CHAR */
431                 case 3:
432                     PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
433                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
434                     break;
435                 case 4:
436                     PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
437                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
438                     break;
439                 case 5:
440                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
441                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
442                     break;
443
444                 /* test cases for WM_KEYDOWN + WM_CHAR */
445                 case 6:
446                     PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
447                     PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
448                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
449                     break;
450                 case 7:
451                     PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
452                     PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
453                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
454                     break;
455                 case 8:
456                     PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
457                     PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
458                     PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
459                     break;
460
461                 default:
462                     break;
463             }
464             break;
465         }
466
467         case WM_COMMAND:
468             if (HIWORD(wparam) != BN_CLICKED)
469                 break;
470
471             switch (LOWORD(wparam))
472             {
473                 case IDOK:
474                     EndDialog(hdlg, 111);
475                     break;
476
477                 case IDCANCEL:
478                     EndDialog(hdlg, 222);
479                     break;
480
481                 default:
482                     break;
483             }
484             break;
485
486         case WM_USER:
487         {
488             HWND hok = GetDlgItem(hdlg, IDOK);
489             HWND hedit = GetDlgItem(hdlg, 1000);
490             HWND hfocus = GetFocus();
491             int len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
492
493             if (wparam != 0xdeadbeef)
494                 break;
495
496             switch (lparam)
497             {
498                 case 0:
499                     if ((hfocus == hedit) && len == 0)
500                         EndDialog(hdlg, 444);
501                     else
502                         EndDialog(hdlg, 555);
503                     break;
504
505                 case 1:
506                     if ((hfocus == hok) && len == 0)
507                         EndDialog(hdlg, 444);
508                     else
509                         EndDialog(hdlg, 555);
510                     break;
511
512                 case 2:
513                     if ((hfocus == hedit) && len == 2)
514                         EndDialog(hdlg, 444);
515                     else
516                         EndDialog(hdlg, 555);
517                     break;
518
519                 default:
520                     EndDialog(hdlg, 55);
521             }
522             break;
523         }
524
525         case WM_CLOSE:
526             EndDialog(hdlg, 333);
527             break;
528
529         default:
530             break;
531     }
532
533     return FALSE;
534 }
535
536 static HINSTANCE hinst;
537 static HWND hwndET2;
538 static const char szEditTest2Class[] = "EditTest2Class";
539 static const char szEditTest3Class[] = "EditTest3Class";
540 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
541
542 static HWND create_editcontrol (DWORD style, DWORD exstyle)
543 {
544     HWND handle;
545
546     handle = CreateWindowEx(exstyle,
547                           "EDIT",
548                           "Test Text",
549                           style,
550                           10, 10, 300, 300,
551                           NULL, NULL, hinst, NULL);
552     assert (handle);
553     if (winetest_interactive)
554         ShowWindow (handle, SW_SHOW);
555     return handle;
556 }
557
558 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
559 {
560     HWND parentWnd;
561     HWND editWnd;
562     RECT rect;
563     
564     rect.left = 0;
565     rect.top = 0;
566     rect.right = 300;
567     rect.bottom = 300;
568     assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
569     
570     parentWnd = CreateWindowEx(0,
571                             szEditTextPositionClass,
572                             "Edit Test",
573                             WS_OVERLAPPEDWINDOW,
574                             CW_USEDEFAULT, CW_USEDEFAULT,
575                             rect.right - rect.left, rect.bottom - rect.top,
576                             NULL, NULL, hinst, NULL);
577     assert(parentWnd);
578
579     editWnd = CreateWindowEx(exstyle,
580                             "EDIT",
581                             "Test Text",
582                             WS_CHILD | style,
583                             0, 0, 300, 300,
584                             parentWnd, NULL, hinst, NULL);
585     assert(editWnd);
586     if (winetest_interactive)
587         ShowWindow (parentWnd, SW_SHOW);
588     return editWnd;
589 }
590
591 static void destroy_child_editcontrol (HWND hwndEdit)
592 {
593     if (GetParent(hwndEdit))
594         DestroyWindow(GetParent(hwndEdit));
595     else {
596         trace("Edit control has no parent!\n");
597         DestroyWindow(hwndEdit);
598     }
599 }
600
601 static LONG get_edit_style (HWND hwnd)
602 {
603     return GetWindowLongA( hwnd, GWL_STYLE ) & (
604         ES_LEFT |
605 /* FIXME: not implemented
606         ES_CENTER |
607         ES_RIGHT |
608         ES_OEMCONVERT |
609 */
610         ES_MULTILINE |
611         ES_UPPERCASE |
612         ES_LOWERCASE |
613         ES_PASSWORD |
614         ES_AUTOVSCROLL |
615         ES_AUTOHSCROLL |
616         ES_NOHIDESEL |
617         ES_COMBO |
618         ES_READONLY |
619         ES_WANTRETURN |
620         ES_NUMBER
621         );
622 }
623
624 static void set_client_height(HWND Wnd, unsigned Height)
625 {
626     RECT ClientRect, WindowRect;
627
628     GetWindowRect(Wnd, &WindowRect);
629     GetClientRect(Wnd, &ClientRect);
630     SetWindowPos(Wnd, NULL, 0, 0,
631                  WindowRect.right - WindowRect.left,
632                  Height + (WindowRect.bottom - WindowRect.top) -
633                  (ClientRect.bottom - ClientRect.top),
634                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
635
636     /* Workaround for a bug in Windows' edit control
637        (multi-line mode) */
638     GetWindowRect(Wnd, &WindowRect);             
639     SetWindowPos(Wnd, NULL, 0, 0,
640                  WindowRect.right - WindowRect.left + 1,
641                  WindowRect.bottom - WindowRect.top + 1,
642                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
643     SetWindowPos(Wnd, NULL, 0, 0,
644                  WindowRect.right - WindowRect.left,
645                  WindowRect.bottom - WindowRect.top,
646                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
647
648     GetClientRect(Wnd, &ClientRect);
649     ok(ClientRect.bottom - ClientRect.top == Height,
650         "The client height should be %d, but is %d\n",
651         Height, ClientRect.bottom - ClientRect.top);
652 }
653
654 static void test_edit_control_1(void)
655 {
656     HWND hwEdit;
657     MSG msMessage;
658     int i;
659     LONG r;
660
661     msMessage.message = WM_KEYDOWN;
662
663     trace("EDIT: Single line\n");
664     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
665     r = get_edit_style(hwEdit);
666     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
667     for (i=0;i<65535;i++)
668     {
669         msMessage.wParam = i;
670         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
671         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
672             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
673     }
674     DestroyWindow (hwEdit);
675
676     trace("EDIT: Single line want returns\n");
677     hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
678     r = get_edit_style(hwEdit);
679     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
680     for (i=0;i<65535;i++)
681     {
682         msMessage.wParam = i;
683         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
684         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
685             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
686     }
687     DestroyWindow (hwEdit);
688
689     trace("EDIT: Multiline line\n");
690     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
691     r = get_edit_style(hwEdit);
692     ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
693     for (i=0;i<65535;i++)
694     {
695         msMessage.wParam = i;
696         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
697         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
698             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
699     }
700     DestroyWindow (hwEdit);
701
702     trace("EDIT: Multi line want returns\n");
703     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
704     r = get_edit_style(hwEdit);
705     ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
706     for (i=0;i<65535;i++)
707     {
708         msMessage.wParam = i;
709         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
710         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
711             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
712     }
713     DestroyWindow (hwEdit);
714 }
715
716 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
717  * selection.  This test checks that the first 'select all' doesn't generate
718  * an UPDATE message which can escape and (via a handler) change the
719  * selection, which would cause WM_SETTEXT to break.  This old bug
720  * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
721  */
722 static void test_edit_control_2(void)
723 {
724     HWND hwndMain;
725     char szLocalString[MAXLEN];
726     LONG r;
727
728     /* Create main and edit windows. */
729     hwndMain = CreateWindow(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
730                             0, 0, 200, 200, NULL, NULL, hinst, NULL);
731     assert(hwndMain);
732     if (winetest_interactive)
733         ShowWindow (hwndMain, SW_SHOW);
734
735     hwndET2 = CreateWindow("EDIT", NULL,
736                            WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
737                            0, 0, 150, 50, /* important this not be 0 size. */
738                            hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
739     assert(hwndET2);
740     if (winetest_interactive)
741         ShowWindow (hwndET2, SW_SHOW);
742
743     trace("EDIT: SETTEXT atomicity\n");
744     /* Send messages to "type" in the word 'foo'. */
745     r = SendMessage(hwndET2, WM_CHAR, 'f', 1);
746     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
747     r = SendMessage(hwndET2, WM_CHAR, 'o', 1);
748     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
749     r = SendMessage(hwndET2, WM_CHAR, 'o', 1);
750     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
751     /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
752     GetWindowText(hwndET2, szLocalString, MAXLEN);
753     ok(lstrcmp(szLocalString, "bar")==0,
754        "Wrong contents of edit: %s\n", szLocalString);
755
756     /* OK, done! */
757     DestroyWindow (hwndET2);
758     DestroyWindow (hwndMain);
759 }
760
761 static void ET2_check_change(void) {
762    char szLocalString[MAXLEN];
763    /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
764    GetWindowText(hwndET2, szLocalString, MAXLEN);
765    if (lstrcmp(szLocalString, "foo")==0) {
766        lstrcpy(szLocalString, "bar");
767        SendMessage(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
768    }
769    /* always leave the cursor at the end. */
770    SendMessage(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
771 }
772 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
773 {
774     if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
775         ET2_check_change();
776 }
777 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
778 {
779     switch (iMsg) {
780     case WM_COMMAND:
781         ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
782         break;
783     }
784     return DefWindowProc(hwnd, iMsg, wParam, lParam);
785 }
786
787 static void zero_notify(void)
788 {
789     notifications.en_change = 0;
790     notifications.en_maxtext = 0;
791     notifications.en_update = 0;
792 }
793
794 #define test_notify(enchange, enmaxtext, enupdate) \
795     ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
796     "got %d\n", enchange, notifications.en_change); \
797     ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
798     "got %d\n", enmaxtext, notifications.en_maxtext); \
799     ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
800     "got %d\n", enupdate, notifications.en_update)
801
802
803 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
804 {
805     switch (msg) {
806         case WM_COMMAND:
807             switch (HIWORD(wParam)) {
808                 case EN_MAXTEXT:
809                     notifications.en_maxtext++;
810                     break;
811                 case EN_UPDATE:
812                     notifications.en_update++;
813                     break;
814                 case EN_CHANGE:
815                     notifications.en_change++;
816                     break;
817             }
818             break;
819     }
820     return DefWindowProcA(hWnd, msg, wParam, lParam);
821 }
822
823 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
824  * to these messages.
825  */
826 static void test_edit_control_3(void)
827 {
828     HWND hWnd;
829     HWND hParent;
830     int len;
831     static const char *str = "this is a long string.";
832     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.";
833
834     trace("EDIT: Test notifications\n");
835
836     hParent = CreateWindowExA(0,
837               szEditTest3Class,
838               NULL,
839               0,
840               CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
841               NULL, NULL, NULL, NULL);
842     assert(hParent);
843
844     trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
845     hWnd = CreateWindowExA(0,
846               "EDIT",
847               NULL,
848               0,
849               10, 10, 50, 50,
850               hParent, NULL, NULL, NULL);
851     assert(hWnd);
852
853     zero_notify();
854     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
855     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
856     ok(lstrlenA(str) > len, "text should have been truncated\n");
857     test_notify(1, 1, 1);
858
859     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
860     zero_notify();
861     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
862     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
863     ok(1 == len, "wrong text length, expected 1, got %d\n", len);
864     test_notify(1, 0, 1);
865
866     zero_notify();
867     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
868     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
869     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
870     test_notify(1, 0, 1);
871
872     len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
873     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
874     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
875     SendMessage(hParent, WM_SETFOCUS, 0, (LPARAM)hWnd);
876     len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
877     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
878     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
879
880     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
881
882     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
883     zero_notify();
884     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
885     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
886     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
887     test_notify(1, 1, 1);
888
889     zero_notify();
890     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
891     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
892     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
893     test_notify(1, 0, 1);
894
895     DestroyWindow(hWnd);
896
897     trace("EDIT: Single line, ES_AUTOHSCROLL\n");
898     hWnd = CreateWindowExA(0,
899               "EDIT",
900               NULL,
901               ES_AUTOHSCROLL,
902               10, 10, 50, 50,
903               hParent, NULL, NULL, NULL);
904     assert(hWnd);
905
906     zero_notify();
907     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
908     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
909     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
910     test_notify(1, 0, 1);
911
912     zero_notify();
913     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
914     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
915     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
916     test_notify(1, 0, 1);
917
918     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
919
920     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
921     zero_notify();
922     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
923     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
924     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
925     test_notify(1, 1, 1);
926
927     zero_notify();
928     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
929     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
930     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
931     test_notify(1, 0, 1);
932
933     DestroyWindow(hWnd);
934
935     trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
936     hWnd = CreateWindowExA(0,
937               "EDIT",
938               NULL,
939               ES_MULTILINE,
940               10, 10, 50, 50,
941               hParent, NULL, NULL, NULL);
942     assert(hWnd);
943
944     zero_notify();
945     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
946     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
947     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
948     test_notify(1, 1, 1);
949
950     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
951     zero_notify();
952     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
953     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
954     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
955     test_notify(1, 0, 1);
956
957     zero_notify();
958     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
959     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
960     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
961     test_notify(0, 0, 0);
962
963     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
964
965     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
966     zero_notify();
967     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
968     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
969     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
970     test_notify(1, 1, 1);
971
972     zero_notify();
973     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
974     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
975     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
976     test_notify(0, 0, 0);
977
978     DestroyWindow(hWnd);
979
980     trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
981     hWnd = CreateWindowExA(0,
982               "EDIT",
983               NULL,
984               ES_MULTILINE | ES_AUTOHSCROLL,
985               10, 10, 50, 50,
986               hParent, NULL, NULL, NULL);
987     assert(hWnd);
988
989     zero_notify();
990     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
991     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
992     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
993     test_notify(1, 1, 1);
994
995     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
996     zero_notify();
997     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
998     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
999     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1000     test_notify(1, 0, 1);
1001
1002     zero_notify();
1003     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1004     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1005     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1006     test_notify(0, 0, 0);
1007
1008     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1009
1010     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1011     zero_notify();
1012     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1013     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1014     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1015     test_notify(1, 1, 1);
1016
1017     zero_notify();
1018     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1019     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1020     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1021     test_notify(0, 0, 0);
1022
1023     DestroyWindow(hWnd);
1024
1025     trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1026     hWnd = CreateWindowExA(0,
1027               "EDIT",
1028               NULL,
1029               ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1030               10, 10, 50, 50,
1031               hParent, NULL, NULL, NULL);
1032     assert(hWnd);
1033
1034     zero_notify();
1035     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1036     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1037     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1038     test_notify(1, 0, 1);
1039
1040     zero_notify();
1041     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1042     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1043     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1044     test_notify(0, 0, 0);
1045
1046     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1047
1048     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1049     zero_notify();
1050     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1051     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1052     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1053     test_notify(1, 1, 1);
1054
1055     zero_notify();
1056     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1057     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1058     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1059     test_notify(0, 0, 0);
1060
1061     DestroyWindow(hWnd);
1062 }
1063
1064 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
1065  */
1066 static void test_edit_control_4(void)
1067 {
1068     HWND hwEdit;
1069     int lo, hi, mid;
1070     int ret;
1071     int i;
1072
1073     trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
1074     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1075     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1076     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1077     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1078     mid = lo + (hi - lo) / 2;
1079
1080     for (i = lo; i < mid; i++) {
1081        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1082        ok(0 == ret, "expected 0 got %d\n", ret);
1083     }
1084     for (i = mid; i <= hi; i++) {
1085        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1086        ok(1 == ret, "expected 1 got %d\n", ret);
1087     }
1088     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1089     ok(-1 == ret, "expected -1 got %d\n", ret);
1090     DestroyWindow(hwEdit);
1091
1092     hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1093     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1094     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1095     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1096     mid = lo + (hi - lo) / 2;
1097
1098     for (i = lo; i < mid; i++) {
1099        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1100        ok(0 == ret, "expected 0 got %d\n", ret);
1101     }
1102     for (i = mid; i <= hi; i++) {
1103        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1104        ok(1 == ret, "expected 1 got %d\n", ret);
1105     }
1106     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1107     ok(-1 == ret, "expected -1 got %d\n", ret);
1108     DestroyWindow(hwEdit);
1109
1110     hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1111     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1112     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1113     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1114     mid = lo + (hi - lo) / 2;
1115
1116     for (i = lo; i < mid; i++) {
1117        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1118        ok(0 == ret, "expected 0 got %d\n", ret);
1119     }
1120     for (i = mid; i <= hi; i++) {
1121        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1122        ok(1 == ret, "expected 1 got %d\n", ret);
1123     }
1124     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1125     ok(-1 == ret, "expected -1 got %d\n", ret);
1126     DestroyWindow(hwEdit);
1127
1128     hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1129     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1130     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1131     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1132     mid = lo + (hi - lo) / 2 +1;
1133
1134     for (i = lo; i < mid; i++) {
1135        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1136        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1137     }
1138     for (i = mid; i <= hi; i++) {
1139        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1140        ok(1 == ret, "expected 1 got %d\n", ret);
1141     }
1142     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1143     ok(-1 == ret, "expected -1 got %d\n", ret);
1144     DestroyWindow(hwEdit);
1145
1146     hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1147     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1148     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1149     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1150     mid = lo + (hi - lo) / 2 +1;
1151
1152     for (i = lo; i < mid; i++) {
1153        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1154        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1155     }
1156     for (i = mid; i <= hi; i++) {
1157        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1158        ok(1 == ret, "expected 1 got %d\n", ret);
1159     }
1160     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1161     ok(-1 == ret, "expected -1 got %d\n", ret);
1162     DestroyWindow(hwEdit);
1163
1164     hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1165     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1166     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1167     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1168     mid = lo + (hi - lo) / 2 +1;
1169
1170     for (i = lo; i < mid; i++) {
1171        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1172        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1173     }
1174     for (i = mid; i <= hi; i++) {
1175        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1176        ok(1 == ret, "expected 1 got %d\n", ret);
1177     }
1178     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1179     ok(-1 == ret, "expected -1 got %d\n", ret);
1180     DestroyWindow(hwEdit);
1181 }
1182
1183 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1184  * truncates text that doesn't fit.
1185  */
1186 static void test_edit_control_5(void)
1187 {
1188     static const char *str = "test\r\ntest";
1189     HWND parentWnd;
1190     HWND hWnd;
1191     int len;
1192     RECT rc1 = { 10, 10, 11, 11};
1193     RECT rc;
1194
1195     /* first show that a non-child won't do for this test */
1196     hWnd = CreateWindowEx(0,
1197               "EDIT",
1198               str,
1199               0,
1200               10, 10, 1, 1,
1201               NULL, NULL, NULL, NULL);
1202     assert(hWnd);
1203     /* size of non-child edit control is (much) bigger than requested */
1204     GetWindowRect( hWnd, &rc);
1205     ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1206             rc.right - rc.left);
1207     DestroyWindow(hWnd);
1208     /* so create a parent, and give it edit controls children to test with */
1209     parentWnd = CreateWindowEx(0,
1210                             szEditTextPositionClass,
1211                             "Edit Test", WS_VISIBLE |
1212                             WS_OVERLAPPEDWINDOW,
1213                             CW_USEDEFAULT, CW_USEDEFAULT,
1214                             250, 250,
1215                             NULL, NULL, hinst, NULL);
1216     assert(parentWnd);
1217     ShowWindow( parentWnd, SW_SHOW);
1218     /* single line */
1219     hWnd = CreateWindowEx(0,
1220               "EDIT",
1221               str, WS_VISIBLE | WS_BORDER |
1222               WS_CHILD,
1223               rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1224               parentWnd, NULL, NULL, NULL);
1225     assert(hWnd);
1226     GetClientRect( hWnd, &rc);
1227     ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1228             "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1229             rc.left, rc.top, rc.right, rc.bottom);
1230     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1231     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1232     DestroyWindow(hWnd);
1233     /* multi line */
1234     hWnd = CreateWindowEx(0,
1235               "EDIT",
1236               str,
1237               WS_CHILD | ES_MULTILINE,
1238               rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1239               parentWnd, NULL, NULL, NULL);
1240     assert(hWnd);
1241     GetClientRect( hWnd, &rc);
1242     ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1243             "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1244             rc.left, rc.top, rc.right, rc.bottom);
1245     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1246     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1247     DestroyWindow(hWnd);
1248 }
1249
1250 /* Test WM_GETTEXT processing
1251  * after destroy messages
1252  */
1253 static void test_edit_control_6(void)
1254 {
1255     static const char *str = "test\r\ntest";
1256     char buf[MAXLEN];
1257     LONG ret;
1258     HWND hWnd;
1259
1260     hWnd = CreateWindowEx(0,
1261               "EDIT",
1262               "Test",
1263               0,
1264               10, 10, 1, 1,
1265               NULL, NULL, hinst, NULL);
1266     assert(hWnd);
1267
1268     ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1269     ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1270     ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1271     ok(ret == lstrlen(str), "Expected %s, got len %d\n", str, ret);
1272     ok(!lstrcmp(buf, str), "Expected %s, got %s\n", str, buf);
1273     buf[0] = 0;
1274     ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1275     ok(ret == 0, "Expected 0, got %d\n", ret);
1276     ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1277     ok(ret == lstrlen(str), "Expected %s, got len %d\n", str, ret);
1278     ok(!lstrcmp(buf, str), "Expected %s, got %s\n", str, buf);
1279     buf[0] = 0;
1280     ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1281     ok(ret == 0, "Expected 0, got %d\n", ret);
1282     ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1283     ok(ret == 0, "Expected 0, got len %d\n", ret);
1284     ok(!lstrcmp(buf, ""), "Expected empty string, got %s\n", buf);
1285
1286     DestroyWindow(hWnd);
1287 }
1288
1289 static void test_edit_control_limittext(void)
1290 {
1291     HWND hwEdit;
1292     DWORD r;
1293
1294     /* Test default limit for single-line control */
1295     trace("EDIT: buffer limit for single-line\n");
1296     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1297     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1298     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1299     SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
1300     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1301     /* Win9x+ME: 32766; WinNT: 2147483646UL */
1302     ok( (r == 32766) || (r == 2147483646UL),
1303         "got limit %u (expected 32766 or 2147483646)\n", r);
1304     DestroyWindow(hwEdit);
1305
1306     /* Test default limit for multi-line control */
1307     trace("EDIT: buffer limit for multi-line\n");
1308     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1309     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1310     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1311     SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
1312     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1313     /* Win9x+ME: 65535; WinNT: 4294967295UL */
1314     ok( (r == 65535) || (r == 4294967295UL),
1315         "got limit %u (expected 65535 or 4294967295)\n", r);
1316     DestroyWindow(hwEdit);
1317 }
1318
1319 /* Test EM_SCROLL */
1320 static void test_edit_control_scroll(void)
1321 {
1322     static const char *single_line_str = "a";
1323     static const char *multiline_str = "Test\r\nText";
1324     HWND hwEdit;
1325     LONG ret;
1326
1327     /* Check the return value when EM_SCROLL doesn't scroll
1328      * anything. Should not return true unless any lines were actually
1329      * scrolled. */
1330     hwEdit = CreateWindow(
1331               "EDIT",
1332               single_line_str,
1333               WS_VSCROLL | ES_MULTILINE,
1334               1, 1, 100, 100,
1335               NULL, NULL, hinst, NULL);
1336
1337     assert(hwEdit);
1338
1339     ret = SendMessage(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1340     ok(!ret, "Returned %x, expected 0.\n", ret);
1341
1342     ret = SendMessage(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1343     ok(!ret, "Returned %x, expected 0.\n", ret);
1344
1345     ret = SendMessage(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1346     ok(!ret, "Returned %x, expected 0.\n", ret);
1347
1348     ret = SendMessage(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1349     ok(!ret, "Returned %x, expected 0.\n", ret);
1350
1351     DestroyWindow (hwEdit);
1352
1353     /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1354        should not cause EM_SCROLL to return a negative value of
1355        scrolled lines that would put us "before" the beginning. */
1356     hwEdit = CreateWindow(
1357                 "EDIT",
1358                 multiline_str,
1359                 WS_VSCROLL | ES_MULTILINE,
1360                 0, 0, 100, 100,
1361                 NULL, NULL, hinst, NULL);
1362     assert(hwEdit);
1363
1364     ret = SendMessage(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1365     ok(!ret, "Returned %x, expected 0.\n", ret);
1366
1367     DestroyWindow (hwEdit);
1368 }
1369
1370 static void test_margins(void)
1371 {
1372     HWND hwEdit;
1373     RECT old_rect, new_rect;
1374     INT old_left_margin, old_right_margin;
1375     DWORD old_margins, new_margins;
1376
1377     hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1378     
1379     old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1380     old_left_margin = LOWORD(old_margins);
1381     old_right_margin = HIWORD(old_margins);
1382     
1383     /* Check if setting the margins works */
1384     
1385     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1386     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1387     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1388     ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1389     
1390     SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1391     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1392     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1393     ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1394     
1395     
1396     /* The size of the rectangle must decrease if we increase the margin */
1397     
1398     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1399     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1400     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1401     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1402     ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1403     ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1404     ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1405     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1406     
1407     
1408     /* If we set the margin to same value as the current margin,
1409        the rectangle must not change */
1410     
1411     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1412     old_rect.left = 1;
1413     old_rect.right = 99;
1414     old_rect.top = 1;
1415     old_rect.bottom = 99;
1416     SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);    
1417     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1418     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1419     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1420     ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
1421     ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
1422     ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
1423     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
1424
1425     DestroyWindow (hwEdit);
1426 }
1427
1428 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
1429 {
1430     return 0;
1431 }
1432
1433 static void test_margins_font_change(void)
1434 {
1435     HWND hwEdit;
1436     DWORD margins, font_margins;
1437     LOGFONT lf;
1438     HFONT hfont, hfont2;
1439     HDC hdc = GetDC(0);
1440
1441     if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
1442     {
1443         trace("Arial not found - skipping font change margin tests\n");
1444         ReleaseDC(0, hdc);
1445         return;
1446     }
1447     ReleaseDC(0, hdc);
1448
1449     hwEdit = create_child_editcontrol(0, 0);
1450
1451     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1452
1453     memset(&lf, 0, sizeof(lf));
1454     strcpy(lf.lfFaceName, "Arial");
1455     lf.lfHeight = 16;
1456     lf.lfCharSet = DEFAULT_CHARSET;
1457     hfont = CreateFontIndirectA(&lf);
1458     lf.lfHeight = 30;
1459     hfont2 = CreateFontIndirectA(&lf);
1460
1461     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1462     font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1463     ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1464     ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1465
1466     /* With 'small' edit controls, test that the margin doesn't get set */
1467     SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1468     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1469     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1470     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1471     ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1472        "got %d\n", LOWORD(margins));
1473     ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1474        "got %d\n", HIWORD(margins));
1475
1476     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1477     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1478     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1479     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1480        "got %d\n", LOWORD(margins));
1481     ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1482        "got %d\n", HIWORD(margins));
1483
1484     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1485     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1486     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1487     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1488        "got %d\n", LOWORD(margins));
1489     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1490        "got %d\n", HIWORD(margins));
1491
1492     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1493     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1494     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1495        "got %d\n", LOWORD(margins));
1496     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1497        "got %d\n", HIWORD(margins));
1498
1499     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1500     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1501     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
1502        "got %d\n", LOWORD(margins));
1503     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
1504        "got %d\n", HIWORD(margins));
1505
1506     /* Above a certain size threshold then the margin is updated */
1507     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1508     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1509     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1510     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1511     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1512     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1513
1514     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1515     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1516     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1517     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1518     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1519
1520     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1521     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1522     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1523     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1524     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1525     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1526     ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
1527        "got %d\n", LOWORD(margins));
1528     ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1529
1530     SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1531     
1532     DeleteObject(hfont2);
1533     DeleteObject(hfont);
1534     destroy_child_editcontrol(hwEdit);
1535
1536 }
1537
1538 #define edit_pos_ok(exp, got, txt) \
1539     ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1540
1541 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1542 do { \
1543     RECT format_rect; \
1544     int left_margin; \
1545     set_client_height(hwEdit, set_height); \
1546     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1547     left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
1548     edit_pos_ok(test_top, format_rect.top, vertical position); \
1549     edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1550     edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1551 } while(0)
1552
1553 static void test_text_position_style(DWORD style)
1554 {
1555     HWND hwEdit;
1556     HFONT font, oldFont;
1557     HDC dc;
1558     TEXTMETRIC metrics;
1559     INT b, bm, b2, b3;
1560     BOOL single_line = !(style & ES_MULTILINE);
1561
1562     b = GetSystemMetrics(SM_CYBORDER) + 1;
1563     b2 = 2 * b;
1564     b3 = 3 * b;
1565     bm = b2 - 1;
1566     
1567     /* Get a stock font for which we can determine the metrics */
1568     assert(font = GetStockObject(SYSTEM_FONT));
1569     assert(dc = GetDC(NULL));
1570     oldFont = SelectObject(dc, font);
1571     assert(GetTextMetrics(dc, &metrics));    
1572     SelectObject(dc, oldFont);
1573     ReleaseDC(NULL, dc);
1574     
1575     /* Windows' edit control has some bugs in multi-line mode:
1576      * - Sometimes the format rectangle doesn't get updated
1577      *   (see workaround in set_client_height())
1578      * - If the height of the control is smaller than the height of a text
1579      *   line, the format rectangle is still as high as a text line
1580      *   (higher than the client rectangle) and the caret is not shown
1581      */
1582     
1583     /* Edit controls that are in a parent window */
1584        
1585     hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1586     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1587     if (single_line)
1588     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
1589     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
1590     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
1591     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
1592     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
1593     destroy_child_editcontrol(hwEdit);
1594
1595     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1596     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1597     if (single_line)
1598     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1599     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1600     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1601     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1602     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1603     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1604     destroy_child_editcontrol(hwEdit);
1605
1606     hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1607     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1608     if (single_line)
1609     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1610     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1611     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1612     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1613     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1614     destroy_child_editcontrol(hwEdit);
1615
1616     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1617     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1618     if (single_line)
1619     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1620     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1621     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1622     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1623     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1624     destroy_child_editcontrol(hwEdit);
1625
1626
1627     /* Edit controls that are popup windows */
1628     
1629     hwEdit = create_editcontrol(style | WS_POPUP, 0);
1630     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1631     if (single_line)
1632     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
1633     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
1634     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
1635     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
1636     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
1637     DestroyWindow(hwEdit);
1638
1639     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1640     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1641     if (single_line)
1642     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1643     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1644     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1645     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1646     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1647     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1648     DestroyWindow(hwEdit);
1649
1650     hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1651     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1652     if (single_line)
1653     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1654     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1655     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1656     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1657     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1658     DestroyWindow(hwEdit);
1659
1660     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1661     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1662     if (single_line)
1663     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1664     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1665     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1666     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1667     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1668     DestroyWindow(hwEdit);
1669 }
1670
1671 static void test_text_position(void)
1672 {
1673     trace("EDIT: Text position (Single line)\n");
1674     test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1675     trace("EDIT: Text position (Multi line)\n");
1676     test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1677 }
1678
1679 static void test_espassword(void)
1680 {
1681     HWND hwEdit;
1682     LONG r;
1683     char buffer[1024];
1684     const char* password = "secret";
1685
1686     hwEdit = create_editcontrol(ES_PASSWORD, 0);
1687     r = get_edit_style(hwEdit);
1688     ok(r == ES_PASSWORD, "Wrong style expected 0x%x got: 0x%x\n", ES_PASSWORD, r);
1689     /* set text */
1690     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1691     ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1692
1693     /* select all, cut (ctrl-x) */
1694     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1695     r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1696     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1697
1698     /* get text */
1699     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1700     ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1701     ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1702
1703     r = OpenClipboard(hwEdit);
1704     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1705     r = EmptyClipboard();
1706     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1707     r = CloseClipboard();
1708     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1709
1710     /* select all, copy (ctrl-c) and paste (ctrl-v) */
1711     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1712     r = SendMessage(hwEdit, WM_CHAR, 3, 0);
1713     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1714     r = SendMessage(hwEdit, WM_CHAR, 22, 0);
1715     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1716
1717     /* get text */
1718     buffer[0] = 0;
1719     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1720     ok(r == 0, "Expected: 0, got: %d\n", r);
1721     ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1722
1723     DestroyWindow (hwEdit);
1724 }
1725
1726 static void test_undo(void)
1727 {
1728     HWND hwEdit;
1729     LONG r;
1730     DWORD cpMin, cpMax;
1731     char buffer[1024];
1732     const char* text = "undo this";
1733
1734     hwEdit = create_editcontrol(0, 0);
1735     r = get_edit_style(hwEdit);
1736     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1737
1738     /* set text */
1739     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1740     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1741
1742     /* select all, */
1743     cpMin = cpMax = 0xdeadbeef;
1744     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1745     r = SendMessage(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1746     ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1747     ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1748     ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1749
1750     /* cut (ctrl-x) */
1751     r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1752     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1753
1754     /* get text */
1755     buffer[0] = 0;
1756     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1757     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1758     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1759
1760     /* undo (ctrl-z) */
1761     r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1762     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1763
1764     /* get text */
1765     buffer[0] = 0;
1766     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1767     ok(strlen(text) == r, "Unexpected length %d\n", r);
1768     ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1769
1770     /* undo again (ctrl-z) */
1771     r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1772     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1773
1774     /* get text */
1775     buffer[0] = 0;
1776     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1777     ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1778     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1779
1780     DestroyWindow (hwEdit);
1781 }
1782
1783 static void test_enter(void)
1784 {
1785     HWND hwEdit;
1786     LONG r;
1787     char buffer[16];
1788
1789     /* multiline */
1790     hwEdit = create_editcontrol(ES_MULTILINE, 0);
1791     r = get_edit_style(hwEdit);
1792     ok(ES_MULTILINE == r, "Wrong style expected 0x%x got: 0x%x\n", ES_MULTILINE, r);
1793
1794     /* set text */
1795     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1796     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1797
1798     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1799     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1800
1801     /* get text */
1802     buffer[0] = 0;
1803     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1804     ok(2 == r, "Expected: %d, got len %d\n", 2, r);
1805     ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
1806
1807     DestroyWindow (hwEdit);
1808
1809     /* single line */
1810     hwEdit = create_editcontrol(0, 0);
1811     r = get_edit_style(hwEdit);
1812     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1813
1814     /* set text */
1815     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1816     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1817
1818     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1819     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1820
1821     /* get text */
1822     buffer[0] = 0;
1823     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1824     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1825     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1826
1827     DestroyWindow (hwEdit);
1828
1829     /* single line with ES_WANTRETURN */
1830     hwEdit = create_editcontrol(ES_WANTRETURN, 0);
1831     r = get_edit_style(hwEdit);
1832     ok(ES_WANTRETURN == r, "Wrong style expected 0x%x got: 0x%x\n", ES_WANTRETURN, r);
1833
1834     /* set text */
1835     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1836     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1837
1838     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1839     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1840
1841     /* get text */
1842     buffer[0] = 0;
1843     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1844     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1845     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1846
1847     DestroyWindow (hwEdit);
1848 }
1849
1850 static void test_tab(void)
1851 {
1852     HWND hwEdit;
1853     LONG r;
1854     char buffer[16];
1855
1856     /* multiline */
1857     hwEdit = create_editcontrol(ES_MULTILINE, 0);
1858     r = get_edit_style(hwEdit);
1859     ok(ES_MULTILINE == r, "Wrong style expected 0x%x got: 0x%x\n", ES_MULTILINE, r);
1860
1861     /* set text */
1862     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1863     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1864
1865     r = SendMessage(hwEdit, WM_CHAR, VK_TAB, 0);
1866     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1867
1868     /* get text */
1869     buffer[0] = 0;
1870     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1871     ok(1 == r, "Expected: %d, got len %d\n", 1, r);
1872     ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
1873
1874     DestroyWindow (hwEdit);
1875
1876     /* single line */
1877     hwEdit = create_editcontrol(0, 0);
1878     r = get_edit_style(hwEdit);
1879     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1880
1881     /* set text */
1882     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1883     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1884
1885     r = SendMessage(hwEdit, WM_CHAR, VK_TAB, 0);
1886     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1887
1888     /* get text */
1889     buffer[0] = 0;
1890     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1891     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1892     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1893
1894     DestroyWindow (hwEdit);
1895 }
1896
1897 static void test_edit_dialog(void)
1898 {
1899     int r;
1900
1901     /* from bug 11841 */
1902     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 0);
1903     ok(333 == r, "Expected %d, got %d\n", 333, r);
1904     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 1);
1905     ok(111 == r, "Expected %d, got %d\n", 111, r);
1906     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 2);
1907     ok(444 == r, "Expected %d, got %d\n", 444, r);
1908
1909     /* more tests for WM_CHAR */
1910     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 3);
1911     ok(444 == r, "Expected %d, got %d\n", 444, r);
1912     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 4);
1913     ok(444 == r, "Expected %d, got %d\n", 444, r);
1914     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 5);
1915     ok(444 == r, "Expected %d, got %d\n", 444, r);
1916
1917     /* more tests for WM_KEYDOWN + WM_CHAR */
1918     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 6);
1919     ok(444 == r, "Expected %d, got %d\n", 444, r);
1920     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 7);
1921     ok(444 == r, "Expected %d, got %d\n", 444, r);
1922     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 8);
1923     ok(444 == r, "Expected %d, got %d\n", 444, r);
1924
1925     /* tests with an editable edit control */
1926     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 0);
1927     ok(333 == r, "Expected %d, got %d\n", 333, r);
1928     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 1);
1929     ok(111 == r, "Expected %d, got %d\n", 111, r);
1930     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 2);
1931     ok(444 == r, "Expected %d, got %d\n", 444, r);
1932
1933     /* tests for WM_CHAR */
1934     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 3);
1935     ok(444 == r, "Expected %d, got %d\n", 444, r);
1936     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 4);
1937     ok(444 == r, "Expected %d, got %d\n", 444, r);
1938     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 5);
1939     ok(444 == r, "Expected %d, got %d\n", 444, r);
1940
1941     /* tests for WM_KEYDOWN + WM_CHAR */
1942     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 6);
1943     ok(444 == r, "Expected %d, got %d\n", 444, r);
1944     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 7);
1945     ok(444 == r, "Expected %d, got %d\n", 444, r);
1946     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 8);
1947     ok(444 == r, "Expected %d, got %d\n", 444, r);
1948
1949     /* multiple tab tests */
1950     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 9);
1951     ok(22 == r, "Expected %d, got %d\n", 22, r);
1952     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 10);
1953     ok(33 == r, "Expected %d, got %d\n", 33, r);
1954 }
1955
1956 static void test_multi_edit_dialog(void)
1957 {
1958     int r;
1959
1960     /* test for multiple edit dialogs (bug 12319) */
1961     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 0);
1962     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
1963     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 1);
1964     ok(1111 == r, "Expected %d, got %d\n", 1111, r);
1965     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 2);
1966     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
1967     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 3);
1968     ok(11 == r, "Expected %d, got %d\n", 11, r);
1969 }
1970
1971 static void test_wantreturn_edit_dialog(void)
1972 {
1973     int r;
1974
1975     /* tests for WM_KEYDOWN */
1976     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 0);
1977     ok(333 == r, "Expected %d, got %d\n", 333, r);
1978     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 1);
1979     ok(444 == r, "Expected %d, got %d\n", 444, r);
1980     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 2);
1981     ok(444 == r, "Expected %d, got %d\n", 444, r);
1982
1983     /* tests for WM_CHAR */
1984     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 3);
1985     ok(444 == r, "Expected %d, got %d\n", 444, r);
1986     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 4);
1987     ok(444 == r, "Expected %d, got %d\n", 444, r);
1988     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 5);
1989     ok(444 == r, "Expected %d, got %d\n", 444, r);
1990
1991     /* tests for WM_KEYDOWN + WM_CHAR */
1992     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 6);
1993     ok(444 == r, "Expected %d, got %d\n", 444, r);
1994     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 7);
1995     ok(444 == r, "Expected %d, got %d\n", 444, r);
1996     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 8);
1997     ok(444 == r, "Expected %d, got %d\n", 444, r);
1998 }
1999
2000 static void test_singleline_wantreturn_edit_dialog(void)
2001 {
2002     int r;
2003
2004     /* tests for WM_KEYDOWN */
2005     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 0);
2006     ok(222 == r, "Expected %d, got %d\n", 222, r);
2007     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 1);
2008     ok(111 == r, "Expected %d, got %d\n", 111, r);
2009     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 2);
2010     ok(444 == r, "Expected %d, got %d\n", 444, r);
2011
2012     /* tests for WM_CHAR */
2013     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 3);
2014     ok(444 == r, "Expected %d, got %d\n", 444, r);
2015     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 4);
2016     ok(444 == r, "Expected %d, got %d\n", 444, r);
2017     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 5);
2018     ok(444 == r, "Expected %d, got %d\n", 444, r);
2019
2020     /* tests for WM_KEYDOWN + WM_CHAR */
2021     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 6);
2022     ok(222 == r, "Expected %d, got %d\n", 222, r);
2023     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 7);
2024     ok(111 == r, "Expected %d, got %d\n", 111, r);
2025     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 8);
2026     ok(444 == r, "Expected %d, got %d\n", 444, r);
2027
2028     /* tests for WM_KEYDOWN */
2029     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 0);
2030     ok(222 == r, "Expected %d, got %d\n", 222, r);
2031     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 1);
2032     ok(111 == r, "Expected %d, got %d\n", 111, r);
2033     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 2);
2034     ok(444 == r, "Expected %d, got %d\n", 444, r);
2035
2036     /* tests for WM_CHAR */
2037     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 3);
2038     ok(444 == r, "Expected %d, got %d\n", 444, r);
2039     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 4);
2040     ok(444 == r, "Expected %d, got %d\n", 444, r);
2041     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 5);
2042     ok(444 == r, "Expected %d, got %d\n", 444, r);
2043
2044     /* tests for WM_KEYDOWN + WM_CHAR */
2045     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 6);
2046     ok(222 == r, "Expected %d, got %d\n", 222, r);
2047     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 7);
2048     ok(111 == r, "Expected %d, got %d\n", 111, r);
2049     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 8);
2050     ok(444 == r, "Expected %d, got %d\n", 444, r);
2051 }
2052
2053 static int child_edit_wmkeydown_num_messages = 0;
2054 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2055 {
2056     switch (msg)
2057     {
2058         case WM_DESTROY:
2059         case WM_NCDESTROY:
2060             break;
2061
2062         default:
2063             child_edit_wmkeydown_num_messages++;
2064             break;
2065     }
2066
2067     return FALSE;
2068 }
2069
2070 static void test_child_edit_wmkeydown(void)
2071 {
2072     HWND hwEdit, hwParent;
2073     int r;
2074
2075     hwEdit = create_child_editcontrol(0, 0);
2076     hwParent = GetParent(hwEdit);
2077     SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2078     r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2079     ok(1 == r, "expected 1, got %d\n", r);
2080     ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2081     destroy_child_editcontrol(hwEdit);
2082 }
2083
2084 static BOOL RegisterWindowClasses (void)
2085 {
2086     WNDCLASSA test2;
2087     WNDCLASSA test3;
2088     WNDCLASSA text_position;
2089     
2090     test2.style = 0;
2091     test2.lpfnWndProc = ET2_WndProc;
2092     test2.cbClsExtra = 0;
2093     test2.cbWndExtra = 0;
2094     test2.hInstance = hinst;
2095     test2.hIcon = NULL;
2096     test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
2097     test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2098     test2.lpszMenuName = NULL;
2099     test2.lpszClassName = szEditTest2Class;
2100     if (!RegisterClassA(&test2)) return FALSE;
2101
2102     test3.style = 0;
2103     test3.lpfnWndProc = edit3_wnd_procA;
2104     test3.cbClsExtra = 0;
2105     test3.cbWndExtra = 0;
2106     test3.hInstance = hinst;
2107     test3.hIcon = 0;
2108     test3.hCursor = LoadCursorA(0, IDC_ARROW);
2109     test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2110     test3.lpszMenuName = NULL;
2111     test3.lpszClassName = szEditTest3Class;
2112     if (!RegisterClassA(&test3)) return FALSE;
2113
2114     text_position.style = CS_HREDRAW | CS_VREDRAW;
2115     text_position.cbClsExtra = 0;
2116     text_position.cbWndExtra = 0;
2117     text_position.hInstance = hinst;
2118     text_position.hIcon = NULL;
2119     text_position.hCursor = LoadCursorA(NULL, IDC_ARROW);
2120     text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2121     text_position.lpszMenuName = NULL;
2122     text_position.lpszClassName = szEditTextPositionClass;
2123     text_position.lpfnWndProc = DefWindowProc;
2124     if (!RegisterClassA(&text_position)) return FALSE;
2125
2126     return TRUE;
2127 }
2128
2129 static void UnregisterWindowClasses (void)
2130 {
2131     UnregisterClassA(szEditTest2Class, hinst);
2132     UnregisterClassA(szEditTest3Class, hinst);
2133     UnregisterClassA(szEditTextPositionClass, hinst);
2134 }
2135
2136 static void test_fontsize(void)
2137 {
2138     HWND hwEdit;
2139     HFONT hfont;
2140     LOGFONT lf;
2141     LONG r;
2142     char szLocalString[MAXLEN];
2143
2144     memset(&lf,0,sizeof(LOGFONTA));
2145     strcpy(lf.lfFaceName,"Arial");
2146     lf.lfHeight = -300; /* taller than the edit box */
2147     lf.lfWeight = 500;
2148     hfont = CreateFontIndirect(&lf);
2149
2150     trace("EDIT: Oversized font (Multi line)\n");
2151     hwEdit= CreateWindow("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2152                            0, 0, 150, 50, NULL, NULL, hinst, NULL);
2153
2154     SendMessage(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2155
2156     if (winetest_interactive)
2157         ShowWindow (hwEdit, SW_SHOW);
2158
2159     r = SendMessage(hwEdit, WM_CHAR, 'A', 1);
2160     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2161     r = SendMessage(hwEdit, WM_CHAR, 'B', 1);
2162     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2163     r = SendMessage(hwEdit, WM_CHAR, 'C', 1);
2164     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2165
2166     GetWindowText(hwEdit, szLocalString, MAXLEN);
2167     ok(lstrcmp(szLocalString, "ABC")==0,
2168        "Wrong contents of edit: %s\n", szLocalString);
2169
2170     r = SendMessage(hwEdit, EM_POSFROMCHAR,0,0);
2171     ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2172     r = SendMessage(hwEdit, EM_POSFROMCHAR,1,0);
2173     ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2174     r = SendMessage(hwEdit, EM_POSFROMCHAR,2,0);
2175     ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2176     r = SendMessage(hwEdit, EM_POSFROMCHAR,3,0);
2177     ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2178
2179     DestroyWindow (hwEdit);
2180     DeleteObject(hfont);
2181 }
2182
2183 struct dialog_mode_messages
2184 {
2185     int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2186 };
2187
2188 static struct dialog_mode_messages dm_messages;
2189
2190 static void zero_dm_messages(void)
2191 {
2192     dm_messages.wm_command      = 0;
2193     dm_messages.wm_close        = 0;
2194     dm_messages.wm_getdefid     = 0;
2195     dm_messages.wm_nextdlgctl   = 0;
2196 }
2197
2198 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2199     ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2200     "got %d\n", wmcommand, dm_messages.wm_command); \
2201     ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2202     "got %d\n", wmclose, dm_messages.wm_close); \
2203     ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2204     "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2205     ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2206     "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2207
2208 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2209 {
2210     switch (iMsg)
2211     {
2212         case WM_COMMAND:
2213             dm_messages.wm_command++;
2214             break;
2215         case DM_GETDEFID:
2216             dm_messages.wm_getdefid++;
2217             return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2218         case WM_NEXTDLGCTL:
2219             dm_messages.wm_nextdlgctl++;
2220             break;
2221         case WM_CLOSE:
2222             dm_messages.wm_close++;
2223             break;
2224     }
2225
2226     return DefWindowProc(hwnd, iMsg, wParam, lParam);
2227 }
2228
2229 static void test_dialogmode(void)
2230 {
2231     HWND hwEdit, hwParent, hwButton;
2232     MSG msg= {0};
2233     int len, r;
2234     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2235
2236     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2237     ok(1 == r, "expected 1, got %d\n", r);
2238     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2239     ok(11 == len, "expected 11, got %d\n", len);
2240
2241     r = SendMessage(hwEdit, WM_GETDLGCODE, 0, 0);
2242     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2243
2244     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2245     ok(1 == r, "expected 1, got %d\n", r);
2246     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2247     ok(13 == len, "expected 13, got %d\n", len);
2248
2249     r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2250     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2251     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2252     ok(1 == r, "expected 1, got %d\n", r);
2253     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2254     ok(13 == len, "expected 13, got %d\n", len);
2255
2256     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2257     ok(1 == r, "expected 1, got %d\n", r);
2258     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2259     ok(13 == len, "expected 13, got %d\n", len);
2260
2261     destroy_child_editcontrol(hwEdit);
2262
2263     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2264
2265     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2266     ok(1 == r, "expected 1, got %d\n", r);
2267     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2268     ok(11 == len, "expected 11, got %d\n", len);
2269
2270     msg.hwnd = hwEdit;
2271     msg.message = WM_KEYDOWN;
2272     msg.wParam = VK_BACK;
2273     msg.lParam = 0xe0001;
2274     r = SendMessage(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2275     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2276
2277     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2278     ok(1 == r, "expected 1, got %d\n", r);
2279     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2280     ok(11 == len, "expected 11, got %d\n", len);
2281
2282     DestroyWindow(hwEdit);
2283
2284     hwEdit = create_child_editcontrol(0, 0);
2285     hwParent = GetParent(hwEdit);
2286     SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2287
2288     zero_dm_messages();
2289     r = SendMessage(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2290     ok(1 == r, "expected 1, got %d\n", r);
2291     test_dm_messages(0, 0, 0, 0);
2292     zero_dm_messages();
2293
2294     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2295     ok(1 == r, "expected 1, got %d\n", r);
2296     test_dm_messages(0, 0, 0, 0);
2297     zero_dm_messages();
2298
2299     msg.hwnd = hwEdit;
2300     msg.message = WM_KEYDOWN;
2301     msg.wParam = VK_TAB;
2302     msg.lParam = 0xf0001;
2303     r = SendMessage(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2304     ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2305     test_dm_messages(0, 0, 0, 0);
2306     zero_dm_messages();
2307
2308     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2309     ok(1 == r, "expected 1, got %d\n", r);
2310     test_dm_messages(0, 0, 0, 0);
2311     zero_dm_messages();
2312
2313     destroy_child_editcontrol(hwEdit);
2314
2315     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2316     hwParent = GetParent(hwEdit);
2317     SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2318
2319     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2320     ok(1 == r, "expected 1, got %d\n", r);
2321     test_dm_messages(0, 0, 0, 0);
2322     zero_dm_messages();
2323
2324     msg.hwnd = hwEdit;
2325     msg.message = WM_KEYDOWN;
2326     msg.wParam = VK_ESCAPE;
2327     msg.lParam = 0x10001;
2328     r = SendMessage(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2329     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2330     test_dm_messages(0, 0, 0, 0);
2331     zero_dm_messages();
2332
2333     r = SendMessage(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2334     ok(1 == r, "expected 1, got %d\n", r);
2335     test_dm_messages(0, 0, 0, 0);
2336     zero_dm_messages();
2337
2338     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2339     ok(1 == r, "expected 1, got %d\n", r);
2340     test_dm_messages(0, 0, 0, 1);
2341     zero_dm_messages();
2342
2343     r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2344     ok(1 == r, "expected 1, got %d\n", r);
2345     test_dm_messages(0, 0, 1, 0);
2346     zero_dm_messages();
2347
2348     hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2349         100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2350     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2351
2352     r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2353     ok(1 == r, "expected 1, got %d\n", r);
2354     test_dm_messages(0, 0, 1, 1);
2355     zero_dm_messages();
2356
2357     DestroyWindow(hwButton);
2358     destroy_child_editcontrol(hwEdit);
2359 }
2360
2361 START_TEST(edit)
2362 {
2363     hinst = GetModuleHandleA(NULL);
2364     assert(RegisterWindowClasses());
2365
2366     test_edit_control_1();
2367     test_edit_control_2();
2368     test_edit_control_3();
2369     test_edit_control_4();
2370     test_edit_control_5();
2371     test_edit_control_6();
2372     test_edit_control_limittext();
2373     test_edit_control_scroll();
2374     test_margins();
2375     test_margins_font_change();
2376     test_text_position();
2377     test_espassword();
2378     test_undo();
2379     test_enter();
2380     test_tab();
2381     test_edit_dialog();
2382     test_multi_edit_dialog();
2383     test_wantreturn_edit_dialog();
2384     test_singleline_wantreturn_edit_dialog();
2385     test_child_edit_wmkeydown();
2386     test_fontsize();
2387     test_dialogmode();
2388
2389     UnregisterWindowClasses();
2390 }