user32: edit: Improve handling of WM_KEYDOWN VK_RETURN in a dialog mode.
[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     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
873
874     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
875     zero_notify();
876     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
877     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
878     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
879     test_notify(1, 1, 1);
880
881     zero_notify();
882     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
883     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
884     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
885     test_notify(1, 0, 1);
886
887     DestroyWindow(hWnd);
888
889     trace("EDIT: Single line, ES_AUTOHSCROLL\n");
890     hWnd = CreateWindowExA(0,
891               "EDIT",
892               NULL,
893               ES_AUTOHSCROLL,
894               10, 10, 50, 50,
895               hParent, NULL, NULL, NULL);
896     assert(hWnd);
897
898     zero_notify();
899     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
900     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
901     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
902     test_notify(1, 0, 1);
903
904     zero_notify();
905     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
906     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
907     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
908     test_notify(1, 0, 1);
909
910     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
911
912     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
913     zero_notify();
914     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
915     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
916     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
917     test_notify(1, 1, 1);
918
919     zero_notify();
920     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
921     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
922     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
923     test_notify(1, 0, 1);
924
925     DestroyWindow(hWnd);
926
927     trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
928     hWnd = CreateWindowExA(0,
929               "EDIT",
930               NULL,
931               ES_MULTILINE,
932               10, 10, 50, 50,
933               hParent, NULL, NULL, NULL);
934     assert(hWnd);
935
936     zero_notify();
937     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
938     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
939     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
940     test_notify(1, 1, 1);
941
942     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
943     zero_notify();
944     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
945     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
946     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
947     test_notify(1, 0, 1);
948
949     zero_notify();
950     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
951     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
952     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
953     test_notify(0, 0, 0);
954
955     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
956
957     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
958     zero_notify();
959     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
960     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
961     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
962     test_notify(1, 1, 1);
963
964     zero_notify();
965     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
966     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
967     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
968     test_notify(0, 0, 0);
969
970     DestroyWindow(hWnd);
971
972     trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
973     hWnd = CreateWindowExA(0,
974               "EDIT",
975               NULL,
976               ES_MULTILINE | ES_AUTOHSCROLL,
977               10, 10, 50, 50,
978               hParent, NULL, NULL, NULL);
979     assert(hWnd);
980
981     zero_notify();
982     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
983     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
984     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
985     test_notify(1, 1, 1);
986
987     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
988     zero_notify();
989     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
990     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
991     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
992     test_notify(1, 0, 1);
993
994     zero_notify();
995     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
996     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
997     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
998     test_notify(0, 0, 0);
999
1000     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1001
1002     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1003     zero_notify();
1004     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1005     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1006     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1007     test_notify(1, 1, 1);
1008
1009     zero_notify();
1010     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1011     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1012     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1013     test_notify(0, 0, 0);
1014
1015     DestroyWindow(hWnd);
1016
1017     trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1018     hWnd = CreateWindowExA(0,
1019               "EDIT",
1020               NULL,
1021               ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1022               10, 10, 50, 50,
1023               hParent, NULL, NULL, NULL);
1024     assert(hWnd);
1025
1026     zero_notify();
1027     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1028     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1029     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1030     test_notify(1, 0, 1);
1031
1032     zero_notify();
1033     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1034     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1035     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1036     test_notify(0, 0, 0);
1037
1038     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1039
1040     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1041     zero_notify();
1042     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1043     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1044     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1045     test_notify(1, 1, 1);
1046
1047     zero_notify();
1048     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1049     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1050     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1051     test_notify(0, 0, 0);
1052
1053     DestroyWindow(hWnd);
1054 }
1055
1056 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
1057  */
1058 static void test_edit_control_4(void)
1059 {
1060     HWND hwEdit;
1061     int lo, hi, mid;
1062     int ret;
1063     int i;
1064
1065     trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
1066     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1067     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1068     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1069     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1070     mid = lo + (hi - lo) / 2;
1071
1072     for (i = lo; i < mid; i++) {
1073        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1074        ok(0 == ret, "expected 0 got %d\n", ret);
1075     }
1076     for (i = mid; i <= hi; i++) {
1077        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1078        ok(1 == ret, "expected 1 got %d\n", ret);
1079     }
1080     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1081     ok(-1 == ret, "expected -1 got %d\n", ret);
1082     DestroyWindow(hwEdit);
1083
1084     hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1085     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1086     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1087     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1088     mid = lo + (hi - lo) / 2;
1089
1090     for (i = lo; i < mid; i++) {
1091        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1092        ok(0 == ret, "expected 0 got %d\n", ret);
1093     }
1094     for (i = mid; i <= hi; i++) {
1095        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1096        ok(1 == ret, "expected 1 got %d\n", ret);
1097     }
1098     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1099     ok(-1 == ret, "expected -1 got %d\n", ret);
1100     DestroyWindow(hwEdit);
1101
1102     hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1103     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1104     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1105     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1106     mid = lo + (hi - lo) / 2;
1107
1108     for (i = lo; i < mid; i++) {
1109        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1110        ok(0 == ret, "expected 0 got %d\n", ret);
1111     }
1112     for (i = mid; i <= hi; i++) {
1113        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1114        ok(1 == ret, "expected 1 got %d\n", ret);
1115     }
1116     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1117     ok(-1 == ret, "expected -1 got %d\n", ret);
1118     DestroyWindow(hwEdit);
1119
1120     hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1121     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1122     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1123     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1124     mid = lo + (hi - lo) / 2 +1;
1125
1126     for (i = lo; i < mid; i++) {
1127        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1128        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1129     }
1130     for (i = mid; i <= hi; i++) {
1131        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1132        ok(1 == ret, "expected 1 got %d\n", ret);
1133     }
1134     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1135     ok(-1 == ret, "expected -1 got %d\n", ret);
1136     DestroyWindow(hwEdit);
1137
1138     hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1139     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1140     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1141     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1142     mid = lo + (hi - lo) / 2 +1;
1143
1144     for (i = lo; i < mid; i++) {
1145        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1146        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1147     }
1148     for (i = mid; i <= hi; i++) {
1149        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1150        ok(1 == ret, "expected 1 got %d\n", ret);
1151     }
1152     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1153     ok(-1 == ret, "expected -1 got %d\n", ret);
1154     DestroyWindow(hwEdit);
1155
1156     hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1157     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1158     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1159     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1160     mid = lo + (hi - lo) / 2 +1;
1161
1162     for (i = lo; i < mid; i++) {
1163        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1164        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1165     }
1166     for (i = mid; i <= hi; i++) {
1167        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
1168        ok(1 == ret, "expected 1 got %d\n", ret);
1169     }
1170     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1171     ok(-1 == ret, "expected -1 got %d\n", ret);
1172     DestroyWindow(hwEdit);
1173 }
1174
1175 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1176  * truncates text that doesn't fit.
1177  */
1178 static void test_edit_control_5(void)
1179 {
1180     static const char *str = "test\r\ntest";
1181     HWND parentWnd;
1182     HWND hWnd;
1183     int len;
1184     RECT rc1 = { 10, 10, 11, 11};
1185     RECT rc;
1186
1187     /* first show that a non-child won't do for this test */
1188     hWnd = CreateWindowEx(0,
1189               "EDIT",
1190               str,
1191               0,
1192               10, 10, 1, 1,
1193               NULL, NULL, NULL, NULL);
1194     assert(hWnd);
1195     /* size of non-child edit control is (much) bigger than requested */
1196     GetWindowRect( hWnd, &rc);
1197     ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1198             rc.right - rc.left);
1199     DestroyWindow(hWnd);
1200     /* so create a parent, and give it edit controls children to test with */
1201     parentWnd = CreateWindowEx(0,
1202                             szEditTextPositionClass,
1203                             "Edit Test", WS_VISIBLE |
1204                             WS_OVERLAPPEDWINDOW,
1205                             CW_USEDEFAULT, CW_USEDEFAULT,
1206                             250, 250,
1207                             NULL, NULL, hinst, NULL);
1208     assert(parentWnd);
1209     ShowWindow( parentWnd, SW_SHOW);
1210     /* single line */
1211     hWnd = CreateWindowEx(0,
1212               "EDIT",
1213               str, WS_VISIBLE | WS_BORDER |
1214               WS_CHILD,
1215               rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1216               parentWnd, NULL, NULL, NULL);
1217     assert(hWnd);
1218     GetClientRect( hWnd, &rc);
1219     ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1220             "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1221             rc.left, rc.top, rc.right, rc.bottom);
1222     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1223     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1224     DestroyWindow(hWnd);
1225     /* multi line */
1226     hWnd = CreateWindowEx(0,
1227               "EDIT",
1228               str,
1229               WS_CHILD | ES_MULTILINE,
1230               rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1231               parentWnd, NULL, NULL, NULL);
1232     assert(hWnd);
1233     GetClientRect( hWnd, &rc);
1234     ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1235             "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1236             rc.left, rc.top, rc.right, rc.bottom);
1237     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1238     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1239     DestroyWindow(hWnd);
1240 }
1241
1242 static void test_edit_control_limittext(void)
1243 {
1244     HWND hwEdit;
1245     DWORD r;
1246
1247     /* Test default limit for single-line control */
1248     trace("EDIT: buffer limit for single-line\n");
1249     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1250     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1251     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1252     SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
1253     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1254     /* Win9x+ME: 32766; WinNT: 2147483646UL */
1255     ok( (r == 32766) || (r == 2147483646UL),
1256         "got limit %u (expected 32766 or 2147483646)\n", r);
1257     DestroyWindow(hwEdit);
1258
1259     /* Test default limit for multi-line control */
1260     trace("EDIT: buffer limit for multi-line\n");
1261     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1262     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1263     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1264     SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
1265     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1266     /* Win9x+ME: 65535; WinNT: 4294967295UL */
1267     ok( (r == 65535) || (r == 4294967295UL),
1268         "got limit %u (expected 65535 or 4294967295)\n", r);
1269     DestroyWindow(hwEdit);
1270 }
1271
1272 static void test_margins(void)
1273 {
1274     HWND hwEdit;
1275     RECT old_rect, new_rect;
1276     INT old_left_margin, old_right_margin;
1277     DWORD old_margins, new_margins;
1278
1279     hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1280     
1281     old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1282     old_left_margin = LOWORD(old_margins);
1283     old_right_margin = HIWORD(old_margins);
1284     
1285     /* Check if setting the margins works */
1286     
1287     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1288     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1289     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1290     ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1291     
1292     SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1293     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1294     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1295     ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1296     
1297     
1298     /* The size of the rectangle must decrease if we increase the margin */
1299     
1300     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1301     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1302     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1303     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1304     ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1305     ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1306     ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1307     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1308     
1309     
1310     /* If we set the margin to same value as the current margin,
1311        the rectangle must not change */
1312     
1313     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1314     old_rect.left = 1;
1315     old_rect.right = 99;
1316     old_rect.top = 1;
1317     old_rect.bottom = 99;
1318     SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);    
1319     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1320     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1321     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1322     ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
1323     ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
1324     ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
1325     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
1326
1327     DestroyWindow (hwEdit);
1328 }
1329
1330 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
1331 {
1332     return 0;
1333 }
1334
1335 static void test_margins_font_change(void)
1336 {
1337     HWND hwEdit;
1338     DWORD margins, font_margins;
1339     LOGFONT lf;
1340     HFONT hfont, hfont2;
1341     HDC hdc = GetDC(0);
1342
1343     if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
1344     {
1345         trace("Arial not found - skipping font change margin tests\n");
1346         ReleaseDC(0, hdc);
1347         return;
1348     }
1349     ReleaseDC(0, hdc);
1350
1351     hwEdit = create_child_editcontrol(0, 0);
1352
1353     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1354
1355     memset(&lf, 0, sizeof(lf));
1356     strcpy(lf.lfFaceName, "Arial");
1357     lf.lfHeight = 16;
1358     lf.lfCharSet = DEFAULT_CHARSET;
1359     hfont = CreateFontIndirectA(&lf);
1360     lf.lfHeight = 30;
1361     hfont2 = CreateFontIndirectA(&lf);
1362
1363     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1364     font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1365     ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1366     ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1367
1368     /* With 'small' edit controls, test that the margin doesn't get set */
1369     SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1370     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1371     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1372     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1373     ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1374        "got %d\n", LOWORD(margins));
1375     ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1376        "got %d\n", HIWORD(margins));
1377
1378     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1379     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1380     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1381     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1382        "got %d\n", LOWORD(margins));
1383     ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1384        "got %d\n", HIWORD(margins));
1385
1386     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1387     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1388     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1389     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1390        "got %d\n", LOWORD(margins));
1391     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1392        "got %d\n", HIWORD(margins));
1393
1394     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1395     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1396     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1397        "got %d\n", LOWORD(margins));
1398     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1399        "got %d\n", HIWORD(margins));
1400
1401     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1402     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1403     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
1404        "got %d\n", LOWORD(margins));
1405     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
1406        "got %d\n", HIWORD(margins));
1407
1408     /* Above a certain size threshold then the margin is updated */
1409     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1410     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1411     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1412     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1413     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1414     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1415
1416     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1417     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1418     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1419     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1420     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1421
1422     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1423     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1424     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1425     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1426     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1427     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1428     ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
1429        "got %d\n", LOWORD(margins));
1430     ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
1431
1432     SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1433     
1434     DeleteObject(hfont2);
1435     DeleteObject(hfont);
1436     destroy_child_editcontrol(hwEdit);
1437
1438 }
1439
1440 #define edit_pos_ok(exp, got, txt) \
1441     ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1442
1443 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1444 do { \
1445     RECT format_rect; \
1446     int left_margin; \
1447     set_client_height(hwEdit, set_height); \
1448     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1449     left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
1450     edit_pos_ok(test_top, format_rect.top, vertical position); \
1451     edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1452     edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1453 } while(0)
1454
1455 static void test_text_position_style(DWORD style)
1456 {
1457     HWND hwEdit;
1458     HFONT font, oldFont;
1459     HDC dc;
1460     TEXTMETRIC metrics;
1461     INT b, bm, b2, b3;
1462     BOOL single_line = !(style & ES_MULTILINE);
1463
1464     b = GetSystemMetrics(SM_CYBORDER) + 1;
1465     b2 = 2 * b;
1466     b3 = 3 * b;
1467     bm = b2 - 1;
1468     
1469     /* Get a stock font for which we can determine the metrics */
1470     assert(font = GetStockObject(SYSTEM_FONT));
1471     assert(dc = GetDC(NULL));
1472     oldFont = SelectObject(dc, font);
1473     assert(GetTextMetrics(dc, &metrics));    
1474     SelectObject(dc, oldFont);
1475     ReleaseDC(NULL, dc);
1476     
1477     /* Windows' edit control has some bugs in multi-line mode:
1478      * - Sometimes the format rectangle doesn't get updated
1479      *   (see workaround in set_client_height())
1480      * - If the height of the control is smaller than the height of a text
1481      *   line, the format rectangle is still as high as a text line
1482      *   (higher than the client rectangle) and the caret is not shown
1483      */
1484     
1485     /* Edit controls that are in a parent window */
1486        
1487     hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1488     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1489     if (single_line)
1490     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
1491     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
1492     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
1493     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
1494     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
1495     destroy_child_editcontrol(hwEdit);
1496
1497     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1498     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1499     if (single_line)
1500     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1501     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1502     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1503     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1504     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1505     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1506     destroy_child_editcontrol(hwEdit);
1507
1508     hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1509     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1510     if (single_line)
1511     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1512     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1513     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1514     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1515     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1516     destroy_child_editcontrol(hwEdit);
1517
1518     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1519     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1520     if (single_line)
1521     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1522     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1523     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1524     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1525     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1526     destroy_child_editcontrol(hwEdit);
1527
1528
1529     /* Edit controls that are popup windows */
1530     
1531     hwEdit = create_editcontrol(style | WS_POPUP, 0);
1532     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1533     if (single_line)
1534     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
1535     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
1536     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
1537     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
1538     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
1539     DestroyWindow(hwEdit);
1540
1541     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1542     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1543     if (single_line)
1544     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1545     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1546     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1547     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1548     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1549     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1550     DestroyWindow(hwEdit);
1551
1552     hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1553     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1554     if (single_line)
1555     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1556     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1557     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1558     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1559     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1560     DestroyWindow(hwEdit);
1561
1562     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1563     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1564     if (single_line)
1565     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1566     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1567     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1568     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1569     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1570     DestroyWindow(hwEdit);
1571 }
1572
1573 static void test_text_position(void)
1574 {
1575     trace("EDIT: Text position (Single line)\n");
1576     test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1577     trace("EDIT: Text position (Multi line)\n");
1578     test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1579 }
1580
1581 static void test_espassword(void)
1582 {
1583     HWND hwEdit;
1584     LONG r;
1585     char buffer[1024];
1586     const char* password = "secret";
1587
1588     hwEdit = create_editcontrol(ES_PASSWORD, 0);
1589     r = get_edit_style(hwEdit);
1590     ok(r == ES_PASSWORD, "Wrong style expected 0x%x got: 0x%x\n", ES_PASSWORD, r);
1591     /* set text */
1592     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1593     ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1594
1595     /* select all, cut (ctrl-x) */
1596     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1597     r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1598     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1599
1600     /* get text */
1601     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1602     ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1603     ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1604
1605     r = OpenClipboard(hwEdit);
1606     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1607     r = EmptyClipboard();
1608     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1609     r = CloseClipboard();
1610     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1611
1612     /* select all, copy (ctrl-c) and paste (ctrl-v) */
1613     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1614     r = SendMessage(hwEdit, WM_CHAR, 3, 0);
1615     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1616     r = SendMessage(hwEdit, WM_CHAR, 22, 0);
1617     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1618
1619     /* get text */
1620     buffer[0] = 0;
1621     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1622     ok(r == 0, "Expected: 0, got: %d\n", r);
1623     ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1624
1625     DestroyWindow (hwEdit);
1626 }
1627
1628 static void test_undo(void)
1629 {
1630     HWND hwEdit;
1631     LONG r;
1632     DWORD cpMin, cpMax;
1633     char buffer[1024];
1634     const char* text = "undo this";
1635
1636     hwEdit = create_editcontrol(0, 0);
1637     r = get_edit_style(hwEdit);
1638     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1639
1640     /* set text */
1641     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1642     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1643
1644     /* select all, */
1645     cpMin = cpMax = 0xdeadbeef;
1646     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1647     r = SendMessage(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1648     ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1649     ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1650     ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1651
1652     /* cut (ctrl-x) */
1653     r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1654     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1655
1656     /* get text */
1657     buffer[0] = 0;
1658     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1659     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1660     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1661
1662     /* undo (ctrl-z) */
1663     r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1664     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1665
1666     /* get text */
1667     buffer[0] = 0;
1668     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1669     ok(strlen(text) == r, "Unexpected length %d\n", r);
1670     ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1671
1672     /* undo again (ctrl-z) */
1673     r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1674     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1675
1676     /* get text */
1677     buffer[0] = 0;
1678     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1679     ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1680     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1681
1682     DestroyWindow (hwEdit);
1683 }
1684
1685 static void test_enter(void)
1686 {
1687     HWND hwEdit;
1688     LONG r;
1689     char buffer[16];
1690
1691     /* multiline */
1692     hwEdit = create_editcontrol(ES_MULTILINE, 0);
1693     r = get_edit_style(hwEdit);
1694     ok(ES_MULTILINE == r, "Wrong style expected 0x%x got: 0x%x\n", ES_MULTILINE, r);
1695
1696     /* set text */
1697     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1698     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1699
1700     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1701     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1702
1703     /* get text */
1704     buffer[0] = 0;
1705     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1706     ok(2 == r, "Expected: %d, got len %d\n", 2, r);
1707     ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
1708
1709     DestroyWindow (hwEdit);
1710
1711     /* single line */
1712     hwEdit = create_editcontrol(0, 0);
1713     r = get_edit_style(hwEdit);
1714     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1715
1716     /* set text */
1717     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1718     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1719
1720     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1721     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1722
1723     /* get text */
1724     buffer[0] = 0;
1725     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1726     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1727     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1728
1729     DestroyWindow (hwEdit);
1730
1731     /* single line with ES_WANTRETURN */
1732     hwEdit = create_editcontrol(ES_WANTRETURN, 0);
1733     r = get_edit_style(hwEdit);
1734     ok(ES_WANTRETURN == r, "Wrong style expected 0x%x got: 0x%x\n", ES_WANTRETURN, r);
1735
1736     /* set text */
1737     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1738     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1739
1740     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1741     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1742
1743     /* get text */
1744     buffer[0] = 0;
1745     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1746     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1747     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1748
1749     DestroyWindow (hwEdit);
1750 }
1751
1752 static void test_tab(void)
1753 {
1754     HWND hwEdit;
1755     LONG r;
1756     char buffer[16];
1757
1758     /* multiline */
1759     hwEdit = create_editcontrol(ES_MULTILINE, 0);
1760     r = get_edit_style(hwEdit);
1761     ok(ES_MULTILINE == r, "Wrong style expected 0x%x got: 0x%x\n", ES_MULTILINE, r);
1762
1763     /* set text */
1764     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1765     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1766
1767     r = SendMessage(hwEdit, WM_CHAR, VK_TAB, 0);
1768     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1769
1770     /* get text */
1771     buffer[0] = 0;
1772     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1773     ok(1 == r, "Expected: %d, got len %d\n", 1, r);
1774     ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
1775
1776     DestroyWindow (hwEdit);
1777
1778     /* single line */
1779     hwEdit = create_editcontrol(0, 0);
1780     r = get_edit_style(hwEdit);
1781     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1782
1783     /* set text */
1784     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1785     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1786
1787     r = SendMessage(hwEdit, WM_CHAR, VK_TAB, 0);
1788     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1789
1790     /* get text */
1791     buffer[0] = 0;
1792     r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1793     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1794     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1795
1796     DestroyWindow (hwEdit);
1797 }
1798
1799 static void test_edit_dialog(void)
1800 {
1801     int r;
1802
1803     /* from bug 11841 */
1804     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 0);
1805     ok(333 == r, "Expected %d, got %d\n", 333, r);
1806     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 1);
1807     ok(111 == r, "Expected %d, got %d\n", 111, r);
1808     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 2);
1809     ok(444 == r, "Expected %d, got %d\n", 444, r);
1810
1811     /* more tests for WM_CHAR */
1812     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 3);
1813     ok(444 == r, "Expected %d, got %d\n", 444, r);
1814     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 4);
1815     ok(444 == r, "Expected %d, got %d\n", 444, r);
1816     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 5);
1817     ok(444 == r, "Expected %d, got %d\n", 444, r);
1818
1819     /* more tests for WM_KEYDOWN + WM_CHAR */
1820     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 6);
1821     ok(444 == r, "Expected %d, got %d\n", 444, r);
1822     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 7);
1823     ok(444 == r, "Expected %d, got %d\n", 444, r);
1824     r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 8);
1825     ok(444 == r, "Expected %d, got %d\n", 444, r);
1826
1827     /* tests with an editable edit control */
1828     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 0);
1829     ok(333 == r, "Expected %d, got %d\n", 333, r);
1830     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 1);
1831     ok(111 == r, "Expected %d, got %d\n", 111, r);
1832     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 2);
1833     ok(444 == r, "Expected %d, got %d\n", 444, r);
1834
1835     /* tests for WM_CHAR */
1836     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 3);
1837     ok(444 == r, "Expected %d, got %d\n", 444, r);
1838     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 4);
1839     ok(444 == r, "Expected %d, got %d\n", 444, r);
1840     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 5);
1841     ok(444 == r, "Expected %d, got %d\n", 444, r);
1842
1843     /* tests for WM_KEYDOWN + WM_CHAR */
1844     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 6);
1845     ok(444 == r, "Expected %d, got %d\n", 444, r);
1846     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 7);
1847     ok(444 == r, "Expected %d, got %d\n", 444, r);
1848     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 8);
1849     ok(444 == r, "Expected %d, got %d\n", 444, r);
1850
1851     /* multiple tab tests */
1852     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 9);
1853     ok(22 == r, "Expected %d, got %d\n", 22, r);
1854     r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, (DLGPROC)edit_dialog_proc, 10);
1855     ok(33 == r, "Expected %d, got %d\n", 33, r);
1856 }
1857
1858 static void test_multi_edit_dialog(void)
1859 {
1860     int r;
1861
1862     /* test for multiple edit dialogs (bug 12319) */
1863     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 0);
1864     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
1865     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 1);
1866     ok(1111 == r, "Expected %d, got %d\n", 1111, r);
1867     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 2);
1868     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
1869     r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, (DLGPROC)multi_edit_dialog_proc, 3);
1870     ok(11 == r, "Expected %d, got %d\n", 11, r);
1871 }
1872
1873 static void test_wantreturn_edit_dialog(void)
1874 {
1875     int r;
1876
1877     /* tests for WM_KEYDOWN */
1878     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 0);
1879     ok(333 == r, "Expected %d, got %d\n", 333, r);
1880     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 1);
1881     ok(444 == r, "Expected %d, got %d\n", 444, r);
1882     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 2);
1883     ok(444 == r, "Expected %d, got %d\n", 444, r);
1884
1885     /* tests for WM_CHAR */
1886     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 3);
1887     ok(444 == r, "Expected %d, got %d\n", 444, r);
1888     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 4);
1889     ok(444 == r, "Expected %d, got %d\n", 444, r);
1890     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 5);
1891     ok(444 == r, "Expected %d, got %d\n", 444, r);
1892
1893     /* tests for WM_KEYDOWN + WM_CHAR */
1894     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 6);
1895     ok(444 == r, "Expected %d, got %d\n", 444, r);
1896     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 7);
1897     ok(444 == r, "Expected %d, got %d\n", 444, r);
1898     r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_wantreturn_dialog_proc, 8);
1899     ok(444 == r, "Expected %d, got %d\n", 444, r);
1900 }
1901
1902 static void test_singleline_wantreturn_edit_dialog(void)
1903 {
1904     int r;
1905
1906     /* tests for WM_KEYDOWN */
1907     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 0);
1908     ok(222 == r, "Expected %d, got %d\n", 222, r);
1909     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 1);
1910     ok(111 == r, "Expected %d, got %d\n", 111, r);
1911     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 2);
1912     ok(444 == r, "Expected %d, got %d\n", 444, r);
1913
1914     /* tests for WM_CHAR */
1915     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 3);
1916     ok(444 == r, "Expected %d, got %d\n", 444, r);
1917     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 4);
1918     ok(444 == r, "Expected %d, got %d\n", 444, r);
1919     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 5);
1920     ok(444 == r, "Expected %d, got %d\n", 444, r);
1921
1922     /* tests for WM_KEYDOWN + WM_CHAR */
1923     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 6);
1924     ok(222 == r, "Expected %d, got %d\n", 222, r);
1925     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 7);
1926     ok(111 == r, "Expected %d, got %d\n", 111, r);
1927     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 8);
1928     ok(444 == r, "Expected %d, got %d\n", 444, r);
1929
1930     /* tests for WM_KEYDOWN */
1931     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 0);
1932     ok(222 == r, "Expected %d, got %d\n", 222, r);
1933     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 1);
1934     ok(111 == r, "Expected %d, got %d\n", 111, r);
1935     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 2);
1936     ok(444 == r, "Expected %d, got %d\n", 444, r);
1937
1938     /* tests for WM_CHAR */
1939     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 3);
1940     ok(444 == r, "Expected %d, got %d\n", 444, r);
1941     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 4);
1942     ok(444 == r, "Expected %d, got %d\n", 444, r);
1943     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 5);
1944     ok(444 == r, "Expected %d, got %d\n", 444, r);
1945
1946     /* tests for WM_KEYDOWN + WM_CHAR */
1947     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 6);
1948     ok(222 == r, "Expected %d, got %d\n", 222, r);
1949     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 7);
1950     ok(111 == r, "Expected %d, got %d\n", 111, r);
1951     r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, (DLGPROC)edit_singleline_dialog_proc, 8);
1952     ok(444 == r, "Expected %d, got %d\n", 444, r);
1953 }
1954
1955 static int child_edit_wmkeydown_num_messages = 0;
1956 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1957 {
1958     switch (msg)
1959     {
1960         case WM_DESTROY:
1961         case WM_NCDESTROY:
1962             break;
1963
1964         default:
1965             child_edit_wmkeydown_num_messages++;
1966             break;
1967     }
1968
1969     return FALSE;
1970 }
1971
1972 static void test_child_edit_wmkeydown(void)
1973 {
1974     HWND hwEdit, hwParent;
1975     int r;
1976
1977     hwEdit = create_child_editcontrol(0, 0);
1978     hwParent = GetParent(hwEdit);
1979     SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
1980     r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
1981     ok(1 == r, "expected 1, got %d\n", r);
1982     ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
1983     destroy_child_editcontrol(hwEdit);
1984 }
1985
1986 static BOOL RegisterWindowClasses (void)
1987 {
1988     WNDCLASSA test2;
1989     WNDCLASSA test3;
1990     WNDCLASSA text_position;
1991     
1992     test2.style = 0;
1993     test2.lpfnWndProc = ET2_WndProc;
1994     test2.cbClsExtra = 0;
1995     test2.cbWndExtra = 0;
1996     test2.hInstance = hinst;
1997     test2.hIcon = NULL;
1998     test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
1999     test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2000     test2.lpszMenuName = NULL;
2001     test2.lpszClassName = szEditTest2Class;
2002     if (!RegisterClassA(&test2)) return FALSE;
2003
2004     test3.style = 0;
2005     test3.lpfnWndProc = edit3_wnd_procA;
2006     test3.cbClsExtra = 0;
2007     test3.cbWndExtra = 0;
2008     test3.hInstance = hinst;
2009     test3.hIcon = 0;
2010     test3.hCursor = LoadCursorA(0, IDC_ARROW);
2011     test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2012     test3.lpszMenuName = NULL;
2013     test3.lpszClassName = szEditTest3Class;
2014     if (!RegisterClassA(&test3)) return FALSE;
2015
2016     text_position.style = CS_HREDRAW | CS_VREDRAW;
2017     text_position.cbClsExtra = 0;
2018     text_position.cbWndExtra = 0;
2019     text_position.hInstance = hinst;
2020     text_position.hIcon = NULL;
2021     text_position.hCursor = LoadCursorA(NULL, IDC_ARROW);
2022     text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2023     text_position.lpszMenuName = NULL;
2024     text_position.lpszClassName = szEditTextPositionClass;
2025     text_position.lpfnWndProc = DefWindowProc;
2026     if (!RegisterClassA(&text_position)) return FALSE;
2027
2028     return TRUE;
2029 }
2030
2031 static void UnregisterWindowClasses (void)
2032 {
2033     UnregisterClassA(szEditTest2Class, hinst);
2034     UnregisterClassA(szEditTest3Class, hinst);
2035     UnregisterClassA(szEditTextPositionClass, hinst);
2036 }
2037
2038 static void test_fontsize(void)
2039 {
2040     HWND hwEdit;
2041     HFONT hfont;
2042     LOGFONT lf;
2043     LONG r;
2044     char szLocalString[MAXLEN];
2045
2046     memset(&lf,0,sizeof(LOGFONTA));
2047     strcpy(lf.lfFaceName,"Arial");
2048     lf.lfHeight = -300; /* taller than the edit box */
2049     lf.lfWeight = 500;
2050     hfont = CreateFontIndirect(&lf);
2051
2052     trace("EDIT: Oversized font (Multi line)\n");
2053     hwEdit= CreateWindow("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2054                            0, 0, 150, 50, NULL, NULL, hinst, NULL);
2055
2056     SendMessage(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2057
2058     if (winetest_interactive)
2059         ShowWindow (hwEdit, SW_SHOW);
2060
2061     r = SendMessage(hwEdit, WM_CHAR, 'A', 1);
2062     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2063     r = SendMessage(hwEdit, WM_CHAR, 'B', 1);
2064     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2065     r = SendMessage(hwEdit, WM_CHAR, 'C', 1);
2066     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2067
2068     GetWindowText(hwEdit, szLocalString, MAXLEN);
2069     ok(lstrcmp(szLocalString, "ABC")==0,
2070        "Wrong contents of edit: %s\n", szLocalString);
2071
2072     r = SendMessage(hwEdit, EM_POSFROMCHAR,0,0);
2073     ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2074     r = SendMessage(hwEdit, EM_POSFROMCHAR,1,0);
2075     ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2076     r = SendMessage(hwEdit, EM_POSFROMCHAR,2,0);
2077     ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2078     r = SendMessage(hwEdit, EM_POSFROMCHAR,3,0);
2079     ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2080
2081     DestroyWindow (hwEdit);
2082     DeleteObject(hfont);
2083 }
2084
2085 struct dialog_mode_messages
2086 {
2087     int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2088 };
2089
2090 static struct dialog_mode_messages dm_messages;
2091
2092 static void zero_dm_messages(void)
2093 {
2094     dm_messages.wm_command      = 0;
2095     dm_messages.wm_close        = 0;
2096     dm_messages.wm_getdefid     = 0;
2097     dm_messages.wm_nextdlgctl   = 0;
2098 }
2099
2100 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2101     ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2102     "got %d\n", wmcommand, dm_messages.wm_command); \
2103     ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2104     "got %d\n", wmclose, dm_messages.wm_close); \
2105     ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2106     "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2107     ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2108     "got %d\n", wmgetdefid, dm_messages.wm_nextdlgctl)
2109
2110 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2111 {
2112     switch (iMsg)
2113     {
2114         case WM_COMMAND:
2115             dm_messages.wm_command++;
2116             break;
2117         case DM_GETDEFID:
2118             dm_messages.wm_getdefid++;
2119             return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2120         case WM_NEXTDLGCTL:
2121             dm_messages.wm_nextdlgctl++;
2122             break;
2123         case WM_CLOSE:
2124             dm_messages.wm_close++;
2125             break;
2126     }
2127
2128     return DefWindowProc(hwnd, iMsg, wParam, lParam);
2129 }
2130
2131 static void test_dialogmode(void)
2132 {
2133     HWND hwEdit, hwParent, hwButton;
2134     MSG msg= {0};
2135     int len, r;
2136     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2137
2138     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2139     ok(1 == r, "expected 1, got %d\n", r);
2140     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2141     ok(11 == len, "expected 11, got %d\n", len);
2142
2143     r = SendMessage(hwEdit, WM_GETDLGCODE, (WPARAM)NULL, (LPARAM)NULL);
2144     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2145
2146     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2147     ok(1 == r, "expected 1, got %d\n", r);
2148     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2149     ok(13 == len, "expected 13, got %d\n", len);
2150
2151     r = SendMessage(hwEdit, WM_GETDLGCODE, (WPARAM)NULL, (LPARAM)&msg);
2152     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2153     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2154     ok(1 == r, "expected 1, got %d\n", r);
2155     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2156     ok(13 == len, "expected 13, got %d\n", len);
2157
2158     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2159     ok(1 == r, "expected 1, got %d\n", r);
2160     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2161     ok(13 == len, "expected 13, got %d\n", len);
2162
2163     destroy_child_editcontrol(hwEdit);
2164
2165     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2166
2167     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2168     ok(1 == r, "expected 1, got %d\n", r);
2169     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2170     ok(11 == len, "expected 11, got %d\n", len);
2171
2172     msg.hwnd = hwEdit;
2173     msg.message = WM_KEYDOWN;
2174     msg.wParam = VK_BACK;
2175     msg.lParam = 0xe0001;
2176     r = SendMessage(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2177     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2178
2179     r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2180     ok(1 == r, "expected 1, got %d\n", r);
2181     len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2182     ok(11 == len, "expected 11, got %d\n", len);
2183
2184     DestroyWindow(hwEdit);
2185
2186     hwEdit = create_child_editcontrol(0, 0);
2187     hwParent = GetParent(hwEdit);
2188     SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2189
2190     zero_dm_messages();
2191     r = SendMessage(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2192     ok(1 == r, "expected 1, got %d\n", r);
2193     test_dm_messages(0, 0, 0, 0);
2194     zero_dm_messages();
2195
2196     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2197     ok(1 == r, "expected 1, got %d\n", r);
2198     test_dm_messages(0, 0, 0, 0);
2199     zero_dm_messages();
2200
2201     msg.hwnd = hwEdit;
2202     msg.message = WM_KEYDOWN;
2203     msg.wParam = VK_TAB;
2204     msg.lParam = 0xf0001;
2205     r = SendMessage(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2206     ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2207     test_dm_messages(0, 0, 0, 0);
2208     zero_dm_messages();
2209
2210     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2211     ok(1 == r, "expected 1, got %d\n", r);
2212     test_dm_messages(0, 0, 0, 0);
2213     zero_dm_messages();
2214
2215     destroy_child_editcontrol(hwEdit);
2216
2217     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2218     hwParent = GetParent(hwEdit);
2219     SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2220
2221     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2222     ok(1 == r, "expected 1, got %d\n", r);
2223     test_dm_messages(0, 0, 0, 0);
2224     zero_dm_messages();
2225
2226     msg.hwnd = hwEdit;
2227     msg.message = WM_KEYDOWN;
2228     msg.wParam = VK_ESCAPE;
2229     msg.lParam = 0x10001;
2230     r = SendMessage(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2231     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2232     test_dm_messages(0, 0, 0, 0);
2233     zero_dm_messages();
2234
2235     r = SendMessage(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2236     ok(1 == r, "expected 1, got %d\n", r);
2237     test_dm_messages(0, 0, 0, 0);
2238     zero_dm_messages();
2239
2240     r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2241     ok(1 == r, "expected 1, got %d\n", r);
2242     test_dm_messages(0, 0, 0, 1);
2243     zero_dm_messages();
2244
2245     r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2246     ok(1 == r, "expected 1, got %d\n", r);
2247     test_dm_messages(0, 0, 1, 0);
2248     zero_dm_messages();
2249
2250     hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2251         100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2252     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2253
2254     r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2255     ok(1 == r, "expected 1, got %d\n", r);
2256     test_dm_messages(0, 0, 1, 1);
2257     zero_dm_messages();
2258
2259     DestroyWindow(hwButton);
2260     destroy_child_editcontrol(hwEdit);
2261 }
2262
2263 START_TEST(edit)
2264 {
2265     hinst = GetModuleHandleA(NULL);
2266     assert(RegisterWindowClasses());
2267
2268     test_edit_control_1();
2269     test_edit_control_2();
2270     test_edit_control_3();
2271     test_edit_control_4();
2272     test_edit_control_5();
2273     test_edit_control_limittext();
2274     test_margins();
2275     test_margins_font_change();
2276     test_text_position();
2277     test_espassword();
2278     test_undo();
2279     test_enter();
2280     test_tab();
2281     test_edit_dialog();
2282     test_multi_edit_dialog();
2283     test_wantreturn_edit_dialog();
2284     test_singleline_wantreturn_edit_dialog();
2285     test_child_edit_wmkeydown();
2286     test_fontsize();
2287     test_dialogmode();
2288
2289     UnregisterWindowClasses();
2290 }