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                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
55                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
56                     break;
57                 case 1:
58                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
59                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
60                     break;
61                 case 2:
62                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
63                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
64                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
65                     break;
66 
67                 /* test cases for pressing enter */
68                 case 3:
69                     num_ok_commands = 0;
70                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
71                     PostMessageA(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                     PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
153                     break;
154                 case 1:
155                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
156                     break;
157                 case 2:
158                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
159                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
160                     break;
161 
162                 /* more test cases for WM_CHAR */
163                 case 3:
164                     PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
165                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
166                     break;
167                 case 4:
168                     PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
169                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
170                     break;
171                 case 5:
172                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
173                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
174                     break;
175 
176                 /* more test cases for WM_KEYDOWN + WM_CHAR */
177                 case 6:
178                     PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
179                     PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
180                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
181                     break;
182                 case 7:
183                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
184                     PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
185                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
186                     break;
187                 case 8:
188                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
189                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
190                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
191                     break;
192 
193                 /* multiple tab tests */
194                 case 9:
195                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
196                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
197                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
198                     break;
199                 case 10:
200                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
201                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
202                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
203                     PostMessageA(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 = SendMessageA(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 = SendMessageA(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                     PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
301                     break;
302                 case 1:
303                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
304                     break;
305                 case 2:
306                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
307                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
308                     break;
309 
310                 /* test cases for WM_CHAR */
311                 case 3:
312                     PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
313                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
314                     break;
315                 case 4:
316                     PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
317                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
318                     break;
319                 case 5:
320                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
321                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
322                     break;
323 
324                 /* test cases for WM_KEYDOWN + WM_CHAR */
325                 case 6:
326                     PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
327                     PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
328                     break;
329                 case 7:
330                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
331                     PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
332                     break;
333                 case 8:
334                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
335                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
336                     PostMessageA(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 = SendMessageA(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                     PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
420                     break;
421                 case 1:
422                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
423                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
424                     break;
425                 case 2:
426                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
427                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 1);
428                     break;
429 
430                 /* test cases for WM_CHAR */
431                 case 3:
432                     PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
433                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
434                     break;
435                 case 4:
436                     PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
437                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
438                     break;
439                 case 5:
440                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
441                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
442                     break;
443 
444                 /* test cases for WM_KEYDOWN + WM_CHAR */
445                 case 6:
446                     PostMessageA(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
447                     PostMessageA(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
448                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 0);
449                     break;
450                 case 7:
451                     PostMessageA(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
452                     PostMessageA(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
453                     PostMessageA(hdlg, WM_USER, 0xdeadbeef, 2);
454                     break;
455                 case 8:
456                     PostMessageA(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
457                     PostMessageA(hedit, WM_CHAR, VK_TAB, 0xf0001);
458                     PostMessageA(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 = SendMessageA(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 szEditTest4Class[] = "EditTest4Class";
541 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
542 
543 static HWND create_editcontrol (DWORD style, DWORD exstyle)
544 {
545     HWND handle;
546 
547     handle = CreateWindowExA(exstyle,
548 			  "EDIT",
549 			  "Test Text",
550 			  style,
551 			  10, 10, 300, 300,
552 			  NULL, NULL, hinst, NULL);
553     ok (handle != NULL, "CreateWindow EDIT Control failed\n");
554     assert (handle);
555     if (winetest_interactive)
556 	ShowWindow (handle, SW_SHOW);
557     return handle;
558 }
559 
560 static HWND create_editcontrolW(DWORD style, DWORD exstyle)
561 {
562     static const WCHAR testtextW[] = {'T','e','s','t',' ','t','e','x','t',0};
563     static const WCHAR editW[] = {'E','d','i','t',0};
564     HWND handle;
565 
566     handle = CreateWindowExW(exstyle, editW, testtextW, style, 10, 10, 300, 300,
567         NULL, NULL, hinst, NULL);
568     ok(handle != NULL, "Failed to create Edit control.\n");
569     return handle;
570 }
571 
572 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
573 {
574     HWND parentWnd;
575     HWND editWnd;
576     RECT rect;
577     BOOL b;
578     SetRect(&rect, 0, 0, 300, 300);
579     b = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
580     ok(b, "AdjustWindowRect failed\n");
581 
582     parentWnd = CreateWindowExA(0,
583                             szEditTextPositionClass,
584                             "Edit Test",
585                             WS_OVERLAPPEDWINDOW,
586                             CW_USEDEFAULT, CW_USEDEFAULT,
587                             rect.right - rect.left, rect.bottom - rect.top,
588                             NULL, NULL, hinst, NULL);
589     ok (parentWnd != NULL, "CreateWindow EDIT Test failed\n");
590     assert(parentWnd);
591 
592     editWnd = CreateWindowExA(exstyle,
593                             "EDIT",
594                             "Test Text",
595                             WS_CHILD | style,
596                             0, 0, 300, 300,
597                             parentWnd, NULL, hinst, NULL);
598     ok (editWnd != NULL, "CreateWindow EDIT Test Text failed\n");
599     assert(editWnd);
600     if (winetest_interactive)
601         ShowWindow (parentWnd, SW_SHOW);
602     return editWnd;
603 }
604 
605 static void destroy_child_editcontrol (HWND hwndEdit)
606 {
607     if (GetParent(hwndEdit))
608         DestroyWindow(GetParent(hwndEdit));
609     else {
610         trace("Edit control has no parent!\n");
611         DestroyWindow(hwndEdit);
612     }
613 }
614 
615 static LONG get_edit_style (HWND hwnd)
616 {
617     return GetWindowLongA( hwnd, GWL_STYLE ) & (
618 	ES_LEFT |
619 /* FIXME: not implemented
620 	ES_CENTER |
621 	ES_RIGHT |
622 	ES_OEMCONVERT |
623 */
624 	ES_MULTILINE |
625 	ES_UPPERCASE |
626 	ES_LOWERCASE |
627 	ES_PASSWORD |
628 	ES_AUTOVSCROLL |
629 	ES_AUTOHSCROLL |
630 	ES_NOHIDESEL |
631 	ES_COMBO |
632 	ES_READONLY |
633 	ES_WANTRETURN |
634 	ES_NUMBER
635 	);
636 }
637 
638 static void set_client_height(HWND Wnd, unsigned Height)
639 {
640     RECT ClientRect, WindowRect;
641 
642     GetWindowRect(Wnd, &WindowRect);
643     GetClientRect(Wnd, &ClientRect);
644     SetWindowPos(Wnd, NULL, 0, 0,
645                  WindowRect.right - WindowRect.left,
646                  Height + (WindowRect.bottom - WindowRect.top) -
647                  (ClientRect.bottom - ClientRect.top),
648                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
649 
650     /* Workaround for a bug in Windows' edit control
651        (multi-line mode) */
652     GetWindowRect(Wnd, &WindowRect);
653     SetWindowPos(Wnd, NULL, 0, 0,
654                  WindowRect.right - WindowRect.left + 1,
655                  WindowRect.bottom - WindowRect.top + 1,
656                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
657     SetWindowPos(Wnd, NULL, 0, 0,
658                  WindowRect.right - WindowRect.left,
659                  WindowRect.bottom - WindowRect.top,
660                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
661 
662     GetClientRect(Wnd, &ClientRect);
663     ok(ClientRect.bottom - ClientRect.top == Height,
664         "The client height should be %d, but is %d\n",
665         Height, ClientRect.bottom - ClientRect.top);
666 }
667 
668 static void test_edit_control_1(void)
669 {
670     HWND hwEdit;
671     MSG msMessage;
672     int i;
673     LONG r;
674 
675     msMessage.message = WM_KEYDOWN;
676 
677     trace("EDIT: Single line\n");
678     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
679     r = get_edit_style(hwEdit);
680     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
681     for (i=0;i<65535;i++)
682     {
683 	msMessage.wParam = i;
684 	r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
685 	ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
686             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
687     }
688     DestroyWindow (hwEdit);
689 
690     trace("EDIT: Single line want returns\n");
691     hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
692     r = get_edit_style(hwEdit);
693     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
694     for (i=0;i<65535;i++)
695     {
696 	msMessage.wParam = i;
697 	r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
698 	ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
699             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
700     }
701     DestroyWindow (hwEdit);
702 
703     trace("EDIT: Multiline line\n");
704     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
705     r = get_edit_style(hwEdit);
706     ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
707     for (i=0;i<65535;i++)
708     {
709 	msMessage.wParam = i;
710 	r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
711 	ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
712             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
713     }
714     DestroyWindow (hwEdit);
715 
716     trace("EDIT: Multi line want returns\n");
717     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
718     r = get_edit_style(hwEdit);
719     ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
720     for (i=0;i<65535;i++)
721     {
722 	msMessage.wParam = i;
723 	r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
724 	ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
725             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
726     }
727     DestroyWindow (hwEdit);
728 }
729 
730 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
731  * selection.  This test checks that the first 'select all' doesn't generate
732  * an UPDATE message which can escape and (via a handler) change the
733  * selection, which would cause WM_SETTEXT to break.  This old bug
734  * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
735  */
736 static void test_edit_control_2(void)
737 {
738     HWND hwndMain, phwnd;
739     char szLocalString[MAXLEN];
740     LONG r, w = 150, h = 50;
741     POINT cpos;
742 
743     /* Create main and edit windows. */
744     hwndMain = CreateWindowA(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
745                             0, 0, 200, 200, NULL, NULL, hinst, NULL);
746     assert(hwndMain);
747     if (winetest_interactive)
748         ShowWindow (hwndMain, SW_SHOW);
749 
750     hwndET2 = CreateWindowA("EDIT", NULL,
751                            WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
752                            0, 0, w, h, /* important this not be 0 size. */
753                            hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
754     assert(hwndET2);
755     if (winetest_interactive)
756         ShowWindow (hwndET2, SW_SHOW);
757 
758     trace("EDIT: SETTEXT atomicity\n");
759     /* Send messages to "type" in the word 'foo'. */
760     r = SendMessageA(hwndET2, WM_CHAR, 'f', 1);
761     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
762     r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
763     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
764     r = SendMessageA(hwndET2, WM_CHAR, 'o', 1);
765     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
766     /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
767     GetWindowTextA(hwndET2, szLocalString, MAXLEN);
768     ok(strcmp(szLocalString, "bar")==0,
769        "Wrong contents of edit: %s\n", szLocalString);
770 
771     /* try setting the caret before it's visible */
772     r = SetCaretPos(0, 0);
773     todo_wine ok(0 == r, "SetCaretPos succeeded unexpectedly, expected: 0, got: %d\n", r);
774     phwnd = SetFocus(hwndET2);
775     ok(phwnd != NULL, "SetFocus failed unexpectedly, expected non-zero, got NULL\n");
776     r = SetCaretPos(0, 0);
777     ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
778     r = GetCaretPos(&cpos);
779     ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
780     ok(cpos.x == 0 && cpos.y == 0, "Wrong caret position, expected: (0,0), got: (%d,%d)\n", cpos.x, cpos.y);
781     r = SetCaretPos(-1, -1);
782     ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
783     r = GetCaretPos(&cpos);
784     ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
785     ok(cpos.x == -1 && cpos.y == -1, "Wrong caret position, expected: (-1,-1), got: (%d,%d)\n", cpos.x, cpos.y);
786     r = SetCaretPos(w << 1, h << 1);
787     ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
788     r = GetCaretPos(&cpos);
789     ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
790     ok(cpos.x == (w << 1) && cpos.y == (h << 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w << 1, h << 1, cpos.x, cpos.y);
791     r = SetCaretPos(w, h);
792     ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
793     r = GetCaretPos(&cpos);
794     ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
795     ok(cpos.x == w && cpos.y == h, "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w, h, cpos.x, cpos.y);
796     r = SetCaretPos(w - 1, h - 1);
797     ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
798     r = GetCaretPos(&cpos);
799     ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
800     ok(cpos.x == (w - 1) && cpos.y == (h - 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w - 1, h - 1, cpos.x, cpos.y);
801 
802     /* OK, done! */
803     DestroyWindow (hwndET2);
804     DestroyWindow (hwndMain);
805 }
806 
807 static void ET2_check_change(void) {
808    char szLocalString[MAXLEN];
809    /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
810    GetWindowTextA(hwndET2, szLocalString, MAXLEN);
811    if (strcmp(szLocalString, "foo")==0) {
812        strcpy(szLocalString, "bar");
813        SendMessageA(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
814    }
815    /* always leave the cursor at the end. */
816    SendMessageA(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
817 }
818 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
819 {
820     if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
821         ET2_check_change();
822 }
823 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
824 {
825     switch (iMsg) {
826     case WM_COMMAND:
827         ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
828         break;
829     }
830     return DefWindowProcA(hwnd, iMsg, wParam, lParam);
831 }
832 
833 static void zero_notify(void)
834 {
835     notifications.en_change = 0;
836     notifications.en_maxtext = 0;
837     notifications.en_update = 0;
838 }
839 
840 #define test_notify(enchange, enmaxtext, enupdate) \
841 do { \
842     ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
843     "got %d\n", enchange, notifications.en_change); \
844     ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
845     "got %d\n", enmaxtext, notifications.en_maxtext); \
846     ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
847     "got %d\n", enupdate, notifications.en_update); \
848 } while(0)
849 
850 
851 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
852 {
853     switch (msg) {
854         case WM_COMMAND:
855             switch (HIWORD(wParam)) {
856                 case EN_MAXTEXT:
857                     notifications.en_maxtext++;
858                     break;
859                 case EN_UPDATE:
860                     notifications.en_update++;
861                     break;
862                 case EN_CHANGE:
863                     notifications.en_change++;
864                     break;
865             }
866             break;
867     }
868     return DefWindowProcA(hWnd, msg, wParam, lParam);
869 }
870 
871 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
872  * to these messages.
873  */
874 static void test_edit_control_3(void)
875 {
876     HWND hWnd;
877     HWND hParent;
878     HDC hDC;
879     int len, dpi;
880     static const char *str = "this is a long string.";
881     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.";
882 
883     hDC = GetDC(NULL);
884     dpi = GetDeviceCaps(hDC, LOGPIXELSY);
885     ReleaseDC(NULL, hDC);
886 
887     trace("EDIT: Test notifications\n");
888 
889     hParent = CreateWindowExA(0,
890               szEditTest3Class,
891               NULL,
892               0,
893               CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
894               NULL, NULL, NULL, NULL);
895     assert(hParent);
896 
897     trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
898     hWnd = CreateWindowExA(0,
899               "EDIT",
900               NULL,
901               0,
902               10, 10, 50, 50,
903               hParent, NULL, NULL, NULL);
904     assert(hWnd);
905 
906     zero_notify();
907     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
908     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
909     if (len == lstrlenA(str)) /* Win 8 */
910         test_notify(1, 0, 1);
911     else
912         test_notify(1, 1, 1);
913 
914     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
915     zero_notify();
916     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
917     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
918     ok(1 == len, "wrong text length, expected 1, got %d\n", len);
919     test_notify(1, 0, 1);
920 
921     zero_notify();
922     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
923     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
924     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
925     test_notify(1, 0, 1);
926 
927     len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
928     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
929     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
930     SendMessageA(hParent, WM_SETFOCUS, 0, (LPARAM)hWnd);
931     len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
932     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
933     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
934 
935     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
936 
937     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
938     zero_notify();
939     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
940     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
941     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
942     test_notify(1, 1, 1);
943 
944     zero_notify();
945     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
946     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
947     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
948     test_notify(1, 0, 1);
949 
950     DestroyWindow(hWnd);
951 
952     trace("EDIT: Single line, ES_AUTOHSCROLL\n");
953     hWnd = CreateWindowExA(0,
954               "EDIT",
955               NULL,
956               ES_AUTOHSCROLL,
957               10, 10, 50, 50,
958               hParent, NULL, NULL, NULL);
959     assert(hWnd);
960 
961     zero_notify();
962     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
963     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
964     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
965     test_notify(1, 0, 1);
966 
967     zero_notify();
968     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
969     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
970     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
971     test_notify(1, 0, 1);
972 
973     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
974     zero_notify();
975     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
976     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
977     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
978     test_notify(1, 0, 1);
979 
980     zero_notify();
981     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
982     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
983     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
984     test_notify(1, 0, 1);
985 
986     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
987 
988     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
989     zero_notify();
990     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
991     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
992     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
993     test_notify(1, 1, 1);
994 
995     zero_notify();
996     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
997     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
998     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
999     test_notify(1, 0, 1);
1000 
1001     DestroyWindow(hWnd);
1002 
1003     trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1004     hWnd = CreateWindowExA(0,
1005               "EDIT",
1006               NULL,
1007               ES_MULTILINE,
1008               10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1009               hParent, NULL, NULL, NULL);
1010     assert(hWnd);
1011 
1012     zero_notify();
1013     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1014     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1015     if (len == lstrlenA(str)) /* Win 8 */
1016         test_notify(1, 0, 1);
1017     else
1018     {
1019         ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1020         test_notify(1, 1, 1);
1021     }
1022 
1023     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1024     zero_notify();
1025     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1026     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1027     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1028     test_notify(1, 0, 1);
1029 
1030     zero_notify();
1031     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1032     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1033     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1034     test_notify(0, 0, 0);
1035 
1036     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1037 
1038     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1039     zero_notify();
1040     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1041     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1042     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1043     test_notify(1, 1, 1);
1044 
1045     zero_notify();
1046     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1047     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1048     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1049     test_notify(0, 0, 0);
1050 
1051     DestroyWindow(hWnd);
1052 
1053     trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1054     hWnd = CreateWindowExA(0,
1055               "EDIT",
1056               NULL,
1057               ES_MULTILINE | ES_AUTOHSCROLL,
1058               10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1059               hParent, NULL, NULL, NULL);
1060     assert(hWnd);
1061 
1062     zero_notify();
1063     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1064     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1065     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1066     test_notify(1, 1, 1);
1067 
1068     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1069     zero_notify();
1070     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1071     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1072     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1073     test_notify(1, 0, 1);
1074 
1075     zero_notify();
1076     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1077     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1078     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1079     test_notify(0, 0, 0);
1080 
1081     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1082 
1083     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1084     zero_notify();
1085     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1086     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1087     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1088     test_notify(1, 1, 1);
1089 
1090     zero_notify();
1091     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1092     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1093     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1094     test_notify(0, 0, 0);
1095 
1096     DestroyWindow(hWnd);
1097 
1098     trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1099     hWnd = CreateWindowExA(0,
1100               "EDIT",
1101               NULL,
1102               ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1103               10, 10, 50, 50,
1104               hParent, NULL, NULL, NULL);
1105     assert(hWnd);
1106 
1107     zero_notify();
1108     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1109     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1110     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1111     test_notify(1, 0, 1);
1112 
1113     zero_notify();
1114     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1115     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1116     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1117     test_notify(0, 0, 0);
1118 
1119     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1120 
1121     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1122     zero_notify();
1123     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1124     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1125     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1126     test_notify(1, 1, 1);
1127 
1128     zero_notify();
1129     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1130     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1131     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1132     test_notify(0, 0, 0);
1133 
1134     DestroyWindow(hWnd);
1135 }
1136 
1137 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
1138  */
1139 static void test_edit_control_4(void)
1140 {
1141     HWND hwEdit;
1142     int lo, hi, mid;
1143     int ret;
1144     int i;
1145 
1146     trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
1147     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1148     SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1149     lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1150     hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1151     mid = lo + (hi - lo) / 2;
1152 
1153     for (i = lo; i < mid; i++) {
1154        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1155        ok(0 == ret, "expected 0 got %d\n", ret);
1156     }
1157     for (i = mid; i <= hi; i++) {
1158        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1159        ok(1 == ret, "expected 1 got %d\n", ret);
1160     }
1161     ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1162     ok(-1 == ret, "expected -1 got %d\n", ret);
1163     DestroyWindow(hwEdit);
1164 
1165     hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1166     SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1167     lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1168     hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1169     mid = lo + (hi - lo) / 2;
1170 
1171     for (i = lo; i < mid; i++) {
1172        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1173        ok(0 == ret, "expected 0 got %d\n", ret);
1174     }
1175     for (i = mid; i <= hi; i++) {
1176        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1177        ok(1 == ret, "expected 1 got %d\n", ret);
1178     }
1179     ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1180     ok(-1 == ret, "expected -1 got %d\n", ret);
1181     DestroyWindow(hwEdit);
1182 
1183     hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1184     SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1185     lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1186     hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1187     mid = lo + (hi - lo) / 2;
1188 
1189     for (i = lo; i < mid; i++) {
1190        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1191        ok(0 == ret, "expected 0 got %d\n", ret);
1192     }
1193     for (i = mid; i <= hi; i++) {
1194        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1195        ok(1 == ret, "expected 1 got %d\n", ret);
1196     }
1197     ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1198     ok(-1 == ret, "expected -1 got %d\n", ret);
1199     DestroyWindow(hwEdit);
1200 
1201     hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1202     SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1203     lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1204     hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1205     mid = lo + (hi - lo) / 2 +1;
1206 
1207     for (i = lo; i < mid; i++) {
1208        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1209        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1210     }
1211     for (i = mid; i <= hi; i++) {
1212        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1213        ok(1 == ret, "expected 1 got %d\n", ret);
1214     }
1215     ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1216     ok(-1 == ret, "expected -1 got %d\n", ret);
1217     DestroyWindow(hwEdit);
1218 
1219     hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1220     SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1221     lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1222     hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1223     mid = lo + (hi - lo) / 2 +1;
1224 
1225     for (i = lo; i < mid; i++) {
1226        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1227        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1228     }
1229     for (i = mid; i <= hi; i++) {
1230        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1231        ok(1 == ret, "expected 1 got %d\n", ret);
1232     }
1233     ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1234     ok(-1 == ret, "expected -1 got %d\n", ret);
1235     DestroyWindow(hwEdit);
1236 
1237     hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1238     SendMessageA(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1239     lo = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 0, 0));
1240     hi = LOWORD(SendMessageA(hwEdit, EM_POSFROMCHAR, 1, 0));
1241     mid = lo + (hi - lo) / 2 +1;
1242 
1243     for (i = lo; i < mid; i++) {
1244        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1245        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1246     }
1247     for (i = mid; i <= hi; i++) {
1248        ret = LOWORD(SendMessageA(hwEdit, EM_CHARFROMPOS, 0, i));
1249        ok(1 == ret, "expected 1 got %d\n", ret);
1250     }
1251     ret = SendMessageA(hwEdit, EM_POSFROMCHAR, 2, 0);
1252     ok(-1 == ret, "expected -1 got %d\n", ret);
1253     DestroyWindow(hwEdit);
1254 }
1255 
1256 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1257  * truncates text that doesn't fit.
1258  */
1259 static void test_edit_control_5(void)
1260 {
1261     static const char *str = "test\r\ntest";
1262     HWND parentWnd;
1263     HWND hWnd;
1264     int len;
1265     RECT rc1 = { 10, 10, 11, 11};
1266     RECT rc;
1267 
1268     /* first show that a non-child won't do for this test */
1269     hWnd = CreateWindowExA(0,
1270               "EDIT",
1271               str,
1272               0,
1273               10, 10, 1, 1,
1274               NULL, NULL, NULL, NULL);
1275     assert(hWnd);
1276     /* size of non-child edit control is (much) bigger than requested */
1277     GetWindowRect( hWnd, &rc);
1278     ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1279             rc.right - rc.left);
1280     DestroyWindow(hWnd);
1281     /* so create a parent, and give it edit controls children to test with */
1282     parentWnd = CreateWindowExA(0,
1283                             szEditTextPositionClass,
1284                             "Edit Test", WS_VISIBLE |
1285                             WS_OVERLAPPEDWINDOW,
1286                             CW_USEDEFAULT, CW_USEDEFAULT,
1287                             250, 250,
1288                             NULL, NULL, hinst, NULL);
1289     assert(parentWnd);
1290     ShowWindow( parentWnd, SW_SHOW);
1291     /* single line */
1292     hWnd = CreateWindowExA(0,
1293               "EDIT",
1294               str, WS_VISIBLE | WS_BORDER |
1295               WS_CHILD,
1296               rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1297               parentWnd, NULL, NULL, NULL);
1298     assert(hWnd);
1299     GetClientRect( hWnd, &rc);
1300     ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1301             "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc ));
1302     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1303     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1304     DestroyWindow(hWnd);
1305     /* multi line */
1306     hWnd = CreateWindowExA(0,
1307               "EDIT",
1308               str,
1309               WS_CHILD | ES_MULTILINE,
1310               rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1311               parentWnd, NULL, NULL, NULL);
1312     assert(hWnd);
1313     GetClientRect( hWnd, &rc);
1314     ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1315             "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc ));
1316     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1317     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1318     DestroyWindow(hWnd);
1319     DestroyWindow(parentWnd);
1320 }
1321 
1322 /* Test WM_GETTEXT processing
1323  * after destroy messages
1324  */
1325 static void test_edit_control_6(void)
1326 {
1327     static const char *str = "test\r\ntest";
1328     char buf[MAXLEN];
1329     LONG ret;
1330     HWND hWnd;
1331 
1332     hWnd = CreateWindowExA(0,
1333               "EDIT",
1334               "Test",
1335               0,
1336               10, 10, 1, 1,
1337               NULL, NULL, hinst, NULL);
1338     assert(hWnd);
1339 
1340     ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1341     ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1342     ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1343     ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1344     ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1345     buf[0] = 0;
1346     ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1347     ok(ret == 0, "Expected 0, got %d\n", ret);
1348     ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1349     ok(ret == strlen(str), "Expected %s, got len %d\n", str, ret);
1350     ok(!strcmp(buf, str), "Expected %s, got %s\n", str, buf);
1351     buf[0] = 0;
1352     ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1353     ok(ret == 0, "Expected 0, got %d\n", ret);
1354     ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1355     ok(ret == 0, "Expected 0, got len %d\n", ret);
1356     ok(!strcmp(buf, ""), "Expected empty string, got %s\n", buf);
1357 
1358     DestroyWindow(hWnd);
1359 }
1360 
1361 static void test_edit_control_limittext(void)
1362 {
1363     HWND hwEdit;
1364     DWORD r;
1365 
1366     /* Test default limit for single-line control */
1367     trace("EDIT: buffer limit for single-line\n");
1368     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1369     r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1370     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1371     SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1372     r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1373     ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r);
1374     DestroyWindow(hwEdit);
1375 
1376     /* Test default limit for multi-line control */
1377     trace("EDIT: buffer limit for multi-line\n");
1378     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1379     r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1380     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1381     SendMessageA(hwEdit, EM_SETLIMITTEXT, 0, 0);
1382     r = SendMessageA(hwEdit, EM_GETLIMITTEXT, 0, 0);
1383     ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r);
1384     DestroyWindow(hwEdit);
1385 }
1386 
1387 /* Test EM_SCROLL */
1388 static void test_edit_control_scroll(void)
1389 {
1390     static const char *single_line_str = "a";
1391     static const char *multiline_str = "Test\r\nText";
1392     HWND hwEdit;
1393     LONG ret;
1394 
1395     /* Check the return value when EM_SCROLL doesn't scroll
1396      * anything. Should not return true unless any lines were actually
1397      * scrolled. */
1398     hwEdit = CreateWindowA(
1399               "EDIT",
1400               single_line_str,
1401               WS_VSCROLL | ES_MULTILINE,
1402               1, 1, 100, 100,
1403               NULL, NULL, hinst, NULL);
1404 
1405     assert(hwEdit);
1406 
1407     ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1408     ok(!ret, "Returned %x, expected 0.\n", ret);
1409 
1410     ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1411     ok(!ret, "Returned %x, expected 0.\n", ret);
1412 
1413     ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1414     ok(!ret, "Returned %x, expected 0.\n", ret);
1415 
1416     ret = SendMessageA(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1417     ok(!ret, "Returned %x, expected 0.\n", ret);
1418 
1419     DestroyWindow (hwEdit);
1420 
1421     /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1422        should not cause EM_SCROLL to return a negative value of
1423        scrolled lines that would put us "before" the beginning. */
1424     hwEdit = CreateWindowA(
1425                 "EDIT",
1426                 multiline_str,
1427                 WS_VSCROLL | ES_MULTILINE,
1428                 0, 0, 100, 100,
1429                 NULL, NULL, hinst, NULL);
1430     assert(hwEdit);
1431 
1432     ret = SendMessageA(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1433     ok(!ret, "Returned %x, expected 0.\n", ret);
1434 
1435     DestroyWindow (hwEdit);
1436 }
1437 
1438 static void test_margins_usefontinfo(UINT charset)
1439 {
1440     HWND hwnd;
1441     HDC hdc;
1442     SIZE size;
1443     BOOL cjk = FALSE;
1444     LOGFONTA lf;
1445     HFONT hfont;
1446     RECT rect;
1447     INT margins, threshold, expect, empty_expect, small_expect;
1448 
1449     memset(&lf, 0, sizeof(lf));
1450     lf.lfHeight = -11;
1451     lf.lfWeight = FW_NORMAL;
1452     lf.lfCharSet = charset;
1453     strcpy(lf.lfFaceName, "Tahoma");
1454 
1455     hfont = CreateFontIndirectA(&lf);
1456     ok(hfont != NULL, "got %p\n", hfont);
1457 
1458     /* Big window rectangle */
1459     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
1460     ok(hwnd != NULL, "got %p\n", hwnd);
1461     GetClientRect(hwnd, &rect);
1462     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1463 
1464     hdc = GetDC(hwnd);
1465     hfont = SelectObject(hdc, hfont);
1466     size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
1467     expect = MAKELONG(size.cx / 2, size.cx / 2);
1468     small_expect = 0;
1469     empty_expect = size.cx >= 28 ? small_expect : expect;
1470 
1471     charset = GetTextCharset(hdc);
1472     switch (charset)
1473     {
1474     case SHIFTJIS_CHARSET:
1475     case HANGUL_CHARSET:
1476     case GB2312_CHARSET:
1477     case CHINESEBIG5_CHARSET:
1478         cjk = TRUE;
1479     }
1480 
1481     hfont = SelectObject(hdc, hfont);
1482     ReleaseDC(hwnd, hdc);
1483 
1484     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1485     ok(margins == 0, "got %x\n", margins);
1486     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1487     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1488     if (!cjk)
1489         ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1490     else
1491     {
1492         ok(HIWORD(margins) > 0 && LOWORD(margins) > 0, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1493         expect = empty_expect = small_expect = margins;
1494     }
1495     DestroyWindow(hwnd);
1496 
1497     threshold = (size.cx / 2 + size.cx) * 2;
1498 
1499     /* Size below which non-cjk margins are zero */
1500     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
1501     ok(hwnd != NULL, "got %p\n", hwnd);
1502     GetClientRect(hwnd, &rect);
1503     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1504 
1505     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1506     ok(margins == 0, "got %x\n", margins);
1507 
1508     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1509     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1510     ok(margins == small_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1511     DestroyWindow(hwnd);
1512 
1513     /* Size at which non-cjk margins become non-zero */
1514     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
1515     ok(hwnd != NULL, "got %p\n", hwnd);
1516     GetClientRect(hwnd, &rect);
1517     ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1518 
1519     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1520     ok(margins == 0, "got %x\n", margins);
1521 
1522     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1523     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1524     ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1525     DestroyWindow(hwnd);
1526 
1527     /* Empty rect */
1528     hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1529     ok(hwnd != NULL, "got %p\n", hwnd);
1530     GetClientRect(hwnd, &rect);
1531     ok(IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
1532 
1533     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1534     ok(margins == 0, "got %x\n", margins);
1535 
1536     SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
1537     margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
1538     ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
1539     DestroyWindow(hwnd);
1540 
1541     DeleteObject(hfont);
1542 }
1543 
1544 static void test_margins(void)
1545 {
1546     HWND hwEdit;
1547     RECT old_rect, new_rect;
1548     INT old_right_margin;
1549     DWORD old_margins, new_margins;
1550 
1551     hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1552 
1553     old_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1554     old_right_margin = HIWORD(old_margins);
1555 
1556     /* Check if setting the margins works */
1557 
1558     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1559     new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1560     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1561     ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1562 
1563     SendMessageA(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1564     new_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1565     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1566     ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1567 
1568     /* The size of the rectangle must decrease if we increase the margin */
1569 
1570     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1571     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1572     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1573     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1574     ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1575     ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1576     ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1577     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1578 
1579     /* If we set the margin to same value as the current margin,
1580        the rectangle must not change */
1581 
1582     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1583     SetRect(&old_rect, 1, 1, 99, 99);
1584     SendMessageA(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1585     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1586     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1587     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1588     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1589 
1590     /* The lParam argument of the WM_SIZE message should be ignored. */
1591 
1592     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1593     SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, 0);
1594     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1595     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1596     SendMessageA(hwEdit, WM_SIZE, SIZE_MINIMIZED, 0);
1597     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1598     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1599     SendMessageA(hwEdit, WM_SIZE, SIZE_MAXIMIZED, 0);
1600     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1601     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1602     SendMessageA(hwEdit, WM_SIZE, SIZE_RESTORED, MAKELONG(10, 10));
1603     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1604     ok(EqualRect(&old_rect, &new_rect), "The border of the rectangle has changed\n");
1605 
1606     DestroyWindow (hwEdit);
1607 
1608     test_margins_usefontinfo(ANSI_CHARSET);
1609     test_margins_usefontinfo(EASTEUROPE_CHARSET);
1610 
1611     test_margins_usefontinfo(SHIFTJIS_CHARSET);
1612     test_margins_usefontinfo(HANGUL_CHARSET);
1613     test_margins_usefontinfo(CHINESEBIG5_CHARSET);
1614     /* Don't test JOHAB_CHARSET.  Treated as CJK by Win 8,
1615        but not by < Win 8 and Win 10. */
1616 
1617     test_margins_usefontinfo(DEFAULT_CHARSET);
1618 }
1619 
1620 static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
1621 {
1622     return 0;
1623 }
1624 
1625 static void test_margins_font_change(void)
1626 {
1627     HWND hwEdit;
1628     DWORD margins, font_margins;
1629     LOGFONTA lf;
1630     HFONT hfont, hfont2;
1631     HDC hdc = GetDC(0);
1632 
1633     if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
1634     {
1635         trace("Arial not found - skipping font change margin tests\n");
1636         ReleaseDC(0, hdc);
1637         return;
1638     }
1639     ReleaseDC(0, hdc);
1640 
1641     hwEdit = create_child_editcontrol(0, 0);
1642 
1643     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1644 
1645     memset(&lf, 0, sizeof(lf));
1646     strcpy(lf.lfFaceName, "Arial");
1647     lf.lfHeight = 16;
1648     lf.lfCharSet = DEFAULT_CHARSET;
1649     hfont = CreateFontIndirectA(&lf);
1650     lf.lfHeight = 30;
1651     hfont2 = CreateFontIndirectA(&lf);
1652 
1653     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1654     font_margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1655     ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1656     ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1657 
1658     /* With 'small' edit controls, test that the margin doesn't get set */
1659     SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1660     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1661     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1662     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1663     ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1664        "got %d\n", LOWORD(margins));
1665     ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1666        "got %d\n", HIWORD(margins));
1667 
1668     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1669     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1670     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1671     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1672        "got %d\n", LOWORD(margins));
1673     ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1674        "got %d\n", HIWORD(margins));
1675 
1676     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1677     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1678     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1679     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1680        "got %d\n", LOWORD(margins));
1681     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1682        "got %d\n", HIWORD(margins));
1683 
1684     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1685     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1686     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1687        "got %d\n", LOWORD(margins));
1688     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1689        "got %d\n", HIWORD(margins));
1690 
1691     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1692     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1693     ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
1694        "got %d\n", LOWORD(margins));
1695     ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
1696        "got %d\n", HIWORD(margins));
1697 
1698     /* Above a certain size threshold then the margin is updated */
1699     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1700     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1701     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1702     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1703     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1704     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1705 
1706     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1707     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1708     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1709     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1710     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1711 
1712     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1713     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1714     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1715     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1716     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1717     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1718     margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
1719     ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
1720        "got %d\n", LOWORD(margins));
1721     ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
1722 
1723     SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1724 
1725     DeleteObject(hfont2);
1726     DeleteObject(hfont);
1727     destroy_child_editcontrol(hwEdit);
1728 
1729 }
1730 
1731 #define edit_pos_ok(exp, got, txt) \
1732     ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1733 
1734 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1735 do { \
1736     RECT format_rect; \
1737     int left_margin; \
1738     set_client_height(hwEdit, set_height); \
1739     SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1740     left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
1741     edit_pos_ok(test_top, format_rect.top, vertical position); \
1742     edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1743     edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1744 } while(0)
1745 
1746 static void test_text_position_style(DWORD style)
1747 {
1748     HWND hwEdit;
1749     HFONT font, oldFont;
1750     HDC dc;
1751     TEXTMETRICA metrics;
1752     INT b, bm, b2, b3;
1753     BOOL xb, single_line = !(style & ES_MULTILINE);
1754 
1755     b = GetSystemMetrics(SM_CYBORDER) + 1;
1756     b2 = 2 * b;
1757     b3 = 3 * b;
1758     bm = b2 - 1;
1759 
1760     /* Get a stock font for which we can determine the metrics */
1761     font = GetStockObject(SYSTEM_FONT);
1762     ok (font != NULL, "GetStockObject SYSTEM_FONT failed\n");
1763     dc = GetDC(NULL);
1764     ok (dc != NULL, "GetDC() failed\n");
1765     oldFont = SelectObject(dc, font);
1766     xb = GetTextMetricsA(dc, &metrics);
1767     ok (xb, "GetTextMetrics failed\n");
1768     SelectObject(dc, oldFont);
1769     ReleaseDC(NULL, dc);
1770 
1771     /* Windows' edit control has some bugs in multi-line mode:
1772      * - Sometimes the format rectangle doesn't get updated
1773      *   (see workaround in set_client_height())
1774      * - If the height of the control is smaller than the height of a text
1775      *   line, the format rectangle is still as high as a text line
1776      *   (higher than the client rectangle) and the caret is not shown
1777      */
1778 
1779     /* Edit controls that are in a parent window */
1780 
1781     hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1782     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1783     if (single_line)
1784     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
1785     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
1786     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
1787     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
1788     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
1789     destroy_child_editcontrol(hwEdit);
1790 
1791     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1792     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1793     if (single_line)
1794     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1795     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1796     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1797     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1798     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1799     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1800     destroy_child_editcontrol(hwEdit);
1801 
1802     hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1803     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1804     if (single_line)
1805     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1806     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1807     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1808     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1809     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1810     destroy_child_editcontrol(hwEdit);
1811 
1812     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1813     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1814     if (single_line)
1815     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1816     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1817     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1818     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1819     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1820     destroy_child_editcontrol(hwEdit);
1821 
1822 
1823     /* Edit controls that are popup windows */
1824 
1825     hwEdit = create_editcontrol(style | WS_POPUP, 0);
1826     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1827     if (single_line)
1828     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
1829     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
1830     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
1831     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
1832     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
1833     DestroyWindow(hwEdit);
1834 
1835     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1836     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1837     if (single_line)
1838     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1839     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1840     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1841     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1842     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1843     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1844     DestroyWindow(hwEdit);
1845 
1846     hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1847     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1848     if (single_line)
1849     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1850     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1851     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1852     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1853     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1854     DestroyWindow(hwEdit);
1855 
1856     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1857     SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1858     if (single_line)
1859     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1860     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1861     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1862     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1863     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1864     DestroyWindow(hwEdit);
1865 }
1866 
1867 static void test_text_position(void)
1868 {
1869     trace("EDIT: Text position (Single line)\n");
1870     test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1871     trace("EDIT: Text position (Multi line)\n");
1872     test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1873 }
1874 
1875 static void test_espassword(void)
1876 {
1877     HWND hwEdit;
1878     LONG r;
1879     char buffer[1024];
1880     const char* password = "secret";
1881 
1882     hwEdit = create_editcontrol(ES_PASSWORD, 0);
1883     r = get_edit_style(hwEdit);
1884     ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
1885     /* set text */
1886     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1887     ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1888 
1889     /* select all, cut (ctrl-x) */
1890     SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1891     r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
1892     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1893 
1894     /* get text */
1895     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1896     ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1897     ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1898 
1899     r = OpenClipboard(hwEdit);
1900     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1901     r = EmptyClipboard();
1902     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1903     r = CloseClipboard();
1904     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1905 
1906     /* select all, copy (ctrl-c) and paste (ctrl-v) */
1907     SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1908     r = SendMessageA(hwEdit, WM_CHAR, 3, 0);
1909     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1910     r = SendMessageA(hwEdit, WM_CHAR, 22, 0);
1911     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1912 
1913     /* get text */
1914     buffer[0] = 0;
1915     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1916     ok(r == 0, "Expected: 0, got: %d\n", r);
1917     ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1918 
1919     DestroyWindow (hwEdit);
1920 }
1921 
1922 static void test_undo(void)
1923 {
1924     HWND hwEdit;
1925     LONG r;
1926     DWORD cpMin, cpMax;
1927     char buffer[1024];
1928     const char* text = "undo this";
1929 
1930     hwEdit = create_editcontrol(0, 0);
1931     r = get_edit_style(hwEdit);
1932     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1933 
1934     /* set text */
1935     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1936     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1937 
1938     /* select all, */
1939     cpMin = cpMax = 0xdeadbeef;
1940     SendMessageA(hwEdit, EM_SETSEL, 0, -1);
1941     r = SendMessageA(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1942     ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1943     ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1944     ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1945 
1946     /* cut (ctrl-x) */
1947     r = SendMessageA(hwEdit, WM_CHAR, 24, 0);
1948     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1949 
1950     /* get text */
1951     buffer[0] = 0;
1952     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1953     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1954     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1955 
1956     /* undo (ctrl-z) */
1957     r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
1958     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1959 
1960     /* get text */
1961     buffer[0] = 0;
1962     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1963     ok(strlen(text) == r, "Unexpected length %d\n", r);
1964     ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1965 
1966     /* undo again (ctrl-z) */
1967     r = SendMessageA(hwEdit, WM_CHAR, 26, 0);
1968     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1969 
1970     /* get text */
1971     buffer[0] = 0;
1972     r = SendMessageA(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1973     ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1974     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1975 
1976     DestroyWindow (hwEdit);
1977 }
1978 
1979 static void test_enter(void)
1980 {
1981     HWND hwEdit;
1982     LONG r;
1983     char buffer[16];
1984 
1985     /* multiline */
1986     hwEdit = create_editcontrol(ES_MULTILINE, 0);
1987     r = get_edit_style(hwEdit);
1988     ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1989 
1990     /* set text */
1991     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1992     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1993 
1994     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
1995     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1996 
1997     /* get text */
1998     buffer[0] = 0;
1999     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2000     ok(2 == r, "Expected: %d, got len %d\n", 2, r);
2001     ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
2002 
2003     DestroyWindow (hwEdit);
2004 
2005     /* single line */
2006     hwEdit = create_editcontrol(0, 0);
2007     r = get_edit_style(hwEdit);
2008     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2009 
2010     /* set text */
2011     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2012     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2013 
2014     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2015     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2016 
2017     /* get text */
2018     buffer[0] = 0;
2019     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2020     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2021     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2022 
2023     DestroyWindow (hwEdit);
2024 
2025     /* single line with ES_WANTRETURN */
2026     hwEdit = create_editcontrol(ES_WANTRETURN, 0);
2027     r = get_edit_style(hwEdit);
2028     ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
2029 
2030     /* set text */
2031     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2032     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2033 
2034     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0);
2035     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2036 
2037     /* get text */
2038     buffer[0] = 0;
2039     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2040     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2041     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2042 
2043     DestroyWindow (hwEdit);
2044 }
2045 
2046 static void test_tab(void)
2047 {
2048     HWND hwEdit;
2049     LONG r;
2050     char buffer[16];
2051 
2052     /* multiline */
2053     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2054     r = get_edit_style(hwEdit);
2055     ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
2056 
2057     /* set text */
2058     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2059     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2060 
2061     r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2062     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2063 
2064     /* get text */
2065     buffer[0] = 0;
2066     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2067     ok(1 == r, "Expected: %d, got len %d\n", 1, r);
2068     ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
2069 
2070     DestroyWindow (hwEdit);
2071 
2072     /* single line */
2073     hwEdit = create_editcontrol(0, 0);
2074     r = get_edit_style(hwEdit);
2075     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
2076 
2077     /* set text */
2078     r = SendMessageA(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
2079     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
2080 
2081     r = SendMessageA(hwEdit, WM_CHAR, VK_TAB, 0);
2082     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2083 
2084     /* get text */
2085     buffer[0] = 0;
2086     r = SendMessageA(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
2087     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
2088     ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
2089 
2090     DestroyWindow (hwEdit);
2091 }
2092 
2093 static void test_edit_dialog(void)
2094 {
2095     int r;
2096 
2097     /* from bug 11841 */
2098     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
2099     ok(333 == r, "Expected %d, got %d\n", 333, r);
2100     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
2101     ok(111 == r, "Expected %d, got %d\n", 111, r);
2102     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
2103     ok(444 == r, "Expected %d, got %d\n", 444, r);
2104 
2105     /* more tests for WM_CHAR */
2106     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
2107     ok(444 == r, "Expected %d, got %d\n", 444, r);
2108     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
2109     ok(444 == r, "Expected %d, got %d\n", 444, r);
2110     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
2111     ok(444 == r, "Expected %d, got %d\n", 444, r);
2112 
2113     /* more tests for WM_KEYDOWN + WM_CHAR */
2114     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
2115     ok(444 == r, "Expected %d, got %d\n", 444, r);
2116     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
2117     ok(444 == r, "Expected %d, got %d\n", 444, r);
2118     r = DialogBoxParamA(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
2119     ok(444 == r, "Expected %d, got %d\n", 444, r);
2120 
2121     /* tests with an editable edit control */
2122     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
2123     ok(333 == r, "Expected %d, got %d\n", 333, r);
2124     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
2125     ok(111 == r, "Expected %d, got %d\n", 111, r);
2126     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
2127     ok(444 == r, "Expected %d, got %d\n", 444, r);
2128 
2129     /* tests for WM_CHAR */
2130     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
2131     ok(444 == r, "Expected %d, got %d\n", 444, r);
2132     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
2133     ok(444 == r, "Expected %d, got %d\n", 444, r);
2134     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
2135     ok(444 == r, "Expected %d, got %d\n", 444, r);
2136 
2137     /* tests for WM_KEYDOWN + WM_CHAR */
2138     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
2139     ok(444 == r, "Expected %d, got %d\n", 444, r);
2140     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
2141     ok(444 == r, "Expected %d, got %d\n", 444, r);
2142     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
2143     ok(444 == r, "Expected %d, got %d\n", 444, r);
2144 
2145     /* multiple tab tests */
2146     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2147     ok(22 == r, "Expected %d, got %d\n", 22, r);
2148     r = DialogBoxParamA(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2149     ok(33 == r, "Expected %d, got %d\n", 33, r);
2150 }
2151 
2152 static void test_multi_edit_dialog(void)
2153 {
2154     int r;
2155 
2156     /* test for multiple edit dialogs (bug 12319) */
2157     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2158     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2159     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2160     ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2161     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2162     ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2163     r = DialogBoxParamA(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2164     ok(11 == r, "Expected %d, got %d\n", 11, r);
2165 }
2166 
2167 static void test_wantreturn_edit_dialog(void)
2168 {
2169     int r;
2170 
2171     /* tests for WM_KEYDOWN */
2172     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2173     ok(333 == r, "Expected %d, got %d\n", 333, r);
2174     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2175     ok(444 == r, "Expected %d, got %d\n", 444, r);
2176     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2177     ok(444 == r, "Expected %d, got %d\n", 444, r);
2178 
2179     /* tests for WM_CHAR */
2180     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2181     ok(444 == r, "Expected %d, got %d\n", 444, r);
2182     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2183     ok(444 == r, "Expected %d, got %d\n", 444, r);
2184     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2185     ok(444 == r, "Expected %d, got %d\n", 444, r);
2186 
2187     /* tests for WM_KEYDOWN + WM_CHAR */
2188     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2189     ok(444 == r, "Expected %d, got %d\n", 444, r);
2190     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2191     ok(444 == r, "Expected %d, got %d\n", 444, r);
2192     r = DialogBoxParamA(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2193     ok(444 == r, "Expected %d, got %d\n", 444, r);
2194 }
2195 
2196 static void test_singleline_wantreturn_edit_dialog(void)
2197 {
2198     int r;
2199 
2200     /* tests for WM_KEYDOWN */
2201     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2202     ok(222 == r, "Expected %d, got %d\n", 222, r);
2203     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2204     ok(111 == r, "Expected %d, got %d\n", 111, r);
2205     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2206     ok(444 == r, "Expected %d, got %d\n", 444, r);
2207 
2208     /* tests for WM_CHAR */
2209     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2210     ok(444 == r, "Expected %d, got %d\n", 444, r);
2211     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2212     ok(444 == r, "Expected %d, got %d\n", 444, r);
2213     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2214     ok(444 == r, "Expected %d, got %d\n", 444, r);
2215 
2216     /* tests for WM_KEYDOWN + WM_CHAR */
2217     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2218     ok(222 == r, "Expected %d, got %d\n", 222, r);
2219     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2220     ok(111 == r, "Expected %d, got %d\n", 111, r);
2221     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2222     ok(444 == r, "Expected %d, got %d\n", 444, r);
2223 
2224     /* tests for WM_KEYDOWN */
2225     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2226     ok(222 == r, "Expected %d, got %d\n", 222, r);
2227     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2228     ok(111 == r, "Expected %d, got %d\n", 111, r);
2229     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2230     ok(444 == r, "Expected %d, got %d\n", 444, r);
2231 
2232     /* tests for WM_CHAR */
2233     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2234     ok(444 == r, "Expected %d, got %d\n", 444, r);
2235     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2236     ok(444 == r, "Expected %d, got %d\n", 444, r);
2237     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2238     ok(444 == r, "Expected %d, got %d\n", 444, r);
2239 
2240     /* tests for WM_KEYDOWN + WM_CHAR */
2241     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2242     ok(222 == r, "Expected %d, got %d\n", 222, r);
2243     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2244     ok(111 == r, "Expected %d, got %d\n", 111, r);
2245     r = DialogBoxParamA(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2246     ok(444 == r, "Expected %d, got %d\n", 444, r);
2247 }
2248 
2249 static int child_edit_wmkeydown_num_messages = 0;
2250 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2251 {
2252     switch (msg)
2253     {
2254         case WM_DESTROY:
2255         case WM_NCDESTROY:
2256             break;
2257 
2258         default:
2259             child_edit_wmkeydown_num_messages++;
2260             break;
2261     }
2262 
2263     return FALSE;
2264 }
2265 
2266 static void test_child_edit_wmkeydown(void)
2267 {
2268     HWND hwEdit, hwParent;
2269     int r;
2270 
2271     hwEdit = create_child_editcontrol(0, 0);
2272     hwParent = GetParent(hwEdit);
2273     SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2274     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2275     ok(1 == r, "expected 1, got %d\n", r);
2276     ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2277     destroy_child_editcontrol(hwEdit);
2278 }
2279 
2280 static BOOL got_en_setfocus = FALSE;
2281 static BOOL got_wm_capturechanged = FALSE;
2282 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2283 
2284 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2285 {
2286     switch (msg) {
2287         case WM_COMMAND:
2288             switch (HIWORD(wParam)) {
2289                 case EN_SETFOCUS:
2290                     got_en_setfocus = TRUE;
2291                     break;
2292             }
2293             break;
2294         case WM_CAPTURECHANGED:
2295             if (hWnd != (HWND)lParam)
2296             {
2297                 got_wm_capturechanged = TRUE;
2298                 EndMenu();
2299             }
2300             break;
2301     }
2302     return DefWindowProcA(hWnd, msg, wParam, lParam);
2303 }
2304 
2305 static LRESULT CALLBACK edit_proc_proxy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2306 {
2307     switch (msg) {
2308         case WM_ENTERIDLE: {
2309             MENUBARINFO mbi;
2310             BOOL ret;
2311             HWND ctx_menu = (HWND)lParam;
2312 
2313             memset(&mbi, 0, sizeof(mbi));
2314             mbi.cbSize = sizeof(mbi);
2315             SetLastError(0xdeadbeef);
2316             ret = GetMenuBarInfo(ctx_menu, OBJID_CLIENT, 0, &mbi);
2317             ok(ret, "GetMenuBarInfo failed\n");
2318             if (ret)
2319             {
2320                 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2321                 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2322                 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2323                 ok(mbi.fFocused, "mbi.fFocused = FALSE\n");
2324             }
2325 
2326             memset(&mbi, 0, sizeof(mbi));
2327             mbi.cbSize = sizeof(mbi);
2328             SetLastError(0xdeadbeef);
2329             ret = GetMenuBarInfo(ctx_menu, OBJID_CLIENT, 1, &mbi);
2330             ok(ret, "GetMenuBarInfo failed\n");
2331             if (ret)
2332             {
2333                 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2334                 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2335                 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2336                 ok(!mbi.fFocused, "mbi.fFocused = TRUE\n");
2337             }
2338 
2339             EndMenu();
2340             break;
2341         }
2342     }
2343     return p_edit_proc(hWnd, msg, wParam, lParam);
2344 }
2345 
2346 struct context_menu_messages
2347 {
2348     unsigned int wm_command, em_setsel;
2349 };
2350 
2351 static struct context_menu_messages menu_messages;
2352 
2353 static LRESULT CALLBACK child_edit_menu_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2354 {
2355     switch (msg) {
2356     case WM_ENTERIDLE:
2357         if (wParam == MSGF_MENU) {
2358             HWND hwndMenu = (HWND)lParam;
2359             MENUBARINFO mbi = { sizeof(MENUBARINFO) };
2360             if (GetMenuBarInfo(hwndMenu, OBJID_CLIENT, 0, &mbi)) {
2361                 MENUITEMINFOA mii = { sizeof(MENUITEMINFOA), MIIM_STATE };
2362                 if (GetMenuItemInfoA(mbi.hMenu, EM_SETSEL, FALSE, &mii)) {
2363                     if (mii.fState & MFS_HILITE) {
2364                         PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2365                         PostMessageA(hwnd, WM_KEYUP, VK_RETURN, 0x1c0001);
2366                     }
2367                     else {
2368                         PostMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0x500001);
2369                         PostMessageA(hwnd, WM_KEYUP, VK_DOWN, 0x500001);
2370                     }
2371                 }
2372             }
2373         }
2374         break;
2375     case WM_COMMAND:
2376         menu_messages.wm_command++;
2377         break;
2378     case EM_SETSEL:
2379         menu_messages.em_setsel++;
2380         break;
2381     }
2382     return CallWindowProcA(p_edit_proc, hwnd, msg, wParam, lParam);
2383 }
2384 
2385 static void test_contextmenu(void)
2386 {
2387     HWND hwndMain, hwndEdit;
2388     MSG msg;
2389 
2390     hwndMain = CreateWindowA(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2391                             0, 0, 200, 200, NULL, NULL, hinst, NULL);
2392     assert(hwndMain);
2393 
2394     hwndEdit = CreateWindowA("EDIT", NULL,
2395                            WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2396                            0, 0, 150, 50, /* important this not be 0 size. */
2397                            hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2398     assert(hwndEdit);
2399 
2400     SetFocus(NULL);
2401     SetCapture(hwndMain);
2402     SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2403     ok(got_en_setfocus, "edit box didn't get focused\n");
2404     ok(got_wm_capturechanged, "main window capture did not change\n");
2405 
2406     p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC, (ULONG_PTR)edit_proc_proxy);
2407     SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2408 
2409     DestroyWindow (hwndEdit);
2410 
2411     hwndEdit = CreateWindowA("EDIT", "Test Text",
2412                              WS_CHILD | WS_BORDER | WS_VISIBLE,
2413                              0, 0, 100, 100,
2414                              hwndMain, NULL, hinst, NULL);
2415     memset(&menu_messages, 0, sizeof(menu_messages));
2416     p_edit_proc = (void*)SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC,
2417                                            (ULONG_PTR)child_edit_menu_proc);
2418 
2419     SetFocus(hwndEdit);
2420     SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)"foo");
2421     SendMessageA(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(-1, -1));
2422     while (PeekMessageA(&msg, hwndEdit, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2423     ok(menu_messages.wm_command == 0,
2424        "Expected no WM_COMMAND messages, got %d\n", menu_messages.wm_command);
2425     ok(menu_messages.em_setsel == 1,
2426        "Expected 1 EM_SETSEL message, got %d\n", menu_messages.em_setsel);
2427 
2428     DestroyWindow (hwndEdit);
2429     DestroyWindow (hwndMain);
2430 }
2431 
2432 static BOOL RegisterWindowClasses (void)
2433 {
2434     WNDCLASSA test2;
2435     WNDCLASSA test3;
2436     WNDCLASSA test4;
2437     WNDCLASSA text_position;
2438 
2439     test2.style = 0;
2440     test2.lpfnWndProc = ET2_WndProc;
2441     test2.cbClsExtra = 0;
2442     test2.cbWndExtra = 0;
2443     test2.hInstance = hinst;
2444     test2.hIcon = NULL;
2445     test2.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2446     test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2447     test2.lpszMenuName = NULL;
2448     test2.lpszClassName = szEditTest2Class;
2449     if (!RegisterClassA(&test2)) return FALSE;
2450 
2451     test3.style = 0;
2452     test3.lpfnWndProc = edit3_wnd_procA;
2453     test3.cbClsExtra = 0;
2454     test3.cbWndExtra = 0;
2455     test3.hInstance = hinst;
2456     test3.hIcon = 0;
2457     test3.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2458     test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2459     test3.lpszMenuName = NULL;
2460     test3.lpszClassName = szEditTest3Class;
2461     if (!RegisterClassA(&test3)) return FALSE;
2462 
2463     test4.style = 0;
2464     test4.lpfnWndProc = edit4_wnd_procA;
2465     test4.cbClsExtra = 0;
2466     test4.cbWndExtra = 0;
2467     test4.hInstance = hinst;
2468     test4.hIcon = NULL;
2469     test4.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
2470     test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2471     test4.lpszMenuName = NULL;
2472     test4.lpszClassName = szEditTest4Class;
2473     if (!RegisterClassA(&test4)) return FALSE;
2474 
2475     text_position.style = CS_HREDRAW | CS_VREDRAW;
2476     text_position.cbClsExtra = 0;
2477     text_position.cbWndExtra = 0;
2478     text_position.hInstance = hinst;
2479     text_position.hIcon = NULL;
2480     text_position.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2481     text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2482     text_position.lpszMenuName = NULL;
2483     text_position.lpszClassName = szEditTextPositionClass;
2484     text_position.lpfnWndProc = DefWindowProcA;
2485     if (!RegisterClassA(&text_position)) return FALSE;
2486 
2487     return TRUE;
2488 }
2489 
2490 static void UnregisterWindowClasses (void)
2491 {
2492     UnregisterClassA(szEditTest2Class, hinst);
2493     UnregisterClassA(szEditTest3Class, hinst);
2494     UnregisterClassA(szEditTest4Class, hinst);
2495     UnregisterClassA(szEditTextPositionClass, hinst);
2496 }
2497 
2498 static void test_fontsize(void)
2499 {
2500     HWND hwEdit;
2501     HFONT hfont;
2502     HDC hDC;
2503     LOGFONTA lf;
2504     LONG r;
2505     char szLocalString[MAXLEN];
2506     int dpi;
2507 
2508     hDC = GetDC(NULL);
2509     dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2510     ReleaseDC(NULL, hDC);
2511 
2512     memset(&lf,0,sizeof(LOGFONTA));
2513     strcpy(lf.lfFaceName,"Arial");
2514     lf.lfHeight = -300; /* taller than the edit box */
2515     lf.lfWeight = 500;
2516     hfont = CreateFontIndirectA(&lf);
2517 
2518     trace("EDIT: Oversized font (Multi line)\n");
2519     hwEdit= CreateWindowA("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2520                            0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2521                            hinst, NULL);
2522 
2523     SendMessageA(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2524 
2525     if (winetest_interactive)
2526         ShowWindow (hwEdit, SW_SHOW);
2527 
2528     r = SendMessageA(hwEdit, WM_CHAR, 'A', 1);
2529     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2530     r = SendMessageA(hwEdit, WM_CHAR, 'B', 1);
2531     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2532     r = SendMessageA(hwEdit, WM_CHAR, 'C', 1);
2533     ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2534 
2535     GetWindowTextA(hwEdit, szLocalString, MAXLEN);
2536     ok(strcmp(szLocalString, "ABC")==0,
2537        "Wrong contents of edit: %s\n", szLocalString);
2538 
2539     r = SendMessageA(hwEdit, EM_POSFROMCHAR,0,0);
2540     ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2541     r = SendMessageA(hwEdit, EM_POSFROMCHAR,1,0);
2542     ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2543     r = SendMessageA(hwEdit, EM_POSFROMCHAR,2,0);
2544     ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2545     r = SendMessageA(hwEdit, EM_POSFROMCHAR,3,0);
2546     ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2547 
2548     DestroyWindow (hwEdit);
2549     DeleteObject(hfont);
2550 }
2551 
2552 struct dialog_mode_messages
2553 {
2554     int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2555 };
2556 
2557 static struct dialog_mode_messages dm_messages;
2558 
2559 static void zero_dm_messages(void)
2560 {
2561     dm_messages.wm_command      = 0;
2562     dm_messages.wm_close        = 0;
2563     dm_messages.wm_getdefid     = 0;
2564     dm_messages.wm_nextdlgctl   = 0;
2565 }
2566 
2567 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2568     ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2569     "got %d\n", wmcommand, dm_messages.wm_command); \
2570     ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2571     "got %d\n", wmclose, dm_messages.wm_close); \
2572     ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2573     "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2574     ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2575     "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2576 
2577 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2578 {
2579     switch (iMsg)
2580     {
2581         case WM_COMMAND:
2582             dm_messages.wm_command++;
2583             break;
2584         case DM_GETDEFID:
2585             dm_messages.wm_getdefid++;
2586             return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2587         case WM_NEXTDLGCTL:
2588             dm_messages.wm_nextdlgctl++;
2589             break;
2590         case WM_CLOSE:
2591             dm_messages.wm_close++;
2592             break;
2593     }
2594 
2595     return DefWindowProcA(hwnd, iMsg, wParam, lParam);
2596 }
2597 
2598 static void test_dialogmode(void)
2599 {
2600     HWND hwEdit, hwParent, hwButton;
2601     MSG msg= {0};
2602     int len, r;
2603     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2604 
2605     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2606     ok(1 == r, "expected 1, got %d\n", r);
2607     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2608     ok(11 == len, "expected 11, got %d\n", len);
2609 
2610     r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, 0);
2611     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2612 
2613     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2614     ok(1 == r, "expected 1, got %d\n", r);
2615     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2616     ok(13 == len, "expected 13, got %d\n", len);
2617 
2618     r = SendMessageA(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2619     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2620     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2621     ok(1 == r, "expected 1, got %d\n", r);
2622     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2623     ok(13 == len, "expected 13, got %d\n", len);
2624 
2625     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2626     ok(1 == r, "expected 1, got %d\n", r);
2627     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2628     ok(13 == len, "expected 13, got %d\n", len);
2629 
2630     destroy_child_editcontrol(hwEdit);
2631 
2632     hwEdit = create_editcontrol(ES_MULTILINE, 0);
2633 
2634     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2635     ok(1 == r, "expected 1, got %d\n", r);
2636     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2637     ok(11 == len, "expected 11, got %d\n", len);
2638 
2639     msg.hwnd = hwEdit;
2640     msg.message = WM_KEYDOWN;
2641     msg.wParam = VK_BACK;
2642     msg.lParam = 0xe0001;
2643     r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2644     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2645 
2646     r = SendMessageA(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2647     ok(1 == r, "expected 1, got %d\n", r);
2648     len = SendMessageA(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2649     ok(11 == len, "expected 11, got %d\n", len);
2650 
2651     DestroyWindow(hwEdit);
2652 
2653     hwEdit = create_child_editcontrol(0, 0);
2654     hwParent = GetParent(hwEdit);
2655     SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2656 
2657     zero_dm_messages();
2658     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2659     ok(1 == r, "expected 1, got %d\n", r);
2660     test_dm_messages(0, 0, 0, 0);
2661     zero_dm_messages();
2662 
2663     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2664     ok(1 == r, "expected 1, got %d\n", r);
2665     test_dm_messages(0, 0, 0, 0);
2666     zero_dm_messages();
2667 
2668     msg.hwnd = hwEdit;
2669     msg.message = WM_KEYDOWN;
2670     msg.wParam = VK_TAB;
2671     msg.lParam = 0xf0001;
2672     r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2673     ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2674     test_dm_messages(0, 0, 0, 0);
2675     zero_dm_messages();
2676 
2677     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2678     ok(1 == r, "expected 1, got %d\n", r);
2679     test_dm_messages(0, 0, 0, 0);
2680     zero_dm_messages();
2681 
2682     destroy_child_editcontrol(hwEdit);
2683 
2684     hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2685     hwParent = GetParent(hwEdit);
2686     SetWindowLongPtrA(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2687 
2688     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2689     ok(1 == r, "expected 1, got %d\n", r);
2690     test_dm_messages(0, 0, 0, 0);
2691     zero_dm_messages();
2692 
2693     msg.hwnd = hwEdit;
2694     msg.message = WM_KEYDOWN;
2695     msg.wParam = VK_ESCAPE;
2696     msg.lParam = 0x10001;
2697     r = SendMessageA(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2698     ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2699     test_dm_messages(0, 0, 0, 0);
2700     zero_dm_messages();
2701 
2702     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2703     ok(1 == r, "expected 1, got %d\n", r);
2704     test_dm_messages(0, 0, 0, 0);
2705     zero_dm_messages();
2706 
2707     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2708     ok(1 == r, "expected 1, got %d\n", r);
2709     test_dm_messages(0, 0, 0, 1);
2710     zero_dm_messages();
2711 
2712     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2713     ok(1 == r, "expected 1, got %d\n", r);
2714     test_dm_messages(0, 0, 1, 0);
2715     zero_dm_messages();
2716 
2717     hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2718         100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2719     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2720 
2721     r = SendMessageA(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2722     ok(1 == r, "expected 1, got %d\n", r);
2723     test_dm_messages(0, 0, 1, 1);
2724     zero_dm_messages();
2725 
2726     DestroyWindow(hwButton);
2727     destroy_child_editcontrol(hwEdit);
2728 }
2729 
2730 static void test_EM_GETHANDLE(void)
2731 {
2732     static const char str0[] = "untouched";
2733     static const char str1[] = "1111+1111+1111#";
2734     static const char str1_1[] = "2111+1111+1111#";
2735     static const char str2[] = "2222-2222-2222-2222#";
2736     static const char str3[] = "3333*3333*3333*3333*3333#";
2737     CHAR    current[42];
2738     HWND    hEdit;
2739     HLOCAL  hmem;
2740     HLOCAL  hmem2;
2741     HLOCAL  halloc;
2742     char    *buffer;
2743     int     len;
2744     int     r;
2745 
2746     trace("EDIT: EM_GETHANDLE\n");
2747 
2748     /* EM_GETHANDLE is not supported for a single line edit control */
2749     hEdit = create_editcontrol(WS_BORDER, 0);
2750     ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2751 
2752     hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2753     ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
2754     DestroyWindow(hEdit);
2755 
2756 
2757     /* EM_GETHANDLE needs a multiline edit control */
2758     hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2759     ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2760 
2761     /* set some text */
2762     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2763     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2764     ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2765 
2766     lstrcpyA(current, str0);
2767     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2768     ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2769         "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2770 
2771     hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2772     ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2773     /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
2774        buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
2775 
2776     buffer = LocalLock(hmem);
2777     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2778     len = lstrlenA(buffer);
2779     ok((len == lstrlenA(str1)) && !lstrcmpA(buffer, str1),
2780         "got %d and \"%s\" (expected %d and \"%s\")\n", len, buffer, lstrlenA(str1), str1);
2781     LocalUnlock(hmem);
2782 
2783     /* See if WM_GETTEXTLENGTH/WM_GETTEXT still work. */
2784     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2785     ok(len == lstrlenA(str1), "Unexpected text length %d.\n", len);
2786 
2787     lstrcpyA(current, str0);
2788     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2789     ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2790         "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2791 
2792     /* Application altered buffer contents, see if WM_GETTEXTLENGTH/WM_GETTEXT pick that up. */
2793     buffer = LocalLock(hmem);
2794     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2795     buffer[0] = '2';
2796     LocalUnlock(hmem);
2797 
2798     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2799     ok(len == lstrlenA(str1_1), "Unexpected text length %d.\n", len);
2800 
2801     lstrcpyA(current, str0);
2802     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2803     ok((r == lstrlenA(str1_1)) && !lstrcmpA(current, str1_1),
2804         "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1_1), str1_1);
2805 
2806     /* See if WM_SETTEXT/EM_REPLACESEL work. */
2807     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2808     ok(r, "Failed to set text.\n");
2809 
2810     buffer = LocalLock(hmem);
2811     ok(buffer != NULL && buffer[0] == '1', "Unexpected buffer contents\n");
2812     LocalUnlock(hmem);
2813 
2814     r = SendMessageA(hEdit, EM_REPLACESEL, 0, (LPARAM)str1_1);
2815     ok(r, "Failed to replace selection.\n");
2816 
2817     buffer = LocalLock(hmem);
2818     ok(buffer != NULL && buffer[0] == '2', "Unexpected buffer contents\n");
2819     LocalUnlock(hmem);
2820 
2821     /* use LocalAlloc first to get a different handle */
2822     halloc = LocalAlloc(LMEM_MOVEABLE, 42);
2823     ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
2824     /* prepare our new memory */
2825     buffer = LocalLock(halloc);
2826     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2827     lstrcpyA(buffer, str2);
2828     LocalUnlock(halloc);
2829 
2830     /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
2831     LocalFree(hmem);
2832     /* use LocalAlloc after the LocalFree to likely consume the handle */
2833     hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
2834     ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
2835 
2836     SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
2837 
2838     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2839     ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
2840 
2841     lstrcpyA(current, str0);
2842     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2843     ok((r == lstrlenA(str2)) && !lstrcmpA(current, str2),
2844         "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
2845 
2846     /* set a different text */
2847     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
2848     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2849     ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
2850 
2851     lstrcpyA(current, str0);
2852     r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2853     ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
2854         "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
2855 
2856     LocalFree(hmem2);
2857     DestroyWindow(hEdit);
2858 
2859     /* Some apps have bugs ... */
2860     hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2861 
2862     /* set some text */
2863     r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2864     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2865     ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2866 
2867     /* everything is normal up to EM_GETHANDLE */
2868     hmem = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2869     /* Some messages still work while other messages fail.
2870        After LocalFree the memory handle, messages can crash the app */
2871 
2872     /* A buggy editor used EM_GETHANDLE twice */
2873     hmem2 = (HGLOBAL) SendMessageA(hEdit, EM_GETHANDLE, 0, 0);
2874     ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
2875 
2876     /* Let the edit control free the memory handle */
2877     SendMessageA(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
2878 
2879     DestroyWindow(hEdit);
2880 }
2881 
2882 static void test_paste(void)
2883 {
2884     HWND hEdit, hMultilineEdit;
2885     HANDLE hmem, hmem_ret;
2886     char *buffer;
2887     int r, len;
2888     static const char *str = "this is a simple text";
2889     static const char *str2 = "first line\r\nsecond line";
2890 
2891     hEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
2892     hMultilineEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
2893 
2894     /* Prepare clipboard data with simple text */
2895     hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
2896     ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2897     buffer = GlobalLock(hmem);
2898     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2899     strcpy(buffer, str);
2900     GlobalUnlock(hmem);
2901 
2902     r = OpenClipboard(hEdit);
2903     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2904     r = EmptyClipboard();
2905     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2906     hmem_ret = SetClipboardData(CF_TEXT, hmem);
2907     ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
2908     r = CloseClipboard();
2909     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2910 
2911     /* Paste single line */
2912     SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
2913     r = SendMessageA(hEdit, WM_PASTE, 0, 0);
2914     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2915     ok(strlen(str) == len, "got %d\n", len);
2916 
2917     /* Prepare clipboard data with multiline text */
2918     hmem = GlobalAlloc(GMEM_MOVEABLE, 255);
2919     ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2920     buffer = GlobalLock(hmem);
2921     ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2922     strcpy(buffer, str2);
2923     GlobalUnlock(hmem);
2924 
2925     r = OpenClipboard(hEdit);
2926     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2927     r = EmptyClipboard();
2928     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2929     hmem_ret = SetClipboardData(CF_TEXT, hmem);
2930     ok(hmem_ret == hmem, "expected %p, got %p\n", hmem, hmem_ret);
2931     r = CloseClipboard();
2932     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
2933 
2934     /* Paste multiline text in singleline edit - should be cut */
2935     SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)"");
2936     r = SendMessageA(hEdit, WM_PASTE, 0, 0);
2937     len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2938     ok(strlen("first line") == len, "got %d\n", len);
2939 
2940     /* Paste multiline text in multiline edit */
2941     SendMessageA(hMultilineEdit, WM_SETTEXT, 0, (LPARAM)"");
2942     r = SendMessageA(hMultilineEdit, WM_PASTE, 0, 0);
2943     len = SendMessageA(hMultilineEdit, WM_GETTEXTLENGTH, 0, 0);
2944     ok(strlen(str2) == len, "got %d\n", len);
2945 
2946     /* Cleanup */
2947     DestroyWindow(hEdit);
2948     DestroyWindow(hMultilineEdit);
2949 }
2950 
2951 static void test_EM_GETLINE(void)
2952 {
2953     HWND hwnd[2];
2954     int i;
2955 
2956     hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
2957     hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
2958 
2959     for (i = 0; i < sizeof(hwnd)/sizeof(hwnd[0]); i++)
2960     {
2961         static const WCHAR strW[] = {'t','e','x','t',0};
2962         static const char *str = "text";
2963         WCHAR buffW[16];
2964         char buff[16];
2965         int r;
2966 
2967         if (i == 0)
2968             ok(!IsWindowUnicode(hwnd[i]), "Expected ansi window.\n");
2969         else
2970             ok(IsWindowUnicode(hwnd[i]), "Expected unicode window.\n");
2971 
2972         SendMessageA(hwnd[i], WM_SETTEXT, 0, (LPARAM)str);
2973 
2974         memset(buff, 0, sizeof(buff));
2975         *(WORD *)buff = sizeof(buff);
2976         r = SendMessageA(hwnd[i], EM_GETLINE, 0, (LPARAM)buff);
2977         ok(r == strlen(str), "Failed to get a line %d.\n", r);
2978         ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
2979 
2980         memset(buff, 0, sizeof(buff));
2981         *(WORD *)buff = sizeof(buff);
2982         r = SendMessageA(hwnd[i], EM_GETLINE, 1, (LPARAM)buff);
2983         ok(r == strlen(str), "Failed to get a line %d.\n", r);
2984         ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
2985 
2986         memset(buffW, 0, sizeof(buffW));
2987         *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
2988         r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
2989         ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
2990         ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
2991 
2992         memset(buffW, 0, sizeof(buffW));
2993         *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
2994         r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
2995         ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
2996         ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
2997 
2998         DestroyWindow(hwnd[i]);
2999     }
3000 }
3001 
3002 static int CALLBACK test_wordbreak_procA(char *text, int current, int length, int code)
3003 {
3004     return -1;
3005 }
3006 
3007 static void test_wordbreak_proc(void)
3008 {
3009     EDITWORDBREAKPROCA proc;
3010     LRESULT ret;
3011     HWND hwnd;
3012 
3013     hwnd = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
3014 
3015     proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3016     ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3017 
3018     ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)test_wordbreak_procA);
3019     ok(ret == 1, "Unexpected return value %ld.\n", ret);
3020 
3021     proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3022     ok(proc == test_wordbreak_procA, "Unexpected wordbreak proc %p.\n", proc);
3023 
3024     ret = SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, 0);
3025     ok(ret == 1, "Unexpected return value %ld.\n", ret);
3026 
3027     proc = (void *)SendMessageA(hwnd, EM_GETWORDBREAKPROC, 0, 0);
3028     ok(proc == NULL, "Unexpected wordbreak proc %p.\n", proc);
3029 
3030     DestroyWindow(hwnd);
3031 }
3032 
3033 START_TEST(edit)
3034 {
3035     BOOL b;
3036 
3037     hinst = GetModuleHandleA(NULL);
3038     b = RegisterWindowClasses();
3039     ok (b, "RegisterWindowClasses failed\n");
3040     if (!b) return;
3041 
3042     test_edit_control_1();
3043     test_edit_control_2();
3044     test_edit_control_3();
3045     test_edit_control_4();
3046     test_edit_control_5();
3047     test_edit_control_6();
3048     test_edit_control_limittext();
3049     test_edit_control_scroll();
3050     test_margins();
3051     test_margins_font_change();
3052     test_text_position();
3053     test_espassword();
3054     test_undo();
3055     test_enter();
3056     test_tab();
3057     test_edit_dialog();
3058     test_multi_edit_dialog();
3059     test_wantreturn_edit_dialog();
3060     test_singleline_wantreturn_edit_dialog();
3061     test_child_edit_wmkeydown();
3062     test_fontsize();
3063     test_dialogmode();
3064     test_contextmenu();
3065     test_EM_GETHANDLE();
3066     test_paste();
3067     test_EM_GETLINE();
3068     test_wordbreak_proc();
3069 
3070     UnregisterWindowClasses();
3071 }
3072