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